From 13e4b1daca8514e93e03e49d166ad4ebcd55dbc5 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Tue, 23 Dec 2014 20:23:36 +0100 Subject: [PATCH] [buffer] Split some of new code into functions --- .../buffer/turn_in_original_visitor.hpp | 141 +++++++++++++----- 1 file changed, 104 insertions(+), 37 deletions(-) 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 04742489a..f6006a770 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 @@ -69,57 +69,124 @@ struct turn_in_original_ovelaps_box } }; +//! Check if specified is in range of specified iterators +//! Return value of strategy (true if we can bail out) +template +< + typename Strategy, + typename State, + typename Point, + typename Iterator +> +inline bool point_in_range(Strategy& strategy, State& state, + Point const& point, Iterator begin, Iterator end) +{ + Iterator it = begin; + for (Iterator previous = it++; it != end; ++previous, ++it) + { + if (! strategy.apply(point, *previous, *it, state)) + { + // We're probably on the boundary + return false; + } + } + return true; +} + +template +< + typename Strategy, + typename State, + typename Point, + typename CoordinateType, + typename Iterator +> +inline bool point_in_section(Strategy& strategy, State& state, + Point const& point, CoordinateType const& point_y, + Iterator begin, Iterator end, + int direction) +{ + if (direction == 0) + { + // Not a monotonic section, or no change in Y-direction + return point_in_range(strategy, state, point, begin, end); + } + + // We're in a monotonic section in y-direction + Iterator it = begin; + + for (Iterator previous = it++; it != end; ++previous, ++it) + { + // Depending on sections.direction we can quit for this section + CoordinateType const previous_y = geometry::get<1>(*previous); + + if (direction == 1 && point_y < previous_y) + { + // Section goes upwards, y increases, point is is below section + return true; + } + else if (direction == -1 && point_y > previous_y) + { + // Section goes downwards, y decreases, point is above section + return true; + } + + if (! strategy.apply(point, *previous, *it, state)) + { + // We're probably on the boundary + return false; + } + } + return true; +} + + template inline int point_in_original(Point const& point, Original const& original) { typedef strategy::within::winding strategy_type; - typedef typename Original::original_robust_ring_type ring_type; - typedef typename Original::sections_type sections_type; - typedef typename boost::range_iterator::type iterator_type; - typedef typename boost::range_iterator::type siterator_type; - - 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 (boost::size(original.m_sections) == 0 + || boost::size(original.m_ring) - boost::size(original.m_sections) < 16) { - typename boost::range_value::type const& section = *sit; + // There are no sections, or it does not profit to walk over sections + // instead of over points. Boundary of 16 is arbitrary but can influence + // performance + point_in_range(strategy, state, point, + original.m_ring.begin(), original.m_ring.end()); + return strategy.result(state); + } + + typedef typename Original::sections_type sections_type; + typedef typename boost::range_iterator::type iterator_type; + typedef typename boost::range_value::type section_type; + typedef typename geometry::coordinate_type::type coordinate_type; + + coordinate_type const point_y = geometry::get<1>(point); + + // Walk through all monotonic sections of this original + for (iterator_type it = boost::begin(original.m_sections); + it != boost::end(original.m_sections); + ++it) + { + section_type const& section = *it; + if (! section.duplicate && section.begin_index < section.end_index && point_y >= geometry::get(section.bounding_box) && point_y <= geometry::get(section.bounding_box)) { - // 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) + // y-coordinate of point overlaps with section + if (! point_in_section(strategy, state, point, point_y, + boost::begin(original.m_ring) + section.begin_index, + boost::begin(original.m_ring) + section.end_index + 1, + section.directions[0])) { - 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; - } + // We're probably on the boundary + break; } } } @@ -180,7 +247,7 @@ public: else { // It is an exterior ring and there are no interior rings. - // Then we are ready with this point + // Then we are completely ready with this turn mutable_turn.within_original = true; mutable_turn.count_in_original = 1; }