Page 1 of 1
AddPathSpline
Posted: Wed Oct 29, 2025 4:28 pm
by pf shadoko
A function for drawing spline curves (closed or open)
This function is not included in the SVG standard, yet it is very simple to implement.
Code: Select all
Structure Vector2:x.f:y.f:EndStructure
Procedure AddPathSpline(Array po.Vector2(1),Flags=0,roundness.f=0.5)
Protected n,i,close,coef.f=roundness/3
Protected.Vector2 b0,b1,b2,b3,c
n=ArraySize(po())+2
Dim p.Vector2(n)
If flags=#PB_Path_Relative:c\x=PathCursorX():c\y=PathCursorY():EndIf
For i=0 To n-2:p(i+1)\x=po(i)\x+c\x:p(i+1)\y=po(i)\y+c\y:Next
If p(n-1)\X = p(1)\X And p(n-1)\Y = p(1)\Y:close=1: p(0) = p(n-2): p(n) = p(2):Else:p(0) = p(2):p(n) = p(n-2):EndIf
MovePathCursor(p(1)\x,p(1)\y)
For i=1 To n-2
b0=p(i)
b3=p(i+1)
b1\x=b0\x+coef*(b3\x-p(i-1)\x)
b1\y=b0\y+coef*(b3\y-p(i-1)\y)
b2\x=b3\x-coef*(p(i+2)\x-b0\x)
b2\y=b3\y-coef*(p(i+2)\y-b0\y)
AddPathCurve(b1\x,b1\y, b2\x,b2\y, b3\x,b3\y)
Next
If close:ClosePath():EndIf
EndProcedure
OpenWindow(0, 0, 0, 600,600, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0,0,0,600,600)
Dim p.Vector2(8)
Repeat
b.f+0.04
For i=0 To 7:a.f=i*2*#PI/8
r=200+Sin(b+i*15)*50
p(i)\x=Cos(a)*r+300
p(i)\y=Sin(a)*r+300
Next
p(8)=p(0); to close the curve
StartVectorDrawing(CanvasVectorOutput(0))
VectorSourceColor($11ff6666)
FillVectorOutput()
addpathspline(p())
VectorSourceColor($ffffaaaa):FillPath(#PB_Path_Preserve)
VectorSourceColor($ff000000):StrokePath(4)
For i=0 To 7:AddPathCircle(p(i)\x,p(i)\y,4):Next
VectorSourceColor($ff0000ff):FillPath()
StopVectorDrawing()
Delay(32)
event=WindowEvent()
Until event=#PB_Event_CloseWindow Or event=#PB_Event_DeactivateWindow
Re: AddPathSpline
Posted: Wed Oct 29, 2025 5:41 pm
by Booger
That is so neat. I have no idea what a good use would be yet but I'm sure you'll tell me.
I saw a huge amount of on the fly calculations, in the 1970's we made a table for such things so there was time
left to actually do something else. Hope you don't mind the tables mod.
Code: Select all
Structure Vector2:x.f:y.f:EndStructure
Procedure AddPathSpline(Array po.Vector2(1),Flags=0,roundness.f=0.5)
Protected n,i,close,coef.f=roundness/3
Protected.Vector2 b0,b1,b2,b3,c
n=ArraySize(po())+2
Dim p.Vector2(n)
If flags=#PB_Path_Relative:c\x=PathCursorX():c\y=PathCursorY():EndIf
For i=0 To n-2:p(i+1)\x=po(i)\x+c\x:p(i+1)\y=po(i)\y+c\y:Next
If p(n-1)\X = p(1)\X And p(n-1)\Y = p(1)\Y:close=1: p(0) = p(n-2): p(n) = p(2):Else:p(0) = p(2):p(n) = p(n-2):EndIf
MovePathCursor(p(1)\x,p(1)\y)
For i=1 To n-2
b0=p(i)
b3=p(i+1)
b1\x=b0\x+coef*(b3\x-p(i-1)\x)
b1\y=b0\y+coef*(b3\y-p(i-1)\y)
b2\x=b3\x-coef*(p(i+2)\x-b0\x)
b2\y=b3\y-coef*(p(i+2)\y-b0\y)
AddPathCurve(b1\x,b1\y, b2\x,b2\y, b3\x,b3\y)
Next
If close:ClosePath():EndIf
EndProcedure
; --- Pre-calculation tables (This is the optimization) ---
Global Dim CosLookup.f(7)
Global Dim SinLookup.f(7)
Global Dim AngleOffset.f(7)
Procedure SetupTables()
Protected i.i, a.f
For i = 0 To 7
a = i * 2 * #PI / 8
CosLookup(i) = Cos(a)
SinLookup(i) = Sin(a)
AngleOffset(i) = i * 15
Next
EndProcedure
; --- Main Program ---
OpenWindow(0, 0, 0, 600,600, "Optimized Spline", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0,0,0,600,600)
; Fill the lookup tables ONE time
SetupTables()
Dim p.Vector2(8)
Define.i event, i
Define.f b, r
Repeat
b + 0.04
For i=0 To 7
; Use pre-calculated values from the tables
r = 200 + Sin(b + AngleOffset(i)) * 50
p(i)\x = CosLookup(i) * r + 300
p(i)\y = SinLookup(i) * r + 300
Next
p(8)=p(0); to close the curve
; Clear the screen (background)
StartDrawing(CanvasOutput(0)):Box(0,0,600,600,$ff8888):StopDrawing()
; Draw the vector graphics
StartVectorDrawing(CanvasVectorOutput(0))
AddPathSpline(p())
VectorSourceColor($22ffffff):FillPath(#PB_Path_Preserve)
VectorSourceColor($ff000000):StrokePath(2)
For i=0 To 7:AddPathCircle(p(i)\x,p(i)\y,4):Next
VectorSourceColor($ff0000ff):FillPath()
StopVectorDrawing()
event = WindowEvent()
; Delay 16ms to target ~60 FPS
Delay(16)
Until event=#PB_Event_CloseWindow
Re: AddPathSpline
Posted: Wed Oct 29, 2025 8:12 pm
by Justin
Nice, using FillVectorOutput removes the flickering here
Code: Select all
Structure Vector2:x.f:y.f:EndStructure
Procedure AddPathSpline(Array po.Vector2(1),Flags=0,roundness.f=0.5)
Protected n,i,close,coef.f=roundness/3
Protected.Vector2 b0,b1,b2,b3,c
n=ArraySize(po())+2
Dim p.Vector2(n)
If flags=#PB_Path_Relative:c\x=PathCursorX():c\y=PathCursorY():EndIf
For i=0 To n-2:p(i+1)\x=po(i)\x+c\x:p(i+1)\y=po(i)\y+c\y:Next
If p(n-1)\X = p(1)\X And p(n-1)\Y = p(1)\Y:close=1: p(0) = p(n-2): p(n) = p(2):Else:p(0) = p(2):p(n) = p(n-2):EndIf
MovePathCursor(p(1)\x,p(1)\y)
For i=1 To n-2
b0=p(i)
b3=p(i+1)
b1\x=b0\x+coef*(b3\x-p(i-1)\x)
b1\y=b0\y+coef*(b3\y-p(i-1)\y)
b2\x=b3\x-coef*(p(i+2)\x-b0\x)
b2\y=b3\y-coef*(p(i+2)\y-b0\y)
AddPathCurve(b1\x,b1\y, b2\x,b2\y, b3\x,b3\y)
Next
If close:ClosePath():EndIf
EndProcedure
OpenWindow(0, 0, 0, 600,600, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0,0,0,600,600)
Dim p.Vector2(8)
Repeat
b.f+0.04
For i=0 To 7:a.f=i*2*#PI/8
r=200+Sin(b+i*15)*50
p(i)\x=Cos(a)*r+300
p(i)\y=Sin(a)*r+300
Next
p(8)=p(0); to close the curve
; StartDrawing(CanvasOutput(0)):Box(0,0,600,600,$ff8888):StopDrawing()
StartVectorDrawing(CanvasVectorOutput(0))
VectorSourceColor($ffff8888)
FillVectorOutput()
addpathspline(p())
VectorSourceColor($22ffffff):FillPath(#PB_Path_Preserve)
VectorSourceColor($ff000000):StrokePath(2)
For i=0 To 7:AddPathCircle(p(i)\x,p(i)\y,4):Next
VectorSourceColor($ff0000ff):FillPath()
StopVectorDrawing()
Delay(32)
event=WindowEvent()
Until event=#PB_Event_CloseWindow Or event=#PB_Event_DeactivateWindow
Re: AddPathSpline
Posted: Wed Oct 29, 2025 10:43 pm
by pf shadoko
@Booger
Splines are used to create smooth curves using control points.
I think these optimizations are completely negligible compared to the graphics functions.
@Justin
Indeed.
I modified the code in my first post.
Re: AddPathSpline
Posted: Thu Oct 30, 2025 12:09 am
by Booger
I get it. I was making things work in code before the Internet so i don't know anything. I'll ignore your posts from now on and won't share how bits and bytes work down below.
Re: AddPathSpline
Posted: Thu Oct 30, 2025 11:24 am
by pjay
@pf - Thanks for posting.
Booger wrote: Thu Oct 30, 2025 12:09 am
I get it. I was making things work in code before the Internet so i don't know anything. I'll ignore your posts from now on and won't share how bits and bytes work down below.
Quite a disappointing attitude really; There are times that our age and past experiences can work against us.
The speed of modern CPUs means that lookup tables for most mathematical functions will often be slower than direct calculation.
Re: AddPathSpline
Posted: Thu Oct 30, 2025 12:04 pm
by Booger
That's today's youth's common assumption and that's why even as far as technology has advanced things are still clunky. I'll run some tests again and see if you're right.
Re: AddPathSpline
Posted: Thu Oct 30, 2025 12:50 pm
by minimy
This form of transformation is very interesting.
I think pjay is correct, I did a test on an old and new computer and on the new one it is a really fast direct calculation, but on the old one the table is more or less the same speed (it is not very old compare with me, it is Atom, slow horse

) It may be that in a pentiun or 486 the table wins.
Anyway thanks for sharing code and knowledge.
Sorry for my English, I have it rusty today.

Re: AddPathSpline
Posted: Thu Oct 30, 2025 1:47 pm
by pjay
Booger wrote: Thu Oct 30, 2025 12:04 pm
That's today's youth's common assumption and that's why even as far as technology has advanced things are still clunky. I'll run some tests again and see if you're right.
Don't get me wrong, I still use lookup tables for some computationally-heavy image processing (as it's doing millions of operations in one go & I knew the tables would remain in cache), but to use them in this particular case seems unnecessary.
Re: AddPathSpline
Posted: Thu Oct 30, 2025 1:51 pm
by Booger
I like opinions, but I still don't know a practical use for this, is this to be transitional button on a window. How many of these would be used in a practical simulation. Please tell me more.
Re: AddPathSpline
Posted: Thu Oct 30, 2025 2:50 pm
by pjay
Users such as Idle & pf have recently been making large strides towards providing other PB users with the ability to use modern (motion) graphics in their projects. Rendering closed paths (such as the one pf has presented here) form an important part of this.
See what Idle is working on here:
viewtopic.php?t=87734
Re: AddPathSpline
Posted: Thu Oct 30, 2025 2:57 pm
by Booger
I'll have a look when I have time to open a computer. Thanks. I'll have to buy 30 extra whiteboards to see what the idle advanced code works though. I'm a few brain cells short to just look at his code and interpret it's so advanced.
Re: AddPathSpline
Posted: Thu Oct 30, 2025 5:12 pm
by Little John
pf shadoko wrote: Wed Oct 29, 2025 10:43 pm
@Justin
Indeed.
I modified the code in my first post.
Works fine here now, without flickering.
Thanks for sharing this code!
Re: AddPathSpline
Posted: Thu Oct 30, 2025 7:27 pm
by Booger
On the machine I treated that on it just like the cache, on two other machines it doesn't like the cache. Hit and miss, I eat my words and apologize.