DIRECTORY CDOrient, Basics, CD, Imager, ImagerTransformation; CDOrientImpl: CEDAR PROGRAM IMPORTS Basics, CDOrient, ImagerTransformation 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 ]]; mirrorX => -- 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]]; }; rotate90X => { -- 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]]; }; rotate180X => { -- 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]]; }; rotate270X => { -- 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; MapPoint: PUBLIC PROC [pointInCell: CD.Position, cellSize: CD.Position, cellInstOrient: Orientation, cellInstPos: CD.Position _ [0,0]] RETURNS [pointInWorld: CD.Position] = BEGIN SELECT cellInstOrient FROM original => RETURN[CD.Position[ x: cellInstPos.x+pointInCell.x, y: cellInstPos.y+pointInCell.y ]]; mirrorX => -- reflection in x RETURN[CD.Position[ x: cellInstPos.x+cellSize.x-pointInCell.x, y: cellInstPos.y+pointInCell.y ]]; rotate90 => { -- 90 degrees clockwise RETURN[CD.Position[ x: cellInstPos.x+cellSize.y-pointInCell.y, y: cellInstPos.y+pointInCell.x]]; }; rotate90X => { -- 90 degrees clockwise followed by reflection in x RETURN[CD.Position[ x: cellInstPos.x+pointInCell.y, y: cellInstPos.y+pointInCell.x]]; }; rotate180 => { -- 180 degrees clockwise RETURN[CD.Position[ x: cellInstPos.x+cellSize.x-pointInCell.x, y: cellInstPos.y+cellSize.y-pointInCell.y]]; }; rotate180X => { -- 180 degrees clockwise followed by reflection in x RETURN[CD.Position[ x: cellInstPos.x+pointInCell.x, y: cellInstPos.y+cellSize.y-pointInCell.y]]; }; rotate270 => { -- 270 degrees clockwise RETURN[CD.Position[ x: cellInstPos.x+pointInCell.y, y: cellInstPos.y+cellSize.x-pointInCell.x]]; }; rotate270X => { -- 270 degrees clockwise followed by reflection in x RETURN[CD.Position[ x: cellInstPos.x+cellSize.y-pointInCell.y, y: cellInstPos.y+cellSize.x-pointInCell.x]]; }; ENDCASE; END; DeMapPoint: PUBLIC PROC [pointInWorld: CD.Position, cellSize: CD.Position, cellInstOrient: Orientation, cellInstPos: CD.Position _ [0,0]] RETURNS [pointInCell: CD.Position] = BEGIN inverseOrient: CD.Orientation = InverseOrient[cellInstOrient]; pointInCell _ MapPoint[ pointInCell: [ x: pointInWorld.x-cellInstPos.x, y: pointInWorld.y-cellInstPos.y ], cellInstOrient: inverseOrient, cellSize: CDOrient.OrientedSize[size: cellSize, orient: inverseOrient] ]; 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; CreateTransform: PUBLIC PROC [ cellSize: CD.Position, cellInstOrient: CD.Orientation, cellInstPos: CD.Position _ [0,0]] RETURNS [Imager.Transformation] = BEGIN RETURN [SELECT cellInstOrient FROM original => ImagerTransformation.Create[1, 0, cellInstPos.x, 0, 1, cellInstPos.y], 1 => ImagerTransformation.Create[-1, 0, cellInstPos.x+cellSize.x, 0, 1, cellInstPos.y], -- reflection in x rotate90 => ImagerTransformation.Create[0, -1, cellInstPos.x+cellSize.y, 1, 0, cellInstPos.y], -- 90 degrees clockwise 3 => ImagerTransformation.Create[0, 1, cellInstPos.x, 1, 0, cellInstPos.y], -- 90 degrees clockwise followed by reflection in x rotate180 => ImagerTransformation.Create[-1, 0, cellInstPos.x+cellSize.x, 0, -1, cellInstPos.y+cellSize.y], -- 180 degrees clockwise 5 => ImagerTransformation.Create[1, 0, cellInstPos.x, 0, -1, cellInstPos.y+cellSize.y], -- 180 degrees clockwise followed by reflection in x rotate270 => ImagerTransformation.Create[0, 1, cellInstPos.x, -1, 0, cellInstPos.y+cellSize.x], -- 270 degrees clockwise 7 => ImagerTransformation.Create[0, -1, cellInstPos.x+cellSize.y, -1, 0, cellInstPos.y+cellSize.x], -- 270 degrees clockwise followed by reflection in x ENDCASE => ERROR ]; 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) Jacobi, September 19, 1985 8:33:29 pm PDT A package to transform Chip'N Dale rectangles and orientations. Copyright c 1983, 1985 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, May 21, 1985 10:59:00 am PDT -- 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. -- 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 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 --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 -- 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. -- 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. -- 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; Κ E˜codešœ&™&K™)—˜Kšœ?™?K˜Kšœ Οmœ7™BKšœ$™$KšœB™BKšœ8™8K˜—šΟk ˜ K˜ K˜Kšž˜Kšœ˜Kšœ˜—K˜šΠln œžœž˜Kšžœ(˜/Kšžœ ˜—šžœ˜Kšžœ ˜K˜—Kšœ™K˜Kšœ1™1K˜Kšœ2™2Kšœ.™.Kšœ2™2K˜š Οnœžœžœžœžœ ˜AKšœžœžœ˜AKšžœžœžœ˜&Kšœ-™-Kšœ?™?KšœL™LKšœ1™1Kšœ,™,Kšžœ˜šžœž˜šœ ˜ šžœžœ˜Kšœ ˜ K˜ K˜ K˜K˜——šœ Οc˜šžœžœ˜Kšœ+˜+Kšœ+˜+K˜ K˜K˜——šœ‘˜%šžœžœ˜Kšœ,˜,K˜!K˜+K˜"—Kšœ˜—šœ‘3˜Bšžœžœ˜Kšœ!˜!Kšœ!˜!Kšœ ˜ Kšœ"˜"—Kšœ˜—šœ‘˜'šžœžœ˜Kšœ+˜+Kšœ,˜,Kšœ+˜+Kšœ-˜-—Kšœ˜—šœ‘4˜Dšžœžœ˜Kšœ!˜!Kšœ,˜,Kšœ ˜ Kšœ-˜-—Kšœ˜—šœ‘˜'šžœžœ˜Kšœ!˜!Kšœ,˜,Kšœ ˜ Kšœ-˜-—Kšœ˜—šœ‘4˜Dšžœžœ˜Kšœ,˜,Kšœ,˜,Kšœ+˜+Kšœ-˜-—Kšœ˜—Kšžœ˜—Kšžœ˜K˜K˜—š   œžœžœžœžœ ˜DKšœžœžœ˜AKšžœžœ˜Kšžœ˜Kšœ/™/Kšœ=™=KšœL™LKšœ:™:Kšœ™Kšœžœ-˜>˜˜ K˜"K˜!K˜"K˜ K˜—K˜K˜FK˜—Kšžœ˜K˜K˜—š œž œžœžœ ˜GKšœ*žœ˜>Kšžœžœ ˜%Kšœ&™&KšœB™BKšœK™KKšœ0™0Kšœ™Kšœ?™?Kšžœ˜šžœž˜šœ ˜ šžœžœ ˜Kšœ˜Kšœ˜K˜——šœ ‘˜šžœžœ ˜Kšœ*˜*Kšœ˜K˜——šœ‘˜%šžœžœ ˜Kšœ*˜*Kšœ!˜!—Kšœ˜—šœ‘3˜Bšžœžœ ˜Kšœ ˜ Kšœ!˜!—Kšœ˜—šœ‘˜'šžœžœ ˜Kšœ*˜*Kšœ,˜,—Kšœ˜—šœ‘4˜Dšžœžœ ˜Kšœ˜Kšœ,˜,—Kšœ˜—šœ‘˜'šžœžœ ˜Kšœ˜Kšœ,˜,—Kšœ˜—šœ‘4˜Dšžœžœ ˜Kšœ*˜*Kšœ,˜,—Kšœ˜—Kšžœ˜—Kšžœ˜K˜—š  œž œžœžœ ˜JKšœ*žœ˜>Kšžœžœ ˜$Kšœ%™%Kšœ=™=KšœK™KKšœ/™/Kšœ™KšœA™AKšž˜Kšœžœ-˜>šœ˜šœ˜Kšœ!˜!Kšœ˜K˜—K˜K˜FK˜—Kšžœ˜—K˜š  œžœžœ˜Kšœ%žœ ˜4Kšžœžœ˜-Kšž˜Kšœ4™4Kšœ4™4Kšœ4™4Kšœ:™:Kšœ>™>Kšœ;™;KšœA™AKšœ™KšœE˜EKšžœ˜˜K˜——š  œžœžœ žœ ˜3Kšžœ žœ˜#Kšž˜KšœK™KKšœ5™5Kšœ>™>Kšœ1™1Kšœ9™9Kšœ5™5Kšœžœ ˜(Kšœžœ ˜'Kšžœžœžœ ˜%K˜Kšžœ˜K˜K˜—š œžœžœ˜Kšœ&žœ ˜5Kšžœžœ˜,Kšž˜Kšœ(™(Kšœ<™™>Kšœ;™;KšœA™AKšœ™Kšœžœ˜3Kšœžœžœ˜=Kšžœ žœžœ˜)š œžœžœžœžœ˜YKš œžœžœžœžœ˜W—Kšžœ˜˜K™——š œžœžœ˜Kšœ žœ ˜Kšœžœ˜ Kšœ žœ˜!Kšžœ˜!Kšœ™KšœF™FKšœ<™