<> <> <> <> <<>> DIRECTORY Atom, CD, CDBasics, CDMEBES, CStitching, IO; CDMEBESGeomFns: CEDAR PROGRAM IMPORTS Atom, CDBasics, CDMEBES, CStitching, IO = BEGIN OPEN CDMEBES; NOTFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Nm _ 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- = BEGIN ComplementTile: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = {result.ChangeRect[CDBasics.Intersection[CDBasics.universe, tile.Area], $covered]}; basis: Tesselation _ GenerateCover[ms, spec.first, extInfluenceDiameter]; result _ NewTesselation[NIL]; [] _ basis.EnumerateArea[rect: CDBasics.universe, eachTile: ComplementTile, skip: $covered]; basis _ DisposeTesselation[basis]; END; ANDFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Nm _ 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- = BEGIN NilTile: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = {result.ChangeRect[CDBasics.Intersection[CDBasics.universe, tile.Area], NIL]}; result _ GenerateCover[ms, spec.first, extInfluenceDiameter]; FOR rest: LIST OF REF ANY _ spec.rest, rest.rest WHILE rest # NIL DO term: Tesselation _ GenerateCover[ms, rest.first, extInfluenceDiameter]; [] _ term.EnumerateArea[rect: CDBasics.universe, eachTile: NilTile, skip: $covered]; term _ DisposeTesselation[term]; ENDLOOP; END; ANDNOTFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Nm _ 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- = BEGIN NilTile: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = {result.ChangeRect[CDBasics.Intersection[CDBasics.universe, tile.Area], NIL]}; result _ GenerateCover[ms, spec.first, extInfluenceDiameter]; FOR rest: LIST OF REF ANY _ spec.rest, rest.rest WHILE rest # NIL DO term: Tesselation _ GenerateCover[ms, rest.first, extInfluenceDiameter]; [] _ term.EnumerateArea[rect: CDBasics.universe, eachTile: NilTile, skip: NIL]; term _ DisposeTesselation[term]; ENDLOOP; END; ORFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Nm _ 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- = BEGIN <> CoverTile: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = {result.ChangeRect[tile.Area, $covered]}; layers: LIST OF CDLayer _ NIL; otherThings: LIST OF REF ANY _ NIL; FOR subList: LIST OF REF ANY _ spec, subList.rest WHILE subList # NIL DO WITH subList.first SELECT FROM layer: CDLayer => IF layer.deltaDiameter >= 0 THEN layers _ CONS[layer, layers] ELSE otherThings _ CONS[layer, otherThings]; ENDCASE => otherThings _ CONS[subList.first, otherThings]; ENDLOOP; IF otherThings = NIL THEN result _ NewTesselation[NIL] ELSE BEGIN result _ GenerateCover[ms, otherThings.first, extInfluenceDiameter]; FOR rest: LIST OF REF ANY _ otherThings.rest, rest.rest WHILE rest # NIL DO term: Tesselation _ GenerateCover[ms, rest.first, extInfluenceDiameter]; [] _ term.EnumerateArea[rect: CDBasics.universe, eachTile: CoverTile]; term _ DisposeTesselation[term]; ENDLOOP; END; IF layers # NIL THEN DrawLayersWithPosDeltas[ms: ms, rects: result, layers: layers, extInfluenceDiameter: extInfluenceDiameter]; END; RunRec: TYPE = RECORD [ desc: ROPE, areaInSqMeters: REAL _ 0, perimInMeters: Meters _ 0.0, runsInMeters: ARRAY Sense OF RECORD [ sense: ROPE, r: REF RunArray ] ]; RunArray: TYPE = RECORD [ ra: SEQUENCE size: NAT OF Meters ]; MeasureRuns: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Nm _ 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- = BEGIN PixelRunArray: TYPE = RECORD [ ra: SEQUENCE size: NAT OF MEBESPixels ]; PixelCoverRec: TYPE = RECORD [ sense: ROPE, maxInterestDist, minFeature: MEBESPixels _ 0, r: REF PixelRunArray ]; areaInSqPixels: INT _ 0; perimInPixels: MEBESPixels _ 0; table: ARRAY Sense OF REF PixelCoverRec _ ALL[NIL]; runRef: REF RunRec _ NIL; -- for external consumption mebesPixelPitch: Meters _ ms.mebesPixelPitch -- nm -- *1.0E-9; LookForRuns: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = BEGIN ComplainAboutFeature: PROC [ dia: MEBESPixels, pos: MEBESPosition ] = BEGIN chose: NAT = ComplainAt[ms: ms, pos: pos, explanation: IO.PutFR["Too-small %g", IO.rope[c.sense]], choice: LIST ["Reduce min feature", "Proceed"]]; SELECT chose FROM 1 => c.minFeature _ dia; ENDCASE => NULL; END; EWRuns: PROC [ cov: CStitching.Tile, x1, x2: MEBESPixels ] = BEGIN IF cov.NEdge < keyTileArea.y2+c.maxInterestDist THEN BEGIN covHeight: MEBESPixels = cov.NEdge-keyTileArea.y2; FOR tile: CStitching.Tile _ cov.EN, tile.SW WHILE x1 < tile.EEdge DO tx1: MEBESPixels = MAX[x1, tile.WEdge]; tx2: MEBESPixels = MIN[x2, tile.EEdge]; SELECT TRUE FROM tx2 <= tx1 => NULL; tile.value # keyTilevalue => BEGIN IF covHeight = 0 THEN perimInPixels _ perimInPixels+(tx2-tx1); EWRuns[cov: tile, x1: tx1, x2: tx2]; END; covHeight >= c.minFeature => c.r[covHeight] _ c.r[covHeight]+(tx2-tx1); covHeight > 0 => -- IN (0..minFeature) -- BEGIN ComplainAboutFeature[covHeight, [x: (tx1+tx2)/2, y: (cov.NEdge+keyTileArea.y2)/2]]; c.r[covHeight] _ c.r[covHeight]+(tx2-tx1); END; ENDCASE => NULL; ENDLOOP; END; END; -- of EWRuns NSRuns: PROC [ cov: CStitching.Tile, y1, y2: MEBESPixels ] = BEGIN IF cov.EEdge < keyTileArea.x2+c.maxInterestDist THEN BEGIN covWidth: MEBESPixels = cov.EEdge-keyTileArea.x2; FOR tile: CStitching.Tile _ cov.NE, tile.WS WHILE y1 < tile.NEdge DO ty1: MEBESPixels = MAX[y1, tile.SEdge]; ty2: MEBESPixels = MIN[y2, tile.NEdge]; SELECT TRUE FROM ty2 <= ty1 => NULL; tile.value # keyTilevalue => BEGIN IF covWidth = 0 THEN perimInPixels _ perimInPixels+(ty2-ty1); NSRuns[cov: tile, y1: ty1, y2: ty2]; END; covWidth >= c.minFeature => c.r[covWidth] _ c.r[covWidth]+(ty2-ty1); covWidth > 0 => -- IN (0..minFeature) -- BEGIN ComplainAboutFeature[covWidth, [x: (cov.EEdge+keyTileArea.x2)/2, y: (ty1+ty2)/2]]; c.r[covWidth] _ c.r[covWidth]+(ty2-ty1); END; ENDCASE => NULL; ENDLOOP; END; END; -- of NSRuns keyTilevalue: REF ANY = tile.value; c: REF PixelCoverRec = table[(IF keyTilevalue = NIL THEN cover ELSE space)]; keyTileArea: CStitching.Rect = tile.Area; clippedKeyTileArea: CStitching.Rect = CDBasics.Intersection[ms.mebesStripeClip, keyTileArea]; IF keyTilevalue # NIL THEN areaInSqPixels _ areaInSqPixels+ (clippedKeyTileArea.x2-clippedKeyTileArea.x1)* (clippedKeyTileArea.y2-clippedKeyTileArea.y1); <> IF keyTileArea.y2 IN (ms.mebesStripeClip.y1 .. ms.mebesStripeClip.y2] THEN EWRuns[cov: tile, x1: clippedKeyTileArea.x1, x2: clippedKeyTileArea.x2]; IF keyTileArea.x2 IN (ms.mebesStripeClip.x1 .. ms.mebesStripeClip.x2] THEN NSRuns[cov: tile, y1: clippedKeyTileArea.y1, y2: clippedKeyTileArea.y2]; END; -- of LookForRuns GetCoverRec: PROC [sense: ROPE, l: LIST OF REF ANY] RETURNS [c: REF PixelCoverRec] = BEGIN c _ NEW[PixelCoverRec _ [sense: sense]]; c.maxInterestDist _ NARROW[l.first, REF Nm]^/ms.mebesPixelPitch; c.minFeature _ NARROW[l.rest.first, REF Nm]^/ms.mebesPixelPitch; c.r _ NEW[PixelRunArray[c.maxInterestDist]]; FOR width: MEBESPixels IN [0..c.r.size) DO c.r[width] _ 0; ENDLOOP; END; table[cover] _ GetCoverRec["cover", spec.rest.rest]; table[space] _ GetCoverRec["space", spec.rest.rest.rest.rest]; result _ GenerateCover[ms, spec.rest.first, extInfluenceDiameter+MAX[table[cover].maxInterestDist, table[space].maxInterestDist]]; [] _ result.EnumerateArea[rect: ms.mebesStripeClip, eachTile: LookForRuns, skip: $none]; ms.data _ runRef _ NEW[RunRec _ [ desc: NARROW[spec.first], areaInSqMeters: areaInSqPixels*mebesPixelPitch*mebesPixelPitch, perimInMeters: perimInPixels*mebesPixelPitch, runsInMeters: [ space: [sense: "space", r: NEW[RunArray[table[space].r.size]]], cover: [sense: "cover", r: NEW[RunArray[table[cover].r.size]]] ] ]]; FOR sense: Sense IN Sense DO FOR width: MEBESPixels IN [0..table[sense].r.size) DO runRef.runsInMeters[sense].r[width] _ table[sense].r[width]*mebesPixelPitch; ENDLOOP; ENDLOOP; END; RestrictedEnlarge: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Nm _ 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- = BEGIN PlaceNImplant: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = BEGIN InteractWithPImplant: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = BEGIN Relationship: TYPE = {pNn, pEn, pSn, pWn}; pTile: CStitching.Tile = tile; pTileArea: MEBESRect = pTile.Area; bestDir: Relationship; bestGap: MEBESPixels _ -1; tGap: MEBESPixels; gaps: ARRAY Relationship OF MEBESPixels _ ALL[maxRadialExtension]; deInsertedArea: MEBESRect; IF (tGap _ nTileArea.x1-pTileArea.x2)>bestGap THEN {bestDir _ $pWn; bestGap _ tGap}; IF (tGap _ pTileArea.x1-nTileArea.x2)>bestGap THEN {bestDir _ $pEn; bestGap _ tGap}; IF (tGap _ nTileArea.y1-pTileArea.y2)>bestGap THEN {bestDir _ $pSn; bestGap _ tGap}; IF (tGap _ pTileArea.y1-nTileArea.y2)>bestGap THEN {bestDir _ $pNn; bestGap _ tGap}; IF bestGap<0 THEN ERROR; -- design rule violation IF NOT anyInteractingPImplant THEN BEGIN anyInteractingPImplant _ TRUE; nImplPieces.ChangeRect[CDBasics.universe, NIL]; nImplPieces.ChangeRect[desiredNImplant, $covered]; END; gaps[bestDir] _ bestGap/2; deInsertedArea _ [x1: pTileArea.x1-gaps[$pEn], y1: pTileArea.y1-gaps[$pNn], x2: pTileArea.x2+gaps[$pWn], y2: pTileArea.y2+gaps[$pSn]]; IF CDBasics.NonEmpty[deInsertedArea] THEN nImplPieces.ChangeRect[deInsertedArea, NIL]; END; CoverNegotiatedPiece: PROCEDURE [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = {area: MEBESRect = tile.Area; result.ChangeRect[area, $covered]}; nTile: CStitching.Tile = tile; nTileArea: MEBESRect = nTile.Area; desiredNImplant: MEBESRect = CDBasics.Extend[nTileArea, maxRadialExtension]; anyInteractingPImplant: BOOL _ FALSE; [] _ pDif.EnumerateArea[rect: CDBasics.Extend[nTileArea, 2*maxRadialExtension], eachTile: InteractWithPImplant]; IF NOT anyInteractingPImplant THEN result.ChangeRect[desiredNImplant, $covered] ELSE [] _ nImplPieces.EnumerateArea[desiredNImplant, CoverNegotiatedPiece]; END; maxRadialExtension: MEBESPixels = NARROW[spec.first, REF Nm]^/ms.mebesPixelPitch; nDif: Tesselation _ GenerateCover[ms, spec.rest.first, extInfluenceDiameter+2*maxRadialExtension]; pDif: Tesselation _ GenerateCover[ms, spec.rest.rest.first, extInfluenceDiameter+2*maxRadialExtension]; nImplPieces: Tesselation _ NewTesselation[]; result _ NewTesselation[]; [] _ nDif.EnumerateArea[rect: CDBasics.universe, eachTile: PlaceNImplant]; nDif _ DisposeTesselation[nDif]; pDif _ DisposeTesselation[pDif]; nImplPieces _ DisposeTesselation[nImplPieces]; END; EnlargeFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Nm _ 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- = BEGIN deltaDiameterNm: Nm = NARROW[spec.first, REF Nm]^; deltaDiameterPixels: MEBESPixels = deltaDiameterNm/ms.mebesPixelPitch; SELECT deltaDiameterPixels FROM =0 => result _ GenerateCover[ms, spec.rest.first, extInfluenceDiameter]; >0 => BEGIN EnlargeTile: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = {result.ChangeRect[Bloat[tile.Area, deltaDiameterPixels], tile.value]}; basis: Tesselation _ GenerateCover[ms, spec.rest.first, extInfluenceDiameter+deltaDiameterNm]; result _ NewTesselation[NIL]; [] _ basis.EnumerateArea[rect: CDBasics.universe, eachTile: EnlargeTile]; basis _ DisposeTesselation[basis]; END; <0 => BEGIN EnlargeGap: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = {result.ChangeRect[CDBasics.Intersection[CDBasics.universe, Bloat[tile.Area, -deltaDiameterPixels]], tile.value]}; basis: Tesselation _ GenerateCover[ms, spec.rest.first, extInfluenceDiameter-deltaDiameterNm]; result _ NewTesselation[NIL]; result.ChangeRect[CDBasics.universe, $covered]; [] _ basis.EnumerateArea[rect: CDBasics.universe, eachTile: EnlargeGap, skip: $covered]; basis _ DisposeTesselation[basis]; END; ENDCASE => ERROR; END; DeNotchFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Nm _ 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- = BEGIN deltaDiams: ARRAY [-1..2] OF Nm _ ALL[0]; ndd: [0..2]; newSpec: REF; FOR ndd_0, ndd+1 WHILE ndd<2 DO WITH spec.first SELECT FROM rnm: REF Nm => {deltaDiams[ndd] _ rnm^; spec _ spec.rest}; ENDCASE => EXIT; ENDLOOP; newSpec _ spec.first; FOR i: [0..2] IN [0..ndd] DO IF deltaDiams[i] # deltaDiams[i-1] THEN newSpec _ LIST[$Enlarge, NEW[Nm _ (deltaDiams[i]-deltaDiams[i-1])], newSpec]; ENDLOOP; result _ GenerateCover[ms, newSpec, extInfluenceDiameter]; END; SizeLEqFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Nm _ 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- = <<>> <> <<>> BEGIN sieveWidth: Nm = NARROW[spec.first, REF Nm]^; sieveHeight: Nm = NARROW[spec.rest.first, REF Nm]^; sieveWidthPixels: MEBESPixels = MAX[sieveWidth, sieveHeight]/ms.mebesPixelPitch; sieveHeightPixels: MEBESPixels = MIN[sieveWidth, sieveHeight]/ms.mebesPixelPitch; BEGIN SizeFilterTile: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = { tileWidth: MEBESPixels; tileHeight: MEBESPixels; IsolatedTile: PROC [tile: CStitching.Tile] RETURNS [b:BOOLEAN] ~ { <> <> en: CStitching.Tile _ tile.EN; ws: CStitching.Tile _ tile.WS; b _ ( (en.value # tile.value) AND (en.WEdge < tile.WEdge) AND (ws.value # tile.value) AND (ws.EEdge > tile.EEdge) ); }; tileWidth _ MAX[(tile.EEdge - tile.WEdge), (tile.NEdge - tile.SEdge)]; tileHeight _ MIN[(tile.EEdge - tile.WEdge), (tile.NEdge - tile.SEdge)]; IF ( IsolatedTile[tile] AND (sieveWidthPixels >= tileWidth) AND (sieveHeightPixels >= tileHeight) ) THEN result.ChangeRect[rect: tile.Area, new: $covered]; }; result _ CStitching.NewTesselation[]; [] _ CStitching.EnumerateArea[ plane: GenerateCover[ms, spec.rest.rest.first, extInfluenceDiameter], rect: CDBasics.universe, eachTile: SizeFilterTile]; END; END; Init: PROC = BEGIN Atom.PutProp[$CDMEBESCoverProcs, $NOT, NEW[CoverProc _ NOTFn]]; Atom.PutProp[$CDMEBESCoverProcs, $AND, NEW[CoverProc _ ANDFn]]; Atom.PutProp[$CDMEBESCoverProcs, $ANDNOT, NEW[CoverProc _ ANDNOTFn]]; Atom.PutProp[$CDMEBESCoverProcs, $OR, NEW[CoverProc _ ORFn]]; Atom.PutProp[$CDMEBESCoverProcs, $MeasureRuns, NEW[CoverProc _ MeasureRuns]]; Atom.PutProp[$CDMEBESCoverProcs, $RestrictedEnlarge, NEW[CoverProc _ RestrictedEnlarge]]; Atom.PutProp[$CDMEBESCoverProcs, $Enlarge, NEW[CoverProc _ EnlargeFn]]; Atom.PutProp[$CDMEBESCoverProcs, $DeNotch, NEW[CoverProc _ DeNotchFn]]; Atom.PutProp[$CDMEBESCoverProcs, $SizeLEq, NEW[CoverProc _ SizeLEqFn]]; END; Init[]; END. -- of CDMEBESGeomFns <<>>