CDOrient.mesa (part of Chipndale)
last edited by Ch. Jacobi, November 21, 1983 8:55 pm
some code from "ChipOrient" E. McCreight, February 22, 1982 10:00 AM
DIRECTORY
PrincOpsUtils,
CD,
Graphics;
CDOrient: CEDAR DEFINITIONS
IMPORTS Graphics, PrincOpsUtils =
BEGIN
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:
--a clockwise rotation of (idx/2)*45 degrees,
--followed by a reflection in x if (idx MOD 2)#0
--odd multiples of 45 degrees are not supported for all kind of objects
--clockwise and anticlockwise might be reversed depending on coordinate system:
--if the origin is on top we mean really clockwise for clockwise,
--if the origin is on the bottom we have to exchange clockwise with anticlockwise
original: Orientation = 0;
rotate90: Orientation = 4;
rotate180: Orientation = 8;
rotate270: Orientation = 12;
mirrorX: Orientation = 1;
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.
MapPosition: PROC [itemInCell: CD.Rect, cellSize: CD.Position,
cellInstOrient: Orientation, cellInstPos: CD.Position ← [0,0]]
RETURNS [posInWorld: CD.Position];
--Given an position 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.
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]};
IncludesOddRot45: PROC [orient: Orientation] RETURNS [BOOLEAN] =
--returns orient includes an odd multiple of 45 degree
TRUSTED INLINE {RETURN [PrincOpsUtils.BITAND[orient, 2]#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, 15]]};
ConcentrateOnRotate90: PROC [orient: Orientation] RETURNS [Orientation] =
--discard mirroring and rotations of 45 degree
TRUSTED INLINE {RETURN [PrincOpsUtils.BITAND[orient, 12]]};
OrientateContext: PROC [cont: Graphics.Context, size: CD.DesignPosition, 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
{Graphics.Scale[cont, -1, 1]; Graphics.Translate[cont, -size.x, 0]};
rotate90 =>
BEGIN
Graphics.Rotate[cont, 90]; Graphics.Translate[cont, 0, -size.y];
IF IncludesMirrorX[orient] THEN
{Graphics.Scale[cont, 1, -1]; Graphics.Translate[cont, 0, -size.y]};
END;
rotate180 =>
BEGIN
Graphics.Rotate[cont, 180]; Graphics.Translate[cont, -size.x, -size.y];
IF IncludesMirrorX[orient] THEN
{Graphics.Scale[cont, -1, 1]; Graphics.Translate[cont, -size.x, 0]};
END;
rotate270 =>
BEGIN
Graphics.Rotate[cont, 270]; Graphics.Translate[cont, -size.x, 0];
IF IncludesMirrorX[orient] THEN
{Graphics.Scale[cont, 1, -1]; Graphics.Translate[cont, 0, -size.y]};
END;
ENDCASE =>ERROR;
END;
END.