<> <> <> <> <> DIRECTORY PrincOpsUtils, CD, Imager; CDOrient: CEDAR DEFINITIONS IMPORTS Imager, 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:>> <<--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]; <> <<--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 [FALSE]}; 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.