-- File: IPCBImpl.mesa
-- Last Edited by: CSChow, February 2, 1985 2:29:38 am PST
--Note: IPCB = ChannelBoundary
DIRECTORY
IPCB;
IPCBImpl: CEDAR PROGRAM
IMPORTS IPCB
EXPORTS IPCB = BEGIN OPEN IPCB;
SideEmpty: PUBLIC ERROR= CODE;
NotFound: PUBLIC ERROR= CODE;
Create: PUBLIC PROC[owner: Channel] RETURNS[r: Ref] ={
RETURN [NEW[Rep ← [owner]]]}; --Create --
Destroy: PUBLIC PROC[r: Ref] ={
p: PROC [iNd: IntersectionNode] ={iNd.dual ← NIL}; --p--
AllIntersectionNodes[r, p] --Maybe should do this differently--
}; --Destroy--
CheckSelf: PUBLIC PROC[r: Ref] ={
BEGIN
pI: PROC [iNd: IPCB.IntersectionNode] ={
IF iNd = NIL OR iNd.dual = NIL THEN ERROR;
IF iNd.owner # r.owner THEN ERROR;
IF iNd.dual.dual # iNd THEN ERROR;
IF iNd.dual.intersection.ch # r.owner THEN ERROR}; --pI--
AllIntersectionNodes[r, pI];
END;
BEGIN
prevComp: Component ← NIL;
pI: EachINodeAction ={
IF prevComp = NIL THEN prevComp ← iNd.posComp ELSE {
IF prevComp = iNd.negComp THEN prevComp ← iNd.posComp ELSE ERROR};
SELECT iNd.intersection.type FROM
Cross => IF iNd.dual.intersection.type # Cross THEN ERROR;
TPos, TNeg => IF iNd.dual.intersection.type # TEnd THEN ERROR;
ENDCASE => ERROR;
}; --pI--
IntersectionNodes[r, pI, neg];
prevComp ← NIL;
IntersectionNodes[r, pI, pos];
END;
BEGIN
IF r.negEnd.negComp # NIL OR r.negEnd.posComp # NIL THEN ERROR;
IF r.posEnd.negComp # NIL OR r.posEnd.posComp # NIL THEN ERROR;
IF r.negComp # NIL AND NOT NoIntersection[r, neg] THEN ERROR;
IF r.posComp # NIL AND NOT NoIntersection[r, pos] THEN ERROR;
SELECT r.negEnd.intersection.type FROM
TEnd => IF r.negEnd.dual.intersection.type # TPos THEN ERROR;
LNeg, LPos => IF r.negEnd.dual.intersection.type # LPos THEN ERROR;
ENDCASE => ERROR;
SELECT r.posEnd.intersection.type FROM
TEnd => IF r.posEnd.dual.intersection.type # TNeg THEN ERROR;
LNeg, LPos => IF r.posEnd.dual.intersection.type # LNeg THEN ERROR;
ENDCASE => ERROR;
END;
BEGIN
IF (r.negSideTl # NIL AND r.negSideTl.rest # NIL) OR
(r.posSideTl # NIL AND r.posSideTl.rest # NIL) THEN ERROR;
IF r.negSideHd = NIL OR r.negSideHd.rest = NIL THEN{
IF r.negSideHd # r.negSideTl THEN ERROR};
IF r.posSideHd = NIL OR r.posSideHd.rest = NIL THEN{
IF r.posSideHd # r.posSideTl THEN ERROR};
END;
}; --CheckSelf--
End: PUBLIC PROC[r: Ref, which: Side] RETURNS[Intersection] ={
RETURN[ SELECT which FROM
neg => r.negEnd.intersection,
pos => r.posEnd.intersection,
ENDCASE => ERROR]}; -- End--
NthIntersection: PUBLIC PROC[r: Ref, which: Side, n: INT] RETURNS[Intersection] ={
iNd: IntersectionNode ← NthINode[r, which, n];
IF iNd = NIL THEN RETURN[NIL] ELSE RETURN [iNd.intersection]}; --NthIntersection --
NthComponent: PUBLIC PROC [r: Ref, which: Side, n: INT] RETURNS[Component] ={
iNd: IntersectionNode;
IF NoIntersection[r, which] THEN {
SELECT n FROM
-1, 1 => RETURN [SideGetComp[r, which]];
ENDCASE => RETURN [NIL]};
iNd ← NthINode[r, which, n];
IF iNd = NIL THEN RETURN [NIL] ELSE RETURN [(IF n < 0 THEN iNd.posComp ELSE iNd.negComp)]
}; --NthComponent--
NoIntersection: PUBLIC PROC[r: Ref, which: Side] RETURNS[BOOL] ={
RETURN[ SELECT which FROM
neg => r.negSideHd = NIL,
pos => r.posSideHd = NIL,
ENDCASE => ERROR]}; -- NoIntersection--
NoComponent: PUBLIC PROC[r: Ref, which: Side] RETURNS[BOOL] ={
RETURN[ SELECT which FROM
neg => r.negSideHd = NIL AND r.negComp = NIL,
pos => r.posSideHd = NIL AND r.posComp = NIL,
ENDCASE => ERROR]}; -- NoComponent--
ComponentOn: PUBLIC PROC[r: Ref, comp: Component, which: Side] RETURNS[quit: BOOL ← FALSE]={
p: EachComponentAction ={IF co = comp THEN {quit ← TRUE}};
RETURN [NOT Components[r, which, p]]
};--ComponentOn--
GetChNbr: PUBLIC PROC[r: Ref, ch: Channel, whichNbr, hint: Side] RETURNS [Channel] ={
IF End[r, neg].ch = ch THEN {
IF whichNbr = neg THEN ERROR NotFound;
RETURN [IF NoIntersection[r, hint] THEN End[r, pos].ch ELSE SideGet[r, hint].Hd.first.intersection.ch]};
IF End[r, pos].ch = ch THEN {
IF whichNbr = pos THEN ERROR NotFound;
RETURN [IF NoIntersection[r, hint] THEN End[r, neg].ch ELSE SideGet[r, hint].Tl.first.intersection.ch]};
BEGIN
lPt, lHd, lTl: LIST OF IntersectionNode ← NIL;
[lHd, lTl] ← SideGet[r, hint];
IF whichNbr = neg THEN {
IF lHd.first.intersection.ch = ch THEN RETURN [End[r, neg].ch];
FOR l: LIST OF IntersectionNode ← lHd, l.rest UNTIL l = NIL DO
IF l.rest.first.intersection.ch = ch THEN {lPt ← l; EXIT}
ENDLOOP;
IF lPt = NIL THEN ERROR NotFound; --ch may not intersects r--
RETURN [lPt.first.intersection.ch]} ELSE {
IF lTl.first.intersection.ch = ch THEN RETURN [End[r,pos].ch];
FOR l: LIST OF IntersectionNode ← lHd, l.rest UNTIL l = NIL DO
IF l.first.intersection.ch = ch THEN {lPt ← l; EXIT}
ENDLOOP;
IF lPt = NIL THEN ERROR NotFound;
RETURN [lPt.rest.first.intersection.ch]};
END;
}; --GetChNbr--
SetBoundary: PUBLIC PROC[r: Ref, negEnd, posEnd: Intersection, negSide, posSide: LIST OF Intersection] ={
SetUpDuals[SetEnd[r, ItoINode[negEnd, r.owner], neg], pos];
SetUpDuals[SetEnd[r, ItoINode[posEnd, r.owner], pos], neg];
FOR l: LIST OF Intersection ← negSide, l.rest UNTIL l = NIL DO
IF l.first.type IN NIntersectionType
THEN SetUpDuals[SideAddh[r, ItoINode[l.first, r.owner], neg], neg]
ELSE ERROR
ENDLOOP;
FOR l: LIST OF Intersection ← posSide, l.rest UNTIL l = NIL DO
IF l.first.type IN PIntersectionType
THEN SetUpDuals[SideAddh[r, ItoINode[l.first, r.owner], pos], pos]
ELSE ERROR
ENDLOOP;
}; --SetBoundary --
InsertCoBetween: PUBLIC PROC[r: Ref, co: Component, negBnd, posBnd: Channel, which: Side] ={
IF NoIntersection[r, which]
THEN SideSetComp[r, co, which]
ELSE {
IF End[r, neg].ch # negBnd THEN GetINode[r, negBnd, which].posComp ← co;
IF End[r, pos].ch # posBnd THEN GetINode[r, posBnd, which].negComp ← co}
}; --InsertCoBetween --
InsertCoAt: PUBLIC PROC[r: Ref, co: Component, whichSide, whichEnd: Side] ={
IF NoIntersection[r, whichSide] THEN SideSetComp[r, co, whichSide]
ELSE {
SELECT whichEnd FROM
neg => {NthINode[r, whichSide, 1].negComp ← co};
pos => {NthINode[r, whichSide, -1].posComp ← co};
ENDCASE => ERROR}
}; --InsertCoAt--
Components: PUBLIC PROC[r: Ref, which: Side, p: EachComponentAction] RETURNS[BOOL] ={
IF NoIntersection[r, which] THEN RETURN [NOT p[SideGetComp[r, which]]]
ELSE {
lHd, lTl: LIST OF IntersectionNode;
[lHd, lTl] ← SideGet[r, which];
FOR l: LIST OF IntersectionNode ← lHd, l.rest UNTIL l = NIL DO {
IF p[l.first.negComp] THEN RETURN[FALSE]}
ENDLOOP;
RETURN[NOT p[lTl.first.posComp]]}
}; -- Components--
AllInteriorIntersections: PUBLIC PROC [r: Ref] RETURNS[LIST OF IntersectionNode] ={
RETURN[NIL];
};
ChannelSegments: PUBLIC PROC[r: Ref, p: EachChSegAction] RETURNS[quit: BOOL ← FALSE] ={
negIntNd: IntersectionNode ← r.negEnd;
posIntNd: IntersectionNode;
next do the interior intersections
FOR iList: LIST OF IntersectionNode ← IPCB.AllInteriorIntersections[r], iList.rest WHILE iList # NIL AND ~quit DO
posIntNd ← iList.first;
quit ← p[r, negIntNd, posIntNd];
negIntNd ← posIntNd;
ENDLOOP;
finally, the right of the channel
posIntNd ← r.posEnd;
IF ~quit THEN quit ← p[r, negIntNd, posIntNd];
};
Intersections: PUBLIC PROC[r: Ref, which: Side, p: EachIntersectionAction] RETURNS[quit: BOOL ← FALSE] ={
FOR l: LIST OF IntersectionNode ← SideGet[r, which].Hd, l.rest UNTIL l = NIL OR quit DO
quit ← p[l.first.intersection]
ENDLOOP;
}; --Intersections --
--######Used mainly by EditOpsImpl######--
GetINode: PUBLIC PROC[r: Ref, ch: Channel, hint: Side] RETURNS [IntersectionNode]= {
IF r.negEnd # NIL AND r.negEnd.intersection.ch = ch THEN RETURN [r.negEnd];
IF r.posEnd # NIL AND r.posEnd.intersection.ch = ch THEN RETURN [r.posEnd];
FOR l: LIST OF IntersectionNode ← SideGet[r, hint].Hd, l.rest UNTIL l = NIL DO
IF l.first.intersection.ch = ch THEN RETURN[l.first]
ENDLOOP;
RETURN [NIL]
}; --GetINode--
IntersectsCh: PUBLIC PROC[r: Ref, ch: Channel] RETURNS [BOOL] ={
RETURN [NOT (GetINode[r, ch, neg] = NIL AND GetINode[r, ch, pos] = NIL)]
}; --IntersectsCh--
ArmOn: PUBLIC PROC[r: Ref, ch: Channel, which: Side] RETURNS [BOOL] ={RETURN [XingCount[r, ch, which] >= 0]}; --ArmOn--
SideAddl: PUBLIC PROC [r: Ref, iNd: IntersectionNode, which: Side] RETURNS [IntersectionNode]= {
UpdateDual[r, iNd];
SELECT which FROM
neg => {r.negComp ← NIL; IF r.negSideHd = NIL THEN r.negSideHd ← r.negSideTl ← LIST[iNd] ELSE r.negSideHd ←CONS[iNd, r.negSideHd]};
pos => {r.posComp ← NIL; IF r.posSideHd = NIL THEN r.posSideHd ← r.posSideTl← LIST[iNd] ELSE r.posSideHd ← CONS[iNd, r.posSideHd]};
ENDCASE => ERROR;
RETURN [iNd]}; --SideAddl--
SideAddh: PUBLIC PROC [r: Ref, iNd: IntersectionNode, which: Side] RETURNS [IntersectionNode] = {
UpdateDual[r, iNd];
SELECT which FROM
neg => {r.negComp ← NIL; IF r.negSideHd = NIL THEN r.negSideHd ← r.negSideTl ← LIST[iNd] ELSE {r.negSideTl.rest ← LIST[iNd]; r.negSideTl ← r.negSideTl.rest}};
pos => {r.posComp ← NIL; IF r.posSideHd = NIL THEN r.posSideHd ← r.posSideTl← LIST[iNd] ELSE {r.posSideTl.rest ← LIST[iNd]; r.posSideTl ← r.posSideTl.rest}};
ENDCASE => ERROR;
RETURN [iNd]}; --SideAddh--
SideInsert: PUBLIC PROC[r: Ref, iNd: IntersectionNode, negBnd, posBnd: Channel, which: Side] RETURNS [IntersectionNode] = {
lNd: LIST OF IntersectionNode;
UpdateDual[r, iNd];
SideSetComp[r, NIL, which];
IF End[r, neg].ch = negBnd THEN {nd: IntersectionNode← NthINode[r, which, 1];
IF nd = NIL THEN {nd ← r.posEnd} ELSE {nd.negComp ← iNd.posComp};
IF nd.intersection.ch # posBnd THEN ERROR;
[] ← SideAddl[r, iNd, which];
RETURN [iNd]};
IF End[r, pos].ch = posBnd THEN {nd: IntersectionNode ← NthINode[r, which, -1];
IF nd = NIL OR nd.intersection.ch # negBnd THEN ERROR;
nd.posComp ← iNd.negComp;
[] ← SideAddh[r, iNd, which];
RETURN [iNd]};
FOR l: LIST OF IntersectionNode ← SideGet[r, which].Hd, l.rest DO
IF l.first.intersection.ch = negBnd THEN {lNd ← l; EXIT}
ENDLOOP;
IF lNd.rest.first.intersection.ch # posBnd THEN ERROR;
lNd.first.posComp ← iNd.negComp;
lNd.rest.first.negComp ← iNd.posComp;
lNd.rest ← CONS[iNd, lNd.rest];
RETURN [iNd]
}; --SideInsert--
SetEnd: PUBLIC PROC [r: Ref, iNd: IntersectionNode, whichEnd: Side] RETURNS [IntersectionNode]={
UpdateDual[r, iNd];
iNd.negComp ← iNd.posComp ← NIL;
SELECT whichEnd FROM
neg => {r.negEnd ← iNd};
pos => {r.posEnd ← iNd};
ENDCASE => ERROR;
RETURN [iNd]
}; --SetEnd--
SideRemovel: PUBLIC PROC [r: Ref, which: Side] RETURNS [iNd: IntersectionNode] = {
IF NoIntersection[r, which] THEN ERROR SideEmpty;
SELECT which FROM
neg => {iNd ← r.negSideHd.first;
IF (r.negSideHd ← r.negSideHd.rest) = NIL THEN {r.negSideTl ← NIL; r.negComp ← iNd.posComp}};
pos => {iNd ← r.posSideHd.first;
IF (r.posSideHd ← r.posSideHd.rest) = NIL THEN {r.posSideTl ← NIL; r.posComp ← iNd.posComp}};
ENDCASE => ERROR;}; --SideRemovel--
SideRemoveh: PUBLIC PROC [r: Ref, which: Side] RETURNS [iNd: IntersectionNode] = {
lHd, lTl: LIST OF IntersectionNode;
[lHd, lTl] ← SideGet[r, which];
IF lHd = NIL THEN ERROR SideEmpty;
iNd ← lTl.first;
IF lHd = lTl THEN {
SELECT which FROM
neg => {r.negSideHd ← r.negSideTl ← NIL; r.negComp ← iNd.negComp};
pos => {r.posSideHd ← r.posSideTl ← NIL; r.posComp ← iNd.negComp};
ENDCASE => ERROR;} ELSE{
lPt: LIST OF IntersectionNode;
FOR l: LIST OF IntersectionNode ← lHd, l.rest DO
IF l.rest = lTl THEN {lPt ← l; EXIT;}
ENDLOOP;
SELECT which FROM
neg => r.negSideTl ← lPt;
pos => r.posSideTl ← lPt;
ENDCASE => ERROR;
lPt.rest ← NIL;}
}; --SideRemoveh--
SideRem: PUBLIC PROC[r: Ref, ch: Channel, which: Side, repCo: Component] RETURNS [iNd: IntersectionNode]= {
lHd, lTl: LIST OF IntersectionNode;
[lHd, lTl] ← SideGet[r, which];
IF lHd = NIL THEN ERROR SideEmpty;
IF lHd.first.intersection.ch = ch THEN {
iNd ← SideRemovel[r,which];
SELECT which FROM
neg => IF r.negSideHd = NIL THEN r.negComp ← repCo ELSE r.negSideHd.first.negComp ← repCo;
pos =>IF r.posSideHd = NIL THEN r.posComp ← repCo ELSE r.posSideHd.first.negComp ← repCo;
ENDCASE => ERROR;} ELSE {
lPt: LIST OF IntersectionNode ← NIL;
FOR l: LIST OF IntersectionNode ← lHd, l.rest UNTIL l.rest = NIL DO
IF l.rest.first.intersection.ch = ch THEN {lPt ← l; EXIT;}
ENDLOOP;
IF lPt = NIL THEN ERROR NotFound;
iNd ← lPt.rest.first;
lPt.first.posComp ← repCo;
lPt.rest ← lPt.rest.rest;
IF lPt.rest = NIL THEN SideSet[r, lHd, lPt, which] ELSE lPt.rest.first.negComp ← repCo;};
RETURN [iNd]
}; --SideRem --
SideRem2: PUBLIC PROC[r: Ref, iNd: IntersectionNode, repCo: Component] RETURNS [IntersectionNode] ={
iNdCh: Channel ← iNd.intersection.ch;
IF r.negEnd = iNd THEN ERROR NotFound;
IF r.posEnd = iNd THEN ERROR NotFound;
IF GetINode[r, iNdCh, neg] = iNd THEN RETURN [SideRem[r, iNdCh, neg, repCo]];
IF GetINode[r, iNdCh, pos] = iNd THEN RETURN [SideRem[r, iNdCh, pos, repCo]];
ERROR NotFound;
}; --SideRem2 --
Fragment: PUBLIC PROC [r: Ref, co1, co2: Component, negCh, posCh: Channel] ={
negF: Ref ← Create[negCh];
posF: Ref ← Create[posCh];
negCo, posCo: Component;
SELECT TRUE FROM
ComponentOn[r, co1, neg] AND ComponentOn[r, co2, pos]=> {negCo ← co1; posCo ← co2};
ComponentOn[r, co2, neg] AND ComponentOn[r, co1, pos]=> {negCo ← co2; posCo ← co1};
ENDCASE => ERROR;
[] ← SetEnd[negF, r.negEnd, neg];
[] ← SetEnd[posF, r.posEnd, pos];
negF.negComp ← posF.negComp ← negCo;
negF.posComp ← posF.posComp ← posCo;
IF r.negComp = negCo AND negCo # NIL THEN NULL ELSE {
addN: BOOLTRUE;
p: EachINodeAction ={
IF iNd.negComp = negCo THEN addN ← FALSE;
IF addN THEN [] ← SideAddh[negF, iNd, neg] ELSE [] ← SideAddh[posF, iNd, neg]}; --p--
IntersectionNodes[r, p, neg]};
IF r.posComp = posCo AND posCo # NIL THEN NULL ELSE {
addN: BOOLTRUE;
p: EachINodeAction ={
IF iNd.negComp = posCo THEN addN ← FALSE;
IF addN THEN [] ← SideAddh[negF, iNd, pos] ELSE [] ← SideAddh[posF, iNd, pos]}; --p--
IntersectionNodes[r, p, pos]};
negCh.boundary ← negF;
posCh.boundary ← posF;
}; --Fragment--
Merge: PUBLIC PROC [negR, posR: Ref, owner: Channel]={
mergedR: Ref ← Create[owner];
pNSide: EachINodeAction ={[] ← SideAddh[mergedR, iNd, neg]}; --pNSide--
pPSide: EachINodeAction ={[] ← SideAddh[mergedR, iNd, pos]}; --pPSide--
IF NthComponent[negR, neg, -1] # NthComponent[posR, neg, 1] OR NthComponent[negR, pos, -1] # NthComponent[posR, pos, 1] THEN ERROR;
mergedR.negComp ← NthComponent[negR, neg, 1];
mergedR.posComp ← NthComponent[posR, pos, 1];
[] ← SetEnd[mergedR, negR.negEnd, neg];
[] ← SetEnd[mergedR, posR.posEnd, pos];
IntersectionNodes[negR, pNSide, neg]; IntersectionNodes[posR, pNSide, neg];
IntersectionNodes[negR, pPSide, pos]; IntersectionNodes[posR, pPSide, pos];
owner.boundary ← mergedR;
};--Merge--
XingCount: PUBLIC PROC [r: Ref, ch: Channel, which: Side] RETURNS [INT]={
found: BOOLFALSE;
notFoundCount: INT = -1;
xingCount: INT ← 0;
p1: PROC[iNd: IntersectionNode] ={
IF iNd.intersection.ch = ch THEN {
SELECT which FROM
neg => IF iNd.intersection.type # IPCB.LPos THEN found ← TRUE;
pos => IF iNd.intersection.type # IPCB.LNeg THEN found ← TRUE;
ENDCASE => ERROR;}}; --p1--
p2: EachINodeAction ={
IF iNd.intersection.ch = ch THEN {found ← TRUE; RETURN [TRUE]};
IF iNd.intersection.type = Cross THEN xingCount ← xingCount.SUCC;}; --p2--
p1[r.negEnd];
IF NOT found THEN IntersectionNodes[r, p2, which];
IF NOT found THEN p1[r.posEnd];
IF found THEN RETURN [xingCount] ELSE RETURN [notFoundCount]
};--XingCount--
InCount: PUBLIC PROC[r: Ref, ch: Channel, which: Side] RETURNS [INT] = {
found: BOOLFALSE;
notFoundCount: INT = -1;
inCount: INT ← 0;
p1: PROC[iNd: IntersectionNode] ={
SELECT which FROM
neg => IF iNd.intersection.type # IPCB.LPos THEN {
inCount ← inCount.SUCC;
IF iNd.intersection.ch = ch THEN found ← TRUE};
pos => IF iNd.intersection.type # IPCB.LNeg THEN {
inCount ← inCount.SUCC;
IF iNd.intersection.ch = ch THEN found ← TRUE};
ENDCASE => ERROR;}; --p1--
p2: EachINodeAction ={
inCount ← inCount.SUCC;
IF iNd.intersection.ch = ch THEN {found ← quit ← TRUE}}; --p2--
p1[r.negEnd];
IF NOT found THEN IntersectionNodes[r, p2, which];
IF NOT found THEN p1[r.posEnd];
IF found THEN RETURN [inCount] ELSE RETURN [notFoundCount]
}; --InCount--
NthINode: PUBLIC PROC [r: Ref, which: Side, n: INT] RETURNS[IntersectionNode]= {
lHd, lTl: LIST OF IntersectionNode;
[lHd, lTl] ← SideGet[r, which];
IF lHd = NIL THEN RETURN [NIL];
SELECT n FROM
-1 => RETURN [lTl.first];
1 => RETURN [lHd.first]
ENDCASE => RETURN [Nth[lHd, n]];
}; --NthINode--
IntersectionNodes: PUBLIC PROC[r: Ref, p: EachINodeAction, which: Side] = {
FOR l: LIST OF IntersectionNode ← SideGet[r, which].Hd, l.rest UNTIL l = NIL DO
IF p[l.first] THEN EXIT
ENDLOOP;}; --IntersectionNodes--
AllIntersectionNodes: PUBLIC PROC [r: Ref, p: PROC [iNd: IntersectionNode]] = {
p[r.negEnd];
FOR l: LIST OF IntersectionNode ← r.negSideHd, l.rest UNTIL l = NIL DO
p[l.first]
ENDLOOP;
FOR l: LIST OF IntersectionNode ← r.posSideHd, l.rest UNTIL l = NIL DO
p[l.first]
ENDLOOP;
p[r.posEnd];
}; --AllIntersectionNodes--
SetUpDuals: PUBLIC PROC [iNd: IntersectionNode, hint: Side] = {
dINode: IntersectionNode ← GetINode[iNd.intersection.ch.boundary, iNd.owner, hint];
IF dINode = NIL
THEN NULL
ELSE {iNd.dual ← dINode; dINode.dual ← iNd};
}; --SetUpDuals--
UpdateDual: PROC[r: Ref, iNd: IntersectionNode] = --INLINE-- {
IF r.owner = iNd.owner THEN NULL ELSE {
iNd.owner ← r.owner;
iNd.dual.intersection.ch ← r.owner}}; --UpdateDual--
SideGet: PUBLIC PROC [r: Ref, which: Side] RETURNS [Hd, Tl: LIST OF IntersectionNode]= {
SELECT which FROM
neg => {Hd ← r.negSideHd; Tl ← r.negSideTl};
pos => {Hd ← r.posSideHd; Tl ← r.posSideTl};
ENDCASE => ERROR;
}; --SideGet--
SideSet: PROC [r: Ref, lHd, lTl: LIST OF IntersectionNode, which: Side]= {
SELECT which FROM
neg => {r.negSideHd ← lHd; r.negSideTl ← lTl};
pos => {r.posSideHd ← lHd; r.posSideTl ← lTl};
ENDCASE => ERROR;
}; --SideGet--
SideSetComp: PUBLIC PROC [r: Ref, comp: Component, which: Side] = {
SELECT which FROM
neg => r.negComp ← comp;
pos => r.posComp ← comp;
ENDCASE => ERROR}; --SideSetComp--
SideGetComp:PUBLIC PROC [r: Ref, which: Side] RETURNS [Component]= {
SELECT which FROM
neg => RETURN [r.negComp];
pos => RETURN [r.posComp];
ENDCASE => ERROR}; --SideGetComp--
ItoINode: PUBLIC PROC [i: Intersection, o: Channel] RETURNS [IntersectionNode] = {
RETURN [NEW[IntersectionNodeRep ← [owner: o, intersection: i]]]};--ItoINode--
SideOpenHole1: PUBLIC PROC[mainR, sideR: Ref, negBnd, posBnd: Channel, sideToOp: Side]={
IF End[mainR, neg].ch = negBnd THEN {
l: LIST OF IntersectionNode ← SideGet[mainR, sideToOp].Hd;
WHILE l # NIL AND l.first.intersection.ch # posBnd DO
[] ← SideAddh[sideR, SideRemovel[mainR, sideToOp], sideToOp];
l ← SideGet[mainR, sideToOp].Hd;
ENDLOOP;
IF NoIntersection[sideR, sideToOp] THEN SideSetComp[sideR, NthComponent[mainR, sideToOp, 1], sideToOp]} ELSE {
lHd, lTl: LIST OF IntersectionNode ← NIL;
FOR l: LIST OF IntersectionNode ← SideGet[mainR, sideToOp].Hd, l.rest UNTIL l = NIL DO
IF l.first.intersection.ch = negBnd THEN lHd ← l;
IF l.first.intersection.ch = posBnd THEN {lTl ← l; EXIT};
ENDLOOP;
IF lTl = NIL THEN SideSet[mainR, SideGet[mainR, sideToOp].Hd, lHd, sideToOp];
FOR l: LIST OF IntersectionNode ← lHd.rest, l.rest UNTIL l = lTl DO
[] ← SideAddh[sideR, l.first, sideToOp];
ENDLOOP;
lHd.rest ← lTl;
IF NoIntersection[sideR, sideToOp] THEN SideSetComp[sideR, lHd.first.posComp, sideToOp]}
}; --SideOpenHole1--
SideOpenHole2: PUBLIC PROC[mainR, sideR: Ref, negBnd, posBnd: Channel, sideToOp: Side]={
lNd, lTl: LIST OF IntersectionNode;
[] ← SetEnd[sideR, mainR.posEnd, pos];
lNd ← SideGet[mainR, sideToOp].Hd;
IF End[mainR, neg].ch = negBnd
THEN SideSet[mainR, NIL, NIL, sideToOp]
ELSE{
FOR l: LIST OF IntersectionNode ← lNd, l.rest DO
IF l.first.intersection.ch = negBnd THEN {lTl ← l; EXIT}
ENDLOOP;
SideSet[mainR, lNd, lTl, sideToOp];
lNd ← lTl.rest; lTl.rest ← NIL;}; --EndIf--
WHILE lNd # NIL DO
[] ← SideAddh[sideR, lNd.first, sideToOp]; lNd ← lNd.rest;
ENDLOOP;
IF NoIntersection[sideR, sideToOp] THEN SideSetComp[sideR, NthComponent[mainR, sideToOp, -1], sideToOp];
sideToOp ← IF sideToOp = neg THEN pos ELSE neg;
lNd ← SideGet[mainR, sideToOp].Hd;
IF End[mainR, pos].ch = posBnd THEN RETURN; --This includes lNd = NIL--
IF lNd.first.intersection.ch = posBnd
THEN {
SideSet[mainR, NIL, NIL, sideToOp];
SideSetComp[mainR, lNd.first.negComp, sideToOp];}
ELSE {
FOR l: LIST OF IntersectionNode ← lNd, l.rest DO
IF l.rest.first.intersection.ch = posBnd THEN {lTl ← l; EXIT}
ENDLOOP;
SideSet[mainR, lNd, lTl, sideToOp];
lNd ← lTl.rest; lTl.rest ← NIL;}; --EndIf--
WHILE lNd # NIL DO
[] ← SideAddh[sideR, lNd.first, sideToOp]; lNd ← lNd.rest;
ENDLOOP;}; --SideOpenHole2--
SideCloseHole1: PUBLIC PROC [mainR, sideR: Ref, negBnd, posBnd: Channel, sideToCl: Side] ={
lNd, lTl: LIST OF IntersectionNode ← NIL;
IF End[mainR, pos].ch = posBnd THEN NULL ELSE {lNd ← SideGet[mainR, sideToCl].Hd;
IF lNd.first.intersection.ch = posBnd
THEN SideSet[mainR, NIL, NIL, sideToCl]
ELSE {
FOR l: LIST OF IntersectionNode ← lNd, l.rest DO
IF l.rest.first.intersection.ch = posBnd THEN {lTl ← l; EXIT}
ENDLOOP;
SideSet[mainR, lNd, lTl, sideToCl];
lNd ← lTl.rest; lTl.rest ← NIL;}; --endIF--
}; --endIF--
FOR l: LIST OF IntersectionNode ← SideGet[sideR, sideToCl].Hd, l.rest UNTIL l = NIL DO
[] ← SideAddh[mainR, l.first, sideToCl];
ENDLOOP;
FOR l: LIST OF IntersectionNode ← lNd, l.rest UNTIL l = NIL DO
[] ← SideAddh[mainR, l.first, sideToCl];
ENDLOOP;
IF NoIntersection[mainR, sideToCl]
THEN SideSetComp[mainR, SideGetComp[sideR, sideToCl], sideToCl];
}; --SideCloseHole1--
SideCloseHole2: PUBLIC PROC [mainR, sideR: Ref, negBnd, posBnd: Channel, sideToCl: Side] ={
FOR l: LIST OF IntersectionNode ← SideGet[sideR, sideToCl].Hd, l.rest UNTIL l = NIL DO
[] ← SideAddh[mainR, l.first, sideToCl];
ENDLOOP;
IF NoIntersection[mainR, sideToCl]
THEN SideSetComp[mainR, SideGetComp[sideR, sideToCl], sideToCl];
sideToCl ← IF sideToCl = neg THEN pos ELSE neg; --Flip it--
FOR l: LIST OF IntersectionNode ← SideGet[sideR, sideToCl].Hd, l.rest UNTIL l = NIL DO
[] ← SideAddh[mainR, l.first, sideToCl];
ENDLOOP;
[] ← SetEnd[mainR, sideR.posEnd, pos];
}; --SideCloseHole2--
Nth: PROC[list: LIST OF IntersectionNode, n: INT] RETURNS[IntersectionNode] ={
tail: LIST OF IntersectionNode;
IF list = NIL OR n = 0 THEN RETURN[NIL];
IF n > 0 THEN
{tail ← NthTail[list, n-1]} ELSE {tail ← NthTail[list, n]};
IF tail = NIL THEN RETURN[NIL];
RETURN[tail.first]}; --Nth --
NthTail: PROC [list: LIST OF IntersectionNode, n: INT] RETURNS[LIST OF IntersectionNode] = {
IF n=0 THEN RETURN[list];
IF list = NIL THEN RETURN[NIL];
IF n > 0 THEN THROUGH [0..n) DO
list ← list.rest;
IF list = NIL THEN RETURN[NIL];
REPEAT
FINISHED => RETURN[list];
ENDLOOP
ELSE
{lead: LIST OF IntersectionNode ← NthTail[list, -n];
UNTIL lead = NIL DO
lead ← lead.rest;
list ← list.rest;
ENDLOOP;
RETURN[list];
};
}; -- of NthTail
END.