-- File: IPEditOpsImpl.mesa
-- Last Edited by: CSChow, February 1, 1985 11:23:00 am PST
DIRECTORY
IPCoTab,
IPCB,
IPCTG,
IPBasicOps,
IPEditOps;
IPEditOpsImpl: CEDAR PROGRAM
IMPORTS IPCB, IPBasicOps, IPCTG, IPCoTab
EXPORTS IPEditOps = BEGIN OPEN BO: IPBasicOps, CTG: IPCTG, CB: IPCB, CoTab: IPCoTab, IPEditOps;
NoIntersection: PUBLIC PROC[ch: CTG.Channel] RETURNS [BOOL] ={
RETURN [CB.NoIntersection[ch.boundary, neg] AND CB.NoIntersection[ch.boundary, pos]]}; --NoIntersection--
CrossIn: PUBLIC PROC[refCh, ch: CTG.Channel] RETURNS [BOOL] ={
iNd: CB.IntersectionNode ← CB.GetINode[refCh.boundary, ch, neg];
IF iNd = NIL
THEN RETURN [FALSE]
ELSE RETURN [iNd.intersection.type = CB.Cross AND CB.INodeDual[iNd].intersection.type = CB.Cross]
}; --CrossIn--
XCount: PUBLIC PROC[refCh, ch: CTG.Channel] RETURNS [INT] ={
rCB: CB.Ref ← refCh.boundary;
RETURN [MAX[CB.XingCount[rCB, ch, neg], CB.XingCount[rCB, ch, pos]]]};
CoInsertNode: PUBLIC PROC[co: CoTab.Component, iNd: CB.IntersectionNode, ontoCh: CTG.Channel] ={
negBnd, posBnd: CTG.Channel;
side: CB.Side;
[negBnd, posBnd, side] ← CoGetBndChsAndSide[co, ontoCh];
[] ← CB.SideInsert[ontoCh.boundary, iNd, negBnd, posBnd, side];
};--CoInsertNode--
CoGetBndChsAndSide: PUBLIC PROC[co: CoTab.Component, refCh: CTG.Channel] RETURNS [negBnd, posBnd: CTG.Channel, side: CB.Side]={
OPEN cPC: co.prinChannels, cCC: co.cornerChannels;
SELECT refCh FROM
cPC.south => {side ← pos;
negBnd ← IF cCC.sw = NIL THEN cPC.west ELSE cCC.sw.ver;
posBnd ← IF cCC.se = NIL THEN cPC.east ELSE cCC.se.ver};
cPC.east => {side ← neg;
negBnd ← IF cCC.se = NIL THEN cPC.south ELSE cCC.se.hor;
posBnd ← IF cCC.ne = NIL THEN cPC.north ELSE cCC.ne.hor};
cPC.north => {side ← neg;
negBnd ← IF cCC.nw = NIL THEN cPC.west ELSE cCC.nw.ver;
posBnd ← IF cCC.ne = NIL THEN cPC.east ELSE cCC.ne.ver};
cPC.west => {side ← pos;
negBnd ← IF cCC.sw = NIL THEN cPC.south ELSE cCC.sw.hor;
posBnd ← IF cCC.nw = NIL THEN cPC.north ELSE cCC.nw.hor};
ENDCASE => ERROR;}; --CoGetBndChsAndSide--
CoGetBndChsAndSide2: PUBLIC PROC[co: CoTab.Component, ch: CTG.Channel] RETURNS [negBnd, posBnd: CTG.Channel, side: CB.Side]={
OPEN cPC: co.prinChannels, cCC: co.cornerChannels;
cornerType: CoTab.CornerTypes ← CoTab.FindCornerType[co, ch];
side ← BO.CTInvDirectnFor[cornerType, BO.OTFlip[ch.type]];
SELECT cornerType FROM
sw => IF ch.type = hor THEN {negBnd ← cPC.west; posBnd ← cCC.sw.ver} ELSE {negBnd ← cPC.south; posBnd ← cCC.sw.hor};
se => IF ch.type = hor THEN {negBnd ← cCC.se.ver; posBnd ← cPC.east} ELSE {negBnd ← cPC.south; posBnd ← cCC.se.hor};
ne => IF ch.type = hor THEN {negBnd ← cCC.ne.ver; posBnd ← cPC.east} ELSE {negBnd ← cCC.ne.hor; posBnd ← cPC.north};
nw => IF ch.type = hor THEN {negBnd ← cPC.west; posBnd ← cCC.nw.ver} ELSE {negBnd ← cCC.nw.hor; posBnd ← cPC.north};
ENDCASE => ERROR}; --CoGetBndChsAndSide2--
MakeLCorner: PUBLIC PROC[ch1, ch2: CTG.Channel, cornerType: CoTab.CornerTypes] ={
horCh, verCh: CTG.Channel;
SELECT ch1.type FROM
hor => {horCh ← ch1; verCh ← ch2};
ver => {verCh ← ch1; horCh ← ch2};
ENDCASE => ERROR;
SELECT cornerType FROM
sw => {[] ← CB.SetEnd[horCh.boundary, CB.ItoINode[CTG.NewIn[verCh, CB.LNeg], horCh], pos];
CB.SetUpDuals[CB.SetEnd[verCh.boundary, CB.ItoINode[CTG.NewIn[horCh, CB.LNeg], verCh], pos], neg]};
se => {[] ← CB.SetEnd[horCh.boundary, CB.ItoINode[CTG.NewIn[verCh, CB.LNeg], horCh], neg];
CB.SetUpDuals[CB.SetEnd[verCh.boundary, CB.ItoINode[CTG.NewIn[horCh, CB.LPos], verCh], pos], neg]};
ne => {[] ← CB.SetEnd[horCh.boundary, CB.ItoINode[CTG.NewIn[verCh, CB.LPos], horCh], neg];
CB.SetUpDuals[CB.SetEnd[verCh.boundary, CB.ItoINode[CTG.NewIn[horCh, CB.LPos], verCh], neg], neg]};
nw => {[] ← CB.SetEnd[horCh.boundary, CB.ItoINode[CTG.NewIn[verCh, CB.LPos], horCh], pos];
CB.SetUpDuals[CB.SetEnd[verCh.boundary, CB.ItoINode[CTG.NewIn[horCh, CB.LNeg], verCh], neg], neg]};
ENDCASE => ERROR;
}; --MakeLCorner--
NewNodesPair: PUBLIC PROC[ch1, ch2: CTG.Channel, iType1, iType2: CB.IntersectionType] RETURNS [nd1, nd2: CB.IntersectionNode] = --INLINE--{
nd1 ← CB.ItoINode[CTG.NewIn[ch2, iType1], ch1];
nd2 ← CB.ItoINode[CTG.NewIn[ch1, iType2], ch2];
CB.SetINodeDual[nd2, nd1];
CB.SetINodeDual[nd1, nd2];
};--NewNodesPair--
OpenHole1: PUBLIC PROC[mainCh, sideCh, negBnd, posBnd: CTG.Channel, sideToOp: CB.Side] ={
sCB: CB.Ref ← sideCh.boundary;
nEndNd, pEndNd: CB.IntersectionNode;
nNbrCh, pNbrCh: CTG.Channel;
CB.SideOpenHole1[mainCh.boundary, sCB, negBnd, posBnd, sideToOp];
nEndNd ← NewNodesPair[sideCh, negBnd, CB.TEnd, CB.TPos].nd2;
pEndNd ← NewNodesPair[sideCh, posBnd, CB.TEnd, CB.TNeg].nd2;
nNbrCh ← CTG.GetChNbr[negBnd, mainCh, sideToOp, pos];
pNbrCh ← CTG.GetChNbr[posBnd, mainCh, sideToOp, neg];
[] ← CB.SetEnd[sCB, CB.INodeDual[nEndNd], neg];
[] ← CB.SetEnd[sCB, CB.INodeDual[pEndNd], pos];
CB.SetINodeComp[nEndNd, CB.NthComponent[sCB, sideToOp, 1], sideToOp];
CB.SetINodeComp[pEndNd, CB.NthComponent[sCB, sideToOp, -1], sideToOp];
IF sideToOp = neg
THEN {[] ← CB.SideInsert[negBnd.boundary, nEndNd, nNbrCh, mainCh, pos];
[] ← CB.SideInsert[posBnd.boundary, pEndNd, pNbrCh, mainCh, neg];}
ELSE {[] ← CB.SideInsert[negBnd.boundary, nEndNd, mainCh, nNbrCh, pos];
[] ← CB.SideInsert[posBnd.boundary, pEndNd, mainCh, pNbrCh, neg];};
}; --OpenHole1--
OpenHole2: PUBLIC PROC[mainCh, sideCh, negBnd, posBnd: CTG.Channel, sideToOp: CB.Side] ={
mCB: CB.Ref ← mainCh.boundary;
sCB: CB.Ref ← sideCh.boundary;
nEndNd, pEndNd: CB.IntersectionNode;
nNbrCh, pNbrCh: CTG.Channel;
CB.SideOpenHole2[mCB, sCB, negBnd, posBnd, sideToOp];
nEndNd ← NewNodesPair[sideCh, negBnd, CB.TEnd, CB.TPos].nd2;
pEndNd ← NewNodesPair[mainCh, posBnd, CB.TEnd, CB.TNeg].nd2;
nNbrCh ← CTG.GetChNbr[negBnd, mainCh, sideToOp, pos];
pNbrCh ← CTG.GetChNbr[posBnd, sideCh, BO.PTNot[sideToOp], neg];
[] ← CB.SetEnd[sCB, CB.INodeDual[nEndNd], neg];
[] ← CB.SetEnd[mCB, CB.INodeDual[pEndNd], pos];
CB.SetINodeComp[nEndNd, CB.NthComponent[sCB, sideToOp, 1], sideToOp];
CB.SetINodeComp[pEndNd, CB.NthComponent[mCB, BO.PTNot[sideToOp], -1], BO.PTNot[sideToOp]];
IF sideToOp = neg
THEN {[] ← CB.SideInsert[negBnd.boundary, nEndNd, nNbrCh, mainCh, pos];
[] ← CB.SideInsert[posBnd.boundary, pEndNd, sideCh, pNbrCh, neg];}
ELSE {[] ← CB.SideInsert[negBnd.boundary, nEndNd, mainCh, nNbrCh, pos];
[] ← CB.SideInsert[posBnd.boundary, pEndNd, pNbrCh, sideCh, neg];};
}; --OpenHole2--
CloseHole1: PUBLIC PROC[mainCh, sideCh, negBnd, posBnd: CTG.Channel, sideToCl: CB.Side] ={
sCB: CB.Ref ← sideCh.boundary;
mCB: CB.Ref ← mainCh.boundary;
nEndCo: CoTab.Component ← CB.NthComponent[sCB, sideToCl, 1];
pEndCo: CoTab.Component ← CB.NthComponent[sCB, sideToCl, -1];
CB.DestroyINode[CB.SideRem[negBnd.boundary, sideCh, pos, nEndCo]];
CB.DestroyINode[CB.SideRem[posBnd.boundary, sideCh, neg, pEndCo]];
IF NOT CB.EndCh[mCB, negBnd]
THEN CB.SetINodeComp[CB.GetINode[mCB, negBnd, sideToCl], nEndCo, pos];
IF NOT CB.EndCh[mCB, posBnd]
THEN CB.SetINodeComp[CB.GetINode[mCB, posBnd, sideToCl], pEndCo, neg];
CB.SideCloseHole1[mCB, sCB, negBnd, posBnd, sideToCl];
}; --CloseHole1--
CloseHole2: PUBLIC PROC[mainCh, sideCh, negBnd, posBnd: CTG.Channel, sideToCl: CB.Side] ={
sCB: CB.Ref ← sideCh.boundary;
mCB: CB.Ref ← mainCh.boundary;
nEndCo: CoTab.Component ← CB.NthComponent[sCB, sideToCl, 1];
pEndCo: CoTab.Component ← CB.NthComponent[mCB, BO.PTNot[sideToCl], -1];
CB.DestroyINode[CB.SideRem[negBnd.boundary, sideCh, pos, nEndCo]];
CB.DestroyINode[CB.SideRem[posBnd.boundary, mainCh, neg, pEndCo]];
IF NOT CB.EndCh[mCB, negBnd]
THEN CB.SetINodeComp[CB.GetINode[mCB, negBnd, sideToCl], nEndCo, pos];
IF NOT CB.EndCh[sCB, posBnd]
THEN CB.SetINodeComp[CB.GetINode[sCB, posBnd, BO.PTNot[sideToCl]], pEndCo, neg];
CB.SideCloseHole2[mCB, sCB, negBnd, posBnd, sideToCl];
}; --CloseHole2--
CBSwapChsInComps: PUBLIC PROC [cb: CB.Ref, oldCh, newCh: CTG.Channel, skew: [-1..1] ← 0] ={
SELECT skew FROM
0 => {pCo: CB.EachComponentAction ={CoSwapChs[co, oldCh, newCh]}; --pCo--
[] ← CB.Components[cb, neg, pCo];
[] ← CB.Components[cb, pos, pCo];};
-1 => {pINd: CB.EachINodeAction ={CoSwapChs[iNd.negComp, oldCh, newCh]}; --pINd--
CB.IntersectionNodes[cb, pINd, neg];
CB.IntersectionNodes[cb, pINd, pos];};
1 => {pINd: CB.EachINodeAction ={CoSwapChs[iNd.posComp, oldCh, newCh]}; --pINd--
CB.IntersectionNodes[cb, pINd, neg];
CB.IntersectionNodes[cb, pINd, pos];};
ENDCASE => ERROR;
};--CBSwapChsInComps--
CoSwapChs: PUBLIC PROC [co: CoTab.Component, oldCh, newCh: CTG.Channel] = {
IF co = NIL
THEN NULL
ELSE {
OPEN pChs: co.prinChannels, cChs: co.cornerChannels;
IF pChs.south = oldCh THEN {pChs.south ← newCh; RETURN};
IF pChs.east = oldCh THEN {pChs.east ← newCh; RETURN};
IF pChs.north = oldCh THEN {pChs.north ← newCh; RETURN};
IF pChs.west = oldCh THEN {pChs.west ← newCh; RETURN};
IF cChs.sw = NIL THEN NULL
ELSE {
IF cChs.sw.hor = oldCh THEN {cChs.sw.hor ← newCh; RETURN};
IF cChs.sw.ver = oldCh THEN {cChs.sw.ver ← newCh; RETURN}};
IF cChs.se = NIL THEN NULL
ELSE {
IF cChs.se.hor = oldCh THEN {cChs.se.hor ← newCh; RETURN};
IF cChs.se.ver = oldCh THEN {cChs.se.ver ← newCh; RETURN}};
IF cChs.ne = NIL THEN NULL
ELSE {
IF cChs.ne.hor = oldCh THEN {cChs.ne.hor ← newCh; RETURN};
IF cChs.ne.ver = oldCh THEN {cChs.ne.ver ← newCh; RETURN}};
IF cChs.nw = NIL THEN NULL
ELSE {
IF cChs.nw.hor = oldCh THEN {cChs.nw.hor ← newCh; RETURN};
IF cChs.nw.ver = oldCh THEN {cChs.nw.ver ← newCh; RETURN}};
}
}; --CoSwapChs--
ChSetCBComps: PUBLIC PROC[ch: CTG.Channel, negComp, posComp: CoTab.Component] = {
CB.SideSetComp[ch.boundary, negComp, neg];
CB.SideSetComp[ch.boundary, posComp, pos];}; --ChSetCBComps--
CoClearCornerChs: PUBLIC PROC[co: CoTab.Component, ch1, ch2: CTG.Channel] = {
cChs: CoTab.CornerChannels;
horCh, verCh: CTG.Channel;
ct: CoTab.CornerTypes ← sw;
IF co = NIL THEN RETURN; --%%%Temporary: For a weird case%%%--
SELECT ch1.type FROM
hor => {horCh ← ch1; verCh ← ch2};
ver => {verCh ← ch1; horCh ← ch2};
ENDCASE => ERROR;
THROUGH [0..4) DO
IF (cChs ← CoTab.GetCornerChs[co, ct]) # NIL AND cChs.hor = horCh AND cChs.ver = verCh
THEN {CoTab.SetCornerChs[co, ct, NIL]; RETURN};
ct ← BO.CTRotate[ct];
ENDLOOP;
ERROR;
};--CoClearCornerChs--
CoSetCornerChs: PUBLIC PROC[co: CoTab.Component, ch1, ch2: CTG.Channel] ={
OPEN cCC: co.cornerChannels;
horCh, verCh: CTG.Channel;
IF co = NIL THEN RETURN; --%%%Temporary: For a weird case%%%--
SELECT ch1.type FROM
hor => {horCh ← ch1; verCh ← ch2};
ver => {verCh ← ch1; horCh ← ch2};
ENDCASE => ERROR;
IF co = CB.NthComponent[horCh.boundary, pos, -1] AND co = CB.NthComponent[verCh.boundary, pos, -1] THEN {
CoTab.SetCornerChs2[co, sw, horCh, verCh]; RETURN};
IF co = CB.NthComponent[horCh.boundary, pos, 1] AND co = CB.NthComponent[verCh.boundary, neg, -1] THEN {
CoTab.SetCornerChs2[co, se, horCh, verCh]; RETURN};
IF co = CB.NthComponent[horCh.boundary, neg, 1] AND co = CB.NthComponent[verCh.boundary, neg, 1] THEN {
CoTab.SetCornerChs2[co, ne, horCh, verCh]; RETURN};
IF co = CB.NthComponent[horCh.boundary, neg, -1] AND co = CB.NthComponent[verCh.boundary, pos, 1] THEN {
CoTab.SetCornerChs2[co, nw, horCh, verCh]; RETURN};
ERROR
}; --CoSetCornerChs--
CoInsert: PUBLIC PROC [co: CoTab.Component, south, east, north, west: CTG.Channel] ={
co.prinChannels ← [south, east, north, west];
CoInsert2[co, south, east, north, west];
}; --CoInsert--
CoInsert2: PUBLIC PROC [co: CoTab.Component, south, east, north, west: CTG.Channel] ={
CB.InsertCoBetween[south.boundary, co, west, east, pos];
CB.InsertCoBetween[east.boundary, co, south, north, neg];
CB.InsertCoBetween[north.boundary, co, west, east, neg];
CB.InsertCoBetween[west.boundary, co, south, north, pos];
}; --CoInsert2--
AreTEndChs: PUBLIC PROC[ch, end1, end2: CTG.Channel] RETURNS [BOOL] ={
IF end1 = end2
THEN RETURN [FALSE]
ELSE RETURN [IsTEndCh[ch, end1] AND IsTEndCh[ch, end2]]
}; --AreTEndChs--
IsTEndCh: PUBLIC PROC[ch, end: CTG.Channel] RETURNS [BOOL] ={
IF CTG.End[ch, neg].ch = end THEN RETURN [CTG.End[ch, neg].type = CB.TEnd];
IF CTG.End[ch, pos].ch = end THEN RETURN [CTG.End[ch, pos].type = CB.TEnd];
RETURN [FALSE]
}; --IsTEndCh--
IsLCorner: PUBLIC PROC[ch1, ch2: CTG.Channel] RETURNS [BOOL] ={
IF CTG.End[ch1, neg].ch = ch2 THEN RETURN [CTG.End[ch1, neg].type # CB.TEnd];
IF CTG.End[ch1, pos].ch = ch2 THEN RETURN [CTG.End[ch1, pos].type # CB.TEnd];
RETURN [FALSE]}; --IsLCorner--
BndsOkChk: PUBLIC PROC[mainCh, negBnd, posBnd: CTG.Channel] RETURNS [BOOL] = {
IF negBnd = posBnd THEN RETURN [FALSE];
IF CTG.End[mainCh, pos].ch = negBnd OR CTG.End[mainCh, neg].ch = posBnd THEN RETURN [FALSE];
IF NOT (CTG.IntersectsCh[mainCh, negBnd] AND CTG.IntersectsCh[mainCh, posBnd]) THEN RETURN [FALSE];
RETURN [TRUE];
}; --ChBndsChk--
CoXingCount: PUBLIC PROC[co: CoTab.Component, prinRefCh: CTG.Channel] RETURNS [INT] ={
negBnd, posBnd: CTG.Channel;
side: CB.Side;
[negBnd, posBnd, side] ← CoGetBndChsAndSide [co, prinRefCh];
RETURN [CB.XingCount[prinRefCh.boundary, posBnd, side]]
};--CoXingCount--
END.
-- Edited on December 11, 1984 0:24:31 am PST, by CSChow
-- Addition of CoXingCount to fix bug in EditPrimitives.FormZChk
-- changes to: CoXingCount ->Created specifically for EditPrimitives.FormZChk,
-- IPEditOpsImpl, BndsOkChk