DIRECTORY CoordSys, SVRay, Convert, DisplayListToTree, Imager, IO, PriorityQueue, Rope, SV3d, SVModelTypes, SVSceneTypes, SVSelect; DisplayListToTreeImpl: CEDAR PROGRAM IMPORTS Convert, CoordSys, SVRay, SVSelect, Imager, IO, PriorityQueue, Rope EXPORTS DisplayListToTree = BEGIN Slice: TYPE = SVSceneTypes.Slice; SliceDescriptor: TYPE = SVSceneTypes.SliceDescriptor; SliceList: TYPE = SVSceneTypes.SliceList; Camera: TYPE = SVModelTypes.Camera; Composite: TYPE = REF CompositeObj; CompositeObj: TYPE = SVSceneTypes.CompositeObj; CoordSystem: TYPE = SVModelTypes.CoordSystem; CoordSysList: TYPE = SVModelTypes.CoordSysList; CSGTree: TYPE = SVSceneTypes.CSGTree; MasterObject: TYPE = SVSceneTypes.MasterObject; Matrix4by4: TYPE = SV3d.Matrix4by4; PointSetOp: TYPE = SVSceneTypes.PointSetOp; -- {union, intersection, difference} Primitive: TYPE = REF PrimitiveObj; PrimitiveObj: TYPE = SVSceneTypes.PrimitiveObj; Scene: TYPE = SVSceneTypes.Scene; Shape: TYPE = SVSceneTypes.Shape; Surface: TYPE = REF ANY; -- may be RectSurface, TubeSurface, DiskSurface, or ShellSurface (of BasicObject3d), etc. SurfaceArray: TYPE = SVSceneTypes.SurfaceArray; CreateEmptyTree: PUBLIC PROC [] RETURNS [tree: CSGTree] = { tree _ SVRay.MakeCSGTree[NIL, Imager.white, FALSE]; }; AssemblyToTree: PUBLIC PROC [assembly: Slice, scene: Scene, camera: Camera, oldTree: CSGTree _ NIL, ignoreMoving: BOOL _ FALSE] RETURNS [tree: CSGTree] = { topAssembly: Slice; topNode: REF ANY; topAssembly _ assembly; topNode _ AssemblyToNode[topAssembly, scene, FALSE, ignoreMoving]; -- Make the tree. IF oldTree # NIL THEN { oldTree.son _ topNode; tree _ oldTree; } ELSE tree _ SVRay.MakeCSGTree[topNode, scene.backgroundColor, scene.shadows]; }; AssemblyToNode: PROC [assembly: Slice, scene: Scene, inverted, ignoreMoving: BOOL] RETURNS [node: REF ANY] = { IF assembly = NIL THEN RETURN[ NIL ]; WITH assembly.shape SELECT FROM shape: Shape => { newPrim: Primitive; newPrim _ PrimitiveFromAssembly[assembly, scene, inverted, ignoreMoving]; node _ newPrim; RETURN}; alist: SliceList => { node _ AssemblyListToNode[alist, scene, assembly.name, ignoreMoving]; RETURN}; ENDCASE => ERROR; }; -- end of AssemblyToNode AssemblyListToNode: PROC [assemblyList: SliceList, scene: Scene, name: Rope.ROPE, ignoreMoving: BOOL] RETURNS [node: REF ANY] = { list: LIST OF Slice _ assemblyList.list; treeList: LIST OF REF ANY; treeList _ AssemblyListToTreeList[list, scene, assemblyList.pointSetOp, ignoreMoving]; IF treeList = NIL THEN RETURN[ NIL ]; IF treeList.rest = NIL THEN { node _ treeList.first; RETURN} ELSE { -- Inspect the treeList more carefully. IF AllAreNil[treeList] THEN RETURN[NIL]; IF assemblyList.pointSetOp = intersection AND AnyAreNIL[treeList] THEN RETURN[ NIL ]; IF treeList.first = NIL AND assemblyList.pointSetOp = difference THEN RETURN[ NIL ]; treeList _ SpliceOutNILs[treeList]; IF treeList = NIL THEN RETURN[NIL]; IF treeList.rest = NIL THEN { node _ treeList.first; RETURN} ELSE { SELECT assemblyList.pointSetOp FROM union => node _ MakeUnionNode[treeList, name, 1]; intersection => node _ MakeIntersectionNode[treeList, name, 1]; difference => node _ MakeDifferenceNode[treeList, name, 1]; ENDCASE => ERROR; }; -- end ELSE }; -- end of ELSE }; -- end of AssemblyListToNode MakeUnionNode: PROC [treeList: LIST OF REF ANY, name: Rope.ROPE, level: NAT] RETURNS [node: REF ANY] = { leftNode, rightNode: REF ANY; intermediateName: Rope.ROPE; IF treeList = NIL THEN RETURN[ NIL]; IF treeList.rest = NIL THEN RETURN [treeList.first]; leftNode _ treeList.first; rightNode _ MakeUnionNode[treeList.rest, name, level + 1]; intermediateName _ Rope.Concat [name, Convert.RopeFromInt[level]]; node _ NEW[CompositeObj _ [intermediateName, union, leftNode, rightNode]]; }; -- end of MakeUnionNode MakeIntersectionNode: PROC [treeList: LIST OF REF ANY, name: Rope.ROPE, level: NAT] RETURNS [node: REF ANY] = { leftNode, rightNode: REF ANY; intermediateName: Rope.ROPE; IF treeList = NIL THEN RETURN[ NIL]; IF treeList.rest = NIL THEN RETURN [treeList.first]; leftNode _ treeList.first; rightNode _ MakeIntersectionNode[treeList.rest, name, level + 1]; intermediateName _ Rope.Concat [name, Convert.RopeFromInt[level]]; node _ NEW[CompositeObj _ [intermediateName, intersection, leftNode, rightNode]]; }; -- end of MakeIntersectionNode MakeDifferenceNode: PROC [treeList: LIST OF REF ANY, name: Rope.ROPE, level: NAT] RETURNS [node: REF ANY] = { leftNode, rightNode: REF ANY; intermediateName: Rope.ROPE; leftNode _ treeList.first; rightNode _ MakeUnionNode[treeList.rest, name, level + 1]; intermediateName _ Rope.Concat [name, Convert.RopeFromInt[level]]; node _ NEW[CompositeObj _ [intermediateName, difference, leftNode, rightNode]]; }; -- end of MakeDifferenceNode AssemblyListToTreeList: PROC [list: LIST OF Slice, scene: Scene, op: PointSetOp, ignoreMoving: BOOL] RETURNS [treeList: LIST OF REF ANY] = { IF list = NIL THEN RETURN[ NIL ]; IF op = difference THEN treeList _ CONS[AssemblyToNode[assembly: list.first, scene: scene, inverted: FALSE, ignoreMoving: ignoreMoving], AssemblyListToTreeList2[list: list.rest, scene: scene, inverted: TRUE, ignoreMoving: ignoreMoving]] ELSE treeList _ CONS[AssemblyToNode[assembly: list.first, scene: scene, inverted: FALSE, ignoreMoving: ignoreMoving], AssemblyListToTreeList2[list: list.rest, scene: scene, inverted: FALSE, ignoreMoving: ignoreMoving]]; }; -- end of AssemblyListToTreeList AssemblyListToTreeList2: PROC [list: LIST OF Slice, scene: Scene, inverted: BOOL, ignoreMoving: BOOL] RETURNS [treeList: LIST OF REF ANY] = { IF list = NIL THEN RETURN[ NIL ]; treeList _ CONS[AssemblyToNode[list.first, scene, inverted, ignoreMoving], AssemblyListToTreeList2[list.rest, scene, inverted, ignoreMoving]]; }; -- end of AssemblyListToTreeList2 AllAreNil: PRIVATE PROC [list: LIST OF REF ANY] RETURNS [BOOL] = { FOR l: LIST OF REF ANY _ list, l.rest UNTIL l = NIL DO IF l.first # NIL THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; }; AnyAreNIL: PRIVATE PROC [list: LIST OF REF ANY] RETURNS [BOOL] = { FOR l: LIST OF REF ANY _ list, l.rest UNTIL l = NIL DO IF l.first = NIL THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; SpliceOutNILs: PRIVATE PROC [list: LIST OF REF ANY] RETURNS [compressed: LIST OF REF ANY] = { IF list = NIL THEN RETURN[ NIL]; IF list.first # NIL THEN compressed _ CONS[list.first, SpliceOutNILs[list.rest]] ELSE compressed _ SpliceOutNILs[list.rest]; }; PrimitiveFromAssembly: PUBLIC PROC [slice: Slice, scene: Scene, inverted, ignoreMoving: BOOL] RETURNS [prim: Primitive] = { mo: MasterObject; shape: Shape; sliceD, stillD: SliceDescriptor; prim _ NEW[PrimitiveObj]; IF NOT ISTYPE[slice.shape, Shape] THEN ERROR PrimitiveAssemblyWithoutMO; shape _ NARROW[slice.shape]; mo _ shape.mo; IF ignoreMoving THEN { sliceD _ SVSelect.FindSelectedSlice[slice, scene, normal]; IF sliceD = NIL THEN stillD _ mo.class.newParts[slice, NIL, [0,0,0], slice] ELSE { background, overlay, rubber, drag: SliceDescriptor; [background, overlay, rubber, drag] _ mo.class.movingParts[sliceD.slice, sliceD.parts]; stillD _ mo.class.unionParts[background, overlay]; }; } ELSE stillD _ mo.class.newParts[slice, NIL, [0,0,0], slice]; prim.name _ slice.name; prim.artwork _ slice.artwork; prim.assembly _ slice; prim.mo _ mo; prim.sliceD _ stillD; prim.rayCast _ mo.class.rayCast; prim.rayCastNoBBoxes _ mo.class.rayCastNoBBoxes; prim.rayCastBoundingSpheres _ mo.class.rayCastBoundingSpheres; prim.localCS _ shape.coordSys; prim.scalars _ CoordSys.GetScalars[shape.coordSys]; prim.primWRTWorld _ CoordSys.WRTWorld[shape.coordSys]; prim.worldWRTPrim _ CoordSys.FindWorldInTermsOf[shape.coordSys]; prim.boundBox _ NIL; -- will be filled in at tree preprocess time prim.boundHedron _ mo.class.getHedron[mo]; prim.inverted _ inverted; prim.currentRay _ NIL; prim.rayStepX _ NIL; }; PrimitiveAssemblyWithoutMO: PUBLIC ERROR = CODE; CoordSysListFromScene: PUBLIC PROC [scene: Scene] RETURNS [csl: CoordSysList] = { csl _ CoordSysListFromAssembly[scene.assembly]; csl _ SortCoordSysListByBreadth[csl]; csl _ CONS[scene.coordSysRoot, csl]; -- add WORLD }; CoordSysListFromAssembly: PROC [assem: Slice] RETURNS [csl: CoordSysList] = { end: CoordSysList; alist, apos, aend: LIST OF Slice; root: CoordSystem _ assem.coordSys; i: NAT _ 0; end _ csl _ CONS[root, NIL]; aend _ alist _ CONS[assem, NIL]; FOR apos _ alist, apos.rest UNTIL apos = NIL DO WITH apos.first.shape SELECT FROM assemList: SliceList => { FOR children: LIST OF Slice _ assemList.list, children.rest UNTIL children = NIL DO end.rest _ CONS[children.first.coordSys, NIL]; aend.rest _ CONS[children.first, NIL]; end _ end.rest; aend _ aend.rest; i _ i+1; IF i > 300 THEN ERROR; ENDLOOP; }; ENDCASE => {}; -- we have no children and are already on the list. ENDLOOP; }; SortCoordSysListByBreadth: PRIVATE PROC [csl: CoordSysList] RETURNS [sortedCsl: CoordSysList] = { q: PriorityQueue.Ref; thisRec, lastRec: CoordSysSortRec; len: NAT _ ListLength[csl]; q _ PriorityQueue.Predict[len, SortProc]; FOR list: CoordSysList _ csl, list.rest UNTIL list = NIL DO thisRec _ NEW[CoordSysSortRecObj _ [Depth[list.first], list]]; PriorityQueue.Insert[q, thisRec]; ENDLOOP; lastRec _ NARROW[PriorityQueue.Remove[q]]; lastRec.coordSysCell.rest _ NIL; FOR i: NAT IN [1..len-1] DO thisRec _ NARROW[PriorityQueue.Remove[q]]; thisRec.coordSysCell.rest _ lastRec.coordSysCell; lastRec _ thisRec; ENDLOOP; sortedCsl _ thisRec.coordSysCell; }; -- end of SortCoordSysListByBreadth CoordSysSortRec: TYPE = REF CoordSysSortRecObj; CoordSysSortRecObj: TYPE = RECORD[ index: NAT, coordSysCell: CoordSysList]; SortProc: SAFE PROC [x, y: PriorityQueue.Item, data: REF _ NIL] RETURNS [BOOL] = { xRec: CoordSysSortRec _ NARROW[x]; yRec: CoordSysSortRec _ NARROW[y]; RETURN[xRec.index > yRec.index]; }; ListLength: PRIVATE PROC [csl: CoordSysList] RETURNS [len: NAT] = { len _ 0; FOR list: CoordSysList _ csl, list.rest UNTIL list = NIL DO len _ len + 1; ENDLOOP; }; Depth: PRIVATE PROC [cs: CoordSystem] RETURNS [index: NAT] = { thisCS: CoordSystem; index _ 0; thisCS _ cs; UNTIL thisCS = NIL DO index _ index + 1; thisCS _ CoordSys.Parent[thisCS]; ENDLOOP; }; ListTree: PUBLIC PROC [outHandle: IO.STREAM, tree: CSGTree] = { indent: NAT _ 0; node: REF ANY _ tree.son; ListNode[outHandle, node, indent]; }; ListNode: PROC [outHandle: IO.STREAM, node: REF ANY, indent: NAT] = { WITH node SELECT FROM prim: Primitive => ListPrimitive[outHandle, prim, indent]; comp: Composite => ListComposite[outHandle, comp, indent]; ENDCASE => ERROR; }; ListPrimitive: PROC [outHandle: IO.STREAM, prim: Primitive, indent: NAT] = { FOR i: NAT IN[1..indent] DO outHandle.PutChar[IO.TAB] ENDLOOP; outHandle.PutF["Primitive: %g\n",[rope[prim.name]]]; }; ListComposite: PROC [outHandle: IO.STREAM, comp: Composite, indent: NAT] = { op: Rope.ROPE; FOR i: NAT IN[1..indent] DO outHandle.PutChar[IO.TAB] ENDLOOP; op _ SVRay.PointSetOpToRope[comp.operation]; outHandle.PutF["Composite: %g op: %g\n",[rope[comp.name]], [rope[op]]]; ListNode[outHandle, comp.leftSolid, indent + 1]; ListNode[outHandle, comp.rightSolid, indent + 1]; }; FindNodeFromName: PUBLIC PROC [tree: REF ANY, name: Rope.ROPE] RETURNS [node: REF ANY, success: BOOL] = { WITH tree SELECT FROM c: Composite => {[node, success] _ FindNodeFromNameInComposite[c, name]; RETURN}; p: Primitive => {[node, success] _ FindNodeFromNameInPrimitive[p, name]; RETURN}; ENDCASE => ERROR; }; FindNodeFromNameInComposite: PROC [c: Composite, name: Rope.ROPE] RETURNS [node: REF ANY, success: BOOL] = { IF Rope.Equal[c.name, name, TRUE] THEN RETURN[c, TRUE]; [node, success] _ FindNodeFromName[c.leftSolid, name]; IF success THEN RETURN; [node, success] _ FindNodeFromName[c.rightSolid, name]; IF success THEN RETURN ELSE RETURN[NIL, FALSE]; }; FindNodeFromNameInPrimitive: PROC [p: Primitive, name: Rope.ROPE] RETURNS [node: REF ANY, success: BOOL] = { IF p.name = name THEN RETURN[p, TRUE] ELSE RETURN[NIL, FALSE]; }; CommonAncestor: PUBLIC PROC [red: Slice, blue: Slice, root: Slice] RETURNS [gramps: Slice] = { IF red = NIL THEN RETURN[blue]; IF blue = NIL THEN RETURN[red]; WITH root.shape SELECT FROM shape: Shape => { IF red = root AND blue = root THEN RETURN[root] ELSE RETURN[NIL]; }; alist: SliceList => { FOR sons: LIST OF Slice _ alist.list, sons.rest UNTIL sons = NIL DO IF ContainsBoth[red, blue, sons.first] THEN RETURN[CommonAncestor[red, blue, sons.first]]; ENDLOOP; IF ContainsBoth[red, blue, root] THEN RETURN[root] ELSE RETURN[NIL]; }; ENDCASE => ERROR; }; ContainsBoth: PRIVATE PROC [red: Slice, blue: Slice, root: Slice] RETURNS [BOOL] = { RETURN[IsSuccessorOf[red, root] AND IsSuccessorOf[blue, root]]; }; IsSuccessorOf: PUBLIC PROC [testChild: Slice, testAncestor: Slice] RETURNS [BOOL] = { WITH testAncestor.shape SELECT FROM shape: Shape => { IF testAncestor = testChild THEN RETURN[TRUE] ELSE RETURN[FALSE]; }; alist: SliceList => { IF testAncestor = testChild THEN RETURN[TRUE]; FOR list: LIST OF Slice _ alist.list, list.rest UNTIL list = NIL DO IF IsSuccessorOf[testChild, list.first] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; ENDCASE => ERROR; }; AncestorAtLevel: PUBLIC PROC [child: Slice, root: Slice, level: NAT] RETURNS [gramps: Slice] = { IF level = 0 THEN { IF IsSuccessorOf[child, root] THEN RETURN[root] ELSE RETURN[NIL]; } ELSE { WITH root.shape SELECT FROM shape: Shape => RETURN[NIL]; -- level >0 and we have no children. alist: SliceList => { FOR list: LIST OF Slice _ alist.list, list.rest UNTIL list = NIL DO gramps _ AncestorAtLevel[child, list.first, level-1]; IF gramps # NIL THEN RETURN; ENDLOOP; RETURN[NIL]; }; ENDCASE => ERROR; }; }; END. File: DisplayListToTreeImpl.mesa Author: Eric Bier on January 1, 1983 11:43 pm Copyright c 1984 by Xerox Corporation. All rights reserved. Last edited by Bier on June 2, 1987 2:04:09 pm PDT Contents: Code to extract a SVRay Tree from the recursive assemblylist-of-assemblylist DisplayList structure. Here's the plan: Each assembly list has an associated PointSetOp. If this op is null, it defaults to "union". Intersection means the intersection of all objects on the assembly list. Union is the union of all of them. Difference is the first one minus all of the others. Adds background color, and shadow information and packages up into a CSGTree record. If assembly is a primitive assembly, return a primitive SVRay node. Otherwise, call AssemblyListToNode on its children and return the resulting tree. We have a list of composite assemblies and/or primitive assemblies. Turn this into a list of Composites, Primitives and NILs: Now we will inspect our list in order to combine the trees we have made. If there are no children, then this node is NIL. It has no effect on the ray tracing. If there is only one item in the list then the node for this assembly is the node produced for its son. If all of the children are NIL, so is this node. If the operation is intersection and any are NIL then so is the node. IF the first is NIL and the operation is difference then the node is NIL. We have handled all cases which involve NILs. For all other cases, we should ignore them, so we will remove them now: At this point, we must reconsider the possibility that we may have a null list or single member list. Since it is now clear that this node has more than one child, we make n-1 Composite nodes for it (if there are n children remaining). In the top level call to MakeUnionNode, treeList should have at least 2 members and none of its members should be NIL. In the top level call to MakeIntersectionNode, treeList should have at least 2 members and none of its members should be NIL. In the top level call to MakeDifferenceNode, treeList should have at least 2 members and none of its members should be NIL. If there are no children, then this node is NIL. It has no effect on the ray tracing. Go down the list turning each primitive or composite assembly into a Composite or Primitive. If there are no children, then this node is NIL. It has no effect on the ray tracing. Go down the list turning each primitive or composite assembly into a Composite or Primitive. A Kludge for Now prim.hints will be filled in at preprocess time Returns a list of all of the assembly coordinate systems (not including the scalars-only shape coordinate systems). The list is in breadth-first order. Because the coordinate system and assembly trees need not be isomorphic, we must be careful to 1) Put into the list only those coordinate systems belonging to assemblies, but 2) Sort the list by depth order of the coordinate systems. One unreasonable way to do this is to tree walk the assemblies to make the list and then sort by depth (which we uncover in NlogN fashion by looking up the tree every bloody time). A better solution is to have a "depth" field in coordinate systems, but that will come later. We do not currently store a node's depth in that node. We recover this information stupidly in an NlogN sort of way by walking to the root from each node. Then we sort these depth numbers. This sorting is used to fileout scene trees. Of course, sorting is NlogN as well. Maybe I will use a bucket sort someday. We sort deep to shallow so we can put the list together backwards Index is distance from WORLD coordsys Here's where it hurts that assemblys don't point to their parents. For now, I will try a brute force approach. Starting at the root, I will walk down the tree until I find a node which contatins red and blue but none of whose children contains both. Returns NIL if no such node exists (perhaps root is below the real gramps, etc.). If root is a Primitive then root can only be gramps if red = blue = root; Could any of root's sons be gramps? None of the sons contain both. If I contain both, I am gramps. A Composite assembly contains if 1) It is lookFor. 2) It has a son which contains lookFor. Returns the ancestor of child which is level levels below root. If level is 0, should return root. If level = 1, an immediate child of root and so on. Works recursively as follows: If level is 0 then if root contains child, return root, else return NIL. If level > 0 then return the first non-NIL value returned by one of the children, or NIL if there are none. Κέ– "cedar" style˜IheadšΟnœ™ Iprocšœ'™-Jšœ Οmœ1™Ÿœ`Ÿœ˜Τ—šŸ˜Lšœ Ÿœ>Ÿœ`Ÿœ˜Φ—Lšœ  œ˜$—šœŸœŸœŸœ ŸœŸœŸœ ŸœŸœŸœŸœ˜Lšœ,Ÿœ'™VLš ŸœŸœŸœŸœŸœ˜!Lšœ\™\Lšœ Ÿœ€˜Lšœ !œ˜%—L˜š œŸœŸœŸœŸœŸœŸœŸœŸœ˜BšŸœŸœŸœŸœŸœŸœŸœŸ˜6Lš Ÿœ ŸœŸœŸœŸœ˜$—LšŸœ˜LšŸœŸœ˜ L˜—š œŸœŸœŸœŸœŸœŸœŸœŸœ˜BšŸœŸœŸœŸœŸœŸœŸœŸ˜6Lš Ÿœ ŸœŸœŸœŸœ˜#—LšŸœ˜LšŸœŸœ˜L˜—š œŸœŸœŸœŸœŸœŸœŸœŸœŸœŸœŸœ˜]š ŸœŸœŸœŸœŸœ˜ LšŸœŸœŸœŸœ&˜PLšŸœ'˜+L˜——J˜š œŸœŸœ6ŸœŸœ˜{Jšœ˜Jšœ ˜ J˜ JšœŸœ˜Jš ŸœŸœŸœŸœŸœ˜HJšœŸœ˜Jšœ˜J˜J™šŸœŸœ˜Jšœ:˜:JšŸœ ŸœŸœ#Ÿœ˜KšŸœ˜Jšœ3˜3JšœW˜WJšœ2˜2J˜—J˜—JšŸœ#Ÿœ˜˜>J˜Jšœ˜Jšœ3˜3Jšœ6˜6Jšœ@˜@Jšœ/™/JšœŸœ ,˜AJšœ*˜*Jšœ˜JšœŸœ˜JšœŸœ˜Jšœ˜—JšœŸœŸœŸœ˜0L˜šœŸœŸœŸœ˜QL™˜Lšœ/˜/Lšœ%˜%LšœŸœ  ˜1L˜L™—šœŸœŸœ˜ML˜LšœŸœŸœ˜!Lšœ#˜#LšœŸœ˜ Lšœ ŸœŸœ˜LšœŸœŸœ˜ šŸœŸœŸœŸ˜/LšŸœŸœŸ˜!šœ˜š Ÿœ ŸœŸœ'Ÿœ ŸœŸ˜SLšœ ŸœŸœ˜.Lšœ ŸœŸœ˜&L˜Lšœ˜L˜LšŸœ ŸœŸœ˜—LšŸœ˜L˜—LšŸœ 3˜B—LšŸœ˜L˜L˜—L™^L™PL™:L™“L™šœŸœŸœŸœ˜aLšœ»™»Lšœ˜Lšœ"˜"LšœŸœ‘ œ˜Lšœ)˜)šŸœ%ŸœŸœŸ˜;Lšœ Ÿœ‘œ˜>Lš‘œ ˜!—šŸœ˜LšœA™A—Lšœ Ÿœ‘œ˜*LšœŸœ˜ šŸœŸœŸœ Ÿ˜Lšœ Ÿœ‘œ˜*Lšœ1˜1Lšœ˜—LšŸœ˜Lšœ!˜!Lšœ #˜&L˜—LšœŸœŸœ˜/šœŸœŸœ˜"LšœŸœ˜ Lšœ˜L˜—šœŸœŸœ"ŸœŸœŸœŸœ˜RLšœŸœ˜"LšœŸœ˜"LšŸœ˜ Lšœ˜L˜—š  œŸœŸœŸœŸœ˜CLšœ˜šŸœ%ŸœŸœŸ˜;Lšœ˜—LšŸœ˜Lšœ˜L˜—š œŸœŸœŸœ Ÿœ˜>LšœŸœ ™%Lšœ˜Lšœ ˜ Lšœ ˜ šŸœ ŸœŸ˜Lšœ˜Lšœ!˜!LšŸœ˜—Lšœ˜L™—š œŸœŸœ ŸœŸœ˜?LšœŸœ˜LšœŸœŸœ ˜Lšœ"˜"Lšœ˜L˜—šœŸœ ŸœŸœŸœŸœ Ÿœ˜EšŸœŸœŸ˜Lšœ:˜:Lšœ:˜:LšŸœŸœ˜—Lšœ˜L˜—š  œŸœ ŸœŸœŸœ˜LLšŸœŸœŸœ ŸœŸœŸœŸœ˜>Lšœ4˜4Lšœ˜L˜—š  œŸœ ŸœŸœŸœ˜LLšœ Ÿœ˜LšŸœŸœŸœ ŸœŸœŸœŸœ˜>Lšœ,˜,LšœG˜GLšœ0˜0Lšœ1˜1Lšœ˜—L˜šœŸœŸœŸœŸœ ŸœŸœŸœŸœ Ÿœ˜išŸœŸœŸ˜LšœIŸœ˜QLšœIŸœ˜QLšŸœŸœ˜—Lšœ˜L˜—šœŸœŸœŸœŸœŸœ Ÿœ˜lLš ŸœŸœŸœŸœŸœ˜7Lšœ6˜6LšŸœ ŸœŸœ˜Lšœ7˜7LšŸœ ŸœŸ˜LšŸœŸœŸœŸœ˜Lšœ˜L˜—šœŸœŸœŸœŸœŸœ Ÿœ˜lšŸœŸœŸœŸœ˜%LšŸœŸœŸœŸœ˜Lšœ˜——L˜šœŸœŸœ(Ÿœ˜^Lšœ…ŸœG™ΟLšŸœŸœŸœŸœ˜LšŸœŸœŸœŸœ˜LšŸœ ŸœŸ˜˜L™ILšŸœ Ÿœ ŸœŸœ˜/LšŸœŸœŸœ˜L˜—šœ˜L™#š ŸœŸœŸœŸœŸœŸ˜CLšŸœ%ŸœŸœ(˜Z—LšŸœ˜L™?LšŸœŸœŸœ˜2LšŸœŸœŸœ˜L˜—LšŸœŸœ˜L˜L˜—š  œŸœŸœ(ŸœŸœ˜TLšŸœŸœ˜?L˜—– "Cedar" styleš  œŸœŸœ)ŸœŸœ˜ULšŸœŸœŸ˜#˜LšŸœŸœŸœŸœ˜-LšŸœŸœŸœ˜L˜—šœ˜Lšœ ™ Lšœ™L™'J– "Cedar" stylešŸœŸœŸœŸœ˜.– "Cedar" styleš ŸœŸœŸœŸœŸœŸ˜CJ– "Cedar" stylešŸœ&ŸœŸœŸœ˜:—J– "Cedar" stylešŸœ˜J– "Cedar" stylešŸœŸœ˜J– "Cedar" style˜—J– "Cedar" stylešŸœŸœ˜J– "Cedar" style˜J– "Cedar" style˜—– "Cedar" styleš œŸœŸœ$ŸœŸœ˜`J– "Cedar" styleš œ'‘œΡŸœ*Ÿœ+Ÿœ™ξ– "Cedar" stylešŸœ Ÿœ˜J– "Cedar" stylešŸœŸœŸœ˜/J– "Cedar" stylešŸœŸœŸœ˜J– "Cedar" style˜—– "Cedar" stylešŸœ˜J– "Cedar" stylešŸœ ŸœŸ˜J– "Cedar" stylešœŸœŸœ $˜A– "Cedar" stylešœ˜– "Cedar" styleš ŸœŸœŸœŸœŸœŸ˜CJ– "Cedar" stylešœ5˜5J– "Cedar" stylešŸœ ŸœŸœŸœ˜—J– "Cedar" stylešŸœ˜J– "Cedar" stylešŸœŸœ˜ J– "Cedar" style˜—J– "Cedar" stylešŸœŸœ˜J– "Cedar" style˜—– "Cedar" style˜J– "Cedar" style˜—J– "Cedar" style˜—– "Cedar" style˜J– "Cedar" style˜—L˜LšŸœ˜L˜—…—5\ο