pointlike_linear.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
  3. // Copyright (c) 2015-2020, 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_OVERLAY_POINTLIKE_LINEAR_HPP
  9. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP
  10. #include <iterator>
  11. #include <vector>
  12. #include <boost/range.hpp>
  13. #include <boost/geometry/core/tags.hpp>
  14. #include <boost/geometry/geometries/box.hpp>
  15. #include <boost/geometry/iterators/segment_iterator.hpp>
  16. #include <boost/geometry/algorithms/disjoint.hpp>
  17. #include <boost/geometry/algorithms/envelope.hpp>
  18. #include <boost/geometry/algorithms/expand.hpp>
  19. #include <boost/geometry/algorithms/not_implemented.hpp>
  20. #include <boost/geometry/algorithms/detail/not.hpp>
  21. #include <boost/geometry/algorithms/detail/partition.hpp>
  22. #include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
  23. #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
  24. #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
  25. #include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
  26. namespace boost { namespace geometry
  27. {
  28. #ifndef DOXYGEN_NO_DETAIL
  29. namespace detail { namespace overlay
  30. {
  31. // difference/intersection of point-linear
  32. template
  33. <
  34. typename Point,
  35. typename Geometry,
  36. typename PointOut,
  37. overlay_type OverlayType,
  38. typename Policy
  39. >
  40. struct point_single_point
  41. {
  42. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  43. static inline OutputIterator apply(Point const& point,
  44. Geometry const& geometry,
  45. RobustPolicy const&,
  46. OutputIterator oit,
  47. Strategy const& strategy)
  48. {
  49. action_selector_pl
  50. <
  51. PointOut, OverlayType
  52. >::apply(point, Policy::apply(point, geometry, strategy), oit);
  53. return oit;
  54. }
  55. };
  56. // difference/intersection of multipoint-segment
  57. template
  58. <
  59. typename MultiPoint,
  60. typename Geometry,
  61. typename PointOut,
  62. overlay_type OverlayType,
  63. typename Policy
  64. >
  65. struct multipoint_single_point
  66. {
  67. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  68. static inline OutputIterator apply(MultiPoint const& multipoint,
  69. Geometry const& geometry,
  70. RobustPolicy const&,
  71. OutputIterator oit,
  72. Strategy const& strategy)
  73. {
  74. for (typename boost::range_iterator<MultiPoint const>::type
  75. it = boost::begin(multipoint);
  76. it != boost::end(multipoint);
  77. ++it)
  78. {
  79. action_selector_pl
  80. <
  81. PointOut, OverlayType
  82. >::apply(*it, Policy::apply(*it, geometry, strategy), oit);
  83. }
  84. return oit;
  85. }
  86. };
  87. // difference/intersection of multipoint-linear
  88. template
  89. <
  90. typename MultiPoint,
  91. typename Linear,
  92. typename PointOut,
  93. overlay_type OverlayType,
  94. typename Policy
  95. >
  96. class multipoint_linear_point
  97. {
  98. private:
  99. // structs for partition -- start
  100. template <typename ExpandPointStrategy>
  101. struct expand_box_point
  102. {
  103. template <typename Box, typename Point>
  104. static inline void apply(Box& total, Point const& point)
  105. {
  106. geometry::expand(total, point, ExpandPointStrategy());
  107. }
  108. };
  109. template <typename EnvelopeStrategy>
  110. struct expand_box_segment
  111. {
  112. explicit expand_box_segment(EnvelopeStrategy const& strategy)
  113. : m_strategy(strategy)
  114. {}
  115. template <typename Box, typename Segment>
  116. inline void apply(Box& total, Segment const& segment) const
  117. {
  118. geometry::expand(total,
  119. geometry::return_envelope<Box>(segment, m_strategy),
  120. m_strategy.get_box_expand_strategy());
  121. }
  122. EnvelopeStrategy const& m_strategy;
  123. };
  124. template <typename DisjointPointBoxStrategy>
  125. struct overlaps_box_point
  126. {
  127. template <typename Box, typename Point>
  128. static inline bool apply(Box const& box, Point const& point)
  129. {
  130. return ! geometry::disjoint(point, box, DisjointPointBoxStrategy());
  131. }
  132. };
  133. template <typename DisjointStrategy>
  134. struct overlaps_box_segment
  135. {
  136. explicit overlaps_box_segment(DisjointStrategy const& strategy)
  137. : m_strategy(strategy)
  138. {}
  139. template <typename Box, typename Segment>
  140. inline bool apply(Box const& box, Segment const& segment) const
  141. {
  142. return ! geometry::disjoint(segment, box, m_strategy);
  143. }
  144. DisjointStrategy const& m_strategy;
  145. };
  146. template <typename OutputIterator, typename Strategy>
  147. class item_visitor_type
  148. {
  149. public:
  150. item_visitor_type(OutputIterator& oit, Strategy const& strategy)
  151. : m_oit(oit)
  152. , m_strategy(strategy)
  153. {}
  154. template <typename Item1, typename Item2>
  155. inline bool apply(Item1 const& item1, Item2 const& item2)
  156. {
  157. action_selector_pl
  158. <
  159. PointOut, overlay_intersection
  160. >::apply(item1, Policy::apply(item1, item2, m_strategy), m_oit);
  161. return true;
  162. }
  163. private:
  164. OutputIterator& m_oit;
  165. Strategy const& m_strategy;
  166. };
  167. // structs for partition -- end
  168. class segment_range
  169. {
  170. public:
  171. typedef geometry::segment_iterator<Linear const> const_iterator;
  172. typedef const_iterator iterator;
  173. segment_range(Linear const& linear)
  174. : m_linear(linear)
  175. {}
  176. const_iterator begin() const
  177. {
  178. return geometry::segments_begin(m_linear);
  179. }
  180. const_iterator end() const
  181. {
  182. return geometry::segments_end(m_linear);
  183. }
  184. private:
  185. Linear const& m_linear;
  186. };
  187. template <typename OutputIterator, typename Strategy>
  188. static inline OutputIterator get_common_points(MultiPoint const& multipoint,
  189. Linear const& linear,
  190. OutputIterator oit,
  191. Strategy const& strategy)
  192. {
  193. item_visitor_type<OutputIterator, Strategy> item_visitor(oit, strategy);
  194. typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
  195. typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type;
  196. typedef typename Strategy::disjoint_point_box_strategy_type disjoint_point_box_strategy_type;
  197. typedef typename Strategy::expand_point_strategy_type expand_point_strategy_type;
  198. // TODO: disjoint Segment/Box may be called in partition multiple times
  199. // possibly for non-cartesian segments which could be slow. We should consider
  200. // passing a range of bounding boxes of segments after calculating them once.
  201. // Alternatively instead of a range of segments a range of Segment/Envelope pairs
  202. // should be passed, where envelope would be lazily calculated when needed the first time
  203. geometry::partition
  204. <
  205. geometry::model::box
  206. <
  207. typename boost::range_value<MultiPoint>::type
  208. >
  209. >::apply(multipoint, segment_range(linear), item_visitor,
  210. expand_box_point<expand_point_strategy_type>(),
  211. overlaps_box_point<disjoint_point_box_strategy_type>(),
  212. expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()),
  213. overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy()));
  214. return oit;
  215. }
  216. public:
  217. template <typename RobustPolicy, typename OutputIterator, typename Strategy>
  218. static inline OutputIterator apply(MultiPoint const& multipoint,
  219. Linear const& linear,
  220. RobustPolicy const& robust_policy,
  221. OutputIterator oit,
  222. Strategy const& strategy)
  223. {
  224. typedef std::vector
  225. <
  226. typename boost::range_value<MultiPoint>::type
  227. > point_vector_type;
  228. point_vector_type common_points;
  229. // compute the common points
  230. get_common_points(multipoint, linear,
  231. std::back_inserter(common_points),
  232. strategy);
  233. return multipoint_multipoint_point
  234. <
  235. MultiPoint, point_vector_type, PointOut, OverlayType
  236. >::apply(multipoint, common_points, robust_policy, oit, strategy);
  237. }
  238. };
  239. }} // namespace detail::overlay
  240. #endif // DOXYGEN_NO_DETAIL
  241. #ifndef DOXYGEN_NO_DISPATCH
  242. namespace detail_dispatch { namespace overlay
  243. {
  244. // dispatch struct for pointlike-linear difference/intersection computation
  245. template
  246. <
  247. typename PointLike,
  248. typename Linear,
  249. typename PointOut,
  250. overlay_type OverlayType,
  251. typename Tag1,
  252. typename Tag2
  253. >
  254. struct pointlike_linear_point
  255. : not_implemented<PointLike, Linear, PointOut>
  256. {};
  257. template
  258. <
  259. typename Point,
  260. typename Linear,
  261. typename PointOut,
  262. overlay_type OverlayType
  263. >
  264. struct pointlike_linear_point
  265. <
  266. Point, Linear, PointOut, OverlayType, point_tag, linear_tag
  267. > : detail::overlay::point_single_point
  268. <
  269. Point, Linear, PointOut, OverlayType,
  270. detail::not_<detail::disjoint::reverse_covered_by>
  271. >
  272. {};
  273. template
  274. <
  275. typename Point,
  276. typename Segment,
  277. typename PointOut,
  278. overlay_type OverlayType
  279. >
  280. struct pointlike_linear_point
  281. <
  282. Point, Segment, PointOut, OverlayType, point_tag, segment_tag
  283. > : detail::overlay::point_single_point
  284. <
  285. Point, Segment, PointOut, OverlayType,
  286. detail::not_<detail::disjoint::reverse_covered_by>
  287. >
  288. {};
  289. template
  290. <
  291. typename MultiPoint,
  292. typename Linear,
  293. typename PointOut,
  294. overlay_type OverlayType
  295. >
  296. struct pointlike_linear_point
  297. <
  298. MultiPoint, Linear, PointOut, OverlayType, multi_point_tag, linear_tag
  299. > : detail::overlay::multipoint_linear_point
  300. <
  301. MultiPoint, Linear, PointOut, OverlayType,
  302. detail::not_<detail::disjoint::reverse_covered_by>
  303. >
  304. {};
  305. template
  306. <
  307. typename MultiPoint,
  308. typename Segment,
  309. typename PointOut,
  310. overlay_type OverlayType
  311. >
  312. struct pointlike_linear_point
  313. <
  314. MultiPoint, Segment, PointOut, OverlayType, multi_point_tag, segment_tag
  315. > : detail::overlay::multipoint_single_point
  316. <
  317. MultiPoint, Segment, PointOut, OverlayType,
  318. detail::not_<detail::disjoint::reverse_covered_by>
  319. >
  320. {};
  321. }} // namespace detail_dispatch::overlay
  322. #endif // DOXYGEN_NO_DISPATCH
  323. }} // namespace boost::geometry
  324. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP