<<-- 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>> <<>> <<>>