1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2014, Oracle and/or its affiliates.
5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
7 // Licensed under the Boost Software License version 1.0.
8 // http://www.boost.org/users/license.html
10 #ifndef BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP
11 #define BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP
13 #include <boost/mpl/assert.hpp>
14 #include <boost/type_traits/is_convertible.hpp>
15 #include <boost/range.hpp>
17 #include <boost/geometry/core/exterior_ring.hpp>
18 #include <boost/geometry/core/interior_rings.hpp>
19 #include <boost/geometry/core/tags.hpp>
21 #include <boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp>
22 #include <boost/geometry/iterators/detail/segment_iterator/iterator_type.hpp>
24 #include <boost/geometry/iterators/dispatch/segment_iterator.hpp>
27 namespace boost { namespace geometry
31 #ifndef DOXYGEN_NO_DISPATCH
36 // specializations for segments_begin
39 template <typename Linestring>
40 struct segments_begin<Linestring, linestring_tag>
42 typedef typename detail::segment_iterator::iterator_type
47 static inline return_type apply(Linestring& linestring)
49 return return_type(linestring);
54 template <typename Ring>
55 struct segments_begin<Ring, ring_tag>
57 typedef typename detail::segment_iterator::iterator_type
62 static inline return_type apply(Ring& ring)
64 return return_type(ring);
69 template <typename Polygon>
70 struct segments_begin<Polygon, polygon_tag>
72 typedef typename detail::point_iterator::inner_range_type
77 typedef typename detail::segment_iterator::iterator_type
82 static inline return_type apply(Polygon& polygon)
84 typedef typename return_type::second_iterator_type flatten_iterator;
90 >::apply(geometry::exterior_ring(polygon)),
94 >::apply(geometry::exterior_ring(polygon)),
95 flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
96 boost::end(geometry::interior_rings(polygon))
98 flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
99 boost::end(geometry::interior_rings(polygon))
106 template <typename MultiLinestring>
107 struct segments_begin<MultiLinestring, multi_linestring_tag>
109 typedef typename detail::segment_iterator::iterator_type
114 static inline return_type apply(MultiLinestring& multilinestring)
116 return return_type(boost::begin(multilinestring),
117 boost::end(multilinestring));
122 template <typename MultiPolygon>
123 struct segments_begin<MultiPolygon, multi_polygon_tag>
125 typedef typename detail::segment_iterator::iterator_type
130 static inline return_type apply(MultiPolygon& multipolygon)
132 return return_type(boost::begin(multipolygon),
133 boost::end(multipolygon));
138 } // namespace dispatch
139 #endif // DOXYGEN_NO_DISPATCH
145 #ifndef DOXYGEN_NO_DISPATCH
150 // specializations for segments_end
153 template <typename Linestring>
154 struct segments_end<Linestring, linestring_tag>
156 typedef typename detail::segment_iterator::iterator_type
161 static inline return_type apply(Linestring& linestring)
163 return return_type(linestring, true);
168 template <typename Ring>
169 struct segments_end<Ring, ring_tag>
171 typedef typename detail::segment_iterator::iterator_type
176 static inline return_type apply(Ring& ring)
178 return return_type(ring, true);
183 template <typename Polygon>
184 struct segments_end<Polygon, polygon_tag>
186 typedef typename detail::point_iterator::inner_range_type
191 typedef typename detail::segment_iterator::iterator_type
196 static inline return_type apply(Polygon& polygon)
198 typedef typename return_type::second_iterator_type flatten_iterator;
204 >::apply(geometry::exterior_ring(polygon)),
205 flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
206 boost::end(geometry::interior_rings(polygon))
208 flatten_iterator( boost::end(geometry::interior_rings(polygon)) )
214 template <typename MultiLinestring>
215 struct segments_end<MultiLinestring, multi_linestring_tag>
217 typedef typename detail::segment_iterator::iterator_type
222 static inline return_type apply(MultiLinestring& multilinestring)
224 return return_type(boost::end(multilinestring));
229 template <typename MultiPolygon>
230 struct segments_end<MultiPolygon, multi_polygon_tag>
232 typedef typename detail::segment_iterator::iterator_type
237 static inline return_type apply(MultiPolygon& multipolygon)
239 return return_type(boost::end(multipolygon));
244 } // namespace dispatch
245 #endif // DOXYGEN_NO_DISPATCH
248 // MK:: need to add doc here
249 template <typename Geometry>
250 class segment_iterator
251 : public detail::segment_iterator::iterator_type<Geometry>::type
254 typedef typename detail::segment_iterator::iterator_type
259 inline base const* base_ptr() const
264 template <typename OtherGeometry> friend class segment_iterator;
266 template <typename G>
267 friend inline segment_iterator<G const> segments_begin(G const&);
269 template <typename G>
270 friend inline segment_iterator<G const> segments_end(G const&);
272 inline segment_iterator(base const& base_it) : base(base_it) {}
275 // The following typedef is needed for this iterator to be
277 // Normally we would not have to define this. However, due to the
278 // fact that the value type of the iterator is not a reference,
279 // the iterator_facade framework (used to define the base class of
280 // this iterator) degrades automatically the iterator's category
281 // to input iterator. With the following typedef we recover the
282 // correct iterator category.
283 typedef std::bidirectional_iterator_tag iterator_category;
285 inline segment_iterator() {}
287 template <typename OtherGeometry>
288 inline segment_iterator(segment_iterator<OtherGeometry> const& other)
289 : base(*other.base_ptr())
291 static const bool is_conv
292 = boost::is_convertible<
293 typename detail::segment_iterator::iterator_type
297 typename detail::segment_iterator::iterator_type<Geometry>::type
300 BOOST_MPL_ASSERT_MSG((is_conv),
302 (segment_iterator<OtherGeometry>));
305 inline segment_iterator& operator++() // prefix
311 inline segment_iterator& operator--() // prefix
317 inline segment_iterator operator++(int) // postfix
319 segment_iterator copy(*this);
324 inline segment_iterator operator--(int) // postfix
326 segment_iterator copy(*this);
333 // MK:: need to add doc here
334 template <typename Geometry>
335 inline segment_iterator<Geometry const>
336 segments_begin(Geometry const& geometry)
338 return dispatch::segments_begin<Geometry const>::apply(geometry);
342 // MK:: need to add doc here
343 template <typename Geometry>
344 inline segment_iterator<Geometry const>
345 segments_end(Geometry const& geometry)
347 return dispatch::segments_end<Geometry const>::apply(geometry);
351 }} // namespace boost::geometry
353 #endif // BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP