pointlike_pointlike.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2014-2019, 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_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP
  8. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP
  9. #include <algorithm>
  10. #include <vector>
  11. #include <boost/range.hpp>
  12. #include <boost/geometry/core/assert.hpp>
  13. #include <boost/geometry/core/point_type.hpp>
  14. #include <boost/geometry/core/tag.hpp>
  15. #include <boost/geometry/core/tags.hpp>
  16. #include <boost/geometry/algorithms/convert.hpp>
  17. #include <boost/geometry/algorithms/not_implemented.hpp>
  18. #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
  19. #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
  20. #include <boost/geometry/policies/compare.hpp>
  21. namespace boost { namespace geometry
  22. {
  23. #ifndef DOXYGEN_NO_DETAIL
  24. namespace detail { namespace overlay
  25. {
  26. // struct for copying points of the pointlike geometries to output
  27. template
  28. <
  29. typename PointOut,
  30. typename GeometryIn,
  31. typename TagIn = typename tag<GeometryIn>::type
  32. >
  33. struct copy_points
  34. : not_implemented<PointOut, GeometryIn>
  35. {};
  36. template <typename PointOut, typename PointIn>
  37. struct copy_points<PointOut, PointIn, point_tag>
  38. {
  39. template <typename OutputIterator>
  40. static inline void apply(PointIn const& point_in,
  41. OutputIterator& oit)
  42. {
  43. PointOut point_out;
  44. geometry::convert(point_in, point_out);
  45. *oit++ = point_out;
  46. }
  47. };
  48. template <typename PointOut, typename MultiPointIn>
  49. struct copy_points<PointOut, MultiPointIn, multi_point_tag>
  50. {
  51. template <typename OutputIterator>
  52. static inline void apply(MultiPointIn const& multi_point_in,
  53. OutputIterator& oit)
  54. {
  55. for (typename boost::range_iterator<MultiPointIn const>::type
  56. it = boost::begin(multi_point_in);
  57. it != boost::end(multi_point_in); ++it)
  58. {
  59. PointOut point_out;
  60. geometry::convert(*it, point_out);
  61. *oit++ = point_out;
  62. }
  63. }
  64. };
  65. // action struct for difference/intersection
  66. template <typename PointOut, overlay_type OverlayType>
  67. struct action_selector_pl_pl
  68. {};
  69. template <typename PointOut>
  70. struct action_selector_pl_pl<PointOut, overlay_intersection>
  71. {
  72. template
  73. <
  74. typename Point,
  75. typename OutputIterator
  76. >
  77. static inline void apply(Point const& point,
  78. bool is_common,
  79. OutputIterator& oit)
  80. {
  81. if ( is_common )
  82. {
  83. copy_points<PointOut, Point>::apply(point, oit);
  84. }
  85. }
  86. };
  87. template <typename PointOut>
  88. struct action_selector_pl_pl<PointOut, overlay_difference>
  89. {
  90. template
  91. <
  92. typename Point,
  93. typename OutputIterator
  94. >
  95. static inline void apply(Point const& point,
  96. bool is_common,
  97. OutputIterator& oit)
  98. {
  99. if ( !is_common )
  100. {
  101. copy_points<PointOut, Point>::apply(point, oit);
  102. }
  103. }
  104. };
  105. //===========================================================================
  106. // difference/intersection of point-point
  107. template
  108. <
  109. typename Point1,
  110. typename Point2,
  111. typename PointOut,
  112. overlay_type OverlayType
  113. >
  114. struct point_point_point
  115. {
  116. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  117. static inline OutputIterator apply(Point1 const& point1,
  118. Point2 const& point2,
  119. RobustPolicy const& ,
  120. OutputIterator oit,
  121. Strategy const& strategy)
  122. {
  123. action_selector_pl_pl
  124. <
  125. PointOut, OverlayType
  126. >::apply(point1,
  127. detail::equals::equals_point_point(point1, point2, strategy),
  128. oit);
  129. return oit;
  130. }
  131. };
  132. // difference of multipoint-point
  133. //
  134. // the apply method in the following struct is called only for
  135. // difference; for intersection the reversal will
  136. // always call the point-multipoint version
  137. template
  138. <
  139. typename MultiPoint,
  140. typename Point,
  141. typename PointOut,
  142. overlay_type OverlayType
  143. >
  144. struct multipoint_point_point
  145. {
  146. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  147. static inline OutputIterator apply(MultiPoint const& multipoint,
  148. Point const& point,
  149. RobustPolicy const& ,
  150. OutputIterator oit,
  151. Strategy const& strategy)
  152. {
  153. BOOST_GEOMETRY_ASSERT( OverlayType == overlay_difference );
  154. for (typename boost::range_iterator<MultiPoint const>::type
  155. it = boost::begin(multipoint);
  156. it != boost::end(multipoint); ++it)
  157. {
  158. action_selector_pl_pl
  159. <
  160. PointOut, OverlayType
  161. >::apply(*it,
  162. detail::equals::equals_point_point(*it, point, strategy),
  163. oit);
  164. }
  165. return oit;
  166. }
  167. };
  168. // difference/intersection of point-multipoint
  169. template
  170. <
  171. typename Point,
  172. typename MultiPoint,
  173. typename PointOut,
  174. overlay_type OverlayType
  175. >
  176. struct point_multipoint_point
  177. {
  178. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  179. static inline OutputIterator apply(Point const& point,
  180. MultiPoint const& multipoint,
  181. RobustPolicy const& ,
  182. OutputIterator oit,
  183. Strategy const& strategy)
  184. {
  185. typedef action_selector_pl_pl<PointOut, OverlayType> action;
  186. for (typename boost::range_iterator<MultiPoint const>::type
  187. it = boost::begin(multipoint);
  188. it != boost::end(multipoint); ++it)
  189. {
  190. if ( detail::equals::equals_point_point(*it, point, strategy) )
  191. {
  192. action::apply(point, true, oit);
  193. return oit;
  194. }
  195. }
  196. action::apply(point, false, oit);
  197. return oit;
  198. }
  199. };
  200. // difference/intersection of multipoint-multipoint
  201. template
  202. <
  203. typename MultiPoint1,
  204. typename MultiPoint2,
  205. typename PointOut,
  206. overlay_type OverlayType
  207. >
  208. struct multipoint_multipoint_point
  209. {
  210. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  211. static inline OutputIterator apply(MultiPoint1 const& multipoint1,
  212. MultiPoint2 const& multipoint2,
  213. RobustPolicy const& robust_policy,
  214. OutputIterator oit,
  215. Strategy const& strategy)
  216. {
  217. typedef geometry::less<void, -1, typename Strategy::cs_tag> less_type;
  218. if ( OverlayType != overlay_difference
  219. && boost::size(multipoint1) > boost::size(multipoint2) )
  220. {
  221. return multipoint_multipoint_point
  222. <
  223. MultiPoint2, MultiPoint1, PointOut, OverlayType
  224. >::apply(multipoint2, multipoint1, robust_policy, oit, strategy);
  225. }
  226. typedef typename boost::range_value<MultiPoint2>::type point2_type;
  227. std::vector<point2_type> points2(boost::begin(multipoint2),
  228. boost::end(multipoint2));
  229. less_type const less = less_type();
  230. std::sort(points2.begin(), points2.end(), less);
  231. for (typename boost::range_iterator<MultiPoint1 const>::type
  232. it1 = boost::begin(multipoint1);
  233. it1 != boost::end(multipoint1); ++it1)
  234. {
  235. bool found = std::binary_search(points2.begin(), points2.end(),
  236. *it1, less);
  237. action_selector_pl_pl
  238. <
  239. PointOut, OverlayType
  240. >::apply(*it1, found, oit);
  241. }
  242. return oit;
  243. }
  244. };
  245. }} // namespace detail::overlay
  246. #endif // DOXYGEN_NO_DETAIL
  247. //===========================================================================
  248. #ifndef DOXYGEN_NO_DISPATCH
  249. namespace detail_dispatch { namespace overlay
  250. {
  251. // dispatch struct for pointlike-pointlike difference/intersection
  252. // computation
  253. template
  254. <
  255. typename PointLike1,
  256. typename PointLike2,
  257. typename PointOut,
  258. overlay_type OverlayType,
  259. typename Tag1,
  260. typename Tag2
  261. >
  262. struct pointlike_pointlike_point
  263. : not_implemented<PointLike1, PointLike2, PointOut>
  264. {};
  265. template
  266. <
  267. typename Point1,
  268. typename Point2,
  269. typename PointOut,
  270. overlay_type OverlayType
  271. >
  272. struct pointlike_pointlike_point
  273. <
  274. Point1, Point2, PointOut, OverlayType,
  275. point_tag, point_tag
  276. > : detail::overlay::point_point_point
  277. <
  278. Point1, Point2, PointOut, OverlayType
  279. >
  280. {};
  281. template
  282. <
  283. typename Point,
  284. typename MultiPoint,
  285. typename PointOut,
  286. overlay_type OverlayType
  287. >
  288. struct pointlike_pointlike_point
  289. <
  290. Point, MultiPoint, PointOut, OverlayType,
  291. point_tag, multi_point_tag
  292. > : detail::overlay::point_multipoint_point
  293. <
  294. Point, MultiPoint, PointOut, OverlayType
  295. >
  296. {};
  297. template
  298. <
  299. typename MultiPoint,
  300. typename Point,
  301. typename PointOut,
  302. overlay_type OverlayType
  303. >
  304. struct pointlike_pointlike_point
  305. <
  306. MultiPoint, Point, PointOut, OverlayType,
  307. multi_point_tag, point_tag
  308. > : detail::overlay::multipoint_point_point
  309. <
  310. MultiPoint, Point, PointOut, OverlayType
  311. >
  312. {};
  313. template
  314. <
  315. typename MultiPoint1,
  316. typename MultiPoint2,
  317. typename PointOut,
  318. overlay_type OverlayType
  319. >
  320. struct pointlike_pointlike_point
  321. <
  322. MultiPoint1, MultiPoint2, PointOut, OverlayType,
  323. multi_point_tag, multi_point_tag
  324. > : detail::overlay::multipoint_multipoint_point
  325. <
  326. MultiPoint1, MultiPoint2, PointOut, OverlayType
  327. >
  328. {};
  329. }} // namespace detail_dispatch::overlay
  330. #endif // DOXYGEN_NO_DISPATCH
  331. //===========================================================================
  332. #ifndef DOXYGEN_NO_DETAIL
  333. namespace detail { namespace overlay
  334. {
  335. // generic pointlike-pointlike union implementation
  336. template
  337. <
  338. typename PointLike1,
  339. typename PointLike2,
  340. typename PointOut
  341. >
  342. struct union_pointlike_pointlike_point
  343. {
  344. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  345. static inline OutputIterator apply(PointLike1 const& pointlike1,
  346. PointLike2 const& pointlike2,
  347. RobustPolicy const& robust_policy,
  348. OutputIterator oit,
  349. Strategy const& strategy)
  350. {
  351. copy_points<PointOut, PointLike1>::apply(pointlike1, oit);
  352. return detail_dispatch::overlay::pointlike_pointlike_point
  353. <
  354. PointLike2, PointLike1, PointOut, overlay_difference,
  355. typename tag<PointLike2>::type,
  356. typename tag<PointLike1>::type
  357. >::apply(pointlike2, pointlike1, robust_policy, oit, strategy);
  358. }
  359. };
  360. }} // namespace detail::overlay
  361. #endif // DOXYGEN_NO_DETAIL
  362. }} // namespace boost::geometry
  363. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_POINTLIKE_HPP