nice..3D version will be fine to o
Code archives/Algorithms/Smoothly moving object
This code has been declared by its author to be Public Domain code.
Download source code
| From article: Cubic spline interpolation (rus) |
;Object in 2D smoothly passing thru random set of points visiting them in certain time (dual cubic spline interpolation) by Matt Merkulov SeedRnd MilliSecs () Const q=10 ; As coordinates x and y are processed equally, files, where are created ; These coordinates and factors for functions on a current interval of time are stored(kept) Dim ptc#(q+2,1) Dim a#(1) Dim b#(1) Dim c#(1) Dim d#(1) ; A file for time in which the object should visit(attend) the set point Dim tim (q+2) ; A file of coordinates of object Dim oc#(1) Graphics 800,600 SetFont LoadFont ("Arial", 16) x#=0 y#=300 Color 255,0,0 For n=1 To q x#=Rnd (50,750) y#=Rnd (50,550) ptc#(n, 0)=x# ptc#(n, 1)=y# tim (n)=t Oval x#-4, y#-4,9,9 Text x#, y#+ 4, .001*t + "s", True t=t+Rand (1000,3000) Next ; Values of parameters of extreme points for maintenance of cyclicity are set For nn=0 To 1 ptc#(0, nn)=ptc#(q, nn) ptc#(q+1, nn)=ptc#(1, nn) ptc#(q+2, nn)=ptc#(2, nn) Next tim (q+1)=t tim (q+2)=t+tim (2) tim (0)=tim (q)-t Color 255,255,255 ; We keep a background i=CreateImage (800,600) GrabImage i, 0,0 SetBuffer BackBuffer () ; time counter it is established(installed) outside an interval of a cycle, that ; To calculate factors for an initial interval of time, having passed(having taken place) through a condition t=t+1 n=q+1 Repeat If t> tim (n+1) Then n=n+1 ; If number of unit has fallen outside the limits a file - return on unit 1, zeroing ; The counter of time If n> q Then n=1 ms=0 tbeg=MilliSecs () End If For nn=0 To 1 d#(nn)=ptc#(n, nn) c#(nn)=(ptc#(n+1, nn)-ptc#(n-1, nn)) / (tim (n+1)-tim (n-1)) dy2#=(ptc#(n+2, nn)-ptc#(n, nn)) / (tim (n+2)-tim (n)) x3#=tim (n+1)-tim (n) xx3#=x3#*x3# b#(nn)=(3*ptc#(n+1, nn)-dy2#*x3#-2*c#(nn)*x3#-3*d#(nn))/xx3# a#(nn)=(dy2#-2*b#(nn)*x3#-c#(nn)) / (3*xx3#) Next End If ; Calculation of coordinates of object For nn=0 To 1 v#=t-tim (n) vv#=v#*v# oc#(nn)=a#(nn)*vv#*v#+ b#(nn)*vv#+ c#(nn)*v#+ d#(nn) Next ; Display of a background, object and current time DrawBlock i, 0,0 Oval oc#(0)-9, oc#(1)-9,19,19 Text 0,0, " Time: " + (.001*t) + "s" Flip t=MilliSecs ()-tbeg Until KeyHit (1) |
Comments
Excellent.
Here's a BlitzMax port + modification, if anybody is interested:
SuperStrict Graphics 1024, 768 SeedRnd MilliSecs() Local Paths:TPath[] = createPaths(3) While Not KeyHit(KEY_ESCAPE) If MouseHit(1) Or MouseHit(2) Paths = Null GCCollect Paths = createPaths(3) EndIf renderPaths Paths Wend End Function createPaths:TPath[](qty:Int = 1) Local paths:TPath[] = New TPath[qty] For Local n:Int = 0 To paths.length - 1 paths[n] = New TPath paths[n].init Rand(3, 10) paths[n].generateCoords Next Return paths EndFunction Function renderPaths(paths:TPath[]) Cls SetColor 255, 255, 255 DrawText "Click mouse button for a new set of paths.", 10, 10 Local t:Int = MilliSecs() For Local p:TPath = EachIn paths p.process t p.render Next Flip True EndFunction '******** Type TPath Field Qty:Int Field Coords:TCoord[] Field CurrentPosition:TCoord Field TimeNow:Int '**** "Scratchpad" variables Field a:TCoord Field b:TCoord Field c:TCoord Field d:TCoord Field n:Int Field tbeg:Int '***** '**** For rendering only Field red:Byte Field green:Byte Field blue:Byte '**** Method init(q:Int = 5) Qty = q Coords = New TCoord[Qty + 3] For Local n:Int = 0 To Coords.length - 1 Coords[n] = TCoord.create() Next CurrentPosition = New TCoord a = New TCoord b = New TCoord c = New TCoord d = New TCoord n = Qty + 1 red = Rand(128, 255) green = Rand(0, 255) blue = Rand(0, 255) EndMethod Method generateCoords() Local t:Int = 0 For Local n:Int = 1 To Qty Coords[n].set Rnd(50, GraphicsWidth() - 50), Rnd(50, GraphicsHeight() - 50), t t :+ Rand(1000, 3000) Next Coords[0].set Coords[Qty].X, Coords[Qty].Y, Coords[Qty].Time - t Coords[Qty + 1].set Coords[1].X, Coords[1].Y, t Coords[Qty + 2].set Coords[2].X, Coords[2].Y, Coords[2].Time + t EndMethod Method render() SetColor red, green, blue For Local n:Int = 1 To Qty DrawOval Coords[n].X - 4, Coords[n].Y - 4, 9, 9 DrawText n, Coords[n].X, Coords[n].Y + 4 Next DrawOval CurrentPosition.X - 9, CurrentPosition.Y - 9, 19, 19 EndMethod Method process(t:Int) TimeNow = t - tbeg If TimeNow > Coords[n+1].Time n :+ 1 If n > Qty n = 1 tbeg = t End If d.set Coords[n].X, Coords[n].Y c.set ((Coords[n+1].X - Coords[n-1].X) / (Coords[n+1].Time - Coords[n-1].Time)), ((Coords[n+1].Y - Coords[n-1].Y) / (Coords[n+1].Time - Coords[n-1].Time)) Local dy2:TCoord = New TCoord dy2.set ((Coords[n+2].X - Coords[n].X) / (Coords[n+2].Time - Coords[n].Time)), ((Coords[n+2].Y - Coords[n].Y) / (Coords[n+2].Time - Coords[n].Time)) Local x3# = Coords[n+1].Time - Coords[n].Time Local xx3# = x3# * x3# b.set ((3 * Coords[n+1].X - dy2.X * x3# - 2 * c.X * x3# - 3 * d.X) / xx3#), ((3 * Coords[n+1].Y - dy2.Y * x3# - 2 * c.Y * x3# - 3 * d.Y) / xx3#) a.set ((dy2.X - 2 * b.X * x3# - c.X) / (3 * xx3#)), ((dy2.Y - 2 * b.Y * x3# - c.Y) / (3 * xx3#)) End If Local v# = TimeNow - Coords[n].time Local vv# = v# * v# CurrentPosition.set (a.X * vv# * v# + b.X * vv# + c.X * v# + d.X), (a.Y * vv# * v# + b.Y * vv# + c.Y * v# + d.Y) EndMethod EndType Type TCoord Field X:Float Field Y:Float Field Time:Int Function create:TCoord(px:Float = 0.0, py:Float = 0.0, t:Int = 0.0) Local c:TCoord = New TCoord c.set px, py, t Return c EndFunction Method set(px:Float = 0.0, py:Float = 0.0, t:Int = 0.0) X = px Y = py Time = t EndMethod EndType