<> <> <> <> <> DIRECTORY Basics, Pipal, PipalInt; PipalIntInline: CEDAR DEFINITIONS IMPORTS Basics = BEGIN <> Number: TYPE = PipalInt.Number; Vector: TYPE = PipalInt.Vector; Position: TYPE = PipalInt.Position; Size: TYPE = PipalInt.Size; Interval: TYPE = PipalInt.Interval; Rectangle: TYPE = PipalInt.Rectangle; Orientation: TYPE = PipalInt.Orientation; Transformation: TYPE = PipalInt.Transformation; <> <> Add: PROC [v1, v2: Vector] RETURNS [Vector] = INLINE { RETURN [[v1.x+v2.x, v1.y+v2.y]] }; <<>> Sub: PROC [v1, v2: Vector] RETURNS [Vector] = INLINE { RETURN [[v1.x-v2.x, v1.y-v2.y]] }; <<>> Min: PROC [v1, v2: Vector] RETURNS [Vector] = INLINE { RETURN [[MIN [v1.x, v2.x], MIN [v1.y, v2.y]]] }; <<>> Max: PROC [v1, v2: Vector] RETURNS [Vector] = INLINE { RETURN [[MAX [v1.x, v2.x], MAX [v1.y, v2.y]]] }; <<>> Neg: PROC [v: Vector] RETURNS [Vector] = INLINE { RETURN [[-v.x, -v.y]] }; <<>> <> IsDegeneratedSize: PROC [s: Size] RETURNS [BOOL] = INLINE { RETURN [s.x<0 OR s.y<0] }; <<>> IsEmptySize: PROC [s: Size] RETURNS [BOOL] = INLINE { RETURN [s.x<=0 OR s.y<=0] }; <<>> <> IntersectionIntervals: PROC [i1, i2: Interval] RETURNS [interv: Interval] = INLINE {interv.base _ MAX [i1.base, i2.base]; interv.size _ MIN [i1.base+i1.size, i2.base+i2.size] - interv.base }; UnionIntervals: PROC [i1, i2: Interval] RETURNS [interv: Interval] = INLINE {interv.base _ MIN [i1.base, i2.base]; interv.size _ MAX [i1.base+i1.size, i2.base+i2.size] - interv.base }; DoIntervalsIntersect: PROC [i1, i2: Interval] RETURNS [BOOL] = INLINE { RETURN [i1.base<=i2.base+i2.size AND i2.base<=i1.base+i1.size] }; IsInsideInterval: PROC [container, candidate: Interval] RETURNS [BOOL] = INLINE { delta: Number _ candidate.base - container.base; RETURN [delta>=0 AND delta+candidate.size<=container.size] }; IsInsideIntervalNumber: PROC [container: Interval, candidate: Number] RETURNS [BOOL] = INLINE { delta: Number _ candidate - container.base; RETURN [delta>=0 AND delta<=container.size] }; <> <> Translate: PROC [r: Rectangle, v: Vector] RETURNS [Rectangle] = INLINE { RETURN [[Add[r.base, v], r.size]] }; <<>> <> IsDegeneratedRectangle: PROC [r: Rectangle] RETURNS [BOOL] = INLINE { RETURN [IsDegeneratedSize[r.size]] }; IsEmptyRectangle: PROC [r: Rectangle] RETURNS [BOOL] = INLINE { RETURN [IsEmptySize[r.size]] }; DoRectanglesIntersect: PROC [r1, r2: Rectangle] RETURNS [BOOL] = INLINE {RETURN [ DoIntervalsIntersect[[r1.base.x, r1.size.x], [r2.base.x, r2.size.x]] AND DoIntervalsIntersect[[r1.base.y, r1.size.y], [r2.base.y, r2.size.y]]] }; IsInsideRectangle: PROC [container, candidate: Rectangle] RETURNS [BOOL] = INLINE {RETURN [ IsInsideInterval[[container.base.x, container.size.x], [candidate.base.x, candidate.size.x]] AND IsInsideInterval[[container.base.y, container.size.y], [candidate.base.y, candidate.size.y]]] }; <<>> IsInsidePoint: PROC [container: Rectangle, candidate: Position] RETURNS [BOOL] = INLINE {RETURN [ IsInsideIntervalNumber[[container.base.x, container.size.x], candidate.x] AND IsInsideIntervalNumber[[container.base.y, container.size.y], candidate.y]] }; <> Extremity: PROC [r: Rectangle] RETURNS [Position] = INLINE { RETURN [[r.base.x + r.size.x, r.base.y + r.size.y]] }; <> <> <<>> composeTable: READONLY ARRAY Orientation OF ARRAY Orientation OF Orientation; ComposeOrientation: PROC [o1, o2: Orientation] RETURNS [Orientation] = INLINE { RETURN [ composeTable[o1][o2]] }; OrientSize: PROC [orient: Orientation, size: Size] RETURNS [Size] = INLINE { RETURN [IF IncludesOddRot90[orient] THEN [size.y, size.x] ELSE size] }; IncludesOddRot90: PROC [orient: Orientation] RETURNS [BOOL] = INLINE { <> RETURN [Basics.BITAND[ORD[orient], ORD[Orientation[rotate90]]]#0] }; IncludesMirrorX: PROC [orient: Orientation] RETURNS [BOOL] = INLINE { <> RETURN [Basics.BITAND[ORD[orient], ORD[Orientation[mirrorX]]]#0] }; ConcentrateOnRotate90: PROC [orient: Orientation] RETURNS [Orientation] = INLINE { <> RETURN [VAL[Basics.BITAND[ORD[orient], 6]]] }; END. <<>>