DIRECTORY SVCoordSys, Feedback, GGParseIn, Imager, IO, Rope, SV2d, SV3d, SVAssembly, SVBasicTypes, SVBoundBox, SVCastRays, SVGraphics, SVMasterObject, SVModelTypes, SVPolygon3d, SVRay, SVScene, SVSceneTypes, SVToolObject; SVToolObjectImpl: CEDAR PROGRAM IMPORTS SVCoordSys, GGParseIn, IO, SVAssembly, SVBoundBox, SVCastRays, SVGraphics, SVMasterObject, SVPolygon3d, SVRay, SVScene EXPORTS SVToolObject = BEGIN BoundHedron: TYPE = SVBasicTypes.BoundHedron; Camera: TYPE = SVModelTypes.Camera; Classification: TYPE = SVSceneTypes.Classification; CoordSystem: TYPE = SVModelTypes.CoordSystem; CoordSysList: TYPE = SVModelTypes.CoordSysList; FeedbackData: TYPE = Feedback.FeedbackData; FrameBlock: TYPE = REF FrameBlockObj; FrameBlockObj: TYPE = SVSceneTypes.FrameBlockObj; LightSourceList: TYPE = SVModelTypes.LightSourceList; MasterObject: TYPE = SVSceneTypes.MasterObject; MasterObjectClass: TYPE = SVSceneTypes.MasterObjectClass; MasterObjectClassObj: TYPE = SVSceneTypes.MasterObjectClassObj; Matrix4by4: TYPE = SV3d.Matrix4by4; PlanarSurface: TYPE = REF PlanarSurfaceObj; PlanarSurfaceObj: TYPE = SVSceneTypes.PlanarSurfaceObj; PlanarSurfaceList: TYPE = SVSceneTypes.PlanarSurfaceList; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Poly3d: TYPE = SV3d.Poly3d; Primitive: TYPE = SVSceneTypes.Primitive; Ray: TYPE = SVSceneTypes.Ray; Shape: TYPE = SVSceneTypes.Shape; SelectMode: TYPE = SVSceneTypes.SelectMode; Slice: TYPE = SVSceneTypes.Slice; SliceList: TYPE = SVSceneTypes.SliceList; SliceDescriptor: TYPE = SVSceneTypes.SliceDescriptor; ToolData: TYPE = SVSceneTypes.ToolData; Vector3d: TYPE = SV3d.Vector3d; toolClass: MasterObjectClass; jackClass: MasterObjectClass; ToolMakeMasterObject: PUBLIC PROC [name: Rope.ROPE, toolData: ToolData] RETURNS [mo: MasterObject] = { mainBody: REF ANY _ toolData; lineBody: REF ANY _ toolData; shadeBody: REF ANY _ toolData; rayCastBody: REF ANY _ toolData; mo _ SVScene.CreateMasterObject[name, toolClass, mainBody, lineBody, shadeBody, rayCastBody]; }; SizeToFit: PUBLIC PROC [toolData: ToolData, assembly: Slice] = { block: FrameBlock; loX, hiX, loY, hiY, loZ, hiZ: REAL; dataFound: BOOL; [loX, hiX, loY, hiY, loZ, hiZ, dataFound] _ BoundBlockOfAssembly[assembly, assembly]; IF dataFound THEN block _ NEW[FrameBlockObj _ [loX, hiX, loY, hiY, loZ, hiZ]] ELSE block _ NEW[FrameBlockObj _ [-400, 400, -400, 400, -400, 400]]; toolData.block _ block; toolData.infinite _ FALSE; }; BoundBlockOfAssembly: PROC [assembly: Slice, wrt: Slice] RETURNS [loX, hiX, loY, hiY, loZ, hiZ: REAL, dataFound: BOOL] = { localDataFound: BOOL; lX, hX, lY, hY, lZ, hZ: REAL; dataFound _ FALSE; WITH assembly.shape SELECT FROM assems: SliceList => { FOR subassemblies: LIST OF Slice _ assems.list, subassemblies.rest UNTIL subassemblies = NIL DO [lX, hX, lY, hY, lZ, hZ, localDataFound] _ BoundBlockOfAssembly[subassemblies.first, wrt]; IF localDataFound THEN { IF (NOT dataFound) THEN { loX _ lX; hiX _ hX; loY _ lY; hiY _ hY; loZ _ lZ; hiZ _ hZ; } ELSE { loX _ MIN[loX, lX]; hiX _ MAX[hiX, hX]; loY _ MIN[loY, lY]; hiY _ MAX[hiY, hY]; loZ _ MIN[loZ, lZ]; hiZ _ MAX[hiZ, hZ]; }; }; dataFound _ dataFound OR localDataFound; ENDLOOP; }; shape: Shape => { bh: BoundHedron _ shape.mo.class.getHedron[shape.mo]; dataFound _ TRUE; IF bh = NIL THEN {dataFound _ FALSE; RETURN}; [loX, hiX, loY, hiY, loZ, hiZ] _ BoundBlockOfBoundHedron[bh, shape.coordSys, wrt.coordSys]; }; ENDCASE => ERROR; }; BoundBlockOfBoundHedron: PROC [bh: BoundHedron, currentCS: CoordSystem, newCS: CoordSystem] RETURNS [loX, hiX, loY, hiY, loZ, hiZ: REAL] = { thisPt: Point3d; thisPt _ SVCoordSys.FromCSToCS[bh[0], currentCS, newCS]; loX _ hiX _ thisPt[1]; loY _ hiY _ thisPt[2]; loZ _ hiZ _ thisPt[3]; FOR i: NAT IN [1..bh.len) DO thisPt _ SVCoordSys.FromCSToCS[bh[i], currentCS, newCS]; loX _ MIN[loX, thisPt[1]]; hiX _ MAX[hiX, thisPt[1]]; loY _ MIN[loY, thisPt[2]]; hiY _ MAX[hiY, thisPt[2]]; loZ _ MIN[loZ, thisPt[3]]; hiZ _ MAX[hiZ, thisPt[3]]; ENDLOOP; }; ToolRayCast: PROC [cameraPoint: Point2d, localRay: Ray, sliceD: SliceDescriptor, prim: Primitive, positiveTOnly: BOOL _ TRUE] RETURNS [class: Classification] = { mo: MasterObject _ prim.mo; RETURN[ToolRayCastAux[localRay, NARROW[mo.rayCastBody], prim, positiveTOnly]]; }; ToolRayCastAux: PROC [localRay: Ray, td: ToolData, prim: Primitive, positiveTOnly: BOOL] RETURNS [class: Classification] = { hitPoint: Point3d; almostZero: REAL _ 1.0e-12; p: Point3d; d: Vector3d; t: REAL; class _ SVCastRays.GetClassFromPool[]; [p, d] _ SVRay.GetLocalRay[localRay]; SELECT td.plane FROM 1 => { -- x = 0 plane only IF ABS[d[1]] < almostZero THEN SVCastRays.MakeClassAMiss[class] ELSE { t _ (- p[1])/d[1]; hitPoint[1] _ 0.0; hitPoint[2] _ p[2] + t*d[2]; hitPoint[3] _ p[3] + t*d[3]; IF hitPoint[2] > td.block.hiY OR hitPoint[2] < td.block.loY OR hitPoint[3] > td.block.hiZ OR hitPoint[3] < td.block.loZ THEN SVCastRays.MakeClassAMiss[class] ELSE { class.count _ 2; IF p[1] < 0.0 THEN { class.normals[1] _ [-1,0,0]; class.normals[2] _ [1,0,0]} ELSE { class.normals[1] _ [1,0,0]; class.normals[2] _ [-1,0,0]}; class.params[1] _ t; class.params[2] _ t; class.surfaces[1] _ NIL; class.surfaces[2] _ NIL; } }; }; 2 => { -- y = 0 plane only IF ABS[d[2]] < almostZero THEN SVCastRays.MakeClassAMiss[class] ELSE { t _ (- p[2])/d[2]; hitPoint[1] _ p[1] + t*d[1]; hitPoint[2] _ 0.0; hitPoint[3] _ p[3] + t*d[3]; IF hitPoint[1] > td.block.hiX OR hitPoint[1] < td.block.loX OR hitPoint[3] > td.block.hiZ OR hitPoint[3] < td.block.loZ THEN SVCastRays.MakeClassAMiss[class] ELSE { class.count _ 2; IF p[2] < 0.0 THEN { class.normals[1] _ [0,-1,0]; class.normals[2] _ [0,1,0]} ELSE { class.normals[1] _ [0,1,0]; class.normals[2] _ [0,-1,0]}; class.params[1] _ t; class.params[2] _ t; class.surfaces[1] _ NIL; class.surfaces[2] _ NIL; } }; }; 3 => { -- z = 0 plane only IF ABS[d[3]] < almostZero THEN SVCastRays.MakeClassAMiss[class] ELSE { t _ (- p[3])/d[3]; hitPoint[1] _ p[1] + t*d[1]; hitPoint[2] _ p[2] + t*d[2]; hitPoint[3] _ 0.0; IF hitPoint[1] > td.block.hiX OR hitPoint[1] < td.block.loX OR hitPoint[2] > td.block.hiY OR hitPoint[2] < td.block.loY THEN SVCastRays.MakeClassAMiss[class] ELSE { IF p[3] < 0 THEN { class.normals[1] _ [0,0,-1]; class.normals[2] _ [0,0,1]} ELSE { class.normals[1] _ [0,0,1]; class.normals[2] _ [0,0,-1]}; class.count _ 2; class.params[1] _ t; class.params[2] _ t; class.surfaces[1] _ NIL; class.surfaces[2] _ NIL; } }; }; 4 => ERROR; ENDCASE => ERROR; }; ToolRayCastNoBBoxes: PROC [localRay: Ray, sliceD: SliceDescriptor, prim: Primitive, positiveTOnly: BOOL _ TRUE] RETURNS [class: Classification] = { mo: MasterObject _ prim.mo; RETURN ToolRayCastAux[localRay, NARROW[mo.rayCastBody], prim, positiveTOnly]; }; ToolRayCastBoundingSpheres: PROC [localRay: Ray, sliceD: SliceDescriptor, prim: Primitive, positiveTOnly: BOOL _ TRUE] RETURNS [class: Classification] = { mo: MasterObject _ prim.mo; RETURN ToolRayCastAux[localRay, NARROW[mo.rayCastBody], prim, positiveTOnly]; }; ToolBoundHedron: PROC [mo: MasterObject] RETURNS [hedron: BoundHedron] = { toolData: ToolData _ NARROW[mo.mainBody]; block: FrameBlock _ toolData.block; hedron _ SVBoundBox.RectangularBoundHedron2[block.loX, block.hiX, block.loY, block.hiY, block.loZ, block.hiZ]; }; ToolLineDraw: PROC[slice: Slice, dc: Imager.Context, camera: Camera] = { mo: MasterObject _ slice.toolMasterObject; td: ToolData _ NARROW[mo.lineBody]; f: FrameBlock _ td.block; localCS: CoordSystem _ slice.coordSys; SELECT td.plane FROM 1 => DrawHitPadX[dc, f.hiZ, f.loZ, f.loY, f.hiY, camera, localCS]; 2 => DrawHitPadY[dc, f.loX, f.hiX, f.loZ, f.hiZ, camera, localCS]; 3 => DrawHitPadZ[dc, f.loX, f.hiX, f.loY, f.hiY, camera, localCS]; 4 => { DrawHitPadX[dc, f.hiZ, f.loZ, f.loY, f.hiY, camera, localCS]; DrawHitPadY[dc, f.loX, f.hiX, f.loZ, f.hiZ, camera, localCS]; DrawHitPadZ[dc, f.loX, f.hiX, f.loY, f.hiY, camera, localCS]; }; ENDCASE => ERROR; }; DrawHitPadX: PRIVATE PROC [dc: Imager.Context, left, right, down, up: REAL, camera: Camera, cs: CoordSystem] = { localCamera: Matrix4by4 _ SVCoordSys.WRTCamera[cs, camera.coordSys]; SVGraphics.SetCP[dc, [0, up, left], camera, localCamera]; -- up left SVGraphics.DrawTo[dc, [0, up, right], camera, localCamera]; --up right SVGraphics.DrawTo[dc, [0, down, right], camera, localCamera]; -- down right SVGraphics.DrawTo[dc, [0, down, left], camera, localCamera]; -- down left SVGraphics.DrawTo[dc, [0, up, left], camera, localCamera]; -- up left }; DrawHitPadY: PRIVATE PROC [dc: Imager.Context, left, right, down, up: REAL, camera: Camera, cs: CoordSystem] = { localCamera: Matrix4by4 _ SVCoordSys.WRTCamera[cs, camera.coordSys]; SVGraphics.SetCP[dc, [left, 0, up], camera, localCamera]; -- up left SVGraphics.DrawTo[dc, [right, 0, up], camera, localCamera]; --up right SVGraphics.DrawTo[dc, [right, 0, down], camera, localCamera]; -- down right SVGraphics.DrawTo[dc, [left, 0, down], camera, localCamera]; -- down left SVGraphics.DrawTo[dc, [left, 0, up], camera, localCamera]; -- up left }; DrawHitPadZ: PRIVATE PROC [dc: Imager.Context, left, right, down, up: REAL, camera: Camera, cs: CoordSystem] = { localCamera: Matrix4by4 _ SVCoordSys.WRTCamera[cs, camera.coordSys]; SVGraphics.SetCP[dc, [left, up, 0], camera, localCamera]; -- up left SVGraphics.DrawTo[dc, [right, up, 0], camera, localCamera]; --up right SVGraphics.DrawTo[dc, [right, down, 0], camera, localCamera]; -- down right SVGraphics.DrawTo[dc, [left, down, 0], camera, localCamera]; -- down left SVGraphics.DrawTo[dc, [left, up, 0], camera, localCamera]; -- up left }; ToolCountSurf: PROC [masterObject: MasterObject] RETURNS [len: NAT] = { toolData: ToolData _ NARROW[masterObject.mainBody]; IF toolData.plane < 4 THEN len _ 1 ELSE len _ 12; }; SortedToolSurface: TYPE = REF SortedToolSurfaceObj; SortedToolSurfaceObj: TYPE = RECORD [ plane: NAT, f: FrameBlock, left: BOOL, down: BOOL ]; ToolGetSurf: PROC [slice: Slice, camera: CoordSystem, eyeWorld: Point3d] RETURNS [psl: PlanarSurfaceList] = { mo: MasterObject _ slice.toolMasterObject; localCS: CoordSystem _ slice.coordSys; thisSortedSurface: PlanarSurface; poly: Poly3d _ SVPolygon3d.CreatePoly[4]; toolData: ToolData _ NARROW[mo.mainBody]; avgDepth: REAL; f: FrameBlock _ toolData.block; psl _ NIL; SELECT toolData.plane FROM 1,2,3,4 => { -- z = 0 plane poly _ SVPolygon3d.AddPolyPoint[poly, [f.loX, f.loY, 0]]; poly _ SVPolygon3d.AddPolyPoint[poly, [f.loX, f.hiY, 0]]; poly _ SVPolygon3d.AddPolyPoint[poly, [f.hiX, f.hiY, 0]]; poly _ SVPolygon3d.AddPolyPoint[poly, [f.hiX, f.loY, 0]]; avgDepth _ AverageDepth[poly, localCS, camera]; thisSortedSurface _ NEW[PlanarSurfaceObj _ [ whichSurface: NEW[SortedToolSurfaceObj _ [toolData.plane, f, FALSE, FALSE]], assembly: slice, normal: [0,0,1], mo: mo, depth: avgDepth, frontDepth: avgDepth, backDepth: avgDepth]]; psl _ CONS[thisSortedSurface, psl]; }; ENDCASE => ERROR; }; AverageDepth: PROC [poly: Poly3d, localCS, cameraCS: CoordSystem] RETURNS [avgDepth: REAL] = { sum: REAL _ 0; realLen: REAL _ poly.len; localPoint: Point3d; FOR i: NAT IN[0..poly.len) DO localPoint _ poly[i]; localPoint _ SVGraphics.LocalToCamera[localPoint, localCS, cameraCS]; sum _ sum + localPoint[3]; ENDLOOP; avgDepth _ sum/realLen; }; ToolDrawSurf: PROC [dc: Imager.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera, eyeWorld: Point3d, hiddenLine: BOOL] = { whichSurface: SortedToolSurface _ NARROW[ps.whichSurface]; poly3d: Poly3d _ SVPolygon3d.CreatePoly[4]; f: FrameBlock _ whichSurface.f; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, [f.loX, f.loY, 0]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, [f.loX, f.hiY, 0]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, [f.hiX, f.hiY, 0]]; poly3d _ SVPolygon3d.AddPolyPoint[poly3d, [f.hiX, f.loY, 0]]; SVGraphics.DrawAreaNormalAbsolute[dc, ps.normal, poly3d, ps.assembly.artwork, lightSources, camera, SVCoordSys.WRTCamera[ps.assembly.coordSys, camera.coordSys], hiddenLine]; }; JackMakeMasterObject: PUBLIC PROC [name: Rope.ROPE] RETURNS [mo: MasterObject] = { mainBody: REF ANY _ NIL; lineBody: REF ANY _ NIL; shadeBody: REF ANY _ NIL; rayCastBody: REF ANY _ NIL; mo _ SVScene.CreateMasterObject[name, jackClass, mainBody, lineBody, shadeBody, rayCastBody]; }; JackUpdate: PUBLIC PROC [mo: MasterObject, updateData: REF ANY] = { }; JackBoundHedron: PUBLIC PROC [mo: MasterObject] RETURNS [hedron: BoundHedron] = { hedron _ SVBoundBox.RectangularBoundHedron[2.0, 2.0, 2.0]; }; JackLineDraw: PUBLIC PROC[slice: Slice, dc: Imager.Context, camera: Camera] = { localCS: CoordSystem _ slice.coordSys; localCamera: Matrix4by4 _ SVCoordSys.WRTCamera[localCS, camera.coordSys]; SVGraphics.SetCP[dc, [-1.0,0.0,0.0], camera, localCamera]; SVGraphics.DrawTo[dc, [1.0,0.0,0.0], camera, localCamera]; SVGraphics.SetCP[dc, [0.0,-1.0,0.0], camera, localCamera]; SVGraphics.DrawTo[dc, [0.0,1.0,0.0], camera, localCamera]; SVGraphics.SetCP[dc, [0.0,0.0,-1.0], camera, localCamera]; SVGraphics.DrawTo[dc, [0.0,0.0,1.0], camera, localCamera]; }; JackCountSurf: PUBLIC PROC [masterObject: MasterObject] RETURNS [len: NAT] = { len _ 6; }; JackGetSurf: PUBLIC PROC [slice: Slice, camera: CoordSystem, eyeWorld: Point3d] RETURNS [psl: PlanarSurfaceList] = { shape: Shape _ NARROW[slice.shape]; masterObject: MasterObject _ shape.mo; psl _ NIL; }; JackNewParts: PUBLIC PROC [slice: Slice, hitData: REF ANY, mode: SelectMode] RETURNS [sliceD: SliceDescriptor] = { sliceD _ SVAssembly.DescriptorFromParts[slice, NIL]; }; JackDrawSurf: PUBLIC PROC [dc: Imager.Context, ps: PlanarSurface, lightSources: LightSourceList, camera: Camera, eyeWorld: Point3d, hiddenLine: BOOL] = { }; JackFileout: PUBLIC PROC [f: IO.STREAM, mo: MasterObject] = { f.PutChar[IO.TAB]; f.PutF["data: procedural\n"]; }; JackFilein: PUBLIC PROC [f: IO.STREAM, name: Rope.ROPE, csList: CoordSysList, defaultCS: CoordSystem, wdir: Rope.ROPE, version: REAL, feedback: FeedbackData] RETURNS [mo: MasterObject] = { GGParseIn.ReadWRope[f, "data: procedural"]; GGParseIn.ReadBlank[f]; mo _ JackMakeMasterObject[name]; }; Init: PROC = { jack: MasterObject; toolClass _ NEW[MasterObjectClassObj _ [ name: "tool", update: SVMasterObject.NoOpUpdate, filein: SVMasterObject.NoOpFilein, fileout: SVMasterObject.NoOpFileout, fileoutPoly: SVMasterObject.NoOpFileoutPoly, rayCast: ToolRayCast, rayCastNoBBoxes: ToolRayCastNoBBoxes, rayCastBoundingSpheres: ToolRayCastBoundingSpheres, getHedron: ToolBoundHedron, preprocess: SVMasterObject.NoOpPreprocess, lineDraw: ToolLineDraw, normalsDraw: SVMasterObject.NoOpNormalsDraw, countSurf: ToolCountSurf, getSurf: ToolGetSurf, pointsInDescriptor: SVMasterObject.NoOpPointsInDescriptor, nextPoint: SVMasterObject.NoOpNextPoint, drawSurf: ToolDrawSurf, drawSubBoxes: SVMasterObject.NoOpDrawSubBoxes, drawSubSpheres: SVMasterObject.NoOpDrawSubSpheres]]; jackClass _ NEW[MasterObjectClassObj _ [ name: "jack", update: JackUpdate, filein: JackFilein, fileout: JackFileout, fileoutPoly: SVMasterObject.NoOpFileoutPoly, rayCast: SVMasterObject.NoOpRayCast, rayCastNoBBoxes: SVMasterObject.NoOpRayCastNoBBoxes, rayCastBoundingSpheres: SVMasterObject.NoOpRayCastBoundingSpheres, getHedron: JackBoundHedron, preprocess: SVMasterObject.NoOpPreprocess, lineDraw: JackLineDraw, normalsDraw: SVMasterObject.NoOpNormalsDraw, countSurf: JackCountSurf, getSurf: JackGetSurf, pointsInDescriptor: SVMasterObject.NoOpPointsInDescriptor, nextPoint: SVMasterObject.NoOpNextPoint, drawSurf: JackDrawSurf, drawSubBoxes: SVMasterObject.NoOpDrawSubBoxes, drawSubSpheres: SVMasterObject.NoOpDrawSubSpheres]]; SVMasterObject.RegisterMasterObjectClass[toolClass]; SVMasterObject.RegisterMasterObjectClass[jackClass]; jack _ JackMakeMasterObject["jack"]; SVMasterObject.RegisterMasterObject[jack]; }; Init[]; END. rFile: SVToolObjectImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. Contents: Defines the master object classes "tool" and "jack". A tool draws itself as from 1 to 3 orthogonal rectangles (even for ray tracing). Any assembly can be made into a tool temporarily, and can draw itself in wireframe normally but ray trace as a tool to allow easy pointing to important object planes. A jack draws itself as a coordinate frame. Jacks are invisible in ray-traces and shaded polygon drawings. Created: July 2, 1984 1:03:38 pm PDT Last edited by: Eric Bier on August 29, 1987 2:19:26 pm PDT The tool in question will just contain in the [loX, hiX, loY, hiY, loZ, hiZ] box, the assembly given. Compute this tight-fitting box from the union of the boundhedron's of all of assembly's master objects. Express all of the boundHedron points in assembly coordinates. Since the boundhedrons are in master object records, we must walk the tree to find them. Since they are in master object coordinates, we must carefully translate them to the coordinates of assembly. For now, I will assume that any infinite objects are negative objects or are intersected with other objects. In either case, they can be ignored. The choice of surface normal depends on the position of the origin of the ray. The choice of surface normal depends on the position of the origin of the ray. The choice of surface normal depends on the position of the origin of the ray. The 3 tool rectangles are: (left, right, down, up) hiZ loZ loY hiY loX hiX loZ hiZ loX hiX loY hiY SVPolygon3d.ClearPoly[poly]; Jack Objects Spheres can be recovered from scratch. ΚΠ˜Ihead™Jšœ Οmœ1™˜ILšœ2’œ˜:Lšœ2’œ˜:Lšœ2’œ˜:Lšœ2’œ˜:Lšœ2’œ˜:Lšœ2’œ˜:Lšœ˜—š   œžœžœžœžœ˜NL˜Lšœ˜—š   œžœžœ(’œ žœ˜tLšœ#˜#Lšœ&˜&Lšœ ˜ Lšœ˜—š   œžœžœžœžœžœ˜rLšœ/žœ˜4Lšœ˜—š   œžœžœ[’œžœ˜™Lšœ˜—š   œžœžœžœžœ˜=Lšœ&™&Lšœ žœžœ˜Lšœ˜Lšœ˜—š  œžœžœžœžœ žœ;žœ žœžœ˜ΌLšœ+˜+Lšœ˜Lšœ ˜ Lšœ˜Jšœ˜—J˜š œžœ˜L˜Lšœ˜L˜šœ žœ˜(Lšœ ˜ LšŸœ˜"LšŸœ˜"LšŸœ˜$LšŸ œ!˜,LšŸœ˜LšŸœ˜%LšŸœ˜3LšŸ œ˜LšŸ œ ˜*LšŸœ˜LšŸ œ!˜,LšŸ œ˜LšŸœ˜LšŸœ(˜:LšŸ œ˜(LšŸœ˜LšŸ œ"˜.LšŸœ&˜4L˜—šœ žœ˜(Lšœ ˜ LšŸœ ˜LšŸœ ˜LšŸœ˜LšŸ œ!˜,LšŸœ˜$LšŸœ%˜4LšŸœ,˜BLšŸ œ˜LšŸ œ ˜*LšŸœ˜LšŸ œ!˜,LšŸ œ˜LšŸœ˜LšŸœ(˜:LšŸ œ˜(LšŸœ˜LšŸ œ"˜.LšŸœ&˜4L˜—Lšœ4˜4Lšœ4˜4L˜L˜$L˜Lšœ*˜*L˜L˜—L˜L˜Jšžœ˜J˜—…—=NT