static inline bool point_is_spike_or_equal(Point1 const& last_point, Point2 const& segment_a, Point3 const& segment_b, RobustPolicy const& robust_policy) { if (point_is_spike_or_equal(last_point, segment_a, segment_b)) { return true; } if (! RobustPolicy::enabled) { return false; } // Try using specified robust policy typedef typename geometry::robust_point_type < Point1, RobustPolicy >::type robust_point_type; robust_point_type last_point_rob, segment_a_rob, segment_b_rob; geometry::recalculate(last_point_rob, last_point, robust_policy); geometry::recalculate(segment_a_rob, segment_a, robust_policy); geometry::recalculate(segment_b_rob, segment_b, robust_policy); return point_is_spike_or_equal ( last_point_rob, segment_a_rob, segment_b_rob ); }
inline void append_no_dups_or_spikes(Range& range, Point const& point, RobustPolicy const& robust_policy) { #ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION std::cout << " add: (" << geometry::get<0>(point) << ", " << geometry::get<1>(point) << ")" << std::endl; #endif // The code below thies condition checks all spikes/dups // for geometries >= 3 points. // So we have to check the first potential duplicate differently if (boost::size(range) == 1 && points_equal_or_close(*(boost::begin(range)), point, robust_policy)) { return; } traits::push_back<Range>::apply(range, point); // If a point is equal, or forming a spike, remove the pen-ultimate point // because this one caused the spike. // If so, the now-new-pen-ultimate point can again cause a spike // (possibly at a corner). So keep doing this. // Besides spikes it will also avoid adding duplicates. while(boost::size(range) >= 3 && point_is_spike_or_equal(point, *(boost::end(range) - 3), *(boost::end(range) - 2), robust_policy)) { // Use the Concept/traits, so resize and append again traits::resize<Range>::apply(range, boost::size(range) - 2); traits::push_back<Range>::apply(range, point); } }
inline bool is_spike_or_equal(Point1 const& a, Point2 const& b, Point3 const& c, SideStrategy const& strategy) { return point_is_spike_or_equal(c, a, b, strategy); }
inline bool point_is_spike_or_equal(Point1 const& last_point, Point2 const& segment_a, Point3 const& segment_b, SideStrategy const& strategy, RobustPolicy const& robust_policy) { if (point_is_spike_or_equal(last_point, segment_a, segment_b, strategy)) { return true; } if (BOOST_GEOMETRY_CONDITION(! RobustPolicy::enabled)) { return false; } // Try using specified robust policy typedef typename geometry::robust_point_type < Point1, RobustPolicy >::type robust_point_type; robust_point_type last_point_rob, segment_a_rob, segment_b_rob; geometry::recalculate(last_point_rob, last_point, robust_policy); geometry::recalculate(segment_a_rob, segment_a, robust_policy); geometry::recalculate(segment_b_rob, segment_b, robust_policy); return point_is_spike_or_equal ( last_point_rob, segment_a_rob, segment_b_rob, strategy ); }
inline void clean_closing_dups_and_spikes(Range& range, RobustPolicy const& robust_policy) { std::size_t const minsize = core_detail::closure::minimum_ring_size < geometry::closure<Range>::value >::value; if (boost::size(range) <= minsize) { return; } typedef typename boost::range_iterator<Range>::type iterator_type; static bool const closed = geometry::closure<Range>::value == geometry::closed; // TODO: the following algorithm could be rewritten to first look for spikes // and then erase some number of points from the beginning of the Range bool found = false; do { found = false; iterator_type first = boost::begin(range); iterator_type second = first + 1; iterator_type ultimate = boost::end(range) - 1; if (BOOST_GEOMETRY_CONDITION(closed)) { ultimate--; } // Check if closing point is a spike (this is so if the second point is // considered as a spike w.r.t. the last segment) if (point_is_spike_or_equal(*second, *ultimate, *first, robust_policy)) { range::erase(range, first); if (BOOST_GEOMETRY_CONDITION(closed)) { // Remove closing last point range::resize(range, boost::size(range) - 1); // Add new closing point range::push_back(range, range::front(range)); } found = true; } } while(found && boost::size(range) > minsize); }