DIRECTORY Sweep; SweepImpl: CEDAR PROGRAM IMPORTS Sweep EXPORTS Sweep = BEGIN OPEN Sweep; LineCarrier: TYPE = REF LineCarrierRec; LineCarrierRec: TYPE = RECORD[ carried: Line, lineLeft, lineRight: LineCarrier _ NIL ]; NilCopy: PUBLIC PROC [stateIn: REF ANY] RETURNS [stateOut: REF ANY] ~ { RETURN[stateIn] }; NilCombine: PUBLIC PROC [state1, state2: REF ANY] RETURNS [state: REF ANY] ~ { RETURN[NIL] }; NilFlip: PUBLIC PROC [stateIn: REF ANY] RETURNS [stateOut: REF ANY] ~ { RETURN[NIL] }; PowerOf2: PROC [in: CARDINAL] RETURNS [out: CARDINAL _ 32] ~ { UNTIL out >= in DO out _ out * 2; ENDLOOP; }; ExpandIfNecessary: PROC [in: REF PointSeq] RETURNS [out: REF PointSeq] ~ INLINE { OPEN in; IF size = max THEN { out _ NEW[PointSeq[max*2]]; FOR i: CARDINAL IN [0..size) DO out.data[i] _ data[i] ENDLOOP; out.size _ size; } ELSE out _ in; }; Intersect: PUBLIC PROC [in: Graph, Copy: CopyLineProc _ NilCopy, Combine: CombineLineProc _ NilCombine, Flip: FlipLineProc _ NilFlip] RETURNS [out: Graph] ~ { pointCount: CARDINAL _ 0; i: CARDINAL _ 0; changed: BOOLEAN; FlipLine: PROC [line: Line] ~ { OPEN line; temp: Point _ above; above _ below; below _ temp; state _ Flip[state]; }; freeLC: LineCarrier _ NIL; NewLC: PROC [carried: Line, lineLeft, lineRight: LineCarrier _ NIL] RETURNS [alive: LineCarrier] ~ { IF freeLC = NIL THEN RETURN[NEW[LineCarrierRec_ [carried: carried, lineLeft: lineLeft, lineRight: lineRight]]] ELSE { alive _ freeLC; freeLC _ alive.lineRight; alive.carried _ carried; alive.lineLeft _ lineLeft; alive.lineRight _ lineRight; } }; TrashFreeLC: PROC [] ~ { UNTIL freeLC = NIL DO freeLC.lineLeft _ NIL; freeLC _ freeLC.lineRight; ENDLOOP; }; sortedIn: REF PointSeq _ NEW[PointSeq[in.points.max]]; indexIn: CARDINAL _ 0; sortedOut: REF PointSeq _ NEW[PointSeq[in.points.max]]; switch: REF PointSeq; heap: REF PointSeq _ in.points; Heapify: PROC [] ~ { OPEN heap; limit: CARDINAL _ size; size _ 1; FOR i: CARDINAL IN [1..limit) DO data[size] _ data[i]; size _ size + 1; BubbleUp[size - 1]; ENDLOOP; }; QueueInsert: PROC [p: Point] ~ { heap _ ExpandIfNecessary[heap]; heap.data[heap.size] _ p; heap.size _ heap.size + 1; BubbleUp[heap.size - 1]; }; BubbleUp: PROC [pos: CARDINAL] ~ { pL: Point; r: Relation; pos _ pos + 1; -- shift for convience pL _ heap.data[pos - 1]; UNTIL pos = 1 DO pH: Point _ heap.data[pos/2 - 1]; r _ ComparePoints[pL, pH]; IF r # greater THEN { heap.data[pos - 1] _ pL; RETURN; } ELSE { heap.data[pos - 1] _ pH; pos _ pos / 2; }; ENDLOOP; heap.data[0] _ pL; }; HoleDown: PROC [pos: CARDINAL] ~ { OPEN heap; lower: CARDINAL; r: Relation; pos _ pos + 1; lower _ pos * 2; UNTIL lower >= size DO r _ ComparePoints[data[lower-1], data[lower]]; IF r = less THEN { data[pos - 1] _ data[lower]; pos _ lower + 1; } ELSE { data[pos - 1] _ data[lower - 1]; pos _ lower; }; lower _ pos*2; ENDLOOP; IF lower = size THEN {data[pos - 1] _ data[lower - 1]; size _ size - 1} ELSE { size _ size - 1; IF pos - 1 # size THEN { data[pos - 1] _ data[size]; BubbleUp[pos - 1]; }; }; }; EmptyQueue: PROC [] RETURNS [BOOLEAN] ~ { RETURN [(indexIn = sortedIn.size) AND (heap.size = 0)] }; NextEvent: PROC [] RETURNS [p: Point] ~ { OPEN heap; IF size = 0 THEN { -- heap is empty IF indexIn = sortedIn.size THEN ERROR ELSE { p _ sortedIn.data[indexIn]; indexIn _ indexIn + 1; } } ELSE { -- heap is full WHILE size >= 3 AND ComparePoints[data[0], data[2]] = equal DO --remove duplicates right tree MergePoints[data[0], data[2]]; HoleDown[2]; ENDLOOP; WHILE size >= 2 AND ComparePoints[data[0], data[1]] = equal DO --remove duplicates left tree MergePoints[data[0], data[1]]; HoleDown[1]; ENDLOOP; IF indexIn = sortedIn.size THEN { p _ data[0]; HoleDown[0]; } ELSE { r: Relation _ ComparePoints[ data[0], sortedIn.data[indexIn] ]; IF r = less THEN { p _ sortedIn.data[indexIn]; indexIn _ indexIn + 1; } ELSE { IF r = greater THEN { p _ data[0]; HoleDown[0] } ELSE { p _ data[0]; MergePoints[p, sortedIn.data[indexIn]]; indexIn _ indexIn + 1; HoleDown[0]; }; }; }; }; sortedOut _ ExpandIfNecessary[sortedOut]; sortedOut.data[sortedOut.size] _ p; sortedOut.size _ sortedOut.size + 1; }; xOrder, neighborRight, leftMostInserted: LineCarrier _ NIL; OrderRemoveLines: PROC [p: Point] RETURNS [rightNeighbor: LineCarrier] ~ { orderScan: LineCarrier _ xOrder; leftNeighbor: LineCarrier; lineScan: Line _ p.incoming; oldLineScan: Line; count: INT; AdvanceLineCarrier: PROC [] ~ { rightNeighbor _ orderScan.lineRight; orderScan.lineRight _ freeLC; freeLC _ orderScan; orderScan _ rightNeighbor; }; IF p.incoming = NIL THEN RETURN[NIL]; UNTIL lineScan = orderScan.carried DO --bounds fault indicates algorithmic failure orderScan _ orderScan.lineLeft; ENDLOOP; leftNeighbor _ orderScan.lineLeft; WHILE leftNeighbor # NIL DO IF leftNeighbor.carried.below # p THEN EXIT; orderScan _ orderScan.lineLeft; leftNeighbor _ orderScan.lineLeft; ENDLOOP; UNTIL lineScan = NIL DO IF lineScan # orderScan.carried THEN {--Out of order acceptable up to slope inequality count _ 0; WHILE orderScan # NIL DO IF (CompareSlopes[lineScan, orderScan.carried] # equal) OR (orderScan.carried.below # p) THEN EXIT; AdvanceLineCarrier[]; count _ count + 1; ENDLOOP; oldLineScan _ lineScan; lineScan _ lineScan.clockwiseAroundBelow; count _ count - 1; WHILE lineScan # NIL DO IF CompareSlopes[lineScan, oldLineScan] # equal THEN EXIT; lineScan _ lineScan.clockwiseAroundBelow; count _ count - 1; ENDLOOP; IF count # 0 THEN ERROR; } ELSE { lineScan _ lineScan.clockwiseAroundBelow; AdvanceLineCarrier[]; }; ENDLOOP; IF leftNeighbor # NIL THEN leftNeighbor.lineRight _ rightNeighbor; IF rightNeighbor # NIL THEN rightNeighbor.lineLeft _ leftNeighbor ELSE xOrder _ leftNeighbor; }; OrderInsertLines: PROC [p: Point, rightNeighborIn: LineCarrier] RETURNS [leftMostInserted, rightNeighbor: LineCarrier] ~ { r: Relation; lineScan, garbage, topHalf, bottomHalf: Line; lc, broken, leftNeighbor: LineCarrier; firstTime: BOOLEAN; rightNeighbor _ rightNeighborIn; IF p.outgoing = NIL THEN RETURN[NIL, rightNeighbor]; leftNeighbor _ IF rightNeighbor = NIL THEN xOrder ELSE rightNeighbor.lineLeft; UNTIL leftNeighbor = NIL DO r _ ComparePointLine[p, leftNeighbor.carried]; IF r = greater THEN EXIT; IF r = equal THEN { broken _ leftNeighbor; leftNeighbor _ leftNeighbor.lineLeft; topHalf _ broken.carried; broken.carried _ NIL; broken.lineLeft _ broken.lineRight _ NIL; bottomHalf _ NEW[LineRec _ [above: p, below: topHalf.below, state: Copy[topHalf.state]]]; RemoveLineFromPointBelow[topHalf]; InsertLineInPointBelow[bottomHalf]; InsertLineInPointAbove[bottomHalf]; IF p.incoming # NIL THEN ERROR; topHalf.below _ p; InsertLineInPointBelow[topHalf]; EXIT; }; rightNeighbor _ leftNeighbor; leftNeighbor _ leftNeighbor.lineLeft; ENDLOOP; leftMostInserted _ rightNeighbor; lineScan _ p.outgoing; firstTime _ TRUE; UNTIL lineScan = NIL DO IF (NOT firstTime) AND (CompareSlopes[leftMostInserted.carried, lineScan] = equal) THEN {r _ ComparePoints[leftMostInserted.carried.below, lineScan.below]; garbage _ lineScan; lineScan _ lineScan.clockwiseAroundAbove; IF r = equal THEN { leftMostInserted.carried.state _ Combine[leftMostInserted.carried.state, garbage.state]; RemoveLineFromPointAbove[garbage]; RemoveLineFromPointBelow[garbage]; } ELSE { IF r = greater THEN {topHalf _ leftMostInserted.carried; bottomHalf _ garbage} ELSE {topHalf _ garbage; bottomHalf _ leftMostInserted.carried; leftMostInserted.carried _ topHalf}; topHalf.state _ Combine[topHalf.state, bottomHalf.state]; RemoveLineFromPointAbove[bottomHalf]; bottomHalf.above _ topHalf.below; InsertLineInPointAbove[bottomHalf] }; } ELSE { lc _ NewLC[carried: lineScan, lineRight: leftMostInserted]; IF leftMostInserted # NIL THEN leftMostInserted.lineLeft _ lc ELSE xOrder _ lc; leftMostInserted _ lc; firstTime _ FALSE; lineScan _ lineScan.clockwiseAroundAbove}; ENDLOOP; leftMostInserted.lineLeft _ leftNeighbor; IF leftNeighbor # NIL THEN leftNeighbor.lineRight _ leftMostInserted; }; CompareLineLeft: PROC [lc: LineCarrier] ~ { newLc: LineCarrier; p: Point; s: LineRelation; s1, s2: EndPointRelation; ll, lr, topHalf, bottomHalf: Line; propagate: BOOLEAN _ FALSE; insertInQueue: BOOLEAN _ TRUE; r: Relation; BreakALine: PROC [l: Line] ~ { propagate _ TRUE; changed _ TRUE; topHalf _ l; bottomHalf _ NEW[LineRec _ [above: p, below: l.below, state: Copy[topHalf.state]]]; RemoveLineFromPointAbove[topHalf]; RemoveLineFromPointBelow[topHalf]; topHalf.below _ p; InsertLineInPointAbove[topHalf]; InsertLineInPointBelow[topHalf]; r _ ComparePoints[bottomHalf.above, bottomHalf.below]; IF r = equal THEN { IF bottomHalf.above = bottomHalf.below THEN insertInQueue _ FALSE } ELSE { IF r = less THEN FlipLine[bottomHalf]; InsertLineInPointAbove[bottomHalf]; InsertLineInPointBelow[bottomHalf] }; }; IF lc = NIL THEN RETURN; lr _ lc.carried; IF lc.lineLeft = NIL THEN RETURN; ll _ lc.lineLeft.carried; [p, s, s1, s2] _ PairIntersection[ll, lr]; IF s = colinear THEN { s1 _ s2 _ interior; IF ComparePoints[ll.below, lr.below] = less THEN { p _ lr.below; s2 _ below; } ELSE { p _ ll.below; s1 _ below; }; }; IF (s = intersect) OR (s = colinear) THEN { IF ComparePoints[p, currentPoint] = less THEN { IF s2 = interior THEN BreakALine[lr] ELSE { insertInQueue _ FALSE; IF s2 # below THEN ERROR; --Remove after debug }; IF s1 = interior THEN BreakALine[ll] ELSE { insertInQueue _ FALSE; IF s1 # below THEN ERROR; --Remove after debug }; IF insertInQueue THEN QueueInsert[p]; }; }; IF s = colinear THEN { r _ ComparePoints[ll.above, lr.above]; IF r = greater THEN { RemoveLineFromPointBelow[ll]; lr.state _ Combine[lr.state, ll.state]; ll.below _ lr.above; InsertLineInPointBelow[ll]; lc.lineLeft.carried _ lr } ELSE IF r = less THEN { RemoveLineFromPointBelow[lr]; ll.state _ Combine[ll.state, lr.state]; lr.below _ ll.above; InsertLineInPointBelow[lr]; } ELSE {ll.state _ Combine[ll.state, lr.state]; RemoveLineFromPointBelow[lr]; RemoveLineFromPointAbove[lr]; }; newLc _ lc.lineLeft; newLc.lineRight _ lc.lineRight; IF lc.lineRight # NIL THEN lc.lineRight.lineLeft _ newLc ELSE xOrder _ newLc; lc.carried _ NIL; lc.lineLeft _ lc.lineRight _ NIL; CompareLineLeft[newLc]; CompareLineLeft[newLc.lineRight]; } ELSE { IF CompareLinesAtY[ll, lr, currentPoint] = greater THEN {lc.carried _ ll; lc.lineLeft.carried _ lr; propagate _ TRUE}; IF propagate THEN {CompareLineLeft[lc.lineLeft]; CompareLineLeft[lc.lineRight]}; }; }; currentPoint: Point; IF in.status = invalid THEN ERROR; IF in.status = planar THEN RETURN[in]; Heapify[]; changed _ TRUE; WHILE changed DO changed _ FALSE; xOrder _ NIL; UNTIL EmptyQueue[] DO currentPoint _ NextEvent[]; neighborRight _ OrderRemoveLines[currentPoint]; [leftMostInserted, neighborRight] _ OrderInsertLines[currentPoint, neighborRight]; CompareLineLeft[neighborRight]; CompareLineLeft[leftMostInserted]; ENDLOOP; switch _ sortedIn; sortedIn _ sortedOut; sortedOut _ switch; indexIn _ 0; sortedOut.size _ 0; ENDLOOP; out _ NEW[GraphRec _ [status: planar, points: sortedIn]]; in.status _ invalid; TrashFreeLC[]; }; NilStart: PUBLIC PROC [lineLeft, lineRight: Line, regionPrevious: REF ANY] RETURNS [regionCenter: REF ANY] ~ { RETURN[NIL] }; NilStop: PUBLIC PROC [lineLeft: Line, regionCenter: REF ANY, lineRight: Line] ~ { RETURN; }; NilSplit: PUBLIC PROC [lineLeft, lineRight: Line, regionRight: REF ANY, regionPrevious: REF ANY _ NIL] RETURNS [regionLeft: REF ANY] ~ { RETURN[regionRight]; }; NilMerge: PUBLIC PROC [regionLeft: REF ANY, lineLeft, lineRight: Line, regionRight: REF ANY] RETURNS [regionCenter: REF ANY] ~ { RETURN[regionRight]; }; NilLineChange: PUBLIC PROC [lineOld, lineNew: Line, side: LeftOrRight, regionCenter: REF ANY, regionPrevious: REF ANY _ NIL] ~ { RETURN; }; ExpandedLineCarrier: TYPE = REF ExpandedLineCarrierRec; ExpandedLineCarrierRec: TYPE = RECORD[ carried: Line, regionLeft: REF ANY _ NIL, lineLeft, lineRight: ExpandedLineCarrier _ NIL ]; Sweep: PUBLIC PROC [in: Graph, infinityRegion: REF ANY _ NIL, Start: StartRegionProc _ NilStart, Stop: StopRegionProc _ NilStop, Split: SplitRegionProc _ NilSplit, Merge: MergeRegionProc _ NilMerge, LineChange: LineChangeRegionProc _ NilLineChange] RETURNS [out: Graph] ~ { xOrder, orderScan, temporaryELC, rightNeighbor, leftNeighbor: ExpandedLineCarrier; holdRegionLeft, temporaryRegion: REF ANY _ NIL; holdLineLeft, lineScan, prevLineScan: Line; currentPoint: Point; freeELC: ExpandedLineCarrier _ NIL; CleanELC: PROC [dead: ExpandedLineCarrier] ~ { OPEN dead; lineRight _ freeELC; freeELC _ dead; }; NewELC: PROC [carried: Line, regionLeft: REF ANY _ NIL, lineLeft, lineRight: ExpandedLineCarrier _ NIL] RETURNS [alive: ExpandedLineCarrier] ~ { IF freeELC = NIL THEN RETURN[NEW[ExpandedLineCarrierRec_ [carried: carried, regionLeft: regionLeft, lineLeft: lineLeft, lineRight: lineRight]]] ELSE { alive _ freeELC; freeELC _ alive.lineRight; alive.carried _ carried; alive.regionLeft _ regionLeft; alive.lineLeft _ lineLeft; alive.lineRight _ lineRight; } }; TrashFreeELC: PROC [] ~ { UNTIL freeELC = NIL DO freeELC.lineLeft _ NIL; freeELC _ freeELC.lineRight; ENDLOOP; }; IF in = NIL THEN RETURN[NIL]; IF in.status # planar THEN ERROR; FOR i: CARDINAL IN [0..in.points.size) DO currentPoint _ in.points.data[i]; lineScan _ currentPoint.incoming; IF lineScan = NIL THEN { leftNeighbor _ xOrder; rightNeighbor _ NIL; UNTIL leftNeighbor = NIL DO IF ComparePointLine[currentPoint, leftNeighbor.carried] = greater THEN EXIT; rightNeighbor _ leftNeighbor; leftNeighbor _ leftNeighbor.lineLeft; ENDLOOP; holdLineLeft _ NIL; holdRegionLeft _ IF rightNeighbor # NIL THEN rightNeighbor.regionLeft ELSE infinityRegion; } ELSE { orderScan _ xOrder; UNTIL lineScan = orderScan.carried DO --bounds fault indicates algorithmic failure orderScan _ orderScan.lineLeft; ENDLOOP; leftNeighbor _ orderScan.lineLeft; holdRegionLeft _ orderScan.regionLeft; holdLineLeft _ lineScan; DO prevLineScan _ lineScan; lineScan _ lineScan.clockwiseAroundBelow; rightNeighbor _ orderScan.lineRight; IF lineScan = NIL THEN EXIT; Stop[prevLineScan, rightNeighbor.regionLeft, lineScan]; CleanELC[orderScan]; orderScan _ rightNeighbor; IF lineScan # orderScan.carried THEN ERROR; ENDLOOP; }; lineScan _ currentPoint.outgoing; IF lineScan = NIL THEN { IF holdLineLeft # NIL THEN { temporaryRegion _ Merge[holdRegionLeft, holdLineLeft, prevLineScan, IF rightNeighbor = NIL THEN infinityRegion ELSE rightNeighbor.regionLeft]; CleanELC[orderScan]; IF rightNeighbor # NIL THEN { rightNeighbor.regionLeft _ temporaryRegion; rightNeighbor.lineLeft _ leftNeighbor } ELSE xOrder _ leftNeighbor; IF leftNeighbor # NIL THEN leftNeighbor.lineRight _ rightNeighbor; }; } ELSE { IF holdLineLeft # NIL THEN { LineChange[prevLineScan, lineScan, left, IF rightNeighbor = NIL THEN infinityRegion ELSE rightNeighbor.regionLeft]; CleanELC[orderScan]; }; DO prevLineScan _ lineScan; lineScan _ lineScan.clockwiseAroundAbove; IF lineScan = NIL THEN EXIT; temporaryELC _ NewELC[ carried: prevLineScan, regionLeft: Start[lineScan, prevLineScan, IF rightNeighbor = NIL THEN infinityRegion ELSE rightNeighbor.regionLeft], lineRight: rightNeighbor ]; IF rightNeighbor # NIL THEN rightNeighbor.lineLeft _ temporaryELC ELSE xOrder _ temporaryELC; rightNeighbor _ temporaryELC; ENDLOOP; temporaryELC _ NewELC[ carried: prevLineScan, regionLeft: holdRegionLeft, lineRight: rightNeighbor, lineLeft: leftNeighbor]; IF leftNeighbor # NIL THEN leftNeighbor.lineRight _ temporaryELC; IF rightNeighbor # NIL THEN rightNeighbor.lineLeft _ temporaryELC ELSE xOrder _ temporaryELC; IF holdLineLeft # NIL THEN { LineChange[holdLineLeft, prevLineScan, right, holdRegionLeft, IF rightNeighbor = NIL THEN infinityRegion ELSE rightNeighbor.regionLeft]; } ELSE temporaryELC.regionLeft _ Split[prevLineScan, currentPoint.outgoing, holdRegionLeft, IF rightNeighbor = NIL THEN infinityRegion ELSE rightNeighbor.regionLeft]; }; ENDLOOP; out _ NEW[GraphRec _ [status: planar, points: in.points]]; RemoveOrphanPoints[out]; in.status _ invalid; TrashFreeELC[]; }; RemoveOrphanPoints: PROC [in: Graph] ~ { OPEN in.points; limit: CARDINAL _ size; size _ 0; FOR i: CARDINAL IN [0..limit) DO IF data[i].incoming # NIL OR data[i].outgoing # NIL THEN { data[size] _ data[i]; size _ size + 1; }; ENDLOOP; }; END. ΪSweepImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Greene, March 28, 1986 2:20:15 pm PST Break LL Break LR Load the points into a priority queue Process the points in the priority queue Κ9˜šœ™Icodešœ Οmœ1™šžœ ž˜K˜Kšžœ˜—K˜—K˜š Ÿœžœžœ žœžœ žœ˜QKšžœ˜šžœ žœ˜Kšœžœ˜Kš žœžœžœ žœžœ˜?K˜Kšœ˜—Kšžœ ˜K˜—K˜J˜JšŸ œžœžœ ŸœŸœ Ÿœžœ˜žJšœ žœ žœ˜*Jšœ žœ˜J˜KšŸœžœ˜šžœ˜ K˜3K˜K˜—K˜Kšœžœ˜K˜šŸœžœ4žœžœ˜dš žœ žœžœžœžœPžœ˜uK˜*K˜PK˜—K˜—K˜šŸ œžœ˜šžœ žœž˜Kšœžœ˜1Kšžœ˜—K˜—J˜Jšœ žœ žœ˜6Jšœ žœ˜Jšœ žœ žœ˜7Jšœžœ ˜Jšœžœ˜J˜KšŸœžœ˜šžœ˜ Kšœžœ˜K˜ šžœžœžœ ž˜ K˜K˜K˜Kšžœ˜—K˜K˜—šŸ œžœ˜ K˜K˜4K˜K˜—K˜šŸœžœžœ˜"K˜KšœΟc˜&K˜šžœ ž˜K˜!K˜šžœ žœ˜K˜Kšžœ˜K˜—šžœ˜K˜K˜K˜—Kšžœ˜—K˜K˜—K˜KšŸœžœžœ˜"Kšžœ˜ šœžœ˜K˜K˜šžœž˜K˜.šžœ žœ˜K˜K˜K˜—šžœ˜K˜ K˜ K˜—K˜Kšžœ˜—Kšžœžœ3˜Gšžœ˜K˜šžœžœ˜K˜K˜K˜—K˜—K˜—K˜šŸ œžœžœžœ˜)Kšžœžœ˜6K˜—K˜KšŸ œžœžœ˜)Kšžœ˜ šžœ žœ ˜#šžœžœžœžœ˜,K˜K˜K˜—K˜—šžœ ˜šžœ žœ)žœ ˜^K˜K˜ Kšžœ˜—šžœ žœ)žœ ˜]K˜K˜ Kšžœ˜—šžœžœ˜!K˜ K˜ K˜—šžœ˜K˜?šžœ žœ˜K˜K˜K˜—šžœ˜šžœ žœ˜K˜ K˜ K˜—šžœ˜K˜ K˜'K˜K˜ K˜—K˜—K˜K˜—K˜)K˜#K˜$K˜—J˜K˜Kšœ7žœ˜;K˜šŸœžœ žœ!˜JK˜ K˜K˜Kšœžœ˜K˜šŸœžœ˜K˜$Kšœ2˜2K˜K˜—Kš žœžœžœžœžœ˜%šžœžœ ,˜UK˜Kšžœ˜—K˜"šžœžœž˜Kšžœ žœžœ˜,K˜K˜"Kšžœ˜—šžœ žœž˜šžœž˜$Kšœ 0˜1K˜ šžœ žœž˜Kšžœ6žœžœžœ˜cK˜K˜Kšžœ˜—K˜AK˜šžœ žœž˜Kšžœ.žœžœ˜:K˜)K˜Kšžœ˜—Kšžœ žœžœ˜K˜—šžœ˜K˜)K˜K˜—Kšžœ˜—Kšžœžœžœ(˜BKšžœžœžœ'žœ˜]K˜—J˜šŸœžœ*žœ3˜zK˜ K˜-K˜&Kšœ žœ˜K˜Kšœ ˜ Kš žœžœžœžœžœ˜4Kš œžœžœžœžœ˜Nšžœžœž˜K˜.Kšžœ žœžœ˜šžœ žœ˜K˜K˜%K˜Kšœžœ'žœ˜?Kšœ žœI˜YK˜"K˜#K˜#Kšžœžœžœžœ˜K˜K˜ Kšžœ˜K˜—K˜K˜%Kšžœ˜—K˜!K˜Kšœ žœ˜šžœ žœž˜šžœžœ žœ=ž˜WK˜CK˜K˜)šžœ žœ˜K˜XK˜EK˜—šžœ˜Kšžœ žœ;˜NKšžœ`˜dK˜9K˜%K˜!K˜"K˜—K˜—šž˜Kšœ=˜=Kšžœžœžœ žœ ˜OK˜Kšœ žœ˜K˜*—Kšžœ˜—K˜)Kšžœžœžœ,˜FK˜—K˜šŸœžœ˜,K˜K˜4K˜"Kšœ žœžœ˜Kšœžœžœ˜Kšœ ˜ K˜šŸ œžœ˜Kšœ žœ˜Kšœ žœ˜K˜ KšœžœC˜TK˜"K˜"K˜K˜ K˜ K˜K˜6šžœ žœ˜Kšžœ%žœž˜AK˜—šžœ˜Kšžœ žœ˜&K˜#K˜"K˜—K˜——˜Kšžœžœžœžœ˜K˜Kšžœžœžœžœ˜!K˜K˜K˜*šžœžœ˜K˜šžœ*žœ˜2K˜ K˜ K˜—šžœ˜K˜ K˜ K˜—K˜K˜—šžœžœžœ˜+šžœ'žœ˜/Kšžœžœ˜%šžœ˜Kšœžœ˜Kšžœ žœžœ ˜/K˜—Kšžœžœ˜$šžœ˜Kšœžœ˜Kšžœ žœžœ ˜/K˜—Kšžœžœ˜%K˜—K˜—K˜šžœžœ˜K˜&šžœ žœ˜Kšœ™K˜K˜'K˜K˜K˜K˜—šžœžœ žœ˜Kšœ™K˜K˜'K˜K˜K˜—šžœ˜K˜(K˜K˜K˜—K˜Kšœ˜Kšžœžœžœžœ˜MKšœ žœžœ˜3K˜K˜!K˜—šžœ˜šžœ1ž˜7K˜K˜Kšœ žœ˜—šžœ ž˜K˜K˜—K˜—K˜—K˜K˜K˜Kšžœžœžœ˜"Kšžœžœžœ˜&J˜Jšœ%™%J˜K˜ J˜Jšœ(™(J˜Jšœ žœ˜šžœ ž˜Kšœ žœ˜Kšœ žœ˜ šžœž˜K˜K˜/K˜RK˜K˜"Kšžœ˜—K˜žœžœžœžœ˜ˆK˜—šž˜Kš œUžœžœžœžœ˜Ÿ—K˜—Kšžœ˜K˜—Kšœžœ1˜:K˜K˜K˜K˜K˜K˜KšŸœžœ˜(šžœ ˜Kšœžœ˜"šžœžœžœ ž˜ š žœžœžœžœžœ˜:K˜K˜K˜—Kšžœ˜—K˜—J˜Jšžœ˜J˜J˜J˜Jšœ˜—…—?vS‰