diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index bc9c1ca7f..1af918eb3 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -1570,10 +1570,8 @@ struct buffered_piece_collection } } - // Assign parents, checking orientation but NOT discarding double - // negative rings (negative child with negative parent) - detail::overlay::assign_parents(offsetted_rings, traversed_rings, - selected, m_intersection_strategy, true, false); + detail::overlay::assign_parents(offsetted_rings, traversed_rings, + selected, m_intersection_strategy); return detail::overlay::add_rings(selected, offsetted_rings, traversed_rings, out, m_area_strategy); } diff --git a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp index c8ce65100..cb8064fe9 100644 --- a/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/assign_parents.hpp @@ -210,10 +210,9 @@ struct assign_visitor }; - - template < + overlay_type OverlayType, typename Geometry1, typename Geometry2, typename RingCollection, typename RingMap, @@ -223,10 +222,15 @@ inline void assign_parents(Geometry1 const& geometry1, Geometry2 const& geometry2, RingCollection const& collection, RingMap& ring_map, - Strategy const& strategy, - bool check_for_orientation = false, - bool discard_double_negative = false) + Strategy const& strategy) { + static bool const is_difference = OverlayType == overlay_difference; + static bool const is_buffer = OverlayType == overlay_buffer; + static bool const is_dissolve = + OverlayType == overlay_dissolve_union + || OverlayType == overlay_dissolve_intersection; + static bool const check_for_orientation = is_buffer || is_dissolve; + typedef typename geometry::tag::type tag1; typedef typename geometry::tag::type tag2; @@ -293,12 +297,14 @@ inline void assign_parents(Geometry1 const& geometry1, return; } - if (count_positive == 1) + if (count_positive == 1 && ! is_difference && ! is_dissolve) { // Optimization for one outer ring // -> assign this as parent to all others (all interior rings) // In unions, this is probably the most occuring case and gives // a dramatic improvement (factor 5 for star_comb testcase) + // In difference or other cases where interior rings might be + // located outside the outer ring, this cannot be done ring_identifier id_of_positive = vector[index_positive].id; ring_info_type& outer = ring_map[id_of_positive]; index = 0; @@ -346,7 +352,7 @@ inline void assign_parents(Geometry1 const& geometry1, bool const pos = math::larger(info.get_area(), 0); bool const parent_pos = math::larger(parent.area, 0); - bool const double_neg = discard_double_negative && ! pos && ! parent_pos; + bool const double_neg = is_dissolve && ! pos && ! parent_pos; if ((pos && parent_pos) || double_neg) { @@ -386,6 +392,7 @@ inline void assign_parents(Geometry1 const& geometry1, // Version for one geometry (called by buffer/dissolve) template < + overlay_type OverlayType, typename Geometry, typename RingCollection, typename RingMap, @@ -394,16 +401,13 @@ template inline void assign_parents(Geometry const& geometry, RingCollection const& collection, RingMap& ring_map, - Strategy const& strategy, - bool check_for_orientation, - bool discard_double_negative) + Strategy const& strategy) { // Call it with an empty geometry as second geometry (source_id == 1) // (ring_map should be empty for source_id==1) - Geometry empty; - assign_parents(geometry, empty, collection, ring_map, strategy, - check_for_orientation, discard_double_negative); + assign_parents(geometry, empty, + collection, ring_map, strategy); } diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index f24cde8b8..c6ea4f13d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -233,7 +233,7 @@ inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1, select_rings(geometry1, geometry2, empty, all_of_one_of_them, strategy); ring_container_type rings; - assign_parents(geometry1, geometry2, rings, all_of_one_of_them, strategy); + assign_parents(geometry1, geometry2, rings, all_of_one_of_them, strategy); return add_rings(all_of_one_of_them, geometry1, geometry2, rings, out, strategy.template get_area_strategy()); } @@ -385,7 +385,8 @@ std::cout << "traverse" << std::endl; } } - assign_parents(geometry1, geometry2, rings, selected_ring_properties, strategy); + assign_parents(geometry1, geometry2, + rings, selected_ring_properties, strategy); // NOTE: There is no need to check result area for union because // as long as the polygons in the input are valid the resulting diff --git a/test/algorithms/overlay/multi_overlay_cases.hpp b/test/algorithms/overlay/multi_overlay_cases.hpp index 304bec279..7077647c8 100644 --- a/test/algorithms/overlay/multi_overlay_cases.hpp +++ b/test/algorithms/overlay/multi_overlay_cases.hpp @@ -1259,10 +1259,24 @@ static std::string case_recursive_boxes_83[2] = static std::string case_recursive_boxes_84[2] = { + // Need to set some ii-turns non-startable "MULTIPOLYGON(((2 4,1 4,1 5,3 5,2 4)),((3 5,4 5,4 4,3 4,3 5)),((3 3,4 3,4 4,5 4,4.5 3.5,5 3,5 2,4 1,3 1,3 2,2 2,2 3,3 3),(4 2,3.5 1.5,4 1,4 2)),((0 3,0 4,1 4,1 3,0 3)))", "MULTIPOLYGON(((4 4,4 5,5 5,5 4,4 4)),((0 5,1 5,1 4,0 4,0 5)),((2 0,1 0,1 1,2 1,2 2,3 2,3 0,2 0)),((2 4,2 3,1 3,2 4)),((2 4,2 5,3 5,2 4)),((2 3,2 2,1 2,2 3)),((1 3,1 1,0 1,0 3,1 3)),((5 1,5 0,4 0,4 1,5 1)))" }; +static std::string case_recursive_boxes_85[2] = +{ + // Contains rescaling problem + "MULTIPOLYGON(((5 2,5 3,6 3,6 2,5 2)),((6 5,6 6,7 6,7 5,6 5)),((3 6,1 6,2 7,3 7,3 6)),((3 6,3 5,2 5,2 6,2.5 5.5,3 6)))", + "MULTIPOLYGON(((2 5,2 6,3 6,2 5)),((6 1,6 2,7 2,6 1)),((5 4,5 5,6 4,5 4)),((0 6,0 7,1 7,0 6)),((3 3,3 2,2 2,3 3)),((3 3,3 4,4 5,4 4,3 3)),((4 4,5 3,4 3,4 4)))" +}; + +static std::string case_recursive_boxes_86[2] = +{ + "MULTIPOLYGON(((3 4,4 4,4 3,2 3,3 4)))", + "MULTIPOLYGON(((4 1,3 1,3 2,4 1)),((4 1,5 1,5 0,4 0,4 1)))" +}; + static std::string pie_21_7_21_0_3[2] = { "MULTIPOLYGON(((2500 2500,2500 3875,2855 3828,3187 3690,3472 3472,3690 3187,3828 2855,3875 2500,3828 2144,3690 1812,3472 1527,3187 1309,2855 1171,2499 1125,2144 1171,1812 1309,1527 1527,1309 1812,1171 2144,1125 2499,1171 2855,1309 3187,2500 2500)))", diff --git a/test/algorithms/set_operations/difference/difference_multi.cpp b/test/algorithms/set_operations/difference/difference_multi.cpp index 7da30ee61..d05f9deb6 100644 --- a/test/algorithms/set_operations/difference/difference_multi.cpp +++ b/test/algorithms/set_operations/difference/difference_multi.cpp @@ -435,6 +435,8 @@ void test_areal() TEST_DIFFERENCE(case_recursive_boxes_81, 3, 5.0, 6, 6.75, 6); + TEST_DIFFERENCE(case_recursive_boxes_86, 1, 1.5, 2, 1.5, 3); + { ut_settings sym_settings; #if defined(BOOST_GEOMETRY_NO_ROBUSTNESS)