DIRECTORY
GGBasicTypes, GGBoundBox, GGError, GGLines, GGModelTypes, GGInterfaceTypes, GGObjects, GGSegmentTypes, GGSelect, GGShapes, GGVector, Imager, ImagerTransformation, Real, RealFns;

GGBoundBoxImpl: CEDAR PROGRAM
IMPORTS GGBoundBox, GGError, GGLines, GGObjects, GGSelect, GGShapes, GGVector, Imager, ImagerTransformation, RealFns
EXPORTS GGBoundBox = BEGIN

BoundBox: TYPE = REF BoundBoxObj;
BoundBoxObj: TYPE = GGBasicTypes.BoundBoxObj;
Circle: TYPE = GGBasicTypes.Circle;
Edge: TYPE = GGBasicTypes.Edge;
EntityGenerator: TYPE = GGModelTypes.EntityGenerator;
Joint: TYPE = GGModelTypes.Joint;
Line: TYPE = GGBasicTypes.Line;
MaskArray: TYPE = GGBoundBox.MaskArray;
Outline: TYPE = GGModelTypes.Outline;
OutlineDescriptor: TYPE = GGModelTypes.OutlineDescriptor;
Point: TYPE = GGBasicTypes.Point;
Scene: TYPE = GGModelTypes.Scene;
Segment: TYPE = GGSegmentTypes.Segment;
SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator;
Sequence: TYPE = GGModelTypes.Sequence;
Slice: TYPE = GGModelTypes.Slice;
SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor;
SliceParts: TYPE = GGModelTypes.SliceParts;
Traj: TYPE = GGModelTypes.Traj;
TrajGenerator: TYPE = GGModelTypes.TrajGenerator;
Vector: TYPE = GGBasicTypes.Vector;

emptyBoundBox: PUBLIC BoundBox _ NEW[GGBasicTypes.BoundBoxObj _ [loX: Real.LargestNumber, loY: Real.LargestNumber, hiX: Real.SmallestNormalizedNumber, hiY: Real.SmallestNormalizedNumber, null: TRUE, infinite: FALSE] ];



CreateBoundBox: PUBLIC PROC [loX, loY, hiX, hiY: REAL, null: BOOL _ FALSE, infinite: BOOL _ FALSE] RETURNS [bBox: BoundBox] = {
bBox _ NEW[BoundBoxObj _ [loX, loY, hiX, hiY, null, infinite]];
};

NullBoundBox: PUBLIC PROC [] RETURNS [bBox: BoundBox] = {
bBox _ NEW[BoundBoxObj _ [0,0,0,0, TRUE, FALSE]];
};

CopyBoundBox: PUBLIC PROC [bBox: BoundBox] RETURNS [copy: BoundBox] = {
copy _ NEW[BoundBoxObj _ [bBox.loX, bBox.loY, bBox.hiX, bBox.hiY, bBox.null, bBox.infinite]];
};

UpdateCopyBoundBox: PUBLIC PROC [bBox: BoundBox, from: BoundBox] = {
bBox^ _ from^;
};

BoundBoxOfBoxes: PUBLIC PROC [list: LIST OF BoundBox] RETURNS [bigBox: BoundBox] = {
bigBox _ NEW[BoundBoxObj];
WHILE list # NIL AND list.first.null DO list _ list.rest ENDLOOP;
IF list = NIL THEN {bigBox.null _ TRUE; bigBox.infinite _ FALSE; RETURN};
CopyContents[bigBox, list.first];
FOR bBoxList: LIST OF BoundBox _ list.rest, bBoxList.rest UNTIL bBoxList = NIL DO
IF bBoxList.first.infinite THEN {bigBox.null _ FALSE;  bigBox.infinite _ TRUE; RETURN};
EnlargeByBox[bBox: bigBox, by: bBoxList.first];
ENDLOOP;
};

BoundBoxOfBoundBox: PUBLIC PROC [box: BoundBox, transform: ImagerTransformation.Transformation] RETURNS [newBox: BoundBox] = {
rect: Imager.Rectangle _ RectangleFromBoundBox[box];
rect _ ImagerTransformation.TransformRectangle[transform, rect];
newBox _ BoundBoxFromRectangle[rect];
};

UpdateBoundBoxOfBoundBox: PUBLIC PROC [bBox: BoundBox, localBox: BoundBox, transform: ImagerTransformation.Transformation] = {
rect: Imager.Rectangle _ RectangleFromBoundBox[localBox];
rect _ ImagerTransformation.TransformRectangle[transform, rect];
UpdateBoundBoxFromRectangle[bBox, rect];
};

BoundBoxFromRectangle: PUBLIC PROC [rect: Imager.Rectangle] RETURNS [bBox: BoundBox] = {
bBox _ NEW[BoundBoxObj _ [rect.x, rect.y, rect.x + rect.w, rect.y + rect.h, FALSE, FALSE]];
};

UpdateBoundBoxFromRectangle: PUBLIC PROC [bBox: BoundBox, rect: Imager.Rectangle] = {
bBox^ _ [rect.x, rect.y, rect.x + rect.w, rect.y + rect.h, FALSE, FALSE];
};

RectangleFromBoundBox: PUBLIC PROC [bBox: BoundBox] RETURNS [rect: Imager.Rectangle] = {
IF bBox.infinite THEN ERROR;
IF bBox.null THEN rect _ [bBox.loX, bBox.loY, 0.0, 0.0]
ELSE rect _ [bBox.loX, bBox.loY, bBox.hiX - bBox.loX, bBox.hiY - bBox.loY];
};

BoundBoxOfPixelArray: PUBLIC PROC [pa: Imager.PixelArray] RETURNS [bBox: BoundBox] = {
xPixels, yPixels: REAL;
xPixels _ pa.sSize;
yPixels _ pa.fSize;
bBox _ GGBoundBox.CreateBoundBox[0, 0, xPixels, yPixels];
bBox _ GGBoundBox.BoundBoxOfBoundBox[bBox, pa.m];
};
BoundBoxOfBitMap: PUBLIC PROC [base: LONG POINTER, wordsPerLine: NAT, 
sMin, fMin, sSize, fSize: NAT, tx, ty: INTEGER _ 0] RETURNS [bBox: BoundBox] = {

};

AllowForJoints: PUBLIC PROC [box: BoundBox] = {
cpHalf: REAL _ GGModelTypes.halfJointSize + 1;
box^ _ [loX: box.loX-cpHalf, loY: box.loY-cpHalf, hiX: box.hiX+cpHalf, hiY: box.hiY+cpHalf, null: box.null, infinite: box.infinite];
};

EnlargeByBox: PUBLIC PROC [bBox: BoundBox, by: BoundBox] = {
IF bBox.infinite OR by.null THEN RETURN;
IF by.infinite THEN {bBox.infinite _ TRUE; bBox.null _ FALSE; RETURN};
IF bBox.null THEN {CopyContents[to: bBox, from: by]; RETURN};
bBox.loX _ MIN[bBox.loX, by.loX];
bBox.hiX _ MAX[bBox.hiX, by.hiX];
bBox.loY _ MIN[bBox.loY, by.loY];
bBox.hiY _ MAX[bBox.hiY, by.hiY];
};

EnlargeByPoint: PUBLIC PROC [bBox: BoundBox, point: Point] = {
IF bBox.infinite THEN RETURN;
IF bBox.null THEN {
bBox.loX _ bBox.hiX _ point.x;
bBox.loY _ bBox.hiY _ point.y;
bBox.null _ FALSE;
RETURN;
};
bBox.loX _ MIN[bBox.loX, point.x];
bBox.hiX _ MAX[bBox.hiX, point.x];
bBox.loY _ MIN[bBox.loY, point.y];
bBox.hiY _ MAX[bBox.hiY, point.y];
};

EnlargeByVector: PUBLIC PROC [bBox: BoundBox, vector: Vector] = {
IF bBox.null OR bBox.infinite THEN RETURN;
IF vector.x <0.0
THEN bBox.loX _ bBox.loX + vector.x
ELSE bBox.hiX _ bBox.hiX + vector.x;
IF vector.y <0.0
THEN bBox.loY _ bBox.loY + vector.y
ELSE bBox.hiY _ bBox.hiY + vector.y;
};

EnlargeByOffset: PUBLIC PROC [bBox: BoundBox, offset: REAL] = {
IF bBox.null OR bBox.infinite THEN RETURN;
bBox.loX _ bBox.loX - offset;
bBox.hiX _ bBox.hiX + offset;
bBox.loY _ bBox.loY - offset;
bBox.hiY _ bBox.hiY + offset;
};

UpdateBoundBox: PUBLIC PROC [bBox: BoundBox, loX, loY, hiX, hiY: REAL] = {
bBox.loX _ loX;
bBox.loY _ loY;
bBox.hiX _ hiX;
bBox.hiY _ hiY;
bBox.null _ FALSE;
bBox.infinite _ FALSE;
};



PointIsInBox: PUBLIC PROC [test: Point, box: GGBasicTypes.BoundBoxObj] RETURNS [BOOL] = {
RETURN[ NOT (test.x < box.loX OR test.x > box.hiX OR test.y < box.loY OR test.y > box.hiY) ];
};


BoundBoxOfSelected: PUBLIC PROC [scene: Scene, selectClass: GGInterfaceTypes.SelectionClass _ normal] RETURNS [bigBox: BoundBox] = {
entityGen: EntityGenerator;
entity: REF ANY;
nextBox: BoundBox;
bigBox _ GGBoundBox.NullBoundBox[];
entityGen _ GGSelect.SelectedStuff[scene, selectClass];
FOR entity _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO
WITH entity SELECT FROM
sliceD: SliceDescriptor => {
nextBox _ sliceD.slice.class.getBoundBox[sliceD.slice, sliceD.parts];
};
outlineD: OutlineDescriptor => { 
nextBox _ outlineD.slice.class.getBoundBox[outlineD.slice, outlineD.parts];
};
ENDCASE => ERROR;
EnlargeByBox[bBox: bigBox, by: nextBox];
ENDLOOP;
};

useSelected: BOOL _ FALSE;
BoundBoxOfMoving: PUBLIC PROC [scene: Scene, selectClass: GGInterfaceTypes.SelectionClass _ normal] RETURNS [bigBox: BoundBox] = {

entityGen: EntityGenerator;
entity: REF ANY;
nextBox: BoundBox;
IF useSelected THEN RETURN[BoundBoxOfSelected[scene, selectClass]];
bigBox _ GGBoundBox.NullBoundBox[];
entityGen _ GGSelect.SelectedStuff[scene, selectClass];
FOR entity _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO
WITH entity SELECT FROM
sliceD: SliceDescriptor => {
movingParts: SliceParts _ sliceD.slice.class.movingParts[sliceD.slice, sliceD.parts];
nextBox _ sliceD.slice.class.getBoundBox[sliceD.slice, movingParts];
};
outlineD: OutlineDescriptor => { 
movingParts: SliceParts _ outlineD.slice.class.movingParts[outlineD.slice, outlineD.parts];
nextBox _ outlineD.slice.class.getBoundBox[outlineD.slice, movingParts];
};
ENDCASE => ERROR;
EnlargeByBox[bBox: bigBox, by: nextBox];
ENDLOOP;
};

CopyContents: PROC [to: BoundBox, from: BoundBox] = {
to^ _ [from.loX, from.loY, from.hiX, from.hiY, from.null, from.infinite];
};

DrawBoundBox: PUBLIC PROC [dc: Imager.Context, bBox: BoundBox] = {
GGShapes.DrawRectangle[dc, bBox.loX, bBox.loY, bBox.hiX, bBox.hiY];
};

EraseWithinBoundBox: PUBLIC PROC [dc: Imager.Context, bBox: BoundBox] = {
EraseWithinBoundBoxAux: PROC = {
rect: Imager.Rectangle _ [x: bBox.loX, y: bBox.loY, w: bBox.hiX-bBox.loX, h: bBox.hiY-bBox.loY];
Imager.SetColor[dc, Imager.white];
Imager.MaskRectangle[dc, rect];
};
IF bBox.null OR bBox.infinite THEN RETURN;
Imager.DoSaveAll[dc, EraseWithinBoundBoxAux];
};

Clip: PUBLIC PROC [dc: Imager.Context, bBox: BoundBox] = {
IF bBox.null THEN ERROR;
IF bBox.infinite THEN RETURN;
Imager.ClipRectangle[dc, [bBox.loX, bBox.loY, (bBox.hiX-bBox.loX), (bBox.hiY-bBox.loY)]];
};

NearestPoint: PUBLIC PROC [bBox: BoundBox, testPoint: Point, tolerance: REAL _ 1E6, mask: MaskArray _ ALL[TRUE] ] RETURNS [bestDist: REAL, bestJoint: NAT, bestPoint: Point, success: BOOL] = {
thisPoint: Point;
thisDist2, bestDist2: REAL;
tolerance2: REAL _ tolerance*tolerance;
index: NAT _ 0;
IF bBox.null OR bBox.infinite THEN
RETURN[bestDist: 99999.0, bestJoint: 999, bestPoint: [-1.0, -1.0], success: FALSE];
bestPoint _ [-1.0, -1.0];
bestDist2 _ 1E12; -- better be big enough
bestJoint _ 9999;
success _ FALSE;
FOR index IN [0..4) DO
IF mask[index] THEN {
thisPoint _ BoxPoint[bBox, index];
thisDist2 _ GGVector.DistanceSquared[thisPoint, testPoint];
IF thisDist2 < bestDist2 THEN {
bestDist2 _ thisDist2;
bestJoint _ index;
bestPoint _ thisPoint;
IF bestDist2 < tolerance2 THEN success _ TRUE;
};
};
ENDLOOP;
bestDist _ RealFns.SqRt[bestDist2];
};

NearestSegment: PUBLIC PROC [bBox: BoundBox, testPoint: Point, tolerance: REAL _ 1E6, mask: MaskArray _ ALL[TRUE] ] RETURNS [bestDist: REAL, bestSeg: NAT, bestPoint: Point, success: BOOL] = {
thisDist2, bestDist2: REAL;
thisPoint: Point;
tolerance2: REAL _ tolerance*tolerance;
index: NAT _ 0;
IF bBox.null OR bBox.infinite THEN
RETURN[bestDist: 99999.0, bestSeg: 999, bestPoint: [-1.0, -1.0], success: FALSE];
bestPoint _ [-1.0, -1.0];
bestDist2 _ 1E12; -- better be big enough
bestSeg _ 9999;
success _ FALSE;
FOR index IN [0..4) DO
IF mask[index] THEN {
FillBoxEdge[globalBoxEdge, bBox, index];
thisPoint _ GGLines.NearestPointOnEdge[testPoint, globalBoxEdge];
thisDist2 _ GGVector.DistanceSquared[thisPoint, testPoint];
IF thisDist2 < bestDist2 THEN {
bestDist2 _ thisDist2;
bestSeg _ index;
bestPoint _ thisPoint;
IF thisDist2 < tolerance2 THEN success _ TRUE;
};
};
ENDLOOP;
bestDist _ RealFns.SqRt[bestDist2];
};

LineMeetsBoundBox: PUBLIC PROC [bBox: BoundBox, line: Line] RETURNS [points: LIST OF Point, pointCount: NAT] = {
noHit: BOOL;
hits: ARRAY[0..3] OF BOOL;
hitPoints: ARRAY[0..3] OF Point;
hitPoint: Point;
epsilon: REAL = 0.072;
points _ NIL;
pointCount _ 0;
FOR i: NAT IN [0..3] DO hits[i] _ FALSE; ENDLOOP;
FOR i: NAT IN [0..2] DO
FillBoxEdge[globalEdge, bBox, i];
[hitPoints[i], noHit] _ GGLines.LineMeetsEdge[line, globalEdge]; -- global scratch edge
IF noHit THEN LOOP;
IF i>0 AND hits[i-1] THEN {
IF ABS[hitPoints[i].x - hitPoints[i-1].x] < epsilon THEN LOOP;
IF ABS[hitPoints[i].y - hitPoints[i-1].y] < epsilon THEN LOOP;
};
points _ CONS[hitPoint, points];
pointCount _ pointCount + 1;
hits[i] _ TRUE;
REPEAT
FINISHED => {
FillBoxEdge[globalEdge, bBox, 3];
[hitPoints[3], noHit] _ GGLines.LineMeetsEdge[line, globalEdge];
IF noHit THEN GOTO End;
IF hits[2] THEN {
IF ABS[hitPoints[3].x - hitPoints[2].x] < epsilon THEN GOTO End;
IF ABS[hitPoints[3].y - hitPoints[2].y] < epsilon THEN GOTO End;
};
IF hits[0] THEN {
IF ABS[hitPoints[3].x - hitPoints[0].x] < epsilon THEN GOTO End;
IF ABS[hitPoints[3].y - hitPoints[0].y] < epsilon THEN GOTO End;
};
points _ CONS[hitPoint, points];
pointCount _ pointCount + 1;
hits[3] _ TRUE;
EXITS
End => NULL;
};
ENDLOOP;
IF pointCount > 2 THEN ERROR;
};

CircleMeetsBoundBox: PUBLIC PROC [bBox: BoundBox, circle: Circle] RETURNS [points: LIST OF Point, pointCount: NAT] = {
SIGNAL GGError.Problem[msg: "Not yet implemented"];
};

BoxPoint: PROC [bBox: BoundBox, index: NAT] RETURNS [point: Point] ~ {
IF bBox.null OR bBox.infinite THEN ERROR;
SELECT index FROM
0 => point _ [bBox.loX, bBox.loY];
1 => point _ [bBox.loX, bBox.hiY];
2 => point _ [bBox.hiX, bBox.hiY];
3 => point _ [bBox.hiX, bBox.loY];
ENDCASE => ERROR;
};

FillBoxEdge: PRIVATE PROC [edge: Edge, bBox: BoundBox, index: NAT] = {
IF bBox.null OR bBox.infinite THEN ERROR;
SELECT index FROM
0 => GGLines.FillEdge[[bBox.loX, bBox.loY], [bBox.loX, bBox.hiY], edge];
1 => GGLines.FillEdge[[bBox.loX, bBox.hiY], [bBox.hiX, bBox.hiY], edge];
2 => GGLines.FillEdge[[bBox.hiX, bBox.hiY], [bBox.hiX, bBox.loY], edge];
3 => GGLines.FillEdge[[bBox.hiX, bBox.loY], [bBox.loX, bBox.loY], edge];
ENDCASE => ERROR;
};

globalEdge: Edge;
globalBoxEdge: Edge;

Init: PROC [] = {
globalEdge _ GGLines.CreateEmptyEdge[];
globalBoxEdge _ GGLines.CreateEmptyEdge[];
};

Init[];

END.
���r��GGBoundBoxImpl.mesa
Copyright c 1985 by Xerox Corporation.  All rights reserved.
Last edited by Bier on December 28, 1986 2:47:12 pm PST
Contents:  Procedures for creating and combining bounding boxes for refresh efficiency.
Pier, December 12, 1986 1:33:10 pm PST
David Kurlander August 23, 1986 5:04:15 pm PDT

Routines which create a new boundBox.
Computes a bounding box in units of screen dots for the given bit map.  The lower left corner will be [0,0].

Routines which modify or return an existing boundBox.
Update bBox to be the bounding box of itself and itself offset by vector.  Useful to take drop shadows into account, for instance.
Enlarges bBox to include a border of width offset around bBox.  Useful to allow for stroke width of a segment, for instance.
Routines which operate on BoundBoxObj (which is presumably allocated on the execution stack).
Routines which require knowledge of Gargoyle data structures.

routine called to calculate the boundBox of all objects that are about to move; that is, all selected slices, selected CPs, selected joints AND the dangling segments of selected joints AND the segments of selected CPs.
Utilities

AllowForArrowHeads: PROC [bBox: BoundBox, traj: Traj] = {
arrowHeight, arrowHalfWidth, firstWidth, lastWidth, delta: REAL;

firstWidth _ GGTraj.FetchSegment[traj, 0].strokeWidth;
lastWidth _ GGTraj.FetchSegment[traj, GGTraj.HiSegment[traj]].strokeWidth;
[arrowHeight, arrowHalfWidth] _ GGShapes.ArrowSize[MAX[firstWidth, lastWidth]];
IF arrowHalfWidth > GGModelTypes.halfJointSize THEN {
delta _ arrowHalfWidth - GGModelTypes.halfJointSize;
bBox.loX _ bBox.loX - delta;
bBox.hiX _ bBox.hiX + delta;
bBox.loY _ bBox.loY - delta;
bBox.hiY _ bBox.hiY + delta;
};
};


Drawing BoundBoxes.

Hit Testing BoundBoxes.

Finds the corner of bBox which is in mask and nearest to testPoint (and its distance from testPoint).  Number the corners of a bBox 0..3 clockwise starting with the lower left corner.
Finds the segment of bBox which is in mask and nearest to testPoint (and its distance from testPoint).  Number the segments of a bBox 0..3 clockwise starting with the left edge.
Find the intersections of the given line with bBox.  pointCount will be at most 2.
Find the intersections of the given circle with bBox.  pointCount will be at most 8.
 [Artwork node; type 'ArtworkInterpress on' to command tool] 
Number the joints 0..3 clockwise starting at the lower left hand corner.  Return the requested point.
BoxEdge: PRIVATE PROC [bBox: BoundBox, index: NAT] RETURNS [edge: Edge] = {
IF bBox.null OR bBox.infinite THEN ERROR;
SELECT index FROM
0 => edge _ GGLines.CreateEdge[[bBox.loX, bBox.loY], [bBox.loX, bBox.hiY]];
1 => edge _ GGLines.CreateEdge[[bBox.loX, bBox.hiY], [bBox.hiX, bBox.hiY]];
2 => edge _ GGLines.CreateEdge[[bBox.hiX, bBox.hiY], [bBox.hiX, bBox.loY]];
3 => edge _ GGLines.CreateEdge[[bBox.hiX, bBox.loY], [bBox.loX, bBox.loY]];
ENDCASE => ERROR;
};

Ê6��˜�codešœ™Kšœ<™<Kšœ7™7KšœW™WK™&Kšœ.™.—K™�šÏk	˜	Kšœ±˜±K˜�—šÏnœœ˜Kšœm˜tKšœ
˜—˜�Kšœ
œœ
˜!Kšœ
œ˜-Kšœœ˜#Kšœœ˜Kšœœ ˜5Kšœœ˜!Kšœœ˜Kšœœ˜'Kšœ	œ˜%Kšœœ"˜9Kšœœ˜!Kšœœ˜!Kšœ	œ˜'Kšœœ!˜7Kšœ
œ˜'Kšœœ˜!Kšœœ ˜5Kšœœ˜+Kšœœ˜Kšœœ˜1Kšœœ˜#—K˜�Kš	œœœœœ˜ÚK˜�K˜�Kšœ%™%K˜�šžœœœœœœœœœ˜Kšœœ5˜?K˜K˜�—šžœœœœ˜9Kšœœœœ˜1K˜K˜�—šžœœœœ˜GKšœœS˜]K˜K˜�—šžœœœ%˜DKšœ˜K˜K˜�—šžœœœœœœ˜TKšœ	œ˜Kš
œœœœœ˜AKšœœœœœœ˜IKšœ!˜!šœœœ%œœ˜QKš
œœœœœ˜WKšœ/˜/Kšœ˜—K˜K˜�—šžœœœAœ˜~Kšœ4˜4Kšœ@˜@Kšœ%˜%K˜K˜�—šžœœœY˜~Kšœ9˜9Kšœ@˜@Kšœ(˜(K˜K˜�—šžœœœœ˜XKšœœBœœ˜[K˜K˜�—šžœœœ-˜UKšœ;œœ˜IK˜K˜�—šžœœœœ˜XKšœœœ˜Kšœœ&˜7KšœG˜KK˜K˜�—šžœœœœ˜VKšœœ˜Kšœ˜Kšœ˜Kšœ9˜9Kšœ1˜1K˜—šžœœœœœœœ
œœ˜—K™lK˜�K˜K™�—Kšœ5™5K˜�šžœœ˜/Kšœœ"˜.Kšœ„˜„K˜K˜�—šžœœœ#˜<Kšœœ	œœ˜(Kš
œ
œœœœ˜FKšœœ$œ˜=Kšœœ˜!Kšœœ˜!Kšœœ˜!Kšœœ˜!K˜K˜�—šžœœœ#˜>Kšœœœ˜šœœ˜Kšœ˜Kšœ˜Kšœœ˜Kšœ˜K˜—Kšœœ˜"Kšœœ˜"Kšœœ˜"Kšœœ˜"K˜K˜�—šžœœœ%˜AK™‚Kšœœœœ˜*šœ˜Kšœ˜#Kšœ ˜$—šœ˜Kšœ˜#Kšœ ˜$—K˜K˜�—šžœœœœ˜?Kšœ|™|Kšœœœœ˜*Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜K˜�—šžœœœ&œ˜JKšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœœ˜Kšœœ˜K˜K˜�—K˜�Kšœ]™]K˜�šžœœ.œœ˜YKš
œœœœœ˜]K˜K˜�—K˜�Kšœ=™=K™�šžœœœGœ˜„K˜Kšœœœ˜Kšœ˜Kšœ#˜#Kšœ7˜7šœKœ
œ˜cšœœ˜šœ˜KšœE˜EK˜—šœ!˜!KšœK˜KK˜—Kšœœ˜—Kšœ(˜(Kšœ˜—K˜K˜�—Kšœ
œœ˜šžœœœGœ˜‚K™ÚK˜�K˜Kšœœœ˜Kšœ˜Kšœ
œœ)˜CKšœ#˜#Kšœ7˜7šœKœ
œ˜cšœœ˜šœ˜KšœU˜UKšœD˜DK˜—šœ!˜!Kšœ[˜[KšœH˜HK˜—Kšœœ˜—Kšœ(˜(Kšœ˜—K˜K˜�—K™	K™�šžœœ#˜5KšœI˜IK˜K˜�—šžœœ!™9Kšœ;œ™@K™�K™6K™JKšœ3œ™Ošœ-œ™5Kšœ4™4Kšœ™Kšœ™Kšœ™Kšœ™K™—K™K™�—K™�Kšœ™K™�šžœœœ)˜BKšœC˜CK˜K˜�—šžœœœ)˜Išžœœ˜ Kšœ`˜`Kšœ"˜"Kšœ˜K˜—Kšœœœœ˜*Kšœ-˜-K˜K˜�—šžœœœ)˜:Kšœœœ˜Kšœœœ˜KšœY˜YK˜—K˜�Kšœ™K™�šžœœœ/œœœœœ
œœ˜¿Kšœ·™·Kšœ˜Kšœœ˜Kšœœ˜'Kšœœ˜šœœ˜"KšœFœ˜S—Kšœ˜KšœÏc˜)Kšœ˜Kšœ
œ˜šœœ˜šœœ˜Kšœ"˜"Kšœ;˜;šœœ˜Kšœ˜Kšœ˜Kšœ˜Kšœœœ˜.K˜—K˜—Kšœ˜—Kšœ#˜#K˜K˜�—šžœœœ/œœœœœœœœ˜¿Kšœ±™±Kšœœ˜Kšœ˜Kšœœ˜'Kšœœ˜šœœ˜"KšœDœ˜Q—Kšœ˜KšœŸ˜)Kšœ˜Kšœ
œ˜šœœ˜šœœ˜Kšœ(˜(KšœA˜AKšœ;˜;šœœ˜Kšœ˜Kšœ˜Kšœ˜Kšœœœ˜.K˜—K˜—Kšœ˜—Kšœ#˜#K˜K˜�—šžœœœœ
œœœ˜pKšœœ˜Kšœœœœ˜Kšœœœ˜ Kšœ˜Kšœ	œ	˜KšœR™RKšœ	œ˜
Kšœ˜Kšœœœœœœ˜1šœœœ˜Kšœ!˜!KšœAŸ˜WKšœœœ˜šœœœ˜Kšœœ.œœ˜>Kšœœ.œœ˜>K˜—Kšœ	œ˜ Kšœ˜Kšœ
œ˜š˜šœ˜
Kšœ!˜!Kšœ@˜@Kšœœœ˜šœ	œ˜Kšœœ,œœ˜@Kšœœ,œœ˜@K˜—šœ	œ˜Kšœœ,œœ˜@Kšœœ,œœ˜@K˜—Kšœ	œ˜ Kšœ˜Kšœ
œ˜š˜Kšœœ˜—K˜——Kšœ˜—Kšœœœ˜K˜K˜�—šžœœœ"œ
œœœ˜vKšœT™TKšœ-˜3K˜—K˜�šžœœœœ˜Fcenter–C34.925 mm topLeading 34.925 mm topIndent 1.411111 mm bottomLeading •Bounds:0.0 mm xmin 0.0 mm ymin 55.03333 mm xmax 32.10278 mm ymax •Artwork
Interpress•
Interpress…Interpress/Xerox/3.0  f j k j¡¥“Ä��WB ¤ ¨  <û¡£2 ¢ ¨ æ ¢ ¨¡¡¨ÄWB�� ¤ ¨ r j¡¥“Ä��WB ¤ ¨¡¡¨ÅXeroxÅ
PressFontsÅ
Helvetica-mrr£¡ “ª ¤ ” •  —JŠÁHexagon– ¡¨TÞ™ÄfõÄY�_ŽޏTŽ¡¡¡¡™¡¯“¡¡¨TÞTÄfõ¡¹¡¯“¡¡¨TÄfõÄY�_Äfõ¡¹¡¯“¡¡¨ÄY�_ÄfõÄY�_Þ¡¹¡¯“¡¡¨ÄY�_ÞTÞ¡¹¡¯“  —JÙŠÁ1–  —L
ŠÁ2–  —˜
ŠÁ3–  —˜ÙŠÁ4– k é k gšœ=™=Icaption™e—Kšœœœœ˜)Kšœ˜Kšœ"˜"Kšœ"˜"Kšœ"˜"Kšœ"˜"Kšœœ˜K˜K˜�—š
žœœœœœ™KKšœœœœ™)Kšœ™KšœK™KKšœK™KKšœK™KKšœK™KKšœœ™K™K™�—šžœœœ%œ˜FKšœœœœ˜)Kšœ˜KšœH˜HKšœH˜HKšœH˜HKšœH˜HKšœœ˜K˜—K˜�K˜K˜K˜�šžœœ˜Kšœ'˜'Kšœ*˜*K˜K˜�—K˜K˜�Kšœ˜—�…—����1h��O��