ndata.sa
Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
--
-- c.f.
-- n-data for links:
-- Masaaki WADA. "CODING LINK DIAGRAMS".
--
-- Copyright (C) 1992 1996 Kouji KODAMA
-- 1998/4 K.Kodama History
-- 1996/10 K.Kodama LINUX version
-- 1992/10/12
-- k49c 49 crossing Pretzel Knot [9,9,9,9,9,3,1]
-- Knot2NData: 6.987 sec
-- WriteNData: 3.363 sec
-- readNData : 3.796 sec
-- NData2Knot: 0.826 sec
-- 1992/10/10
-- k49c 49 crossing Pretzel Knot [9,9,9,9,9,3,1]
-- Knot2NData: 12.172 sec
-- WriteNData: 3.363 sec
-- readNData : 3.796 sec
-- NData2Knot: 0.826 sec
--NData: K49C
--n1 n3 n5 n3 n7 n9 2n11 2n13 r6 r18 r2 r16 r8 r4 r12 r10 r14 u7 u13
--u7 2u5 u7 u5 u3 4n3 n9 n3 n9 n3 r10 r14 r18 r8 r16 r6 r4 r2 r12 u3
-- u5 u3 u7 u9 3u3 n3 n5 n3 n9 n5 n13 n3 n5 r10 r14 r8 r16 r4 r18 r2
-- r6 r12 u17 u9 u11 u9 2u3 u5 u3 4n3 n7 n3 n5 n3 r18 r16 r8 r10 r12
-- r14 r2 r4 r6 u17 u15 u7 u11 u5 u3 u5 u3 3n3 n5 n3 3n7 r18 r16 r14
-- r12 r10 r6 r8 r4 r2 u13 u15 u13 2u9 u3 u5 u3 2n3 r4 r2 r6 2u3 r2 u3 u1
-- 49 crossing
-- 140 Code
-- 405 char
-- max:
-- 49 crossing
-- maxC*4 = 200 code
-- (code)*3 =600 char
-- 1992/10 Kouji KODAMA
-- NData --> Knot Diagram.
class NCODE
class NCODE is
attr typ:INT;
attr str:CARD; -- str-th string
attr index:CARD; -- braid/ndata index
attr pos:INT; -- height
-- attr weight:INT; -- work
-- types --
const tw:=0;-- empty/work
const tz:=1;-- terminator
const tn:=2;-- code n
const tu:=3;-- code u
const tr:=4;-- code r
const tl:=5;-- code l
create:SAME is
res:SAME:=new;
res.typ:=tw; res.str:=0; res.index:=0; res.pos:=0.int;
return res;
end;
create(t:INT, s:CARD):SAME is
res:SAME:=new;
res.typ:=t; res.str:=s; res.index:=0; res.pos:=0.int;
return res;
end;
clone:SAME is
res:NCODE:=#;
res.typ:=typ; res.str:=str; res.index:=index; res.pos:=pos;
return res;
end;
end; -- class NCODE
class NDATA
class NDATA is
attr nd:ARRAY{NCODE};
create:SAME is
res:SAME:=new; res.nd:=#(1); res.nd[0]:=#(NCODE::tz,0);
return res;
end;
clone:SAME is
res:SAME:=#; res.nd:=#(nd.size);
loop i::=nd.ind!; res.nd[i]:=nd[i].clone; end;
return res;
end;
size:CARD is
return nd.size;
end;
aget(i:CARD):NCODE is return nd[i]; end;
aset(i:CARD, v:NCODE) is nd[i]:=v; end;
aget(i:INT):NCODE is return nd[i.card]; end;
aset(i:INT, v:NCODE) is nd[i.card]:=v; end;
append(ncode:NCODE) is
-- append ncode at the end of self.
nd:=nd.resize(nd.size+1);
if nd.has_ind(nd.size-2) and nd[nd.size-2].typ=NCODE::tz then
nd[nd.size-1]:=nd[nd.size-2]; nd[nd.size-2]:=ncode;
else
nd[nd.size-1]:=ncode;
end;
end;
append(Type:INT,String:CARD) is
append(#NCODE(Type,String));
end;
printD is
-- print for debug/check
#OUT+"NDATA\n";
#OUT+NDATA2STR::N2S(self)+"\n";
end;
check:BOOL is
if void(self) then return false;
elsif void(nd) then return false;
elsif nd.size=0 then return false;
elsif nd[nd.size-1].typ/=NCODE::tz then return false;
end;
ind::=0;
loop i::=nd.ind!;
case nd[i].typ
when NCODE::tn then
if (nd[i].str<=0)or(nd[i].str>(ind+1)) then return false; end;
ind:=ind+2;
when NCODE::tu then
if (nd[i].str<=0)or(nd[i].str>=ind) then return false; end;
ind:=ind-2;
when NCODE::tr then
if (nd[i].str<=0)or(nd[i].str>=ind) then return false; end;
when NCODE::tl then
if (nd[i].str<=0)or(nd[i].str>=ind) then return false; end;
when NCODE::tz then
if ind/=0 then return false; end;
if i/=(nd.size-1) then return false; end;
when NCODE::tw then ;
else return false;
end;
end;
return true;
end;
setIndex:BOOL is
if ~check then #OUT+"setIndex: check error\n"; return false; end;
ind::=0;
loop i::=nd.ind!;
case nd[i].typ
when NCODE::tn then
if nd[i].str>(ind+1) then #OUT+"setIndex: error tn\n"; return false; end;
ind:=ind+2; nd[i].index:=ind;
when NCODE::tu then
if nd[i].str>=ind then #OUT+"setIndex: error tu\n"; return false; end;
nd[i].index:=ind; ind:=ind-2;
when NCODE::tr then
if nd[i].str>=ind then #OUT+"setIndex: error tr\n"; return false; end;
nd[i].index:=ind;
when NCODE::tl then
if nd[i].str>=ind then #OUT+"setIndex: error tl\n"; return false; end;
nd[i].index:=ind;
when NCODE::tz then
if ind/=0 then #OUT+"setIndex: error tz\n"; return false; end;
nd[i].str:=0; nd[i].index:=ind;
when NCODE::tw then
nd[i].index:=ind;
else #OUT+"setIndex: unknown code\n"; return false;
end;
end;
return true;
end;
initPos:BOOL is
-- Set pos: position on diagram
if size<=0 then return false; end;
loop i::=nd.ind!; nd[i].pos:=i.int; end;
return true;
end;
end; -- class NDATA is
class NDATA2STR
class NDATA2STR is
------------------- NDATA --> STR -------------
private addS(inout wordStr:STR, ite:CARD, mark:STR, strnum:CARD) is
if ite>1 then wordStr:=wordStr+ite.str; end;
wordStr:=wordStr+mark+strnum.str+" ";
end;
N2S(NData:NDATA):STR is
mark:STR; wordStr::=""; ite::=1;
loop wi::=NData.nd.ind!;
if NData.nd.has_ind(wi+1)
and (NData[wi].str=NData[wi+1].str)
and (NData[wi].typ=NData[wi+1].typ) then
ite:=ite+1;
else
case NData[wi].typ
when NCODE::tn then mark:="n";
addS(inout wordStr, ite, mark, NData[wi].str);
ite:=1;
when NCODE::tu then mark:="u";
addS(inout wordStr, ite, mark, NData[wi].str);
ite:=1;
when NCODE::tr then mark:="r";
addS(inout wordStr, ite, mark, NData[wi].str);
ite:=1;
when NCODE::tl then mark:="l";
addS(inout wordStr, ite, mark, NData[wi].str);
ite:=1;
when NCODE::tz then mark:="endcode "; ite:=1;
wordStr:=wordStr+mark;
when NCODE::tw then mark:="w";
addS(inout wordStr, ite, mark, NData[wi].str);
ite:=1;
else mark:="?";-- Unknown code
wordStr:=" endcode "; return wordStr;
end;
if (wi+1).mod(10)=0 then wordStr:=wordStr+"\n"; end;
end;
end;
return wordStr;
end;
NData2Str(NData:NDATA, out wordStr:STR):BOOL is
if ~NData.check then
#OUT+"NData2Str: failed to convert ndata to str.\n";
wordStr:=" endcode ";return false;
end;
wordStr:=N2S(NData);
return true;
end;
end; -- class NDATA2STR
class STR2NDATA
class STR2NDATA is
---------------- STR --> NDATA -------------
errMsg(n:CARD) is
#OUT+"Str2NData: Cannot parse the NDATA expression.("+n.str+")\n";
end;
Str2NData(wordStr:STR, out NData:NDATA):BOOL is
strnum:INT;
wstr, typeC:STR;
if wordStr.size<1 then return false; end;
sc::=wordStr.cursor;
NData:=#;
ip::=0; ite:INT:=1.int;
loop
-- parse wordStr
if sc.is_done then errMsg(1); NData:=#; return false; end;
wstr:=STRINGSK::splitStr(inout sc);
--
if wstr="endcode" then
if ~NData.check then
errMsg(2); NData:=#; return false;
end;
return NData.setIndex;
end;
ip:=0;
if ~STRINGSK::Str2Int(wstr,inout ip,inout ite) then ite:=1.int; end;
if ite.is_non_pos then errMsg(3); NData:=#; return false;
elsif ite>1.int then
if sc.is_done then errMsg(4); NData:=#; return false; end;
typeC:=STRINGSK::splitStr(inout sc);
--
else typeC:=wstr;
end;
if sc.is_done then errMsg(5); NData:=#; return false; end;
wstr:=STRINGSK::splitStr(inout sc);
--
ip:=0;
if ~STRINGSK::Str2Int(wstr,inout ip,inout strnum) then
errMsg(6); NData:=#; return false;
end;
loop ite.times!;
case typeC
when "n" then NData.append(#NCODE(NCODE::tn,strnum.card));
when "u" then NData.append(#NCODE(NCODE::tu,strnum.card));
when "r" then NData.append(#NCODE(NCODE::tr,strnum.card));
when "l" then NData.append(#NCODE(NCODE::tl,strnum.card));
else errMsg(7); NData:=#; return false;
end;
end;
end;
end;
end; -- class STR2NDATA
class NDATA2KNOT
class NDATA2KNOT is
-------------NData[] --> Knot[] ---------------------
findStart(NData:NDATA, KTbl:ARRAY{BOOL}, out wi:CARD):BOOL is
--search start point of a component -->wi
wi:=0;
loop
if NData[wi].typ=NCODE::tz then return false; end;
if (NCODE::tn=NData[wi].typ )and(~KTbl[wi]) then return true; end;
wi:=wi+1;
end;
end;
searchNext(NData:NDATA, inout wi:CARD, dir0:INT, str0:CARD):BOOL is
-- search next code
loop
wi:=(wi.int+dir0).card;
if ~NData.nd.has_ind(wi) then return false; end;
case NData[wi].typ
when NCODE::tn, NCODE::tu then break!;
when NCODE::tr, NCODE::tl then
if (NData[wi].str=str0)or(NData[wi].str+1=str0) then
break!;
end;
end;
end;
return true;
end;
setStr1(NData:NDATA, wi:CARD, dir0:INT, inout str0:CARD, inout dir1:INT, inout str1:CARD, inout ofs:INT) is
-- wi,dir0,str0 ---> str0,dir1,str1,ofs
dir1:=dir0; str1:=str0; ofs:=1.int;
if dir0=1.int then
case NData[wi].typ
when NCODE::tn then
if NData[wi].str>str0 then str0:=str0+1; ofs:=-1;
else str1:=str0+2; str0:=str0+1;
end;
when NCODE::tu then
if NData[wi].str>=str0 then
if NData[wi].str=str0 then str1:=str0+1; dir1:=-1;
end;
else ofs:=-1;
if NData[wi].str+1=str0 then str1:=str0-1; dir1:=-1;
else str1:=str0-2;
end;
end;
when NCODE::tr, NCODE::tl then
if NData[wi].str=str0 then str1:=str0+1;
else ofs:=-1; str1:=str0-1;
end;
end;
else -- dir=-1
case NData[wi].typ
when NCODE::tu then
if NData[wi].str>str0 then str0:=str0+1; ofs:=-1;
else str1:=str0+2; str0:=str0+1;
end;
when NCODE::tn then
if NData[wi].str>=str0 then
if NData[wi].str=str0 then str1:=str0+1; dir1:=1; end;
else ofs:=-1;
if NData[wi].str+1=str0 then str1:=str0-1; dir1:=1;
else str1:=str0-2;
end;
end;
when NCODE::tr, NCODE::tl then
if NData[wi].str=str0 then str1:=str0+1;
else ofs:=-1; str1:=str0-1;
end;
end;
end;
end;
shared str0:CARD; --current str.
shared str1: CARD;
shared pos0: INT; -- current pos.
shared dir0:INT; -- current dir= -1/ 1
shared dir1:INT;
shared ofs:INT; -- slope
shared v0,v1,v2,p0,scale:VERTEXK;
setPts(NData:NDATA,wi:INT) is
-- x0:=px0+(pos0*2+1-dir0)*xscale;
-- y0:=py0+(str0*2 -index )*yscale;
-- x1:=px0+(pos0*2+1+dir0)*xscale;
-- y1:=py0+((str0+ofs)*2 -index )*yscale;
-- x2:=(x0+x1) DIV 2;
-- y2:=(y0+y1) DIV 2;
vd:VERTEXK:=scale.transform(dir0,ofs);
v0:=scale.transform(pos0*2+1-dir0, str0.int*2.int -NData[wi].index.int)+p0;
v2:=v0+vd; v1:=v2+vd;
--x2:=px0+(pos0*2+1)*xscale; x0:=x2-d; x1:=x2+d;
--y0:=py0 + (str0*2 -NData[wi].index )*yscale; y2:=y0+o; y1:=y2+o;
end;
PointInPt2(NData:NDATA,inout Knot:KNOT,wi1:CARD,dir0:INT,str1:CARD,pos0,ofs:INT,v:VERTEXK, inout pt:CARD,inout needPt0:BOOL) is
-- check the condition of the next code,
-- then set (x1,y1) to Knot[] if needed
-- and set "needPt0" be true if (x0,y0) of the next code is needed.
-- --> needPt0.
le, ge, og:BOOL;
if NData[wi1].pos=pos0+dir0 then
needPt0:=false;
le:=NData[wi1].str<=str1; ge:=NData[wi1].str>=str1; og:=(ofs=1.int);
case NData[wi1].typ
when NCODE::tn then
if dir0=1.int then
--if (NData[wi1].str>str1) and (ofs=-1) then
--elsif (NData[wi1].str<=str1)and(ofs=1) then
--else Knot.CodeIn(x, y, pt); pt:=pt+1; ;
--end;
if le/=og then Knot.CodeIn(v, pt); pt:=pt+1; end;
else -- dir0=-1
--if (NData[wi1].str>=str1) and (ofs=1) then
--elsif (NData[wi1].str < str1) and (ofs=-1) then
--else Knot.CodeIn(x, y, pt); pt:=pt+1; ;
--end;
if ge/=og then Knot.CodeIn(v, pt); pt:=pt+1; end;
end;
when NCODE::tu then
if dir0=1.int then
--if (NData[wi1].str>=str1) and (ofs=1) then
--elsif (NData[wi1].str < str1) and (ofs=-1) then
--else Knot.CodeIn(x, y, pt); pt:=pt+1; ;
--end;
if ge/=og then Knot.CodeIn(v, pt); pt:=pt+1; end;
else -- dir0=-1
--if (NData[wi1].str>str1)and(ofs=-1) then
--elsif (NData[wi1].str<=str1)and(ofs=1)then
--else Knot.CodeIn(x, y, pt); pt:=pt+1; ;
--end;
if le/=og then Knot.CodeIn(v, pt); pt:=pt+1; end;
end;
when NCODE::tr, NCODE::tl then
if (NData[wi1].str=str1)and og then ;
elsif (NData[wi1].str+1 =str1)and (~og) then ;
else Knot.CodeIn(v, pt); pt:=pt+1;
end;
end;
else Knot.CodeIn(v, pt); pt:=pt+1; needPt0:=true;
end;
end;
PointInCr(inout Knot:KNOT,inout tp:CARD, OverSw:BOOL) is
Knot.CodeIn(v2, tp);
if (str1>str0)=OverSw then Knot[tp].sep:=VERTEXC::cross_over;
else Knot[tp].sep:=VERTEXC::cross_under;
end;
tp:=tp+1;
end;
errMsg(n:CARD) is
#OUT+"NData2Knot: failed to convert ndata to knot.("+n.str+")\n";
end;
NData2Knot(ndata:NDATA, inout Knot:KNOT):BOOL is
wi, tp:CARD;
-- wi, dir0/1, str0/1, pos0, ofs ,x , y, tp
if ndata.size=0 then Knot:=#; return true; end;
if ~ ndata.check then errMsg(1); return false; end;
NData:NDATA:=ndata.clone;
if ~ NData.initPos then errMsg(2);return false; end;
if ~ NData.setIndex then errMsg(3);return false; end;
maxWidth:INT:=0.int; maxDepth:INT:=0.int;
KTbl:ARRAY{BOOL}:=#(NData.size); -- false: not used. true: used.
loop wi:=NData.nd.ind!;
KTbl[wi]:=false;
maxWidth:=maxWidth.max(NData[wi].index.int);
maxDepth:=maxDepth.max(NData[wi].pos);
end;
screenX::=KNOTXW::GraphWidth-20;
screenY::=KNOTXW::GraphHeight-20;
scale:=#(screenX.div((maxDepth+1)*2.int),screenY.div((maxWidth-1)*2.int));
scale:=scale.max(2.int,2.int).min(20.int,20.int);
-- xscale:=screenX.div((maxDepth+1)*2); xscale:=xscale.max(2).min(20);
-- yscale:=screenY.div((maxWidth-1)*2); yscale:=yscale.max(2).min(20);
if (scale.y*100.int)>(scale.x*140.int) then scale.y:=(scale.x*140.int+50)/100.int; end;
if (scale.x*100.int)>(scale.y*140.int) then scale.x:=(scale.y*140.int+50)/100.int; end;
p0:=#(screenX/2.int -(maxDepth+1)*scale.x, -screenY/2.int -scale.y);
needPt0:BOOL; -- true if needed to set Pt0 at the next code
Knot:=#; tp:=0; wi:=0;
loop while!(findStart(NData,KTbl,out wi)) ;
KTbl[wi]:=true;
Knot.CodeIn(0.int, 0.int,VERTEXC::knot_s, tp); tp:=tp+1;
Knot.CodeIn(0.int, 0.int,VERTEXC::knot_e, tp);
dir0:=-1; str0:=NData[wi].str+1; pos0:=NData[wi].pos;
setStr1(NData,wi,dir0,inout str0,inout dir1,inout str1,inout ofs);
setPts(NData,wi.int);
Knot.CodeIn(v2, tp); tp:=tp+1;
v1:=#(v0.x,v1.y);
loop
if ~searchNext(NData,inout wi,dir1,str1) then
errMsg(4);return false;
end;
PointInPt2(NData,inout Knot,wi,dir1,str1,pos0,ofs,v1,inout tp,inout needPt0);
dir0:=dir1; str0:=str1; pos0:=NData[wi].pos;
setStr1(NData,wi,dir0,inout str0,inout dir1,inout str1,inout ofs);
setPts(NData,wi.int);
if needPt0 then Knot.CodeIn(v0, tp); tp:=tp+1; end;
if dir0=1.int then
case NData[wi].typ
when NCODE::tu then
if dir1=-1 then
Knot.CodeIn(v2, tp); tp:=tp+1; v1:=#(v0.x,v1.y);
end;
when NCODE::tn then ;
when NCODE::tr then PointInCr(inout Knot,inout tp,false);
when NCODE::tl then PointInCr(inout Knot,inout tp,true);
end;
else --dir0=-1
case NData[wi].typ
when NCODE::tn then
if dir1=1.int then
Knot.CodeIn(v2, tp); tp:=tp+1; v1:=#(v0.x,v1.y);
if KTbl[wi] then tp:=tp+1; break!; end; -- end of the component
KTbl[wi]:=true;
end;
when NCODE::tu then ;
when NCODE::tr then PointInCr(inout Knot,inout tp,true);
when NCODE::tl then PointInCr(inout Knot,inout tp,false);
end;
end;
end;
end;
Knot.concat; Knot.edge_clean; Knot.shiftToInside;
return true;
end;
end; -- class NDATA2KNOT
class KNOT2NDATA
class KNOT2NDATA is
----------------- Knot[] --> NData[] --------------------------
-- Note.
-- Let
-- p: prime (> maxY)
-- q: (p,q)=1 (coprime).
-- r: rx= p*x+q*y
-- ry= y
--then
-- for points (x1,y1) and (x2,y2),
-- if rx1=rx2 then x1=x2, y1=y2.
--Because, x and y are integer.
--This means that
-- points in RKnot[] have difference x-coordinates each other.
--The following is the FLT version of the above.
--Let
-- delta=0.05;
-- theta0=0.0003 ( < 1/screenDepth )
-- + delta;
--r:
--rx = x +theta*y
--ry = y
x_is_lt(Knot:KNOT, i,j:CARD):BOOL is
-- sorting order
return Knot[i].x < Knot[j].x;
end;
checkRegular(inout Knot:KNOT, inout SortX:ARRAY{CARD}):BOOL is
--Check if Knot[] is in a standard/regular position.
--Especially, it check condition around crossing points.
--And it make a table of critical points SortX[].
kp, kp1, sp, i:CARD;
fp:BOOL;
kp:=1; -- start of compo
kp1:=Knot.cmpOf(kp.int-1).card-2; -- back 1 vertex
loop
fp:=(Knot[kp].x<Knot[kp1].x)=(Knot[kp].x<Knot[kp+1].x);
if VERTEXC::crossing.in(Knot[kp].sep) then -- tr or tl
SortX:=SortX.resize(SortX.size+1);
SortX[SortX.size-1]:=kp;
if fp then return false;
--check crossing condition be regular
end;
else
-- Now, normal.in(Knot[].sep)
--SortX[] contains critical pts. only.
--So it is tn or tu.
if fp then
-- tn or tu
SortX:=SortX.resize(SortX.size+1);
SortX[SortX.size-1]:=kp;
end;
end;
-- move to next vertex
if VERTEXC::separator.in(Knot[kp+2].sep) then
kp:=kp+4; -- head of next component
if kp>=Knot.length then break!; end;
kp1:=Knot.cmpOf(kp.int-1).card-2;
else kp1:=kp; kp:=kp+1;
end;
end;
lt:ROUT{CARD,CARD}:BOOL:=bind(x_is_lt(Knot,_,_));
SortX.insertion_sort_by(lt);
-- check if coord of each vertex be unique up to crossings.
--I assumed that the diagram be regular projection.
--Not needed the following checker of regularity on vertices.
-- Because, Knot[], knot in new coordinate is in regular position.
--loop sp:=0.upto!(SortX.size-2);
-- if (Knot[SortX[sp]].x=Knot[SortX[sp+1]].x) and
-- (Knot[SortX[sp]].y/=Knot[SortX[sp+1]].y)
-- then return false;
-- end;
--end;
return true;
end;
rotToNormal(inout Knot:KNOT, inout SortX:ARRAY{CARD}):BOOL is
-- p be prime>(knot Height) and not overflow on p*(knot x coord)
maxX,minX,maxY,minY:INT;
Knot.width(out minX,out maxX,out minY,out maxY);
p:INT:=(maxY-minY)+1;
if p.is_even then p:=p+1; end;
loop until!(p.is_prime); p:=p+2; end;
-- (p,q)=1 coprime
q:INT:=1;
loop until!(p.gcd(q)=1.int); q:=q+1; end;
-- prepare for "SortRecords" and compare
-- delta is a divisor of q, and $(p,q)=1$.
Knot.transform(p,q,0.int,1.int);
if ~checkRegular(inout Knot,inout SortX) then
#OUT+"Cannot move to good position. (rotateToNormal)\n";
return false; -- cannot find a good position
end;
-- find a good position.
-- Now, Knot[] is in normal position.
-- And we can think a Morse function according Knot[] and SortX[].
return true;
end;
countLowerEdge(Knot:KNOT, kp:CARD):CARD is
v0::=Knot[kp]; count::=0; k1::=1;
loop
v1::=Knot[k1]-v0; v2::=Knot[k1+1]-v0;
if ((v1.x.is_pos)/=(v2.x.is_pos))and(v1.x.is_non_zero)and(v2.x.is_non_zero) then
-- check the edge: y-coord
if ( v1.y.is_pos and v2.y.is_pos) then ;
elsif ( v1.y.is_neg and v2.y.is_neg) then count:=count+1;
elsif (v1.outer(v2).is_pos )=(v1.x<v2.x) then count:=count+1;
-- if condition of slope
--y1/x1 > y2/x2 when (x1<x2)
--y1/x1 < y2/x2 when (x1>x2)
--then line p1-p2 through under the point p0.
end;
end;
-- move to next vertex
if VERTEXC::separator.in(Knot[k1+2].sep) then
k1:=k1+4; -- head of next component
if k1>=Knot.length then break!; end;
else k1:=k1+1;
end;
end;
return count;
end;
makeNData(Knot:KNOT, SortX:ARRAY{CARD}, inout NData:NDATA):BOOL is
wl, kp, kp1, kp2:CARD;
tmp:CARD;
-- Now, SortX[] is the sorted table of critical points
-- and RKnot[] is unique in height function '.x' .
-- So, we can use these as if a Morse function.
NData:=#; wl:=0;
loop sp::=SortX.ind!;
kp:=SortX[sp];
if VERTEXC::crossing.in(Knot[kp].sep) and
(Knot.cmpOf(kp.int)=SortX[sp+1].int) then
-- crossing tr/tl
kp1:=kp+1;
if Knot[kp].x<Knot[kp1].x then kp1:=kp1-2; end;
kp2:=SortX[sp+1]+1;
if Knot[kp].x<Knot[kp2].x then kp2:=kp2-2; end;
if ~VERTEXC::over.in(Knot[kp].sep) then
tmp:=kp1; kp1:=kp2; kp2:=tmp;
end;
if Knot[kp].outer(Knot[kp1],Knot[kp2]).is_pos then
NData.append(NCODE::tr,countLowerEdge(Knot,kp)+1);
else
NData.append(NCODE::tl,countLowerEdge(Knot,kp)+1);
end;
elsif VERTEXC::normal.in(Knot[kp].sep) then
-- SortX[] contains critical pts. only.
kp2:=kp+1;
if Knot[kp].x<Knot[kp2].x then -- tn
NData.append(NCODE::tn,countLowerEdge(Knot,kp)+1);
else -- Knot[kp].x>Knot[kp2].x --tu
NData.append(NCODE::tu,countLowerEdge(Knot,kp)+1);
end;
end;
end;
if NData[NData.size-1].typ/=NCODE::tz then
NData.append(NCODE::tz,0);
end;
return NData.setIndex;
end;
errMsg(n:CARD) is
#OUT+"Knot2NData: failed to convert knot to ndata.("+n.str+")\n";
end;
Knot2NData(knot:KNOT, inout NData:NDATA):BOOL is
NData:=#;
if ~knot.is_proper then return false; end;
if knot.has_band then
#OUT+"Band is not supported.\n"; return false;
end;
if knot.CrossSet then ; end;
KnotW:KNOT:=knot.clone;
SortX:ARRAY{CARD}:=#;
-- SortX is a list of critical points of a Morse function.
-- It is a table of index of vertex and crossing pts.
if ~rotToNormal(inout KnotW, inout SortX) then errMsg(1);
elsif ~makeNData(KnotW,SortX,inout NData) then errMsg(2);
end;
return true;
end;
end; -- class KNOT2NDATA
class NDATA_CNV
class NDATA_CNV is
shared packNData:BOOL;-- TRUE: reduce the diagram. Not implemented.
Knot2NDataStr(Knot:KNOT, out strNData:STR):BOOL is
if Knot.is_proper.not then strNData:=" endcode "; return false; end;
NData:NDATA:=#;
strNData:=" endcode ";
k::=Knot.clone; k.transform(0.int,-1,1.int,0.int);
reply:BOOL:=KNOT2NDATA::Knot2NData(k,inout NData);
if ~ reply then strNData:=" endcode "; return false; end;
reply:=NDATA2STR::NData2Str(NData,out strNData) and reply;
-- Note that 'reply' is afterward
return reply;
end;
NDataStr2Knot(strNData:STR, inout Knot:KNOT):BOOL is
--#OUT+"NDataStr2Knot:1 \n";
NData:NDATA:=#;
HISTORY::put(Knot.clone);
reply:BOOL:=STR2NDATA::Str2NData(strNData,out NData);
if NData.size>0 then
reply:=reply and NDATA2KNOT::NData2Knot(NData,inout Knot);
Knot.transform(0.int,1.int,-1,0.int);
else Knot:=#;
end;
if ~reply then HISTORY::back(inout Knot); end;
return reply;
end;
SetNDiagram(inout Knot:KNOT) is
str:STR;
if Knot2NDataStr(Knot,out str) and NDataStr2Knot(str,inout Knot) then; end;
end;
end; -- class NDATA_CNV