segment_iterator.hpp 8.8 KB

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