jumpmove.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
class JUMP_MOVE
class JUMP_MOVE is
-- Knot type is not change.
-- 1998/4 Linux version K.Kodama
--
-- 1991 MS-DOS version Kouji KODAMA
shared SW0:BOOL:=true;
-- SW0:default mode. TRUE:over jump, FALSE:under jump
shared SW:BOOL;
-- true:over jump, false:under jump. Use SW0 as default mode
----------------state variables--------------------
shared phase:CARD:=0;
-- 0: needed setup
-- 1: set start pt
-- left: set start pt. "p1" & goto phase 2
-- right: none
-- 2: set end pt
-- left: set end pt. "p2" & goto phase 3
-- right: cancel start pt. goto phase 1
-- 3: set new bridge
-- left: set new vertex & move vertex
-- right: do jump move & goto phase 1
shared knotPtr,knotPtr1:INT;
shared press3:BOOL;
shared x0,y0:INT;
shared pressL:BOOL;
shared i0:INT;
shared p1, p2, stp, enp:INT;
shared KnotP0, KnotP1: KNOT;
lMouse(inout Knot:KNOT, inout p, inout ps:INT, sw:INT) is
-- p: stump of the segment (set by left button),
-- ps: if point is inserted and p<ps then ps must be shifted.
if sw=1.int then
if (stp<p)and(p<enp) then Knot.PointInEdge(p); end;
p:=p+1;
if p<=ps then ps:=ps+1; end;
enp:=enp+1;
end;
end;
chOv(Knot:KNOT, inout seg1:BOOL, inout seg2:BOOL) is
-- Check if over bridge
seg1:=true;
loop i::=p1.upto!(p2);
seg1:=seg1 and (~VERTEXC::under.in(Knot[i].sep));
end;
if (VERTEXC::ks.in(Knot[stp].sep))and(Knot.Match(stp+1,enp-1)) then
seg2:=true;
loop
i::=(stp+1).upto!(p1);
seg2:=seg2 and (~VERTEXC::under.in(Knot[i].sep));
end;
loop i::=p2.upto!(enp-1);
seg2:=seg2 and (~VERTEXC::under.in(Knot[i].sep));
end;
else seg2:=false;
end;
end;
CheckSegment(inout Knot:KNOT):BOOL is
-- Check if the segment p1--p2 be over/under bridge.
-- and rotate
kFlg1o, kFlg2o, kFlg1u, kFlg2u:BOOL;
c:INT;
chOv(Knot,inout kFlg1o, inout kFlg2o);
Knot.mirrorZ; chOv(Knot,inout kFlg1u,inout kFlg2u); Knot.mirrorZ;
if ~(kFlg1o or kFlg2o or kFlg1u or kFlg2u) then return false; end;
if (kFlg1o or kFlg2o)and(kFlg1u or kFlg2u) then
SW:=SW0; -- Use default mode
else SW:= (kFlg1o or kFlg2o);
end;
if (kFlg1o and SW) or (kFlg1u and (~ SW)) then
return ~Knot.has_band(p1+1,p2-1);
elsif (kFlg2o and SW) or (kFlg2u and (~ SW)) then
--loop while!((stp+1)<p1);
-- Knot.rotBack1(stp, enp); p1:=p1-1; p2:=p2-1;
--end;
--p1:=p2; p2:=enp-1;
Knot.rotComponent(stp,enp,p1);
p1:=stp+1+p2-p1; p2:=enp-1;
--
return ~Knot.has_band(p1+1,p2-1);
end;
end;
trimCrosses(inout Knot:KNOT) is
-- delete bands on the bridge
i0:=p1+1;
loop while!(i0<p2);
if VERTEXC::band.in(Knot[i0].sep) then Knot.BandDel(i0); end;
i0:=i0+1;
end;
-- delete crossings on the bridge
i0:=p1+1;
loop while!(i0<p2);
if VERTEXC::crossing.in(Knot[i0].sep) then
-- i:=cmpOf(i0);
-- if 0<=i then CodeDel(i); if i<i0 then DEC(i0); end;
-- if (i<p2) then DEC(p2); end; if (i<p1) then DEC(p1); end;
-- end;
Knot.CodeDel(i0.card);
if (i0<p2) then p2:=p2-1; end;
if (i0<p1) then p1:=p1-1; end;
else i0:=i0+1;
end;
end;
i0:=0.int;
loop until!( VERTEXC::code_e=Knot[i0].sep );
-- Del crossings if not exist cmp.
if VERTEXC::crossing.in(Knot[i0].sep) and (Knot.cmpOf(i0).is_neg) then
Knot.CodeDel(i0.card);
if (i0<p2) then p2:=p2-1; end;
if (i0<p1) then p1:=p1-1; end;
else i0:=i0+1;
end;
end;
end;
LenMatch(inout Knot:KNOT, inout q0, inout q1:INT) is
-- match q1 to q0
i0:INT:=q1-1;
loop while!( q0>q1 );
if (stp<i0)and(i0<enp) then Knot.PointInEdge(i0); end;
i0:=i0-1; q1:=q1+1;
if i0<p1 then i0:=q1-1; end;
end;
end;
Animate(p20,p21:INT) is
--Move from KontP0 to KnotP1(=KnotP2).
t, t1, sl, i, j, s, d:INT;
KnotW:KNOT;
-- DRAWKNOT_ALG::ResetPage(KnotP1);
LenMatch(inout KnotP1,inout p20,inout p21);
if ~ SW then KnotP1.mirrorZ; end;
DRAWKNOT_ALG::ResetPage(KnotP0);
LenMatch(inout KnotP0,inout p21,inout p20);
if ~ SW then KnotP0.mirrorZ; end;
s:=0;
loop j:=(p1+1).upto!(p20-1);
d:=KnotP1[j].distance1(KnotP0[j]);
if s<d then s:=d; end;
end;
s:=(s/8)+1; sl:=s;
loop i:=1.int.upto!(s-1);
KnotW:=KnotP0.clone; t:=i; t1:=sl-t; -- 0<=t<=1, scaled s
loop j:=(p1+1).upto!(p20-1);
KnotW[j]:=(KnotP0[j]*t1+KnotP1[j]*t).div(sl);
end;
KnotW.CrossSet(p1, p20); if ~ SW then KnotW.mirrorZ; end;
DRAWKNOT_ALG::ResetPage(KnotW);
end;
end;
SetPhase1(Knot:KNOT) is
if phase.is_zero then
KnotP0:=#; KnotP1:=#;
end;
HISTORY::put(Knot);
stp:=0.int; enp:=Knot.length.int;
p1:=-1; p2:=-1;
phase:=1;
DRAWKNOT_ALG::ResetPage(Knot);
end;
SetPhase0(inout Knot:KNOT) is
if phase.is_zero.not then
HISTORY::back(inout Knot); KnotP0:=#; KnotP1:=#;
end;
phase:=0;
DRAWKNOT_ALG::ResetPage(Knot);
end;
IfNear(inout Knot:KNOT, i0:INT) is
-- check if i0 have near points, and shrink/splice it. c.f. MoveVertex
d,j:INT;
if (i0.is_neg) or (Knot.length.int<i0) then return; end;
Knot.nearVertexV(i0,i0,out j,out d);
if d>=DRAW_ALG::near then return; end;
-- shrink knot
if j=(i0+1) then Knot.DelV(i0); p2:=p2-1;
elsif j=(i0-1) then Knot.DelV(i0); p2:=p2-1;
end;
end;
shared p20,p21:INT;
JumpMove(inout Knot:KNOT, event, button, mouseX,mouseY:INT) is
d,sw,pt:INT;
if event=-1 then SetPhase1(Knot); return;
elsif event=-2 then DRAW_ALG::nearMark(Knot,0.int,DRAW_ALG::far,0.int);
SetPhase0(inout Knot); return;
end;
if phase=0 then SetPhase1(Knot); end;
case phase
when 1 then -- Set p1 of segment p1--p2
case event
when KNOTX::knotMotionNotify then
Knot.miniPt(mouseX,mouseY,out pt,out d,out sw);
DRAW_ALG::nearMark(Knot,pt,d,sw);
when KNOTX::knotButtonPress then ;
when KNOTX::knotButtonRelease then
Knot.miniPt(mouseX,mouseY,out pt,out d,out sw);
DRAW_ALG::nearMark(Knot,pt,DRAW_ALG::far,sw);
if (button=KNOTX::knotButtonL)and(d<DRAW_ALG::near) then
p1:=pt; p2:=-1;
lMouse(inout Knot,inout p1,inout p2,sw);
stp:=Knot.endOfString(p1,-1);enp:=Knot.endOfString(p1,1.int);
DRAWKNOT_ALG::ResetPage(Knot);
KNOTXW::DrawCircle(Knot[p1].x, -Knot[p1].y, 7.int, KNOTX::kStr,false);
phase:=2;
else SetPhase0(inout Knot); SetPhase1(Knot);
end;
end;
when 2 then -- Set p2 of segment p1--p2
case event
when KNOTX::knotMotionNotify then
Knot.miniPt(mouseX,mouseY,out pt,out d,out sw);
if ~((stp<pt)and(pt<enp))then d:=DRAW_ALG::far; end;
DRAW_ALG::nearMark(Knot,pt,d,sw);
KNOTXW::DrawCircle(Knot[p1].x,-Knot[p1].y,7.int,KNOTX::kStr,false);
when KNOTX::knotButtonPress then ;
when KNOTX::knotButtonRelease then
Knot.miniPt(mouseX,mouseY,out pt,out d,out sw);
DRAW_ALG::nearMark(Knot,pt,DRAW_ALG::far,sw);
if (button=KNOTX::knotButtonL)and(d<DRAW_ALG::near) then
p2:=pt;
lMouse(inout Knot,inout p2,inout p1,sw);
if p1=p2 then
SetPhase0(inout Knot); SetPhase1(Knot); return;
end;
if p1>p2 then i0:=p1; p1:=p2; p2:=i0; end;
if CheckSegment(inout Knot) then phase:=3;
else SetPhase0(inout Knot); SetPhase1(Knot); return;
end;
-- Delete crossings on the segment
trimCrosses(inout Knot);
KnotP0:=Knot.clone; -- save original
p20:=p2;
-- KnotP0 with segment p1--p20 is origin work.
-- del old segment
i0:=p1+1;
loop while!(i0<p2); Knot.CodeDel(i0.card); p2:=p2-1; end;
DRAWKNOT_ALG::ResetPage(Knot);
-- OpenMessage("Jump move");
KNOTXW::DrawCircle( Knot[p1].x,-Knot[p1].y, 7.int, KNOTX::kMark, false);
KNOTXW::DrawCircle(Knot[p2].x, -Knot[p2].y, 7.int, KNOTX::kMark, false);
phase:=3; pressL:=false;
elsif button=KNOTX::knotButtonR then
SetPhase0(inout Knot); SetPhase1(Knot);
end;
end;
when 3 then --move segment p1--p2
case event
when KNOTX::knotMotionNotify then
if pressL then
Knot[knotPtr].x:=mouseX; Knot[knotPtr].y:=-mouseY;
KNOTXW::WindowSw(0.int);
DRAWKNOT_ALG::DrawKnot(Knot);
DRAW_ALG::DrawLattice; f_sw::=KNOTXW::FlushPixel;
KNOTXW::WindowSw(1.int);
KNOTXW::DrawCircle(Knot[p1].x, -Knot[p1].y, 7.int, KNOTX::kMark,false);
KNOTXW::DrawCircle(Knot[p2].x, -Knot[p2].y, 7.int, KNOTX::kMark, false);
else
i:INT;
Knot.miniPt(mouseX,mouseY,out i,out d,out sw);
if (i<p1)or(p2<=i)or((i=p1)and(sw.is_zero))then d:=DRAW_ALG::far; end;
DRAW_ALG::nearMark(Knot,i,d,sw);
end;
when KNOTX::knotButtonPress then
if button=KNOTX::knotButtonL then
DRAW_ALG::nearMark(Knot,0.int,DRAW_ALG::far,0.int);
Knot.miniPt(mouseX,mouseY,out i0,out d,out sw);
if (i0<p1)or(p2<=i0)or((i0=p1)and(sw.is_zero))then return; end;
if d>=DRAW_ALG::near then return; end;
if sw=1.int then
i0:=i0+1; Knot.CodeIn(mouseX,-mouseY,i0.card);
p2:=p2+1;
end;
knotPtr:=i0;
pressL:=true;
Knot[knotPtr].x:=mouseX; Knot[knotPtr].y:=-mouseY;
end;
DRAWKNOT_ALG::DrawKnot(Knot); DRAW_ALG::DrawLattice;
KNOTXW::DrawCircle(Knot[p1].x, -Knot[p1].y, 7.int, KNOTX::kMark,false);
KNOTXW::DrawCircle(Knot[p2].x, -Knot[p2].y, 7.int, KNOTX::kMark, false);
when KNOTX::knotButtonRelease then
if button=KNOTX::knotButtonL then
pressL:=false; DRAW_ALG::nearMark(Knot,0.int,DRAW_ALG::far,0.int);
if DRAW_ALG::latticeFlg then
Knot[knotPtr].x:= DRAW_ALG::trimL(Knot[knotPtr].x);
Knot[knotPtr].y:= -DRAW_ALG::trimL(-Knot[knotPtr].y);
end;
IfNear(inout Knot,knotPtr);
knotPtr:=-1;
DRAWKNOT_ALG::DrawKnot(Knot);
DRAW_ALG::DrawLattice;
KNOTXW::DrawCircle(Knot[p1].x, -Knot[p1].y, 7.int, KNOTX::kMark,false);
KNOTXW::DrawCircle(Knot[p2].x, -Knot[p2].y, 7.int, KNOTX::kMark, false);
elsif button=KNOTX::knotButtonR then
-- KnotP0 is original.
-- KnotP1 with segment p1--p21 is new
KnotP1:=Knot.clone; p21:=p2;
Animate(p20,p21);
if ~ SW then Knot.mirrorZ; end;
Knot.CrossSet(p1, p2);
if ~ SW then Knot.mirrorZ; end;
DRAWKNOT_ALG::ResetPage(Knot);
SetPhase1(Knot);
end;
end;
end;
end;
end;