January 15, 2021, 05:42:36 PM

### Author Topic: [bmx] Akima spline by Jur [ 1+ years ago ]  (Read 527 times)

#### BlitzBot

• Jr. Member
• Posts: 1
##### [bmx] Akima spline by Jur [ 1+ years ago ]
« on: June 29, 2017, 12:28:40 AM »
Title : Akima spline
Author : Jur
Posted : 1+ years ago

Description : Make splines with akima interpolation method

Code :
Code: BlitzMax
1. SuperStrict
2.
3. Graphics 800,600
4. SeedRnd(MilliSecs())    'Different each time
5. SetLineWidth(2)
6.
7. Global SelectedPoint:Point
8. Global Points:Point[10]
9. MakePoints()
10.
11. Function MakePoints()
12.         For Local p:Int=0 Until Points.length
13.                 Points[p]=New Point
14.                 Points[p].x=Rand(50,750)
15.                 Points[p].y=Rand(100,550)
16.         Next
17. EndFunction
18.
19. While Not KeyHit(KEY_ESCAPE)
20.         Cls
21.
22.         For Local p:Int=0 Until Points.length
23.                 If Abs(MouseX()-Points[p].x)<4 And Abs(MouseY()-Points[p].y)<4 Then
24.                         If MouseDown(1) Then
25.                                 SelectedPoint = Points[p]
26.                         EndIf
27.                 EndIf
28.         Next
29.
30.         If SelectedPoint Then
31.                 SelectedPoint.x=MouseX()
32.                 SelectedPoint.y=MouseY()
33.                 If MouseDown(1) = False Then
34.                         SelectedPoint = Null
35.                         FlushMouse()
36.                 EndIf
37.         EndIf
38.
39.         If KeyHit(KEY_SPACE) Then MakePoints()
40.
41.         Local xAprev:Float, yAprev:Float, xCprev:Float, yCprev:Float
42.         For Local i:Int=2 Until Points.length-3
43.                 For Local mu:Float=0 To 1 Step 0.05
44.                         'DebugStop()
45.
46.                         Local xC:Float = CubicInterpolate(Points[i-1].x, Points[i].x, Points[i+1].x, Points[i+2].x, mu)
47.                         Local yC:Float = CubicInterpolate(Points[i-1].y, Points[i].y, Points[i+1].y, Points[i+2].y, mu)
48.
49.                         Local yA:Float = AkimaInterpolate(Points[i-2].y, Points[i-1].y, Points[i].y, Points[i+1].y, Points[i+2].y, Points[i+3].y, mu)
50.                         Local xA:Float = AkimaInterpolate(Points[i-2].x, Points[i-1].x, Points[i].x, Points[i+1].x, Points[i+2].x, Points[i+3].x, mu)
51.
52.                         If xAprev=0 And yAprev=0 Then
53.                                 xAprev = xA
54.                                 yAprev = yA
55.                         EndIf
56.                         If xCprev=0 And yCprev=0 Then
57.                                 xCprev = xC
58.                                 yCprev = yC
59.                         EndIf
60.
61.                         SetColor 220,220,200
62.                         DrawLine xCprev,yCprev, xC,yC
63.
64.                         SetColor 255,200,0
65.                         DrawLine xAprev,yAprev, xA,yA
66.
67.                         xAprev = xA
68.                         yAprev = yA
69.                         xCprev = xC
70.                         yCprev = yC
71.
72.                 Next
73.         Next
74.
75.
76.         'points
77.         SetColor 255,255,255
78.         For Local i:Int=2 Until Points.length-3
79.                 DrawOval(Points[i].x-2, Points[i].y-2, 4,4)
80.                 DrawText i,Points[i].x+7,Points[i].y+7
81.         Next
82.
83.         SetColor 220,220,200
84.         DrawText "cubic spline",10,10
85.         SetColor 255,200,0
86.         DrawText "akima spline",10,30
87.         SetColor 200,200,200
88.         DrawText "move points with mouse, make new points with <space> ",10,50
89.
90.         Flip
91. Wend
92.
93.
94. ' akima interpolation requires 6 points
95. ' interpolate between y3 And y4 at position mu (0..1)
96. '----------------------------------------------------------------------------
97. Function AkimaInterpolate:Float(y1:Float, y2:Float, y3:Float, y4:Float, y5:Float, y6:Float, mu:Float)
98.
99.         Local num1:Float = Abs((y5-y4)- (y4-y3))*(y3-y2) + Abs((y3-y2) - (y2-y1))*(y4-y3)
100.         Local den1:Float = Abs((y5-y4) - (y4-y3)) + Abs((y3-y2) - (y2-y1))
101.
102.         Local num2:Float = Abs((y6-y5)- (y5-y4))*(y4-y3) + Abs((y4-y3) - (y3-y2))*(y5-y4)
103.         Local den2:Float = Abs((y6-y5) - (y5-y4)) + Abs((y4-y3) - (y3-y2))
104.
105.         Local t1:Float
106.         If den1>0.00001 Then   '0
107.                 t1=num1/den1
108.         Else
109.                 t1=0.0
110.         EndIf
111.
112.         Local t2:Float
113.         If den2>0.00001 Then   '0
114.                 t2=num2/den2
115.         Else
116.                 t2=0.0
117.         EndIf
118.
119.         Local C:Float = (3*(y4-y3) - 2*t1 - t2)
120.         Local D:Float = (t1 + t2 - 2*(y4-y3))
121.
122.         Return  y3 + (t1 + (C + D*mu)*mu)*mu
123.
124. EndFunction
125.
126.
127.
128.
129. 'interpolate between y1 and y2
130. Function CubicInterpolate:Float(y0:Float, y1:Float, y2:Float, y3:Float, mu:Float)
131.    Local a0#,a1#,a2#,a3#,mu2#
132.
133.    mu2 = mu*mu
134.    a0 = y3-y2-y0+y1
135.    a1 = y0-y1-a0
136.    a2 = y2-y0
137.    a3 = y1
138.
139.    Return a0*mu*mu2+a1*mu2+a2*mu+a3
140. End Function
141.
142. Type Point
143.         Field x:Int
144.         Field y:Int
145.
146.         Function Create:point(x#,y#)
147.                 Local p:point=New point
148.                 p.x=x
149.                 p.y=y
150.                 Return p
151.         End Function
152. End Type