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