IPTopEditOpsImpl:
CEDAR
PROGRAM
IMPORTS IPOrient, RefStack, CDBasics, IPBasicOps, IPCoTab, IPCTG, IPTop, IPPinNets, IPEditOps, IPEditPrimitives, IPTopOps
EXPORTS IPTopOps, IPTopOpsPrivate = BEGIN OPEN BO: IPBasicOps, TOR: IPTopOpRecs, EO: IPEditOps, EP: IPEditPrimitives, CoTab: IPCoTab, CTG: IPCTG, Top: IPTop, IPTopOps;
FirstSideToTry: CTG.Side ← pos; --A minor detail--
WhichOneFirst: [1..2] ← 1; --Another minor detail--
InvalidArgs: PUBLIC ERROR[op: ATOM] = CODE;
BreakCross:
PUBLIC
PROC [top: Top.Ref, refCh, chToBreak:
CTG.Channel, keepTrack:
BOOL ←
FALSE]
RETURNS [fr:
TOR.FRBreakCross, ir:
TOR.IRFormCross] ={
newCh1: CTG.Channel;
IF NOT EP.BreakCrossChk[refCh, chToBreak] THEN ERROR InvalidArgs[$BreakCross]; --(1) Check args--
newCh1 ← top.CreateChannel[chToBreak.type];
EP.BreakCross[refCh, chToBreak, newCh1];
fr ← NEW[TOR.FRBreakCrossRec ← [refCh, chToBreak]]; --(2a) Setup fr--
ir ← NEW[TOR.IRFormCrossRec ← [refCh, chToBreak, newCh1]]; --(2b) Setup ir--
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --BreakCross--
FormCross:
PUBLIC
PROC[top: Top.Ref, ch1, ch2:
CTG.Channel, keepTrack:
BOOL ←
FALSE]
RETURNS [fr:
TOR.FRFormCross, ir:
TOR.IRBreakCross] = {
refCh, negCh, posCh: CTG.Channel;
IF
CTG.End[ch1, neg].ch =
CTG.End[ch2, pos].ch
THEN {negCh ← ch2; posCh ← ch1}
ELSE {negCh ← ch1; posCh ← ch2};
refCh ← CTG.End[negCh, pos].ch;
IF NOT EP.FormCrossChk[refCh, negCh, posCh] THEN ERROR InvalidArgs[$FormCross]; --(1) Check args--
EP.FormCross[refCh, negCh, posCh];
top.DeActivateChannel[posCh];
fr ← NEW[TOR.FRFormCrossRec ← [ch1, ch2]]; --(2a) Setup fr--
ir ← NEW[TOR.IRBreakCrossRec ← [refCh, negCh, posCh]]; --(2b) Setup ir--
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --FormCross--
BreakCrosses:
PUBLIC
PROC[top: Top.Ref, refCh, chBnd1, chBnd2:
CTG.Channel, keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.RComposite ←
NIL] = {
negCh, posCh: CTG.Channel;
noXToBreak: NAT;
startBreaking: BOOL ← FALSE;
breakXPROC:
CTG.EachIntersectionAction
-- [i: CB.Intersection] RETURNS [quit: BOOL ← FALSE] -- = {
tempFR: TOR.FRBreakCross;
tempIR: TOR.IRFormCross;
IF noXToBreak = 0 THEN RETURN [TRUE];
IF startBreaking
AND i.type =
CTG.Cross
THEN {
[tempFR, tempIR] ← BreakCross[top, refCh, i.ch];
[fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--
noXToBreak ← noXToBreak.PRED};
IF i.ch = negCh THEN startBreaking ← TRUE;}; --breakXPROC--
IF NOT (CTG.IntersectsCh[refCh, chBnd1] AND CTG.IntersectsCh[refCh, chBnd2]) THEN ERROR InvalidArgs[$BreakCrosses]; --(1) Check args--
IF EO.XCount[refCh, chBnd1] > EO.XCount[refCh, chBnd2] THEN {posCh ← chBnd1; negCh ← chBnd2} ELSE {posCh ← chBnd2; negCh ← chBnd1};
noXToBreak ← EO.XCount[refCh, posCh] - EO.XCount[refCh, negCh];
IF EO.CrossIn[refCh, negCh] THEN noXToBreak ← noXToBreak.PRED;
IF CTG.EndCh[refCh, negCh] THEN startBreaking ← TRUE;
IF
CTG.ArmOn[refCh, negCh, neg]
THEN [] ← CTG.Intersections[refCh, neg, breakXPROC]
ELSE [] ← CTG.Intersections[refCh, pos, breakXPROC];
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --BreakCrosses--
FormZ:
PUBLIC
PROC[top: Top.Ref, comp1, comp2: CoTab.Component, zType:
CTG.Side, keepTrack:
BOOL ←
FALSE]
RETURNS [fr:
TOR.FRFormZ, ir:
TOR.IRRemoveZ] ={
et: CoTab.EdgeTypes ← south;
refCh: CTG.Channel ← NIL;
negComp, posComp: CoTab.Component;
newCh1, newCh2: CTG.Channel;
THROUGH [0..4)
DO
IF CoTab.GetPrinCh[comp1, et] = CoTab.GetPrinCh[comp2,
BO.ETRotate[et, 2]]
THEN {refCh ← CoTab.GetPrinCh[comp1, et]; EXIT};
et ← BO.ETRotate[et];
ENDLOOP;
IF
BO.ETDirectn[et] = neg
THEN {negComp ← comp2; posComp ← comp1}
ELSE {negComp ← comp1; posComp ← comp2};
IF refCh = NIL OR NOT EP.FormZChk[refCh, negComp, posComp, zType] THEN ERROR InvalidArgs[$FormZ]; --(1) Check args--
newCh1 ← top.CreateChannel[refCh.type];
newCh2 ← top.CreateChannel[BO.OTFlip[refCh.type]];
EP.FormZ[refCh, negComp, posComp, zType, newCh1, newCh2];
fr ← NEW[TOR.FRFormZRec ← [comp1, comp2, zType]]; --(2a) Setup fr--
ir ← NEW[TOR.IRRemoveZRec ← [newCh2]]; --(2b) Setup ir--
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --FormZ--
RemoveZ:
PUBLIC
PROC[top: Top.Ref, zSpine:
CTG.Channel, keepTrack:
BOOL ←
FALSE]
RETURNS [fr:
TOR.FRRemoveZ, ir:
TOR.IRFormZ] ={
refCh, newCh1: CTG.Channel;
negComp, posComp: CoTab.Component;
zType: CTG.Side;
IF NOT EP.RemoveZChk[zSpine] THEN ERROR InvalidArgs[$RemoveZ]; --(1) Check args--
[refCh, newCh1, negComp, posComp, zType] ← EP.RemoveZ[zSpine];
top.DeActivateChannel[newCh1];
top.DeActivateChannel[zSpine];
fr ← NEW[TOR.FRRemoveZRec ← [zSpine]]; --(2a) Setup fr--
ir ← NEW[TOR.IRFormZRec ← [refCh, negComp, posComp, zType, newCh1, zSpine]]; --(2b) Setup ir--
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --RemoveZ--
LtoT:
PUBLIC
PROC[top: Top.Ref, ch:
CTG.Channel, whichEnd:
CTG.Side, keepTrack:
BOOL ←
FALSE]
RETURNS [fr:
TOR.FRLtoT, ir:
TOR.RComposite] ={
lType: CTG.Side;
endCo: CoTab.Component;
otherCh, newCh1: CTG.Channel;
okProc:
PROC
RETURNS [
BOOL] = {
otherInt: CTG.Intersection;
SELECT
CTG.End[ch, whichEnd].type
FROM
CTG.LNeg => otherInt ← CTG.NthIntersection[ch, pos, - BO.PTToInt[whichEnd]];
CTG.LPos => otherInt ← CTG.NthIntersection[ch, neg, - BO.PTToInt[whichEnd]];
CTG.TEnd => RETURN[FALSE];
ENDCASE => ERROR;
IF otherInt =
NIL
OR (otherCh ← otherInt.ch) =
NIL
THEN RETURN [FALSE]
ELSE RETURN [TRUE]
}; --okProc--
IF NOT okProc[] THEN ERROR InvalidArgs[$LtoT]; --(1) Check args--
IF EO.CrossIn[ch, otherCh] THEN ir ←LIST[BreakCross[top, ch, otherCh].ir];
[newCh1, lType, endCo] ← EP.LtoT[ch, whichEnd];
top.DeActivateChannel[newCh1];
fr ← NEW[TOR.FRLtoTRec ← [ch, whichEnd]]; --(2a) Setup fr--
ir ← CONS[NEW[TOR.IRTtoLRec ← [ch, whichEnd, lType, endCo, newCh1]], ir]; --(2b) Setup ir--
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --LtoT--
TtoL:
PUBLIC
PROC [top: Top.Ref, co: CoTab.Component, ch:
CTG.Channel, lType:
CTG.Side, keepTrack:
BOOL ←
FALSE]
RETURNS [fr:
TOR.FRTtoL, ir:
TOR.IRLtoT] ={
newCh1: CTG.Channel;
whichEnd: CTG.Side;
SELECT
TRUE
FROM
--(1) Check args--
EP.TtoLChk[ch, neg, lType, co] => whichEnd ← neg;
EP.TtoLChk[ch, pos, lType, co] => whichEnd ← pos;
ENDCASE => ERROR InvalidArgs[$TtoL];
newCh1 ← top.CreateChannel[BO.OTFlip[ch.type]];
EP.TtoL[ch, whichEnd, lType, co, newCh1];
fr ← NEW[TOR.FRTtoLRec ← [co, ch, lType]]; --(2a) Setup fr--
ir ← NEW[TOR.IRLtoTRec ← [ch, whichEnd]]; --(2b) Setup ir--
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --TtoL--
FlexKnee:
PUBLIC
PROC [top: Top.Ref, leg, floor:
CTG.Channel, whichEnd:
CTG.Side, keepTrack:
BOOL ←
FALSE]
RETURNS [fr:
TOR.FRFlexKnee, ir:
TOR.RComposite] ={
newCh1: CTG.Channel;
chToAtt: CTG.Channel ← CTG.End[leg, whichEnd].ch;
sideToAtt: CTG.Side ← BO.PTNot[whichEnd];
whichDirection: CTG.Side ← IF CTG.InCount[chToAtt, floor, sideToAtt] < CTG.InCount[chToAtt, leg, sideToAtt] THEN neg ELSE pos;
flexOk:
PROC
RETURNS [
BOOL] ={
parent: CoTab.Component ← CTG.NthComponent[leg, BO.PTNot[whichDirection], -BO.PTToInt[whichEnd]];
corner: CoTab.CornerTypes ← IF leg.type = hor THEN BO.CTFromPTs[hor: sideToAtt, ver: whichDirection] ELSE BO.CTFromPTs[hor: whichDirection, ver: sideToAtt];
IF CoTab.GetCornerSp[parent, corner] = NIL OR CoTab.GetCornerChs[parent, corner] # NIL THEN RETURN [FALSE];
IF CTG.End[leg, whichEnd].type # CTG.TEnd THEN RETURN [FALSE];
IF NOT CTG.ArmOn[chToAtt, floor, sideToAtt] THEN RETURN [FALSE];
RETURN [TRUE]
}; --flexOk--
IF NOT flexOk[] THEN ERROR InvalidArgs[$FlexKnee]; --(1) Check args--
newCh1 ← top.CreateChannel[BO.OTFlip[leg.type]];
ir ← BreakCrosses[top, chToAtt, floor, leg].ir;
EP.FlexKnee[leg, floor, whichEnd, whichDirection, newCh1];
fr ← NEW[TOR.FRFlexKneeRec ← [leg, floor, whichEnd]]; --(2a) Setup fr--
ir ← CONS[NEW[TOR.IRExtendKneeRec ← [newCh1]], ir]; --(2b) Setup ir--
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --FlexKnee--
ExtendKnee:
PUBLIC
PROC [top: Top.Ref, shin:
CTG.Channel, keepTrack:
BOOL ←
FALSE]
RETURNS [fr:
TOR.FRExtendKnee, ir:
TOR.IRFlexKnee] ={
leg, floor: CTG.Channel;
whichEnd, whichDirection: CTG.Side;
IF NOT EP.ExtendKneeChk[shin] THEN ERROR InvalidArgs[$ExtendKnee]; --(1) Check args--
[leg, floor, whichEnd, whichDirection] ← EP.ExtendKnee[shin];
top.DeActivateChannel[shin];
fr ← NEW[TOR.FRExtendKneeRec ← [shin]]; --(2a) Setup fr--
ir ← NEW[TOR.IRFlexKneeRec ← [leg, floor, whichEnd, whichDirection, shin]]; --(2b) Setup ir--
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --ExtendKnee--
Grow:
PUBLIC
PROC[top: Top.Ref, co: CoTab.Component, chToSplit, negBnd, posBnd:
CTG.Channel, keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.RComposite ←
NIL] ={
tempFR, tempIR: TOR.RAny;
IF
CTG.End[chToSplit, pos].ch = negBnd
--Just to make Grow more General--
THEN {negBnd ← posBnd; posBnd ← CTG.End[chToSplit, pos].ch};
IF
CTG.End[chToSplit, neg].ch = posBnd
--Just to make Grow more General--
THEN {posBnd ← negBnd; negBnd ← CTG.End[chToSplit, neg].ch};
IF CoTab.CoActive[co] OR NOT EO.BndsOkChk[chToSplit, negBnd, posBnd] THEN ERROR InvalidArgs[$Grow]; --(1) Check args--
[tempFR, tempIR] ← BreakCrosses[top, chToSplit, negBnd, posBnd]; --Break All Crosses in between--
[fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--
[tempFR, tempIR] ← InsertCo[top, co, chToSplit, negBnd, posBnd, FirstSideToTry, WhichOneFirst];
[fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --Grow--
Grow1:
PUBLIC
PROC[top: Top.Ref, co, host: CoTab.Component, hostCorner: CoTab.CornerTypes, keepTrack:
BOOL ←
FALSE]
RETURNS [fr:
TOR.FRGrow1, ir:
TOR.IRRemoveCoAtCorner] ={
newHCh1, newVCh1: CTG.Channel;
IF CoTab.CoActive[co] OR NOT EP.InsertCoAtCornerChk[host, co, hostCorner] THEN ERROR InvalidArgs[$Grow1]; --(1) Check args--
CoTab.ReActivateComponent[co];
newHCh1 ← top.CreateChannel[hor];
newVCh1 ← top.CreateChannel[ver];
EP.InsertCoAtCorner[host, co, hostCorner, newHCh1, newVCh1];
fr ← NEW[TOR.FRGrow1Rec ← [co, host, hostCorner]]; --(2a) Setup fr--
ir ← NEW[TOR.IRRemoveCoAtCornerRec ← [host, hostCorner]]; --(2b) Setup ir--
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --Grow1--
Shrink:
PUBLIC
PROC[top: Top.Ref, co: CoTab.Component, shrinkDirectionHint:
CTG.ChType, keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.RComposite ←
NIL] ={
corner: CoTab.CornerTypes ← sw;
hintNot: CTG.ChType ← BO.OTFlip[shrinkDirectionHint];
tempFR, tempIR: TOR.RAny;
IF NOT CoTab.CoActive[co] THEN ERROR InvalidArgs[$Shrink]; --(1) Check args--
[tempFR, tempIR] ← ClearAllNegCorners[top, co, hintNot];
IF tempIR # NIL THEN [fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--
[tempFR, tempIR] ← ClearAllLCorners[top, co, shrinkDirectionHint];
IF tempIR # NIL THEN [fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--
THROUGH [0..4)
DO
frAny, irAny: TOR.RAny;
[frAny, irAny] ← BreakXAtCorner[top, co, corner, hintNot];
IF irAny # NIL THEN [fr, ir] ← Cons2[frAny, fr, irAny, ir]; --Setup fr and ir--
corner ← BO.CTRotate[corner];
ENDLOOP;
IF Shrink1Chk[co]
THEN {[tempFR, tempIR]← Shrink1[top, co];
[fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--}
ELSE {
[tempFR, tempIR] ← IF RemoveCoChk[co, shrinkDirectionHint] THEN RemoveCo[top, co, shrinkDirectionHint] ELSE RemoveCo[top, co, hintNot];
[fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--};
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --Shrink--
ClearNegCorner:
PUBLIC
PROC[top: Top.Ref, co: CoTab.Component, corner: CoTab.CornerTypes, chToUse:
CTG.ChType, breakOtherIfX, keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.RComposite ←
NIL] ={
IF CoTab.GetCornerChs[co, corner] = NIL THEN GOTO done; -- nothing to do--
BEGIN
chDn: CTG.Side ← BO.CTDirectnFor[corner, chToUse];
otherDn: CTG.Side ← BO.CTDirectnFor[corner, BO.OTFlip[chToUse]];
cornerCh: CTG.Channel ← CoTab.GetCornerChFor[co, corner, chToUse];
prinCh: CTG.Channel ← CoTab.GetPrinCh[co, BO.CTResolveFor[corner, BO.OTFlip[chToUse]]];
tempFR, tempIR: TOR.RAny ← NIL;
IF
EO.CrossIn[cornerCh, prinCh]
THEN {
[tempFR, tempIR] ← IF breakOtherIfX THEN BreakCross[top, cornerCh, prinCh] ELSE BreakCross[top, prinCh, cornerCh];
[fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--
cornerCh ← CoTab.GetCornerChFor[co, corner, chToUse];
prinCh ← CoTab.GetPrinCh[co, BO.CTResolveFor[corner, BO.OTFlip[chToUse]]];};
IF
NOT
CTG.NoIntersection[cornerCh,
BO.PTNot[otherDn]]
THEN {
[tempFR, tempIR] ← LtoT[top, cornerCh, BO.PTNot[chDn]];
[fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--
GOTO done};
IF
CTG.End[cornerCh, chDn].type #
CTG.TEnd
THEN{
IF
EO.NoIntersection[cornerCh]
THEN {[tempFR, tempIR] ← RemoveZ[top, cornerCh];
[fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--
GOTO done}
ELSE {[tempFR, tempIR] ← LtoT[top, cornerCh, chDn];
[fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--}};
[tempFR, tempIR] 𡤎xtendKnee[top, cornerCh];
[fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--
GOTO done;
END;
EXITS
done => IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --ClearNegCorner--
ClearAllNegCorners:
PUBLIC
PROC[top: Top.Ref, co: CoTab.Component, chToUse:
CTG.ChType, breakOtherIfX, keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.RComposite ←
NIL] ={
corner: CoTab.CornerTypes ← sw;
tempFR, tempIR: TOR.RAny ← NIL;
IF NOT CoTab.CoActive[co] THEN ERROR InvalidArgs[$ClearAllNegCorners]; --(1) Check args--
THROUGH [0..4)
DO
[tempFR, tempIR] ← ClearNegCorner[top, co, corner, chToUse, breakOtherIfX];
IF tempIR # NIL THEN [fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--
corner ← BO.CTRotate[corner];
ENDLOOP;
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --ClearAllNegCorners--
ClearLCorner:
PUBLIC
PROC[top: Top.Ref, co: CoTab.Component, corner: CoTab.CornerTypes, hint:
CTG.ChType, keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.RAny ←
NIL] ={
IF CoTab.GetCornerChs[co, corner] # NIL THEN ERROR InvalidArgs [$ClearLCorner];
BEGIN
hintNot: CTG.ChType ← BO.OTFlip[hint];
hintDn: CTG.Side ← BO.CTDirectnFor[corner, hint];
otherDn: CTG.Side ← BO.CTDirectnFor[corner, BO.OTFlip[hint]];
hintCh: CTG.Channel ← CoTab.GetPrinCh[co, BO.CTResolveFor[corner, hint]];
otherCh: CTG.Channel ← CoTab.GetPrinCh[co, BO.CTResolveFor[corner, hintNot]];
IF NOT EO.IsLCorner[hintCh, otherCh] THEN GOTO done; --Nothing to do--
IF
NOT
CTG.NoIntersection[hintCh, otherDn]
THEN {[fr, ir] ← LtoT[top, hintCh, hintDn]; GOTO done};
IF
NOT
CTG.NoIntersection[otherCh, hintDn]
THEN {[fr, ir] ← LtoT[top, otherCh, otherDn]; GOTO done};
GOTO done--Cant do anything--
EXITS
done => IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
END;
}; --ClearLCorner--
ClearAllLCorners:
PUBLIC
PROC[top: Top.Ref, co: CoTab.Component, hint:
CTG.ChType, keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.RComposite ←
NIL] ={
corner: CoTab.CornerTypes ← sw;
tempFR, tempIR: TOR.RAny;
IF NOT CoTab.CoActive[co] THEN ERROR InvalidArgs[$ClearAllLCorners]; --(1) Check args--
THROUGH [0..4)
DO
[tempFR, tempIR] ← ClearLCorner[top, co, corner, hint];
IF tempIR # NIL THEN [fr, ir] ← Cons2[tempFR, fr, tempIR, ir]; --Setup fr and ir--
corner ← BO.CTRotate[corner];
ENDLOOP;
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --ClearAllLCorners--
BreakXAtCorner:
PUBLIC
PROC [top: Top.Ref, co: CoTab.Component, corner: CoTab.CornerTypes, chToBreak:
CTG.ChType, keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.RAny ←
NIL] ={
IF CoTab.GetCornerChs[co, corner] # NIL THEN ERROR InvalidArgs [$BreakXAtCorner];
BEGIN
hCh: CTG.Channel ← CoTab.GetPrinCh[co, BO.CTResolveFor[corner, hor]];
vCh: CTG.Channel ← CoTab.GetPrinCh[co, BO.CTResolveFor[corner, ver]];
IF
EO.CrossIn[hCh, vCh]
THEN
[fr, ir] ← (IF chToBreak = hor THEN BreakCross[top, vCh, hCh] ELSE BreakCross[top, hCh, vCh]);
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
END;
}; --BreakXAtCorner--
Mirror:
PUBLIC
PROC[top: Top.Ref, co: CoTab.Component, mirrorOrientation:
CTG.ChType, keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.ROrient] ={
SELECT mirrorOrientation
FROM
ver => [fr, ir] ← Orient[top, co, mirrorX, keepTrack];
hor => [fr, ir] ← Orient[top, co, rotate180X, keepTrack];
ENDCASE => ERROR;
}; --Mirror
Rotate:
PUBLIC
PROC[top: Top.Ref, co: CoTab.Component, numberOfRot:
INT ← 1, keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.ROrient] ={
SELECT numberOfRot
MOD 4
FROM
0 => [fr, ir] ← Orient[top, co, original, keepTrack];
1, -3 => [fr, ir] ← Orient[top, co, rotate90, keepTrack];
2, -2 => [fr, ir] ← Orient[top, co, rotate180, keepTrack];
3, -1 => [fr, ir] ← Orient[top, co, rotate270, keepTrack];
ENDCASE => ERROR;
}; --Rotate
Orient:
PUBLIC
PROC[top: Top.Ref, co: CoTab.Component, operation: D2Orient.Orientation, keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.ROrient] ={
IF ~ CoTab.OrientCoShapeChk[co, operation] THEN ERROR InvalidArgs[$Orient]; --(1) Check args--
fr ← NEW[TOR.ROrientRec ← [co, operation]]; --(2a) Setup fr--
ir ← NEW[TOR.ROrientRec ← [co, IPOrient.InverseOrient[operation]]]; --(2b) Setup ir--
CoTab.OrientCoShape[co, operation];
IPPinNets.OrientPinNets[co, operation]; --this must be done before co.orient ← ...
co.orient ← IPOrient.ComposeOrient[co.orient, operation];
top.initialized ← FALSE; --Set Flags to indicate geometry is not right
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --Orient
SetComponent:
PUBLIC
PROC[top: Top.Ref, co: CoTab.Component, active:
BOOL, atPosition: IPCoTab.IntVector ← [0, 0], keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.RSetComponent] ={
IF ~ SetComponentChk[top, co, active]
THEN ERROR InvalidArgs[$SetComponent];--(1) Check args
fr ← NEW[TOR.RSetComponentRec ← [co, active, atPosition]]; --(2a) Setup fr--
ir ← NEW[TOR.RSetComponentRec ← [co, CoTab.CoActive[co], CoTab.GetOrigin[co]]]; --(2b) Setup ir--
IF active
THEN {IF ~ CoTab.CoActive[co] THEN CoTab.ReActivateComponent[co]}
ELSE {IF CoTab.CoActive[co] THEN CoTab.DeActivateComponent[co]};
CoTab.SetOrigin[co, atPosition];
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --SetComponent
MoveComponent:
PUBLIC
PROC [top: Top.Ref, co: CoTab.Component, by: IPCoTab.IntVector, keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.RMoveComponent] ={
--(1) DONT have to Check args--
fr ← NEW[TOR.RMoveComponentRec ← [co, by]]; --(2a) Setup fr--
ir ← NEW[TOR.RMoveComponentRec ← [co, BO.IntVectorNegate[by]]]; --(2b) Setup ir--
CoTab.SetOrigin[co, CDBasics.AddPoints[CoTab.GetOrigin[co], by]];
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
};--MoveComponent
SwapComponents:
PUBLIC
PROC[top: Top.Ref, co1, co2: CoTab.Component, keepTrack:
BOOL ←
FALSE]
RETURNS [fr, ir:
TOR.RSwapComponents] ={
--This is the only place where I did not obey the IPCoTab.Component abstraction
-- (ie. accessing the fields directly)
IF ~ SwapComponentsChk[top, co1, co2] THEN ERROR InvalidArgs[$SwapComponents]; --(1) Check args
BEGIN OPEN c1P: co1.prinChannels, c1C: co1.cornerChannels, c2P: co2.prinChannels, c2C: co2.cornerChannels;
--(A) Keep temporary for co1
tActive: BOOL ← co1.active;
tOrigin: CoTab.IntVector ← co1.origin;
tSouth, tEast, tNorth, tWest: CTG.Channel;
tSw, tSe, tNe, tNw: CoTab.CornerChannels;
[tSouth, tEast, tNorth, tWest] ← co1.prinChannels;
[tSw, tSe, tNe, tNw] ← co1.cornerChannels;
--(B) Assign to co1
IF co1.active # co2.active
THEN {
IF co2.active
THEN IPCoTab.ReActivateComponent[co1]
ELSE IPCoTab.DeActivateComponent[co1]};
co1.origin ← co2.origin;
co1.prinChannels ← co2.prinChannels;
co1.cornerChannels ← co2.cornerChannels;
-- (C) Assign to co2
IF co2.active # tActive
THEN {
IF tActive
THEN IPCoTab.ReActivateComponent[co2]
ELSE IPCoTab.DeActivateComponent[co2]};
co2.origin ← tOrigin;
co2.prinChannels ← [tSouth, tEast, tNorth, tWest];
co2.cornerChannels ← [tSw, tSe, tNe, tNw];
--(D) Do insertion into surrounding channels
IF co1.active THEN CoTab.InsertComponent[co1, c1P.south, c1P.east, c1P.north, c1P.west, c1C.sw, c1C.se, c1C.ne, c1C.nw];
IF co2.active THEN CoTab.InsertComponent[co2, c2P.south, c2P.east, c2P.north, c2P.west, c2C.sw, c2C.se, c2C.ne, c2C.nw];
END;
ir ← fr ←
NEW[
TOR.RSwapComponentsRep ← [co1, co2]];
--(2) Setup fr and ir.
-- NB: It's its own inverse
top.initialized ← FALSE; --Set Flags to indicate geometry not right
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --SwapComponents
--##Private Procedures##--
InsertCo:
PUBLIC PROC[top: Top.Ref, co: CoTab.Component, chToSplit, negBnd, posBnd:
CTG.Channel, sideHint:
CTG.Side, whichFirstHint: [1..2], keepTrack:
BOOL ←
FALSE]
RETURNS [fr:
TOR.FRInsertCo, ir:
TOR.RAny] ={
newCh1: CTG.Channel;
sideToClHint: CTG.Side;
shrinkDirectn: CTG.ChType ← BO.OTFlip[chToSplit.type];
IF CoTab.CoActive[co] OR (NOT EP.InsertCo1Chk[co, chToSplit, negBnd, posBnd] AND NOT EP.InsertCo2Chk[co, chToSplit, negBnd, posBnd] ) THEN ERROR InvalidArgs[$InsertCo]; --(1) Check args--
fr ← NEW[TOR.FRInsertCoRec ← [co, chToSplit, negBnd, posBnd, sideHint, whichFirstHint]]; --(2a) Setup fr--
SELECT whichFirstHint
FROM
1 => IF NOT EP.InsertCo1Chk[co, chToSplit, negBnd, posBnd] THEN whichFirstHint ← 2;
2 => IF NOT EP.InsertCo2Chk[co, chToSplit, negBnd, posBnd] THEN whichFirstHint ← 1;
ENDCASE => ERROR;
IF whichFirstHint = 1
THEN {
CoTab.ReActivateComponent[co];
newCh1 ← top.CreateChannel[chToSplit.type];
sideToClHint ← EP.InsertCo1[co, chToSplit, negBnd, posBnd, sideHint, newCh1];
ir ← NEW[TOR.IRRemoveCo1Rec ← [co, shrinkDirectn, sideToClHint]]--(2b) Setup ir--}
ELSE {
CoTab.ReActivateComponent[co];
newCh1 ← top.CreateChannel[chToSplit.type];
sideToClHint ← EP.InsertCo2[co, chToSplit, negBnd, posBnd, sideHint, newCh1];
ir ← NEW[TOR.IRRemoveCo2Rec ← [co, shrinkDirectn, sideToClHint]]--(2b) Setup ir--};
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --InsertCo--
RemoveCo:
PUBLIC PROC[top: Top.Ref, co: CoTab.Component, shrinkDirectn:
BO.OrientationTypes, keepTrack:
BOOL ←
FALSE]
RETURNS [fr:
TOR.FRRemoveCo, ir:
TOR.RAny] ={
chToSplit, negBnd, posBnd, newCh1: CTG.Channel;
sideToOpHint: CTG.Side;
IF NOT CoTab.CoActive[co] THEN ERROR InvalidArgs[$RemoveCo]; --(1) Check args--
fr ← NEW[TOR.FRRemoveCoRec ← [co, shrinkDirectn]]; --(2a) Setup fr--
SELECT
TRUE
FROM
EP.RemoveCo1Chk[co, shrinkDirectn] => {[chToSplit, negBnd, posBnd, newCh1, sideToOpHint] ←
EP.RemoveCo1[co, shrinkDirectn, FirstSideToTry];
CoTab.DeActivateComponent[co];
top.DeActivateChannel[newCh1];
ir ← NEW[TOR.IRInsertCo1Rec ← [co, chToSplit, negBnd, posBnd, sideToOpHint, newCh1]]; --(2b) Setup ir--};
EP.RemoveCo2Chk[co, shrinkDirectn] => {[chToSplit, negBnd, posBnd, newCh1, sideToOpHint] ←
EP.RemoveCo2[co, shrinkDirectn, FirstSideToTry];
CoTab.DeActivateComponent[co];
top.DeActivateChannel[newCh1];
ir ← NEW[TOR.IRInsertCo2Rec ← [co, chToSplit, negBnd, posBnd, sideToOpHint, newCh1]]; --(2b) Setup ir--};
ENDCASE => ERROR InvalidArgs[$RemoveCo];
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --RemoveCo--
RemoveCoChk: PROC[co: CoTab.Component, shrinkDirectn: BO.OrientationTypes] RETURNS [BOOL] ={RETURN [EP.RemoveCo1Chk[co, shrinkDirectn] OR EP.RemoveCo2Chk[co, shrinkDirectn]]}; --RemoveCoChk--
Shrink1:
PUBLIC PROC[top: Top.Ref, co: CoTab.Component, keepTrack:
BOOL ←
FALSE]
RETURNS [fr:
TOR.FRShrink1, ir:
TOR.IRInsertCoAtCorner] ={
host: CoTab.Component;
corner: CoTab.CornerTypes;
hCh, vCh: CTG.Channel;
[host, corner] ← Shrink1FindHost[co];
IF NOT Shrink1Chk[co] THEN ERROR InvalidArgs[$Shrink1]; --(1) Check args--
[horCh: hCh, verCh: vCh] ← EP.RemoveCoAtCorner[host, corner];
CoTab.DeActivateComponent[co];
top.DeActivateChannel[hCh];
top.DeActivateChannel[vCh];
fr ← NEW[TOR.FRShrink1Rec ← [co]]; --(2a) Setup fr--
ir ← NEW[TOR.IRInsertCoAtCornerRec ← [host, co, corner, hCh, vCh]]; --(2b) Setup ir--
IF keepTrack THEN PushStacks[top, fr, ir]; --(3) Push Stacks?--
}; --Shrink1--
Shrink1Chk:
PROC[co: CoTab.Component]
RETURNS [
BOOL] ={
host: CoTab.Component;
corner: CoTab.CornerTypes;
[host, corner] ← Shrink1FindHost[co];
IF
NOT CoTab.CoActive[co]
OR host =
NIL
THEN RETURN [FALSE]
ELSE RETURN[EP.RemoveCoAtCornerChk[host, corner]];
}; --Shrink1Chk--
Shrink1FindHost:
PROC [co: CoTab.Component]
RETURNS [host: CoTab.Component ←
NIL, hostCorner: CoTab.CornerTypes ← sw] ={
coCorner: CoTab.CornerTypes ← sw;
findHostProc:
PROC
RETURNS [found:
BOOL] ={
hCh: CTG.Channel ← CoTab.GetPrinCh[co, BO.CTResolveFor[coCorner, hor]];
vCh: CTG.Channel ← CoTab.GetPrinCh[co, BO.CTResolveFor[coCorner, ver]];
IF NOT EO.IsLCorner[hCh, vCh] THEN RETURN [FALSE];
host ← CTG.NthComponent[vCh, BO.CTDirectnFor[coCorner, hor], BO.PTToInt[BO.CTInvDirectnFor[coCorner, ver]]];
IF host = NIL THEN RETURN [FALSE];
hostCorner ← BO.CTDiag[coCorner];
IF
EP.RemoveCoAtCornerChk[host, hostCorner]
THEN RETURN [TRUE]
ELSE RETURN [FALSE];
}; --findHostProc--
THROUGH [0..4)
DO
IF findHostProc[] THEN EXIT;
coCorner ← BO.CTRotate[coCorner];
ENDLOOP;
}; --Shrink1FindHost--
SetComponentChk:
PROC[top: Top.Ref, co: CoTab.Component, active:
BOOL]
RETURNS [
BOOL] ={
RETURN [Top.NoTopology[top] OR active = CoTab.CoActive[co]];
}; --SetComponentChk
SwapComponentsChk:
PROC [top: Top.Ref, co1, co2: CoTab.Component]
RETURNS [
BOOL] ={
IF CoTab.CoActive[co1]
THEN {
FOR corner: CoTab.CornerTypes
IN [sw..nw]
DO
IF CoTab.GetCornerChs[co1, corner] #
NIL
AND CoTab.GetCornerSp[co2, corner] =
NIL
THEN RETURN [FALSE]
ENDLOOP;};
IF CoTab.CoActive[co2]
THEN {
FOR corner: CoTab.CornerTypes
IN [sw..nw]
DO
IF CoTab.GetCornerChs[co2, corner] #
NIL
AND CoTab.GetCornerSp[co1, corner] =
NIL
THEN RETURN [FALSE]
ENDLOOP;};
RETURN [TRUE];
}; --SwapComponentsChk
END.