This animations shows the motion of a mass particle, which is attracted to a fixed point by a linear force. (The force increases linearly with the distance.) The arrow attached to the particle represents the current velocity. After stopping the animation with a double click you can move the mass point and/or manipulate the velocity of the mass point. |
The independent variables in this example are the time variable t of the Animate command, the coordinates of the mass point (x and y), the coordinates of the top of the velocity vector (topx and topy) and the velocity vector (vx and vy). Additionally, values for the next time step are necessary (newvx, newvy, newx, and newy) and variables for saving the values of the current time step (oldx, oldy, oldtopx, oldtopy, and oldt).
<PARAM NAME=INDEPENDENT_VARIABLES VALUE="{ (* Animate variable *) t->0, (* variables associated with parameters *) x->0.5, y->0, topx->0.5, topy->0.1, vx->0, vy->0, (* variables for the next time step *) newvx->0, newvy->0, newx->0, newy->0, (* variables for buffering *) oldx->0, oldy->0, oldtopx->0, oldtopy->0, oldt->0}">
There are several dependent variables: some constants (length of a time step dt, spring constant D, mass m), some flags (isAnimating, isManipulatingPoint, isManipulatingTop, isManipulating), the absolute value of the velocity vector v, and a few variables for the integration of the motion of the mass point (ax, ay, nextax, nextay). Between the definitions of these dependent variables, independent variables are also set.
<PARAM NAME=DEPENDENT_VARIABLES VALUE="{ (* constants *) dt->0.1, D->1, m->1, (* animation and manipulation flags *) isAnimating->If[t != oldt, True, False], isManipulatingPoint->If[x != oldx || y != oldy, True, False], isManipulatingTop->If[topx != oldtopx || topy != oldtopy, True, False], isManipulating->(isManipulatingPoint || isManipulatingTop), (* computation of variables associated with parameters *) x->If[isAnimating, newx, x], y->If[isAnimating, newy, y], vx->If[isManipulating, If[isManipulatingTop, topx - x, vx], If[isAnimating, newvx, vx]], vy->If[isManipulating, If[isManipulatingTop, topy - y, vy], If[isAnimating, newvy, vy]], topx->x + vx, topy->y + vy, (* dependent variables for the Graphics3D object *) v->Sqrt[vx * vx + vy * vy], (* integration *) ax->-D / m x, ay->-D / m y, newx->x + vx dt + 0.5 ax dt^2, newy->y + vy dt + 0.5 ay dt^2, nextax->-D / m newx, nextay->-D / m newy, newx->x + vx dt + 0.5 (ax + nextax) / 2 dt^2, newy->y + vy dt + 0.5 (ay + nextay) / 2 dt^2, newvx->vx + (ax + nextax) / 2 dt, newvy->vy + (ay + nextay) / 2 dt, (* buffering variables associated with parameters *) oldx->x, oldy->y, oldtopx->topx, oldtopy->topy, oldt->t}">
The actual Animate command is rather simple. Only the arrow head needs a few computations:
<PARAM NAME=INPUT VALUE="Animate[Graphics3D[{ PointSize[0.02],Point[{0,0,0}], Thickness[0.01],Line[{{0,0,0},{x,y,0}}],PointSize[0.03],Point[{x,y,0}], Thickness[0.001],Line[{{x,y,0},{topx,topy,0}}], SurfaceColor[RGBColor[0,0,0]], EdgeForm[], Polygon[{ {topx + 0.05 vx/v, topy + 0.05 vy/v, 0}, {topx - 0.05 vx/v + 0.05 vy/v, topy - 0.05 vy/v - 0.05 vx/v, 0}, {topx - 0.05 vx/v - 0.05 vy/v, topy - 0.05 vy/v + 0.05 vx/v, 0}}], PointSize[0.015], Point[{topx , topy, 0}]}, Boxed->False,ViewPoint->{0,0,10},ViewVertical->{0,1,0}, PlotRange->{{-1,1},{-1,1},{-1,1}}],{t,0,1}]">