segment_iterator.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2014-2021, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  4. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  5. // Licensed under the Boost Software License version 1.0.
  6. // http://www.boost.org/users/license.html
  7. #ifndef BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP
  8. #define BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP
  9. #include <type_traits>
  10. #include <boost/range/begin.hpp>
  11. #include <boost/range/end.hpp>
  12. #include <boost/geometry/core/exterior_ring.hpp>
  13. #include <boost/geometry/core/interior_rings.hpp>
  14. #include <boost/geometry/core/tags.hpp>
  15. #include <boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp>
  16. #include <boost/geometry/iterators/detail/segment_iterator/iterator_type.hpp>
  17. #include <boost/geometry/iterators/dispatch/segment_iterator.hpp>
  18. namespace boost { namespace geometry
  19. {
  20. #ifndef DOXYGEN_NO_DISPATCH
  21. namespace dispatch
  22. {
  23. // specializations for segments_begin
  24. template <typename Linestring>
  25. struct segments_begin<Linestring, linestring_tag>
  26. {
  27. typedef typename detail::segment_iterator::iterator_type
  28. <
  29. Linestring
  30. >::type return_type;
  31. static inline return_type apply(Linestring& linestring)
  32. {
  33. return return_type(linestring);
  34. }
  35. };
  36. template <typename Ring>
  37. struct segments_begin<Ring, ring_tag>
  38. {
  39. typedef typename detail::segment_iterator::iterator_type
  40. <
  41. Ring
  42. >::type return_type;
  43. static inline return_type apply(Ring& ring)
  44. {
  45. return return_type(ring);
  46. }
  47. };
  48. template <typename Polygon>
  49. struct segments_begin<Polygon, polygon_tag>
  50. {
  51. typedef typename detail::point_iterator::inner_range_type
  52. <
  53. Polygon
  54. >::type inner_range;
  55. typedef typename detail::segment_iterator::iterator_type
  56. <
  57. Polygon
  58. >::type return_type;
  59. static inline return_type apply(Polygon& polygon)
  60. {
  61. typedef typename return_type::second_iterator_type flatten_iterator;
  62. return return_type
  63. (segments_begin
  64. <
  65. inner_range
  66. >::apply(geometry::exterior_ring(polygon)),
  67. segments_end
  68. <
  69. inner_range
  70. >::apply(geometry::exterior_ring(polygon)),
  71. flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
  72. boost::end(geometry::interior_rings(polygon))
  73. ),
  74. flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
  75. boost::end(geometry::interior_rings(polygon))
  76. )
  77. );
  78. }
  79. };
  80. template <typename MultiLinestring>
  81. struct segments_begin<MultiLinestring, multi_linestring_tag>
  82. {
  83. typedef typename detail::segment_iterator::iterator_type
  84. <
  85. MultiLinestring
  86. >::type return_type;
  87. static inline return_type apply(MultiLinestring& multilinestring)
  88. {
  89. return return_type(boost::begin(multilinestring),
  90. boost::end(multilinestring));
  91. }
  92. };
  93. template <typename MultiPolygon>
  94. struct segments_begin<MultiPolygon, multi_polygon_tag>
  95. {
  96. typedef typename detail::segment_iterator::iterator_type
  97. <
  98. MultiPolygon
  99. >::type return_type;
  100. static inline return_type apply(MultiPolygon& multipolygon)
  101. {
  102. return return_type(boost::begin(multipolygon),
  103. boost::end(multipolygon));
  104. }
  105. };
  106. } // namespace dispatch
  107. #endif // DOXYGEN_NO_DISPATCH
  108. #ifndef DOXYGEN_NO_DISPATCH
  109. namespace dispatch
  110. {
  111. // specializations for segments_end
  112. template <typename Linestring>
  113. struct segments_end<Linestring, linestring_tag>
  114. {
  115. typedef typename detail::segment_iterator::iterator_type
  116. <
  117. Linestring
  118. >::type return_type;
  119. static inline return_type apply(Linestring& linestring)
  120. {
  121. return return_type(linestring, true);
  122. }
  123. };
  124. template <typename Ring>
  125. struct segments_end<Ring, ring_tag>
  126. {
  127. typedef typename detail::segment_iterator::iterator_type
  128. <
  129. Ring
  130. >::type return_type;
  131. static inline return_type apply(Ring& ring)
  132. {
  133. return return_type(ring, true);
  134. }
  135. };
  136. template <typename Polygon>
  137. struct segments_end<Polygon, polygon_tag>
  138. {
  139. typedef typename detail::point_iterator::inner_range_type
  140. <
  141. Polygon
  142. >::type inner_range;
  143. typedef typename detail::segment_iterator::iterator_type
  144. <
  145. Polygon
  146. >::type return_type;
  147. static inline return_type apply(Polygon& polygon)
  148. {
  149. typedef typename return_type::second_iterator_type flatten_iterator;
  150. return return_type
  151. (segments_end
  152. <
  153. inner_range
  154. >::apply(geometry::exterior_ring(polygon)),
  155. flatten_iterator(boost::begin(geometry::interior_rings(polygon)),
  156. boost::end(geometry::interior_rings(polygon))
  157. ),
  158. flatten_iterator( boost::end(geometry::interior_rings(polygon)) )
  159. );
  160. }
  161. };
  162. template <typename MultiLinestring>
  163. struct segments_end<MultiLinestring, multi_linestring_tag>
  164. {
  165. typedef typename detail::segment_iterator::iterator_type
  166. <
  167. MultiLinestring
  168. >::type return_type;
  169. static inline return_type apply(MultiLinestring& multilinestring)
  170. {
  171. return return_type(boost::end(multilinestring));
  172. }
  173. };
  174. template <typename MultiPolygon>
  175. struct segments_end<MultiPolygon, multi_polygon_tag>
  176. {
  177. typedef typename detail::segment_iterator::iterator_type
  178. <
  179. MultiPolygon
  180. >::type return_type;
  181. static inline return_type apply(MultiPolygon& multipolygon)
  182. {
  183. return return_type(boost::end(multipolygon));
  184. }
  185. };
  186. } // namespace dispatch
  187. #endif // DOXYGEN_NO_DISPATCH
  188. // MK:: need to add doc here
  189. template <typename Geometry>
  190. class segment_iterator
  191. : public detail::segment_iterator::iterator_type<Geometry>::type
  192. {
  193. private:
  194. typedef typename detail::segment_iterator::iterator_type
  195. <
  196. Geometry
  197. >::type base;
  198. inline base const* base_ptr() const
  199. {
  200. return this;
  201. }
  202. template <typename OtherGeometry> friend class segment_iterator;
  203. template <typename G>
  204. friend inline segment_iterator<G const> segments_begin(G const&);
  205. template <typename G>
  206. friend inline segment_iterator<G const> segments_end(G const&);
  207. inline segment_iterator(base const& base_it) : base(base_it) {}
  208. public:
  209. // The following typedef is needed for this iterator to be
  210. // bidirectional.
  211. // Normally we would not have to define this. However, due to the
  212. // fact that the value type of the iterator is not a reference,
  213. // the iterator_facade framework (used to define the base class of
  214. // this iterator) degrades automatically the iterator's category
  215. // to input iterator. With the following typedef we recover the
  216. // correct iterator category.
  217. typedef std::bidirectional_iterator_tag iterator_category;
  218. inline segment_iterator() = default;
  219. template
  220. <
  221. typename OtherGeometry,
  222. std::enable_if_t
  223. <
  224. std::is_convertible
  225. <
  226. typename detail::segment_iterator::iterator_type<OtherGeometry>::type,
  227. typename detail::segment_iterator::iterator_type<Geometry>::type
  228. >::value,
  229. int
  230. > = 0
  231. >
  232. inline segment_iterator(segment_iterator<OtherGeometry> const& other)
  233. : base(*other.base_ptr())
  234. {}
  235. inline segment_iterator& operator++() // prefix
  236. {
  237. base::operator++();
  238. return *this;
  239. }
  240. inline segment_iterator& operator--() // prefix
  241. {
  242. base::operator--();
  243. return *this;
  244. }
  245. inline segment_iterator operator++(int) // postfix
  246. {
  247. segment_iterator copy(*this);
  248. base::operator++();
  249. return copy;
  250. }
  251. inline segment_iterator operator--(int) // postfix
  252. {
  253. segment_iterator copy(*this);
  254. base::operator--();
  255. return copy;
  256. }
  257. };
  258. // MK:: need to add doc here
  259. template <typename Geometry>
  260. inline segment_iterator<Geometry const>
  261. segments_begin(Geometry const& geometry)
  262. {
  263. return dispatch::segments_begin<Geometry const>::apply(geometry);
  264. }
  265. // MK:: need to add doc here
  266. template <typename Geometry>
  267. inline segment_iterator<Geometry const>
  268. segments_end(Geometry const& geometry)
  269. {
  270. return dispatch::segments_end<Geometry const>::apply(geometry);
  271. }
  272. }} // namespace boost::geometry
  273. #endif // BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP