EVOLUTION-MANAGER
Edit File: segment_iterator.hpp
// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2014, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Licensed under the Boost Software License version 1.0. // http://www.boost.org/users/license.html #ifndef BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP #define BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP #include <boost/mpl/assert.hpp> #include <boost/type_traits/is_convertible.hpp> #include <boost/range.hpp> #include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/interior_rings.hpp> #include <boost/geometry/core/tags.hpp> #include <boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp> #include <boost/geometry/iterators/detail/segment_iterator/iterator_type.hpp> #include <boost/geometry/iterators/dispatch/segment_iterator.hpp> namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { // specializations for segments_begin template <typename Linestring> struct segments_begin<Linestring, linestring_tag> { typedef typename detail::segment_iterator::iterator_type < Linestring >::type return_type; static inline return_type apply(Linestring& linestring) { return return_type(linestring); } }; template <typename Ring> struct segments_begin<Ring, ring_tag> { typedef typename detail::segment_iterator::iterator_type < Ring >::type return_type; static inline return_type apply(Ring& ring) { return return_type(ring); } }; template <typename Polygon> struct segments_begin<Polygon, polygon_tag> { typedef typename detail::point_iterator::inner_range_type < Polygon >::type inner_range; typedef typename detail::segment_iterator::iterator_type < Polygon >::type return_type; static inline return_type apply(Polygon& polygon) { typedef typename return_type::second_iterator_type flatten_iterator; return return_type (segments_begin < inner_range >::apply(geometry::exterior_ring(polygon)), segments_end < inner_range >::apply(geometry::exterior_ring(polygon)), flatten_iterator(boost::begin(geometry::interior_rings(polygon)), boost::end(geometry::interior_rings(polygon)) ), flatten_iterator(boost::begin(geometry::interior_rings(polygon)), boost::end(geometry::interior_rings(polygon)) ) ); } }; template <typename MultiLinestring> struct segments_begin<MultiLinestring, multi_linestring_tag> { typedef typename detail::segment_iterator::iterator_type < MultiLinestring >::type return_type; static inline return_type apply(MultiLinestring& multilinestring) { return return_type(boost::begin(multilinestring), boost::end(multilinestring)); } }; template <typename MultiPolygon> struct segments_begin<MultiPolygon, multi_polygon_tag> { typedef typename detail::segment_iterator::iterator_type < MultiPolygon >::type return_type; static inline return_type apply(MultiPolygon& multipolygon) { return return_type(boost::begin(multipolygon), boost::end(multipolygon)); } }; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { // specializations for segments_end template <typename Linestring> struct segments_end<Linestring, linestring_tag> { typedef typename detail::segment_iterator::iterator_type < Linestring >::type return_type; static inline return_type apply(Linestring& linestring) { return return_type(linestring, true); } }; template <typename Ring> struct segments_end<Ring, ring_tag> { typedef typename detail::segment_iterator::iterator_type < Ring >::type return_type; static inline return_type apply(Ring& ring) { return return_type(ring, true); } }; template <typename Polygon> struct segments_end<Polygon, polygon_tag> { typedef typename detail::point_iterator::inner_range_type < Polygon >::type inner_range; typedef typename detail::segment_iterator::iterator_type < Polygon >::type return_type; static inline return_type apply(Polygon& polygon) { typedef typename return_type::second_iterator_type flatten_iterator; return return_type (segments_end < inner_range >::apply(geometry::exterior_ring(polygon)), flatten_iterator(boost::begin(geometry::interior_rings(polygon)), boost::end(geometry::interior_rings(polygon)) ), flatten_iterator( boost::end(geometry::interior_rings(polygon)) ) ); } }; template <typename MultiLinestring> struct segments_end<MultiLinestring, multi_linestring_tag> { typedef typename detail::segment_iterator::iterator_type < MultiLinestring >::type return_type; static inline return_type apply(MultiLinestring& multilinestring) { return return_type(boost::end(multilinestring)); } }; template <typename MultiPolygon> struct segments_end<MultiPolygon, multi_polygon_tag> { typedef typename detail::segment_iterator::iterator_type < MultiPolygon >::type return_type; static inline return_type apply(MultiPolygon& multipolygon) { return return_type(boost::end(multipolygon)); } }; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH // MK:: need to add doc here template <typename Geometry> class segment_iterator : public detail::segment_iterator::iterator_type<Geometry>::type { private: typedef typename detail::segment_iterator::iterator_type < Geometry >::type base; inline base const* base_ptr() const { return this; } template <typename OtherGeometry> friend class segment_iterator; template <typename G> friend inline segment_iterator<G const> segments_begin(G const&); template <typename G> friend inline segment_iterator<G const> segments_end(G const&); inline segment_iterator(base const& base_it) : base(base_it) {} public: // The following typedef is needed for this iterator to be // bidirectional. // Normally we would not have to define this. However, due to the // fact that the value type of the iterator is not a reference, // the iterator_facade framework (used to define the base class of // this iterator) degrades automatically the iterator's category // to input iterator. With the following typedef we recover the // correct iterator category. typedef std::bidirectional_iterator_tag iterator_category; inline segment_iterator() {} template <typename OtherGeometry> inline segment_iterator(segment_iterator<OtherGeometry> const& other) : base(*other.base_ptr()) { static const bool is_conv = boost::is_convertible< typename detail::segment_iterator::iterator_type < OtherGeometry >::type, typename detail::segment_iterator::iterator_type<Geometry>::type >::value; BOOST_MPL_ASSERT_MSG((is_conv), NOT_CONVERTIBLE, (segment_iterator<OtherGeometry>)); } inline segment_iterator& operator++() // prefix { base::operator++(); return *this; } inline segment_iterator& operator--() // prefix { base::operator--(); return *this; } inline segment_iterator operator++(int) // postfix { segment_iterator copy(*this); base::operator++(); return copy; } inline segment_iterator operator--(int) // postfix { segment_iterator copy(*this); base::operator--(); return copy; } }; // MK:: need to add doc here template <typename Geometry> inline segment_iterator<Geometry const> segments_begin(Geometry const& geometry) { return dispatch::segments_begin<Geometry const>::apply(geometry); } // MK:: need to add doc here template <typename Geometry> inline segment_iterator<Geometry const> segments_end(Geometry const& geometry) { return dispatch::segments_end<Geometry const>::apply(geometry); } }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP