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.