Just finished the closed algorithem. The first point should be the same as the last now. I've moved away from the crumby vector method of calculating the sub points, improving division speed by a whopping 50%.
Here is the source:
' attempt at subdivision algorithem for splines
Strict
SeedRnd(MilliSecs())
' set up an array for our point objects
Global points:point[]
' toggle variable for closed or open shapes
Global closed:Int = 0
' a point datastructure holding x and y
Type point
Field x:Float, y:Float
End Type
' return a point at a percent between both points
Function midpoint:point(a:point, b:point, percent:Float)
Local p:point = New point
p.x = a.x + ((b.x - a.x) * percent)
p.y = a.y + ((b.y - a.y) * percent)
Return p
End Function
' return a list with a point added
Function add_point:point[] (p:point, a:point[] )
Local i:Int = a.Length
a = a[..i + 1]
a[i] = p
Return a
EndFunction
' used to divide a curve
Function divide()
' save the first and last points
Local start:point = New point
start = points[0]
Local eEnd:point = New point
eEnd = points[points.length - 1]
Local temp_array:point[] ' one point longer than the old array
' add first point
temp_array = add_point(start, temp_array)
' find new midpoints and add them to temp array
For Local i = 0 To points.Length - 2
Local n:point = midpoint(points[i] , points[i + 1] , .25)
temp_array = add_point(n, temp_array)
n = midpoint(points[i] , points[i + 1] , .75)
temp_array = add_point(n, temp_array)
Next
temp_array = add_point(eEnd, temp_array)
points = temp_array
End Function
' used to divide a CLOSED curve
Function divide_loop()
' save the first and last points
Local eEnd:point = New point
eEnd = midpoint(points[points.length - 1] , points[points.length - 2] , .25)
Local temp_array:point[] ' one point longer than the old array
' add first point
' find new midpoints and add them to temp array
temp_array = add_point(eEnd, temp_array)
For Local i = 0 To points.Length - 2
Local n:point = midpoint(points[i] , points[i + 1] , .25)
temp_array = add_point(n, temp_array)
n = midpoint(points[i] , points[i + 1] , .75)
temp_array = add_point(n, temp_array)
Next
points = temp_array
End Function
' draw all segments in the curve array
Function draw()
For Local i = 0 To points.Length - 2
DrawLine(points[i].x, points[i].y, points[i + 1].x, points[i + 1].y)
Next
DrawOval(points[0].x - 2, points[0].y - 2, 4, 4)
DrawOval(points[points.length - 1].x - 2, points[points.length - 1].y - 2, 4, 4)
End Function
' seed the points
Function seed()
Local a:point = New point
a.x = 320
a.y = 384
points = add_point(a, points)
Local b:point = New point
b.x = 208
b.y = 256
points = add_point(b, points)
Local c:point = New point
c.x = 208
c.y = 160
points = add_point(c, points)
Local d:point = New point
d.x = 304
d.y = 160
points = add_point(d, points)
Local e:point = New point
e.x = 320
e.y = 192+32
points = add_point(e, points)
Local f:point = New point
f.x = 336
f.y = 160
points = add_point(f, points)
Local g:point = New point
g.x = 432
g.y = 160
points = add_point(g, points)
Local h:point = New point
h.x = 432
h.y = 256
points = add_point(h, points)
Local i:point = New point
i.x = 320
i.y = 384
points = add_point(i, points)
EndFunction
seed()
Graphics(640, 480)
While Not KeyDown(KEY_ESCAPE)
If KeyHit(KEY_SPACE)
If closed
divide_loop()
Else
divide()
EndIf
End If
If KeyHit(KEY_N)
Cls
points = Null
seed()
End If
If KeyHit(KEY_C)
Cls
closed = True
points = Null
seed()
End If
If KeyHit(KEY_O)
Cls
closed = False
points = Null
seed()
End If
'draw point count
SetColor 0, 0, 0
DrawRect(0, 0, 640, 24)
SetColor 255, 255 * (Float(points.Length) / 360.0), 255-(255 * (Float(points.Length) / 180.0))
DrawText("Points: " + points.Length + " O-Open Polyline" + " C-Closed Polyline", 2, 2)
draw()
Flip
WEnd
A cute little heart shape closed inside a ridged frame.