linear_linear.hpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2014-2022, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  4. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  5. // Licensed under the Boost Software License version 1.0.
  6. // http://www.boost.org/users/license.html
  7. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP
  8. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP
  9. #include <algorithm>
  10. #include <vector>
  11. #include <boost/range/begin.hpp>
  12. #include <boost/range/end.hpp>
  13. #include <boost/geometry/core/tag.hpp>
  14. #include <boost/geometry/core/tags.hpp>
  15. #include <boost/geometry/algorithms/detail/relate/turns.hpp>
  16. #include <boost/geometry/algorithms/detail/turns/compare_turns.hpp>
  17. #include <boost/geometry/algorithms/detail/turns/filter_continue_turns.hpp>
  18. #include <boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp>
  19. #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
  20. #include <boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp>
  21. #include <boost/geometry/algorithms/convert.hpp>
  22. #include <boost/geometry/geometries/helper_geometry.hpp>
  23. namespace boost { namespace geometry
  24. {
  25. #ifndef DOXYGEN_NO_DETAIL
  26. namespace detail { namespace overlay
  27. {
  28. template
  29. <
  30. typename LineStringOut,
  31. overlay_type OverlayType,
  32. typename Geometry,
  33. typename GeometryTag
  34. >
  35. struct linear_linear_no_intersections;
  36. template <typename LineStringOut, typename LineString>
  37. struct linear_linear_no_intersections
  38. <
  39. LineStringOut, overlay_difference, LineString, linestring_tag
  40. >
  41. {
  42. template <typename OutputIterator>
  43. static inline OutputIterator apply(LineString const& linestring,
  44. OutputIterator oit)
  45. {
  46. LineStringOut ls_out;
  47. geometry::convert(linestring, ls_out);
  48. *oit++ = ls_out;
  49. return oit;
  50. }
  51. };
  52. template <typename LineStringOut, typename MultiLineString>
  53. struct linear_linear_no_intersections
  54. <
  55. LineStringOut,
  56. overlay_difference,
  57. MultiLineString,
  58. multi_linestring_tag
  59. >
  60. {
  61. template <typename OutputIterator>
  62. static inline OutputIterator apply(MultiLineString const& multilinestring,
  63. OutputIterator oit)
  64. {
  65. for (auto it = boost::begin(multilinestring); it != boost::end(multilinestring); ++it)
  66. {
  67. LineStringOut ls_out;
  68. geometry::convert(*it, ls_out);
  69. *oit++ = ls_out;
  70. }
  71. return oit;
  72. }
  73. };
  74. template <typename LineStringOut, typename Geometry, typename GeometryTag>
  75. struct linear_linear_no_intersections
  76. <
  77. LineStringOut, overlay_intersection, Geometry, GeometryTag
  78. >
  79. {
  80. template <typename OutputIterator>
  81. static inline OutputIterator apply(Geometry const&,
  82. OutputIterator oit)
  83. {
  84. return oit;
  85. }
  86. };
  87. template
  88. <
  89. typename Linear1,
  90. typename Linear2,
  91. typename LinestringOut,
  92. overlay_type OverlayType,
  93. bool EnableFilterContinueTurns = false,
  94. bool EnableRemoveDuplicateTurns = false,
  95. bool EnableDegenerateTurns = true,
  96. #ifdef BOOST_GEOMETRY_INTERSECTION_DO_NOT_INCLUDE_ISOLATED_POINTS
  97. bool EnableFollowIsolatedPoints = false
  98. #else
  99. bool EnableFollowIsolatedPoints = true
  100. #endif
  101. >
  102. class linear_linear_linestring
  103. {
  104. protected:
  105. struct assign_policy
  106. {
  107. static bool const include_no_turn = false;
  108. static bool const include_degenerate = EnableDegenerateTurns;
  109. static bool const include_opposite = false;
  110. static bool const include_start_turn = false;
  111. };
  112. template
  113. <
  114. typename Turns,
  115. typename LinearGeometry1,
  116. typename LinearGeometry2,
  117. typename Strategy,
  118. typename RobustPolicy
  119. >
  120. static inline void compute_turns(Turns& turns,
  121. LinearGeometry1 const& linear1,
  122. LinearGeometry2 const& linear2,
  123. Strategy const& strategy,
  124. RobustPolicy const& robust_policy)
  125. {
  126. turns.clear();
  127. detail::get_turns::no_interrupt_policy interrupt_policy;
  128. geometry::detail::relate::turns::get_turns
  129. <
  130. LinearGeometry1,
  131. LinearGeometry2,
  132. detail::get_turns::get_turn_info_type
  133. <
  134. LinearGeometry1,
  135. LinearGeometry2,
  136. assign_policy
  137. >
  138. >::apply(turns, linear1, linear2, interrupt_policy, strategy, robust_policy);
  139. }
  140. template
  141. <
  142. overlay_type OverlayTypeForFollow,
  143. bool FollowIsolatedPoints,
  144. typename Turns,
  145. typename LinearGeometry1,
  146. typename LinearGeometry2,
  147. typename OutputIterator,
  148. typename Strategy
  149. >
  150. static inline OutputIterator
  151. sort_and_follow_turns(Turns& turns,
  152. LinearGeometry1 const& linear1,
  153. LinearGeometry2 const& linear2,
  154. OutputIterator oit,
  155. Strategy const& strategy)
  156. {
  157. // remove turns that have no added value
  158. turns::filter_continue_turns
  159. <
  160. Turns,
  161. EnableFilterContinueTurns && OverlayType != overlay_intersection
  162. >::apply(turns);
  163. // sort by seg_id, distance, and operation
  164. std::sort(boost::begin(turns), boost::end(turns),
  165. detail::turns::less_seg_fraction_other_op<>());
  166. // remove duplicate turns
  167. turns::remove_duplicate_turns
  168. <
  169. Turns, EnableRemoveDuplicateTurns
  170. >::apply(turns, strategy);
  171. return detail::overlay::following::linear::follow
  172. <
  173. LinestringOut,
  174. LinearGeometry1,
  175. LinearGeometry2,
  176. OverlayTypeForFollow,
  177. FollowIsolatedPoints,
  178. !EnableFilterContinueTurns || OverlayType == overlay_intersection
  179. >::apply(linear1, linear2, boost::begin(turns), boost::end(turns),
  180. oit, strategy);
  181. }
  182. public:
  183. template
  184. <
  185. typename RobustPolicy, typename OutputIterator, typename Strategy
  186. >
  187. static inline OutputIterator apply(Linear1 const& linear1,
  188. Linear2 const& linear2,
  189. RobustPolicy const& robust_policy,
  190. OutputIterator oit,
  191. Strategy const& strategy)
  192. {
  193. typedef typename detail::relate::turns::get_turns
  194. <
  195. Linear1,
  196. Linear2,
  197. detail::get_turns::get_turn_info_type
  198. <
  199. Linear1,
  200. Linear2,
  201. assign_policy
  202. >
  203. >::template turn_info_type<Strategy, RobustPolicy>::type turn_info;
  204. typedef std::vector<turn_info> turns_container;
  205. turns_container turns;
  206. compute_turns(turns, linear1, linear2, strategy, robust_policy);
  207. if ( turns.empty() )
  208. {
  209. // the two linear geometries are disjoint
  210. return linear_linear_no_intersections
  211. <
  212. LinestringOut,
  213. OverlayType,
  214. Linear1,
  215. typename tag<Linear1>::type
  216. >::apply(linear1, oit);
  217. }
  218. return sort_and_follow_turns
  219. <
  220. OverlayType,
  221. EnableFollowIsolatedPoints
  222. && OverlayType == overlay_intersection
  223. >(turns, linear1, linear2, oit, strategy);
  224. }
  225. };
  226. template
  227. <
  228. typename Linear1,
  229. typename Linear2,
  230. typename LinestringOut,
  231. bool EnableFilterContinueTurns,
  232. bool EnableRemoveDuplicateTurns,
  233. bool EnableDegenerateTurns,
  234. bool EnableFollowIsolatedPoints
  235. >
  236. struct linear_linear_linestring
  237. <
  238. Linear1, Linear2, LinestringOut, overlay_union,
  239. EnableFilterContinueTurns, EnableRemoveDuplicateTurns,
  240. EnableDegenerateTurns, EnableFollowIsolatedPoints
  241. >
  242. {
  243. template
  244. <
  245. typename RobustPolicy, typename OutputIterator, typename Strategy
  246. >
  247. static inline OutputIterator apply(Linear1 const& linear1,
  248. Linear2 const& linear2,
  249. RobustPolicy const& robust_policy,
  250. OutputIterator oit,
  251. Strategy const& strategy)
  252. {
  253. oit = linear_linear_no_intersections
  254. <
  255. LinestringOut,
  256. overlay_difference,
  257. Linear1,
  258. typename tag<Linear1>::type
  259. >::apply(linear1, oit);
  260. return linear_linear_linestring
  261. <
  262. Linear2, Linear1, LinestringOut, overlay_difference,
  263. EnableFilterContinueTurns, EnableRemoveDuplicateTurns,
  264. EnableDegenerateTurns, EnableFollowIsolatedPoints
  265. >::apply(linear2, linear1, robust_policy, oit, strategy);
  266. }
  267. };
  268. }} // namespace detail::overlay
  269. #endif // DOXYGEN_NO_DETAIL
  270. }} // namespace boost::geometry
  271. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_LINEAR_LINEAR_HPP