drawknot_alg.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
-- IF ELSIF ELSE THEN END RETURN IN ".in(" AND OR LOOP WHILE TRUE FALSE
-- INTEGER BOOLEAN VertexC
-- PROCEDURE BEGIN
class DRAW_ALG
class DRAW_ALG is
------------------------ lattice ----------------------
const LWidthP:INT:=5;
const LWidth:INT:=2*LWidthP;
const LWidth2:INT:=2*LWidth;
shared latticeFlg:BOOL:=false;
trimL(c:INT):INT is
-- return (c -(c mod LWidth)+LWidthP);
return ((c+LWidthP).div(LWidth))*LWidth;
end;
CnvLattice(c:INT):INT is
return trimL(c);
end;
DrawLattice is
loop x:INT:=LWidth.stepto!(KNOTXW::GraphWidth,LWidth2);
loop y:INT:=LWidth.stepto!(KNOTXW::GraphHeight,LWidth2);
KNOTXW::DrawPoint(x, y, 2);
end;
end;
end;
-- for DrawKnot,DrawKnotPic spaced r-dot at under crossing
sl(x0, y0:INT, inout x1:INT, inout y1:INT, r:INT) is
vx, vy, d, s:INT;
-- vx:=LONG(x1-x0); vy:=LONG(y1-y0);
-- d:=ABS(vx)+ABS(vy); if d>r then s:=d-r; else s:=0; d:=1; end;
-- x1:=x0+SHORT((vx*s) DIV d); y1:=y0+SHORT((vy*s) DIV d);
vx:=(x0-x1); vy:=(y0-y1); d:=vx.abs+vy.abs;
if d>r then x1:=x1+((vx*r) / d); y1:=y1+((vy*r) / d);
else x1:=x0; y1:=y0;
end;
end;
---------------------- mark ------------------------
circleK(Knot:KNOT, i,sw,r,col:INT) is
-- Draw circle at vertex/edge.
-- sw=0:vertex, sw=1:edge.
if (sw=1)or(sw=0) then
KNOTXW::DrawCircle((Knot[i].x+Knot[i+sw].x)/ 2,
-(Knot[i].y+Knot[i+sw].y)/ 2, r, col, false);
end;
end;
circleF(Knot:KNOT, i,r,col:INT) is
KNOTXW::DrawCircle(Knot[i].x, -Knot[i].y, r, col, true);
end;
UpdateVE(Knot:KNOT,inout i0:INT, i1:INT, inout sw0:INT, sw1:INT) is
#OUT+"UpdateVE is uncertified.\n";
if (i0/=i1)or(sw0/=sw1) then
-- MouseK.Off;
if 0<i0 then circleK(Knot,i0,sw0,5,KNOTX::kMark); end;
circleK(Knot,i1,sw1,5,KNOTX::kMark);
i0:=i1; sw0:=sw1;
-- MouseK.On;
end;
end;
------------- state of nearMark -----------
shared smoothDraw:BOOL:=false;
shared markVertex:BOOL:=false;
const near:INT:=16;
const far:INT:=10000;
shared nearMarkd0:INT:=far;
shared nearMarkx0:INT:=0;
shared nearMarky0:INT:=0;
nearMark(Knot:KNOT,pt,d,sw:INT) is
-- Markup the point, if near.
if nearMarkd0<near then
KNOTXW::DrawCircle(nearMarkx0,-nearMarky0,5,KNOTX::kMark,false);
end;
if sw>=2 then d:=far; end;
if d <near then
nearMarkx0:=(Knot[pt].x+Knot[pt+sw].x)/ 2;
nearMarky0:=(Knot[pt].y+Knot[pt+sw].y)/ 2;
KNOTXW::DrawCircle(nearMarkx0,-nearMarky0,5,KNOTX::kMark,false);
end;
nearMarkd0:=d;
end;
end; -- DRAW_ALG
class DRAWKNOT_ALG
class DRAWKNOT_ALG is
--------------------------- Draw Knot --------------------
const arrowLen:FLT:=10.0;
const arrowRatio:FLT:=1.0/3.0;
const arrowLenS:FLT:=arrowLen/arrowRatio;
arrow(inout gx0,inout gy0,inout gx1,inout gy1,inout gx2,inout gy2:INT) is
-- Draw arrow at the center of pt0 and pt1
-- return line pt0-pt1-pt2
ux, uy, vx, vy, s:FLT;
ux:=(gx1-gx0).flt; uy:=(gy1-gy0).flt;
gx1:=(gx1+gx0)/2; gy1:=(gy1+gy0)/2;
s:=(ux*ux+uy*uy).sqrt;
if s>=arrowLenS then s:=arrowLen/s; else s:=arrowRatio; end;
ux:=ux*s; uy:=uy*s;
gx0:=gx1+(-ux+uy*0.6).round.int; gy0:=gy1+(-uy-ux*0.6).round.int;
gx2:=gx1+(-ux-uy*0.6).round.int; gy2:=gy1+(-uy+ux*0.6).round.int;
end;
arrowS(gx0, gy0, gx1, gy1, col:INT) is
-- Draw arrow at the center of pt.0 and pt.1
gx2, gy2:INT;
arrow(inout gx0,inout gy0,inout gx1,inout gy1,inout gx2,inout gy2);
KNOTXW::DrawLine(gx0, gy0, gx1, gy1, col);
KNOTXW::DrawLine(gx2, gy2, gx1, gy1, col);
end;
Bezier(x0, y0, x1, y1, x2, y2, col:INT) is
s, s0, s1, s2, x0l, y0l, x1l, y1l, x2l, y2l:INT;
step:INT:=8;
step2:INT:=step*step;
x0l:=x0; y0l:=y0;
x1l:=x1; y1l:=y1;
x2l:=x2; y2l:=y2;
loop i::=1.upto!(step); -- Followings are scaled ``step''.
-- Bezier curve of order 2.
-- $p(t)=(1-t)^2 p0 + 2t(1-t) p1 + t^2 p2$
s:=i; s1:=step-s;
s0:=s1*s1; s1:=s*s1; s1:=s1+s1; s2:=s*s;
x1:=((s0*x0l+s1*x1l+s2*x2l)/ step2);
y1:=((s0*y0l+s1*y1l+s2*y2l)/ step2);
KNOTXW::DrawLine(x0, y0, x1, y1, col);
x0:=x1; y0:=y1;
end;
end;
next(Bridge:KNOT,
inout x0, inout y0, inout x1, inout y1, inout x2, inout y2, fi:INT) is
x0:=x2; y0:=y2;
x1:=Bridge[fi].x; y1:=Bridge[fi].y;
x2:=(Bridge[fi+1].x+x1)/ 2; y2:=(Bridge[fi+1].y+y1)/ 2;
end;
flush(inout Bridge:KNOT,col:INT) is
-- display bridge
x0,x1,x2, y0,y1,y2:INT;
fi:INT;
if DRAW_ALG::smoothDraw then
Bridge.append(Bridge[1].x,Bridge[1].y);
fi:=0;
next(Bridge,inout x0,inout y0,inout x1,inout y1,inout x2,inout y2,fi);
loop fi:=1.upto!(Bridge.length-3);
next(Bridge,inout x0,inout y0,inout x1,inout y1,inout x2,inout y2,fi);
Bezier(x0, y0, x1, y1, x2, y2,col);
end;
fi:=Bridge.length-2;
next(Bridge,inout x0,inout y0,inout x1,inout y1,inout x2,inout y2,fi);
if (Bridge[0].x=x1)and(Bridge[0].y=y1) then
Bezier(x0, y0, x1, y1, x2, y2, col);
else
KNOTXW::DrawLine(x0, y0, x1, y1, col);
fi:=0; -- draw 1st segment
next(Bridge,inout x0,inout y0,inout x1,inout y1,inout x2,inout y2,fi);
KNOTXW::DrawLine(x1, y1, x2, y2, col);
end;
else
loop fi:=0.upto!(Bridge.length-2);
KNOTXW::DrawLine(Bridge[fi].x,Bridge[fi].y,
Bridge[fi+1].x,Bridge[fi+1].y,col);
end;
end;
Bridge:=#;
end;
DrawKnot(Knot:KNOT) is
col:INT; (* current line width/color*)
i,band_sgn1,band_sgn2:INT;
gx0, gx1, gy0, gy1:INT;
px0, py0, px1, py1:INT;
firstK:BOOL;
fPos:INT;
-- #OUT+"DrawKnot:\n"; Knot.checkKnot;
Bridge:KNOT:=#; fBridge:KNOT:=#;
KNOTXW::ClearWindow;
i:=0;
loop
if ((i+1)>Knot.length) or VERTEXC::endc.in(Knot[i].sep ) then break!; end;
Knot[i].work:=0;
gx0:=gx1; gy0:=gy1;
gx1:=Knot[i+1].x; gy1:=-Knot[i+1].y;
if DRAW_ALG::markVertex and VERTEXC::normal.in(Knot[i].sep) then
DRAW_ALG::circleK(Knot,i,0,1,col);
end;
if VERTEXC::separator.in(Knot[i].sep) then
-- start point of a string
if VERTEXC::gs.in(Knot[i].sep) then
firstK:=true; col:=KNOTX::kStr;
elsif VERTEXC::ks.in(Knot[i].sep) then
firstK:=true;
col:=KNOTX::kStr;
elsif VERTEXC::ts.in(Knot[i].sep) then
firstK:=false; col:=KNOTX::tStr;
if Knot.is_coherent(i) then col:=KNOTX::tStr;
else col:=KNOTX::rtStr;
end;
end;
i:=i+1;
elsif VERTEXC::separator.in(Knot[i+1].sep) then --end of the string
if VERTEXC::ge.in(Knot[i+1].sep) then
DRAW_ALG::circleF(Knot,i,4,col);
elsif VERTEXC::ks.in(Knot[i-1].sep) then
DRAW_ALG::circleK(Knot,i,0,3,col); --first point of ``AddCompo''
elsif VERTEXC::ke.in(Knot[i+1].sep) then
if firstK then -- The component has no under crossings.
Bridge.append(gx0, gy0);
else
if (gx0/=fBridge[0].x)or(gy0/=fBridge[0].y) then
Bridge.append(gx0,gy0);flush(inout Bridge,col);
end;
fPos:=-1;
Bridge.append(fBridge);
end;
flush(inout Bridge,col);
else --te:end of band
Bridge.append(gx0, gy0);
flush(inout Bridge,col);
end;
i:=i+2; --jump the end code and go to start code of next string
else
px0:=gx0; py0:=gy0; px1:=gx1; py1:=gy1;
if VERTEXC::under.in(Knot[i+1].sep) then
DRAW_ALG::sl(px0, py0,inout px1,inout py1, 7);
end;
if VERTEXC::under.in(Knot[i].sep) then
DRAW_ALG::sl(px1, py1,inout px0,inout py0, 7);
elsif VERTEXC::ks.in(Knot[i-1].sep)
or VERTEXC::ts.in(Knot[i-1].sep) then
arrowS(gx0, gy0, gx1, gy1,col); -- start point
elsif VERTEXC::band.in(Knot[i].sep) then
DRAW_ALG::circleK(Knot,i,0,4,KNOTX::kMark);
end;
Bridge.append(px0, py0);
if VERTEXC::under.in(Knot[i+1].sep)
or VERTEXC::band.in(Knot[i+1].sep) then
Bridge.append(px1, py1);
if firstK then fBridge:=Bridge; firstK:=false; Bridge:=#;
else flush(inout Bridge,col);
end;
end;
i:=i+1;
end;
end;
-- Knot.checkCode;
end;
ChangeScreen(Knot:KNOT, latticeFlg:BOOL) is
-- writePage:=WPCh-writePage; Screen(Mode, 0, writePage, dispPage);
DrawKnot(Knot); if latticeFlg then DRAW_ALG::DrawLattice; end;
-- dispPage:=DPCh-dispPage; Screen(Mode, 0, writePage, dispPage);
end;
ResetPage(Knot:KNOT) is
KNOTXW::WindowSw(0); DrawKnot(Knot); KNOTXW::FlushPixel;
KNOTXW::WindowSw(1);
-- ChangeScreen(false);
-- REPEAT;ChangeScreen(false);UNTIL writePage=Wp1;
end;
end; -- DRAWKNOT_ALG