From 8b260caec84ca154cc1f512aa1646bb9e21666c8 Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Mon, 24 May 2010 20:52:33 +0000 Subject: [PATCH] Added ever_circling_range_iterator (range version) Small adaptions to get_turns [SVN r62180] --- Jamroot | 1 + .../algorithms/detail/overlay/get_turns.hpp | 33 ++++++---- .../iterators/ever_circling_iterator.hpp | 64 +++++++++++++++++++ test/iterators/ever_circling_iterator.cpp | 12 +++- 4 files changed, 95 insertions(+), 15 deletions(-) diff --git a/Jamroot b/Jamroot index 317ddfd55..aa7c50324 100644 --- a/Jamroot +++ b/Jamroot @@ -13,4 +13,5 @@ project ../.. gcc:"-pedantic -Wall -Wstrict-aliasing -fstrict-aliasing -Wno-long-long" msvc:_SCL_SECURE_NO_DEPRECATE # For Ublas + /boost//headers ; diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index 582792d89..96e3789a6 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -111,6 +111,12 @@ public : typename geometry::range_type::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 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 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 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 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 - static inline ever_circling_iterator 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 next(begin_range_it, end_range_it, it, true); - next++; - return next; + return it; } }; diff --git a/include/boost/geometry/iterators/ever_circling_iterator.hpp b/include/boost/geometry/iterators/ever_circling_iterator.hpp index ddb58c471..a0d0e933a 100644 --- a/include/boost/geometry/iterators/ever_circling_iterator.hpp +++ b/include/boost/geometry/iterators/ever_circling_iterator.hpp @@ -9,6 +9,7 @@ #ifndef BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP #define BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP +#include #include #include #include @@ -90,6 +91,69 @@ private: }; + +template +class ever_circling_range_iterator + : public boost::iterator_adaptor + < + ever_circling_range_iterator, + typename boost::range_iterator::type + > +{ +public : + typedef typename boost::range_iterator::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 diff --git a/test/iterators/ever_circling_iterator.cpp b/test/iterators/ever_circling_iterator.cpp index 0da6bb011..7fb48a575 100644 --- a/test/iterators/ever_circling_iterator.cpp +++ b/test/iterators/ever_circling_iterator.cpp @@ -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::type iterator_type; + typedef typename boost::range_iterator::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 it(geo); + for (int i = 0; i < n; ++i, ++it) + { + out << boost::geometry::get<0>(*it); + } + BOOST_CHECK_EQUAL(out.str(), "123451234512345"); + } } template