CDBasicsImpl.mesa (part of ChipNDale)
Copyright © 1983, 1985, 1986 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, May 3, 1983 4:26 pm
Last edited by: Christian Jacobi, October 30, 1986 11:29:24 am PST
DIRECTORY
Basics,
CD,
CDBasics,
CDBasicsInline,
Imager,
ImagerTransformation;
CDBasicsImpl: CEDAR PROGRAM
IMPORTS Basics, CDBasics, ImagerTransformation, CDBasicsInline
EXPORTS CDBasics, CDBasicsInline =
BEGIN
Skip: PUBLIC PROC[CD.Rect] = {
};
DecomposeRect: PUBLIC PROC [r, test: CD.Rect, inside, outside: PROC[CD.Rect]←Skip] = {
IF r.x1<test.x1 THEN {
outside[[x1: r.x1, y1: r.y1, x2: MIN[r.x2, test.x1], y2: r.y2]];
IF r.x2<test.x1 THEN RETURN;
};
IF r.y1<test.y1 THEN {
outside[[x1: MAX[test.x1, r.x1], y1: r.y1, x2: r.x2, y2: MIN[r.y2, test.y1]]];
IF r.y2<test.y1 THEN RETURN;
};
IF test.y2<r.y2 THEN {
outside[[x1: MAX[test.x1, r.x1], y1: MAX[test.y2, r.y1], x2: r.x2,
y2: r.y2]];
IF test.y2<r.y1 THEN RETURN;
};
IF test.x2<r.x2 THEN {
outside[[x1: MAX[test.x2, r.x1], y1: MAX[test.y1, r.y1], x2: r.x2,
y2: MIN[r.y2, test.y2]]];
IF test.x2<r.x1 THEN RETURN;
};
inside[[x1: MAX[test.x1, r.x1], y1: MAX[test.y1, r.y1], x2: MIN[test.x2, r.x2], y2: MIN[test.y2, r.y2]]];
};
MapRect: PUBLIC PROC [itemInCell: CD.Rect, cellInWorld: CD.Transformation] RETURNS [itemInWorld: CD.Rect←TRASH] = {
RETURN [CDBasicsInline.MapRect[itemInCell, cellInWorld]]
};
DeMapRect: PUBLIC PROC [itemInWorld: CD.Rect, cellInWorld: CD.Transformation] RETURNS [itemInCell: CD.Rect] = {
RETURN [CDBasicsInline.DeMapRect[itemInWorld, cellInWorld]]
};
MapPoint: PUBLIC PROC [pointInCell: CD.Position, cellInWorld: CD.Transformation] RETURNS [pointInWorld: CD.Position] = {
RETURN [CDBasicsInline.MapPoint[pointInCell, cellInWorld]]
};
DeMapPoint: PUBLIC PROC [pointInWorld: CD.Position, cellInWorld: CD.Transformation] RETURNS [pointInCell: CD.Position] = {
pointInCell ← MapPoint[
pointInCell: [
x: pointInWorld.x-cellInWorld.off.x,
y: pointInWorld.y-cellInWorld.off.y
],
cellInWorld: [[0, 0], inverseTable[cellInWorld.orient]]
];
};
ComposeOrient: PUBLIC PROC [itemInCell, cellInWorld: CD.Orientation] RETURNS [itemInWorld: CD.Orientation] = {
-- This procedure produces the composite orientation
-- obtained by first doing itemInCell and then
-- doing cellInWorld. It uses the observation
-- that a reflection in x followed by a z-degree clockwise
-- rotation is the same as a (360-z)-degree clockwise rotation
-- followed by a reflection in x. Thus if itemInCell
-- contains a final reflection, then cellInWorld's rotation
-- operates in reverse.
itemInWorld ← composeTable[itemInCell][cellInWorld]
};
ReallyInverseOrient: PROC [orient: CD.Orientation] RETURNS [inverse: CD.Orientation] = {
-- For all orientationIndexes o1, ComposeOrient[o1, InverseOrient[o1]] = 0.
-- A reflection in x followed by a z-degree clockwise
-- rotation is the same as a (360-z)-degree clockwise rotation
-- followed by a reflection in x. Thus if orient
-- contains a final reflection, then the inverse rotation
-- operates in the same direction as the forward one.
refl: [0..1] ~ Basics.BITAND[ORD[orient], 1];
rot: [0..6] ← Basics.BITAND[ORD[orient], 6];
IF refl=0 AND rot#0 THEN rot ← 8-rot;
inverse ← VAL[rot+refl];
};
InverseOrient: PUBLIC PROC [orient: CD.Orientation] RETURNS [CD.Orientation] = {
RETURN [inverseTable[orient]]
};
DecomposeOrient: PUBLIC PROC [itemInWorld, cellInWorld: CD.Orientation] RETURNS [itemInCell: CD.Orientation] = {
RETURN[ composeTable[itemInWorld][inverseTable[cellInWorld]] ]
};
ReallyComposeOrient: PROC [itemInCell, cellInWorld: CD.Orientation] RETURNS [itemInWorld: CD.Orientation] = {
-- This procedure produces the composite orientation
-- obtained by first doing itemInCell and then
-- doing cellInWorld. It uses the observation
-- that a reflection in x followed by a z-degree clockwise
-- rotation is the same as a (360-z)-degree clockwise rotation
-- followed by a reflection in x. Thus if itemInCell
-- contains a final reflection, then cellInWorld's rotation
-- operates in reverse.
refl1: [0..1] ~ Basics.BITAND[ORD[itemInCell], 1];
rot2: [0..6] ← Basics.BITAND[ORD[cellInWorld], 6];
IF refl1#0 AND rot2#0 THEN rot2 ← 8-rot2;
itemInWorld ← VAL[Basics.BITAND[
Basics.BITAND[ORD[itemInCell], 6] + rot2 + Basics.BITXOR[refl1, Basics.BITAND[ORD[cellInWorld], 1]],
7]];
};
ComposeTransform: PUBLIC PROC [itemInCell, cellInWorld: CD.Transformation] RETURNS [itemInWorld: CD.Transformation] = {
RETURN [CDBasicsInline.ComposeTransform[itemInCell, cellInWorld]]
};
InverseTransform: PUBLIC PROC [trans: CD.Transformation] RETURNS [CD.Transformation] = {
ERROR;
its wrong !?!@#
RETURN [ [CDBasics.NegOffset[trans.off], inverseTable[trans.orient]] ];
};
DecomposeTransform: PUBLIC PROC [itemInWorld, cellInWorld: CD.Transformation] RETURNS [itemInCell: CD.Transformation] = {
itemInCell.off ← DeMapPoint[itemInWorld.off, cellInWorld];
itemInCell.orient ← DecomposeOrient[itemInWorld.orient, cellInWorld.orient]
};
ImagerTransform: PUBLIC PROC [trans: CD.Transformation] RETURNS [Imager.Transformation] = {
RETURN [CDBasicsInline.ImagerTransform[trans]]
};
composeTable: PUBLIC ARRAY CD.Orientation OF ARRAY CD.Orientation OF CD.Orientation;
inverseTable: PUBLIC ARRAY CD.Orientation OF CD.Orientation;
--set up
FOR o1: CD.Orientation IN CD.Orientation DO
inverseTable[o1] ← ReallyInverseOrient[o1];
FOR o2: CD.Orientation IN CD.Orientation DO
composeTable[o1][o2] ← ReallyComposeOrient[o1, o2];
ENDLOOP;
ENDLOOP;
END.