1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2014-2021, Oracle and/or its affiliates.
4 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
5 // Contributed and/or modified by Adam Wulkiewicz, 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
14 #include <type_traits>
16 #include <boost/range/begin.hpp>
17 #include <boost/range/end.hpp>
19 #include <boost/geometry/core/exterior_ring.hpp>
20 #include <boost/geometry/core/interior_rings.hpp>
21 #include <boost/geometry/core/tags.hpp>
23 #include <boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp>
24 #include <boost/geometry/iterators/detail/segment_iterator/iterator_type.hpp>
26 #include <boost/geometry/iterators/dispatch/segment_iterator.hpp>
29 namespace boost { namespace geometry
33 #ifndef DOXYGEN_NO_DISPATCH
38 // specializations for segments_begin
41 template <typename Linestring>
42 struct segments_begin<Linestring, linestring_tag>
44 typedef typename detail::segment_iterator::iterator_type
49 static inline return_type apply(Linestring& linestring)
51 return return_type(linestring);
56 template <typename Ring>
57 struct segments_begin<Ring, ring_tag>
59 typedef typename detail::segment_iterator::iterator_type
64 static inline return_type apply(Ring& ring)
66 return return_type(ring);
71 template <typename Polygon>
72 struct segments_begin<Polygon, polygon_tag>
74 typedef typename detail::point_iterator::inner_range_type
79 typedef typename detail::segment_iterator::iterator_type
84 static inline return_type apply(Polygon& polygon)
86 typedef typename return_type::second_iterator_type flatten_iterator;
92 >::apply(geometry::exterior_ring(polygon)),
96 >::apply(geometry::exterior_ring(polygon)),
97 flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
98 boost::end(geometry::interior_rings(polygon))
100 flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
101 boost::end(geometry::interior_rings(polygon))
108 template <typename MultiLinestring>
109 struct segments_begin<MultiLinestring, multi_linestring_tag>
111 typedef typename detail::segment_iterator::iterator_type
116 static inline return_type apply(MultiLinestring& multilinestring)
118 return return_type(boost::begin(multilinestring),
119 boost::end(multilinestring));
124 template <typename MultiPolygon>
125 struct segments_begin<MultiPolygon, multi_polygon_tag>
127 typedef typename detail::segment_iterator::iterator_type
132 static inline return_type apply(MultiPolygon& multipolygon)
134 return return_type(boost::begin(multipolygon),
135 boost::end(multipolygon));
140 } // namespace dispatch
141 #endif // DOXYGEN_NO_DISPATCH
147 #ifndef DOXYGEN_NO_DISPATCH
152 // specializations for segments_end
155 template <typename Linestring>
156 struct segments_end<Linestring, linestring_tag>
158 typedef typename detail::segment_iterator::iterator_type
163 static inline return_type apply(Linestring& linestring)
165 return return_type(linestring, true);
170 template <typename Ring>
171 struct segments_end<Ring, ring_tag>
173 typedef typename detail::segment_iterator::iterator_type
178 static inline return_type apply(Ring& ring)
180 return return_type(ring, true);
185 template <typename Polygon>
186 struct segments_end<Polygon, polygon_tag>
188 typedef typename detail::point_iterator::inner_range_type
193 typedef typename detail::segment_iterator::iterator_type
198 static inline return_type apply(Polygon& polygon)
200 typedef typename return_type::second_iterator_type flatten_iterator;
206 >::apply(geometry::exterior_ring(polygon)),
207 flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
208 boost::end(geometry::interior_rings(polygon))
210 flatten_iterator( boost::end(geometry::interior_rings(polygon)) )
216 template <typename MultiLinestring>
217 struct segments_end<MultiLinestring, multi_linestring_tag>
219 typedef typename detail::segment_iterator::iterator_type
224 static inline return_type apply(MultiLinestring& multilinestring)
226 return return_type(boost::end(multilinestring));
231 template <typename MultiPolygon>
232 struct segments_end<MultiPolygon, multi_polygon_tag>
234 typedef typename detail::segment_iterator::iterator_type
239 static inline return_type apply(MultiPolygon& multipolygon)
241 return return_type(boost::end(multipolygon));
246 } // namespace dispatch
247 #endif // DOXYGEN_NO_DISPATCH
250 // MK:: need to add doc here
251 template <typename Geometry>
252 class segment_iterator
253 : public detail::segment_iterator::iterator_type<Geometry>::type
256 typedef typename detail::segment_iterator::iterator_type
261 inline base const* base_ptr() const
266 template <typename OtherGeometry> friend class segment_iterator;
268 template <typename G>
269 friend inline segment_iterator<G const> segments_begin(G const&);
271 template <typename G>
272 friend inline segment_iterator<G const> segments_end(G const&);
274 inline segment_iterator(base const& base_it) : base(base_it) {}
277 // The following typedef is needed for this iterator to be
279 // Normally we would not have to define this. However, due to the
280 // fact that the value type of the iterator is not a reference,
281 // the iterator_facade framework (used to define the base class of
282 // this iterator) degrades automatically the iterator's category
283 // to input iterator. With the following typedef we recover the
284 // correct iterator category.
285 typedef std::bidirectional_iterator_tag iterator_category;
287 inline segment_iterator() = default;
291 typename OtherGeometry,
296 typename detail::segment_iterator::iterator_type<OtherGeometry>::type,
297 typename detail::segment_iterator::iterator_type<Geometry>::type
302 inline segment_iterator(segment_iterator<OtherGeometry> const& other)
303 : base(*other.base_ptr())
306 inline segment_iterator& operator++() // prefix
312 inline segment_iterator& operator--() // prefix
318 inline segment_iterator operator++(int) // postfix
320 segment_iterator copy(*this);
325 inline segment_iterator operator--(int) // postfix
327 segment_iterator copy(*this);
334 // MK:: need to add doc here
335 template <typename Geometry>
336 inline segment_iterator<Geometry const>
337 segments_begin(Geometry const& geometry)
339 return dispatch::segments_begin<Geometry const>::apply(geometry);
343 // MK:: need to add doc here
344 template <typename Geometry>
345 inline segment_iterator<Geometry const>
346 segments_end(Geometry const& geometry)
348 return dispatch::segments_end<Geometry const>::apply(geometry);
352 }} // namespace boost::geometry
354 #endif // BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP