pointlike_pointlike.hpp 12 KB

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