[overlay][range] Replace the explicit call to Range::erase() with version using std::copy() and traits::resize<>

This commit is contained in:
Adam Wulkiewicz
2014-06-18 19:42:44 +02:00
parent 76a56c787c
commit 9f7828b7ec
2 changed files with 119 additions and 4 deletions

View File

@@ -15,6 +15,8 @@
#include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry
{
@@ -108,7 +110,11 @@ inline void clean_closing_dups_and_spikes(Range& range,
}
typedef typename boost::range_iterator<Range>::type iterator_type;
const bool closed = geometry::closure<Range>::value == geometry::closed;
static const bool 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
{
@@ -125,13 +131,13 @@ inline void clean_closing_dups_and_spikes(Range& range,
// considered as a spike w.r.t. the last segment)
if (point_is_spike_or_equal(*second, *ultimate, *first, robust_policy))
{
range.erase(first);
range::erase(range, first);
if (closed)
{
// Remove closing last point
traits::resize<Range>::apply(range, boost::size(range) - 1);
range::resize(range, boost::size(range) - 1);
// Add new closing point
traits::push_back<Range>::apply(range, *boost::begin(range));
range::push_back(range, *boost::begin(range));
}
found = true;
}

View File

@@ -14,6 +14,9 @@
#ifndef BOOST_GEOMETRY_UTIL_RANGE_HPP
#define BOOST_GEOMETRY_UTIL_RANGE_HPP
#include <algorithm>
#include <boost/assert.hpp>
#include <boost/concept_check.hpp>
#include <boost/range/concepts.hpp>
#include <boost/range/begin.hpp>
@@ -21,6 +24,8 @@
#include <boost/range/empty.hpp>
#include <boost/range/size.hpp>
#include <boost/geometry/core/mutable_range.hpp>
namespace boost { namespace geometry { namespace range {
// NOTE: For SinglePassRanges at could iterate over all elements until the i-th element is met.
@@ -105,6 +110,110 @@ back(BidirectionalRange & rng)
return *(--boost::end(rng));
}
/*!
\brief Short utility to conveniently clear a mutable range.
It uses traits::clear<>.
\ingroup utility
*/
template <typename Range>
inline void clear(Range & rng)
{
// NOTE: this trait is probably not needed since it could be implemented using resize()
geometry::traits::clear<Range>::apply(rng);
}
/*!
\brief Short utility to conveniently insert a new element at the end of a mutable range.
It uses boost::geometry::traits::push_back<>.
\ingroup utility
*/
template <typename Range>
inline void push_back(Range & rng,
typename boost::range_value<Range>::type const& value)
{
geometry::traits::push_back<Range>::apply(rng, value);
}
/*!
\brief Short utility to conveniently resize a mutable range.
It uses boost::geometry::traits::resize<>.
\ingroup utility
*/
template <typename Range>
inline void resize(Range & rng,
typename boost::range_size<Range>::type new_size)
{
geometry::traits::resize<Range>::apply(rng, new_size);
}
/*!
\brief Short utility to conveniently remove an element from the back of a mutable range.
It uses resize().
\ingroup utility
*/
template <typename Range>
inline void pop_back(Range & rng)
{
BOOST_ASSERT(!boost::empty(rng));
range::resize(rng, boost::size(rng) - 1);
}
/*!
\brief Short utility to conveniently remove an element from a mutable range.
It uses std::copy() and resize(). It requires mutable iterator as parameter.
\ingroup utility
*/
template <typename Range>
inline typename boost::range_iterator<Range>::type
erase(Range & rng,
typename boost::range_iterator<Range>::type it)
{
BOOST_ASSERT(!boost::empty(rng));
BOOST_ASSERT(it != boost::end(rng));
typename boost::range_iterator<Range>::type
next = it;
++next;
std::copy(next, boost::end(rng), it);
range::resize(rng, boost::size(rng) - 1);
// NOTE: assuming that resize() doesn't invalidate the iterators
return it;
}
/*!
\brief Short utility to conveniently remove a range of elements from a mutable range.
It uses std::copy() and resize(). It requires mutable iterators as parameters.
\ingroup utility
*/
template <typename Range>
inline typename boost::range_iterator<Range>::type
erase(Range & rng,
typename boost::range_iterator<Range>::type first,
typename boost::range_iterator<Range>::type last)
{
typename std::iterator_traits
<
typename boost::range_iterator<Range>::type
>::difference_type const diff = std::distance(first, last);
BOOST_ASSERT(diff >= 0);
std::size_t const count = static_cast<std::size_t>(diff);
BOOST_ASSERT(count <= boost::size(rng));
if ( count > 0 )
{
std::copy(last, boost::end(rng), first);
range::resize(rng, boost::size(rng) - count);
}
// NOTE: assuming that resize() doesn't invalidate the iterators
return first;
}
}}} // namespace boost::geometry::range
#endif // BOOST_GEOMETRY_UTIL_RANGE_HPP