From e006eaa6c6adc42f073ef6417c44276c363630e5 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 29 Jun 2015 16:47:53 +0300 Subject: [PATCH] Added minkowski_sum_by_decomposition_2() --- .../include/CGAL/minkowski_sum_2.h | 384 +++++++++++++++++- .../test_minkowski_sum_with_holes.cmd | 2 +- .../test_minkowski_sum_with_holes.cpp | 65 +-- 3 files changed, 424 insertions(+), 27 deletions(-) diff --git a/Minkowski_sum_2/include/CGAL/minkowski_sum_2.h b/Minkowski_sum_2/include/CGAL/minkowski_sum_2.h index ad3d14dfa07..42e911e7785 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 { @@ -730,6 +731,387 @@ minkowski_sum_2(const Polygon_with_holes_2& pgn1, 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); +} /*!@}*/ 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 dc520b30f01..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 @@ -rvtwu +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 ffb123a51fa..cfb6d5ac8b3 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 @@ -26,10 +26,11 @@ bool are_equal(const Polygon_with_holes_2& ph1, typedef enum { REDUCED_CONVOLUTION, - VERTICAL_DECOMP, - TRIANGULATION_DECOMP, - VERTICAL_AND_ANGLE_BISECTOR_DECOMP, - TRIANGULATION_AND_ANGLE_BISECTOR_DECOMP + VERTICAL_DECOMPOSITION, + TRIANGULATION_DECOMPOSITION, + VERTICAL_AND_ANGLE_BISECTOR_DECOMPOSITION, + TRIANGULATION_AND_ANGLE_BISECTOR_DECOMPOSITION, + OPTIMAL_DECOMPOSITION, } Strategy; static const char* strategy_names[] = { @@ -37,7 +38,8 @@ static const char* strategy_names[] = { "vertical decomposition", "constrained triangulation decomposition", "vertical and angle bisector decomposition", - "constrained triangulation 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, @@ -49,43 +51,43 @@ Polygon_with_holes_2 compute_minkowski_sum_2(Polygon_with_holes_2& p, { return CGAL::minkowski_sum_reduced_convolution_2(p, q); } - case VERTICAL_DECOMP: + case VERTICAL_DECOMPOSITION: { CGAL::Polygon_vertical_decomposition_2 decomp; return CGAL::minkowski_sum_2(p, q, decomp); } - case TRIANGULATION_DECOMP: + case TRIANGULATION_DECOMPOSITION: { CGAL::Polygon_triangulation_decomposition_2 decomp; return CGAL::minkowski_sum_2(p, q, decomp); } - case VERTICAL_AND_ANGLE_BISECTOR_DECOMP: + case VERTICAL_AND_ANGLE_BISECTOR_DECOMPOSITION: { typedef CGAL::Small_side_angle_bisector_decomposition_2 - No_hole_decomposition; + No_holes_decomposition; typedef CGAL::Polygon_vertical_decomposition_2 - With_hole_decomposition; + With_holes_decomposition; if (0 == p.number_of_holes()) { const Polygon_2& pnh = p.outer_boundary(); - No_hole_decomposition decomp_no_holes; + 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_hole_decomposition decomp_with_holes; + With_holes_decomposition decomp_with_holes; return CGAL::minkowski_sum_2(pnh, q, decomp_no_holes, decomp_with_holes); } } else { - With_hole_decomposition decomp_with_holes; + With_holes_decomposition decomp_with_holes; if (0 == q.number_of_holes()) { const Polygon_2& qnh = q.outer_boundary(); - No_hole_decomposition decomp_no_holes; + No_holes_decomposition decomp_no_holes; return CGAL::minkowski_sum_2(p, qnh, decomp_with_holes, decomp_no_holes); } @@ -96,31 +98,31 @@ Polygon_with_holes_2 compute_minkowski_sum_2(Polygon_with_holes_2& p, } } - case TRIANGULATION_AND_ANGLE_BISECTOR_DECOMP: + case TRIANGULATION_AND_ANGLE_BISECTOR_DECOMPOSITION: { typedef CGAL::Small_side_angle_bisector_decomposition_2 - No_hole_decomposition; + No_holes_decomposition; typedef CGAL::Polygon_triangulation_decomposition_2 - With_hole_decomposition; + With_holes_decomposition; if (0 == p.number_of_holes()) { const Polygon_2& pnh = p.outer_boundary(); - No_hole_decomposition decomp_no_holes; + 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_hole_decomposition decomp_with_holes; + With_holes_decomposition decomp_with_holes; return CGAL::minkowski_sum_2(pnh, q, decomp_no_holes, decomp_with_holes); } } else { - With_hole_decomposition decomp_with_holes; + With_holes_decomposition decomp_with_holes; if (0 == q.number_of_holes()) { const Polygon_2& qnh = q.outer_boundary(); - No_hole_decomposition decomp_no_holes; + No_holes_decomposition decomp_no_holes; return CGAL::minkowski_sum_2(p, qnh, decomp_with_holes, decomp_no_holes); } @@ -131,6 +133,15 @@ Polygon_with_holes_2 compute_minkowski_sum_2(Polygon_with_holes_2& p, } } + 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(); @@ -161,19 +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_DECOMP); + strategies.push_back(VERTICAL_AND_ANGLE_BISECTOR_DECOMPOSITION); break; case 'u': - strategies.push_back(TRIANGULATION_AND_ANGLE_BISECTOR_DECOMP); + strategies.push_back(TRIANGULATION_AND_ANGLE_BISECTOR_DECOMPOSITION); + break; + + case 'd': + strategies.push_back(OPTIMAL_DECOMPOSITION); break; default: