<> <> <> <> <> <<>> DIRECTORY ImagerBox, ImagerTransformation, IO, Pipal, PipalInt, PipalReal, PipalRealInline, RefTab; PipalRealImpl: CEDAR PROGRAM IMPORTS ImagerTransformation, IO, Pipal, PipalInt, PipalRealInline, RefTab EXPORTS PipalReal, PipalRealInline = BEGIN OPEN PipalReal; <> VectorToRope: PUBLIC PROC [v: Vector] RETURNS [rope: Pipal.ROPE] = { rope _ IO.PutFR["[%g, %g]", IO.real[v.x], IO.real[v.y]]; }; RectangleToRope: PUBLIC PROC [r: Rectangle] RETURNS [rope: Pipal.ROPE] = { rope _ IO.PutFR["[base: %g, size: %g]", IO.rope[VectorToRope[r.base]], IO.rope[VectorToRope[r.size]]]; }; TransformationToRope: PUBLIC PROC [t: Transformation] RETURNS [rope: Pipal.ROPE] = { rope _ IO.PutFR["[...Transformation...]"]; }; <> Add: PUBLIC PROC [v1, v2: Vector] RETURNS [Vector] = { RETURN [PipalRealInline.Add[v1, v2]] }; Sub: PUBLIC PROC [v1, v2: Vector] RETURNS [Vector] = { RETURN [PipalRealInline.Sub[v1, v2]] }; Min: PUBLIC PROC [v1, v2: Vector] RETURNS [Vector] = { RETURN [PipalRealInline.Min[v1, v2]] }; Max: PUBLIC PROC [v1, v2: Vector] RETURNS [Vector] = { RETURN [PipalRealInline.Max[v1, v2]] }; Neg: PUBLIC PROC [v: Vector] RETURNS [Vector] = { RETURN [PipalRealInline.Neg[v]] }; IsDegeneratedSize: PUBLIC PROC [s: Size] RETURNS [BOOL] = { RETURN [PipalRealInline.IsDegeneratedSize[s]] }; IsEmptySize: PUBLIC PROC [s: Size] RETURNS [BOOL] = { RETURN [PipalRealInline.IsEmptySize[s]] }; <> IntersectionIntervals: PUBLIC PROC [i1, i2: Interval] RETURNS [Interval] = { RETURN [PipalRealInline.IntersectionIntervals[i1, i2]] }; UnionIntervals: PUBLIC PROC [i1, i2: Interval] RETURNS [Interval] = { RETURN [PipalRealInline.UnionIntervals[i1, i2]] }; DoIntervalsIntersect: PUBLIC PROC [i1, i2: Interval] RETURNS [BOOL] = { RETURN [PipalRealInline.DoIntervalsIntersect[i1, i2]] }; IsInsideInterval: PUBLIC PROC [container, candidate: Interval] RETURNS [BOOL] = { RETURN [PipalRealInline.IsInsideInterval[container, candidate]] }; IsInsideIntervalNumber: PUBLIC PROC [container: Interval, candidate: Number] RETURNS [BOOL] = { RETURN [PipalRealInline.IsInsideIntervalNumber[container, candidate]] }; <> <> Translate: PUBLIC PROC [r: Rectangle, v: Vector] RETURNS [Rectangle] = { RETURN [PipalRealInline.Translate[r, v]] }; Extend: PUBLIC PROC [r: Rectangle, n: Number] RETURNS [Rectangle] = { RETURN [[[r.base.x-n, r.base.y-n], [r.size.x+n+n, r.size.y+n+n]]] }; IntersectBox: PUBLIC PROC [r1, r2: Rectangle] RETURNS [r: Rectangle] = { <> r.base _ PipalRealInline.Max[r1.base, r2.base]; r.size _ PipalRealInline.Sub[PipalRealInline.Min[PipalRealInline.Extremity[r1], PipalRealInline.Extremity[r2]], r.base]; }; BoundingBox: PUBLIC PROC [r1, r2: Rectangle] RETURNS [r: Rectangle] = { <> r.base _ PipalRealInline.Min[r1.base, r2.base]; r.size _ PipalRealInline.Sub[PipalRealInline.Max[PipalRealInline.Extremity[r1], PipalRealInline.Extremity[r2]], r.base]; }; BoundingRectangle: PUBLIC PROC [p1, p2: Position] RETURNS [r: Rectangle] = { <> r.base _ PipalRealInline.Min[p1, p2]; r.size _ PipalRealInline.Sub[PipalRealInline.Max[p1, p2], r.base]; }; <> IsDegeneratedRectangle: PUBLIC PROC [r: Rectangle] RETURNS [BOOL] = { RETURN [PipalRealInline.IsDegeneratedRectangle[r]] }; IsEmptyRectangle: PUBLIC PROC [r: Rectangle] RETURNS [BOOL] = { RETURN [PipalRealInline.IsEmptyRectangle[r]] }; DoRectanglesIntersect: PUBLIC PROC [r1, r2: Rectangle] RETURNS [BOOL] = { RETURN [PipalRealInline.DoRectanglesIntersect[r1, r2]] }; IsInsideRectangle: PUBLIC PROC [container, candidate: Rectangle] RETURNS [BOOL] = { RETURN [PipalRealInline.IsInsideRectangle[container, candidate]] }; IsInsidePoint: PUBLIC PROC [container: Rectangle, candidate: Position] RETURNS [BOOL] = { RETURN [PipalRealInline.IsInsidePoint[container, candidate]] }; <> AlwaysQuit: PUBLIC RectangleProc = {quit _ TRUE}; Extremity: PUBLIC PROC [r: Rectangle] RETURNS [Position] = { RETURN [PipalRealInline.Extremity[r]] }; DecomposeRect: PUBLIC PROC [r, clip: Rectangle, inside, outside: RectangleProc _ NIL] RETURNS [quit: BOOL _ FALSE] = { clipext: Position = PipalRealInline.Extremity[clip]; rext: Position = PipalRealInline.Extremity[r]; delta: Vector = PipalRealInline.Sub[r.base, clip.base]; IF clip.base.x> TransformVector: PUBLIC PROC [t: Transformation, v: Vector] RETURNS [Vector] = { <> RETURN [ImagerTransformation.Transform[t, v]]; }; TransformBBox: PUBLIC PROC [t: Transformation, s: Size] RETURNS [Rectangle] = { <> RETURN [TransformRectangle[t, [zeroVector, s]]]; }; TransformRectangle: PUBLIC PROC [t: Transformation, r: Rectangle] RETURNS [rr: Rectangle] = { <> ir: ImagerBox.Rectangle = ImagerTransformation.TransformRectangle[t, [r.base.x, r.base.y, r.size.x, r.size.y]]; rr _ [[ir.x, ir.y], [ir.w, ir.h]]; }; Compose: PUBLIC PROC [t1, t2: Transformation] RETURNS [Transformation] = { <> RETURN [ImagerTransformation.Concat[t2, t1]]; }; Apply: PUBLIC PROC [t1, t2: Transformation] = { <> ImagerTransformation.ApplyPreConcat[t1, t2]; }; CreateTransformation: PUBLIC PROC RETURNS [Transformation] = { RETURN [ImagerTransformation.Create[1, 0, 0, 0, 1, 0]]}; CopyTransformation: PUBLIC PROC [t: Transformation] RETURNS [Transformation] = { RETURN [ImagerTransformation.Copy[t]]}; DestroyTransformation: PUBLIC PROC [t: Transformation] = {ImagerTransformation.Destroy[t]}; EqualTransformation: PUBLIC PROC [t1, t2: Transformation] RETURNS [BOOL] = {RETURN [ImagerTransformation.CloseEnough[t1, t2]]}; <> enumerateMethod: PUBLIC Pipal.Method _ Pipal.RegisterMethod["RealEnumerate"]; HasEnumerate: PUBLIC PROC [object: Pipal.Object] RETURNS [BOOL] = { RETURN [Pipal.ObjectMethod[object, enumerateMethod]#NIL OR Pipal.ObjectMethod[object, PipalInt.enumerateMethod]#NIL]; }; Enumerate: PUBLIC EnumerateProc = { data: REF _ Pipal.ObjectMethod[object, enumerateMethod]; quit _ (IF data=NIL THEN UseIntEnumerate ELSE NARROW [data, REF EnumerateProc]^)[object, each, transformation]; }; UseIntEnumerate: EnumerateProc = { EachChild: PipalInt.EachChildProc = { realTransformation: Transformation _ CopyTransformation[rt]; ApplyRealInt[realTransformation, transformation]; quit _ each[realTransformation, child]; DestroyTransformation[realTransformation]; }; rt: Transformation _ transformation; -- just renaming! quit _ PipalInt.Enumerate[object, EachChild]; }; NthChild: PUBLIC PROC [object: Pipal.Object, transformation: Transformation, rank: NAT _ 0] RETURNS [nthTrans: Transformation, nthChild: Pipal.Object _ NIL] = { EachChild: EachChildProc = { IF rank=0 THEN {nthChild _ child; nthTrans _ CopyTransformation[transformation]; quit _ TRUE} ELSE rank _ rank - 1; }; [] _ Enumerate[object, EachChild, transformation]; }; CountChildren: PUBLIC PROC [object: Pipal.Object] RETURNS [count: NAT _ 0] = { realTransformation: Transformation _ CreateTransformation[]; EachChild: EachChildProc = {count _ count + 1}; [] _ Enumerate[object, EachChild, realTransformation]; DestroyTransformation[realTransformation]; }; <> <> <<>> sizeMethod: PUBLIC Pipal.Method _ Pipal.RegisterMethod["RealSize"]; bboxMethod: PUBLIC Pipal.Method _ Pipal.RegisterMethod["RealBBox"]; ObjectSize: PUBLIC SizeProc = { ref: REF = Pipal.ObjectMethod[object, sizeMethod]; size _ (IF ref=NIL THEN SizeFromEnumerate ELSE NARROW [ref, REF SizeProc]^)[object]; }; BBox: PUBLIC BBoxProc = { ref: REF = Pipal.ObjectMethod[object, bboxMethod]; bbox _ (SELECT TRUE FROM ref#NIL => (NARROW [ref, REF BBoxProc]^), HasEnumerate[object] => BBoxFromEnumerate, ENDCASE => BBoxFromSize)[object, transformation]; }; UseIntSize: PUBLIC SizeProc = { size _ PipalRealInline.IntToRealVector[PipalInt.ObjectSize[object]]; }; SizeFromEnumerate: SizeProc = { transformation: Transformation _ CreateTransformation[]; size _ BBoxFromEnumerate[object, transformation].size; DestroyTransformation[transformation]; }; BBoxFromEnumerate: BBoxProc = { ComputeBBoxRec: EachChildProc = { bbox _ BoundingBox[bbox, BBox[child, transformation]]; }; bbox _ emptyRectangle; [] _ Enumerate[object, ComputeBBoxRec, transformation]; }; BBoxFromSize: BBoxProc = { bbox _ TransformRectangle[transformation, [zeroVector, ObjectSize[object]]]; }; cachedSizes: Pipal.ObjectCache _ Pipal.CreateObjectCache[]; CachedSizeFromEnumerate: PUBLIC SizeProc = { refSize: REF Size _ NARROW [RefTab.Fetch[cachedSizes, object].val]; IF refSize#NIL THEN RETURN [refSize^]; size _ SizeFromEnumerate[object]; refSize _ NEW [Size _ size]; [] _ RefTab.Store[cachedSizes, object, refSize]; }; cachedBBoxes: Pipal.ObjectCache _ Pipal.CreateObjectCache[]; CachedBBoxFromEnumerate: PUBLIC BBoxProc = { refBBox: REF Rectangle _ NARROW [RefTab.Fetch[cachedBBoxes, object].val]; IF refBBox#NIL THEN bbox _ refBBox^ ELSE { transformation: Transformation _ CreateTransformation[]; bbox _ BBoxFromEnumerate[object, transformation]; DestroyTransformation[transformation]; refBBox _ NEW [Rectangle _ bbox]; [] _ RefTab.Store[cachedBBoxes, object, refBBox]; }; bbox _ TransformRectangle[transformation, bbox]; }; <> <> transformClass: PUBLIC Pipal.Class _ Pipal.RegisterClass["RealTransform", CODE [TransformRec]]; EnumerateTransform: EnumerateProc = { transform: Transform _ NARROW [object]; rt: Transformation _ Compose[transformation, transform.transformation]; quit _ each[rt, transform.child]; DestroyTransformation[rt]; }; DescribeTransform: Pipal.DescribeProc = { transform: Transform _ NARROW [object]; Pipal.PutIndent[out, indent, cr]; IO.PutF[out, "RealTransform %g of : ", IO.rope[TransformationToRope[transform.transformation]]]; Pipal.Describe[out, transform.child, indent+1, level-1, cr]; }; CreateTransform: PUBLIC PROC [transformation: Transformation, child: Pipal.Object] RETURNS [transform: Transform] = { transform _ NEW [TransformRec _ [transformation, child]]; }; <> identityTransformation: PRIVATE Transformation = CreateTransformation[]; TransformObject: PUBLIC PROC [transformation: Transformation, child: Pipal.Object] RETURNS [Pipal.Object] = { RETURN [SELECT TRUE FROM transformation=identityTransformation => child, ENDCASE => CreateTransform[transformation, child] ]; }; <> IntToRealVector: PUBLIC PROC [v: PipalInt.Vector] RETURNS [Vector] = {RETURN [PipalRealInline.IntToRealVector[v]]}; IntToRealRectangle: PUBLIC PROC [r: PipalInt.Rectangle] RETURNS [Rectangle] = {RETURN [PipalRealInline.IntToRealRectangle[r]]}; IntToRealTransformation: PUBLIC PROC [t: PipalInt.Transformation] RETURNS [Transformation] = {RETURN [PipalRealInline.IntToRealTransformation[t]]}; ApplyRealInt: PUBLIC PROC [t1: Transformation, t2: PipalInt.Transformation] = { <> rt: Transformation _ PipalRealInline.IntToRealTransformation[t2]; Apply[t1, rt]; DestroyTransformation[rt]; }; <> <> EnumerateOverlay: EnumerateProc ~ { overlay: Pipal.Overlay _ NARROW [object]; FOR i: NAT IN [0..overlay.size) DO IF each[transformation, overlay[i]] THEN RETURN[TRUE]; ENDLOOP; }; BBoxAnnotation: BBoxProc = { annotation: Pipal.Annotation _ NARROW [object]; bbox _ BBox[annotation.child, transformation]; IF annotation.key=PipalInt.abutBoxProp THEN bbox _ BoundingBox[ bbox, TransformRectangle[transformation, PipalRealInline.IntToRealRectangle[(NARROW [annotation.value, REF PipalInt.Rectangle]^)]] ]; }; <> Pipal.PutClassMethod[Pipal.overlayClass, enumerateMethod, NEW [EnumerateProc _ EnumerateOverlay]]; -- speed up only Pipal.PutClassMethod[Pipal.overlayClass, sizeMethod, NEW [SizeProc _ CachedSizeFromEnumerate]]; -- speed up only Pipal.PutClassMethod[Pipal.overlayClass, bboxMethod, NEW [BBoxProc _ CachedBBoxFromEnumerate]]; -- speed up only Pipal.PutClassMethod[Pipal.annotationClass, bboxMethod, NEW [BBoxProc _ BBoxAnnotation]]; <> Pipal.PutClassMethod[transformClass, enumerateMethod, NEW [EnumerateProc _ EnumerateTransform]]; Pipal.PutClassMethod[transformClass, Pipal.describeMethod, NEW [Pipal.DescribeProc _ DescribeTransform]]; END. <<>>