CornerBasedDRCImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Redesign of some spinifex internals, originaly from Mark Shand
Created by Christian Jacobi, December 13, 1985 11:06:49 am PST
Last edited by: Christian Jacobi, December 2, 1986 5:59:25 pm PST
DIRECTORY
Atom,
CD,
CDBasics,
CornerBasedDRC,
CStitching,
Rope;
CornerBasedDRCImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CStitching
EXPORTS CornerBasedDRC =
BEGIN
OPEN CornerBasedDRC;
Quadrants: TYPE = {ne, nw, sw, se};
DefaultError: ErrorProc = {
};
DefaultCompatibleNodes: CompatibleNodesProc = {
RETURN [FALSE];
};
neverInTesselation: REF ATOMNEW[ATOM←$neverInTesselation];
stopped: ERROR = CODE;
Check: PUBLIC PROC [task: REF DrcTask, area: CD.Rect] = {
IF task.geometry.stopFlag=NIL THEN task.geometry.stopFlag←NEW[BOOLFALSE];
IF task.compatibleNodes=NIL THEN task.compatibleNodes ← DefaultCompatibleNodes;
IF task.error=NIL THEN task.error ← DefaultError;
[] ← CStitching.EnumerateArea[plane: task.geometry, rect: area, eachTile: CheckOneTile, skip: neverInTesselation, data: task ! stopped => GOTO hasStopped];
EXITS hasStopped => NULL;
};
CompatibleNodes: PROC [task: REF DrcTask, rule: Rule, corner: REF, pos: CD.Position, other: REF, r: CD.Rect ← CDBasics.empty] RETURNS [BOOL] = INLINE {
RETURN [ 
corner=other OR
task.compatibleNodes[task, rule, corner, pos, other, r]
]
};
CheckOneTile: CStitching.TileProc = {
task: REF DrcTask = NARROW[data];
r: CD.Rect = CStitching.Area[tile];
CheckCorner: PROC [quadVals: ARRAY Quadrants OF REF ANY, pos: CD.Position] = {
CheckArea: PROC [rule: Rule, orient: CD.Orientation, flavour: { convex, concave}] = {
CheckTileValue: CStitching.TileProc = {
CheckValue[tile.value, CStitching.Area[tile]]
};
CheckValue: PROC [value: REF ANY, area: CD.Rect] = {
IF value=NIL THEN {
IF ~rule.isError[spaceConstraintIndex] THEN RETURN;
}
ELSE WITH value SELECT FROM
cc: Constraint => {
IF ~rule.isError[cc.index] THEN RETURN;
IF rule.okIfConnected AND nodeOrConstraintAtCorner#NIL AND CompatibleNodes[task, rule, nodeOrConstraintAtCorner, pos, cc, area] THEN
RETURN;
};
ENDCASE => {
IF ~rule.isError[nodeConstraintIndex] THEN RETURN;
IF rule.okIfConnected AND nodeOrConstraintAtCorner#NIL AND CompatibleNodes[task, rule, nodeOrConstraintAtCorner, pos, value] THEN
RETURN;
};
-- Check if it really is an error.
IF ~notReportedYet THEN RETURN;
IF task.restrict#NIL THEN {
IF ~CStitching.IsEmpty[
plane: task.restrict,
rect: CDBasics.MapRect[itemInCell: [x1: -delta, y1: -delta, x2: len, y2: len], cellInWorld: [pos, orient]],
skip: task.skipThese
] THEN RETURN;
};
task.error[
task: task,
rule: rule,
r: CDBasics.MapRect[itemInCell: [x1: 0, y1: 0, x2: rule.extent, y2: rule.extent], cellInWorld: [pos, orient]]
];
notReportedYet ← FALSE
}; -- CheckValue
--CheckArea
notReportedYet: BOOLTRUE;
len: INT = rule.extent;
delta: INT = 1;
IF len = 0 THEN {
-- Optimize purely local checks.
IF notReportedYet THEN
CheckValue[quadVals[ne], [pos.x, pos.y, pos.x+delta, pos.y+delta]];
IF notReportedYet THEN
CheckValue[quadVals[nw], [pos.x, pos.y-delta, pos.x+delta, pos.y]];
IF notReportedYet THEN
CheckValue[quadVals[sw], [pos.x-delta, pos.y-delta, pos.x, pos.y]];
IF notReportedYet THEN
CheckValue[quadVals[se], [pos.x-delta, pos.y, pos.x, pos.y+delta]];
}
ELSE {
SELECT flavour FROM
convex => {
[] ← CStitching.EnumerateArea[
plane: task.geometry,
rect: CDBasics.MapRect[itemInCell: [x1: -delta, y1: 0, x2: len, y2: len], cellInWorld: [pos, orient]],
eachTile: CheckTileValue,
skip: neverInTesselation
];
[] ← CStitching.EnumerateArea[
plane: task.geometry,
rect: CDBasics.MapRect[itemInCell: [x1: 0, y1: -delta, x2: len, y2: 0], cellInWorld: [pos, orient]],
eachTile: CheckTileValue,
skip: neverInTesselation
];
};
concave => {
[] ← CStitching.EnumerateArea[
plane: task.geometry,
rect: CDBasics.MapRect[itemInCell: [x1: 0, y1: 0, x2: len, y2: len], cellInWorld: [pos, orient]],
eachTile: CheckTileValue,
skip: neverInTesselation
];
};
ENDCASE
}
}; -- CheckArea
-- CheckCorner
nodeOrConstraintAtCorner: REFNIL;
FOR rL: Rules ← task.rules, rL.rest WHILE rL#NIL DO
rule: Rule = rL.first;
bitIndex: ARRAY Quadrants OF INTEGER = [8, 4, 2, 1];
quadBits: INTEGER ← 0;
nodeOrConstraintAtCorner ← NIL;
-- Translate the quadrant contents into bit vector values.
FOR q: Quadrants IN Quadrants DO
IF quadVals[q]=NIL THEN {
IF rule.isStuff[spaceConstraintIndex] THEN quadBits ← quadBits + bitIndex[q]
}
ELSE WITH quadVals[q] SELECT FROM
cc: Constraint => {
IF rule.isStuff[cc.index] THEN {
quadBits ← quadBits + bitIndex[q];
IF nodeOrConstraintAtCorner=NIL THEN nodeOrConstraintAtCorner ← cc
}
};
ENDCASE => {
IF rule.isStuff[nodeConstraintIndex] THEN {
quadBits ← quadBits + bitIndex[q];
nodeOrConstraintAtCorner ← quadVals[q];
};
};
ENDLOOP;
-- Is this really a corner in the terms of this rule?
-- Bits are ne=8, nw=4, sw=2, se=1.
-- The check is applied to the quad opposite the generating corner. (IE rot. 180)
-- X=TRUE, O=FALSE
0 - OO 1 - OO 2 - OO 3 - OO
OO OX XO XX

4 - XO 5 - XO 6 - XO 7 - XO
OO OX XO XX

8 - OX 9 - OX 10- OX 11- OX
OO OX XO XX

12- XX 13- XX 14- XX 15- XX
OO OX XO XX
SELECT quadBits FROM
0 => NULL;
1 => CheckArea[rule, rotate90, convex];
2 => CheckArea[rule, original, convex];
3 => NULL;
4 => CheckArea[rule, rotate270, convex];
5 => {CheckArea[rule, rotate90, convex]; CheckArea[rule, rotate270, convex]};
6 => NULL;
7 => CheckArea[rule, original, concave];
8 => CheckArea[rule, rotate180, convex];
9 => NULL;
10 => {CheckArea[rule, original, convex]; CheckArea[rule, rotate180, convex]};
11 => CheckArea[rule, rotate90, concave];
12 => NULL;
13 => CheckArea[rule, rotate180, concave];
14 => CheckArea[rule, rotate270, concave];
15 => NULL;
ENDCASE => ERROR;
ENDLOOP;
}; -- CheckCorner
-- SW corner
IF task.geometry.stopFlag^ THEN ERROR stopped;
IF task.restrict=NIL OR CStitching.FindTile[task.restrict, [x: r.x1, y: r.y1]].value#task.skipThese THEN {
IF tile.SW.SEdge[] = r.y1 THEN {
IF tile.WS.WEdge[]#r.x1 THEN {
IF tile.value=tile.SW.value THEN
CD.Error[ec: other, explanation: "tile violates horz rule"];
-- Get the quadrants at the SW corner
CheckCorner[[ne: tile.value, nw: tile.SW.value, sw: tile.WS.value, se: tile.WS.value], [r.x1, r.y1]];
}
-- ELSE NULL; a (probably rare) 4 way corner; handled at the NE corner.
}
ELSE { -- CStitching.WEdge[CStitching.WS[tile]] = r.x1 IMPLICITLY
IF tile.value=tile.WS.value THEN {
-- Get the quadrants at the SW corner
CheckCorner[[ne: tile.value, nw: tile.SW.value, sw: tile.SW.value, se: tile.WS.value], [r.x1, r.y1]];
}
-- ELSE NULL; No corner really
}
};
-- NE corner
IF task.restrict=NIL OR CStitching.FindTile[task.restrict, [x: r.x2, y: r.y2]].value#task.skipThese THEN {
IF tile.NE.NEdge[]=r.y2 THEN {
IF tile.EN.EEdge[]=r.x2 THEN {
-- 4 way corner
neQTile: CStitching.Tile ← tile.EN.NE;
WHILE neQTile.SEdge > r.y2 DO neQTile ← neQTile.WS[] ENDLOOP;
CheckCorner[[ne: neQTile.value, nw: tile.EN.value, sw: tile.value, se: tile.NE.value], [r.x2, r.y2]];
}
ELSE {
IF tile.value = tile.NE.value THEN
CD.Error[ec: other, explanation: "tile violates max horz rule NEast"];
-- Get the quadrants at the NE corner
CheckCorner[[ne: tile.EN.value, nw: tile.EN.value, sw: tile.value, se: tile.NE.value], [r.x2, r.y2]];
}
}
ELSE { -- tile.EN.EEdge = r.x2 IMPLICITLY
IF tile.value#tile.EN.value THEN {
-- NE corner
CheckCorner[[ne: tile.NE.value, nw: tile.EN.value, sw: tile.value, se: tile.NE.value], [r.x2, r.y2]];
}
--ELSE NULL; No corner really
}
}
}; --CheckOneTile
END.