Skip to content

Instantly share code, notes, and snippets.

@valexey
Created January 5, 2012 23:47
Show Gist options
  • Save valexey/1568037 to your computer and use it in GitHub Desktop.
Save valexey/1568037 to your computer and use it in GitHub Desktop.
PROCEDURE Move * (VAR p:Base; dt:Float; VAR r:Reflection; mode:MovementMode): BOOLEAN;
(** Moves the specified particle p in all the space with a straight trajectory
taking into account possible reflections from walls. r.Process(p) is
called every time after the particle is collided with the wall and
mirror-reflected form it. At that p.r contains coordinate of the collision
with the wall, p.v contains speed of the particle after the elastic mirror
reflection, r.wall contains the wall, r.alive contains TRUE.
If r.alive=FALSE after the collision then the particle is not anymore
moved. Also r.Process() may change p.v.
There are 2 possible modes of motion specified by mode:
1) mode = InTime. In this case the particle is moved until the specified
time dt is passed.
2) mode = InSpace. In this case the particle passes the distance which is
equal to initial particle speed multiplied by dt. In this mode r.Process()
may not set p.v to zero.
The modes are different only is the collision with walls takes place and
the particle speed is changed by r.Process().
The procedure returns if the movement was valid. *)
VAR
NextR,n:Vector;
w:Wall.Wall;
alive:BOOLEAN;
counter:INTEGER;
dr,AbsV,PassedDistance:Float;
d:CollData;
BEGIN
ASSERT(dt>0);
AbsV:=Vec.Abs(p.v);
ClearCollData(d);
counter:=0;
PassedDistance:=0;
REPEAT
GetNextPos(p,dt,NextR,w,d);
IF (w#NIL) & (dt#0) THEN (* The 2nd condition may take place owing to rounding errors *)
(* Now NextR contains the cross of the trajectory with w *)
ASSERT(dt>0);
dr:=AbsV*dt; (* Rest dr *)
p.r:=NextR;
w.Normal(NextR.x,NextR.y,n);
ReflectSpeed(p,n);
r.alive:=TRUE;
r.wall:=w;
PassedDistance:=PassedDistance+Vec.Dist(p.r,NextR);
r.PassedDistance:=PassedDistance;
r.Process(p);
alive:=r.alive;
IF alive THEN
IF mode=inSpace THEN
AbsV:=Vec.Abs(p.v);
ASSERT(AbsV#0);
dt:=dr/AbsV;
ASSERT(dt>0);
END;
END;
INC(counter);
ELSE
p.r:=NextR;
dt:=0;
alive:=TRUE;
END;
UNTIL (dt<=0) OR ~alive OR (counter>=MaxReflectionCount);
RETURN counter<MaxReflectionCount
END Move;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment