point_point.hpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // This file was modified by Oracle on 2013-2022.
  4. // Modifications copyright (c) 2013-2023, Oracle and/or its affiliates.
  5. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  6. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  7. // Use, modification and distribution is subject to the Boost Software License,
  8. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP
  11. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP
  12. #include <algorithm>
  13. #include <vector>
  14. #include <boost/range/empty.hpp>
  15. #include <boost/range/size.hpp>
  16. #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
  17. #include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
  18. #include <boost/geometry/algorithms/detail/relate/result.hpp>
  19. #include <boost/geometry/policies/compare.hpp>
  20. namespace boost { namespace geometry
  21. {
  22. #ifndef DOXYGEN_NO_DETAIL
  23. namespace detail { namespace relate {
  24. template <typename Point1, typename Point2>
  25. struct point_point
  26. {
  27. static const bool interruption_enabled = false;
  28. template <typename Result, typename Strategy>
  29. static inline void apply(Point1 const& point1, Point2 const& point2,
  30. Result & result,
  31. Strategy const& strategy)
  32. {
  33. bool equal = detail::equals::equals_point_point(point1, point2, strategy);
  34. if ( equal )
  35. {
  36. update<interior, interior, '0'>(result);
  37. }
  38. else
  39. {
  40. update<interior, exterior, '0'>(result);
  41. update<exterior, interior, '0'>(result);
  42. }
  43. update<exterior, exterior, result_dimension<Point1>::value>(result);
  44. }
  45. };
  46. template <typename Point, typename MultiPoint, typename EqPPStrategy>
  47. std::pair<bool, bool> point_multipoint_check(Point const& point,
  48. MultiPoint const& multi_point,
  49. EqPPStrategy const& strategy)
  50. {
  51. bool found_inside = false;
  52. bool found_outside = false;
  53. // point_in_geometry could be used here but why iterate over MultiPoint twice?
  54. // we must search for a point in the exterior because all points in MultiPoint can be equal
  55. auto const end = boost::end(multi_point);
  56. for (auto it = boost::begin(multi_point); it != end; ++it)
  57. {
  58. bool ii = detail::equals::equals_point_point(point, *it, strategy);
  59. if (ii)
  60. {
  61. found_inside = true;
  62. }
  63. else
  64. {
  65. found_outside = true;
  66. }
  67. if (found_inside && found_outside)
  68. {
  69. break;
  70. }
  71. }
  72. return std::make_pair(found_inside, found_outside);
  73. }
  74. template <typename Point, typename MultiPoint, bool Transpose = false>
  75. struct point_multipoint
  76. {
  77. static const bool interruption_enabled = false;
  78. template <typename Result, typename Strategy>
  79. static inline void apply(Point const& point, MultiPoint const& multi_point,
  80. Result & result,
  81. Strategy const& strategy)
  82. {
  83. if ( boost::empty(multi_point) )
  84. {
  85. // TODO: throw on empty input?
  86. update<interior, exterior, '0', Transpose>(result);
  87. return;
  88. }
  89. std::pair<bool, bool> rel = point_multipoint_check(point, multi_point, strategy);
  90. if ( rel.first ) // some point of MP is equal to P
  91. {
  92. update<interior, interior, '0', Transpose>(result);
  93. if ( rel.second ) // a point of MP was found outside P
  94. {
  95. update<exterior, interior, '0', Transpose>(result);
  96. }
  97. }
  98. else
  99. {
  100. update<interior, exterior, '0', Transpose>(result);
  101. update<exterior, interior, '0', Transpose>(result);
  102. }
  103. update<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
  104. }
  105. };
  106. template <typename MultiPoint, typename Point>
  107. struct multipoint_point
  108. {
  109. static const bool interruption_enabled = false;
  110. template <typename Result, typename Strategy>
  111. static inline void apply(MultiPoint const& multi_point, Point const& point,
  112. Result & result,
  113. Strategy const& strategy)
  114. {
  115. point_multipoint<Point, MultiPoint, true>::apply(point, multi_point, result, strategy);
  116. }
  117. };
  118. template <typename MultiPoint1, typename MultiPoint2>
  119. struct multipoint_multipoint
  120. {
  121. static const bool interruption_enabled = true;
  122. template <typename Result, typename Strategy>
  123. static inline void apply(MultiPoint1 const& multi_point1, MultiPoint2 const& multi_point2,
  124. Result & result,
  125. Strategy const& /*strategy*/)
  126. {
  127. {
  128. // TODO: throw on empty input?
  129. bool empty1 = boost::empty(multi_point1);
  130. bool empty2 = boost::empty(multi_point2);
  131. if ( empty1 && empty2 )
  132. {
  133. return;
  134. }
  135. else if ( empty1 )
  136. {
  137. update<exterior, interior, '0'>(result);
  138. return;
  139. }
  140. else if ( empty2 )
  141. {
  142. update<interior, exterior, '0'>(result);
  143. return;
  144. }
  145. }
  146. // The geometry containing smaller number of points will be analysed first
  147. if ( boost::size(multi_point1) < boost::size(multi_point2) )
  148. {
  149. search_both<false, Strategy>(multi_point1, multi_point2, result);
  150. }
  151. else
  152. {
  153. search_both<true, Strategy>(multi_point2, multi_point1, result);
  154. }
  155. update<exterior, exterior, result_dimension<MultiPoint1>::value>(result);
  156. }
  157. template <bool Transpose, typename Strategy, typename MPt1, typename MPt2, typename Result>
  158. static inline void search_both(MPt1 const& first_sorted_mpt, MPt2 const& first_iterated_mpt,
  159. Result & result)
  160. {
  161. if ( relate::may_update<interior, interior, '0'>(result)
  162. || relate::may_update<interior, exterior, '0'>(result)
  163. || relate::may_update<exterior, interior, '0'>(result) )
  164. {
  165. // NlogN + MlogN
  166. bool is_disjoint = search<Transpose, Strategy>(first_sorted_mpt, first_iterated_mpt, result);
  167. if ( BOOST_GEOMETRY_CONDITION(is_disjoint || result.interrupt) )
  168. return;
  169. }
  170. if ( relate::may_update<interior, interior, '0'>(result)
  171. || relate::may_update<interior, exterior, '0'>(result)
  172. || relate::may_update<exterior, interior, '0'>(result) )
  173. {
  174. // MlogM + NlogM
  175. search<! Transpose, Strategy>(first_iterated_mpt, first_sorted_mpt, result);
  176. }
  177. }
  178. template <bool Transpose,
  179. typename Strategy,
  180. typename SortedMultiPoint,
  181. typename IteratedMultiPoint,
  182. typename Result>
  183. static inline bool search(SortedMultiPoint const& sorted_mpt,
  184. IteratedMultiPoint const& iterated_mpt,
  185. Result & result)
  186. {
  187. // sort points from the 1 MPt
  188. typedef typename geometry::point_type<SortedMultiPoint>::type point_type;
  189. typedef geometry::less<void, -1, Strategy> less_type;
  190. std::vector<point_type> points(boost::begin(sorted_mpt), boost::end(sorted_mpt));
  191. less_type const less = less_type();
  192. std::sort(points.begin(), points.end(), less);
  193. bool found_inside = false;
  194. bool found_outside = false;
  195. // for each point in the second MPt
  196. for (auto it = boost::begin(iterated_mpt); it != boost::end(iterated_mpt); ++it)
  197. {
  198. bool ii = std::binary_search(points.begin(), points.end(), *it, less);
  199. if (ii)
  200. {
  201. found_inside = true;
  202. }
  203. else
  204. {
  205. found_outside = true;
  206. }
  207. if (found_inside && found_outside)
  208. {
  209. break;
  210. }
  211. }
  212. if ( found_inside ) // some point of MP2 is equal to some of MP1
  213. {
  214. // TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed
  215. // so if e.g. only I/I must be analysed we musn't check the other MPt
  216. update<interior, interior, '0', Transpose>(result);
  217. if ( found_outside ) // some point of MP2 was found outside of MP1
  218. {
  219. update<exterior, interior, '0', Transpose>(result);
  220. }
  221. }
  222. else
  223. {
  224. update<interior, exterior, '0', Transpose>(result);
  225. update<exterior, interior, '0', Transpose>(result);
  226. }
  227. // if no point is intersecting the other MPt then we musn't analyse the reversed case
  228. return ! found_inside;
  229. }
  230. };
  231. }} // namespace detail::relate
  232. #endif // DOXYGEN_NO_DETAIL
  233. }} // namespace boost::geometry
  234. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_POINT_HPP