<> <> <> 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]; <> <<--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.