CDOrient.mesa (part of ChipNDale)
Copyright © 1983, 1985 by Xerox Corporation. All rights reserved.
Ch. Jacobi, November 21, 1983 8:55 pm
last edited by Ch. Jacobi, September 19, 1985 3:32:27 am PDT
some code from "ChipOrient" E. McCreight, May 16, 1985 12:00:54 pm PDT
DIRECTORY
PrincOpsUtils,
CD,
Imager;
CDOrient:
CEDAR
DEFINITIONS
IMPORTS Imager, PrincOpsUtils =
BEGIN
All about Orientation you probably want to use.
Remember: sizes are in cd coordinates.
Orientation:
TYPE =
CD.Orientation;
-- If your program depends on the representation of Orientation, it
-- is probably wrong.
-- An orientation idx is composed of two parts:
-- an anticlockwise rotation of (idx/2)*90 degrees,
-- followed by a reflection in x if (idx MOD 2)#0
original: Orientation = 0;
mirrorX: Orientation = 1;
rotate90: Orientation = 2;
rotate90X: Orientation = 3;
rotate180: Orientation = 4;
rotate180X: Orientation = 5;
mirrorY: Orientation = 5;
rotate270: Orientation = 6;
rotate270X: Orientation = 7;
MapRect:
PROC [itemInCell:
CD.Rect, cellSize:
CD.Position,
cellInstOrient: Orientation, cellInstPos:
CD.Position ← [0,0]]
RETURNS [itemInWorld:
CD.Rect];
-- Given an item in a prototype cell, and the
-- size of the prototype cell, both in "cell" co-ordinates, and
-- the position and orientation index of an instance of that cell in "world"
-- co-ordinates, this procedure returns the world
-- co-ordinates of the instance of the item.
DeMapRect:
PROC [itemInWorld:
CD.Rect, cellSize:
CD.Position,
cellInstOrient: Orientation, cellInstPos:
CD.Position ← [0,0]]
RETURNS [itemInCell:
CD.Rect];
-- Given an item in world co-ordinates, and the
-- size of a prototype cell, in "cell" co-ordinates, and
-- the position and orientation index of an instance of that cell in "world"
-- co-ordinates, this procedure returns the cell prototype
-- co-ordinates of that item.
MapPoint:
PROC [pointInCell:
CD.Position, cellSize:
CD.Position,
cellInstOrient: Orientation, cellInstPos:
CD.Position ← [0,0]]
RETURNS [pointInWorld:
CD.Position];
-- Given an point in a prototype cell,
-- the size of the prototype cell, both in "cell" co-ordinates, and
-- the position and orientation index of an instance of that cell in "world"
-- co-ordinates, this procedure returns the world
-- co-ordinates of the point.
-- WARNING: a position of a rect can not be mapped with MapPoint
DeMapPoint:
PROC [pointInWorld:
CD.Position, cellSize:
CD.Position,
cellInstOrient: Orientation, cellInstPos:
CD.Position ← [0,0]]
RETURNS [pointInCell:
CD.Position];
-- Given a point in world co-ordinates
-- the size of the prototype cell, in "cell" co-ordinates, and
-- the position and orientation index of an instance of that cell in "world"
-- co-ordinates, this procedure returns the cell
-- co-ordinates of the point.
-- WARNING: a position of a rect can not be mapped with DeMapPoint
ComposeOrient:
PROC [
itemOrientInCell, cellOrientInWorld: Orientation]
RETURNS [itemOrientInWorld: Orientation];
-- This procedure produces the composite orientation
-- obtained by first doing itemInCell and then
-- doing cellInWorld.
InverseOrient:
PROC [orient: Orientation]
RETURNS [inverse: Orientation];
--For all orientationIndexes o1, ComposeOrient[o1, InverseOrient[o1]] = 0.
DecomposeOrient:
PROCEDURE[
itemOrientInWorld, cellOrientInWorld: Orientation]
RETURNS [itemOrientInCell: Orientation];
-- For all orientationIndexes o1 and o2,
-- DecomposeOrient[cellOrientInWorld: o1, itemOrientInWorld:
-- ComposeOrient[cellOrientInWorld: o1, itemOrientInCell: o2]] = o2.
OrientedSize:
PROC [size:
CD.Position, orient: Orientation]
RETURNS [
CD.Position] =
-- returns the size transformed by transformation "orient"
INLINE {
RETURN
[IF IncludesOddRot90[orient] THEN [x: size.y, y: size.x] ELSE size]};
OrientedRect:
PROC [rect:
CD.Rect, orient: Orientation]
RETURNS [
CD.Rect] =
-- returns the rect "rect" transformed by transformation "orient"
INLINE {
RETURN
[
IF IncludesOddRot90[orient]
THEN
[x1: rect.x1, y1: rect.y1, x2: rect.x1+rect.y2-rect.y1, y2: rect.y1+rect.x2-rect.x1]
ELSE rect]};
RectAt:
PROC [pos, size:
CD.Position, orient: Orientation←original]
RETURNS [
CD.Rect] =
-- returns a rect of size "size" at position "pos" and orientation "orient"
INLINE {
RETURN [
IF IncludesOddRot90[orient] THEN CD.Rect[x1: pos.x, y1: pos.y, x2: pos.x+size.y, y2: pos.y+size.x]
ELSE CD.Rect[x1: pos.x, y1: pos.y, x2: pos.x+size.x, y2: pos.y+size.y]]};
IncludesOddRot90:
PROC [orient: Orientation]
RETURNS [
BOOLEAN] =
-- returns orient includes an odd multiple of 90 degree
TRUSTED INLINE {RETURN [PrincOpsUtils.BITAND[orient, rotate90]#0]};
IncludesMirrorX:
PROC [orient: Orientation]
RETURNS [
BOOLEAN] =
-- returns orient includes some mirroring
TRUSTED INLINE {RETURN [PrincOpsUtils.BITAND[orient, mirrorX]#0]};
MirrorX:
PROC [orient: Orientation]
RETURNS [Orientation] =
-- returns the orientation composed with mirror in x
TRUSTED INLINE {RETURN [PrincOpsUtils.BITXOR[orient, mirrorX]]};
Rotate90:
PROC [orient: Orientation]
RETURNS [Orientation] =
-- returns the orientation composed with a clockwise rotation of 90 degree
TRUSTED INLINE {RETURN [PrincOpsUtils.BITAND[orient+rotate90, 7]]};
ConcentrateOnRotate90:
PROC [orient: Orientation]
RETURNS [Orientation] =
--discard mirroring
TRUSTED INLINE {RETURN [PrincOpsUtils.BITAND[orient, 6]]};
OrientateContext:
PROC [cont: Imager.Context, size:
CD.Position, orient: Orientation] =
-- if cont is an context drawing in object coordinates of an un-transformed object,
-- transforms cont such that it draws into an oriented object. (size=size of object)
INLINE BEGIN
SELECT ConcentrateOnRotate90[orient]
FROM
-- ChipNDale rotates clockwise but graphics anticlockwise
-- but we do still not reverse rotation, because viewerpackage does
original =>
IF IncludesMirrorX[orient]
THEN
{Imager.Scale2T[cont, [-1, 1]]; Imager.TranslateT[cont, [-size.x, 0]]};
rotate90 =>
BEGIN
Imager.RotateT[cont, 90]; Imager.TranslateT[cont, [0, -size.y]];
IF IncludesMirrorX[orient]
THEN
{Imager.Scale2T[cont, [1, -1]]; Imager.TranslateT[cont, [0, -size.y]]};
END;
rotate180 =>
BEGIN
Imager.RotateT[cont, 180]; Imager.TranslateT[cont, [-size.x, -size.y]];
IF IncludesMirrorX[orient]
THEN
{Imager.Scale2T[cont, [-1, 1]]; Imager.TranslateT[cont, [-size.x, 0]]};
END;
rotate270 =>
BEGIN
Imager.RotateT[cont, 270]; Imager.TranslateT[cont, [-size.x, 0]];
IF IncludesMirrorX[orient]
THEN
{Imager.Scale2T[cont, [1, -1]]; Imager.TranslateT[cont, [0, -size.y]]};
END;
ENDCASE =>ERROR;
END;
CreateTransform:
PROC [
cellSize:
CD.Position,
cellInstOrient:
CD.Orientation,
cellInstPos:
CD.Position ← [0,0]]
RETURNS [Imager.Transformation];
-- Given the size of a cell,
-- the position and orientation of an instance of that cell in "world"
-- co-ordinates, returns the transformation to be applied to
-- cell points to get world points.
END.