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[
BOOL]={
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[
BOOL] ={
negIntNd: IntersectionNode ← r.negEnd;
posIntNd: IntersectionNode;
next do the interior intersections
FOR iList:
LIST
OF IntersectionNode ←
IPCB.AllInteriorIntersections[r], iList.rest
WHILE iList #
NIL
DO
posIntNd ← iList.first;
IF p[r, negIntNd, posIntNd] THEN RETURN[FALSE];
negIntNd ← posIntNd;
ENDLOOP;
finally, the right of the channel
posIntNd ← r.posEnd;
IF p[r, negIntNd, posIntNd] THEN RETURN[FALSE];
RETURN[TRUE]
};
Intersections:
PUBLIC
PROC[r: Ref, which: Side, p: EachIntersectionAction]
RETURNS[
BOOL] ={
FOR l:
LIST
OF IntersectionNode ← SideGet[r, which].Hd, l.rest
UNTIL l =
NIL
DO {
IF p[l.first.intersection] THEN RETURN[FALSE]}
ENDLOOP;
RETURN[TRUE]
}; --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: BOOL ← TRUE;
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: BOOL ← TRUE;
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: BOOL ← FALSE;
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: BOOL ← FALSE;
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.