DIRECTORY CDOrient, Basics, CD; CDOrientImpl: CEDAR PROGRAM IMPORTS Basics, CDOrient EXPORTS CDOrient = BEGIN OPEN CDOrient; MapRect: PUBLIC PROC [itemInCell: CD.Rect, cellSize: CD.Position, cellInstOrient: CD.Orientation, cellInstPos: CD.Position _ [0,0]] RETURNS [itemInWorld: CD.Rect_TRASH] = BEGIN SELECT cellInstOrient FROM original => RETURN[CD.Rect[ x1: cellInstPos.x+itemInCell.x1, x2: cellInstPos.x+itemInCell.x2, y1: cellInstPos.y+itemInCell.y1, y2: cellInstPos.y+itemInCell.y2 ]]; 1 => -- reflection in x RETURN[CD.Rect[ x1: cellInstPos.x+cellSize.x-itemInCell.x2, x2: cellInstPos.x+cellSize.x-itemInCell.x1, y1: cellInstPos.y+itemInCell.y1, y2: cellInstPos.y+itemInCell.y2 ]]; rotate90 => { -- 90 degrees clockwise RETURN[CD.Rect[ x1: cellInstPos.x+cellSize.y-itemInCell.y2, y1: cellInstPos.y+itemInCell.x1, x2: cellInstPos.x+cellSize.y-itemInCell.y1, y2: cellInstPos.y+itemInCell.x2]]; }; 3 => { -- 90 degrees clockwise followed by reflection in x RETURN[CD.Rect[ x1: cellInstPos.x+itemInCell.y1, y1: cellInstPos.y+itemInCell.x1, x2: cellInstPos.x+itemInCell.y2, y2: cellInstPos.y+itemInCell.x2]]; }; rotate180 => { -- 180 degrees clockwise RETURN[CD.Rect[ x1: cellInstPos.x+cellSize.x-itemInCell.x2, y1: cellInstPos.y+cellSize.y-itemInCell.y2, x2: cellInstPos.x+cellSize.x-itemInCell.x1, y2: cellInstPos.y+cellSize.y-itemInCell.y1]]; }; 5 => { -- 180 degrees clockwise followed by reflection in x RETURN[CD.Rect[ x1: cellInstPos.x+itemInCell.x1, y1: cellInstPos.y+cellSize.y-itemInCell.y2, x2: cellInstPos.x+itemInCell.x2, y2: cellInstPos.y+cellSize.y-itemInCell.y1]]; }; rotate270 => { -- 270 degrees clockwise RETURN[CD.Rect[ x1: cellInstPos.x+itemInCell.y1, y1: cellInstPos.y+cellSize.x-itemInCell.x2, x2: cellInstPos.x+itemInCell.y2, y2: cellInstPos.y+cellSize.x-itemInCell.x1]]; }; 7 => { -- 270 degrees clockwise followed by reflection in x RETURN[CD.Rect[ x1: cellInstPos.x+cellSize.y-itemInCell.y2, y1: cellInstPos.y+cellSize.x-itemInCell.x2, x2: cellInstPos.x+cellSize.y-itemInCell.y1, y2: cellInstPos.y+cellSize.x-itemInCell.x1]]; }; ENDCASE; END; DeMapRect: PUBLIC PROC [itemInWorld: CD.Rect, cellSize: CD.Position, cellInstOrient: CD.Orientation, cellInstPos: CD.Position _ [0,0]] RETURNS [itemInCell: CD.Rect] = BEGIN inverseOrient: CD.Orientation = InverseOrient[cellInstOrient]; itemInCell _ MapRect[ itemInCell: [ x1: itemInWorld.x1-cellInstPos.x, y1: itemInWorld.y1-cellInstPos.y, x2: itemInWorld.x2-cellInstPos.x, y2: itemInWorld.y2-cellInstPos.y ], cellInstOrient: inverseOrient, cellSize: CDOrient.OrientedSize[size: cellSize, orient: inverseOrient] ]; END; MapPosition: PUBLIC PROC [itemInCell: CD.Rect, cellSize: CD.Position, cellInstOrient: CD.Orientation, cellInstPos: CD.Position _ [0,0]] RETURNS [posInWorld: CD.Position] = BEGIN x1, y1, x2, y2, sizeX, sizeY, t: CD.Number; IF cellInstOrient=original THEN -- most common case RETURN[[ x: cellInstPos.x+itemInCell.x1, y: cellInstPos.y+itemInCell.y1 ]]; [x: sizeX, y: sizeY] _ cellSize; [x1: x1, x2: x2, y1: y1, y2: y2] _ itemInCell; SELECT ConcentrateOnRotate90[cellInstOrient] FROM rotate90 => { -- 90 degrees clockwise t _ y1; y1 _ x1; x1 _ sizeY-y2; x2 _ sizeY-t; sizeX _ sizeY; }; rotate180 => { -- 180 degrees clockwise t _ sizeX-x1; x1 _ sizeX-x2; x2 _ t; y1 _ sizeY-y2; }; rotate270 => { -- 270 degrees clockwise x1 _ y1; y1 _ sizeX-x2; x2 _ y2; sizeX _ sizeY; }; original => NULL; ENDCASE; IF IncludesMirrorX[cellInstOrient] THEN {x1 _ sizeX-x2}; posInWorld _ [x: cellInstPos.x+x1, y: cellInstPos.y+y1]; END; ComposeOrient: PUBLIC PROC [ itemOrientInCell, cellOrientInWorld: CD.Orientation] RETURNS [itemOrientInWorld: CD.Orientation] = BEGIN itemOrientInWorld _ composeTable[itemOrientInCell][cellOrientInWorld] END; InverseOrient: PUBLIC PROC [orient: CD.Orientation] RETURNS [inverse: CD.Orientation] = BEGIN refl: [0..1] ~ Basics.BITAND[orient, 1]; rot: [0..6] _ Basics.BITAND[orient, 6]; IF refl=0 AND rot#0 THEN rot _ 8-rot; inverse _ rot+refl; END; DecomposeOrient: PUBLIC PROC [ itemOrientInWorld, cellOrientInWorld: CD.Orientation] RETURNS [itemOrientInCell: CD.Orientation] = BEGIN RETURN[ composeTable[itemOrientInWorld][InverseOrient[cellOrientInWorld]] ] END; ReallyComposeOrient: PUBLIC PROC [ itemOrientInCell, cellOrientInWorld: CD.Orientation] RETURNS [itemOrientInWorld: CD.Orientation] = BEGIN refl1: [0..1] ~ Basics.BITAND[itemOrientInCell, 1]; rot2: [0..6] _ LOOPHOLE[Basics.BITAND[cellOrientInWorld, 6]]; IF refl1#0 AND rot2#0 THEN rot2 _ 8-rot2; itemOrientInWorld _ Basics.BITAND[LOOPHOLE[Basics.BITAND[itemOrientInCell, 6], CARDINAL]+ rot2+LOOPHOLE[Basics.BITXOR[refl1, Basics.BITAND[cellOrientInWorld, 1]], CARDINAL], 7]; END; composeTable: ARRAY CD.Orientation OF ARRAY CD.Orientation OF CD.Orientation; FOR o1: CD.Orientation IN CD.Orientation DO FOR o2: CD.Orientation IN CD.Orientation DO composeTable[o1][o2] _ ReallyComposeOrient[o1, o2]; ENDLOOP; ENDLOOP; END. ,CDOrientImpl.mesa (part of Chipndale) A package to transform Chip'N Dale rectangles and orientations. Copyright c 1983, 1984 by Xerox Corporation. All rights reserved. by Ch. Jacobi, May 12, 1983 5:58 pm originally written by E. McCreight for Chipmonk, February 22, 1982 last edited by Ch. Jacobi, November 9, 1984 11:22:13 am PST -- Orientation Transformations -- x increases to the right, y increases upward. -- An CD.Orientation idx is composed of two parts: -- a clockwise rotation of (idx/2)*90 degrees, -- followed by a reflection in x if (idx MOD 2)#0. GoodOldMapRect: PUBLIC PROC [itemInCell: CD.Rect, cellSize: CD.Position, cellInstOrient: CD.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. BEGIN x1, y1, x2, y2, sizeX, sizeY, t: CD.Number; -- most common case IF cellInstOrient=original THEN RETURN[CD.Rect[ x1: cellInstPos.x+itemInCell.x1, x2: cellInstPos.x+itemInCell.x2, y1: cellInstPos.y+itemInCell.y1, y2: cellInstPos.y+itemInCell.y2 ]]; [x: sizeX, y: sizeY] _ cellSize; [x1: x1, x2: x2, y1: y1, y2: y2] _ itemInCell; SELECT ConcentrateOnRotate90[cellInstOrient] FROM rotate90 => { -- 90 degrees clockwise t _ y1; y1 _ x1; x1 _ sizeY-y2; y2 _ x2; x2 _ sizeY-t; sizeX _ sizeY; }; rotate180 => { -- 180 degrees clockwise t _ sizeX-x1; x1 _ sizeX-x2; x2 _ t; t _ sizeY-y1; y1 _ sizeY-y2; y2 _ t; }; rotate270 => { -- 270 degrees clockwise t _ x1; x1 _ y1; y1 _ sizeX-x2; x2 _ y2; y2 _ sizeX-t; sizeX _ sizeY; }; original => NULL; ENDCASE; IF IncludesMirrorX[cellInstOrient] THEN { -- mirror in x t _ sizeX-x1; x1 _ sizeX-x2; x2 _ t }; itemInWorld _ [x1: cellInstPos.x+x1, -- translate by cellInstPos y1: cellInstPos.y+y1, x2: cellInstPos.x+x2, y2: cellInstPos.y+y2]; END; -- 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. -- Given an item in world co-ordinates, and the -- size of a 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 cell prototype -- co-ordinates of that item. -- 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 position. -- This procedure is only speed up from MapRect -- This procedure produces the composite orientation -- obtained by first doing itemOrientInCell and then -- doing cellOrientInWorld. 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 itemOrientInCell -- contains a final reflection, then cellOrientInWorld's rotation -- operates in reverse. -- 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. -- For all orientationIndexes o1 and o2, -- DecomposeOrient[cellOrientInWorld: o1, itemOrientInWorld: -- ComposeOrient[cellOrientInWorld: o1, itemOrientInCell: o2]] = o2. -- This procedure produces the composite orientation -- obtained by first doing itemOrientInCell and then -- doing cellOrientInWorld. 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 itemOrientInCell -- contains a final reflection, then cellOrientInWorld's rotation -- operates in reverse. -- Certification tests, can be commented out for speed of startup FOR o1: CD.Orientation IN CD.Orientation DO IF ComposeOrient[o1, InverseOrient[o1]] # 0 THEN ERROR; FOR o2: CD.Orientation IN CD.Orientation DO IF DecomposeOrient[cellOrientInWorld: o1, itemOrientInWorld: ComposeOrient[cellOrientInWorld: o1, itemOrientInCell: o2]] # o2 THEN ERROR; ENDLOOP; ENDLOOP; Ê k˜J˜Jšœ&™&˜Jšœ?™?J˜Jšœ Ïmœ7™BJšœ#™#JšœB™BJšœ;™;J˜—šÏk ˜ J˜ J˜Jšžœ˜J˜—šÏn œžœž˜Jšžœ˜Jšžœ ˜Jšžœžœ ˜J˜Jšœ™J˜Jšœ1™1J˜Jšœ2™2Jšœ.™.Jšœ2™2J˜š Ÿœžœžœžœžœ ™HJšœžœžœ™AJšžœžœ™ J™Jšœ-™-Jšœ?™?JšœL™LJšœ1™1Jšœ,™,J™Jšžœ™Jšœ!žœ™+Jšœ™šžœž™šžœžœ™Jšœ ™ J™ J™ J™J™——J™J™ J™.J™šžœ'ž™1šœÏc™%J™J™J™J™J™ J™Jšžœ™—šœ ™'J™$J™$Jšžœ™—šœ ™'J™J™J™J™J™ J™Jšœ™—Jšœ žœ™Jšžœ™J™—šžœ!žœ ™8J™#J™J™—šœ% ™@J™+J™—Jšžœ™J™J™—š Ÿœžœžœžœžœ ˜AJšœžœžœ˜AJšžœžœžœ˜&Jšœ-™-Jšœ?™?JšœL™LJšœ1™1Jšœ,™,Jšžœ˜šžœž˜šœ ˜ šžœžœ˜Jšœ ˜ J˜ J˜ J˜J˜——šœ ˜šžœžœ˜Jšœ+˜+Jšœ+˜+J˜ J˜J˜——šœ ˜%šžœžœ˜Jšœ,˜,J˜!J˜+J˜"—Jšœ˜—šœ 3˜:šžœžœ˜Jšœ!˜!Jšœ!˜!Jšœ ˜ Jšœ"˜"—Jšœ˜—šœ ˜'šžœžœ˜Jšœ+˜+Jšœ,˜,Jšœ+˜+Jšœ-˜-—Jšœ˜—šœ 4˜;šžœžœ˜Jšœ!˜!Jšœ,˜,Jšœ ˜ Jšœ-˜-—Jšœ˜—šœ ˜'šžœžœ˜Jšœ!˜!Jšœ,˜,Jšœ ˜ Jšœ-˜-—Jšœ˜—šœ 4˜;šžœžœ˜Jšœ,˜,Jšœ,˜,Jšœ+˜+Jšœ-˜-—Jšœ˜—Jšžœ˜—Jšžœ˜J˜J˜—š Ÿ œžœžœžœžœ ˜DJšœžœžœ˜AJšžœžœ˜Jšžœ˜Jšœ/™/Jšœ=™=JšœL™LJšœ:™:Jšœ™Jšœžœ-˜>˜˜ J˜"J˜!J˜"J˜ J˜—J˜J˜FJ˜—Jšžœ˜J˜J˜——š Ÿ œžœžœžœžœ ˜EJšœžœžœ˜AJšžœžœ ˜#Jšœ1™1Jšœ?™?JšœL™LJšœ1™1Jšœ ™ Jšœ/™/Jšž˜Jšœ!žœ˜+šžœžœ ˜3šžœ˜J˜J˜J˜——J˜ J˜.šžœ'ž˜1šœ ˜%J˜J˜J˜J˜ J˜Jšœ˜—šœ ˜'J˜$J˜Jšœ˜—šœ ˜'J˜J˜J˜J˜Jšœ˜—Jšœ žœ˜Jšžœ˜—Jšžœ!žœ˜9J˜8Jšžœ˜J˜J˜šŸ œžœžœ˜Jšœ%žœ ˜4Jšžœžœ˜-Jšž˜Jšœ4™4Jšœ4™4Jšœ4™4Jšœ:™:Jšœ>™>Jšœ;™;JšœA™AJšœ™JšœE˜EJšžœ˜J˜J˜—šŸ œžœžœ žœ ˜3Jšžœ žœ˜#Jšž˜JšœK™KJšœ5™5Jšœ>™>Jšœ1™1Jšœ9™9Jšœ5™5Jšœžœ ˜(Jšœžœ ˜'Jšžœžœžœ ˜%J˜Jšžœ˜J˜J˜—šŸœžœžœ˜Jšœ&žœ ˜5Jšžœžœ˜,Jšž˜Jšœ(™(Jšœ<™™>Jšœ;™;JšœA™AJšœ™Jšœžœ˜3Jšœžœžœ˜=Jšžœ žœžœ˜)š œžœžœžœžœ˜YJš œžœžœžœžœ˜W—Jšžœ˜J˜J˜—JšœA™Aš žœžœ žœžœ ž™+Jšžœ*žœžœ™7š žœžœ žœžœ ž™+šžœ:™