copy_segment_point.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Use, modification and distribution is subject to the Boost Software License,
  4. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
  7. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
  8. #include <boost/array.hpp>
  9. #include <boost/mpl/assert.hpp>
  10. #include <boost/range.hpp>
  11. #include <boost/geometry/core/assert.hpp>
  12. #include <boost/geometry/core/ring_type.hpp>
  13. #include <boost/geometry/core/exterior_ring.hpp>
  14. #include <boost/geometry/core/interior_rings.hpp>
  15. #include <boost/geometry/core/tags.hpp>
  16. #include <boost/geometry/algorithms/convert.hpp>
  17. #include <boost/geometry/algorithms/detail/signed_size_type.hpp>
  18. #include <boost/geometry/geometries/concepts/check.hpp>
  19. #include <boost/geometry/util/range.hpp>
  20. #include <boost/geometry/iterators/ever_circling_iterator.hpp>
  21. #include <boost/geometry/views/closeable_view.hpp>
  22. #include <boost/geometry/views/reversible_view.hpp>
  23. namespace boost { namespace geometry
  24. {
  25. #ifndef DOXYGEN_NO_DETAIL
  26. namespace detail { namespace copy_segments
  27. {
  28. template <typename Range, bool Reverse, typename SegmentIdentifier, typename PointOut>
  29. struct copy_segment_point_range
  30. {
  31. static inline bool apply(Range const& range,
  32. SegmentIdentifier const& seg_id, int offset,
  33. PointOut& point)
  34. {
  35. typedef typename closeable_view
  36. <
  37. Range const,
  38. closure<Range>::value
  39. >::type cview_type;
  40. typedef typename reversible_view
  41. <
  42. cview_type const,
  43. Reverse ? iterate_reverse : iterate_forward
  44. >::type rview_type;
  45. cview_type cview(range);
  46. rview_type view(cview);
  47. typedef typename boost::range_iterator<rview_type>::type iterator;
  48. geometry::ever_circling_iterator<iterator> it(boost::begin(view), boost::end(view),
  49. boost::begin(view) + seg_id.segment_index, true);
  50. for (signed_size_type i = 0; i < offset; ++i, ++it)
  51. {
  52. }
  53. geometry::convert(*it, point);
  54. return true;
  55. }
  56. };
  57. template <typename Polygon, bool Reverse, typename SegmentIdentifier, typename PointOut>
  58. struct copy_segment_point_polygon
  59. {
  60. static inline bool apply(Polygon const& polygon,
  61. SegmentIdentifier const& seg_id, int offset,
  62. PointOut& point)
  63. {
  64. // Call ring-version with the right ring
  65. return copy_segment_point_range
  66. <
  67. typename geometry::ring_type<Polygon>::type,
  68. Reverse,
  69. SegmentIdentifier,
  70. PointOut
  71. >::apply
  72. (
  73. seg_id.ring_index < 0
  74. ? geometry::exterior_ring(polygon)
  75. : range::at(geometry::interior_rings(polygon), seg_id.ring_index),
  76. seg_id, offset,
  77. point
  78. );
  79. }
  80. };
  81. template <typename Box, bool Reverse, typename SegmentIdentifier, typename PointOut>
  82. struct copy_segment_point_box
  83. {
  84. static inline bool apply(Box const& box,
  85. SegmentIdentifier const& seg_id, int offset,
  86. PointOut& point)
  87. {
  88. signed_size_type index = seg_id.segment_index;
  89. for (int i = 0; i < offset; i++)
  90. {
  91. index++;
  92. }
  93. boost::array<typename point_type<Box>::type, 4> bp;
  94. assign_box_corners_oriented<Reverse>(box, bp);
  95. point = bp[index % 4];
  96. return true;
  97. }
  98. };
  99. template
  100. <
  101. typename MultiGeometry,
  102. typename SegmentIdentifier,
  103. typename PointOut,
  104. typename Policy
  105. >
  106. struct copy_segment_point_multi
  107. {
  108. static inline bool apply(MultiGeometry const& multi,
  109. SegmentIdentifier const& seg_id, int offset,
  110. PointOut& point)
  111. {
  112. BOOST_GEOMETRY_ASSERT
  113. (
  114. seg_id.multi_index >= 0
  115. && seg_id.multi_index < int(boost::size(multi))
  116. );
  117. // Call the single-version
  118. return Policy::apply(range::at(multi, seg_id.multi_index), seg_id, offset, point);
  119. }
  120. };
  121. }} // namespace detail::copy_segments
  122. #endif // DOXYGEN_NO_DETAIL
  123. #ifndef DOXYGEN_NO_DISPATCH
  124. namespace dispatch
  125. {
  126. template
  127. <
  128. typename Tag,
  129. typename GeometryIn,
  130. bool Reverse,
  131. typename SegmentIdentifier,
  132. typename PointOut
  133. >
  134. struct copy_segment_point
  135. {
  136. BOOST_MPL_ASSERT_MSG
  137. (
  138. false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
  139. , (types<GeometryIn>)
  140. );
  141. };
  142. template <typename LineString, bool Reverse, typename SegmentIdentifier, typename PointOut>
  143. struct copy_segment_point<linestring_tag, LineString, Reverse, SegmentIdentifier, PointOut>
  144. : detail::copy_segments::copy_segment_point_range
  145. <
  146. LineString, Reverse, SegmentIdentifier, PointOut
  147. >
  148. {};
  149. template <typename Ring, bool Reverse, typename SegmentIdentifier, typename PointOut>
  150. struct copy_segment_point<ring_tag, Ring, Reverse, SegmentIdentifier, PointOut>
  151. : detail::copy_segments::copy_segment_point_range
  152. <
  153. Ring, Reverse, SegmentIdentifier, PointOut
  154. >
  155. {};
  156. template <typename Polygon, bool Reverse, typename SegmentIdentifier, typename PointOut>
  157. struct copy_segment_point<polygon_tag, Polygon, Reverse, SegmentIdentifier, PointOut>
  158. : detail::copy_segments::copy_segment_point_polygon
  159. <
  160. Polygon, Reverse, SegmentIdentifier, PointOut
  161. >
  162. {};
  163. template <typename Box, bool Reverse, typename SegmentIdentifier, typename PointOut>
  164. struct copy_segment_point<box_tag, Box, Reverse, SegmentIdentifier, PointOut>
  165. : detail::copy_segments::copy_segment_point_box
  166. <
  167. Box, Reverse, SegmentIdentifier, PointOut
  168. >
  169. {};
  170. template
  171. <
  172. typename MultiGeometry,
  173. bool Reverse,
  174. typename SegmentIdentifier,
  175. typename PointOut
  176. >
  177. struct copy_segment_point
  178. <
  179. multi_polygon_tag,
  180. MultiGeometry,
  181. Reverse,
  182. SegmentIdentifier,
  183. PointOut
  184. >
  185. : detail::copy_segments::copy_segment_point_multi
  186. <
  187. MultiGeometry,
  188. SegmentIdentifier,
  189. PointOut,
  190. detail::copy_segments::copy_segment_point_polygon
  191. <
  192. typename boost::range_value<MultiGeometry>::type,
  193. Reverse,
  194. SegmentIdentifier,
  195. PointOut
  196. >
  197. >
  198. {};
  199. template
  200. <
  201. typename MultiGeometry,
  202. bool Reverse,
  203. typename SegmentIdentifier,
  204. typename PointOut
  205. >
  206. struct copy_segment_point
  207. <
  208. multi_linestring_tag,
  209. MultiGeometry,
  210. Reverse,
  211. SegmentIdentifier,
  212. PointOut
  213. >
  214. : detail::copy_segments::copy_segment_point_multi
  215. <
  216. MultiGeometry,
  217. SegmentIdentifier,
  218. PointOut,
  219. detail::copy_segments::copy_segment_point_range
  220. <
  221. typename boost::range_value<MultiGeometry>::type,
  222. Reverse,
  223. SegmentIdentifier,
  224. PointOut
  225. >
  226. >
  227. {};
  228. } // namespace dispatch
  229. #endif // DOXYGEN_NO_DISPATCH
  230. /*!
  231. \brief Helper function, copies a point from a segment
  232. \ingroup overlay
  233. */
  234. template<bool Reverse, typename Geometry, typename SegmentIdentifier, typename PointOut>
  235. inline bool copy_segment_point(Geometry const& geometry,
  236. SegmentIdentifier const& seg_id, int offset,
  237. PointOut& point_out)
  238. {
  239. concepts::check<Geometry const>();
  240. return dispatch::copy_segment_point
  241. <
  242. typename tag<Geometry>::type,
  243. Geometry,
  244. Reverse,
  245. SegmentIdentifier,
  246. PointOut
  247. >::apply(geometry, seg_id, offset, point_out);
  248. }
  249. /*!
  250. \brief Helper function, to avoid the same construct several times,
  251. copies a point, based on a source-index and two geometries
  252. \ingroup overlay
  253. */
  254. template
  255. <
  256. bool Reverse1, bool Reverse2,
  257. typename Geometry1, typename Geometry2,
  258. typename SegmentIdentifier,
  259. typename PointOut
  260. >
  261. inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geometry2,
  262. SegmentIdentifier const& seg_id, int offset,
  263. PointOut& point_out)
  264. {
  265. concepts::check<Geometry1 const>();
  266. concepts::check<Geometry2 const>();
  267. BOOST_GEOMETRY_ASSERT(seg_id.source_index == 0 || seg_id.source_index == 1);
  268. if (seg_id.source_index == 0)
  269. {
  270. return dispatch::copy_segment_point
  271. <
  272. typename tag<Geometry1>::type,
  273. Geometry1,
  274. Reverse1,
  275. SegmentIdentifier,
  276. PointOut
  277. >::apply(geometry1, seg_id, offset, point_out);
  278. }
  279. else if (seg_id.source_index == 1)
  280. {
  281. return dispatch::copy_segment_point
  282. <
  283. typename tag<Geometry2>::type,
  284. Geometry2,
  285. Reverse2,
  286. SegmentIdentifier,
  287. PointOut
  288. >::apply(geometry2, seg_id, offset, point_out);
  289. }
  290. // Exception?
  291. return false;
  292. }
  293. /*!
  294. \brief Helper function, to avoid the same construct several times,
  295. copies a point, based on a source-index and two geometries
  296. \ingroup overlay
  297. */
  298. template
  299. <
  300. bool Reverse1, bool Reverse2,
  301. typename Geometry1, typename Geometry2,
  302. typename SegmentIdentifier,
  303. typename PointOut
  304. >
  305. inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2,
  306. SegmentIdentifier const& seg_id,
  307. PointOut& point1, PointOut& point2)
  308. {
  309. concepts::check<Geometry1 const>();
  310. concepts::check<Geometry2 const>();
  311. return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 0, point1)
  312. && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 1, point2);
  313. }
  314. /*!
  315. \brief Helper function, copies three points: two from the specified segment
  316. (from, to) and the next one
  317. \ingroup overlay
  318. */
  319. template
  320. <
  321. bool Reverse1, bool Reverse2,
  322. typename Geometry1, typename Geometry2,
  323. typename SegmentIdentifier,
  324. typename PointOut
  325. >
  326. inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2,
  327. SegmentIdentifier const& seg_id,
  328. PointOut& point1, PointOut& point2, PointOut& point3)
  329. {
  330. concepts::check<Geometry1 const>();
  331. concepts::check<Geometry2 const>();
  332. return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 0, point1)
  333. && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 1, point2)
  334. && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 2, point3);
  335. }
  336. }} // namespace boost::geometry
  337. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP