1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
14 #ifndef BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
15 #define BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
17 #include <boost/range.hpp>
18 #include <boost/iterator.hpp>
19 #include <boost/iterator/iterator_adaptor.hpp>
20 #include <boost/iterator/iterator_categories.hpp>
22 #include <boost/geometry/iterators/base.hpp>
24 namespace boost { namespace geometry
28 \brief Iterator which ever circles through a range
29 \tparam Iterator iterator on which this class is based on
31 \details If the iterator arrives at range.end() it restarts from the
32 beginning. So it has to be stopped in another way.
33 Don't call for(....; it++) because it will turn in an endless loop
34 \note Name inspired on David Bowie's
35 "Chant Of The Ever Circling Skeletal Family"
37 template <typename Iterator>
38 struct ever_circling_iterator :
39 public detail::iterators::iterator_base
41 ever_circling_iterator<Iterator>,
45 friend class boost::iterator_core_access;
47 explicit inline ever_circling_iterator(Iterator begin, Iterator end,
48 bool skip_first = false)
51 , m_skip_first(skip_first)
53 this->base_reference() = begin;
56 explicit inline ever_circling_iterator(Iterator begin, Iterator end, Iterator start,
57 bool skip_first = false)
60 , m_skip_first(skip_first)
62 this->base_reference() = start;
65 /// Navigate to a certain position, should be in [start .. end], if at end
66 /// it will circle again.
67 inline void moveto(Iterator it)
69 this->base_reference() = it;
75 inline void increment(bool possibly_skip = true)
77 (this->base_reference())++;
78 check_end(possibly_skip);
81 inline void check_end(bool possibly_skip = true)
83 if (this->base() == this->m_end)
85 this->base_reference() = this->m_begin;
86 if (m_skip_first && possibly_skip)
98 template <typename Range>
99 struct ever_circling_range_iterator
100 : public boost::iterator_facade
102 ever_circling_range_iterator<Range>,
103 typename boost::range_value<Range>::type const,
104 boost::random_access_traversal_tag
107 /// Constructor including the range it is based on
108 explicit inline ever_circling_range_iterator(Range& range)
110 , m_iterator(boost::begin(range))
111 , m_size(boost::size(range))
115 /// Default constructor
116 explicit inline ever_circling_range_iterator()
122 typedef std::ptrdiff_t difference_type;
125 friend class boost::iterator_core_access;
127 inline typename boost::range_value<Range>::type const& dereference() const
132 inline difference_type distance_to(ever_circling_range_iterator<Range> const& other) const
134 return other.m_index - this->m_index;
137 inline bool equal(ever_circling_range_iterator<Range> const& other) const
139 return this->m_range == other.m_range
140 && this->m_index == other.m_index;
143 inline void increment()
146 if (m_index >= 0 && m_index < m_size)
156 inline void decrement()
159 if (m_index >= 0 && m_index < m_size)
169 inline void advance(difference_type n)
171 if (m_index >= 0 && m_index < m_size
172 && m_index + n >= 0 && m_index + n < m_size)
184 inline void update_iterator()
190 m_index = m_index % m_size;
191 this->m_iterator = boost::begin(*m_range) + m_index;
195 typename boost::range_iterator<Range>::type m_iterator;
196 difference_type m_size;
197 difference_type m_index;
201 }} // namespace boost::geometry
203 #endif // BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP