drawknot_alg.sa


Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
 


class DRAW_ALG

class DRAW_ALG is ------------------------ lattice ---------------------- const LWidthP:INT:=5; const LWidth:INT:=LWidthP*2; const LWidth2:INT:=LWidth*2; shared latticeFlg:BOOL:=false; trimL(c:INT):INT is 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.int); end; 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.int)or(sw=0.int) 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 i0.is_pos then circleK(Knot,i0,sw0,5.int,KNOTX::kMark); end; circleK(Knot,i1,sw1,5.int,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.int,KNOTX::kMark,false); end; if sw>=2.int 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.int,KNOTX::kMark,false); end; nearMarkd0:=d; end; ------------ crossings sl(x0, y0:INT, inout x1:INT, inout y1:INT, r:INT) is -- for DrawKnot,DrawKnotPic spaced r-dot at under crossing 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; ------------ orientation of strings 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; end; -- DRAW_ALG

class DRAWKNOT_ALG

class DRAWKNOT_ALG is --------------------------- Draw Knot -------------------- arrowS(gx0, gy0, gx1, gy1, col:INT) is -- Draw arrow at the center of pt.0 and pt.1 gx2, gy2:INT; DRAW_ALG::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.int.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.int.upto!(Bridge.length.int-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.int-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.int.upto!(Bridge.length.int-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:=#; sw::=KNOTXW::ClearWindow; i:=0.int; loop if ((i+1)>Knot.length.int) or VERTEXC::endc.in(Knot[i].sep ) then break!; end; Knot[i].work:=0.int; 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.int,1.int,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.int,col); elsif VERTEXC::ks.in(Knot[i-1].sep) then DRAW_ALG::circleK(Knot,i,0.int,3.int,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.int); end; if VERTEXC::under.in(Knot[i].sep) then DRAW_ALG::sl(px1, py1,inout px0,inout py0, 7.int); 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.int,4.int,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.int); DrawKnot(Knot); sw::=KNOTXW::FlushPixel; KNOTXW::WindowSw(1.int); -- ChangeScreen(false); -- REPEAT;ChangeScreen(false);UNTIL writePage=Wp1; end; end; -- DRAWKNOT_ALG

class DRAWKNOT_PIC_ALG

class DRAWKNOT_PIC_ALG is -- Convert knot diagram to Tpic graphic data for plainTeX, AmS-TeX, LaTex. -- -- I assume as follows in this version. Use 'mm' as a unit length. -- Diagram is scaled into the box of (width,height) with margin of 'margin'. -- -- (xofs(mm),yofs(mm)) is offset from top-left in LaTeX picture. -- -- To use this, copy to LaTeX file as picture environment. -- top-left is origin of LaTeX/picture and tpic. -- But, note their direction. -- picture: right to positive, under to negative -- tpic : right to positive, under to positive -- In tpic , unit length is 1/1000 in. shared kxmin, kxmax, kymin, kymax, kwidth:INT; shared scale:FLT; -- scaling shared xofsTP, yofsTP:FLT; -- (left,top) of knot shared widthTeX,heightTeX:FLT; -- size of picture unitLen:FLT is -- Note that unit length of tpic is 0.001in = 0.001*25.4mm. return 0.0254; -- 0.0254mm = 0.001in end; spc:STR is -- TeX special command. return " \\special{"; end; SetScale(Knot:KNOT, width, height, margin, scalingMode:INT) is scaleX,scaleY:FLT; max:INT:=30000; kxmin:= max; kxmax:=-max; kymin:= max; kymax:=-max; loop v::=Knot.k.elt!; if VERTEXC::endc.in(v.sep) then break!; end; if VERTEXC::normal.in(v.sep) then if v.x<kxmin then kxmin:=v.x; end; if kxmax<v.x then kxmax:=v.x; end; if (-v.y)<kymin then kymin:=-v.y; end; if kymax<(-v.y) then kymax:=-v.y; end; end; end; widthTeX:=width.flt/unitLen; heightTeX:=height.flt/unitLen; xofsTP:=margin.flt/unitLen; yofsTP:=margin.flt/unitLen; scaleX:=(widthTeX-2.0*xofsTP)/(kxmax-kxmin).flt; scaleY:=(heightTeX-2.0*yofsTP)/(kymax-kymin).flt; scale:=scaleX; if scaleY<scale then scale:=scaleY; end; if scalingMode=1.int then -- centering xofsTP:=(widthTeX-((kxmax-kxmin).flt*scale))/2.0; yofsTP:=(heightTeX-((kymax-kymin).flt*scale))/2.0; elsif scalingMode=2.int then -- remake width and height widthTeX:=(kxmax-kxmin).flt*scale+2.0*xofsTP; heightTeX:=(kymax-kymin).flt*scale+2.0*yofsTP; else -- centering by default xofsTP:=(widthTeX-((kxmax-kxmin).flt*scale))/2.0; yofsTP:=(heightTeX-((kymax-kymin).flt*scale))/2.0; end; end; xposTP(x:INT):STR is return ((x-kxmin).flt*scale+xofsTP).round.inti.decimal_str; end; yposTP(y:INT):STR is return ((y-kymin).flt*scale+yofsTP).round.inti.decimal_str; end; setCol(col:INT) is #LOGOUT+spc+"pn "+col.str+"}% line width\n"; end; setPa(x, y:INT) is #LOGOUT+spc+"pa "+xposTP(x)+" "+yposTP(y)+"}% point\n"; end; arrowPic(gx0, gy0, gx1, gy1:INT) is -- Draw arrow at the center of pt.0 and pt.1 gx2, gy2:INT; DRAW_ALG::arrow(inout gx0,inout gy0,inout gx1,inout gy1,inout gx2,inout gy2); setPa(gx0, gy0); setPa(gx1, gy1); setPa(gx2, gy2); #LOGOUT+spc+"fp}% arrow\n"; end; circle(x, y, r, incol:INT) is if incol>=0.int then #LOGOUT+spc+"sh "+incol.str+"}%\n"; end; #LOGOUT+spc+"ar "+xposTP(x)+" "+yposTP(y)+" " +(scale*r.flt).round.str+" "+(scale*r.flt).round.str+" 0 6.3}% circle\n"; end; flush(inout Bridge:KNOT,smoothDraw:BOOL) is if Bridge.size>2 then loop i::=0.upto!(Bridge.size-2); setPa(Bridge[i].x, Bridge[i].y); end; if (Bridge.size>3)and smoothDraw then #LOGOUT+spc+"sp}% smooth lines\n"; else #LOGOUT+spc+"fp}% rigid lines\n"; end; end; Bridge:=#; end; DrawKnotPic(Knot:KNOT, width, height, margin, scalingMode:INT) is DrawKnotPic(Knot, width, height, margin, scalingMode,DRAW_ALG::smoothDraw) end; DrawKnotPic(Knot:KNOT, width, height, margin, scalingMode:INT,smoothDraw:BOOL) is -- width, height, margin : unit length 1mm -- JIS standard -- fat line : 0.3-0.8mm -- medium line : 0.2-0.4mm -- thin line : <0.2mm col:INT; -- current line width kStr:INT:=16; -- knot: 0.4mm tStr:INT:=8; -- band: 0.2mm col0:INT:=8; i:INT; gx0, gx1, gy0, gy1:INT; px0, px1, py0, py1:INT; fBridge:KNOT:=#; firstK:BOOL; Bridge:KNOT:=#;-- sequences of vertices to draw lines, and terminated by "endc" if Knot.length<5 then return; end; if (width<(margin*2+10))or(height<(margin*2+10))or(margin.is_neg) then return; end; SetScale(Knot, width, height, margin, scalingMode); -- header #LOGOUT+"\n%% "; LOGOUT::LogTime; #LOGOUT+"%% LaTeX picture with tpic-special: knot diagram with "; if smoothDraw then #LOGOUT+"smooth"; else #LOGOUT+"rigid"; end; #LOGOUT+" lines.\n"; #LOGOUT+"%% knot size(mm): (width,height)=(" +((kxmax-kxmin).flt*scale*unitLen).round.card.str+"," +((kymax-kymin).flt*scale*unitLen).round.card.str+")\n"; #LOGOUT+"%% box size: (width,height)=(" +(widthTeX*unitLen).round.card.str+","+(heightTeX*unitLen).round.card.str+")\n"; #LOGOUT+"%% margin: (left,upper)=(" +(xofsTP*unitLen).round.card.str+","+(yofsTP*unitLen).round.card.str+")\n"; #LOGOUT+"\\begin{center}\n"; #LOGOUT+"\\unitlength 0.001in\n"; #LOGOUT+"\\begin{picture}("+widthTeX.round.inti.decimal_str+","+heightTeX.round.inti.decimal_str+")" +"(0,"+(-heightTeX).round.inti.decimal_str+")\n"; col:=col0; i:=0; loop if VERTEXC::endc.in(Knot[i].sep) then; break!; end; gx0:=gx1; gy0:=gy1; gx1:=Knot[i+1].x; gy1:=-Knot[i+1].y; if VERTEXC::separator.in(Knot[i].sep) then -- start point of a string if VERTEXC::gs.in(Knot[i].sep)then firstK:=true; col:=kStr; elsif VERTEXC::ks.in(Knot[i].sep)then firstK:=true; col:=kStr; elsif VERTEXC::ts.in(Knot[i].sep)then firstK:=false; col:=tStr; end; setCol(col); i:=i+1; -- circle(gx1,gy1,3,1.0); -- mark start pt. elsif VERTEXC::separator.in(Knot[i+1].sep) then -- end of the string if VERTEXC::ge.in(Knot[i+1].sep) then circle(px0, py0, 2.int, col); 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,smoothDraw); end; Bridge.append(fBridge); fBridge:=#; end; flush(inout Bridge,smoothDraw); else -- te:end of band Bridge.append(gx0,gy0); flush(inout Bridge,smoothDraw); 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, 10.int); end; if VERTEXC::under.in(Knot[i].sep) then DRAW_ALG::sl(px1, py1,inout px0,inout py0, 10.int); elsif VERTEXC::ks.in(Knot[i-1].sep) or VERTEXC::ts.in(Knot[i-1].sep) then -- start point arrowPic(gx0, gy0, gx1, gy1); elsif VERTEXC::band.in(Knot[i].sep) then circle(px0, py0, 2.int, tStr); 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; Bridge:=#; firstK:=false; else flush(inout Bridge,smoothDraw); end; end; i:=i+1; end; end; #LOGOUT+"\\end{picture}\n"; #LOGOUT+"\\end{center}\n"; #LOGOUT+"\n"; end; end; -- PIC