pointlike_areal.hpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2020, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  4. // Licensed under the Boost Software License version 1.0.
  5. // http://www.boost.org/users/license.html
  6. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_AREAL_HPP
  7. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_AREAL_HPP
  8. #include <vector>
  9. #include <boost/range.hpp>
  10. #include <boost/geometry/core/tags.hpp>
  11. #include <boost/geometry/geometries/box.hpp>
  12. #include <boost/geometry/geometries/point.hpp>
  13. #include <boost/geometry/algorithms/disjoint.hpp>
  14. #include <boost/geometry/algorithms/envelope.hpp>
  15. #include <boost/geometry/algorithms/expand.hpp>
  16. #include <boost/geometry/algorithms/not_implemented.hpp>
  17. #include <boost/geometry/algorithms/detail/not.hpp>
  18. #include <boost/geometry/algorithms/detail/partition.hpp>
  19. #include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
  20. #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
  21. #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
  22. #include <boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp>
  23. namespace boost { namespace geometry
  24. {
  25. #ifndef DOXYGEN_NO_DETAIL
  26. namespace detail { namespace overlay
  27. {
  28. // difference/intersection of multipoint-multipolygon
  29. template
  30. <
  31. typename MultiPoint,
  32. typename MultiPolygon,
  33. typename PointOut,
  34. overlay_type OverlayType,
  35. typename Policy
  36. >
  37. class multipoint_multipolygon_point
  38. {
  39. private:
  40. template <typename ExpandPointStrategy>
  41. struct expand_box_point
  42. {
  43. template <typename Box, typename Point>
  44. static inline void apply(Box& total, Point const& point)
  45. {
  46. geometry::expand(total, point, ExpandPointStrategy());
  47. }
  48. };
  49. template <typename ExpandBoxStrategy>
  50. struct expand_box_boxpair
  51. {
  52. template <typename Box1, typename Box2, typename SizeT>
  53. static inline void apply(Box1& total, std::pair<Box2, SizeT> const& box_pair)
  54. {
  55. geometry::expand(total, box_pair.first, ExpandBoxStrategy());
  56. }
  57. };
  58. template <typename DisjointPointBoxStrategy>
  59. struct overlaps_box_point
  60. {
  61. template <typename Box, typename Point>
  62. static inline bool apply(Box const& box, Point const& point)
  63. {
  64. return ! geometry::disjoint(point, box, DisjointPointBoxStrategy());
  65. }
  66. };
  67. template <typename DisjointBoxBoxStrategy>
  68. struct overlaps_box_boxpair
  69. {
  70. template <typename Box1, typename Box2, typename SizeT>
  71. static inline bool apply(Box1 const& box, std::pair<Box2, SizeT> const& box_pair)
  72. {
  73. return ! geometry::disjoint(box, box_pair.first, DisjointBoxBoxStrategy());
  74. }
  75. };
  76. template <typename OutputIterator, typename Strategy>
  77. class item_visitor_type
  78. {
  79. public:
  80. item_visitor_type(MultiPolygon const& multipolygon,
  81. OutputIterator& oit,
  82. Strategy const& strategy)
  83. : m_multipolygon(multipolygon)
  84. , m_oit(oit)
  85. , m_strategy(strategy)
  86. {}
  87. template <typename Point, typename Box, typename SizeT>
  88. inline bool apply(Point const& item1, std::pair<Box, SizeT> const& item2)
  89. {
  90. action_selector_pl
  91. <
  92. PointOut, overlay_intersection
  93. >::apply(item1,
  94. Policy::apply(item1,
  95. range::at(m_multipolygon,
  96. item2.second),
  97. m_strategy),
  98. m_oit);
  99. return true;
  100. }
  101. private:
  102. MultiPolygon const& m_multipolygon;
  103. OutputIterator& m_oit;
  104. Strategy const& m_strategy;
  105. };
  106. template <typename Iterator, typename Box, typename SizeT, typename EnvelopeStrategy>
  107. static inline void fill_box_pairs(Iterator first, Iterator last,
  108. std::vector<std::pair<Box, SizeT> > & box_pairs,
  109. EnvelopeStrategy const& strategy)
  110. {
  111. SizeT index = 0;
  112. for (; first != last; ++first, ++index)
  113. {
  114. box_pairs.push_back(
  115. std::make_pair(geometry::return_envelope<Box>(*first, strategy),
  116. index));
  117. }
  118. }
  119. template <typename OutputIterator, typename Strategy>
  120. static inline OutputIterator get_common_points(MultiPoint const& multipoint,
  121. MultiPolygon const& multipolygon,
  122. OutputIterator oit,
  123. Strategy const& strategy)
  124. {
  125. item_visitor_type<OutputIterator, Strategy> item_visitor(multipolygon, oit, strategy);
  126. typedef geometry::model::point
  127. <
  128. typename geometry::coordinate_type<MultiPoint>::type,
  129. geometry::dimension<MultiPoint>::value,
  130. typename geometry::coordinate_system<MultiPoint>::type
  131. > point_type;
  132. typedef geometry::model::box<point_type> box_type;
  133. typedef std::pair<box_type, std::size_t> box_pair;
  134. std::vector<box_pair> box_pairs;
  135. box_pairs.reserve(boost::size(multipolygon));
  136. fill_box_pairs(boost::begin(multipolygon),
  137. boost::end(multipolygon),
  138. box_pairs,
  139. strategy.get_envelope_strategy());
  140. typedef typename Strategy::envelope_strategy_type::box_expand_strategy_type expand_box_strategy_type;
  141. typedef typename Strategy::disjoint_box_box_strategy_type disjoint_box_box_strategy_type;
  142. typedef typename Strategy::disjoint_point_box_strategy_type disjoint_point_box_strategy_type;
  143. typedef typename Strategy::expand_point_strategy_type expand_point_strategy_type;
  144. geometry::partition
  145. <
  146. box_type
  147. >::apply(multipoint, box_pairs, item_visitor,
  148. expand_box_point<expand_point_strategy_type>(),
  149. overlaps_box_point<disjoint_point_box_strategy_type>(),
  150. expand_box_boxpair<expand_box_strategy_type>(),
  151. overlaps_box_boxpair<disjoint_box_box_strategy_type>());
  152. return oit;
  153. }
  154. public:
  155. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  156. static inline OutputIterator apply(MultiPoint const& multipoint,
  157. MultiPolygon const& multipolygon,
  158. RobustPolicy const& robust_policy,
  159. OutputIterator oit,
  160. Strategy const& strategy)
  161. {
  162. typedef std::vector
  163. <
  164. typename boost::range_value<MultiPoint>::type
  165. > point_vector_type;
  166. point_vector_type common_points;
  167. // compute the common points
  168. get_common_points(multipoint, multipolygon,
  169. std::back_inserter(common_points),
  170. strategy);
  171. return multipoint_multipoint_point
  172. <
  173. MultiPoint, point_vector_type, PointOut, OverlayType
  174. >::apply(multipoint, common_points, robust_policy, oit, strategy);
  175. }
  176. };
  177. }} // namespace detail::overlay
  178. #endif // DOXYGEN_NO_DISPATCH
  179. #ifndef DOXYGEN_NO_DISPATCH
  180. namespace detail_dispatch { namespace overlay
  181. {
  182. // dispatch struct for pointlike-areal difference/intersection computation
  183. template
  184. <
  185. typename PointLike,
  186. typename Areal,
  187. typename PointOut,
  188. overlay_type OverlayType,
  189. typename Tag1,
  190. typename Tag2
  191. >
  192. struct pointlike_areal_point
  193. : not_implemented<PointLike, Areal, PointOut>
  194. {};
  195. template
  196. <
  197. typename Point,
  198. typename Areal,
  199. typename PointOut,
  200. overlay_type OverlayType,
  201. typename Tag2
  202. >
  203. struct pointlike_areal_point
  204. <
  205. Point, Areal, PointOut, OverlayType, point_tag, Tag2
  206. > : detail::overlay::point_single_point
  207. <
  208. Point, Areal, PointOut, OverlayType,
  209. detail::not_<detail::disjoint::reverse_covered_by>
  210. >
  211. {};
  212. // TODO: Consider implementing Areal-specific version
  213. // calculating envelope first in order to reject Points without
  214. // calling disjoint for Rings and Polygons
  215. template
  216. <
  217. typename MultiPoint,
  218. typename Areal,
  219. typename PointOut,
  220. overlay_type OverlayType,
  221. typename Tag2
  222. >
  223. struct pointlike_areal_point
  224. <
  225. MultiPoint, Areal, PointOut, OverlayType, multi_point_tag, Tag2
  226. > : detail::overlay::multipoint_single_point
  227. <
  228. MultiPoint, Areal, PointOut, OverlayType,
  229. detail::not_<detail::disjoint::reverse_covered_by>
  230. >
  231. {};
  232. template
  233. <
  234. typename MultiPoint,
  235. typename MultiPolygon,
  236. typename PointOut,
  237. overlay_type OverlayType
  238. >
  239. struct pointlike_areal_point
  240. <
  241. MultiPoint, MultiPolygon, PointOut, OverlayType, multi_point_tag, multi_polygon_tag
  242. > : detail::overlay::multipoint_multipolygon_point
  243. <
  244. MultiPoint, MultiPolygon, PointOut, OverlayType,
  245. detail::not_<detail::disjoint::reverse_covered_by>
  246. >
  247. {};
  248. }} // namespace detail_dispatch::overlay
  249. #endif // DOXYGEN_NO_DISPATCH
  250. }} // namespace boost::geometry
  251. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_AREAL_HPP