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: BOOL ← TRUE;
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
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;