multipoint_geometry.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
  3. // Copyright (c) 2014-2019, Oracle and/or its affiliates.
  4. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  5. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  6. // Licensed under the Boost Software License version 1.0.
  7. // http://www.boost.org/users/license.html
  8. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP
  9. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP
  10. #include <algorithm>
  11. #include <vector>
  12. #include <boost/range.hpp>
  13. #include <boost/mpl/assert.hpp>
  14. #include <boost/geometry/core/assert.hpp>
  15. #include <boost/geometry/core/tag.hpp>
  16. #include <boost/geometry/core/tags.hpp>
  17. #include <boost/geometry/geometries/box.hpp>
  18. #include <boost/geometry/iterators/segment_iterator.hpp>
  19. #include <boost/geometry/algorithms/envelope.hpp>
  20. #include <boost/geometry/algorithms/expand.hpp>
  21. #include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
  22. #include <boost/geometry/algorithms/detail/partition.hpp>
  23. #include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
  24. #include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
  25. #include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
  26. #include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
  27. #include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
  28. #include <boost/geometry/algorithms/dispatch/disjoint.hpp>
  29. #include <boost/geometry/policies/compare.hpp>
  30. namespace boost { namespace geometry
  31. {
  32. #ifndef DOXYGEN_NO_DETAIL
  33. namespace detail { namespace disjoint
  34. {
  35. class multipoint_multipoint
  36. {
  37. private:
  38. template <typename Iterator, typename CSTag>
  39. class unary_disjoint_predicate
  40. : geometry::less<void, -1, CSTag>
  41. {
  42. private:
  43. typedef geometry::less<void, -1, CSTag> base_type;
  44. public:
  45. unary_disjoint_predicate(Iterator first, Iterator last)
  46. : base_type(), m_first(first), m_last(last)
  47. {}
  48. template <typename Point>
  49. inline bool apply(Point const& point) const
  50. {
  51. return !std::binary_search(m_first,
  52. m_last,
  53. point,
  54. static_cast<base_type const&>(*this));
  55. }
  56. private:
  57. Iterator m_first, m_last;
  58. };
  59. public:
  60. template <typename MultiPoint1, typename MultiPoint2, typename Strategy>
  61. static inline bool apply(MultiPoint1 const& multipoint1,
  62. MultiPoint2 const& multipoint2,
  63. Strategy const&)
  64. {
  65. typedef typename Strategy::cs_tag cs_tag;
  66. typedef geometry::less<void, -1, cs_tag> less_type;
  67. BOOST_GEOMETRY_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) );
  68. typedef typename boost::range_value<MultiPoint1>::type point1_type;
  69. std::vector<point1_type> points1(boost::begin(multipoint1),
  70. boost::end(multipoint1));
  71. std::sort(points1.begin(), points1.end(), less_type());
  72. typedef unary_disjoint_predicate
  73. <
  74. typename std::vector<point1_type>::const_iterator,
  75. cs_tag
  76. > predicate_type;
  77. return check_iterator_range
  78. <
  79. predicate_type
  80. >::apply(boost::begin(multipoint2),
  81. boost::end(multipoint2),
  82. predicate_type(points1.begin(), points1.end()));
  83. }
  84. };
  85. template <typename MultiPoint, typename Linear>
  86. class multipoint_linear
  87. {
  88. private:
  89. template <typename ExpandPointBoxStrategy>
  90. struct expand_box_point
  91. {
  92. template <typename Box, typename Point>
  93. static inline void apply(Box& total, Point const& point)
  94. {
  95. geometry::expand(total, point, ExpandPointBoxStrategy());
  96. }
  97. };
  98. template <typename EnvelopeStrategy>
  99. struct expand_box_segment
  100. {
  101. explicit expand_box_segment(EnvelopeStrategy const& strategy)
  102. : m_strategy(strategy)
  103. {}
  104. template <typename Box, typename Segment>
  105. inline void apply(Box& total, Segment const& segment) const
  106. {
  107. geometry::expand(total,
  108. geometry::return_envelope<Box>(segment, m_strategy),
  109. typename EnvelopeStrategy::box_expand_strategy_type());
  110. }
  111. EnvelopeStrategy const& m_strategy;
  112. };
  113. template <typename DisjointPointBoxStrategy>
  114. struct overlaps_box_point
  115. {
  116. template <typename Box, typename Point>
  117. static inline bool apply(Box const& box, Point const& point)
  118. {
  119. // The default strategy is enough in this case
  120. return ! detail::disjoint::disjoint_point_box(point, box,
  121. DisjointPointBoxStrategy());
  122. }
  123. };
  124. template <typename DisjointStrategy>
  125. struct overlaps_box_segment
  126. {
  127. explicit overlaps_box_segment(DisjointStrategy const& strategy)
  128. : m_strategy(strategy)
  129. {}
  130. template <typename Box, typename Segment>
  131. inline bool apply(Box const& box, Segment const& segment) const
  132. {
  133. return ! dispatch::disjoint<Segment, Box>::apply(segment, box, m_strategy);
  134. }
  135. DisjointStrategy const& m_strategy;
  136. };
  137. template <typename PtSegStrategy>
  138. class item_visitor_type
  139. {
  140. public:
  141. item_visitor_type(PtSegStrategy const& strategy)
  142. : m_intersection_found(false)
  143. , m_strategy(strategy)
  144. {}
  145. template <typename Item1, typename Item2>
  146. inline bool apply(Item1 const& item1, Item2 const& item2)
  147. {
  148. if (! m_intersection_found
  149. && ! dispatch::disjoint<Item1, Item2>::apply(item1, item2, m_strategy))
  150. {
  151. m_intersection_found = true;
  152. return false;
  153. }
  154. return true;
  155. }
  156. inline bool intersection_found() const { return m_intersection_found; }
  157. private:
  158. bool m_intersection_found;
  159. PtSegStrategy const& m_strategy;
  160. };
  161. // structs for partition -- end
  162. class segment_range
  163. {
  164. public:
  165. typedef geometry::segment_iterator<Linear const> const_iterator;
  166. typedef const_iterator iterator;
  167. segment_range(Linear const& linear)
  168. : m_linear(linear)
  169. {}
  170. const_iterator begin() const
  171. {
  172. return geometry::segments_begin(m_linear);
  173. }
  174. const_iterator end() const
  175. {
  176. return geometry::segments_end(m_linear);
  177. }
  178. private:
  179. Linear const& m_linear;
  180. };
  181. public:
  182. template <typename Strategy>
  183. static inline bool apply(MultiPoint const& multipoint, Linear const& linear, Strategy const& strategy)
  184. {
  185. item_visitor_type<Strategy> visitor(strategy);
  186. typedef typename Strategy::expand_point_strategy_type expand_point_strategy_type;
  187. typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
  188. typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type;
  189. typedef typename Strategy::disjoint_point_box_strategy_type disjoint_pb_strategy_type;
  190. // TODO: disjoint Segment/Box may be called in partition multiple times
  191. // possibly for non-cartesian segments which could be slow. We should consider
  192. // passing a range of bounding boxes of segments after calculating them once.
  193. // Alternatively instead of a range of segments a range of Segment/Envelope pairs
  194. // should be passed, where envelope would be lazily calculated when needed the first time
  195. geometry::partition
  196. <
  197. geometry::model::box<typename point_type<MultiPoint>::type>
  198. >::apply(multipoint, segment_range(linear), visitor,
  199. expand_box_point<expand_point_strategy_type>(),
  200. overlaps_box_point<disjoint_pb_strategy_type>(),
  201. expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()),
  202. overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy()));
  203. return ! visitor.intersection_found();
  204. }
  205. template <typename Strategy>
  206. static inline bool apply(Linear const& linear, MultiPoint const& multipoint, Strategy const& strategy)
  207. {
  208. return apply(multipoint, linear, strategy);
  209. }
  210. };
  211. template <typename MultiPoint, typename SingleGeometry>
  212. class multi_point_single_geometry
  213. {
  214. public:
  215. template <typename Strategy>
  216. static inline bool apply(MultiPoint const& multi_point,
  217. SingleGeometry const& single_geometry,
  218. Strategy const& strategy)
  219. {
  220. typedef typename Strategy::disjoint_point_box_strategy_type d_pb_strategy_type;
  221. typedef typename point_type<MultiPoint>::type point1_type;
  222. typedef typename point_type<SingleGeometry>::type point2_type;
  223. typedef model::box<point2_type> box2_type;
  224. box2_type box2;
  225. geometry::envelope(single_geometry, box2, strategy.get_envelope_strategy());
  226. geometry::detail::expand_by_epsilon(box2);
  227. typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
  228. for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
  229. {
  230. // The default strategy is enough for Point/Box
  231. if (! detail::disjoint::disjoint_point_box(*it, box2, d_pb_strategy_type())
  232. && ! dispatch::disjoint<point1_type, SingleGeometry>::apply(*it, single_geometry, strategy))
  233. {
  234. return false;
  235. }
  236. }
  237. return true;
  238. }
  239. template <typename Strategy>
  240. static inline bool apply(SingleGeometry const& single_geometry, MultiPoint const& multi_point, Strategy const& strategy)
  241. {
  242. return apply(multi_point, single_geometry, strategy);
  243. }
  244. };
  245. template <typename MultiPoint, typename MultiGeometry>
  246. class multi_point_multi_geometry
  247. {
  248. private:
  249. template <typename ExpandPointStrategy>
  250. struct expand_box_point
  251. {
  252. template <typename Box, typename Point>
  253. static inline void apply(Box& total, Point const& point)
  254. {
  255. geometry::expand(total, point, ExpandPointStrategy());
  256. }
  257. };
  258. template <typename ExpandBoxStrategy>
  259. struct expand_box_box_pair
  260. {
  261. template <typename Box, typename BoxPair>
  262. inline void apply(Box& total, BoxPair const& box_pair) const
  263. {
  264. geometry::expand(total, box_pair.first, ExpandBoxStrategy());
  265. }
  266. };
  267. template <typename DisjointPointBoxStrategy>
  268. struct overlaps_box_point
  269. {
  270. template <typename Box, typename Point>
  271. static inline bool apply(Box const& box, Point const& point)
  272. {
  273. // The default strategy is enough for Point/Box
  274. return ! detail::disjoint::disjoint_point_box(point, box,
  275. DisjointPointBoxStrategy());
  276. }
  277. };
  278. template <typename DisjointBoxBoxStrategy>
  279. struct overlaps_box_box_pair
  280. {
  281. template <typename Box, typename BoxPair>
  282. inline bool apply(Box const& box, BoxPair const& box_pair) const
  283. {
  284. // The default strategy is enough for Box/Box
  285. return ! detail::disjoint::disjoint_box_box(box_pair.first, box,
  286. DisjointBoxBoxStrategy());
  287. }
  288. };
  289. template <typename PtSegStrategy>
  290. class item_visitor_type
  291. {
  292. public:
  293. item_visitor_type(MultiGeometry const& multi_geometry,
  294. PtSegStrategy const& strategy)
  295. : m_intersection_found(false)
  296. , m_multi_geometry(multi_geometry)
  297. , m_strategy(strategy)
  298. {}
  299. template <typename Point, typename BoxPair>
  300. inline bool apply(Point const& point, BoxPair const& box_pair)
  301. {
  302. typedef typename PtSegStrategy::disjoint_point_box_strategy_type d_pb_strategy_type;
  303. typedef typename boost::range_value<MultiGeometry>::type single_type;
  304. // The default strategy is enough for Point/Box
  305. if (! m_intersection_found
  306. && ! detail::disjoint::disjoint_point_box(point, box_pair.first, d_pb_strategy_type())
  307. && ! dispatch::disjoint<Point, single_type>::apply(point, range::at(m_multi_geometry, box_pair.second), m_strategy))
  308. {
  309. m_intersection_found = true;
  310. return false;
  311. }
  312. return true;
  313. }
  314. inline bool intersection_found() const { return m_intersection_found; }
  315. private:
  316. bool m_intersection_found;
  317. MultiGeometry const& m_multi_geometry;
  318. PtSegStrategy const& m_strategy;
  319. };
  320. // structs for partition -- end
  321. public:
  322. template <typename Strategy>
  323. static inline bool apply(MultiPoint const& multi_point, MultiGeometry const& multi_geometry, Strategy const& strategy)
  324. {
  325. typedef typename point_type<MultiPoint>::type point1_type;
  326. typedef typename point_type<MultiGeometry>::type point2_type;
  327. typedef model::box<point1_type> box1_type;
  328. typedef model::box<point2_type> box2_type;
  329. typedef std::pair<box2_type, std::size_t> box_pair_type;
  330. typename Strategy::envelope_strategy_type const
  331. envelope_strategy = strategy.get_envelope_strategy();
  332. std::size_t count2 = boost::size(multi_geometry);
  333. std::vector<box_pair_type> boxes(count2);
  334. for (std::size_t i = 0 ; i < count2 ; ++i)
  335. {
  336. geometry::envelope(range::at(multi_geometry, i), boxes[i].first, envelope_strategy);
  337. geometry::detail::expand_by_epsilon(boxes[i].first);
  338. boxes[i].second = i;
  339. }
  340. item_visitor_type<Strategy> visitor(multi_geometry, strategy);
  341. typedef expand_box_point
  342. <
  343. typename Strategy::expand_point_strategy_type
  344. > expand_box_point_type;
  345. typedef overlaps_box_point
  346. <
  347. typename Strategy::disjoint_point_box_strategy_type
  348. > overlaps_box_point_type;
  349. typedef expand_box_box_pair
  350. <
  351. typename Strategy::envelope_strategy_type::box_expand_strategy_type
  352. > expand_box_box_pair_type;
  353. typedef overlaps_box_box_pair
  354. <
  355. typename Strategy::disjoint_box_box_strategy_type
  356. > overlaps_box_box_pair_type;
  357. geometry::partition
  358. <
  359. box1_type
  360. >::apply(multi_point, boxes, visitor,
  361. expand_box_point_type(),
  362. overlaps_box_point_type(),
  363. expand_box_box_pair_type(),
  364. overlaps_box_box_pair_type());
  365. return ! visitor.intersection_found();
  366. }
  367. template <typename Strategy>
  368. static inline bool apply(MultiGeometry const& multi_geometry, MultiPoint const& multi_point, Strategy const& strategy)
  369. {
  370. return apply(multi_point, multi_geometry, strategy);
  371. }
  372. };
  373. template <typename MultiPoint, typename Areal, typename Tag = typename tag<Areal>::type>
  374. struct multipoint_areal
  375. : multi_point_single_geometry<MultiPoint, Areal>
  376. {};
  377. template <typename MultiPoint, typename Areal>
  378. struct multipoint_areal<MultiPoint, Areal, multi_polygon_tag>
  379. : multi_point_multi_geometry<MultiPoint, Areal>
  380. {};
  381. }} // namespace detail::disjoint
  382. #endif // DOXYGEN_NO_DETAIL
  383. #ifndef DOXYGEN_NO_DISPATCH
  384. namespace dispatch
  385. {
  386. template <typename Point, typename MultiPoint, std::size_t DimensionCount>
  387. struct disjoint
  388. <
  389. Point, MultiPoint, DimensionCount, point_tag, multi_point_tag, false
  390. > : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Point>
  391. {};
  392. template <typename MultiPoint, typename Segment, std::size_t DimensionCount>
  393. struct disjoint
  394. <
  395. MultiPoint, Segment, DimensionCount, multi_point_tag, segment_tag, false
  396. > : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Segment>
  397. {};
  398. template <typename MultiPoint, typename Box, std::size_t DimensionCount>
  399. struct disjoint
  400. <
  401. MultiPoint, Box, DimensionCount, multi_point_tag, box_tag, false
  402. > : detail::disjoint::multirange_constant_size_geometry<MultiPoint, Box>
  403. {};
  404. template
  405. <
  406. typename MultiPoint1,
  407. typename MultiPoint2,
  408. std::size_t DimensionCount
  409. >
  410. struct disjoint
  411. <
  412. MultiPoint1, MultiPoint2, DimensionCount,
  413. multi_point_tag, multi_point_tag, false
  414. >
  415. {
  416. template <typename Strategy>
  417. static inline bool apply(MultiPoint1 const& multipoint1,
  418. MultiPoint2 const& multipoint2,
  419. Strategy const& strategy)
  420. {
  421. if ( boost::size(multipoint2) < boost::size(multipoint1) )
  422. {
  423. return detail::disjoint::multipoint_multipoint
  424. ::apply(multipoint2, multipoint1, strategy);
  425. }
  426. return detail::disjoint::multipoint_multipoint
  427. ::apply(multipoint1, multipoint2, strategy);
  428. }
  429. };
  430. template <typename Linear, typename MultiPoint, std::size_t DimensionCount>
  431. struct disjoint
  432. <
  433. Linear, MultiPoint, DimensionCount, linear_tag, multi_point_tag, false
  434. > : detail::disjoint::multipoint_linear<MultiPoint, Linear>
  435. {};
  436. template <typename MultiPoint, typename Linear, std::size_t DimensionCount>
  437. struct disjoint
  438. <
  439. MultiPoint, Linear, DimensionCount, multi_point_tag, linear_tag, false
  440. > : detail::disjoint::multipoint_linear<MultiPoint, Linear>
  441. {};
  442. template <typename Areal, typename MultiPoint, std::size_t DimensionCount>
  443. struct disjoint
  444. <
  445. Areal, MultiPoint, DimensionCount, areal_tag, multi_point_tag, false
  446. > : detail::disjoint::multipoint_areal<MultiPoint, Areal>
  447. {};
  448. template <typename MultiPoint, typename Areal, std::size_t DimensionCount>
  449. struct disjoint
  450. <
  451. MultiPoint, Areal, DimensionCount, multi_point_tag, areal_tag, false
  452. > : detail::disjoint::multipoint_areal<MultiPoint, Areal>
  453. {};
  454. } // namespace dispatch
  455. #endif // DOXYGEN_NO_DISPATCH
  456. }} // namespace boost::geometry
  457. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIPOINT_GEOMETRY_HPP