From 18bb4e7110d4c5cdd6b7bcc885b3f921bf642a96 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 29 Jun 2015 01:32:01 +0300 Subject: [PATCH] Improved and introduced the overloaded minkowski_sum_2(), which accepts 2 decompositio strategies --- .../doc/Minkowski_sum_2/Minkowski_sum_2.txt | 234 ++++++++++-------- .../fig/ms_concave_polygon.png | Bin 3951 -> 1395 bytes .../Minkowski_sum_2/fig/ms_convex_polygon.png | Bin 3068 -> 639 bytes .../Minkowski_sum_2/fig/ms_convolution.png | Bin 6526 -> 3735 bytes 4 files changed, 134 insertions(+), 100 deletions(-) diff --git a/Minkowski_sum_2/doc/Minkowski_sum_2/Minkowski_sum_2.txt b/Minkowski_sum_2/doc/Minkowski_sum_2/Minkowski_sum_2.txt index 89de2cb1379..511f43b5965 100644 --- a/Minkowski_sum_2/doc/Minkowski_sum_2/Minkowski_sum_2.txt +++ b/Minkowski_sum_2/doc/Minkowski_sum_2/Minkowski_sum_2.txt @@ -13,16 +13,16 @@ namespace CGAL { Given two sets \f$ A,B \in \mathbb{R}^d\f$, their Minkowski sum, denoted by \f$ A \oplus B\f$, is their point-wise sum, namely the set -\f$ \left\{ a + b ~|~ a \in A, b \in B \right\}\f$. -Minkowski sums are used in many applications, such as motion planning and -computer-aided design and manufacturing. This package contains functions -that compute the planar Minkowski sums of two simple polygons; namely, -\f$ A\f$ and \f$ B\f$ are two closed polygons in \f$ \mathbb{R}^2\f$) -(see Chapter \ref Chapter_2D_Regularized_Boolean_Set-Operations -"2D Regularized Boolean Set-Operations" for the precise definition of a -simple polygon), and the planar Minkowski sum of a simple polygon and a +\f$ \left\{ a + b ~|~ a \in A, b \in B \right\}\f$. Minkowski sums are +used in many applications, such as motion planning and computer-aided +design and manufacturing. This package contains functions that compute +the planar Minkowski sums of two polygons. (Here, \f$ A\f$ and \f$ B\f$ +are two closed polygons in \f$ \mathbb{R}^2\f$, which may have holes; see +Chapter \ref Chapter_2D_Regularized_Boolean_Set-Operations "2D +Regularized Boolean Set-Operations" for the precise definition of valid +polygons), and the planar Minkowski sum of a simple polygon and a disc---an operation also referred to as offsetting or dilating -a polygon).\cgalFootnote{The family of valid types of summands is slightly +a polygon). \cgalFootnote{The family of valid types of summands is slightly broader for certain operations, e.g., a degenerate polygon consisting of line segments is a valid operand for the approximate-offsetting operation.} This package, like the \ref Chapter_2D_Regularized_Boolean_Set-Operations @@ -32,7 +32,7 @@ by the \ref chapterArrangement_on_surface_2 "2D Arrangements" package. The two packages are integrated well to allow mixed operations. For example, it is possible to apply Boolean set operations on objects that are the result of Minkowski sum -computations.\cgalFootnote{The operands of the Minkowski sum operations +computations. \cgalFootnote{The operands of the Minkowski sum operations supported by this package must be (linear) polygons, as opposed to the operands of the Boolean set operations supported by the \ref Chapter_2D_Regularized_Boolean_Set-Operations @@ -51,7 +51,7 @@ edges ordered according to the angle they form with the \f$ x\f$-axis. As the two input polygons are convex, their edges are already sorted by the angle they form with the \f$ x\f$-axis; see the figure above. The Minkowski sum can therefore be computed using an operation similar to the -merge step of the merge-sort algorithm\cgalFootnote{See, for example, +merge step of the merge-sort algorithm \cgalFootnote{See, for example, http://en.wikipedia.org/wiki/Merge_sort.} in \f$ O(m + n)\f$ time, starting from two bottommost vertices in \f$ P\f$ and in \f$ Q\f$ and merging @@ -62,16 +62,14 @@ The convolution of a convex polygon and a non-convex polygon. The convolution consists of a single self-intersecting cycle, drawn as a sequence of directed line segments. Each face of the arrangement induced by the segments forming the cycle contains its winding number. The Minkowski sum of the two polygons -is shaded. +is shaded. Dotted edges are not part of the reduced convolution. \cgalFigureEnd If the polygons are not convex, you can utilize either the -Decomposition or the Convolution approaches described below. -Regarding the implementation of the two approaches, applications of -Minkowski sum operations are restricted to polygons that are simple. -Applications of some of the variant operations are also restricted to -polygons that do not contain holes. (Resulting sums may contain holes -though.) +Decomposition or the Convolution approaches described +below. Applications of some of the operations in this package are +restricted to polygons that do not contain holes. (Resulting sums may +contain holes though.)
Decomposition:
@@ -84,92 +82,119 @@ simple procedure described above, and finally compute the union \f$ P \oplus Q = \bigcup_{ij}{S_{ij}}\f$; see \ref ref_bso_union "Union Functions". -This approach relies on a successful decomposition of the input polygons -into convex pieces, and its performance depends on the quality and performance -of the decomposition. The supplied decomposition methods do not handle point -sets that are not simple. +This approach relies on a successful decomposition of the input +polygons into convex pieces, and its performance depends on the +quality and performance of the decomposition. Some of the supplied +decomposition methods do not handle polygons that contain holes.
Convolution:
-Let us denote the vertices of the input polygons by -\f$ P = \left( p_0, \ldots, p_{m-1} \right)\f$ and -\f$ Q = \left( q_0, \ldots, q_{n-1} \right)\f$. We assume that both \f$ P\f$ and \f$ Q\f$ -have positive orientations (i.e.\ their boundaries wind in a counterclockwise -order around their interiors) and compute the convolution of the two polygon -boundaries. The convolution of these two polygons \cgalCite{grs-kfcg-83}, +Let \f$ P = \left( p_0, \ldots, p_{m-1} \right)\f$ and +\f$ Q = \left(q_0, \ldots, q_{n-1} \right)\f$ denote the vertices of +the input polygons. We assume that both \f$ P\f$ and \f$ Q\f$ have +positive orientations (i.e., their boundaries wind in a +counterclockwise order around their interiors). The +convolution of these two polygons \cgalCite{grs-kfcg-83}, denoted \f$ P * Q\f$, is a collection of line segments of the form -\f$ [p_i + q_j, p_{i+1} + q_j]\f$, \cgalFootnote{Throughout this chapter, we increment -or decrement an index of a vertex modulo the size of the polygon.} -where the vector \f$ {\mathbf{p_i p_{i+1}}}\f$ -lies between \f$ {\mathbf{q_{j-1} q_j}}\f$ and \f$ {\mathbf{q_j -q_{j+1}}}\f$, \cgalFootnote{We say that a vector \f$ {\mathbf v}\f$ lies between -two vectors \f$ {\mathbf u}\f$ and \f$ {\mathbf w}\f$ if we reach \f$ {\mathbf v}\f$ strictly before reaching \f$ {\mathbf w}\f$ if we move all three vectors to the origin and rotate \f$ {\mathbf u}\f$ counterclockwise. Note that this also covers the case where \f$ {\mathbf u}\f$ has the same direction as \f$ {\mathbf v}\f$.} and, symmetrically, of segments of the form \f$ [p_i + q_j, p_i + q_{j+1}]\f$, -where the vector \f$ {\mathbf{q_j q_{j+1}}}\f$ lies between -\f$ {\mathbf{p_{i-1} p_i}}\f$ and \f$ {\mathbf{p_i p_{i+1}}}\f$. +\f$ [p_i + q_j, p_{i+1} + q_j]\f$, \cgalFootnote{Throughout this +chapter, we increment or decrement an index of a vertex modulo the +size of the polygon.} where the vector \f$ {\mathbf{p_i p_{i+1}}}\f$ +lies between \f$ {\mathbf{q_{j-1} q_j}}\f$ and +\f$ {\mathbf{q_j q_{j+1}}}\f$, \cgalFootnote{We say that a vector +\f$ {\mathbf v}\f$ lies between two vectors \f$ {\mathbf u}\f$ and +\f$ {\mathbf w}\f$ if we reach \f$ {\mathbf v}\f$ strictly before +reaching \f$ {\mathbf w}\f$ if we move all three vectors to the +origin and rotate \f$ {\mathbf u}\f$ counterclockwise. Note that this +also covers the case where \f$ {\mathbf u}\f$ has the same direction +as \f$ {\mathbf v}\f$.} and, symmetrically, of segments of the form +\f$ [p_i + q_j, p_i + q_{j+1}]\f$, where the vector \f$ {\mathbf{q_j +q_{j+1}}}\f$ lies between \f$ {\mathbf{p_{i-1} p_i}}\f$ and \f$ +{\mathbf{p_i p_{i+1}}}\f$. The segments of the convolution form a number of closed (not -necessarily simple) polygonal curves called convolution -cycles. The Minkowski sum \f$ P \oplus Q\f$ is the set of points -having a non-zero winding number with respect to the cycles -of \f$ P * Q\f$. \cgalFootnote{Informally speaking, the winding number of a point \f$ p \in\mathbb{R}^2\f$ with respect to some planar curve \f$ \gamma\f$ is an integer number counting how many times does \f$ \gamma\f$ wind in a counterclockwise direction around \f$ p\f$.} See \cgalFigureRef{mink_figonecyc} -for an illustration. +necessarily simple) polygonal curves called convolution cycles. +The Minkowski sum \f$ P \oplus Q\f$ is the set of points +having a non-zero winding number with respect to the cycles of +\f$ P * Q\f$. \cgalFootnote{Informally speaking, the winding number +of a point \f$ p \in\mathbb{R}^2\f$ with respect to some planar curve +\f$ \gamma\f$ is an integer number counting how many times does +\f$ \gamma\f$ wind in a counterclockwise direction around \f$ p\f$.} +See \cgalFigureRef{mink_figonecyc} for an illustration. -The number of segments in the convolution of two polygons is usually -smaller than the number of segments that constitute the boundaries of the -sub-sums \f$ S_{ij}\f$ when using the decomposition approach. As both approaches -construct the arrangement of these segments and extract the sum from this -arrangement, computing Minkowski sum using the convolution approach usually -generates a smaller intermediate arrangement, hence it is faster and -consumes less space. -
Reduced Convolution:
-We can reduce the number of segments in the arrangement even further by -noticing that only convolution segments created by a convex vertex can be part -of the Minkowski sum. In segments of the form \f$ [p_i + q_j, p_{i+1} + q_j]\f$, -the vertex \f$q_j\f$ has to be convex, and in segments of the form \f$ -[p_i + q_j, p_i + q_{j+1}]\f$, the vertex \f$p_i\f$ has to be convex. The -collection of the remaining segments is called the reduced convolution -\cgalCite{cgal:bl-frmsurc-11}. +We construct the arrangement induced by the convolution cycles of +\f$P \f$ and \f$Q \f$, then compute the winding numbers of the cells +of the arrangement. Finally, we extract the Minkowski sum from the +arrangement. This variant is referred to as the full-convolution method. -The winding number property can no longer be used here. Instead we define two -different filters to identify holes in the Minkowski sum: +A segment \f$[p_i + q_j, p_{i+1} + q_j] \f$ (resp. +\f$[p_i + q_j, p_i + q_{j+1}] \f$) cannot possibly contribute to the +boundary of the Minkowski sum if \f$q_j \f$ (resp. \f$p_i \f$) is a +reflex vertex (see dotted edges in \cgalFigureRef{mink_figonecyc}). +The remaining subset of convolution segments is called the +reduced convolution \cgalCite{cgal:bl-frmsurc-11}. This subset +is still a superset of the Minkowski sum boundary, but the winding +number property does not apply any longer as there are no closed +cycles anymore. We apply two different filters, which identify holes in +the Minkowski sum:
    -
  1. Loops that are on the Minkowski sum's boundary have to be orientable, that -is, all normal directions of its edges have to point either inward or -outward.
  2. -
  3. For any point \f$x\f$ inside of a hole of the Minkowski sum, the following -condition holds: \f$(-P + x) \cap Q = \emptyset\f$. If, on the other hand, the -inversed version of \f$P\f$, translated by \f$x\f$, overlaps \f$Q\f$, the loop -is a false hole and is in the Minkowski sum's interior.
  4. +
  5. A loop that is on the Minkowski sum boundary has to be orientable; + that is, all normal directions of its edges have to point either + inward or outward.
  6. +
  7. For any point \f$x\f$ inside of a hole of the Minkowski sum, the + following condition holds: \f$(-P + x) \cap Q = \emptyset\f$. If, on + the other hand, the inversed version of \f$P\f$, translated by + \f$x\f$, overlaps \f$Q\f$, the loop is a false hole and is in + the interior of the Minkowski sum.
-After applying these two filters, only those segments which constitute the -Minkowski sum's boundary remain. In most cases, the reduced convolution -approach is even faster than the full convolution approach, as the induced -arrangement is usually much smaller. However, in degenerated cases with many -holes in the Minkowski sum, the full convolution approach can be preferable to -avoid the costly intersection tests. +After applying these two filters, only those segments which constitute +the Minkowski sum boundary remain. This variant is referred to as the +reduced-convolution method.
+The number of segments in the convolution of two polygons is usually +smaller than the number of segments that constitute the boundaries of +the sub-sums \f$ S_{ij}\f$ when using the decomposition approach. As +both approaches construct the arrangement of these segments and +extract the sum from this arrangement, computing Minkowski sum using +the convolution approach usually generates a smaller intermediate +arrangement, hence it is faster and consumes less space. In most cases, +the reduced convolution method is faster than the full convolution +method, as the respective induced arrangement is usually much smaller. +However, in degenerate cases with many holes in the Minkowski sum, the +full convolution method can be preferable, as it avoids costly +intersection tests. + \subsection mink_ssecsum_conv Computing Minkowski Sum using Convolutions -The function template \link minkowski_sum_2() `minkowski_sum_2(P, Q)`\endlink -accepts two simple polygons \f$ P\f$ and \f$ Q\f$ and computes their -Minkowski sum \f$ S = P \oplus Q\f$ using the convolution method. -\link minkowski_sum_2() `minkowski_sum_2(P, Q)`\endlink defaults to calling the -function \link minkowski_sum_reduced_convolution_2() `minkowski_sum_reduced_convolution_2(P, Q)`\endlink, -which applies the reduced convolution aforementioned. -Explicitly call the function \link minkowski_sum_full_convolution_2() +The function template \link minkowski_sum_2() +`minkowski_sum_2(P, Q)`\endlink accepts two polygons +\f$ P\f$ and \f$ Q\f$ and computes their Minkowski sum +\f$ S = P \oplus Q\f$ using the convolution approach. +The call \link minkowski_sum_2() `minkowski_sum_2(P, Q)`\endlink +defaults to the call \link minkowski_sum_reduced_convolution_2() +`minkowski_sum_reduced_convolution_2(P, Q)`\endlink, which applies +the reduced convolution aforementioned method. Explicitly call +\link minkowski_sum_full_convolution_2() `minkowski_sum_full_convolution_2(P, Q)`\endlink to apply -the full convolution approach. -The types of the operands are instances of the -\link Polygon_2 `Polygon_2`\endlink class template. As the input polygons -may not be convex, their Minkowski sum may not be simply connected and -contain polygonal holes; see for example \cgalFigureRef{mink_figonecyc}. -The type of the returned object \f$ S \f$ is therefore an instance of the -\link Polygon_with_holes_2 `Polygon_with_holes_2`\endlink class template. -The outer boundary of \f$ S \f$ is a polygon that can be accessed using -`S.outer_boundary()`, and its polygonal holes are given by the range -[`S.holes_begin()`, `S.holes_end()`) (where \f$ S \f$ contains -`S.number_of_holes()` holes in its interior). +the full convolution method. The types of the operands accepted by +the function \link minkowski_sum_full_convolution_2() +`minkowski_sum_full_convolution_2(P, Q)`\endlink are instances of +the \link Polygon_2 `Polygon_2`\endlink class template. The types of +operands accepted by the function \link +minkowski_sum_reduced_convolution_2() +`minkowski_sum_reduced_convolution_2(P, Q)`\endlink +are instances of either the \link Polygon_2 `Polygon_2`\endlink or +\link Polygon_with_holes_2 `Polygon_with_holes_2`\endlink class templates. +Even when the input polygons are restricted to be simple polygons, they +still may not be convex; thus, their Minkowski sum may not be simply +connected and may contain polygonal holes; see for example +\cgalFigureRef{mink_figonecyc}. The type of the returned object \f$ S \f$ +is therefore an instance of the +\link Polygon_with_holes_2 `Polygon_with_holes_2`\endlink class template +in all cases. Recall that the outer boundary of \f$S \f$ is a polygon +that can be accessed using `S.outer_boundary()`, and its polygonal +holes are given by the range [`S.holes_begin()`, `S.holes_end()`) (where +\f$ S \f$ contains `S.number_of_holes()` holes in its interior). \cgalFigureBegin{mink_figsum_tri_sqr,ms_sum_triangle_square.png} The Minkowski sum of a triangle and a square, as computed by the example @@ -208,17 +233,26 @@ Minkowski sum procedure. In order to compute Minkowski sums of two polygon \f$ P \f$ and \f$ Q \f$ using the decomposition method, issue the call -`minkowski_sum_2(P, Q, decomp)`, where `decomp` is an object of a type -that models the concept `PolygonConvexDecomposition`, which in turn -refines a `Functor` concept variant. Namely, it requires the provision -of a function operator (`operator()`) that accepts a planar polygon and -returns a range of convex polygons that represents its convex decomposition. -If at least one of \f$ P \f$ or \f$ Q \f$ is a polygon with holes, -`decomp` is an object of a type that models the concept +`minkowski_sum_2(P, Q, decompP, decompQ)`, where each of \f$P \f$ +and \f$Q \f$ is either a simple polygon or a polygon with holes. +If \f$P \f$ is a simple polygon, `decompP` must be an object of +a type that models the concept `PolygonConvexDecomposition_2`. +If \f$P \f$ is a polygon with holes, them `decompP` is an object +of a type that models the concept `PolygonWithHolesConvexDecomposition_2`, which refines the concept -`PolygonConvexDecomposition` and adds a requirement for the provision -of a function operator (`operator()`) that accepts a planar polygon with -holes. +`PolygonConvexDecomposition_2`. The same holds for \f$Q \f$. +The two concepts `PolygonConvexDecomposition_2` and +`PolygonWithHolesConvexDecomposition` refine a `Functor` concept +variant. Namely, they both require the provision of a function +operator (`operator()`). The function operator of the model of the +concept `PolygonConvexDecomposition_2` accepts a planar simple +polygon, while the function operator of the model of the concept +`PolygonWithHolesConvexDecomposition_2` accepts a planar polygon +with holes. Both return a range of convex polygons that represents +the convex decomposition of the input polygon. If the decomposition +strategy that decomposes \f$P \f$ is the same as the strategy that +decompose \f$Q \f$, you can omit the forth argument, and +issue the call `minkowski_sum_2(P, Q, decomp)`. The Minkowski-sum package includes four models of the concept `PolygonConvexDecomposition_2` and two models of the refined concept @@ -274,7 +308,7 @@ diagonal that is closest to the angle bisector emanating from this vertex and having rational-coordinate endpoints on both sides. -The following two models the refined concept +The following are two models of the refined concept `PolygonWithHolesConvexDecomposition_2`. An instance of any one these two types can be used to decompose a polygon with holes. You can pass the instance as the third argument to call diff --git a/Minkowski_sum_2/doc/Minkowski_sum_2/fig/ms_concave_polygon.png b/Minkowski_sum_2/doc/Minkowski_sum_2/fig/ms_concave_polygon.png index 5511967d444fd62635c65c63ca50d85e832ab5c3..d92b6d433db427a684009fb5a48f50f72db7d866 100644 GIT binary patch literal 1395 zcmZ`&e@qj16#r77BKT{y3m~W!jzh+w?ID!b@}sQ4oh?-=5}Gl`k1MQ>0V_2YC4+*_ zow9jwu~IE+7#$-{LIIsWm~lg9j{=5Hr=rs>Hd9d9hBAk9W5<#u+mhwweLi`g_da>= zpGR&|XDswz<_`c^h+_&3%N{mQ_<6G^-+PhEl23^|Qx1URK){OvU$*wD)MTWB&XLe@ zwh$CynoIz8!T{9n2H-g>)jj}VyAXhhd;p})00dUp&SlBiM(HM1c3S7Qu(MUMr;IVD zDv{4?Bz@KKo!i3Cn9wsO(d?(zqgyXGmppy=y`vmCT_v5F{^{OO@Ax5 z?wxPcs5d{od;id*_GdpIlZW5?jTOBLl^KelBl~tIhqywX zZ5n(0wKj*JwIpp+<9Ib-{Z)R5;(l_5veU)gUp;!K`qIAG`X`PZ=XYH@KbyZ}s&{Am z;$7Y8iCX*7Pc<8JIwDV8rMFBluS^pMcXn_1huk~h>A620`K)B^)|_M2)6a)zZcWfX z-dXF~yMK&cnH=Mqnh7`B@DqfgljUKsa?%rrT_W(77rwlg zv}j~aJ<&s`|M0?#aodXk$Qn^TwUWxS^fDoW4n$9j<*2qBp7mx3{IHDE?xF!?NU@qDW+3b437 zietTkZrAvsExL&|J`wL4!bQ$f3rYJ^4DtltBB<2E=1Z(_+3=-KnI(!&r}RiHJS^zREmn=mVTY>OSgR@wP9Eo2`_XFmd~}cQ*S0`{ z>w18TF}@2mp#bvN1+Ne0@Y1>)S{l4aj`lq@*Q_uj;gS6*tqB%0Z5Ct&xh^sowR)fK zHnAGx51^%J5aeGN92dNZH_+8^xM3cdn#;|EYZa@IB6xF3tDj{RjSI4Xi@l$6UO@}d zh0s*bf@YNuc^mni?hrH{ve%%2kfGbS5w2ILEq53r<-F{c;DF3STIdCov)?Voy+|4I zIt@|IFWj-XH~9!jq-B(I$SuNs$RXr0olQ9h-7=g@HXy@vDdqgiEyd@NrN{?#NUZ|4 zoMtjp!UB}HJn@1?vt4fpr<@nv=-FVbtwi5^dkLiJS*I$S&(musBE`OBFLI3zsaI^U zj4{LVu;t3fo?irw`|Jh-hr$LlVu>%-R?uZucTR$jkInv!c*4 z#dM^EMJZ=Id4fjDZZe=0=F~_f%Q2`Z%4S;v@f>{hh#wEn9faF`NC-)z={g0+(!}WH zts*7k=@X1n_IyJj^`_Gxlf+@`3MDpMD736AR6VkYcd{omQ@wbORFhXaFMLamT+dwu zuf1^Bs$LF9|IcUqNACB0L{B8XJLRo|TTfkjqdAv-(FkK&u8}A(>ZC;m9ZLWeisE8~ z@iC|*TPT#GVrgt#v@ljG6pr2u3jCMh?Q%k2T=oBkZGP*l7oPHYm1g=-QLqJ?ZEiON_9|8GZ*&QPf@F9Vwt=`o@;>ja@0QWM(; Mc$!+#nVMhsC%n!%1ONa4 literal 3951 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 diff --git a/Minkowski_sum_2/doc/Minkowski_sum_2/fig/ms_convex_polygon.png b/Minkowski_sum_2/doc/Minkowski_sum_2/fig/ms_convex_polygon.png index a58431589396dec30f2d0c3e10f0167e0bbeb4d8..9d1fc365ff0f34d7f7b4873a74287d9d80a79d7e 100644 GIT binary patch literal 639 zcmeAS@N?(olHy`uVBq!ia0vp^Rv^s53?#3m?veshEa{HEjtmSN`?>!lvI6;x#X;^) z4C~IxyaaL-l0AZa85pY67#JE_7#My5g&JNkFq9fFFuY0t8Z?7}LA+qju0R{0gmHjR zi0l9V{~Zgr8mFyxD%$E@wc8?Vy=~q`kMdnsIU9k3_W7GFv)8XW`g7)vcbm@qPwPJm zRR1?s&;h8OrzFTPm|=R_+TTC!e(4u{Fn^nMl>$(lG0EHAg`tC0)&t1lEbxdd2GSt5 z2ZP(mY&#(1lBbJfh{y4{=RL)m90XV{h6%_ByswY0?6JKvA#&sYZjX~M%KQ)R`X{(0 z*1k5mY~p8`O{;ls#-lsVX_jiP|0)x`Z}$v8>UG&GtAx>(Z7!lQr6* z+#W}rg0?IW(b19iK5;5&(}pEybaeftC+y}ud6sW~$DHLKXU4tnn0xH}C#j9Idu}*? z`Zj6JS=Ds!lQ*IsZJWAcs!CdFXN2#su<7%*F3HW!jP!qXZTc+NB{_zgks;f}rf*G6 z$+Vmq9TqojdVBAQv&WufH5YAc*8IQDEHZzpA?p#K?^H`%BT7;dOH!?pi&B9UgOP!u zsjh*Uu90Pkfq|8gxs|brwt=ygfkF8?;l(H#a`RI%(<*UmVEepU9;iVDWJ5tpnw3Xp zP-?MLeraAxW?s5eeg%W6xt@hl1(?(}&^GwvxYiY@UIeB-EVZaOGe3_Zz{O41P|rj` T#@(s{D9_;O>gTe~DWM4f-RbEw delta 3057 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 literal 6526 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 RThv&