[geometry] Instead of (non-rescaled) append, we clean rescaled dups afterwards.

We don't do it on the fly to avoid additional rescaling, it is done only once per point
This also changes occasionally some number-of-points in testcases (now more cleaned)
This commit is contained in:
Barend Gehrels 2013-12-22 14:12:40 +01:00
parent 2c2c384652
commit 9cd79d8033
6 changed files with 144 additions and 15 deletions

View File

@ -0,0 +1,135 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLEAN_DUPS_AND_SPIKES_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLEAN_DUPS_AND_SPIKES_HPP
#include <boost/range.hpp>
#include <boost/geometry/core/mutable_range.hpp>
#include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace overlay
{
// This is refactored from remove_spikes. This function considers rescaled points
template <typename Range, typename RescalePolicy>
static inline void clean_dups_and_spikes(Range& range,
RescalePolicy const& rescale_policy)
{
std::size_t n = boost::size(range);
if (n < core_detail::closure::minimum_ring_size
<
geometry::closure<Range>::value
>::value)
{
return;
}
typedef typename point_type<Range>::type point_type;
typedef std::pair
<
point_type,
typename geometry::robust_point_type
<
point_type,
RescalePolicy
>::type
> point_pair;
std::deque<point_pair> cleaned;
for (typename boost::range_iterator<Range const>::type it = boost::begin(range);
it != boost::end(range); ++it)
{
point_pair pp;
pp.first = *it;
geometry::recalculate(pp.second, pp.first, rescale_policy);
// Add point
cleaned.push_back(pp);
while(cleaned.size() >= 3
&& point_is_spike_or_equal(cleaned.back().second,
(cleaned.end() - 3)->second,
(cleaned.end() - 2)->second))
{
// Remove pen-ultimate point causing the spike (or which was equal)
cleaned.erase(cleaned.end() - 2);
}
}
// For a closed-polygon, remove closing point
// this makes checking first point(s) easier and consistent
if (geometry::closure<Range>::value == geometry::closed)
{
cleaned.pop_back();
}
bool found = false;
do
{
found = false;
// Check for spike in first point
int const penultimate = 2;
while(cleaned.size() > 3
&& point_is_spike_or_equal(cleaned.front().second,
(cleaned.end() - penultimate)->second,
cleaned.back().second))
{
cleaned.pop_back();
found = true;
}
// Check for spike in second point
while(cleaned.size() > 3
&& point_is_spike_or_equal((cleaned.begin() + 1)->second,
cleaned.back().second,
cleaned.front().second))
{
cleaned.pop_front();
found = true;
}
}
while (found);
// Create new output
geometry::clear(range);
range.reserve(n);
for (typename boost::range_iterator<std::deque<point_pair> const>::type it = boost::begin(cleaned);
it != boost::end(cleaned); ++it)
{
range.push_back(it->first);
}
// Close if necessary
if (geometry::closure<Range>::value == geometry::closed)
{
point_type const first = range.front();
range.push_back(first);
}
}
}} // namespace detail::overlay
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLEAN_DUPS_AND_SPIKES_HPP

View File

@ -93,7 +93,7 @@ struct copy_segments_ring
for (size_type i = 0; i < count; ++i, ++it)
{
detail::overlay::append_no_dups_or_spikes(current_output, *it);
traits::push_back<RangeOut>::apply(current_output, *it);
}
}
};

View File

@ -13,7 +13,7 @@
#include <boost/range.hpp>
#include <boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp>
#include <boost/geometry/algorithms/detail/overlay/clean_dups_and_spikes.hpp>
#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>
#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
@ -139,7 +139,7 @@ inline bool assign_next_ip(G1 const& g1, G2 const& g2,
seg_id = info.seg_id;
}
detail::overlay::append_no_dups_or_spikes(current_output, ip->point);
traits::push_back<GeometryOut>::apply(current_output, ip->point);
return true;
}
@ -391,6 +391,7 @@ public :
detail::overlay::debug_traverse(*current, *iit, "->Finished");
if (geometry::num_points(current_output) >= min_num_points)
{
clean_dups_and_spikes(current_output, rescale_policy);
rings.push_back(current_output);
}
}

View File

@ -185,9 +185,7 @@ void test_areal()
test_one<Polygon, Polygon, Polygon>("ggl_list_20110716_enrico",
ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1],
3,
if_typed<ct, double>(21, 20),
35723.8506317139);
3, 16, 35723.8506317139);
test_one<Polygon, Polygon, Polygon>("ggl_list_20131119_james",
ggl_list_20131119_james[0], ggl_list_20131119_james[1],

View File

@ -500,7 +500,7 @@ void test_all(bool test_self_tangencies = true, bool test_mixed = false)
}
test_traverse<polygon, polygon, operation_intersection>::apply("53_iet", 0, 0, case_53[0], case_53[2]);
test_traverse<polygon, polygon, operation_intersection>::apply("54_iet_iet", 1, 2, case_54[1], case_54[3]);
test_traverse<polygon, polygon, operation_intersection>::apply("54_iet_iet", 2, 2, case_54[1], case_54[3]);
if (test_self_tangencies)
{
test_traverse<polygon, polygon, operation_intersection>::apply("54_st_iet", 1, 2, case_54[0], case_54[3]);
@ -647,7 +647,7 @@ void test_all(bool test_self_tangencies = true, bool test_mixed = false)
2, 16, case_53[0], case_53[2]);
if (test_self_tangencies)
{
test_traverse<polygon, polygon, operation_union>::apply("54_st_st", 2, 20, case_54[0], case_54[2]);
test_traverse<polygon, polygon, operation_union>::apply("54_st_st", 3, 20, case_54[0], case_54[2]);
test_traverse<polygon, polygon, operation_union>::apply("54_st_iet", 2, 20, case_54[0], case_54[3]);
test_traverse<polygon, polygon, operation_union>::apply("54_iet_st", 2, 20, case_54[1], case_54[2]);
}

View File

@ -221,16 +221,11 @@ void test_areal()
test_one<Polygon, Polygon, Polygon>("ggl_list_20110627_phillip",
ggl_list_20110627_phillip[0], ggl_list_20110627_phillip[1],
1, 0,
if_typed<ct, double>(5, if_typed_tt<ct>(8, 8)),
14729.07145);
1, 0, 8, 14729.07145);
// FP might return different amount of points
test_one<Polygon, Polygon, Polygon>("ggl_list_20110716_enrico",
ggl_list_20110716_enrico[0], ggl_list_20110716_enrico[1],
1, 1,
if_typed<ct, double>(18, if_typed<ct, float>(-1, 17)),
129904.197692871);
1, 1, 15, 129904.197692871);
test_one<Polygon, Polygon, Polygon>("ggl_list_20110820_christophe",
ggl_list_20110820_christophe[0], ggl_list_20110820_christophe[1],