Added ever_circling_range_iterator (range version)

Small adaptions to get_turns

[SVN r62180]
This commit is contained in:
Barend Gehrels 2010-05-24 20:52:33 +00:00
parent 8e9dfdf3e6
commit 8b260caec8
4 changed files with 95 additions and 15 deletions

View File

@ -13,4 +13,5 @@ project
<include>../..
<toolset>gcc:<cxxflags>"-pedantic -Wall -Wstrict-aliasing -fstrict-aliasing -Wno-long-long"
<toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE # For Ublas
<dependency>/boost//headers
;

View File

@ -111,6 +111,12 @@ public :
typename geometry::range_type<Geometry2>::type const
>::type range2_iterator;
range1_iterator begin_range_1, end_range_1;
get_full_section(geometry1, sec1, begin_range_1, end_range_1);
range2_iterator begin_range_2, end_range_2;
get_full_section(geometry2, sec2, begin_range_2, end_range_2);
int const dir1 = sec1.directions[0];
int const dir2 = sec2.directions[0];
int index1 = sec1.begin_index;
@ -122,13 +128,18 @@ public :
&& sec1.ring_index == sec2.ring_index;
range1_iterator prev1, it1, end1;
range1_iterator begin_range_1, end_range_1;
ever_circling_iterator<range1_iterator> next1
= start_at_section(sec1, prev1, it1, end1, begin_range_1, end_range_1,
get_start_point_iterator(sec1, prev1, it1, end1,
index1, ndi1, geometry1, dir1, sec2.bounding_box);
// We need a circular iterator because it might run through the closing point.
// One circle is actually enough but this one is just convenient.
ever_circling_iterator<range1_iterator> next1(begin_range_1, end_range_1, it1, true);
next1++;
// Walk through section and stop if we exceed the other box
// section 2: [--------------]
// section 1: |----|---|---|---|---|
for (prev1 = it1++, next1++;
it1 != end1 && ! exceeding<0>(dir1, *prev1, sec2.bounding_box);
prev1 = it1++, index1++, next1++, ndi1++)
@ -141,11 +152,11 @@ public :
int ndi2 = sec2.non_duplicate_index;
range2_iterator prev2, it2, end2;
range2_iterator begin_range_2, end_range_2;
ever_circling_iterator<range2_iterator> next2 =
start_at_section(sec2, prev2, it2, end2, begin_range_2, end_range_2,
get_start_point_iterator(sec2, prev2, it2, end2,
index2, ndi2, geometry2, dir2, sec1.bounding_box);
ever_circling_iterator<range2_iterator> next2(begin_range_2, end_range_2, it2, true);
next2++;
for (prev2 = it2++, next2++;
it2 != end2 && ! exceeding<0>(dir2, *prev2, sec1.bounding_box);
@ -264,9 +275,8 @@ private :
// skips to the begin-point, we loose the index or have to recalculate it)
// So we mimic it here
template <typename RangeIterator, typename Section, typename Geometry, typename Box>
static inline ever_circling_iterator<RangeIterator> start_at_section(Section & section,
static inline RangeIterator get_start_point_iterator(Section & section,
RangeIterator& it, RangeIterator& prev, RangeIterator& end,
RangeIterator& begin_range_it, RangeIterator& end_range_it,
int& index, int& ndi,
Geometry const& geometry,
int dir, Box const& other_bounding_box)
@ -281,12 +291,7 @@ private :
{}
// Go back one step because we want to start completely preceding
it = prev;
get_full_section(geometry, section, begin_range_it, end_range_it);
ever_circling_iterator<RangeIterator> next(begin_range_it, end_range_it, it, true);
next++;
return next;
return it;
}
};

View File

@ -9,6 +9,7 @@
#ifndef BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
#define BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
#include <boost/range.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/iterator_categories.hpp>
@ -90,6 +91,69 @@ private:
};
template <typename Range>
class ever_circling_range_iterator
: public boost::iterator_adaptor
<
ever_circling_range_iterator<Range>,
typename boost::range_iterator<Range>::type
>
{
public :
typedef typename boost::range_iterator<Range>::type iterator_type;
explicit inline ever_circling_range_iterator(Range& range,
bool skip_first = false)
: m_range(range)
, m_skip_first(skip_first)
{
this->base_reference() = boost::begin(m_range);
}
explicit inline ever_circling_range_iterator(Range& range, iterator_type start,
bool skip_first = false)
: m_range(range)
, m_skip_first(skip_first)
{
this->base_reference() = start;
}
/// Navigate to a certain position, should be in [start .. end], if at end
/// it will circle again.
inline void moveto(iterator_type it)
{
this->base_reference() = it;
check_end();
}
private:
friend class boost::iterator_core_access;
inline void increment(bool possibly_skip = true)
{
(this->base_reference())++;
check_end(possibly_skip);
}
inline void check_end(bool possibly_skip = true)
{
if (this->base_reference() == boost::end(m_range))
{
this->base_reference() = boost::begin(m_range);
if (m_skip_first && possibly_skip)
{
increment(false);
}
}
}
Range& m_range;
bool m_skip_first;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP

View File

@ -22,7 +22,7 @@ void test_geometry(std::string const& wkt)
{
G geo;
boost::geometry::read_wkt(wkt, geo);
typedef typename boost::range_const_iterator<G>::type iterator_type;
typedef typename boost::range_iterator<G const>::type iterator_type;
// Run 3 times through the geometry
@ -64,6 +64,16 @@ void test_geometry(std::string const& wkt)
BOOST_CHECK_EQUAL(out.str(), "543215432154321");
}
// Check the range_iterator-one
{
std::ostringstream out;
boost::geometry::ever_circling_range_iterator<G> it(geo);
for (int i = 0; i < n; ++i, ++it)
{
out << boost::geometry::get<0>(*it);
}
BOOST_CHECK_EQUAL(out.str(), "123451234512345");
}
}
template <typename P>