<<-- File: IPEditPrimitivesImpl.mesa>> <<-- Last Edited by: CSChow, February 1, 1985 11:23:52 am PST>> <<--Intro: Welcome to the 'underground world'. It has been quite thoroughly debugged. Try not to >> <<-- change anything here, if possible, as they are sensitive.>> <<>> DIRECTORY IPCoTab, IPCB, IPCTG, IPBasicOps, IPEditOps, IPEditPrimitives; IPEditPrimitivesImpl: CEDAR PROGRAM IMPORTS IPCB, IPBasicOps, IPCTG, IPCoTab, IPEditOps EXPORTS IPEditPrimitives = BEGIN OPEN BO: IPBasicOps, EO: IPEditOps, CB: IPCB, CTG: IPCTG, CoTab: IPCoTab, IPEditPrimitives; InvalidArgs: PUBLIC ERROR[editPrim: ATOM] = CODE; BreakCross: PUBLIC PROC [refCh, chToBreak, newCh1: CTG.Channel]={ negBrPt: CB.IntersectionNode _ CB.GetINode[chToBreak.boundary, refCh, neg]; posBrPt: CB.IntersectionNode _ CB.GetINode[chToBreak.boundary, refCh, pos]; IF BreakCrossChk[refCh, chToBreak] THEN NULL ELSE ERROR InvalidArgs[$BreakCross]; <> CB.INodeDual[negBrPt].intersection.type _ CB.TNeg; CB.INodeDual[posBrPt].intersection.type _ CB.TPos; CB.Fragment[chToBreak.boundary, negBrPt.negComp, posBrPt.negComp, chToBreak, newCh1]; [] _ CB.SetEnd[chToBreak.boundary, CB.SideRemovel[newCh1.boundary, neg], pos]; [] _ CB.SetEnd[newCh1.boundary, CB.SideRemovel[newCh1.boundary, pos], neg]; EO.CBSwapChsInComps[newCh1.boundary, chToBreak, newCh1] }; --BreakCross-- BreakCrossChk: PUBLIC PROC[refCh, chToBreak: CTG.Channel] RETURNS [BOOL] ={ rNd: CB.IntersectionNode _ CB.GetINode[refCh.boundary, chToBreak, neg]; cNd: CB.IntersectionNode _ CB.GetINode[chToBreak.boundary, refCh, neg]; IF rNd = NIL OR rNd.intersection.type # CB.Cross OR cNd = NIL OR cNd.intersection.type # CB.Cross THEN RETURN[FALSE] ELSE RETURN[TRUE]; }; --BreakCrossChk-- FormCross: PUBLIC PROC [refCh, negCh, posCh: CTG.Channel]={ nChEnd: CB.IntersectionNode _ CB.GetEnd[negCh.boundary, pos]; pChEnd: CB.IntersectionNode _ CB.GetEnd[posCh.boundary, neg]; IF FormCrossChk[refCh, negCh, posCh] THEN NULL ELSE ERROR InvalidArgs[$FormCross]; --FormCross Failure: Invalid inputs-- EO.CBSwapChsInComps[posCh.boundary, posCh, negCh]; CB.INodeDual[nChEnd].intersection.type _ CB.Cross; CB.INodeDual[pChEnd].intersection.type _ CB.Cross; CB.SetINodeComps[nChEnd, CB.NthComponent[negCh.boundary, neg, -1], CB.NthComponent[posCh.boundary, neg, 1]]; CB.SetINodeComps[pChEnd, CB.NthComponent[negCh.boundary, pos, -1], CB.NthComponent[posCh.boundary, pos, 1]]; [] _ CB.SideAddh[negCh.boundary, nChEnd, neg]; [] _ CB.SideAddh[negCh.boundary, pChEnd, pos]; CB.Merge[negCh.boundary, posCh.boundary, negCh]; }; --FormCross-- FormCrossChk: PUBLIC PROC[refCh, negCh, posCh: CTG.Channel] RETURNS [BOOL] ={ IF CB.EndCh[refCh.boundary, negCh] OR CB.EndCh[refCh.boundary, posCh] THEN RETURN [FALSE]; IF CB.XingCount[refCh.boundary, negCh, neg] # CB.XingCount[refCh.boundary, posCh, pos] OR CB.XingCount[refCh.boundary, negCh, neg] < 0 THEN RETURN[FALSE] ELSE RETURN [TRUE]; }; --FormCrossChk-- FormZ: PUBLIC PROC[refCh: CTG.Channel, negComp, posComp: CoTab.Component, zType: CB.Side, newCh1, newCh2: CTG.Channel] ={ spineCB: CB.Ref _ newCh2.boundary; IF FormZChk[refCh, negComp, posComp, zType] THEN NULL ELSE ERROR InvalidArgs[$FormZ]; CB.Fragment[refCh.boundary, negComp, posComp, refCh, newCh1]; EO.CBSwapChsInComps[newCh1.boundary, refCh, newCh1, 1]; SELECT zType FROM neg => { SELECT refCh.type FROM hor => {EO.MakeLCorner[newCh2, refCh, nw]; EO.MakeLCorner[newCh2, newCh1, se];}; ver => {EO.MakeLCorner[newCh2, refCh, sw]; EO.MakeLCorner[newCh2, newCh1, ne];}; ENDCASE => ERROR;}; pos => { SELECT refCh.type FROM hor => {EO.MakeLCorner[newCh2, refCh, sw]; EO.MakeLCorner[newCh2, newCh1, ne];}; ver => {EO.MakeLCorner[newCh2, refCh, se]; EO.MakeLCorner[newCh2, newCh1, nw];}; ENDCASE => ERROR;}; ENDCASE => ERROR; IF (zType = neg AND refCh.type = hor) OR (zType = pos AND refCh.type = ver) THEN { CB.SideSetComp[spineCB, posComp, neg]; CB.SideSetComp[spineCB, negComp, pos]; EO.CoSetCornerChs[negComp, newCh2, refCh]; EO.CoSetCornerChs[posComp, newCh2, newCh1]; EO.CoSwapChs[negComp, refCh, newCh1]; }; IF (zType = neg AND refCh.type = ver) OR (zType = pos AND refCh.type = hor) THEN { CB.SideSetComp[spineCB, negComp, neg]; CB.SideSetComp[spineCB, posComp, pos]; EO.CoSetCornerChs[negComp, newCh2, newCh1]; EO.CoSetCornerChs[posComp, newCh2, refCh]; EO.CoSwapChs[posComp, refCh, newCh1]; }; }; --FormZ-- FormZChk: PUBLIC PROC[refCh: CTG.Channel, negComp, posComp: CoTab.Component, zType: CB.Side] RETURNS [BOOL] ={ OPEN nPC: negComp.prinChannels, nCS: negComp.shape.cornerSpaces, nCC: negComp.cornerChannels, pPC: posComp.prinChannels, pCS: posComp.shape.cornerSpaces, pCC: posComp.cornerChannels; IF ~ CTG.ComponentOn[refCh, negComp, neg] AND ~ CTG.ComponentOn[refCh, posComp, pos] THEN RETURN[FALSE]; IF EO.CoXingCount[negComp, refCh] # EO.CoXingCount[posComp, refCh] THEN RETURN [FALSE]; SELECT refCh.type FROM hor => {SELECT zType FROM neg => {IF nCC.nw # NIL OR pCC.se # NIL OR nCS.nw = NIL OR pCS.se = NIL THEN RETURN[FALSE];}; pos => {IF nCC.ne # NIL OR pCC.sw # NIL OR nCS.ne = NIL OR pCS.sw = NIL THEN RETURN[FALSE];}; ENDCASE => ERROR;}; ver => {SELECT zType FROM neg => {IF nCC.ne # NIL OR pCC.sw # NIL OR nCS.ne = NIL OR pCS.sw = NIL THEN RETURN[FALSE];}; pos => {IF nCC.se # NIL OR pCC.nw # NIL OR nCS.se = NIL OR pCS.nw = NIL THEN RETURN[FALSE];}; ENDCASE => ERROR;}; ENDCASE => ERROR; RETURN [TRUE] }; --FormZChk-- RemoveZ: PUBLIC PROC[zSpine: CTG.Channel] RETURNS [negCh, posCh: CTG.Channel, negComp, posComp: CoTab.Component, zType: CB.Side] --negCh ~ refCh; posCh ~ newCh1-- ={ nNd: CB.IntersectionNode _ CB.GetEnd[zSpine.boundary, neg]; pNd: CB.IntersectionNode _ CB.GetEnd[zSpine.boundary, pos]; IF RemoveZChk[zSpine] THEN NULL ELSE ERROR InvalidArgs[$RemoveZ]; SELECT nNd.intersection.type FROM CB.LNeg => {negCh _ nNd.intersection.ch; posCh _ pNd.intersection.ch; negComp _ zSpine.boundary.posComp; posComp _ zSpine.boundary.negComp; zType _ IF zSpine.type = hor THEN pos ELSE neg}; CB.LPos => {negCh _ pNd.intersection.ch; posCh _ nNd.intersection.ch; negComp _ zSpine.boundary.negComp; posComp _ zSpine.boundary.posComp; zType _ IF zSpine.type = hor THEN neg ELSE pos}; ENDCASE => ERROR; EO.CoClearCornerChs[zSpine.boundary.negComp, zSpine, posCh]; EO.CoClearCornerChs[zSpine.boundary.posComp, zSpine, negCh]; EO.CBSwapChsInComps[posCh.boundary, posCh, negCh]; CB.DestroyINode[nNd]; CB.DestroyINode[pNd]; CB.Merge[negCh.boundary, posCh.boundary, negCh]; }; --RemoveZ-- RemoveZChk: PUBLIC PROC[zSpine: CTG.Channel] RETURNS [BOOL] ={ zCB: CB.Ref _ zSpine.boundary; IF zCB.negComp # NIL AND zCB.posComp # NIL AND (CB.GetEnd[zCB, neg].intersection.type * CB.GetEnd[zCB, pos].intersection.type = -1) THEN RETURN[TRUE] ELSE RETURN [FALSE]; }; --RemoveZChk-- TtoL: PUBLIC PROC [refCh: CTG.Channel, whichEnd, lType: CB.Side, endCo: CoTab.Component, newCh1: CTG.Channel]={ rCB: CB.Ref _ refCh.boundary; bndNd: CB.IntersectionNode _ CB.GetEnd[rCB, whichEnd]; bndCh: CTG.Channel _ bndNd.intersection.ch; newNd: CB.IntersectionNode; IF TtoLChk [refCh, whichEnd, lType, endCo] THEN NULL ELSE ERROR InvalidArgs[$TtoL]; CB.Fragment[bndCh.boundary, endCo, CB.INodeDual[bndNd].posComp, bndCh, newCh1]; SELECT lType FROM neg => { bndNd.intersection.type _ CB.LNeg; EO.CBSwapChsInComps[newCh1.boundary, bndCh, newCh1]; SELECT whichEnd FROM neg => {[] _ CB.SideRemoveh[bndCh.boundary, pos]; newNd _ CB.SideAddl[rCB, CB.ItoINode[CTG.NewIn[newCh1, CB.TPos], refCh], pos]; CB.SetINodeComps[newNd, endCo, CB.INodeDual[bndNd].posComp];}; pos => {[] _ CB.SideRemoveh[bndCh.boundary, neg]; newNd _ CB.SideAddh[rCB, CB.ItoINode[CTG.NewIn[newCh1, CB.TPos], refCh], pos]; CB.SetINodeComps[newNd, CB.INodeDual[bndNd].posComp, endCo];}; ENDCASE => ERROR; [] _ CB.SetEnd[bndCh.boundary, CB.INodeDual[bndNd], pos]; [] _ CB.SetEnd[newCh1.boundary, CB.ItoINode[CTG.NewIn[refCh, CB.TEnd], newCh1], neg]; EO.CoSetCornerChs[endCo, refCh, bndCh]; CB.SetUpDuals[newNd, pos];}; pos => { bndNd.intersection.type _ CB.LPos; EO.CBSwapChsInComps[newCh1.boundary, bndCh, newCh1, 1]; EO.CoSwapChs[CB.INodeDual[bndNd].posComp, bndCh, newCh1]; SELECT whichEnd FROM neg => {[] _ CB.SideRemoveh[bndCh.boundary, pos]; newNd _ CB.SideAddl[rCB, CB.ItoINode[CTG.NewIn[bndCh, CB.TNeg], refCh], neg]; CB.SetINodeComps[newNd, endCo, CB.INodeDual[bndNd].negComp];}; pos => {[] _ CB.SideRemoveh[bndCh.boundary, neg]; newNd _ CB.SideAddh[rCB, CB.ItoINode[CTG.NewIn[bndCh, CB.TNeg], refCh], neg]; CB.SetINodeComps[newNd, CB.INodeDual[bndNd].negComp, endCo];}; ENDCASE => ERROR; [] _ CB.SetEnd[newCh1.boundary, CB.INodeDual[bndNd], neg]; [] _ CB.SetEnd[bndCh.boundary, CB.ItoINode[CTG.NewIn[refCh, CB.TEnd], bndCh], pos]; EO.CoSetCornerChs[endCo, refCh, newCh1]; CB.SetUpDuals[newNd, neg];}; ENDCASE => ERROR; }; --TtoL -- TtoLChk: PUBLIC PROC [refCh: CTG.Channel, whichEnd, lType: CB.Side, endCo: CoTab.Component] RETURNS [BOOL]={ OPEN eCS: endCo.shape.cornerSpaces, eCC: endCo.cornerChannels; endI: CB.Intersection _ CTG.End[refCh, whichEnd]; IF endI.type # CB.TEnd THEN RETURN [FALSE]; IF NOT CB.ComponentOn[endI.ch.boundary, endCo, whichEnd] THEN RETURN [FALSE]; IF endCo = NIL THEN RETURN [TRUE]; --%%%Temporary: For a weird case%%%-- SELECT lType FROM neg => SELECT refCh.type FROM hor => IF whichEnd = neg THEN RETURN [eCC.se = NIL AND eCS.se # NIL] ELSE RETURN[eCC.sw = NIL AND eCS.sw # NIL]; ver => IF whichEnd = neg THEN RETURN [eCC.nw = NIL AND eCS.nw # NIL] ELSE RETURN[eCC.sw = NIL AND eCS.sw # NIL]; ENDCASE => ERROR; pos => SELECT refCh.type FROM hor => IF whichEnd = neg THEN RETURN [eCC.ne = NIL AND eCS.ne # NIL] ELSE RETURN[eCC.nw = NIL AND eCS.nw # NIL]; ver => IF whichEnd = neg THEN RETURN [eCC.ne = NIL AND eCS.ne # NIL] ELSE RETURN[eCC.se = NIL AND eCS.se # NIL]; ENDCASE => ERROR; ENDCASE => ERROR; }; --TtoLChk -- LtoT: PUBLIC PROC [refCh: CTG.Channel, whichEnd: CB.Side] RETURNS [posCh: CTG.Channel, lType: CB.Side, endCo: CoTab.Component]={ rCB: CB.Ref _ refCh.boundary; bndNd: CB.IntersectionNode _ CB.GetEnd[rCB, whichEnd]; negCh: CTG.Channel; IF LtoTChk[refCh, whichEnd] THEN NULL ELSE ERROR InvalidArgs[$LtoT]; SELECT bndNd.intersection.type FROM CB.LNeg => {lType _ neg; negCh _ bndNd.intersection.ch; SELECT whichEnd FROM neg => {posCh _ CB.NthIntersection[rCB, pos, 1].ch; endCo _ CB.NthComponent[rCB, pos, 1]; CB.DestroyINode[CB.SideRemovel[rCB, pos]];}; pos => {posCh _ CB.NthIntersection[rCB, pos, -1].ch; endCo _ CB.NthComponent[rCB, pos, -1]; CB.DestroyINode[CB.SideRemoveh[rCB, pos]];}; ENDCASE => ERROR; EO.CoClearCornerChs[endCo, refCh, negCh];}; CB.LPos => {lType _ pos; posCh _ bndNd.intersection.ch; SELECT whichEnd FROM neg => {negCh _ CB.NthIntersection[rCB, neg, 1].ch; endCo _ CB.NthComponent[rCB, neg, 1]; CB.DestroyINode[CB.SideRemovel[rCB, neg]];}; pos => {negCh _ CB.NthIntersection[rCB, neg, -1].ch; endCo _ CB.NthComponent[rCB, neg, -1]; CB.DestroyINode[CB.SideRemoveh[rCB, neg]];}; ENDCASE => ERROR; EO.CoClearCornerChs[endCo, refCh, posCh];}; ENDCASE => ERROR; bndNd.intersection.type _CB.TEnd; SELECT whichEnd FROM neg => {CB.SetINodeComps[CB.INodeDual[bndNd], CB.NthComponent[negCh.boundary, pos, -1], CB.NthComponent[posCh.boundary, pos, 1]]; [] _ CB.SideAddh[negCh.boundary, CB.INodeDual[bndNd], pos];}; pos => {CB.SetINodeComps[CB.INodeDual[bndNd], CB.NthComponent[negCh.boundary, neg, -1], CB.NthComponent[posCh.boundary, neg, 1]]; [] _ CB.SideAddh[negCh.boundary, CB.INodeDual[bndNd], neg];}; ENDCASE => ERROR; EO.CBSwapChsInComps[posCh.boundary, posCh, negCh]; CB.Merge[negCh.boundary, posCh.boundary, negCh]; }; -- LtoT-- LtoTChk: PUBLIC PROC[refCh: CTG.Channel, whichEnd: CB.Side] RETURNS [BOOL]={ otherCh: CTG.Channel; SELECT CTG.End[refCh, whichEnd].type FROM CTG.LNeg => otherCh _ CTG.NthIntersection[refCh, pos, - BO.PTToInt[whichEnd]].ch; CTG.LPos => otherCh _ CTG.NthIntersection[refCh, neg, - BO.PTToInt[whichEnd]].ch; CTG.TEnd => RETURN [FALSE]; ENDCASE => ERROR; IF otherCh = NIL OR EO.CrossIn[refCh, otherCh] THEN RETURN [FALSE] ELSE RETURN [TRUE]; }; --LtoTChk -- FlexKnee: PUBLIC PROC [leg, floor: CTG.Channel, whichEnd, whichDirection: CB.Side, newCh1: CTG.Channel]={ IF FlexKneeChk[leg, floor, whichEnd, whichDirection] THEN NULL ELSE ERROR InvalidArgs[$FlexKnee]; BEGIN lCB: CB.Ref _ leg.boundary; tEndNd: CB.IntersectionNode _ CB.GetEnd[lCB, whichEnd]; tEndDual: CB.IntersectionNode _ CB.INodeDual[tEndNd]; tEndCh: CTG.Channel _ tEndNd.intersection.ch; parent: CoTab.Component _ CB.NthComponent[lCB, BO.PTNot[whichDirection], -BO.PTToInt[whichEnd]]; cornerType: CoTab.CornerTypes _ IF leg.type = hor THEN BO.CTFromPTs[hor: BO.PTNot[whichEnd], ver: whichDirection] ELSE BO.CTFromPTs[hor: whichDirection, ver: BO.PTNot[whichEnd]]; sideToOpen: CB.Side _ BO.PTNot[whichEnd]; negBnd, posBnd: CTG.Channel; IF whichDirection= neg THEN {negBnd _ floor; posBnd _ leg} ELSE {negBnd _ leg; posBnd _ floor}; EO.OpenHole1[tEndCh, newCh1, negBnd, posBnd, sideToOpen]; EO.CBSwapChsInComps[newCh1.boundary, tEndCh, newCh1]; SELECT tEndCh.type FROM hor => IF sideToOpen = pos THEN EO.CoInsert2[parent, tEndCh, posBnd, newCh1, negBnd] ELSE EO.CoInsert2[parent, newCh1, posBnd, tEndCh, negBnd]; ver => IF sideToOpen = pos THEN EO.CoInsert2[parent, negBnd, newCh1, posBnd, tEndCh] ELSE EO.CoInsert2[parent, negBnd, tEndCh, posBnd, newCh1]; ENDCASE => ERROR; CB.DestroyINode[CB.SideRem2[tEndCh.boundary, tEndDual, parent]]; CB.DestroyINode[IF whichEnd = neg THEN CB.SideRemovel[lCB, whichDirection] ELSE CB.SideRemoveh[lCB, whichDirection]]; EO.MakeLCorner[leg, newCh1, cornerType]; EO.CoSwapChs[parent, leg, floor]; EO.CoSetCornerChs[parent, leg, newCh1]; END; };--FlexKnee -- FlexKneeChk: PUBLIC PROC [leg, floor: CTG.Channel, whichEnd, whichDirection: CB.Side] RETURNS [BOOL]={ parent: CoTab.Component _ CTG.NthComponent[leg, BO.PTNot[whichDirection], -BO.PTToInt[whichEnd]]; sideToOpen: CB.Side _ BO.PTNot[whichEnd]; corner: CoTab.CornerTypes _ IF leg.type = hor THEN BO.CTFromPTs[hor: BO.PTNot[whichEnd], ver: whichDirection] ELSE BO.CTFromPTs[hor: whichDirection, ver: BO.PTNot[whichEnd]]; tEndCh: CTG.Channel _ CTG.End[leg, whichEnd].ch; negBnd, posBnd: CTG.Channel; IF CoTab.GetCornerSp[parent, corner] = NIL OR CoTab.GetCornerChs[parent, corner] # NIL THEN RETURN [FALSE]; IF CTG.End[leg, whichEnd].type # CB.TEnd THEN RETURN [FALSE]; IF NOT CTG.ArmOn[tEndCh, floor, sideToOpen] THEN RETURN [FALSE]; IF whichDirection = neg THEN {negBnd _ floor; posBnd _ leg} ELSE {negBnd _ leg; posBnd _ floor}; IF CTG.InCount[tEndCh, negBnd, sideToOpen] < CTG.InCount[tEndCh, posBnd, sideToOpen] THEN NULL ELSE RETURN [FALSE]; IF EO.CrossIn[tEndCh, negBnd] THEN RETURN [EO.XCount[tEndCh, posBnd] = EO.XCount[tEndCh, negBnd] + 1] ELSE RETURN [EO.XCount[tEndCh, posBnd] = EO.XCount[tEndCh, negBnd]]; };--FlexKneeChk -- ExtendKnee: PUBLIC PROC [shin: CTG.Channel] RETURNS [leg, floor: CTG.Channel, whichEnd, whichDirection: CB.Side]={ IF ExtendKneeChk[shin] THEN NULL ELSE ERROR InvalidArgs[$ExtendKnee]; BEGIN sCB: CB.Ref _ shin.boundary; tEnd: CB.Side _ IF CTG.End[shin, neg].type = CB.TEnd THEN neg ELSE pos; lEndNd: CB.IntersectionNode _ CB.GetEnd[sCB, BO.PTNot[tEnd]]; lEndDual: CB.IntersectionNode _ CB.INodeDual[lEndNd]; lType: CB.IntersectionType _ lEndNd.intersection.type; parent: CoTab.Component _ CB.SideGetComp[sCB, BO.PTFromInt[- lType]]; cornerType: CoTab.CornerTypes _ CoTab.FindCornerType[parent, shin]; edgeType: CoTab.EdgeTypes _ BO.CTResolveFor[cornerType, BO.OTFlip[shin.type]]; rotDirectn: INT _ BO.PTToInt[BO.CTFindRotDirectn[cornerType, shin.type]]; chToAttach, negBnd, posBnd: CTG.Channel; sideToAttach: CB.Side; newLegNd, newLegDual: CB.IntersectionNode; leg _ lEndNd.intersection.ch; floor _ CB.GetEnd[sCB, tEnd].intersection.ch; whichDirection _ BO.PTFromInt[CB.INodeDual[lEndNd].intersection.type]; whichEnd _ BO.CTInvDirectnFor[cornerType, leg.type]; edgeType _ CoTab.FindEdgeType[parent, floor]; CoTab.SetCornerChs[parent, cornerType, NIL]; lEndNd.intersection.type _ CB.TEnd; lEndDual.intersection.type _ BO.PTToInt[whichDirection]; CB.SetINodeComp[lEndDual, CTG.NthComponent[leg, whichDirection, lType], BO.PTNot[whichEnd]]; IF whichEnd = neg THEN [] _ CB.SideAddl[leg.boundary, lEndDual, whichDirection] ELSE [] _ CB.SideAddh[leg.boundary, lEndDual, whichDirection]; IF (chToAttach _ CoTab.GetCornerChFor[parent, BO.CTRotate[cornerType, rotDirectn], shin.type]) = NIL THEN {chToAttach _ CoTab.GetPrinCh[parent, BO.ETRotate[edgeType, rotDirectn]]; [negBnd, posBnd, sideToAttach] _ EO.CoGetBndChsAndSide[parent, chToAttach]} ELSE {[negBnd, posBnd, sideToAttach] _ EO.CoGetBndChsAndSide2[parent, chToAttach]}; [newLegNd, newLegDual] _ EO.NewNodesPair[leg, chToAttach, CB.TEnd, - BO.PTToInt[whichEnd]]; [] _ CB.SetEnd[leg.boundary, newLegNd, whichEnd]; CB.SetINodeComp[newLegDual, parent, BO.PTNot[whichDirection]]; [] _ CB.SideInsert[chToAttach.boundary, newLegDual, negBnd, posBnd, sideToAttach]; EO.CBSwapChsInComps[sCB, shin, chToAttach]; IF whichDirection = neg --negBnd and posBnd have different meaning now-- THEN {negBnd _ floor; posBnd _ leg} ELSE {negBnd _ leg; posBnd _ floor}; EO.CloseHole1[chToAttach, shin, negBnd, posBnd, sideToAttach]; EO.CoSwapChs[parent, floor, leg]; END; };--ExtendKnee -- ExtendKneeChk: PUBLIC PROC [shin: CTG.Channel] RETURNS [BOOL]={ lType: CB.IntersectionType; IF (lType _ CTG.End[shin, neg].type) # CB.TEnd AND CTG.End[shin, pos].type = CB.TEnd THEN RETURN [CTG.NoIntersection[shin, BO.PTFromInt[- lType]]]; IF CTG.End[shin, neg].type = CB.TEnd AND (lType _ CTG.End[shin, pos].type) # CB.TEnd THEN RETURN [CTG.NoIntersection[shin, BO.PTFromInt[- lType]]]; RETURN [FALSE] };--ExtendKneeChk -- InsertCoAtCorner: PUBLIC PROC[host, co: CoTab.Component, corner: CoTab.CornerTypes, newHCh1, newVCh1: CTG.Channel] ={ eNode, eDual1, eDual2: CB.IntersectionNode; south, east, north, west, ch1, ch2: CTG.Channel; [south, east, north, west] _ host.prinChannels; IF InsertCoAtCornerChk[host, co, corner] THEN NULL ELSE ERROR InvalidArgs[$InsertCoAtCorner]; EO.MakeLCorner[newHCh1, newVCh1, corner]; SELECT corner FROM sw => {ch1 _ south; ch2 _ west; [eNode, eDual1] _ EO.NewNodesPair[newVCh1, south, CB.TEnd, CB.TPos]; [] _CB.SetEnd[newVCh1.boundary, eNode, neg]; EO.ChSetCBComps[newVCh1, co, host]; CB.SetINodeComps[eDual1, co, host]; [eNode, eDual2] _ EO.NewNodesPair[newHCh1, west, CB.TEnd, CB.TPos]; [] _ CB.SetEnd[newHCh1.boundary, eNode, neg]; EO.ChSetCBComps[newHCh1, co, host]; CB.SetINodeComps[eDual2, co, host];}; se => {ch1 _ south; ch2 _ east; [eNode, eDual1] _ EO.NewNodesPair[newVCh1, south, CB.TEnd, CB.TPos]; [] _CB.SetEnd[newVCh1.boundary, eNode, neg]; EO.ChSetCBComps[newVCh1, host, co]; CB.SetINodeComps[eDual1, host, co]; [eNode, eDual2] _ EO.NewNodesPair[newHCh1, east, CB.TEnd, CB.TNeg]; [] _ CB.SetEnd[newHCh1.boundary, eNode, pos]; EO.ChSetCBComps[newHCh1, co, host]; CB.SetINodeComps[eDual2, co, host];}; ne => {ch1 _ north; ch2 _ east; [eNode, eDual1] _ EO.NewNodesPair[newVCh1, north, CB.TEnd, CB.TNeg]; [] _CB.SetEnd[newVCh1.boundary, eNode, pos]; EO.ChSetCBComps[newVCh1, host, co]; CB.SetINodeComps[eDual1, host, co]; [eNode, eDual2] _ EO.NewNodesPair[newHCh1, east, CB.TEnd, CB.TNeg]; [] _ CB.SetEnd[newHCh1.boundary, eNode, pos]; EO.ChSetCBComps[newHCh1, host, co]; CB.SetINodeComps[eDual2, host, co];}; nw => {ch1 _ north; ch2 _ west; [eNode, eDual1] _ EO.NewNodesPair[newVCh1, north, CB.TEnd, CB.TNeg]; [] _CB.SetEnd[newVCh1.boundary, eNode, pos]; EO.ChSetCBComps[newVCh1, co, host]; CB.SetINodeComps[eDual1, co, host]; [eNode, eDual2] _ EO.NewNodesPair[newHCh1, west, CB.TEnd, CB.TPos]; [] _ CB.SetEnd[newHCh1.boundary, eNode, neg]; EO.ChSetCBComps[newHCh1, host, co]; CB.SetINodeComps[eDual2, host, co];}; ENDCASE => ERROR; EO.CoInsertNode[host, eDual1, ch1]; EO.CoInsertNode[host, eDual2, ch2]; SELECT corner FROM sw => EO.CoInsert[co, south, newVCh1, newHCh1, west]; se => EO.CoInsert[co, south, east, newHCh1, newVCh1]; ne => EO.CoInsert[co, newHCh1, east, north, newVCh1]; nw => EO.CoInsert[co, newHCh1, newVCh1, north, west]; ENDCASE => ERROR; EO.CoSetCornerChs[host, newHCh1, newVCh1]; --can be sped up-- }; --CoCornerInsertComp-- InsertCoAtCornerChk: PUBLIC PROC[host, co: CoTab.Component, corner: CoTab.CornerTypes] RETURNS [BOOL] ={ OPEN pCS: host.shape.cornerSpaces, pCC: host.cornerChannels; SELECT corner FROM sw => RETURN [pCS.sw # NIL AND pCC.sw = NIL]; se => RETURN [pCS.se # NIL AND pCC.se = NIL]; ne => RETURN [pCS.ne # NIL AND pCC.ne = NIL]; nw => RETURN [pCS.nw # NIL AND pCC.nw = NIL]; ENDCASE => ERROR; }; --InsertCoAtCornerChk-- RemoveCoAtCorner: PUBLIC PROC[host: CoTab.Component, corner: CoTab.CornerTypes] RETURNS [co: CoTab.Component, horCh, verCh: CTG.Channel]={ hEdge, vEdge: CoTab.EdgeTypes; hSide, vSide: CB.Side; IF RemoveCoAtCornerChk[host, corner] THEN NULL ELSE ERROR InvalidArgs[$RemoveCoAtCorner]; [horCh, verCh] _ CoTab.GetCornerChs[host, corner]^; CoTab.SetCornerChs[host, corner, NIL]; [hEdge, vEdge] _ BO.CTResolve[corner]; [hSide, vSide] _ BO.CTInvDirectn[corner]; co _CB.SideGetComp[verCh.boundary, BO.PTNot[hSide]]; CB.DestroyINode[CB.SideRem[CoTab.GetPrinCh[host, hEdge].boundary, verCh, vSide, host]]; CB.DestroyINode[CB.SideRem[CoTab.GetPrinCh[host, vEdge].boundary, horCh, hSide, host]]; };--RemoveCoAtCorner -- RemoveCoAtCornerChk: PUBLIC PROC[host: CoTab.Component, corner: CoTab.CornerTypes] RETURNS [BOOL]={ cChs: CoTab.CornerChannels _ CoTab.GetCornerChs[host, corner]; hDirectn, vDirectn: BO.PolarityTypes; IF cChs = NIL THEN RETURN [FALSE]; [hDirectn, vDirectn] _ BO.CTDirectn[corner]; IF NOT (CTG.End[cChs.hor, hDirectn].type = CB.TEnd AND CTG.End[cChs.ver, vDirectn].type = CB.TEnd) THEN RETURN [FALSE]; IF EO.NoIntersection[cChs.hor] AND EO.NoIntersection[cChs.ver] THEN RETURN [TRUE] ELSE RETURN [FALSE]; };--RemoveCoAtCornerChk -- InsertCo1: PUBLIC PROC[co: CoTab.Component, chToSplit, negBnd, posBnd: CTG.Channel, sideToOpHint: CB.Side, newCh1: CTG.Channel] RETURNS [sideToClHint: CB.Side]= { IF InsertCo1Chk[co, chToSplit, negBnd, posBnd] THEN NULL ELSE ERROR InvalidArgs [$InsertCo1]; SELECT sideToOpHint FROM neg => IF CTG.ArmOn[chToSplit, negBnd, neg] AND CTG.ArmOn[chToSplit, posBnd, neg] THEN NULL ELSE sideToOpHint _ pos; pos => IF CTG.ArmOn[chToSplit, negBnd, pos] AND CTG.ArmOn[chToSplit, posBnd, pos] THEN NULL ELSE sideToOpHint _ neg; ENDCASE => ERROR; EO.OpenHole1[chToSplit, newCh1, negBnd, posBnd, sideToOpHint]; EO.CBSwapChsInComps[newCh1.boundary, chToSplit, newCh1]; SELECT chToSplit.type FROM hor => IF sideToOpHint = pos THEN EO.CoInsert[co, chToSplit, posBnd, newCh1, negBnd] ELSE EO.CoInsert[co, newCh1, posBnd, chToSplit, negBnd]; ver => IF sideToOpHint = pos THEN EO.CoInsert[co, negBnd, newCh1, posBnd, chToSplit] ELSE EO.CoInsert[co, negBnd, chToSplit, posBnd, newCh1]; ENDCASE => ERROR; RETURN [sideToOpHint]; }; --InsertCo1-- InsertCo1Chk: PUBLIC PROC[co: CoTab.Component, chToSplit, negBnd, posBnd: CTG.Channel] RETURNS [BOOL]= { cCB: CB.Ref _ chToSplit.boundary; IF NOT EO.BndsOkChk[chToSplit, negBnd, posBnd] THEN RETURN [FALSE]; SELECT TRUE FROM CB.ArmOn[cCB, negBnd, neg] AND CB.ArmOn[cCB, posBnd, neg] => IF CB.InCount[cCB, negBnd, neg] < CB.InCount[cCB, posBnd, neg] THEN NULL ELSE RETURN [FALSE]; CB.ArmOn[cCB, negBnd, pos] AND CB.ArmOn[cCB, posBnd, pos] => IF CB.InCount[cCB, negBnd, pos] < CB.InCount[cCB, posBnd, pos] THEN NULL ELSE RETURN [FALSE]; ENDCASE => RETURN[FALSE]; IF EO.CrossIn[chToSplit, negBnd] THEN RETURN [EO.XCount[chToSplit, posBnd] = EO.XCount[chToSplit, negBnd] + 1] ELSE RETURN [EO.XCount[chToSplit, posBnd] = EO.XCount[chToSplit, negBnd]] }; --InsertCo1Chk-- RemoveCo1: PUBLIC PROC[co: CoTab.Component, shrinkDirectn: BO.OrientationTypes, sideToClHint: CB.Side] RETURNS [mainCh, negBnd, posBnd, sideCh: CTG.Channel, sideToOpHint: CB.Side] --mainCh ~ chToSplit; sideCh ~newCh1 -- = { negCh, posCh: CTG.Channel; IF RemoveCo1Chk[co, shrinkDirectn] THEN NULL ELSE ERROR InvalidArgs[$RemoveCo1]; IF shrinkDirectn = hor THEN {negCh _ CoTab.GetPrinCh[co, west]; posCh _ CoTab.GetPrinCh[co, east]; negBnd _ CoTab.GetPrinCh[co, south]; posBnd _ CoTab.GetPrinCh[co, north];} ELSE {negCh _ CoTab.GetPrinCh[co, south]; posCh _ CoTab.GetPrinCh[co, north]; negBnd _ CoTab.GetPrinCh[co, west]; posBnd _ CoTab.GetPrinCh[co, east];}; SELECT sideToClHint FROM neg => IF EO.AreTEndChs[negCh, negBnd, posBnd] THEN NULL ELSE sideToClHint _ pos; pos => IF EO.AreTEndChs[posCh, negBnd, posBnd] THEN NULL ELSE sideToClHint _ neg; ENDCASE => ERROR; IF sideToClHint = pos THEN {mainCh _ negCh; sideCh _ posCh} ELSE {mainCh _ posCh; sideCh _ negCh}; EO.CBSwapChsInComps[sideCh.boundary, sideCh, mainCh]; EO.CloseHole1[mainCh, sideCh, negBnd, posBnd, sideToClHint]; sideToOpHint _ sideToClHint; }; --RemoveCo1-- RemoveCo1Chk: PUBLIC PROC[co: CoTab.Component, shrinkDirectn: BO.OrientationTypes] RETURNS [BOOL]= { ct: CoTab.CornerTypes _ sw; negCh, posCh, negBnd, posBnd: CTG.Channel; THROUGH [0..4) DO IF CoTab.GetCornerChs[co, ct] # NIL THEN RETURN [FALSE]; ct _ BO.CTRotate[ct]; ENDLOOP; IF shrinkDirectn = hor THEN {negCh _ CoTab.GetPrinCh[co, west]; posCh _ CoTab.GetPrinCh[co, east]; negBnd _ CoTab.GetPrinCh[co, south]; posBnd _ CoTab.GetPrinCh[co, north];} ELSE {negCh _ CoTab.GetPrinCh[co, south]; posCh _ CoTab.GetPrinCh[co, north]; negBnd _ CoTab.GetPrinCh[co, west]; posBnd _ CoTab.GetPrinCh[co, east];}; IF EO.AreTEndChs[negCh, negBnd, posBnd] THEN RETURN [TRUE]; IF EO.AreTEndChs[posCh, negBnd, posBnd] THEN RETURN [TRUE]; RETURN [FALSE];}; --RemoveCo1Chk-- InsertCo2: PUBLIC PROC[co: CoTab.Component, chToSplit, negBnd, posBnd: CTG.Channel, sideToOpHint: CB.Side, newCh1: CTG.Channel] RETURNS [sideToClHint: CB.Side]= { IF InsertCo2Chk[co, chToSplit, negBnd, posBnd] THEN NULL ELSE ERROR InvalidArgs [$InsertCo2]; SELECT sideToOpHint FROM neg => IF CTG.ArmOn[chToSplit, negBnd, neg] AND CTG.ArmOn[chToSplit, posBnd, pos] THEN NULL ELSE sideToOpHint _ pos; pos => IF CTG.ArmOn[chToSplit, negBnd, pos] AND CTG.ArmOn[chToSplit, posBnd, neg] THEN NULL ELSE sideToOpHint _ neg; ENDCASE => ERROR; EO.OpenHole2[chToSplit, newCh1, negBnd, posBnd, sideToOpHint]; EO.CBSwapChsInComps[newCh1.boundary, chToSplit, newCh1, 1]; EO.CoSwapChs[CTG.NthComponent[newCh1, sideToOpHint, 1], chToSplit, newCh1]; SELECT chToSplit.type FROM hor => IF sideToOpHint = pos THEN EO.CoInsert[co, chToSplit, posBnd, newCh1, negBnd] ELSE EO.CoInsert[co, newCh1, posBnd, chToSplit, negBnd]; ver => IF sideToOpHint = pos THEN EO.CoInsert[co, negBnd, newCh1, posBnd, chToSplit] ELSE EO.CoInsert[co, negBnd, chToSplit, posBnd, newCh1]; ENDCASE => ERROR; RETURN [sideToOpHint]; }; --InsertCo2-- InsertCo2Chk: PUBLIC PROC[co: CoTab.Component, chToSplit, negBnd, posBnd: CTG.Channel] RETURNS [BOOL]= { cCB: CB.Ref _ chToSplit.boundary; IF NOT EO.BndsOkChk[chToSplit, negBnd, posBnd] THEN RETURN [FALSE]; SELECT TRUE FROM CB.ArmOn[cCB, negBnd, neg] AND CB.ArmOn[cCB, posBnd, pos] => NULL; CB.ArmOn[cCB, negBnd, pos] AND CB.ArmOn[cCB, posBnd, neg] => NULL; ENDCASE => RETURN[FALSE]; IF EO.CrossIn[chToSplit, negBnd] THEN RETURN [EO.XCount[chToSplit, posBnd] = EO.XCount[chToSplit, negBnd] + 1] ELSE RETURN [EO.XCount[chToSplit, posBnd] = EO.XCount[chToSplit, negBnd]] }; --InsertCo2Chk-- RemoveCo2: PUBLIC PROC[co: CoTab.Component, shrinkDirectn: BO.OrientationTypes, sideToClHint: CB.Side] RETURNS [mainCh, negBnd, posBnd, sideCh: CTG.Channel, sideToOpHint: CB.Side] --mainCh ~ chToSplit; sideCh ~newCh1 -- = { negCh, posCh: CTG.Channel; IF RemoveCo2Chk[co, shrinkDirectn] THEN NULL ELSE ERROR InvalidArgs[$RemoveCo2]; IF shrinkDirectn = hor THEN {negCh _ CoTab.GetPrinCh[co, west]; posCh _ CoTab.GetPrinCh[co, east]; negBnd _ CoTab.GetPrinCh[co, south]; posBnd _ CoTab.GetPrinCh[co, north];} ELSE {negCh _ CoTab.GetPrinCh[co, south]; posCh _ CoTab.GetPrinCh[co, north]; negBnd _ CoTab.GetPrinCh[co, west]; posBnd _ CoTab.GetPrinCh[co, east];}; SELECT sideToClHint FROM neg => IF EO.IsTEndCh[negCh, negBnd] AND EO.IsTEndCh[posCh, posBnd] THEN NULL ELSE sideToClHint _ pos; pos => IF EO.IsTEndCh[posCh, negBnd] AND EO.IsTEndCh[negCh, posBnd] THEN NULL ELSE sideToClHint _ neg; ENDCASE => ERROR; IF sideToClHint = pos THEN {mainCh _ negCh; sideCh _ posCh} ELSE {mainCh _ posCh; sideCh _ negCh}; EO.CBSwapChsInComps[sideCh.boundary, sideCh, mainCh]; EO.CloseHole2[mainCh, sideCh, negBnd, posBnd, sideToClHint]; sideToOpHint _ sideToClHint; }; --RemoveCo2-- RemoveCo2Chk: PUBLIC PROC[co: CoTab.Component, shrinkDirectn: BO.OrientationTypes] RETURNS [BOOL]= { ct: CoTab.CornerTypes _ sw; negCh, posCh, negBnd, posBnd: CTG.Channel; THROUGH [0..4) DO IF CoTab.GetCornerChs[co, ct] # NIL THEN RETURN [FALSE]; ct _ BO.CTRotate[ct]; ENDLOOP; IF shrinkDirectn = hor THEN {negCh _ CoTab.GetPrinCh[co, west]; posCh _ CoTab.GetPrinCh[co, east]; negBnd _ CoTab.GetPrinCh[co, south]; posBnd _ CoTab.GetPrinCh[co, north];} ELSE {negCh _ CoTab.GetPrinCh[co, south]; posCh _ CoTab.GetPrinCh[co, north]; negBnd _ CoTab.GetPrinCh[co, west]; posBnd _ CoTab.GetPrinCh[co, east];}; IF EO.IsTEndCh[negCh, negBnd] AND EO.IsTEndCh[posCh, posBnd] THEN RETURN [TRUE]; IF EO.IsTEndCh[negCh, posBnd] AND EO.IsTEndCh[posCh, negBnd] THEN RETURN [TRUE]; RETURN [FALSE];}; --RemoveCo2Chk-- END. <<--Change Log>> <<--This is a bug fix: to handle a case not thought of earlier>> <<-- changes to: FormZChk-> Construct EO.CoXingCount to >> <<-- solve this sticky problem IPEditPrimitivesImpl>> <<>>