-- File: DisjointSplit.mesa -- Splits symbols into non-overlapping segements -- Written by Martin Newell/Dan Fitzpatrick February 1981 -- Last edited (Pilot): August 6, 1981 3:46 PM DIRECTORY DisjointGatherDefs: FROM "DisjointGatherDefs" USING [Gather], DisjointSplitDefs: FROM "DisjointSplitDefs", DisjointTypes: FROM "DisjointTypes" USING [DisCell, Symbol, Instance, Rectangle, PIP, Geometry], DisjointAllocDefs: FROM "DisjointAllocDefs" USING [AllocateRectangle, AllocateDisCell, AllocatePIP, FreePIP, AllocateGeometry, FreeGeometry, Alloc, Free], Inline: FROM "Inline" USING [LowHalf]; DisjointSplit: PROGRAM IMPORTS DisjointGatherDefs, DisjointAllocDefs, Inline EXPORTS DisjointSplitDefs = BEGIN OPEN DisjointGatherDefs, DisjointAllocDefs, DisjointTypes, Inline; --PrimInstance Edges PIEdge: TYPE = LONG POINTER TO PIEdgeRecord; PIEdgeRecord: TYPE = RECORD [ next: PIEdge, x,yMin,yMax: REAL, up: BOOLEAN, pi: Instance ]; PIEdgeList,PIActiveList: PIEdge; PIyPrev,PIyCurr,PIyNext: REAL; Split: PUBLIC PROCEDURE[symbol: Symbol] = --This procedure takes a list of PrimInstances, pi, and a list of windows, -- windows, that mask pi, and generates a list of -- disjoint cells, DisCell, within the window. BEGIN pi: Instance _ symbol.insts; windows: Rectangle _ symbol.windows; edge,newPIActiveList,endOfNewPIActiveList:PIEdge; xCurr,pieceL,bottom,top: REAL; PISet: PIP; --list of PrimInstances covering current region of swath dcList: DisCell; StartPiece: PROCEDURE[x: REAL] = BEGIN pieceL _ x; END; EndPiece: PROCEDURE[x,yMin,yMax: REAL, piSet: PIP] = BEGIN newdc: DisCell; copyPISet,copyPISetEnd: PIP; dc: DisCell; IF PISet=NIL THEN RETURN; IF yMin>=yMax OR pieceL>=x THEN RETURN; IF (dc_Exists[piSet])#NIL THEN AddWindow[dc, pieceL,yMin,x,yMax] ELSE { newdc _ AllocateDisCell[]; copyPISet _ copyPISetEnd _ NIL; FOR pi:PIP _ piSet, pi.next UNTIL pi=NIL DO copypi: PIP _ AllocatePIP[]; copypi^ _ [ next: NIL, inst: pi.inst ]; IF copyPISet=NIL THEN copyPISet _ copyPISetEnd _ copypi ELSE { copyPISetEnd.next _ copypi; copyPISetEnd _ copypi; }; ENDLOOP; newdc^ _ [ next: NIL, geom: NIL, --***!!!NOT RIGHT!!! insts: copyPISet, windows: AllocateRectangle[], symbol: NIL ]; newdc.windows^ _ [ next: NIL, l:pieceL, b:yMin, r:x, t:yMax ]; EnterDC[newdc]; }; END; AddToEndOfNewPIActiveList: PROCEDURE[edge: PIEdge] = BEGIN edge.next _ NIL; IF newPIActiveList=NIL THEN newPIActiveList _ endOfNewPIActiveList _ edge ELSE { endOfNewPIActiveList.next _ edge; endOfNewPIActiveList _ edge; } END; IF pi=NIL THEN { PartitionGeometry[symbol, NIL]; --to get clipping to symbol boundary RETURN; }; [PIEdgeList,bottom,top] _ BuildPIEdgeList[pi, windows]; PIActiveList _ newPIActiveList _ endOfNewPIActiveList _ NIL; PIyPrev _ PIyCurr _ bottom; PIyNext _ top; InitDCSet[101]; UNTIL (PIEdgeList=NIL AND PIActiveList=NIL) OR PIyPrev>=top DO --once per swath windowdepth: INTEGER _ 0; PISet _ NIL; FOR edge _ GetPIEdge[], GetPIEdge[] UNTIL edge=NIL DO xCurr _ edge.x; IF PIyCurr>PIyPrev AND edge.yMinPIyCurr THEN { AddToEndOfNewPIActiveList[edge]; PIyNext _ MIN[PIyNext,edge.yMax]; } ELSE FreePIEdge[edge]; ENDLOOP; PIActiveList _ newPIActiveList; newPIActiveList _ NIL; IF PIEdgeList#NIL THEN PIyNext _ MIN[PIyNext,PIEdgeList.yMin]; PIyPrev _ PIyCurr; PIyCurr _ PIyNext; PIyNext _ top; ENDLOOP; dcList _ MakeDCList[]; PartitionGeometry[symbol, dcList]; --PrintDisCells[dcList]; Gather[symbol, dcList]; END; BuildPIEdgeList: PROCEDURE[pi: Instance, windows: Rectangle] RETURNS[edgeList: PIEdge, bottom,top: REAL] = --Build edge list of pi edges and window edges. --Window edges will have a NIL PrimInstance --bottom and top are extrema of all edges --insertion sort for now BEGIN bottom _ windows.b; top _ windows.t; edgeList _ NIL; FOR p:Instance _ pi, p.next UNTIL p=NIL DO s: Symbol _ p.symbol; l: REAL _ s.windows.l+p.xOffset; b: REAL _ s.windows.b+p.yOffset; r: REAL _ s.windows.r+p.xOffset; t: REAL _ s.windows.t+p.yOffset; edgeList _ InsertPIEdges[edgeList, l,b,r,t, p]; bottom _ MIN[bottom,b]; top _ MAX[top,t]; ENDLOOP; FOR rec:Rectangle _ windows, rec.next UNTIL rec=NIL DO edgeList _ InsertPIEdges[edgeList, rec.l,rec.b,rec.r,rec.t, NIL]; bottom _ MIN[bottom,rec.b]; top _ MAX[top,rec.t]; ENDLOOP; END; InsertPIEdges: PROCEDURE[edgeList: PIEdge, l,b,r,t: REAL, pi: Instance] RETURNS[PIEdge] = --Create and insert edges corresponding to given rectangle into edgeList BEGIN e1: PIEdge _ AllocatePIEdge[l,b,t,TRUE,pi]; e2: PIEdge _ AllocatePIEdge[r,b,t,FALSE,pi]; eptr: LONG POINTER TO PIEdge; --find where e1 goes FOR eptr _ @edgeList,@eptr.next UNTIL eptr^=NIL DO IF PIEdgeLessThan[e1,eptr^] THEN EXIT; ENDLOOP; --and insert it e1.next _ eptr^; eptr^ _ e1; --continue search for position of e2 FOR eptr _ eptr,@eptr.next UNTIL eptr^=NIL DO IF PIEdgeLessThan[e2,eptr^] THEN EXIT; ENDLOOP; --and insert it e2.next _ eptr^; eptr^ _ e2; RETURN[edgeList]; END; PIInsert: PROCEDURE[piSet: PIP, pi: Instance] RETURNS[newpiSet: PIP] = -- Simply search for it, for now BEGIN pp: LONG POINTER TO PIP; p: PIP _ NIL; --find where pi goes FOR pp _ @piSet, @pp.next UNTIL pp^=NIL DO p _ pp^; IF p.inst=pi THEN RETURN[piSet]; --already there IF AddressLessThan[pi,p.inst] THEN EXIT; ENDLOOP; --and insert it p _ AllocatePIP[]; p.next _ pp^; p.inst _pi; pp^ _ p; RETURN[piSet]; END; PIRemove: PROCEDURE[piSet: PIP, pi: Instance] RETURNS[newpiSet: PIP] = BEGIN pp: LONG POINTER TO PIP; p: PIP _ NIL; FOR pp _ @piSet, @pp.next UNTIL pp^=NIL DO p _ pp^; IF p.inst=pi THEN EXIT; ENDLOOP; pp^ _ pp.next; IF p#NIL THEN FreePIP[p]; RETURN[piSet]; END; AddressLessThan: PROCEDURE[p1,p2: LONG POINTER] RETURNS[BOOLEAN] = BEGIN c1: LONG CARDINAL _ LOOPHOLE[p1]; c2: LONG CARDINAL _ LOOPHOLE[p2]; RETURN[c1PIyCurr THEN RETURN[NIL] ELSE {edge _ PIEdgeList; PIEdgeList _ PIEdgeList.next} ELSE IF PIEdgeList=NIL OR PIEdgeList.yMin>PIyCurr THEN {edge _ PIActiveList; PIActiveList _ PIActiveList.next} ELSE --both candidates IF PIActiveList.x less, >s2 => greater, ENDCASE => SELECT pi1.xOffset FROM less, >pi2.xOffset => greater, ENDCASE => SELECT pi1.yOffset FROM less, >pi2.yOffset => greater, ENDCASE => equal]; END; PartitionGeometry: PUBLIC PROCEDURE[symbol: Symbol, dcList: DisCell] = --This procedure takes a list of Geometry, symbol.geom, and a list of -- DisCells, dcList. --It partitions the geometry onto the Discells(.geom) by clipping to -- the .windows of each DisCell, and replaces symbol.geom with -- a list of any remaining Geometry, additionally clipped to boundary -- of symbol BEGIN geom: Geometry; inside,outside: Geometry; IF symbol=NIL THEN RETURN; IF symbol.geom=NIL THEN RETURN; geom _ symbol.geom; FOR dc:DisCell _ dcList, dc.next UNTIL dc=NIL DO inside _ NIL; FOR w:Rectangle _ dc.windows, w.next UNTIL w=NIL DO outside _ NIL; UNTIL geom=NIL DO in,out1,outn: Geometry; r: Geometry _ geom; geom _ geom.next; [in,out1,outn] _ Clip[w,r]; IF in#NIL THEN {in.next _ inside; inside _ in;}; IF out1#NIL THEN {outn.next _ outside; outside _ out1;}; ENDLOOP; geom _ outside; ENDLOOP; dc.geom _ inside; ENDLOOP; --geom now contains what's left over after assigning pieces to discells --clip geom to windows of symbol inside _ NIL; FOR w:Rectangle _ symbol.windows, w.next UNTIL w=NIL DO outside _ NIL; UNTIL geom=NIL DO in,out1,outn: Geometry; r: Geometry _ geom; geom _ geom.next; [in,out1,outn] _ Clip[w,r]; IF in#NIL THEN {in.next _ inside; inside _ in;}; IF out1#NIL THEN {outn.next _ outside; outside _ out1;}; ENDLOOP; geom _ outside; ENDLOOP; symbol.geom _ inside; --free geom FOR g:Geometry _ geom,geom UNTIL g=NIL DO geom _ geom.next; FreeGeometry[g]; ENDLOOP; END; Clip: PROCEDURE[w: Rectangle, r: Geometry] RETURNS[in,out1,outn: Geometry] = --Clip rectangle, r, against window, w, and return relevant pieces --out1,outn are head and tail of outside pieces (up to 4) --r will be overwritten to make one of the pieces BEGIN left: REAL _ MAX[w.l,r.l]; bottom: REAL _ MAX[w.b,r.b]; right: REAL _ MIN[w.r,r.r]; top: REAL _ MIN[w.t,r.t]; IF left>=right OR bottom>=top THEN RETURN[NIL,r,r]; --all out out1 _ outn _ NIL; IF bottom#r.b THEN --slice off bottom part { g: Geometry _ AllocateGeometry[]; g^ _ [next:out1, layer:r.layer, l:r.l, b:r.b, r:r.r, t:w.b]; out1 _ g; IF outn=NIL THEN outn _ g; r.b _ w.b; }; IF top#r.t THEN --slice off top part { g: Geometry _ AllocateGeometry[]; g^ _ [next:out1, layer:r.layer, l:r.l, b:w.t, r:r.r, t:r.t]; out1 _ g; IF outn=NIL THEN outn _ g; r.t _ w.t; }; IF left#r.l THEN --slice off left part { g: Geometry _ AllocateGeometry[]; g^ _ [next:out1, layer:r.layer, l:r.l, b:r.b, r:w.l, t:r.t]; out1 _ g; IF outn=NIL THEN outn _ g; r.l _ w.l; }; IF right#r.r THEN --slice off right part { g: Geometry _ AllocateGeometry[]; g^ _ [next:out1, layer:r.layer, l:w.r, b:r.b, r:r.r, t:r.t]; out1 _ g; IF outn=NIL THEN outn _ g; r.r _ w.r; }; --r now contains inside part RETURN[r,out1,outn]; END; END. (635)\183b4B412b13B403b5B458b10B53b8B869b25B1669b15B825b13B664b8B421b8B268b15B152b9B642b14B121b9B67b6B291b7B129b10B313b13B234b9B508b4B225b14B215b10B77b16B674b17B1559b4B