diff --git a/Minkowski_sum_2/doc/Minkowski_sum_2/CGAL/Polygon_nop_decomposition_2.h b/Minkowski_sum_2/doc/Minkowski_sum_2/CGAL/Polygon_nop_decomposition_2.h new file mode 100644 index 00000000000..9f3773823e5 --- /dev/null +++ b/Minkowski_sum_2/doc/Minkowski_sum_2/CGAL/Polygon_nop_decomposition_2.h @@ -0,0 +1,24 @@ +namespace CGAL { + +/*! +\ingroup PkgMinkowskiSum2 + +\anchor mink_refnop_decomp + +The `Polygon_nop_decomposition_2` class implements a convex +decompistion of a polygon, which merely passes the input polygon into +the list of output convex polygons. It should be used when it is known +that the input polygon is convex to start with. + +\cgalModels `PolygonConvexDecomposition_2` + +*/ +template +class Polygon_nop_decomposition_2 { +public: + + /// @{ + /// @} + +}; /* end Polygon_nop_decomposition_2 */ +} /* end namespace CGAL */ diff --git a/Minkowski_sum_2/doc/Minkowski_sum_2/CGAL/minkowski_sum_2.h b/Minkowski_sum_2/doc/Minkowski_sum_2/CGAL/minkowski_sum_2.h index ee213fd944c..a0b5d14f579 100644 --- a/Minkowski_sum_2/doc/Minkowski_sum_2/CGAL/minkowski_sum_2.h +++ b/Minkowski_sum_2/doc/Minkowski_sum_2/CGAL/minkowski_sum_2.h @@ -64,19 +64,98 @@ minkowski_sum_by_full_convolution_2(const Polygon_2& P, \ingroup PkgMinkowskiSum2 Computes the Minkowski sum \f$ P \oplus Q\f$ of the two given polygons. -If the input polygons `P` and `Q` are not convex, the function -decomposes them into convex sub-polygons \f$ P_1, \ldots, P_k\f$ and -\f$ Q_1, \ldots, Q_{\ell}\f$ and computes the union of pairwise sub-sums -(namely \f$ \bigcup_{i,j}{(P_i \oplus Q_j)}\f$). -The decomposition is performed using the given decomposition method -`decomp`, which must be an instance of a class template that models -the concept `PolygonConvexDecomposition_2`. +The function decomposes the summand `P` into convex sub-polygons +\f$ P_1, \ldots, P_k\f$ using the given decomposition method `decomp_P`. +If the summand `P` is of type `Polygon_2`, then `decomp_P` must be an +instance of a class template that models the concept +`PolygonConvexDecomposition_2`. If `P` is of type `Polygon_with_holes_2`, +then `decomp_P` must be an instance of a class template that models the +concept `PolygonWithHolesConvexDecomposition_2`. +Similarly, the function decomposes the summand `Q` into convex sub-polygons +\f$ Q_1, \ldots, Q_k\f$ using the given decomposition method `decomp_Q`. +If the summand `Q` is of type `Polygon_2`, then `decomp_Q` must be an +instance of a class template that models the concept +`PolygonConvexDecomposition_2`. If `Q` is of type `Polygon_with_holes_2`, +then `decomp_Q` must be an instance of a class template that models the +concept `PolygonWithHolesConvexDecomposition_2`. +Then, the function computes the union of pairwise sub-sums (namely +\f$ \bigcup_{i,j}{(P_i \oplus Q_j)}\f$). */ -template +template Polygon_with_holes_2 minkowski_sum_2(const PolygonType1& P, const PolygonType2& Q, - const PolygonConvexDecomposition_2& decomp, + const PolygonConvexDecompositionP_2_& decomp_P, + const PolygonConvexDecompositionQ_2_& decomp_Q, + const Gps_segment_traits_2& traits = Gps_segment_traits_2()); + +/*! +\ingroup PkgMinkowskiSum2 + +Computes the Minkowski sum \f$ P \oplus Q\f$ of the two given polygons. +The function decomposes the summands `P` and `Q` into convex sub-polygons +\f$ P_1, \ldots, P_k\f$ and \f$ Q_1, \ldots, Q_{\ell}\f$, respectively. +Then, it computes the union of pairwise sub-sums (namely +\f$ \bigcup_{i,j}{(P_i \oplus Q_j)}\f$). The decomposition is performed +using the given decomposition method `decomp`. If both summands +\f$ P \oplus Q\f$ are of type `Polygon_2`, then `decomp` must be instance +of a class template that models the concept `PolygonConvexDecomposition_2`. +If both summands are of type `Polygon_with_holes_2`, then `decomp` must be +a model of the concept `PolygonWithHolesConvexDecomposition_2`. +*/ +template +Polygon_with_holes_2 +minkowski_sum_2(const PolygonType1& P, + const PolygonType2& Q, + const PolygonConvexDecomposition_2_& decomp, + const Gps_segment_traits_2& traits = Gps_segment_traits_2()); + +/*! +\ingroup PkgMinkowskiSum2 + +Computes the Minkowski sum \f$ P \oplus Q\f$ of the two given polygons +using the decomposition strategy. It decomposes the summands `P` and `Q` +into convex sub-polygons \f$ P_1, \ldots, P_k\f$ and +\f$ Q_1, \ldots, Q_{\ell}\f$, respectively. Then, it computes the union +of pairwise sub-sums (namely \f$ \bigcup_{i,j}{(P_i \oplus Q_j)}\f$). + +If the summand `P` is of type `Polygon_with_holes_2`, then the function +first applies the hole filteration on `P`. If the summand `P` remains a +polygon with holes, then the function decomposes the summand `P` using +the given decomposition method `with_holes_decomp`. If, however, `P` +turns into a polygon without holes, then the function decomposes the +summand `P` using the given decomposition method `no_holes_decomp`, +unless the result is a convex polygon, in which case the nop strategy is +applied; namely, an instance of the class template +`Polygon_nop_decomposition_2` is used. If `P` is a polygon without holes +to start with, then only convexity is checked (checking whether the +result is convex inccurs a small overhead though). Then depending on +the result either `no_holes_decomp` or the nop strategy is applied. +Similarly, if the summand `Q` is of type `Polygon_with_holes_2`, then +the function first applies the hole filteration on `Q`. If the summand +`Q` remains a polygon with holes, then the function decomposes the +summand `Q` using the given decomposition method `with_holes_decomp`. +If, however, `Q` turns into a polygon without holes, then the function +decomposes the summand `Q` using the given decomposition method +`no_holes_decomp`, unless the result is a convex polygon, in which case +the nop strategy is applied. If `Q` is a polygon without holes to start +with, then only convexity is checked and the decomposition strategy is +chosen accordingly. + +\tparam PolygonNoHolesConvexDecomposition_2_ a model of the concept `PolygonConvexDecomposition_2`. +\tparam PolygonWithHolesConvexDecomposition_2_ a model of the concept `PolygonWithHolesConvexDecomposition_2`. +*/ + template +Polygon_with_holes_2 +minkowski_sum_by_decomposition_2(const PolygonType1& P, + const PolygonType2& Q, + const PolygonNoHolesConvexDecomposition_2_& no_holes_decomp, + const PolygonWithHolesConvexDecomposition_2_& with_holes_decomp, const Gps_segment_traits_2& traits = Gps_segment_traits_2()); } /* namespace CGAL */ diff --git a/Minkowski_sum_2/doc/Minkowski_sum_2/Concepts/PolygonConvexDecomposition_2.h b/Minkowski_sum_2/doc/Minkowski_sum_2/Concepts/PolygonConvexDecomposition_2.h index cf0c7fbe55b..20b4cf23fb7 100644 --- a/Minkowski_sum_2/doc/Minkowski_sum_2/Concepts/PolygonConvexDecomposition_2.h +++ b/Minkowski_sum_2/doc/Minkowski_sum_2/Concepts/PolygonConvexDecomposition_2.h @@ -10,6 +10,7 @@ decomposing an input polygon \f$ P\f$ into a set of convex sub-polygons \cgalHasModel `CGAL::Optimal_convex_decomposition_2` \cgalHasModel `CGAL::Hertel_Mehlhorn_convex_decomposition_2` \cgalHasModel `CGAL::Greene_convex_decomposition_2` +\cgalHasModel `CGAL::Polygon_nop_decomposition_2` */ 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 92a2b087899..2962c11c312 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 @@ -54,24 +54,22 @@ The Minkowski sum can therefore be computed using an operation similar to the 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 -the ordered list of edges. +starting from the two bottommost vertices in \f$ P\f$ and in \f$ Q\f$ and +merging the ordered list of edges. \cgalFigureBegin{mink_figonecyc,ms_convex_polygon.png,ms_concave_polygon.png,ms_convolution.png} 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,135 @@ 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.
-\subsection mink_ssecsum_conv Computing Minkowski Sum using Convolutions +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. -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_by_reduced_convolution_2() `minkowski_sum_by_reduced_convolution_2(P, Q)`\endlink, -which applies the reduced convolution aforementioned. -Explicitly call the function \link minkowski_sum_by_full_convolution_2() +\subsection mink_ssec_hole_filter Filtering Out Holes + +If a hole in one polygon is relatively small compared to the other +polygon, the hole is irrelevant for the computation of +\f$P\oplus Q \f$ \cgalCite{bfhhm-epsph-15}; It implies that the hole +can be removed (that is, filled up) before the main computation starts. +Theoretically, we can always fill up all the holes of at least one +polygon, transforming it into a simple polygon, and still obtain +exactly the same Minkowski sum. Practically, we remove all holes in one +polygon whose bounding boxes are, in \f$x \f$- or \f$y \f$-direction, +smaller than, or as large as, the bounding box of the other polygon. +Obliterating holes in the input summands speeds up the computation of +Minkowski sums, regardless of the approach used to compute the +Minkowski sum. + +\subsection mink_ssec_conv Computing Minkowski Sum using Convolutions + +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_by_reduced_convolution_2() +`minkowski_sum_by_reduced_convolution_2(P, Q)`\endlink, which applies +the reduced convolution aforementioned method. Explicitly call +\link minkowski_sum_by_full_convolution_2() `minkowski_sum_by_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_by_full_convolution_2() +`minkowski_sum_by_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_by_reduced_convolution_2() +`minkowski_sum_by_reduced_convolution_2(P, Q)`\endlink (and by the +function \link minkowski_sum_2() `minkowski_sum_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 @@ -204,27 +245,48 @@ in both summands is large, the decomposition approach runs faster. In the following we describe how to employ the decomposition-based Minkowski sum procedure. -\subsection mink_ssecdecomp Decomposition Strategies +\subsection mink_ssec_decomp_strategies Decomposition Strategies 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 +\link minkowski_sum_2() +`minkowski_sum_2(P, Q, decompP, decompQ)`\endlink, 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_2` 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 +decomposes \f$Q \f$, you can omit the forth argument, and issue the call +\link minkowski_sum_2() `minkowski_sum_2(P, Q, decomp)`\endlink, +where `decomp` is an object that represents the common strategy. +The class template `Polygon_nop_decomposition_2`, which models the +concept `PolygonConvexDecomposition_2`, is a trivial convex +decomposition strategy referred to as the nop strategy; it merely +passes the input polygon to the next stage intact; use it in cases you +know that the corresponding input polygon is convex to start with. If +both \f$P \f$ and \f$Q \f$ are known to be convex, you can issue the call +\link minkowski_sum_2() `minkowski_sum_2(P, Q, nop)`\endlink, where `nop` +is an object that represents the nop strategy. The Minkowski-sum package includes four models of the concept -`PolygonConvexDecomposition_2` and two models of the refined concept +`PolygonConvexDecomposition_2` (besides the trivial model +`Polygon_nop_decomposition_2`) and two models of the refined concept `PolygonWithHolesConvexDecomposition_2` as described below. The first -three are class templates that wrap the decomposition functions included -in the \ref Chapter_2D_Polygon "Planar Polygon Partitioning" package. +three are class templates that wrap the corresponding decomposition +functions included in the +\ref Chapter_2D_Polygon "Planar Polygon Partitioning" package.
  • The `Optimal_convex_decomposition_2` class template uses @@ -274,12 +336,9 @@ 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 -`minkowski_sum_2(P, Q, decomp)` to compute the Minkowski sum of two -polygons with holes, \f$P \f$ and \f$Q \f$. +two types can be used to decompose a polygon with holes.
  • The `Polygon_vertical_decomposition_2` class template uses vertical decomposition to decompose the underlying arrangement; @@ -298,6 +357,29 @@ angle-bisector decomposition strategy. \cgalExample{Minkowski_sum_2/sum_by_decomposition.cpp} +\subsection mink_ssec_optimal_decomp Optimal Decomposition + +Decomposition methods that handle polygons with holes are typically +more costly than decomposition methods that handle only simple +polygons. The hole filtration (see \ref mink_ssec_hole_filter) is +applied before the actual construction starts (be it convolution +based or decomposition based). The filteration may result with a +polygon that does not have holes, or even a convex polygon, but this +is unkown at the time of the call. To this end, we introduce the +overloaded function template \link minkowski_sum_by_decomposition_2() +`minkowski_sum_by_decomposition_2(P, Q, no_holes_decomp, with_holes_decomp)`\endlink, +where `no_holes_decomp` and `with_holes_decomp` are objects that model +the concepts `PolygonConvexDecomposition_2` and +`PolygonWithHolesConvexDecomposition_2`, respectively. If after the +application of the hole filtration \f$P\f$ remains a polygon with holes, +then the strategy represented by the object `with_holes_decomp` is +applied to it. If, however, \f$P\f$ turns into a polygon without holes, +then the strategy represented by the object `no_holes_decomp` is applied +to it, unless the result is a convex polygon, in which case the nop +strategy is applied. If \f$P\f$ is a polygon without holes to start with, +then only convexity is checked. (Checking whether the result is convex +inccurs a small overhead though.) The same holds for \f$Q\f$. + \section mink_secoffset Offsetting a Polygon The operation of computing the Minkowski sum \f$ P \oplus B_r\f$ of a @@ -354,7 +436,7 @@ sub-polygon, and finally calculating the union of these offsets sub-polygons; see \cgalFigureRef{mink_figpgn_offset} (b). However, as with the case of the Minkowski sum of a pair of polygons, it is also more efficient to compute the convolution cycle of the polygon and the -disc \f$ B_r\f$, \cgalFootnote{As the disc is convex, it is guaranteed +disc \f$ B_r\f$,\cgalFootnote{As the disc is convex, it is guaranteed that the convolution curve comprises a single cycle.} which can be constructed by applying the process described in the previous paragraph for convex polygons: The only difference is that a circular arc @@ -365,7 +447,7 @@ the last step consists of computing the winding numbers of the faces of the arrangement induced by the convolution cycle and discarding the faces with zero winding numbers. -\subsection mink_ssecapprox_offset Approximating the Offset with a Guaranteed Error Bound +\subsection mink_ssec_approx_offset Approximating the Offset with a Guaranteed Error Bound Let \f$ P \f$ be a counterclockwise-oriented simple polygon all vertices of which \f$ p_0, \ldots, p_{n-1} \f$ have rational coordinates, @@ -395,7 +477,7 @@ is supported by the line \f$ Ax + By + C' = 0 \f$, where rational number. Therefore, the line segments that compose the offset boundaries cannot be represented as segments of lines with rational coefficients. -In Section \ref mink_ssecexact_offset we use the line-pair representation +In Section \ref mink_ssec_exact_offset we use the line-pair representation to construct the offset polygonin an exact manner using the traits class for conic arcs.
@@ -470,7 +552,7 @@ the header file `bops_circular.h`, which defines the polygon types. \cgalExample{Minkowski_sum_2/approx_offset.cpp} -\subsection mink_ssecexact_offset Computing the Exact Offset +\subsection mink_ssec_exact_offset Computing the Exact Offset As mentioned in the previous section, it is possible to represent offset polygons in an exact manner if the edges of the polygons are @@ -514,7 +596,7 @@ handles polygons with holes, such as the `Polygon_vertical_decomposition_2` class template. \cgalAdvancedEnd -\subsection mink_ssecinner_offset Computing Inner Offsets +\subsection mink_ssec_inner_offset Computing Inner Offsets An operation closely related to the (outer) offset computation, is computing the inner offset of a polygon, or insetting it diff --git a/Minkowski_sum_2/doc/Minkowski_sum_2/PackageDescription.txt b/Minkowski_sum_2/doc/Minkowski_sum_2/PackageDescription.txt index d3bf5dc3821..b203702bf79 100644 --- a/Minkowski_sum_2/doc/Minkowski_sum_2/PackageDescription.txt +++ b/Minkowski_sum_2/doc/Minkowski_sum_2/PackageDescription.txt @@ -36,6 +36,9 @@ bounds, in order to speed up the computation time. ## Functions ## - `CGAL::minkowski_sum_2()` +- `CGAL::minkowski_sum_by_decomposition_2()` +- `CGAL::minkowski_sum_full_convolution_2()` +- `CGAL::minkowski_sum_reduced_convolution_2()` - `CGAL::approximated_offset_2()` - `CGAL::approximated_inset_2()` - `CGAL::offset_polygon_2()` @@ -52,5 +55,6 @@ bounds, in order to speed up the computation time. - `CGAL::Greene_convex_decomposition_2` - `CGAL::Polygon_vertical_decomposition_2` - `CGAL::Polygon_triangulation_decomposition_2` +- `CGAL::Polygon_nop_decomposition_2` */ 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 5511967d444..d92b6d433db 100644 Binary files a/Minkowski_sum_2/doc/Minkowski_sum_2/fig/ms_concave_polygon.png and b/Minkowski_sum_2/doc/Minkowski_sum_2/fig/ms_concave_polygon.png differ 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 a5843158939..9d1fc365ff0 100644 Binary files a/Minkowski_sum_2/doc/Minkowski_sum_2/fig/ms_convex_polygon.png and b/Minkowski_sum_2/doc/Minkowski_sum_2/fig/ms_convex_polygon.png differ diff --git a/Minkowski_sum_2/doc/Minkowski_sum_2/fig/ms_convolution.png b/Minkowski_sum_2/doc/Minkowski_sum_2/fig/ms_convolution.png index 51459952f49..b16d5076e88 100644 Binary files a/Minkowski_sum_2/doc/Minkowski_sum_2/fig/ms_convolution.png and b/Minkowski_sum_2/doc/Minkowski_sum_2/fig/ms_convolution.png differ diff --git a/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Minkowski_sum_decomp_2.h b/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Minkowski_sum_decomp_2.h index 5f03d75ef2b..f917b0c8621 100644 --- a/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Minkowski_sum_decomp_2.h +++ b/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Minkowski_sum_decomp_2.h @@ -28,20 +28,22 @@ namespace CGAL { /*! \class - * A class for computing the Minkowski sum of two simple polygons based on - * their decomposition two convex sub-polygons, taking the pairwise sums and + * A class for computing the Minkowski sum of two polygons based on their + * decomposition to convex sub-polygons, taking the pairwise sums and * computing the union of the sub-sums. */ -template +template class Minkowski_sum_by_decomposition_2 { public: - typedef DecompStrategy_ Decomposition_strategy; - typedef Container_ Container; + typedef DecompStrategy1_ Decomposition_strategy1; + typedef DecompStrategy2_ Decomposition_strategy2; + typedef Container_ Container; - typedef typename Decomposition_strategy::Polygon_2 Polygon_2; + typedef typename Decomposition_strategy1::Polygon_2 Polygon_2; - typedef typename Decomposition_strategy::Kernel Kernel; + typedef typename Decomposition_strategy1::Kernel Kernel; typedef CGAL::Arr_segment_traits_2 Arr_segment_traits; typedef CGAL::Gps_segment_traits_2 Traits_2; @@ -73,8 +75,10 @@ private: Polygon_with_holes_list; // Data members: - const Decomposition_strategy* m_decomposition_strategy; - bool m_own_strategy; // inidicates whether the stategy should be freed up. + const Decomposition_strategy1* m_decomposition_strategy1; + const Decomposition_strategy2* m_decomposition_strategy2; + bool m_own_strategy1; // inidicates whether the stategy should be freed up. + bool m_own_strategy2; // inidicates whether the stategy should be freed up. const Traits_2* m_traits; bool m_own_traits; // inidicates whether the kernel should be freed up. @@ -90,33 +94,43 @@ private: public: //! Default constructor. Minkowski_sum_by_decomposition_2() : - m_decomposition_strategy(NULL), - m_own_strategy(false), + m_decomposition_strategy1(NULL), + m_decomposition_strategy2(NULL), + m_own_strategy1(false), + m_own_strategy2(false), m_traits(NULL), m_own_traits(false) { init(); } //! Constructor. - Minkowski_sum_by_decomposition_2(const Decomposition_strategy& strategy, + Minkowski_sum_by_decomposition_2(const Decomposition_strategy1& strategy1, + const Decomposition_strategy2& strategy2, const Traits_2& traits) : - m_decomposition_strategy(&strategy), - m_own_strategy(false), + m_decomposition_strategy1(&strategy1), + m_decomposition_strategy2(&strategy2), + m_own_strategy1(false), + m_own_strategy2(false), m_traits(&traits), m_own_traits(false) { init(); } //! Constructor. - Minkowski_sum_by_decomposition_2(const Decomposition_strategy& strategy) : - m_decomposition_strategy(&strategy), - m_own_strategy(false), + Minkowski_sum_by_decomposition_2(const Decomposition_strategy1& strategy1, + const Decomposition_strategy2& strategy2) : + m_decomposition_strategy1(&strategy1), + m_decomposition_strategy2(&strategy2), + m_own_strategy1(false), + m_own_strategy2(false), m_traits(NULL), m_own_traits(false) { init(); } //! Constructor. Minkowski_sum_by_decomposition_2(const Traits_2& traits) : - m_decomposition_strategy(NULL), - m_own_strategy(false), + m_decomposition_strategy1(NULL), + m_decomposition_strategy2(NULL), + m_own_strategy1(false), + m_own_strategy2(false), m_traits(&traits), m_own_traits(false) { init(); } @@ -132,12 +146,20 @@ public: m_own_traits = false; } - if (m_own_strategy) { - if (m_decomposition_strategy != NULL) { - delete m_decomposition_strategy; - m_decomposition_strategy = NULL; + if (m_own_strategy1) { + if (m_decomposition_strategy1 != NULL) { + delete m_decomposition_strategy1; + m_decomposition_strategy1 = NULL; } - m_own_strategy = false; + m_own_strategy1 = false; + } + + if (m_own_strategy2) { + if (m_decomposition_strategy2 != NULL) { + delete m_decomposition_strategy2; + m_decomposition_strategy2 = NULL; + } + m_own_strategy2 = false; } } @@ -150,10 +172,15 @@ public: m_own_traits = true; } // Allocate the strategy if not provided. - if (m_decomposition_strategy == NULL) { - m_decomposition_strategy = new Decomposition_strategy; - m_own_strategy = true; + if (m_decomposition_strategy1 == NULL) { + m_decomposition_strategy1 = new Decomposition_strategy1; + m_own_strategy1 = true; } + if (m_decomposition_strategy2 == NULL) { + m_decomposition_strategy2 = new Decomposition_strategy2; + m_own_strategy2 = true; + } + // Obtain kernel functors. const Kernel* kernel = m_traits; f_compare_angle = kernel->compare_angle_with_x_axis_2_object(); @@ -175,8 +202,11 @@ public: * Obtain the decomposition strategy * \return the decomposition strategy */ - const Decomposition_strategy* decomposition_strategy() const - { return m_decomposition_strategy; } + const Decomposition_strategy1* decomposition_strategy1() const + { return m_decomposition_strategy1; } + + const Decomposition_strategy2* decomposition_strategy2() const + { return m_decomposition_strategy2; } /*! * Compute the Minkowski sum of two simple polygons. @@ -195,8 +225,8 @@ public: Polygons_list sub_pgns1; Polygons_list sub_pgns2; - (*m_decomposition_strategy)(pgn1, std::back_inserter(sub_pgns1)); - (*m_decomposition_strategy)(pgn2, std::back_inserter(sub_pgns2)); + (*m_decomposition_strategy1)(pgn1, std::back_inserter(sub_pgns1)); + (*m_decomposition_strategy2)(pgn2, std::back_inserter(sub_pgns2)); return operator()(sub_pgns1.begin(), sub_pgns1.end(), sub_pgns2.begin(), sub_pgns2.end()); @@ -217,8 +247,8 @@ public: Polygons_list sub_pgns1; Polygons_list sub_pgns2; - (*m_decomposition_strategy)(pgn1, std::back_inserter(sub_pgns1)); - (*m_decomposition_strategy)(pgn2, std::back_inserter(sub_pgns2)); + (*m_decomposition_strategy1)(pgn1, std::back_inserter(sub_pgns1)); + (*m_decomposition_strategy2)(pgn2, std::back_inserter(sub_pgns2)); return operator()(sub_pgns1.begin(), sub_pgns1.end(), sub_pgns2.begin(), sub_pgns2.end()); @@ -240,8 +270,8 @@ public: Polygons_list sub_pgns1; Polygons_list sub_pgns2; - (*m_decomposition_strategy)(pgn1, std::back_inserter(sub_pgns1)); - (*m_decomposition_strategy)(pgn2, std::back_inserter(sub_pgns2)); + (*m_decomposition_strategy1)(pgn1, std::back_inserter(sub_pgns1)); + (*m_decomposition_strategy2)(pgn2, std::back_inserter(sub_pgns2)); return operator()(sub_pgns1.begin(), sub_pgns1.end(), sub_pgns2.begin(), sub_pgns2.end()); diff --git a/Minkowski_sum_2/include/CGAL/Polygon_nop_decomposition_2.h b/Minkowski_sum_2/include/CGAL/Polygon_nop_decomposition_2.h new file mode 100644 index 00000000000..2e2dc6d91e8 --- /dev/null +++ b/Minkowski_sum_2/include/CGAL/Polygon_nop_decomposition_2.h @@ -0,0 +1,43 @@ +// Copyright (c) 2013 Tel-Aviv University (Israel). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Author(s) : Efi Fogel + +#ifndef CGAL_POLYGON_NOP_DECOMPOSITION_2_H +#define CGAL_POLYGON_NOP_DECOMPOSITION_2_H + +#include + +namespace CGAL { + +/*! \class + * Nop decomposition strategy. + * Used for polygons that are already convex. + */ +template > +class Polygon_nop_decomposition_2 { +public: + typedef Kernel_ Kernel; + typedef Container_ Container; + typedef CGAL::Polygon_2 Polygon_2; + + template + OutputIterator_ operator()(const Polygon_2& pgn, OutputIterator_ oi) const + { *oi++ = pgn; return oi; } +}; + +} //namespace CGAL + +#endif diff --git a/Minkowski_sum_2/include/CGAL/minkowski_sum_2.h b/Minkowski_sum_2/include/CGAL/minkowski_sum_2.h index 5e4641538f1..afb99198e11 100644 --- a/Minkowski_sum_2/include/CGAL/minkowski_sum_2.h +++ b/Minkowski_sum_2/include/CGAL/minkowski_sum_2.h @@ -20,11 +20,12 @@ #include #include - #include #include #include #include +#include + #include namespace CGAL { @@ -243,7 +244,7 @@ minkowski_sum_2(const Polygon_2& pgn1, const Polygon_with_holes_2& pgn2) { return minkowski_sum_by_reduced_convolution_2(pgn1, pgn2); } - /*! +/*! * Compute the Minkowski sum of a simple polygon and a polygon with holes * using the convolution method. This function defaults to calling the reduced * convolution method, as it is more efficient in most cases. @@ -263,7 +264,11 @@ minkowski_sum_2(const Polygon_with_holes_2& pgn1, { return minkowski_sum_by_reduced_convolution_2(pgn1, pgn2); } /*! - * Compute the Minkowski sum of two simple polygons by decomposing each + * \defgroup Minkowski sum by decomposition + * @{ + */ + +/*! Compute the Minkowski sum of two simple polygons by decomposing each * polygon to convex sub-polygons and computing the union of the pairwise * Minkowski sums of the sub-polygons. * Note that as the input polygons may not be convex, their Minkowski sum may @@ -275,19 +280,22 @@ minkowski_sum_2(const Polygon_with_holes_2& pgn1, * \return The resulting polygon with holes, representing the sum. */ template + typename DecompositionStrategy1_, typename DecompositionStrategy2_> Polygon_with_holes_2 minkowski_sum_2(const Polygon_2& pgn1, const Polygon_2& pgn2, - const DecompositionStrategy_& decomposition_strategy) + const DecompositionStrategy1_& decomposition_strategy1, + const DecompositionStrategy2_& decomposition_strategy2) { - typename Minkowski_sum_by_decomposition_2::Traits_2 traits; - return minkowski_sum_2(pgn1, pgn2, decomposition_strategy, traits); + return minkowski_sum_2(pgn1, pgn2, + decomposition_strategy1, decomposition_strategy2, + traits); } -/*! - * Compute the Minkowski sum of two simple polygons by decomposing each +/*! Compute the Minkowski sum of two simple polygons by decomposing each * polygon to convex sub-polygons and computing the union of the pairwise * Minkowski sums of the sub-polygons. * Note that as the input polygons may not be convex, their Minkowski sum may @@ -300,20 +308,24 @@ minkowski_sum_2(const Polygon_2& pgn1, * \return The resulting polygon with holes, representing the sum. */ template + typename DecompositionStrategy1_, typename DecompositionStrategy2_> Polygon_with_holes_2 minkowski_sum_2(const Polygon_2& pgn1, const Polygon_2& pgn2, - const DecompositionStrategy_& decomposition_strategy, + const DecompositionStrategy1_& decomposition_strategy1, + const DecompositionStrategy2_& decomposition_strategy2, const typename - Minkowski_sum_by_decomposition_2::Traits_2& traits) { typedef Container_ Container; - typedef DecompositionStrategy_ Decomposition_strategy; + typedef DecompositionStrategy1_ Decomposition_strategy1; + typedef DecompositionStrategy2_ Decomposition_strategy2; - Minkowski_sum_by_decomposition_2 - mink_sum(decomposition_strategy, traits); + Minkowski_sum_by_decomposition_2 + mink_sum(decomposition_strategy1, decomposition_strategy2, traits); return mink_sum(pgn1, pgn2); } @@ -328,19 +340,22 @@ minkowski_sum_2(const Polygon_2& pgn1, * \return The resulting polygon with holes, representing the sum. */ template + typename DecompositionStrategy1_, typename DecompositionStrategy2_> Polygon_with_holes_2 minkowski_sum_2(const Polygon_with_holes_2& pgn1, const Polygon_with_holes_2& pgn2, - const DecompositionStrategy_& decomposition_strategy) + const DecompositionStrategy1_& decomposition_strategy1, + const DecompositionStrategy2_& decomposition_strategy2) { - typename Minkowski_sum_by_decomposition_2::Traits_2 traits; - return minkowski_sum_2(pgn1, pgn2, decomposition_strategy, traits); + return minkowski_sum_2(pgn1, pgn2, + decomposition_strategy1, decomposition_strategy2, + traits); } -/*! - * Compute the Minkowski sum of two polygon with holes by decomposing each +/*! Compute the Minkowski sum of two polygon with holes by decomposing each * polygon to convex sub-polygons and computing the union of the pairwise * Minkowski sums of the sub-polygons. * The result is also represented as a polygon with holes. @@ -351,21 +366,25 @@ minkowski_sum_2(const Polygon_with_holes_2& pgn1, * \return The resulting polygon with holes, representing the sum. */ template + typename DecompositionStrategy1_, typename DecompositionStrategy2_> Polygon_with_holes_2 minkowski_sum_2(const Polygon_with_holes_2& pgn1, const Polygon_with_holes_2& pgn2, - const DecompositionStrategy_& decomposition_strategy, + const DecompositionStrategy1_& decomposition_strategy1, + const DecompositionStrategy2_& decomposition_strategy2, const typename - Minkowski_sum_by_decomposition_2::Traits_2& traits) { typedef Kernel_ Kernel; typedef Container_ Container; - typedef DecompositionStrategy_ Decomposition_strategy; + typedef DecompositionStrategy1_ Decomposition_strategy1; + typedef DecompositionStrategy2_ Decomposition_strategy2; - Minkowski_sum_by_decomposition_2 - mink_sum(decomposition_strategy, traits); + Minkowski_sum_by_decomposition_2 + mink_sum(decomposition_strategy1, decomposition_strategy2, traits); Hole_filter_2 hole_filter; Polygon_with_holes_2 filtered_pgn1; Polygon_with_holes_2 filtered_pgn2; @@ -374,8 +393,7 @@ minkowski_sum_2(const Polygon_with_holes_2& pgn1, return mink_sum(filtered_pgn1, filtered_pgn2); } -/*! - * Compute the Minkowski sum of a simple polygon and a polygon with holes +/*! Compute the Minkowski sum of a simple polygon and a polygon with holes * by decomposing each polygon to convex sub-polygons and computing the union * of the pairwise Minkowski sums of the sub-polygons. The result is also * represented as a polygon with holes. @@ -385,19 +403,22 @@ minkowski_sum_2(const Polygon_with_holes_2& pgn1, * \return The resulting polygon with holes, representing the sum. */ template + typename DecompositionStrategy1_, typename DecompositionStrategy2_> Polygon_with_holes_2 minkowski_sum_2(const Polygon_2& pgn1, const Polygon_with_holes_2& pgn2, - const DecompositionStrategy_& decomposition_strategy) + const DecompositionStrategy1_& decomposition_strategy1, + const DecompositionStrategy2_& decomposition_strategy2) { - typename Minkowski_sum_by_decomposition_2::Traits_2 traits; - return minkowski_sum_2(pgn1, pgn2, decomposition_strategy, traits); + return minkowski_sum_2(pgn1, pgn2, + decomposition_strategy1, decomposition_strategy2, + traits); } -/*! - * Compute the Minkowski sum of a simple polygon and a polygon with holes +/*! Compute the Minkowski sum of a simple polygon and a polygon with holes * by decomposing each polygon to convex sub-polygons and computing the union * of the pairwise Minkowski sums of the sub-polygons. The result is also * represented as a polygon with holes. @@ -408,29 +429,32 @@ minkowski_sum_2(const Polygon_2& pgn1, * \return The resulting polygon with holes, representing the sum. */ template + typename DecompositionStrategy1_, typename DecompositionStrategy2_> Polygon_with_holes_2 minkowski_sum_2(const Polygon_2& pgn1, const Polygon_with_holes_2& pgn2, - const DecompositionStrategy_& decomposition_strategy, + const DecompositionStrategy1_& decomposition_strategy1, + const DecompositionStrategy2_& decomposition_strategy2, const typename - Minkowski_sum_by_decomposition_2::Traits_2& traits) { typedef Kernel_ Kernel; typedef Container_ Container; - typedef DecompositionStrategy_ Decomposition_strategy; + typedef DecompositionStrategy1_ Decomposition_strategy1; + typedef DecompositionStrategy2_ Decomposition_strategy2; - Minkowski_sum_by_decomposition_2 - mink_sum(decomposition_strategy, traits); + Minkowski_sum_by_decomposition_2 + mink_sum(decomposition_strategy1, decomposition_strategy2, traits); Hole_filter_2 hole_filter; Polygon_with_holes_2 filtered_pgn2; hole_filter(pgn2, pgn1, filtered_pgn2); return mink_sum(pgn1, filtered_pgn2); } -/*! - * Compute the Minkowski sum of a simple polygon and a polygon with holes +/*! Compute the Minkowski sum of a simple polygon and a polygon with holes * by decomposing each polygon to convex sub-polygons and computing the union * of the pairwise Minkowski sums of the sub-polygons. The result is also * represented as a polygon with holes. @@ -440,19 +464,22 @@ minkowski_sum_2(const Polygon_2& pgn1, * \return The resulting polygon with holes, representing the sum. */ template + typename DecompositionStrategy1_, typename DecompositionStrategy2_> Polygon_with_holes_2 minkowski_sum_2(const Polygon_with_holes_2& pgn1, const Polygon_2& pgn2, - const DecompositionStrategy_& decomposition_strategy) + const DecompositionStrategy1_& decomposition_strategy1, + const DecompositionStrategy2_& decomposition_strategy2) { - typename Minkowski_sum_by_decomposition_2::Traits_2 traits; - return minkowski_sum_2(pgn1, pgn2, decomposition_strategy, traits); + return minkowski_sum_2(pgn1, pgn2, + decomposition_strategy1, decomposition_strategy2, + traits); } -/*! - * Compute the Minkowski sum of a simple polygon and a polygon with holes +/*! Compute the Minkowski sum of a simple polygon and a polygon with holes * by decomposing each polygon to convex sub-polygons and computing the union * of the pairwise Minkowski sums of the sub-polygons. The result is also * represented as a polygon with holes. @@ -463,15 +490,632 @@ minkowski_sum_2(const Polygon_with_holes_2& pgn1, * \return The resulting polygon with holes, representing the sum. */ template + typename DecompositionStrategy1_, typename DecompositionStrategy2_> Polygon_with_holes_2 minkowski_sum_2(const Polygon_with_holes_2& pgn1, const Polygon_2& pgn2, - const DecompositionStrategy_& decomposition_strategy, + const DecompositionStrategy1_& decomposition_strategy1, + const DecompositionStrategy2_& decomposition_strategy2, const typename - Minkowski_sum_by_decomposition_2::Traits_2& traits) -{ return minkowski_sum_2(pgn2, pgn1, decomposition_strategy, traits); } +{ + return minkowski_sum_2(pgn2, pgn1, + decomposition_strategy2, decomposition_strategy1, + traits); +} + +/*! Compute the Minkowski sum of two simple polygons by decomposing each + * polygon to convex sub-polygons and computing the union of the pairwise + * Minkowski sums of the sub-polygons. + * Note that as the input polygons may not be convex, their Minkowski sum may + * not be a simple polygon. The result is therefore represented as a polygon + * with holes. + * \param[in] pgn1 The first polygon. + * \param[in] pgn2 The second polygon. + * \param[in] decomposition_strategy A functor for decomposing polygons. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_2(const Polygon_2& pgn1, + const Polygon_2& pgn2, + const DecompositionStrategy1_& decomposition_strategy1) +{ + typename Minkowski_sum_by_decomposition_2::Traits_2 traits; + return minkowski_sum_2(pgn1, pgn2, + decomposition_strategy1, decomposition_strategy1, + traits); +} + +/*! Compute the Minkowski sum of two simple polygons by decomposing each + * polygon to convex sub-polygons and computing the union of the pairwise + * Minkowski sums of the sub-polygons. + * Note that as the input polygons may not be convex, their Minkowski sum may + * not be a simple polygon. The result is therefore represented as a polygon + * with holes. + * \param[in] pgn1 The first polygon. + * \param[in] pgn2 The second polygon. + * \param[in] decomposition_strategy A functor for decomposing polygons. + * \param[in] traits The traits. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_2(const Polygon_2& pgn1, + const Polygon_2& pgn2, + const DecompositionStrategy1_& decomposition_strategy1, + const typename + Minkowski_sum_by_decomposition_2::Traits_2& traits) +{ + typedef Container_ Container; + typedef DecompositionStrategy1_ Decomposition_strategy1; + + Minkowski_sum_by_decomposition_2 + mink_sum(decomposition_strategy1, decomposition_strategy1, traits); + return mink_sum(pgn1, pgn2); +} + +/*! + * Compute the Minkowski sum of two polygon with holes by decomposing each + * polygon to convex sub-polygons and computing the union of the pairwise + * Minkowski sums of the sub-polygons. + * The result is also represented as a polygon with holes. + * \param[in] pgn1 The first polygon. + * \param[in] pgn2 The second polygon. + * \param[in] decomposition_strategy A functor for decomposing polygons. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_2(const Polygon_with_holes_2& pgn1, + const Polygon_with_holes_2& pgn2, + const DecompositionStrategy1_& decomposition_strategy1) +{ + typename Minkowski_sum_by_decomposition_2::Traits_2 traits; + return minkowski_sum_2(pgn1, pgn2, + decomposition_strategy1, decomposition_strategy1, + traits); +} + +/*! Compute the Minkowski sum of two polygon with holes by decomposing each + * polygon to convex sub-polygons and computing the union of the pairwise + * Minkowski sums of the sub-polygons. + * The result is also represented as a polygon with holes. + * \param[in] pgn1 The first polygon. + * \param[in] pgn2 The second polygon. + * \param[in] decomposition_strategy A functor for decomposing polygons. + * \param[in] traits The traits. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_2(const Polygon_with_holes_2& pgn1, + const Polygon_with_holes_2& pgn2, + const DecompositionStrategy1_& decomposition_strategy1, + const typename + Minkowski_sum_by_decomposition_2::Traits_2& traits) +{ + typedef Kernel_ Kernel; + typedef Container_ Container; + typedef DecompositionStrategy1_ Decomposition_strategy1; + + Minkowski_sum_by_decomposition_2 + mink_sum(decomposition_strategy1, decomposition_strategy1, traits); + Hole_filter_2 hole_filter; + Polygon_with_holes_2 filtered_pgn1; + Polygon_with_holes_2 filtered_pgn2; + hole_filter(pgn1, pgn2, filtered_pgn1); + hole_filter(pgn2, pgn1, filtered_pgn2); + return mink_sum(filtered_pgn1, filtered_pgn2); +} + +/*! Compute the Minkowski sum of a simple polygon and a polygon with holes + * by decomposing each polygon to convex sub-polygons and computing the union + * of the pairwise Minkowski sums of the sub-polygons. The result is also + * represented as a polygon with holes. + * \param[in] pgn1 The first polygon. + * \param[in] pgn2 The second polygon. + * \param[in] decomposition_strategy A functor for decomposing polygons. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_2(const Polygon_2& pgn1, + const Polygon_with_holes_2& pgn2, + const DecompositionStrategy1_& decomposition_strategy1) +{ + typename Minkowski_sum_by_decomposition_2::Traits_2 traits; + return minkowski_sum_2(pgn1, pgn2, + decomposition_strategy1, decomposition_strategy1, + traits); +} + +/*! Compute the Minkowski sum of a simple polygon and a polygon with holes + * by decomposing each polygon to convex sub-polygons and computing the union + * of the pairwise Minkowski sums of the sub-polygons. The result is also + * represented as a polygon with holes. + * \param[in] pgn1 The simple polygon. + * \param[in] pgn2 The polygon with holes. + * \param[in] decomposition_strategy A functor for decomposing polygons. + * \param[in] traits The traits. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_2(const Polygon_2& pgn1, + const Polygon_with_holes_2& pgn2, + const DecompositionStrategy1_& decomposition_strategy1, + const typename + Minkowski_sum_by_decomposition_2::Traits_2& traits) +{ + typedef Kernel_ Kernel; + typedef Container_ Container; + typedef DecompositionStrategy1_ Decomposition_strategy1; + + Minkowski_sum_by_decomposition_2 + mink_sum(decomposition_strategy1, decomposition_strategy1, traits); + Hole_filter_2 hole_filter; + Polygon_with_holes_2 filtered_pgn2; + hole_filter(pgn2, pgn1, filtered_pgn2); + return mink_sum(pgn1, filtered_pgn2); +} + +/*! Compute the Minkowski sum of a simple polygon and a polygon with holes + * by decomposing each polygon to convex sub-polygons and computing the union + * of the pairwise Minkowski sums of the sub-polygons. The result is also + * represented as a polygon with holes. + * \param[in] pgn1 The second polygon. + * \param[in] pgn2 The first polygon. + * \param[in] decomposition_strategy A functor for decomposing polygons. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_2(const Polygon_with_holes_2& pgn1, + const Polygon_2& pgn2, + const DecompositionStrategy1_& decomposition_strategy1) +{ + typename Minkowski_sum_by_decomposition_2::Traits_2 traits; + return minkowski_sum_2(pgn1, pgn2, + decomposition_strategy1, decomposition_strategy1, + traits); +} + +/*! Compute the Minkowski sum of a simple polygon and a polygon with holes + * by decomposing each polygon to convex sub-polygons and computing the union + * of the pairwise Minkowski sums of the sub-polygons. The result is also + * represented as a polygon with holes. + * \param[in] pgn1 The polygon with holes. + * \param[in] pgn2 The simple polygon. + * \param[in] decomposition_strategy A functor for decomposing polygons. + * \param[in] traits The traits. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_2(const Polygon_with_holes_2& pgn1, + const Polygon_2& pgn2, + const DecompositionStrategy1_& decomposition_strategy1, + const typename + Minkowski_sum_by_decomposition_2::Traits_2& traits) +{ + return minkowski_sum_2(pgn2, pgn1, + decomposition_strategy1, decomposition_strategy1, + traits); +} + +/*! Compute the Minkowski sum of two simple polygons by decomposing each + * polygon to convex sub-polygons and computing the union of the pairwise + * Minkowski sums of the sub-polygons. + * Note that as the input polygons may not be convex, their Minkowski sum may + * not be a simple polygon. The result is therefore represented as a polygon + * with holes. + * \param[in] pgn1 The first polygon. + * \param[in] pgn2 The second polygon. + * \param[in] decomposition_strategy A functor for decomposing polygons. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_by_decomposition_2(const Polygon_2& pgn1, + const Polygon_2& pgn2, + const Decomposition_& decomp) +{ + typename Minkowski_sum_by_decomposition_2::Traits_2 traits; + return minkowski_sum_by_decomposition_2(pgn1, pgn2, decomp, traits); +} + +/*! Compute the Minkowski sum of two simple polygons by decomposing each + * polygon to convex sub-polygons and computing the union of the pairwise + * Minkowski sums of the sub-polygons. + * Note that as the input polygons may not be convex, their Minkowski sum may + * not be a simple polygon. The result is therefore represented as a polygon + * with holes. + * \param[in] pgn1 The first polygon. + * \param[in] pgn2 The second polygon. + * \param[in] decomposition A functor for decomposing polygons. + * \param[in] traits The traits. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_by_decomposition_2 +(const Polygon_2& pgn1, + const Polygon_2& pgn2, + const Decomposition_& decomp, + const typename Minkowski_sum_by_decomposition_2::Traits_2& traits) +{ + typedef Kernel_ Kernel; + typedef Container_ Container; + typedef Decomposition_ Decomposition; + typedef Polygon_nop_decomposition_2 Nop_decomposition; + + if (pgn1.is_convex()) { + Nop_decomposition decomp_nop; + if (pgn2.is_convex()) { + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_nop, decomp_nop, traits); + return mink_sum(pgn1, pgn2); + } + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_nop, decomp, traits); + return mink_sum(pgn1, pgn2); + } + + if (pgn2.is_convex()) { + Nop_decomposition decomp_nop; + Minkowski_sum_by_decomposition_2 + mink_sum(decomp, decomp_nop, traits); + return mink_sum(pgn1, pgn2); + } + + Minkowski_sum_by_decomposition_2 + mink_sum(decomp, decomp, traits); + return mink_sum(pgn1, pgn2); +} + +/*! Compute the Minkowski sum of two polygon with holes by decomposing each + * polygon to convex sub-polygons and computing the union of the pairwise + * Minkowski sums of the sub-polygons. + * The result is also represented as a polygon with holes. + * \param[in] pgn1 The first polygon. + * \param[in] pgn2 The second polygon. + * \param[in] decomposition A functor for decomposing polygons. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_by_decomposition_2 +(const Polygon_with_holes_2& pgn1, + const Polygon_with_holes_2& pgn2, + const NoHolesDecomposition_& decomp_no_holes, + const WithHolesDecomposition_& decomp_with_holes) +{ + typename Minkowski_sum_by_decomposition_2::Traits_2 traits; + return minkowski_sum_by_decomposition_2(pgn1, pgn2, + decomp_no_holes, decomp_with_holes, + traits); +} + +/*! Compute the Minkowski sum of two polygon with holes by decomposing each + * polygon to convex sub-polygons and computing the union of the pairwise + * Minkowski sums of the sub-polygons. + * The result is also represented as a polygon with holes. + * \param[in] pgn1 The first polygon. + * \param[in] pgn2 The second polygon. + * \param[in] decomposition A functor for decomposing polygons. + * \param[in] traits The traits. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_by_decomposition_2 +(const Polygon_with_holes_2& pgn1, + const Polygon_with_holes_2& pgn2, + const NoHolesDecomposition_& decomp_no_holes, + const WithHolesDecomposition_& decomp_with_holes, + const typename Minkowski_sum_by_decomposition_2::Traits_2& traits) +{ + typedef Kernel_ Kernel; + typedef Container_ Container; + typedef NoHolesDecomposition_ No_holes_decomposition; + typedef WithHolesDecomposition_ With_holes_decomposition; + typedef Polygon_nop_decomposition_2 Nop_decomposition; + + Hole_filter_2 hole_filter; + Polygon_with_holes_2 filtered_pgn1; + Polygon_with_holes_2 filtered_pgn2; + hole_filter(pgn1, pgn2, filtered_pgn1); + hole_filter(pgn2, pgn1, filtered_pgn2); + + if (0 == filtered_pgn1.number_of_holes()) { + const Polygon_2& pnh1 = filtered_pgn1.outer_boundary(); + if (pnh1.is_convex()) { + // pnh1 is convex + Nop_decomposition decomp_nop; + if (0 == filtered_pgn2.number_of_holes()) { + const Polygon_2& pnh2 = + filtered_pgn2.outer_boundary(); + if (pnh2.is_convex()) { + // pnh2 is convex + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_nop, decomp_nop, traits); + return mink_sum(pnh1, pnh2); + } + // pnh2 is concave + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_nop, decomp_no_holes, traits); + return mink_sum(pnh1, pnh2); + } + // pnh2 has holes + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_nop, decomp_with_holes, traits); + return mink_sum(pnh1, filtered_pgn2); + } + // pnh1 is concave + if (0 == filtered_pgn2.number_of_holes()) { + const Polygon_2& pnh2 = + filtered_pgn2.outer_boundary(); + if (pnh2.is_convex()) { + // pnh2 is convex + Nop_decomposition decomp_nop; + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_no_holes, decomp_nop, traits); + return mink_sum(pnh1, pnh2); + } + // pnh2 is concave + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_no_holes, decomp_no_holes, traits); + return mink_sum(pnh1, pnh2); + } + // pnh2 has holes + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_no_holes, decomp_with_holes, traits); + return mink_sum(pnh1, filtered_pgn2); + } + + // filtered_pgn1 has holes + if (0 == filtered_pgn2.number_of_holes()) { + const Polygon_2& pnh2 = + filtered_pgn2.outer_boundary(); + if (pnh2.is_convex()) { + // pnh2 is convex + Nop_decomposition decomp_nop; + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_nop, decomp_with_holes, traits); + return mink_sum(pnh2, filtered_pgn1); + } + // pnh2 is concave + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_no_holes, decomp_with_holes, traits); + return mink_sum(pnh2, filtered_pgn1); + } + // pnh2 has holes + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_with_holes, decomp_with_holes, traits); + return mink_sum(filtered_pgn1, filtered_pgn2); +} + +/*! Compute the Minkowski sum of a simple polygon and a polygon with holes + * by decomposing each polygon to convex sub-polygons and computing the union + * of the pairwise Minkowski sums of the sub-polygons. The result is also + * represented as a polygon with holes. + * \param[in] pgn1 The first polygon. + * \param[in] pgn2 The second polygon. + * \param[in] decomposition A functor for decomposing polygons. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_by_decomposition_2 +(const Polygon_2& pgn1, + const Polygon_with_holes_2& pgn2, + const NoHolesDecomposition_& decomp_no_holes, + const WithHolesDecomposition_& decomp_with_holes) +{ + typename Minkowski_sum_by_decomposition_2::Traits_2 traits; + return minkowski_sum_by_decomposition_2(pgn1, pgn2, + decomp_no_holes, decomp_with_holes, + traits); +} + +/*! Compute the Minkowski sum of a simple polygon and a polygon with holes + * by decomposing each polygon to convex sub-polygons and computing the union + * of the pairwise Minkowski sums of the sub-polygons. The result is also + * represented as a polygon with holes. + * \param[in] pgn1 The simple polygon. + * \param[in] pgn2 The polygon with holes. + * \param[in] decomposition A functor for decomposing polygons. + * \param[in] traits The traits. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_by_decomposition_2 +(const Polygon_2& pgn1, + const Polygon_with_holes_2& pgn2, + const NoHolesDecomposition_& decomp_no_holes, + const WithHolesDecomposition_& decomp_with_holes, + const typename Minkowski_sum_by_decomposition_2::Traits_2& traits) +{ + typedef Kernel_ Kernel; + typedef Container_ Container; + typedef NoHolesDecomposition_ No_holes_decomposition; + typedef WithHolesDecomposition_ With_holes_decomposition; + typedef Polygon_nop_decomposition_2 Nop_decomposition; + + Hole_filter_2 hole_filter; + Polygon_with_holes_2 filtered_pgn2; + hole_filter(pgn2, pgn1, filtered_pgn2); + + if (pgn1.is_convex()) { + Nop_decomposition decomp_nop; + if (0 == filtered_pgn2.number_of_holes()) { + const Polygon_2& pnh2 = filtered_pgn2.outer_boundary(); + if (pnh2.is_convex()) { + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_nop, decomp_nop, traits); + return mink_sum(pgn1, pnh2); + } + // pnh2 is concave + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_nop, decomp_no_holes, traits); + return mink_sum(pgn1, pnh2); + } + // pnh2 has holes + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_nop, decomp_with_holes, traits); + return mink_sum(pgn1, filtered_pgn2); + } + // pgn1 is concave + if (0 == filtered_pgn2.number_of_holes()) { + const Polygon_2& pnh2 = filtered_pgn2.outer_boundary(); + if (pnh2.is_convex()) { + // pnh2 is convex + Nop_decomposition decomp_nop; + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_no_holes, decomp_nop, traits); + return mink_sum(pgn1, pnh2); + } + // pnh2 is concave + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_no_holes, decomp_no_holes, traits); + return mink_sum(pgn1, pnh2); + } + // pnh2 has holes + Minkowski_sum_by_decomposition_2 + mink_sum(decomp_no_holes, decomp_with_holes, traits); + return mink_sum(pgn1, filtered_pgn2); +} + +/*! Compute the Minkowski sum of a simple polygon and a polygon with holes + * by decomposing each polygon to convex sub-polygons and computing the union + * of the pairwise Minkowski sums of the sub-polygons. The result is also + * represented as a polygon with holes. + * \param[in] pgn1 The second polygon. + * \param[in] pgn2 The first polygon. + * \param[in] decomposition A functor for decomposing polygons. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_by_decomposition_2 +(const Polygon_with_holes_2& pgn1, + const Polygon_2& pgn2, + const NoHolesDecomposition_& decomp_no_holes, + const WithHolesDecomposition_& decomp_with_holes) +{ + typename Minkowski_sum_by_decomposition_2::Traits_2 traits; + return minkowski_sum_by_decomposition_2(pgn1, pgn2, + decomp_no_holes, decomp_with_holes, + traits); +} + +/*! Compute the Minkowski sum of a simple polygon and a polygon with holes + * by decomposing each polygon to convex sub-polygons and computing the union + * of the pairwise Minkowski sums of the sub-polygons. The result is also + * represented as a polygon with holes. + * \param[in] pgn1 The polygon with holes. + * \param[in] pgn2 The simple polygon. + * \param[in] decomposition A functor for decomposing polygons. + * \param[in] traits The traits. + * \return The resulting polygon with holes, representing the sum. + */ +template +Polygon_with_holes_2 +minkowski_sum_by_decomposition_2 +(const Polygon_with_holes_2& pgn1, + const Polygon_2& pgn2, + const NoHoleDecomposition_& decomp_no_holes, + const WithHolesDecomposition_& decomp_with_holes, + const typename Minkowski_sum_by_decomposition_2::Traits_2& traits) +{ + return minkowski_sum_by_decomposition_2(pgn2, pgn1, + decomp_no_holes, decomp_with_holes, + traits); +} + +/*!@}*/ } //namespace CGAL diff --git a/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cmd b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cmd index 2fc35b88ddc..35b994e0217 100644 --- a/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cmd +++ b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cmd @@ -1,4 +1,4 @@ -rvt +rvtwud data/pwh1.dat data/pwh1.dat data/pwh2.dat data/pwh2.dat data/pwh1.dat data/pwh2.dat diff --git a/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cpp b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cpp index 27bbd87fc87..6b5eb2b377b 100644 --- a/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cpp +++ b/Minkowski_sum_2/test/Minkowski_sum_2/test_minkowski_sum_with_holes.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "read_polygon.h" @@ -25,14 +26,20 @@ bool are_equal(const Polygon_with_holes_2& ph1, typedef enum { REDUCED_CONVOLUTION, - VERTICAL_DECOMP, - TRIANGULATION_DECOMP + VERTICAL_DECOMPOSITION, + TRIANGULATION_DECOMPOSITION, + VERTICAL_AND_ANGLE_BISECTOR_DECOMPOSITION, + TRIANGULATION_AND_ANGLE_BISECTOR_DECOMPOSITION, + OPTIMAL_DECOMPOSITION, } Strategy; static const char* strategy_names[] = { "reduced convolution", "vertical decomposition", - "constrained triangulation decomposition" + "constrained triangulation decomposition", + "vertical and angle bisector decomposition", + "constrained triangulation and angle bisector decomposition", + "optimal decomposition" }; Polygon_with_holes_2 compute_minkowski_sum_2(Polygon_with_holes_2& p, @@ -42,18 +49,102 @@ Polygon_with_holes_2 compute_minkowski_sum_2(Polygon_with_holes_2& p, switch (strategy) { case REDUCED_CONVOLUTION: { - return minkowski_sum_by_reduced_convolution_2(p, q); + return CGAL::minkowski_sum_by_reduced_convolution_2(p, q); } - case VERTICAL_DECOMP: + case VERTICAL_DECOMPOSITION: { CGAL::Polygon_vertical_decomposition_2 decomp; - return minkowski_sum_2(p, q, decomp); + return CGAL::minkowski_sum_2(p, q, decomp); } - default: // TRIANGULATION_DECOMP + case TRIANGULATION_DECOMPOSITION: { CGAL::Polygon_triangulation_decomposition_2 decomp; - return minkowski_sum_2(p, q, decomp); + return CGAL::minkowski_sum_2(p, q, decomp); } + + case VERTICAL_AND_ANGLE_BISECTOR_DECOMPOSITION: + { + typedef CGAL::Small_side_angle_bisector_decomposition_2 + No_holes_decomposition; + typedef CGAL::Polygon_vertical_decomposition_2 + With_holes_decomposition; + + if (0 == p.number_of_holes()) { + const Polygon_2& pnh = p.outer_boundary(); + No_holes_decomposition decomp_no_holes; + if (0 == q.number_of_holes()) { + const Polygon_2& qnh = q.outer_boundary(); + return CGAL::minkowski_sum_2(pnh, qnh, + decomp_no_holes, decomp_no_holes); + } + else { + With_holes_decomposition decomp_with_holes; + return + CGAL::minkowski_sum_2(pnh, q, decomp_no_holes, decomp_with_holes); + } + } + else { + With_holes_decomposition decomp_with_holes; + if (0 == q.number_of_holes()) { + const Polygon_2& qnh = q.outer_boundary(); + No_holes_decomposition decomp_no_holes; + return + CGAL::minkowski_sum_2(p, qnh, decomp_with_holes, decomp_no_holes); + } + else { + return + CGAL::minkowski_sum_2(p, q, decomp_with_holes, decomp_with_holes); + } + } + } + + case TRIANGULATION_AND_ANGLE_BISECTOR_DECOMPOSITION: + { + typedef CGAL::Small_side_angle_bisector_decomposition_2 + No_holes_decomposition; + typedef CGAL::Polygon_triangulation_decomposition_2 + With_holes_decomposition; + if (0 == p.number_of_holes()) { + const Polygon_2& pnh = p.outer_boundary(); + No_holes_decomposition decomp_no_holes; + if (0 == q.number_of_holes()) { + const Polygon_2& qnh = q.outer_boundary(); + return CGAL::minkowski_sum_2(pnh, qnh, + decomp_no_holes, decomp_no_holes); + } + else { + With_holes_decomposition decomp_with_holes; + return + CGAL::minkowski_sum_2(pnh, q, decomp_no_holes, decomp_with_holes); + } + } + else { + With_holes_decomposition decomp_with_holes; + if (0 == q.number_of_holes()) { + const Polygon_2& qnh = q.outer_boundary(); + No_holes_decomposition decomp_no_holes; + return + CGAL::minkowski_sum_2(p, qnh, decomp_with_holes, decomp_no_holes); + } + else { + return + CGAL::minkowski_sum_2(p, q, decomp_with_holes, decomp_with_holes); + } + } + } + + case OPTIMAL_DECOMPOSITION: + { + CGAL::Small_side_angle_bisector_decomposition_2 decomp_no_holes; + CGAL::Polygon_triangulation_decomposition_2 decomp_with_holes; + return CGAL::minkowski_sum_by_decomposition_2(p, q, + decomp_no_holes, + decomp_with_holes); + } + + default: + std::cerr << "Invalid strategy" << std::endl; + return Polygon_with_holes_2(); } } @@ -81,11 +172,23 @@ int main(int argc, char* argv[]) break; case 'v': - strategies.push_back(VERTICAL_DECOMP); + strategies.push_back(VERTICAL_DECOMPOSITION); break; case 't': - strategies.push_back(TRIANGULATION_DECOMP); + strategies.push_back(TRIANGULATION_DECOMPOSITION); + break; + + case 'w': + strategies.push_back(VERTICAL_AND_ANGLE_BISECTOR_DECOMPOSITION); + break; + + case 'u': + strategies.push_back(TRIANGULATION_AND_ANGLE_BISECTOR_DECOMPOSITION); + break; + + case 'd': + strategies.push_back(OPTIMAL_DECOMPOSITION); break; default: