diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index acea1259c..7a901c869 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -810,7 +810,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator visit_pieces_policy.apply(const_collection, 0); collection.discard_rings(); - collection.discard_turns(); + collection.block_turns(); collection.enrich(); collection.traverse(); 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 f674d805b..5ac6bd0c6 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -205,17 +205,6 @@ struct buffered_piece_collection RobustPolicy const& m_robust_policy; - struct redundant_turn - { - inline bool operator()(buffer_turn_info_type const& turn) const - { - // Erase discarded turns (location not OK) and the turns - // only used to detect oppositeness. - return turn.location != location_ok - || turn.opposite(); - } - }; - buffered_piece_collection(RobustPolicy const& robust_policy) : m_first_piece_index(-1) , m_robust_policy(robust_policy) @@ -844,15 +833,24 @@ struct buffered_piece_collection } } - inline void discard_turns() + inline void block_turns() { - m_turns.erase - ( - std::remove_if(boost::begin(m_turns), boost::end(m_turns), - redundant_turn()), - boost::end(m_turns) - ); - + for (typename boost::range_iterator::type it = + boost::begin(m_turns); it != boost::end(m_turns); ++it) + { + if (it->location != location_ok) + { + // Set it to blocked. They should not be discarded, to avoid + // generating rings over these turns + // Performance goes down a tiny bit from 161 s to 173 because there + // are sometimes much more turns. + // We might speed it up a bit by keeping only one blocked + // intersection per segment, but that is complex to program + // because each turn involves two segments + it->operations[0].operation = detail::overlay::operation_blocked; + it->operations[1].operation = detail::overlay::operation_blocked; + } + } } inline void traverse() diff --git a/test/algorithms/buffer/multi_polygon_buffer.cpp b/test/algorithms/buffer/multi_polygon_buffer.cpp index 26c792622..e9fb98505 100644 --- a/test/algorithms/buffer/multi_polygon_buffer.cpp +++ b/test/algorithms/buffer/multi_polygon_buffer.cpp @@ -250,6 +250,7 @@ static std::string const rt_u9 static std::string const rt_u10 = "MULTIPOLYGON(((7 5,8 6,8 5,7 5)),((4 5,5 6,5 5,5 4,4 4,4 5)),((9 5,10 5,10 4,9 4,8 4,9 5)),((1 2,1 1,0 1,1 2)),((6 6,6 7,7 7,7 6,6 6)),((3 6,3 7,4 6,3 6)),((8 6,8 7,9 6,8 6)),((1 3,1 4,2 3,1 3)),((9 9,10 8,9 8,9 7,8 7,8 8,9 9)),((9 2,10 3,10 2,9 2)),((2 5,2 6,3 6,2 5)),((1 9,1 10,2 10,2 9,1 9)),((4 6,4 7,5 7,5 6,4 6)),((6 0,6 1,7 1,7 0,6 0)),((0 9,0 10,1 10,0 9)),((3.5 5.5,4 6,4 5,3 5,3 6,3.5 5.5)),((9 3,9 4,10 3,9 3)),((9 9,10 10,10 9,9 9)),((1 6,2 7,2 6,1 6)),((4 2,4 3,5 2,4 2)),((5 10,4 9,4 10,5 10)),((0 3,1 2,0 2,0 3)),((5 8,4 8,5 9,6 10,6 9,7 9,7 8,6 8,5 7,5 8)),((6 2,5 2,5 3,5.5 2.5,6 3,6 4,7 4,8 4,8 3,7 3,7 2,6 2)),((4 0,3 0,3 1,2.5 0.5,3 0,2 0,2 1,2 2,3 3,3 2,4 2,4 1,5 0,4 0)),((3 5,4 4,3 4,2 4,3 5)),((0 6,0 7,1 7,1 6,1 5,0 5,0 6)),((2 8,3 8,3 7,2 7,1 7,1 8,2 8)),((9 1,9 0,8 0,8 1,8 2,9 1)),((7 10,8 10,8 9,7 9,7 10)))"; +// Fixed by blocking IP's instead of discarding them static std::string const rt_u11 = "MULTIPOLYGON(((7 3,8 4,8 3,7 3)),((4 8,5 9,5 8,4 8)),((7 1,8 2,8 1,7 1)),((7 2,8 3,8 2,7 2)),((0 1,0 2,1 2,0 1)),((8 1,9 2,9 1,8 1)),((6 9,6 8,5 8,6 9)),((7 9,7 10,8 10,7 9)),((0 7,1 8,1 7,0 7)),((6 4,6 5,7 5,7 4,6 4)),((7 4,8 5,8 4,7 4)),((4 2,4 3,5 3,5 2,4 2)),((5 5,5 6,6 6,6 5,5 5)),((5 9,6 10,6 9,5 9)),((4 8,4 7,3 7,3 8,4 8)),((5 5,6 4,5 4,4 4,4 5,5 5)),((4.5 0.5,5 0,4 0,4 1,5 2,6 2,6 3,7 4,7 3,7 2,7 1,6 1,6 0,5 0,5 1,4.5 0.5)),((4 6,3 5,3 6,4 7,5 7,5 6,4 6)),((2 3,1 3,0 3,1 4,1 5,1 6,2 6,2 5,2 4,2 3)),((3 4,4 4,3 3,2 3,3 4)),((3 9,4 9,3 8,2 8,2 9,3 9)),((1 9,1 8,0 8,0 9,1 10,2 9,1 9)),((3 7,3 6,2 6,2 7,3 7)),((8 6,8 7,9 7,9 6,9 5,8 5,8 6)),((9 1,10 2,10 1,10 0,9 0,9 1)),((8 8,8 7,7 7,7 8,8 8)),((6 8,7 9,7 8,6 7,6 8)),((10 9,10 8,10 7,9 7,9 8,9 9,9 10,10 10,10 9)))"; @@ -381,8 +382,8 @@ void test_all() test_one("rt_u9", rt_u9, join_miter, end_flat, 59.3063, 1.0); test_one("rt_u10", rt_u10, join_miter, end_flat, 144.0858, 1.0); + test_one("rt_u11", rt_u11, join_miter, end_flat, 131.3995, 1.0); #if defined(BOOST_GEOMETRY_BUFFER_INCLUDE_FAILING_TESTS) - test_one("rt_u11", rt_u11, join_miter, end_flat, 999, 1.0); test_one("rt_u12", rt_u12, join_miter, end_flat, 999, 1.0); #endif }