<> <> <> <> DIRECTORY CD USING [Number, Instance, Orientation, Position, Rect, Transformation], Imager USING [Transformation], ImagerTransformation USING [Create]; CDBasicsInline: CEDAR DEFINITIONS IMPORTS ImagerTransformation = BEGIN <> <> <> Number: TYPE = CD.Number; Orientation: TYPE = CD.Orientation; Position: TYPE = CD.Position; Rect: TYPE = CD.Rect; Transformation: TYPE = CD.Transformation; composeTable: READONLY ARRAY CD.Orientation OF ARRAY CD.Orientation OF CD.Orientation; inverseTable: READONLY ARRAY CD.Orientation OF CD.Orientation; MapPoint: PROC [pointInCell: CD.Position, cellInWorld: CD.Transformation] RETURNS [pointInWorld: CD.Position_TRASH] = INLINE { SELECT cellInWorld.orient FROM original => RETURN[CD.Position[ x: cellInWorld.off.x+pointInCell.x, y: cellInWorld.off.y+pointInCell.y]]; mirrorX => RETURN[CD.Position[ x: cellInWorld.off.x-pointInCell.x, y: cellInWorld.off.y+pointInCell.y]]; rotate90 => RETURN[CD.Position[ x: cellInWorld.off.x-pointInCell.y, y: cellInWorld.off.y+pointInCell.x]]; rotate90X => RETURN[CD.Position[ x: cellInWorld.off.x+pointInCell.y, y: cellInWorld.off.y+pointInCell.x]]; rotate180 => RETURN[CD.Position[ x: cellInWorld.off.x-pointInCell.x, y: cellInWorld.off.y-pointInCell.y]]; rotate180X => RETURN[CD.Position[ x: cellInWorld.off.x+pointInCell.x, y: cellInWorld.off.y-pointInCell.y]]; rotate270 => RETURN[CD.Position[ x: cellInWorld.off.x+pointInCell.y, y: cellInWorld.off.y-pointInCell.x]]; rotate270X => RETURN[CD.Position[ x: cellInWorld.off.x-pointInCell.y, y: cellInWorld.off.y-pointInCell.x]]; ENDCASE; }; MapRect: PUBLIC PROC [itemInCell: CD.Rect, cellInWorld: CD.Transformation] RETURNS [itemInWorld: CD.Rect_TRASH] = INLINE { SELECT cellInWorld.orient FROM original => RETURN[CD.Rect[ x1: cellInWorld.off.x+itemInCell.x1, x2: cellInWorld.off.x+itemInCell.x2, y1: cellInWorld.off.y+itemInCell.y1, y2: cellInWorld.off.y+itemInCell.y2 ]]; mirrorX => RETURN[CD.Rect[ x1: cellInWorld.off.x-itemInCell.x2, x2: cellInWorld.off.x-itemInCell.x1, y1: cellInWorld.off.y+itemInCell.y1, y2: cellInWorld.off.y+itemInCell.y2 ]]; rotate90 => { RETURN[CD.Rect[ x1: cellInWorld.off.x-itemInCell.y2, y1: cellInWorld.off.y+itemInCell.x1, x2: cellInWorld.off.x-itemInCell.y1, y2: cellInWorld.off.y+itemInCell.x2]]; }; rotate90X => { RETURN[CD.Rect[ x1: cellInWorld.off.x+itemInCell.y1, y1: cellInWorld.off.y+itemInCell.x1, x2: cellInWorld.off.x+itemInCell.y2, y2: cellInWorld.off.y+itemInCell.x2]]; }; rotate180 => { RETURN[CD.Rect[ x1: cellInWorld.off.x-itemInCell.x2, y1: cellInWorld.off.y-itemInCell.y2, x2: cellInWorld.off.x-itemInCell.x1, y2: cellInWorld.off.y-itemInCell.y1]]; }; rotate180X => { RETURN[CD.Rect[ x1: cellInWorld.off.x+itemInCell.x1, y1: cellInWorld.off.y-itemInCell.y2, x2: cellInWorld.off.x+itemInCell.x2, y2: cellInWorld.off.y-itemInCell.y1]]; }; rotate270 => { RETURN[CD.Rect[ x1: cellInWorld.off.x+itemInCell.y1, y1: cellInWorld.off.y-itemInCell.x2, x2: cellInWorld.off.x+itemInCell.y2, y2: cellInWorld.off.y-itemInCell.x1]]; }; rotate270X => { RETURN[CD.Rect[ x1: cellInWorld.off.x-itemInCell.y2, y1: cellInWorld.off.y-itemInCell.x2, x2: cellInWorld.off.x-itemInCell.y1, y2: cellInWorld.off.y-itemInCell.x1]]; }; ENDCASE; }; OrientedRect: PUBLIC PROC [itemInCell: CD.Rect, cellInWorld: CD.Orientation] RETURNS [itemInWorld: CD.Rect_TRASH] = INLINE { RETURN[ SELECT cellInWorld FROM original => itemInCell, mirrorX => [-itemInCell.x2, +itemInCell.y1, -itemInCell.x1, +itemInCell.y2], rotate90 => [-itemInCell.y2, +itemInCell.x1, -itemInCell.y1, +itemInCell.x2], rotate90X => [+itemInCell.y1, +itemInCell.x1, +itemInCell.y2, +itemInCell.x2], rotate180 => [-itemInCell.x2, -itemInCell.y2, -itemInCell.x1, -itemInCell.y1], rotate180X => [+itemInCell.x1, -itemInCell.y2, +itemInCell.x2, -itemInCell.y1], rotate270 => [+itemInCell.y1, -itemInCell.x2, +itemInCell.y2, -itemInCell.x1], rotate270X => [-itemInCell.y2, -itemInCell.x2, -itemInCell.y1, -itemInCell.x1], ENDCASE => ERROR ] }; ComposeTransform: PROC [itemInCell, cellInWorld: CD.Transformation] RETURNS [itemInWorld: CD.Transformation_TRASH] = INLINE { itemInWorld.off _ MapPoint[itemInCell.off, cellInWorld]; itemInWorld.orient _ composeTable[itemInCell.orient][cellInWorld.orient]; }; DeMapRect: PUBLIC PROC [itemInWorld: CD.Rect, cellInWorld: CD.Transformation] RETURNS [itemInCell: CD.Rect] = INLINE { itemInCell _ OrientedRect[ [ x1: itemInWorld.x1-cellInWorld.off.x, y1: itemInWorld.y1-cellInWorld.off.y, x2: itemInWorld.x2-cellInWorld.off.x, y2: itemInWorld.y2-cellInWorld.off.y ], inverseTable[cellInWorld.orient] ]; }; ImagerTransform: PROC [trans: CD.Transformation] RETURNS [Imager.Transformation] = INLINE { RETURN [SELECT trans.orient FROM original => ImagerTransformation.Create[1, 0, trans.off.x, 0, 1, trans.off.y], mirrorX => ImagerTransformation.Create[-1, 0, trans.off.x, 0, 1, trans.off.y], rotate90 => ImagerTransformation.Create[0, -1, trans.off.x, 1, 0, trans.off.y], rotate90X => ImagerTransformation.Create[0, 1, trans.off.x, 1, 0, trans.off.y], rotate180 => ImagerTransformation.Create[-1, 0, trans.off.x, 0, -1, trans.off.y], rotate180X => ImagerTransformation.Create[1, 0, trans.off.x, 0, -1, trans.off.y], rotate270 => ImagerTransformation.Create[0, 1, trans.off.x, -1, 0, trans.off.y], rotate270X => ImagerTransformation.Create[0, -1, trans.off.x, -1, 0, trans.off.y], ENDCASE => ERROR ]; }; IntersectRI: PROC[r: CD.Rect, inst: CD.Instance] RETURNS [BOOL] = TRUSTED INLINE { <<--returns rect intersects or touches inst >> SELECT inst.trans.orient FROM original => RETURN [ r.x2 >= inst.trans.off.x+inst.ob.bbox.x1 AND r.x1 <= inst.trans.off.x+inst.ob.bbox.x2 AND r.y2 >= inst.trans.off.y+inst.ob.bbox.y1 AND r.y1 <= inst.trans.off.y+inst.ob.bbox.y2 ]; mirrorX => RETURN [ r.x2 >= inst.trans.off.x-inst.ob.bbox.x2 AND r.x1 <= inst.trans.off.x-inst.ob.bbox.x1 AND r.y2 >= inst.trans.off.y+inst.ob.bbox.y1 AND r.y1 <= inst.trans.off.y+inst.ob.bbox.y2 ]; rotate90 => RETURN [ r.x2 >= inst.trans.off.x-inst.ob.bbox.y2 AND r.y2 >= inst.trans.off.y+inst.ob.bbox.x1 AND r.x1 <= inst.trans.off.x-inst.ob.bbox.y1 AND r.y1 <= inst.trans.off.y+inst.ob.bbox.x2 ]; rotate90X => RETURN [ r.x2 >= inst.trans.off.x+inst.ob.bbox.y1 AND r.y2 >= inst.trans.off.y+inst.ob.bbox.x1 AND r.x1 <= inst.trans.off.x+inst.ob.bbox.y2 AND r.y1 <= inst.trans.off.y+inst.ob.bbox.x2 ]; rotate180 => RETURN [ r.x2 >= inst.trans.off.x-inst.ob.bbox.x2 AND r.y2 >= inst.trans.off.y-inst.ob.bbox.y2 AND r.x1 <= inst.trans.off.x-inst.ob.bbox.x1 AND r.y1 <= inst.trans.off.y-inst.ob.bbox.y1 ]; rotate180X => RETURN [ r.x2 >= inst.trans.off.x+inst.ob.bbox.x1 AND r.y2 >= inst.trans.off.y-inst.ob.bbox.y2 AND r.x1 <= inst.trans.off.x+inst.ob.bbox.x2 AND r.y1 <= inst.trans.off.y-inst.ob.bbox.y1 ]; rotate270 => RETURN [ r.x2 >= inst.trans.off.x+inst.ob.bbox.y1 AND r.y2 >= inst.trans.off.y-inst.ob.bbox.x2 AND r.x1 <= inst.trans.off.x+inst.ob.bbox.y2 AND r.y1 <= inst.trans.off.y-inst.ob.bbox.x1 ]; rotate270X => RETURN [ r.x2 >= inst.trans.off.x-inst.ob.bbox.y2 AND r.y2 >= inst.trans.off.y-inst.ob.bbox.x2 AND r.x1 <= inst.trans.off.x-inst.ob.bbox.y1 AND r.y1 <= inst.trans.off.y-inst.ob.bbox.x1 ]; ENDCASE => ERROR; }; END.