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 209542a44..368215537 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -203,6 +203,9 @@ struct buffered_piece_collection struct robust_original { + typedef robust_ring_type original_robust_ring_type; + typedef geometry::sections sections_type; + inline robust_original() : m_is_interior(false) , m_has_interiors(true) @@ -224,9 +227,7 @@ struct buffered_piece_collection robust_ring_type m_ring; robust_box_type m_box; - geometry::sections m_sections; - - typedef robust_ring_type original_robust_ring_type; + sections_type m_sections; bool m_is_interior; bool m_has_interiors; diff --git a/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp b/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp index 587d0cd67..04742489a 100644 --- a/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp @@ -73,20 +73,54 @@ template inline int point_in_original(Point const& point, Original const& original) { typedef strategy::within::winding strategy_type; - strategy_type strategy; typedef typename Original::original_robust_ring_type ring_type; + typedef typename Original::sections_type sections_type; typedef typename boost::range_iterator::type iterator_type; - typename strategy_type::state_type state; - iterator_type it = boost::begin(original.m_ring); + typedef typename boost::range_iterator::type siterator_type; - for (iterator_type previous = it++; - it != boost::end(original.m_ring); - ++previous, ++it) + typename geometry::coordinate_type::type const point_y + = geometry::get<1>(point); + + typename strategy_type::state_type state; + strategy_type strategy; + + // Walk through all monotonic sections + for (siterator_type sit = boost::begin(original.m_sections); + sit != boost::end(original.m_sections); + ++sit) { - if (! strategy.apply(point, *previous, *it, state)) + typename boost::range_value::type const& section = *sit; + if (! section.duplicate + && section.begin_index < section.end_index + && point_y >= geometry::get(section.bounding_box) + && point_y <= geometry::get(section.bounding_box)) { - break; + // Walk through this section + iterator_type it + = boost::begin(original.m_ring) + section.begin_index; + iterator_type const end + = boost::begin(original.m_ring) + section.end_index + 1; + for (iterator_type previous = it++; it != end; ++previous, ++it) + { + if (! strategy.apply(point, *previous, *it, state)) + { + break; + } + + // Depending on sections.direction we can quit the inner loop + typename geometry::coordinate_type::type const ring_y + = geometry::get<1>(*it); + + if (section.directions[0] == 1 && point_y < ring_y) + { + break; + } + else if (section.directions[0] == -1 && point_y > ring_y) + { + break; + } + } } }