mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-20 14:52:10 +00:00
[geometry] Use robust_policy in append_no_dups_or_spikes
Only if robust_policy would make any difference, so we added an "enabled" boolean into the policy
This commit is contained in:
@@ -24,37 +24,118 @@ namespace boost { namespace geometry
|
||||
namespace detail { namespace overlay
|
||||
{
|
||||
|
||||
template <typename Range, typename Point, typename RobustPolicys>
|
||||
// TODO: move this / rename this
|
||||
template <typename Point1, typename Point2, typename RobustPolicy>
|
||||
inline bool points_equal_or_close(Point1 const& point1,
|
||||
Point2 const& point2,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
if (detail::equals::equals_point_point(point1, point2))
|
||||
{
|
||||
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 point1_rob, point2_rob;
|
||||
geometry::recalculate(point1_rob, point1, robust_policy);
|
||||
geometry::recalculate(point2_rob, point2, robust_policy);
|
||||
|
||||
return detail::equals::equals_point_point(point1_rob, point2_rob);
|
||||
}
|
||||
|
||||
|
||||
template <typename Range, typename Point, typename RobustPolicy>
|
||||
inline void append_no_dups_or_spikes(Range& range, Point const& point,
|
||||
RobustPolicys const& robust_policy)
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
|
||||
std::cout << " add: ("
|
||||
<< geometry::get<0>(point) << ", " << geometry::get<1>(point) << ")"
|
||||
<< std::endl;
|
||||
#endif
|
||||
boost::ignore_unused_variable_warning(robust_policy);
|
||||
// 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 duplicates.
|
||||
// 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)))
|
||||
&& 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);
|
||||
}
|
||||
}
|
||||
|
||||
// There might still be one duplicate not catched by the condition above
|
||||
if (boost::size(range) == 2
|
||||
&& geometry::detail::equals::equals_point_point(*boost::begin(range), point))
|
||||
template <typename Range, typename RobustPolicy>
|
||||
inline void clean_closing_dups_and_spikes(Range& range,
|
||||
RobustPolicy const& robust_policy)
|
||||
{
|
||||
int const minsize
|
||||
= core_detail::closure::minimum_ring_size
|
||||
<
|
||||
geometry::closure<Range>::value
|
||||
>::value;
|
||||
|
||||
if (boost::size(range) <= minsize)
|
||||
{
|
||||
traits::clear<Range>::apply(range);
|
||||
traits::push_back<Range>::apply(range, point);
|
||||
return;
|
||||
}
|
||||
|
||||
typedef typename boost::range_iterator<Range>::type iterator_type;
|
||||
const bool closed = geometry::closure<Range>::value == geometry::closed;
|
||||
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 (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(first);
|
||||
if (closed)
|
||||
{
|
||||
// Remove closing last point
|
||||
traits::resize<Range>::apply(range, boost::size(range) - 1);
|
||||
// Add new closing point
|
||||
traits::push_back<Range>::apply(range, *boost::begin(range));
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
} while(found && boost::size(range) > minsize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -399,9 +399,7 @@ public :
|
||||
detail::overlay::debug_traverse(*current, *iit, "->Finished");
|
||||
if (geometry::num_points(current_output) >= min_num_points)
|
||||
{
|
||||
// TODO this call should go, it should already be clean from dups/spikes
|
||||
clean_dups_and_spikes(current_output, rescale_policy);
|
||||
// END TODO
|
||||
clean_closing_dups_and_spikes(current_output, rescale_policy);
|
||||
rings.push_back(current_output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,8 +25,18 @@ namespace boost { namespace geometry
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Checks if a point ("last_point") causes a spike w.r.t.
|
||||
// the specified two other points (segment_a, segment_b)
|
||||
//
|
||||
// x-------x------x
|
||||
// a lp b
|
||||
//
|
||||
// Above, lp generates a spike w.r.t. segment(a,b)
|
||||
// So specify last point first, then (a,b) (this is unordered, so unintuitive)
|
||||
template <typename Point1, typename Point2, typename Point3>
|
||||
static inline bool point_is_spike_or_equal(Point1 const& last_point, Point2 const& segment_a, Point3 const& segment_b)
|
||||
static inline bool point_is_spike_or_equal(Point1 const& last_point,
|
||||
Point2 const& segment_a,
|
||||
Point3 const& segment_b)
|
||||
{
|
||||
typedef typename strategy::side::services::default_strategy
|
||||
<
|
||||
@@ -62,6 +72,49 @@ static inline bool point_is_spike_or_equal(Point1 const& last_point, Point2 cons
|
||||
return false;
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Point1,
|
||||
typename Point2,
|
||||
typename Point3,
|
||||
typename RobustPolicy
|
||||
>
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
#endif
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace detail
|
||||
// Probably this will be moved out of namespace detail
|
||||
struct no_rescale_policy
|
||||
{
|
||||
static bool const enabled = false;
|
||||
|
||||
// We don't rescale but return the reference of the input
|
||||
template <std::size_t Dimension, typename Value>
|
||||
inline Value const& apply(Value const& value) const
|
||||
|
||||
@@ -59,6 +59,8 @@ struct get_max_size<Box, 0>
|
||||
template <typename FpPoint, typename IntPoint, typename CalculationType>
|
||||
struct rescale_strategy
|
||||
{
|
||||
static bool const enabled = true;
|
||||
|
||||
typedef typename geometry::coordinate_type<IntPoint>::type output_ct;
|
||||
|
||||
rescale_strategy(FpPoint const& fp_min, IntPoint const& int_min, CalculationType const& the_factor)
|
||||
|
||||
Reference in New Issue
Block a user