diff --git a/include/boost/geometry/iterators/base.hpp b/include/boost/geometry/iterators/base.hpp new file mode 100644 index 000000000..fb18f1436 --- /dev/null +++ b/include/boost/geometry/iterators/base.hpp @@ -0,0 +1,70 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_ITERATORS_BASE_HPP +#define BOOST_GEOMETRY_ITERATORS_BASE_HPP + +#include +#include +#include +#include + +#ifndef DOXYGEN_NO_DETAIL +namespace boost { namespace geometry { namespace detail { namespace iterators +{ + +template +< + typename DerivedClass, + typename Iterator, + typename TraversalFlag = boost::bidirectional_traversal_tag +> +struct iterator_base + : public boost::iterator_adaptor + < + DerivedClass, + Iterator, + boost::use_default, + typename boost::mpl::if_ + < + boost::is_convertible + < + typename boost::iterator_traversal::type, + boost::random_access_traversal_tag + >, + TraversalFlag, + boost::use_default + >::type + > +{ + // Define operator cast to Iterator to be able to write things like Iterator it = myit++ + inline operator Iterator() const + { + return this->base(); + } + + /*inline bool operator==(Iterator const& other) const + { + return this->base() == other; + } + inline bool operator!=(Iterator const& other) const + { + return ! operator==(other); + }*/ +}; + +}}}} // namespace boost::geometry::detail::iterators +#endif + + +#endif // BOOST_GEOMETRY_ITERATORS_BASE_HPP diff --git a/include/boost/geometry/iterators/box_iterator.hpp b/include/boost/geometry/iterators/box_iterator.hpp new file mode 100644 index 000000000..d9fa8fae8 --- /dev/null +++ b/include/boost/geometry/iterators/box_iterator.hpp @@ -0,0 +1,113 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_BOX_ITERATOR_HPP +#define BOOST_GEOMETRY_BOX_ITERATOR_HPP + +#include +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +/*! + \brief Iterator which adapts a box (four points + closing) as iterator + \tparam Box box type on which this iterator is based on + \note It is always const. We cannot dereference something non-const + (at least not without doing tricks as returning assignables) + \ingroup iterators +*/ +template +struct box_iterator + : public boost::iterator_facade + < + box_iterator, + typename point_type::type const, + boost::random_access_traversal_tag + > +{ + explicit inline box_iterator(Box const& box) + : m_index(0) + , m_box_address(&box) + { + init(box); + } + + // Constructor to indicate the end of a box + explicit inline box_iterator(Box const& box, bool) + : m_index(5) + , m_box_address(&box) + { + init(box); + } + + typedef std::ptrdiff_t difference_type; + +private: + friend class boost::iterator_core_access; + typedef typename point_type::type point_type; + + inline point_type const& dereference() const + { + if (m_index >= 0 && m_index <= 3) + { + return m_points[m_index]; + } + // If it index is 4, or other, return first point + return m_points[0]; + } + + inline bool equal(box_iterator const& other) const + { + return m_box_address == this->m_box_address + && other.m_index == this->m_index; + } + + inline void increment() + { + m_index++; + } + + inline void decrement() + { + m_index--; + } + + inline difference_type distance_to(box_iterator const& other) const + { + return other.m_index - this->m_index; + } + + inline void init(Box const& box) + { + // asb -> lower_left, lower_right, upper_left, upper_right + // we want: clockwise + assign_box_corners(box, m_points[0], m_points[3], m_points[1], m_points[2]); + } + + // Copy points here - box might define them otherwise + point_type m_points[4]; + int m_index; + Box const* const m_box_address; +}; + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_BOX_ITERATOR_HPP diff --git a/include/boost/geometry/iterators/circular_iterator.hpp b/include/boost/geometry/iterators/circular_iterator.hpp new file mode 100644 index 000000000..390c2d9a9 --- /dev/null +++ b/include/boost/geometry/iterators/circular_iterator.hpp @@ -0,0 +1,121 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_ITERATORS_CIRCULAR_ITERATOR_HPP +#define BOOST_GEOMETRY_ITERATORS_CIRCULAR_ITERATOR_HPP + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + +/*! + \brief Iterator which goes circular through a range, starting at a point, ending at that point + \tparam Iterator iterator on which this class is based on + \ingroup iterators +*/ +template +struct circular_iterator : + public detail::iterators::iterator_base + < + circular_iterator, + Iterator + > +{ + friend class boost::iterator_core_access; + + explicit inline circular_iterator(Iterator begin, Iterator end, Iterator start) + : m_begin(begin) + , m_end(end) + , m_start(start) + { + this->base_reference() = start; + } + + // Constructor to indicate the end of a range, to enable e.g. std::copy + explicit inline circular_iterator(Iterator end) + : m_begin(end) + , m_end(end) + , m_start(end) + { + this->base_reference() = end; + } + + /// Navigate to a certain position, should be in [start .. end], it at end + /// it will circle again. + inline void moveto(Iterator it) + { + this->base_reference() = it; + check_end(); + } + +private: + + inline void increment() + { + if (this->base() != m_end) + { + (this->base_reference())++; + check_end(); + } + } + inline void decrement() + { + if (this->base() != m_end) + { + // If at begin, go back to end (assumed this is possible...) + if (this->base() == m_begin) + { + this->base_reference() = this->m_end; + } + + // Decrement + (this->base_reference())--; + + // If really back at start, go to end == end of iteration + if (this->base() == m_start) + { + this->base_reference() = this->m_end; + } + } + } + + + inline void check_end() + { + if (this->base() == this->m_end) + { + this->base_reference() = this->m_begin; + } + + if (this->base() == m_start) + { + this->base_reference() = this->m_end; + } + } + + Iterator m_begin; + Iterator m_end; + Iterator m_start; +}; + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ITERATORS_CIRCULAR_ITERATOR_HPP diff --git a/include/boost/geometry/iterators/closing_iterator.hpp b/include/boost/geometry/iterators/closing_iterator.hpp new file mode 100644 index 000000000..501ff8ab4 --- /dev/null +++ b/include/boost/geometry/iterators/closing_iterator.hpp @@ -0,0 +1,157 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_ITERATORS_CLOSING_ITERATOR_HPP +#define BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP + +#include +#include +#include +#include + + + +namespace boost { namespace geometry +{ + +/*! +\brief Iterator which iterates through a range, but adds first element at end of the range +\tparam Range range on which this class is based on +\ingroup iterators +\note Use with "closing_iterator or "closing_iterator + to get non-const / const behaviour +\note This class is normally used from "closeable_view" if Close==true +*/ +template +struct closing_iterator + : public boost::iterator_facade + < + closing_iterator, + typename boost::range_value::type const, + boost::random_access_traversal_tag + > +{ + /// Constructor including the range it is based on + explicit inline closing_iterator(Range& range) + : m_range(&range) + , m_iterator(boost::begin(range)) + , m_end(boost::end(range)) + , m_size(boost::size(range)) + , m_index(0) + {} + + /// Constructor to indicate the end of a range + explicit inline closing_iterator(Range& range, bool) + : m_range(&range) + , m_iterator(boost::end(range)) + , m_end(boost::end(range)) + , m_size(boost::size(range)) + , m_index(m_size + 1) + {} + + /// Default constructor + explicit inline closing_iterator() + : m_range(NULL) + , m_size(0) + , m_index(0) + {} + + inline closing_iterator& operator=(closing_iterator const& source) + { + m_range = source.m_range; + m_iterator = source.m_iterator; + m_end = source.m_end; + m_size = source.m_size; + m_index = source.m_index; + return *this; + } + + typedef std::ptrdiff_t difference_type; + +private: + friend class boost::iterator_core_access; + + inline typename boost::range_value::type const& dereference() const + { + return *m_iterator; + } + + inline difference_type distance_to(closing_iterator const& other) const + { + return other.m_index - this->m_index; + } + + inline bool equal(closing_iterator const& other) const + { + return this->m_range == other.m_range + && this->m_index == other.m_index; + } + + inline void increment() + { + if (++m_index < m_size) + { + ++m_iterator; + } + else + { + update_iterator(); + } + } + + inline void decrement() + { + if (m_index-- < m_size) + { + --m_iterator; + } + else + { + update_iterator(); + } + } + + inline void advance(difference_type n) + { + if (m_index < m_size && m_index + n < m_size) + { + m_index += n; + m_iterator += n; + } + else + { + m_index += n; + update_iterator(); + } + } + + inline void update_iterator() + { + this->m_iterator = m_index <= m_size + ? boost::begin(*m_range) + (m_index % m_size) + : boost::end(*m_range) + ; + } + + Range* m_range; + typename boost::range_iterator::type m_iterator; + typename boost::range_iterator::type m_end; + difference_type m_size; + difference_type m_index; +}; + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP diff --git a/include/boost/geometry/iterators/ever_circling_iterator.hpp b/include/boost/geometry/iterators/ever_circling_iterator.hpp new file mode 100644 index 000000000..cd89f06d8 --- /dev/null +++ b/include/boost/geometry/iterators/ever_circling_iterator.hpp @@ -0,0 +1,164 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_ITERATORS_EVER_CIRCLING_ITERATOR_HPP +#define BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP + +#include +#include +#include +#include + +#include + +namespace boost { namespace geometry +{ + +/*! + \brief Iterator which ever circles through a range + \tparam Iterator iterator on which this class is based on + \ingroup iterators + \details If the iterator arrives at range.end() it restarts from the + beginning. So it has to be stopped in another way. + Don't call for(....; it++) because it will turn in an endless loop + \note Name inspired on David Bowie's + "Chant Of The Ever Circling Skeletal Family" +*/ +template +struct ever_circling_iterator : + public detail::iterators::iterator_base + < + ever_circling_iterator, + Iterator + > +{ + friend class boost::iterator_core_access; + + explicit inline ever_circling_iterator(Iterator begin, Iterator end, + bool skip_first = false) + : m_begin(begin) + , m_end(end) + , m_skip_first(skip_first) + { + this->base_reference() = begin; + } + + explicit inline ever_circling_iterator(Iterator begin, Iterator end, Iterator start, + bool skip_first = false) + : m_begin(begin) + , m_end(end) + , 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 it) + { + this->base_reference() = it; + check_end(); + } + +private: + + 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() == this->m_end) + { + this->base_reference() = this->m_begin; + if (m_skip_first && possibly_skip) + { + increment(false); + } + } + } + + Iterator m_begin; + Iterator m_end; + bool m_skip_first; +}; + + + +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/include/boost/geometry/iterators/range_type.hpp b/include/boost/geometry/iterators/range_type.hpp new file mode 100644 index 000000000..6fb6c1ad6 --- /dev/null +++ b/include/boost/geometry/iterators/range_type.hpp @@ -0,0 +1,89 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_ITERATORS_RANGE_TYPE_HPP +#define BOOST_GEOMETRY_ITERATORS_RANGE_TYPE_HPP + + +#include + +#include +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + + +template +struct range_type +{ + // Even if it is not recognized, define itself as a type. + // This enables calling range_type over any range + // (not necessarily a geometry) + + // Furthermore, applicable for ring/linestring + typedef Geometry type; +}; + + +template +struct range_type +{ + typedef void type; +}; + + +template +struct range_type +{ + typedef typename ring_type::type type; +}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + + +/*! +\brief Meta-function defining a type which is a boost-range. +\details +- For linestrings and rings, it defines the type itself. +- For polygons it defines the ring type. +- For multi-points, it defines the type itself +- For multi-polygons and multi-linestrings, it defines the single-version + (so in the end the linestring and ring-type-of-multi-polygon) +\ingroup iterators +*/ +template +struct range_type +{ + typedef typename dispatch::range_type + < + typename tag::type, + Geometry + >::type type; +}; + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ITERATORS_RANGE_TYPE_HPP diff --git a/include/boost/geometry/iterators/segment_range_iterator.hpp b/include/boost/geometry/iterators/segment_range_iterator.hpp new file mode 100644 index 000000000..0eaa7300a --- /dev/null +++ b/include/boost/geometry/iterators/segment_range_iterator.hpp @@ -0,0 +1,134 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2011 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2011 Mateusz Loskot, London, UK. + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, 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_SEGMENT_RANGE_ITERATOR_HPP +#define BOOST_GEOMETRY_SEGMENT_RANGE_ITERATOR_HPP + +#include + +#include +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + +/*! + \brief Iterator which adapts a segment (two points) as iterator + \tparam Segment segment type on which this iterator is based on + \note It is always const. We cannot dereference something non-const + (at least not without doing tricks as returning assignables) + \ingroup iterators +*/ +template +struct segment_range_iterator + : public boost::iterator_facade + < + segment_range_iterator, + typename point_type::type const, + boost::random_access_traversal_tag + > +{ + // Default constructor is required to check concept of Range + // (used in checking linestring/ring concepts) + inline segment_range_iterator() + : m_index(-1) + , m_segment_address(NULL) + { + } + + // Operator= is required to check concept of Range + inline segment_range_iterator& operator=(segment_range_iterator const& source) + { + m_index = source.m_index; + m_segment_address = source.m_segment_address; + return *this; + } + + + explicit inline segment_range_iterator(Segment const& segment) + : m_index(0) + , m_segment_address(&segment) + { + init(segment); + } + + // Constructor to indicate the end of a segment + explicit inline segment_range_iterator(Segment const& segment, bool) + : m_index(2) + , m_segment_address(&segment) + { + init(segment); + } + + typedef std::ptrdiff_t difference_type; + +private: + friend class boost::iterator_core_access; + typedef typename point_type::type point_type; + + inline point_type const& dereference() const + { + if (m_index >= 0 && m_index <= 1) + { + return m_points[m_index]; + } + + BOOST_ASSERT(!"Should not occur"); // Probably throw here. + return m_points[0]; + } + + inline bool equal(segment_range_iterator const& other) const + { + return m_segment_address == this->m_segment_address + && other.m_index == this->m_index; + } + + inline void increment() + { + m_index++; + } + + inline void decrement() + { + m_index--; + } + + inline difference_type distance_to(segment_range_iterator const& other) const + { + return other.m_index - this->m_index; + } + + inline void init(Segment const& segment) + { + assign_point_from_index<0>(segment, m_points[0]); + assign_point_from_index<1>(segment, m_points[1]); + } + + // We HAVE TO copy the points, because a segment does not need + // to consist of two points, + // and we are expected to return a point here + point_type m_points[2]; + int m_index; + Segment const* m_segment_address; +}; + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_SEGMENT_RANGE_ITERATOR_HPP