Created
January 5, 2012 23:47
-
-
Save valexey/1568037 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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