<> <> <> <> <> <<>> DIRECTORY Atom, CD, CDBasics, CDMEBES, CStitching, IO; CDMEBESGeomFns: CEDAR PROGRAM IMPORTS Atom, CDBasics, CDMEBES, CStitching, IO = BEGIN OPEN CDMEBES; <<**** S U P P O R T R O U T I N E S ****>> Direction: TYPE = {N, E, S, W} _ N; reverseDirection: ARRAY Direction OF Direction _ [N: S, E: W, S: N, W: E]; Juxtaposition: PROC [ a, b: TadRect ] RETURNS [ aVsB: Direction _ N, biggestGap: Tad _ -1 ] = { tGap: Tad; IF (tGap _ b.x1-a.x2) > biggestGap THEN {aVsB _ W; biggestGap _ tGap}; IF (tGap _ a.x1-b.x2) > biggestGap THEN {aVsB _ E; biggestGap _ tGap}; IF (tGap _ b.y1-a.y2) > biggestGap THEN {aVsB _ S; biggestGap _ tGap}; IF (tGap _ a.y1-b.y2) > biggestGap THEN {aVsB _ N; biggestGap _ tGap}; }; ScanNeighborhood: PROC [ proc: PROC [z1, z2, depth: Tad], mother: CStitching.Tile, p1, p2: TadPair, depthLimit: Tad, continueValue: REF _ NIL ] = { InnerDepthScanS: PROC [ tile: CStitching.Tile, z1, z2: Tad ] = { <<-- z1 < z2>> curDepth: Tad = p1.y - tile.NEdge; IF curDepth >= depthLimit THEN proc[z1, z2, depthLimit] ELSE { FOR tileSouth: CStitching.Tile _ tile.WS, tileSouth.NE WHILE tileSouth.WEdge < z2 DO IF tileSouth.EEdge > z1 THEN { IF (curDepth > 0) AND (tileSouth.value # continueValue) THEN proc[z1, z2, curDepth] ELSE InnerDepthScanS[tileSouth, MAX[z1, tileSouth.WEdge], MIN[z2, tileSouth.EEdge]]; }; ENDLOOP; }; }; InnerDepthScanN: PROC [ tile: CStitching.Tile, z1, z2: Tad ] = { <<-- z1 < z2>> curDepth: Tad = tile.SEdge - p1.y; IF curDepth >= depthLimit THEN proc[z1, z2, depthLimit] ELSE { FOR tileNorth: CStitching.Tile _ tile.EN, tileNorth.SW WHILE tileNorth.EEdge > z1 DO IF tileNorth.WEdge < z2 THEN { IF (curDepth > 0) AND (tileNorth.value # continueValue) THEN proc[z1, z2, curDepth] ELSE InnerDepthScanN[tileNorth, MAX[z1, tileNorth.WEdge], MIN[z2, tileNorth.EEdge]]; }; ENDLOOP; }; }; InnerDepthScanE: PROC [ tile: CStitching.Tile, z1, z2: Tad ] = { <<-- z1 < z2>> curDepth: Tad = tile.WEdge - p1.x; IF curDepth >= depthLimit THEN proc[z1, z2, depthLimit] ELSE { FOR tileEast: CStitching.Tile _ tile.NE, tileEast.WS WHILE tileEast.NEdge > z1 DO IF tileEast.SEdge < z2 THEN { IF (curDepth > 0) AND (tileEast.value # continueValue) THEN proc[z1, z2, curDepth] ELSE InnerDepthScanE[tileEast, MAX[z1, tileEast.SEdge], MIN[z2, tileEast.NEdge]]; }; ENDLOOP; }; }; InnerDepthScanW: PROC [ tile: CStitching.Tile, z1, z2: Tad ] = { <<-- z1 < z2>> curDepth: Tad = p1.x - tile.EEdge; IF curDepth >= depthLimit THEN proc[z1, z2, depthLimit] ELSE { FOR tileWest: CStitching.Tile _ tile.SW, tileWest.EN WHILE tileWest.SEdge < z2 DO IF tileWest.NEdge > z1 THEN { IF (curDepth > 0) AND (tileWest.value # continueValue) THEN proc[z1, z2, curDepth] ELSE InnerDepthScanW[tileWest, MAX[z1, tileWest.SEdge], MIN[z2, tileWest.NEdge]]; }; ENDLOOP; }; }; < p2.>> SELECT (p2.x - p1.x) FROM > 0 => {IF p2.y # p1.y THEN ERROR; InnerDepthScanS[mother, p1.x, p2.x]}; < 0 => {IF p2.y # p1.y THEN ERROR; InnerDepthScanN[mother, p2.x, p1.x]}; ENDCASE => SELECT (p2.y - p1.y) FROM > 0 => InnerDepthScanE[mother, p1.y, p2.y]; < 0 => InnerDepthScanW[mother, p2.y, p1.y]; ENDCASE => ERROR; }; <<***** M A S K O P E R A T I O N R O U T I N E S *****>> NOTFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Tad _ 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: Tad _ 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: Tad _ 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: Tad _ 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: Tad _ 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- = BEGIN PixelRunArray: TYPE = RECORD [ ra: SEQUENCE size: NAT OF MEBESPixels ]; TadCoverRec: TYPE = RECORD [ sense: ROPE, maxInterestDist, minFeature: Tad _ 0, r: REF PixelRunArray ]; areaInSqPixels: INT _ 0; perimInPixels: MEBESPixels _ 0; table: ARRAY Sense OF REF TadCoverRec _ ALL[NIL]; runRef: REF RunRec _ NIL; -- for external consumption mebesPixelPitch: Meters _ ms.mebesPixelPitch -- nm -- *1.0E-9; tadsPerPixel: Tad = ms.mebesPixelPitch*ms.tadsPerNm; LookForRuns: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = BEGIN ComplainAboutFeature: PROC [ dia: Tad, pos: TadPosition ] = 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: Tad ] = BEGIN IF cov.NEdge < keyTileArea.y2+c.maxInterestDist THEN BEGIN covHeightTads: Tad = cov.NEdge-keyTileArea.y2; covHeightPixels: MEBESPixels = covHeightTads/tadsPerPixel; FOR tile: CStitching.Tile _ cov.EN, tile.SW WHILE x1 < tile.EEdge DO tx1: Tad = MAX[x1, tile.WEdge]; tx2: Tad = MIN[x2, tile.EEdge]; dxPixels: MEBESPixels = (tx2-tx1)/tadsPerPixel; SELECT TRUE FROM tx2 <= tx1 => NULL; tile.value # keyTilevalue => BEGIN IF covHeightTads = 0 THEN perimInPixels _ perimInPixels+dxPixels; EWRuns[cov: tile, x1: tx1, x2: tx2]; END; covHeightTads >= c.minFeature => c.r[covHeightPixels] _ c.r[covHeightPixels]+dxPixels; covHeightTads > 0 => -- IN (0..minFeature) -- BEGIN ComplainAboutFeature[covHeightTads, [x: (tx1+tx2)/2, y: (cov.NEdge+keyTileArea.y2)/2]]; c.r[covHeightPixels] _ c.r[covHeightPixels]+dxPixels; END; ENDCASE => NULL; ENDLOOP; END; END; -- of EWRuns NSRuns: PROC [ cov: CStitching.Tile, y1, y2: Tad ] = BEGIN IF cov.EEdge < keyTileArea.x2+c.maxInterestDist THEN BEGIN covWidthTads: Tad = cov.EEdge-keyTileArea.x2; covWidthPixels: MEBESPixels = covWidthTads/tadsPerPixel; 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]; dyPixels: MEBESPixels = (ty2-ty1)/tadsPerPixel; SELECT TRUE FROM ty2 <= ty1 => NULL; tile.value # keyTilevalue => BEGIN IF covWidthTads = 0 THEN perimInPixels _ perimInPixels+dyPixels; NSRuns[cov: tile, y1: ty1, y2: ty2]; END; covWidthTads >= c.minFeature => c.r[covWidthPixels] _ c.r[covWidthPixels]+dyPixels; covWidthTads > 0 => -- IN (0..minFeature) -- BEGIN ComplainAboutFeature[covWidthTads, [x: (cov.EEdge+keyTileArea.x2)/2, y: (ty1+ty2)/2]]; c.r[covWidthPixels] _ c.r[covWidthPixels]+dyPixels; END; ENDCASE => NULL; ENDLOOP; END; END; -- of NSRuns keyTilevalue: REF ANY = tile.value; c: REF TadCoverRec = table[(IF keyTilevalue = NIL THEN cover ELSE space)]; keyTileArea: TadRect = tile.Area; clippedKeyTileArea: TadRect = CDBasics.Intersection[ms.tadStripeClip, keyTileArea]; IF keyTilevalue # NIL THEN areaInSqPixels _ areaInSqPixels+ ((clippedKeyTileArea.x2-clippedKeyTileArea.x1)/tadsPerPixel)* ((clippedKeyTileArea.y2-clippedKeyTileArea.y1)/tadsPerPixel); <> IF keyTileArea.y2 IN (ms.tadStripeClip.y1 .. ms.tadStripeClip.y2] THEN EWRuns[cov: tile, x1: clippedKeyTileArea.x1, x2: clippedKeyTileArea.x2]; IF keyTileArea.x2 IN (ms.tadStripeClip.x1 .. ms.tadStripeClip.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 TadCoverRec] = BEGIN c _ NEW[TadCoverRec _ [sense: sense]]; c.maxInterestDist _ NARROW[l.first, REF Nm]^*ms.tadsPerNm; c.minFeature _ NARROW[l.rest.first, REF Nm]^*ms.tadsPerNm; c.r _ NEW[PixelRunArray[c.maxInterestDist/(ms.mebesPixelPitch*ms.tadsPerNm)]]; 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.tadStripeClip, 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: Tad _ 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 pTile: CStitching.Tile = tile; pTileArea: TadRect = pTile.Area; aVsB: Direction; biggestGap: Tad _ -1; gaps: ARRAY Direction OF Tad _ ALL[maxRadialExtension]; deInsertedArea: TadRect; [aVsB, biggestGap] _ Juxtaposition[a: pTileArea, b: nTileArea]; IF biggestGap<0 THEN ERROR; -- design rule violation IF NOT anyInteractingPImplant THEN BEGIN anyInteractingPImplant _ TRUE; nImplPieces.ChangeRect[CDBasics.universe, NIL]; nImplPieces.ChangeRect[desiredNImplant, $covered]; END; gaps[aVsB] _ biggestGap/2; deInsertedArea _ [x1: pTileArea.x1-gaps[E], y1: pTileArea.y1-gaps[N], x2: pTileArea.x2+gaps[W], y2: pTileArea.y2+gaps[S]]; IF CDBasics.NonEmpty[deInsertedArea] THEN nImplPieces.ChangeRect[deInsertedArea, NIL]; END; CoverNegotiatedPiece: PROCEDURE [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = {area: TadRect = tile.Area; result.ChangeRect[area, $covered]}; nTile: CStitching.Tile = tile; nTileArea: TadRect = nTile.Area; desiredNImplant: TadRect = 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: Tad = NARROW[spec.first, REF Nm]^*ms.tadsPerNm; 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; EnlargeSparse: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Tad _ 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- = BEGIN EnlargeToThe: PROC [ curDir: Direction, sideSpacing: Tad ] = { Enlarge: PROC [tile: CStitching.Tile, data: REF] -- CStitching.TileProc -- = { tileArea: TadRect = tile.Area; enlargedArea: TadRect = [ x1: tile.WEdge-enlargeTable[W], y1: tile.SEdge-enlargeTable[S], x2: tile.EEdge+enlargeTable[E], y2: tile.NEdge+enlargeTable[N]]; result.ChangeRect[enlargedArea, $covered]; }; Clip: PROC [tile: CStitching.Tile, data: REF] -- CStitching.TileProc -- = { ClipS: PROC [tile: CStitching.Tile, data: REF] -- CStitching.TileProc -- = { <> x1: Tad = MAX[tile.WEdge, clipBasisTile.WEdge]; x2: Tad = MIN[tile.EEdge, clipBasisTile.EEdge]; IF x1 < x2 THEN result.ChangeRect[[x1: x1-sideSpacing, y1: clipBasisTile.SEdge-minSpacing, x2: x2+sideSpacing, y2: clipBasisTile.SEdge], NIL]; }; ClipN: PROC [tile: CStitching.Tile, data: REF] -- CStitching.TileProc -- = { <> x1: Tad = MAX[tile.WEdge, clipBasisTile.WEdge]; x2: Tad = MIN[tile.EEdge, clipBasisTile.EEdge]; IF x1 < x2 THEN result.ChangeRect[[x1: x1-sideSpacing, y1: clipBasisTile.NEdge, x2: x2+sideSpacing, y2: clipBasisTile.NEdge+minSpacing], NIL]; }; ClipW: PROC [tile: CStitching.Tile, data: REF] -- CStitching.TileProc -- = { <> y1: Tad = MAX[tile.SEdge, clipBasisTile.SEdge]; y2: Tad = MIN[tile.NEdge, clipBasisTile.NEdge]; IF y1 < y2 THEN result.ChangeRect[[x1: clipBasisTile.WEdge-minSpacing, y1: y1-sideSpacing, x2: clipBasisTile.WEdge, y2: y2+sideSpacing], NIL]; }; ClipE: PROC [tile: CStitching.Tile, data: REF] -- CStitching.TileProc -- = { <> y1: Tad = MAX[tile.SEdge, clipBasisTile.SEdge]; y2: Tad = MIN[tile.NEdge, clipBasisTile.NEdge]; IF y1 < y2 THEN result.ChangeRect[[x1: clipBasisTile.EEdge, y1: y1-sideSpacing, x2: clipBasisTile.EEdge+minSpacing, y2: y2+sideSpacing], NIL]; }; clipBasisTile: CStitching.Tile = tile; basis.EnumerateNeighborhood[tile: tile, eachTileS: (IF curDir = N THEN ClipS ELSE NIL), eachTileW: (IF curDir = E THEN ClipW ELSE NIL), eachTileN: (IF curDir = S THEN ClipN ELSE NIL), eachTileE: (IF curDir = W THEN ClipE ELSE NIL), skip: $covered]; }; IncludeOriginal: PROC [tile: CStitching.Tile, data: REF] -- CStitching.TileProc -- = { tileArea: TadRect = tile.Area; result.ChangeRect[tile.Area, $covered]; }; enlargeTable: ARRAY Direction OF Tad; FOR d: Direction IN Direction DO enlargeTable[d] _ (IF d = curDir THEN maxRadialEnlargement ELSE 0); ENDLOOP; result _ CStitching.NewTesselation[]; basis.EnumerateArea[rect: CDBasics.universe, eachTile: Enlarge]; basis.EnumerateArea[rect: CDBasics.universe, eachTile: Clip]; basis.EnumerateArea[rect: CDBasics.universe, eachTile: IncludeOriginal]; basis _ DisposeTesselation[basis]; basis _ result; }; maxRadialEnlargement: Tad = NARROW[spec.first, REF Nm]^*ms.tadsPerNm; minSpacing: Tad = NARROW[spec.rest.first, REF Nm]^*ms.tadsPerNm; basis: Tesselation _ GenerateCover[ms, spec.rest.rest.first, extInfluenceDiameter+2*maxRadialEnlargement+minSpacing]; EnlargeToThe[N, minSpacing+2*maxRadialEnlargement]; EnlargeToThe[S, minSpacing+2*maxRadialEnlargement]; EnlargeToThe[E, minSpacing]; EnlargeToThe[W, minSpacing]; basis _ NIL; END; EnlargeFn: PROC [ ms: MaskState, spec: LIST OF REF ANY, extInfluenceDiameter: Tad _ 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- = BEGIN deltaDiameterNm: Nm = NARROW[spec.first, REF Nm]^; deltaDiameterTads: MEBESPixels = deltaDiameterNm*ms.tadsPerNm; SELECT deltaDiameterTads 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, deltaDiameterTads], tile.value]}; basis: Tesselation _ GenerateCover[ms, spec.rest.first, extInfluenceDiameter+deltaDiameterTads]; 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, -deltaDiameterTads]], tile.value]}; basis: Tesselation _ GenerateCover[ms, spec.rest.first, extInfluenceDiameter-deltaDiameterTads]; 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: Tad _ 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: Tad _ 0 ] RETURNS [ result: Tesselation ] -- CoverProc -- = <<>> <> <<>> BEGIN sieveWidth: Nm = NARROW[spec.first, REF Nm]^; sieveHeight: Nm = NARROW[spec.rest.first, REF Nm]^; sieveWidthTads: MEBESPixels = MAX[sieveWidth, sieveHeight]*ms.tadsPerNm; sieveHeightTads: MEBESPixels = MIN[sieveWidth, sieveHeight]*ms.tadsPerNm; BEGIN SizeFilterTile: PROC [tile: CStitching.Tile, data: REF ANY] -- CStitching.PerTileProc -- = { tileWidth, tileHeight: Tad; 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 (sieveWidthTads >= tileWidth) AND (sieveHeightTads >= 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, $EnlargeSparse, NEW[CoverProc _ EnlargeSparse]]; 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 <<>>