self_turn_points.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
  4. // This file was modified by Oracle on 2017-2021.
  5. // Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
  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_OVERLAY_SELF_TURN_POINTS_HPP
  11. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP
  12. #include <cstddef>
  13. #include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
  14. #include <boost/geometry/algorithms/detail/partition.hpp>
  15. #include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
  16. #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
  17. #include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>
  18. #include <boost/geometry/core/coordinate_dimension.hpp>
  19. #include <boost/geometry/core/point_order.hpp>
  20. #include <boost/geometry/core/tags.hpp>
  21. #include <boost/geometry/geometries/box.hpp>
  22. #include <boost/geometry/geometries/concepts/check.hpp>
  23. #include <boost/geometry/strategies/detail.hpp>
  24. #include <boost/geometry/strategies/relate/services.hpp>
  25. #include <boost/geometry/util/condition.hpp>
  26. namespace boost { namespace geometry
  27. {
  28. #ifndef DOXYGEN_NO_DETAIL
  29. namespace detail { namespace self_get_turn_points
  30. {
  31. struct no_interrupt_policy
  32. {
  33. static bool const enabled = false;
  34. static bool const has_intersections = false;
  35. template <typename Range>
  36. static inline bool apply(Range const&)
  37. {
  38. return false;
  39. }
  40. };
  41. template
  42. <
  43. bool Reverse,
  44. typename Geometry,
  45. typename Turns,
  46. typename TurnPolicy,
  47. typename Strategy,
  48. typename RobustPolicy,
  49. typename InterruptPolicy
  50. >
  51. struct self_section_visitor
  52. {
  53. Geometry const& m_geometry;
  54. Strategy const& m_strategy;
  55. RobustPolicy const& m_rescale_policy;
  56. Turns& m_turns;
  57. InterruptPolicy& m_interrupt_policy;
  58. int m_source_index;
  59. bool m_skip_adjacent;
  60. inline self_section_visitor(Geometry const& g,
  61. Strategy const& s,
  62. RobustPolicy const& rp,
  63. Turns& turns,
  64. InterruptPolicy& ip,
  65. int source_index,
  66. bool skip_adjacent)
  67. : m_geometry(g)
  68. , m_strategy(s)
  69. , m_rescale_policy(rp)
  70. , m_turns(turns)
  71. , m_interrupt_policy(ip)
  72. , m_source_index(source_index)
  73. , m_skip_adjacent(skip_adjacent)
  74. {}
  75. template <typename Section>
  76. inline bool apply(Section const& sec1, Section const& sec2)
  77. {
  78. if (! detail::disjoint::disjoint_box_box(sec1.bounding_box,
  79. sec2.bounding_box,
  80. m_strategy)
  81. && ! sec1.duplicate
  82. && ! sec2.duplicate)
  83. {
  84. // false if interrupted
  85. return detail::get_turns::get_turns_in_sections
  86. <
  87. Geometry, Geometry,
  88. Reverse, Reverse,
  89. Section, Section,
  90. TurnPolicy
  91. >::apply(m_source_index, m_geometry, sec1,
  92. m_source_index, m_geometry, sec2,
  93. false, m_skip_adjacent,
  94. m_strategy,
  95. m_rescale_policy,
  96. m_turns, m_interrupt_policy);
  97. }
  98. return true;
  99. }
  100. };
  101. template <bool Reverse, typename TurnPolicy>
  102. struct get_turns
  103. {
  104. template <typename Geometry, typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
  105. static inline bool apply(
  106. Geometry const& geometry,
  107. Strategy const& strategy,
  108. RobustPolicy const& robust_policy,
  109. Turns& turns,
  110. InterruptPolicy& interrupt_policy,
  111. int source_index, bool skip_adjacent)
  112. {
  113. typedef model::box
  114. <
  115. typename geometry::robust_point_type
  116. <
  117. typename geometry::point_type<Geometry>::type,
  118. RobustPolicy
  119. >::type
  120. > box_type;
  121. // sectionalize in two dimensions to detect
  122. // all potential spikes correctly
  123. typedef geometry::sections<box_type, 2> sections_type;
  124. typedef std::integer_sequence<std::size_t, 0, 1> dimensions;
  125. sections_type sec;
  126. geometry::sectionalize<Reverse, dimensions>(geometry, robust_policy,
  127. sec, strategy);
  128. self_section_visitor
  129. <
  130. Reverse, Geometry,
  131. Turns, TurnPolicy, Strategy, RobustPolicy, InterruptPolicy
  132. > visitor(geometry, strategy, robust_policy, turns, interrupt_policy,
  133. source_index, skip_adjacent);
  134. // false if interrupted
  135. geometry::partition
  136. <
  137. box_type
  138. >::apply(sec, visitor,
  139. detail::section::get_section_box<Strategy>(strategy),
  140. detail::section::overlaps_section_box<Strategy>(strategy));
  141. return ! interrupt_policy.has_intersections;
  142. }
  143. };
  144. }} // namespace detail::self_get_turn_points
  145. #endif // DOXYGEN_NO_DETAIL
  146. #ifndef DOXYGEN_NO_DISPATCH
  147. namespace dispatch
  148. {
  149. template
  150. <
  151. bool Reverse,
  152. typename GeometryTag,
  153. typename Geometry,
  154. typename TurnPolicy
  155. >
  156. struct self_get_turn_points
  157. {
  158. };
  159. template
  160. <
  161. bool Reverse,
  162. typename Ring,
  163. typename TurnPolicy
  164. >
  165. struct self_get_turn_points
  166. <
  167. Reverse, ring_tag, Ring,
  168. TurnPolicy
  169. >
  170. : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
  171. {};
  172. template
  173. <
  174. bool Reverse,
  175. typename Box,
  176. typename TurnPolicy
  177. >
  178. struct self_get_turn_points
  179. <
  180. Reverse, box_tag, Box,
  181. TurnPolicy
  182. >
  183. {
  184. template <typename Strategy, typename RobustPolicy, typename Turns, typename InterruptPolicy>
  185. static inline bool apply(
  186. Box const& ,
  187. Strategy const& ,
  188. RobustPolicy const& ,
  189. Turns& ,
  190. InterruptPolicy& ,
  191. int /*source_index*/,
  192. bool /*skip_adjacent*/)
  193. {
  194. return true;
  195. }
  196. };
  197. template
  198. <
  199. bool Reverse,
  200. typename Polygon,
  201. typename TurnPolicy
  202. >
  203. struct self_get_turn_points
  204. <
  205. Reverse, polygon_tag, Polygon,
  206. TurnPolicy
  207. >
  208. : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
  209. {};
  210. template
  211. <
  212. bool Reverse,
  213. typename MultiPolygon,
  214. typename TurnPolicy
  215. >
  216. struct self_get_turn_points
  217. <
  218. Reverse, multi_polygon_tag, MultiPolygon,
  219. TurnPolicy
  220. >
  221. : detail::self_get_turn_points::get_turns<Reverse, TurnPolicy>
  222. {};
  223. } // namespace dispatch
  224. #endif // DOXYGEN_NO_DISPATCH
  225. namespace resolve_strategy
  226. {
  227. template
  228. <
  229. bool Reverse,
  230. typename AssignPolicy,
  231. typename Strategies,
  232. bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
  233. >
  234. struct self_get_turn_points
  235. {
  236. template
  237. <
  238. typename Geometry,
  239. typename RobustPolicy,
  240. typename Turns,
  241. typename InterruptPolicy
  242. >
  243. static inline void apply(Geometry const& geometry,
  244. Strategies const& strategies,
  245. RobustPolicy const& robust_policy,
  246. Turns& turns,
  247. InterruptPolicy& interrupt_policy,
  248. int source_index,
  249. bool skip_adjacent)
  250. {
  251. using turn_policy = detail::overlay::get_turn_info<AssignPolicy>;
  252. dispatch::self_get_turn_points
  253. <
  254. Reverse,
  255. typename tag<Geometry>::type,
  256. Geometry,
  257. turn_policy
  258. >::apply(geometry, strategies, robust_policy, turns, interrupt_policy,
  259. source_index, skip_adjacent);
  260. }
  261. };
  262. template <bool Reverse, typename AssignPolicy, typename Strategy>
  263. struct self_get_turn_points<Reverse, AssignPolicy, Strategy, false>
  264. {
  265. template
  266. <
  267. typename Geometry,
  268. typename RobustPolicy,
  269. typename Turns,
  270. typename InterruptPolicy
  271. >
  272. static inline void apply(Geometry const& geometry,
  273. Strategy const& strategy,
  274. RobustPolicy const& robust_policy,
  275. Turns& turns,
  276. InterruptPolicy& interrupt_policy,
  277. int source_index,
  278. bool skip_adjacent)
  279. {
  280. using strategies::relate::services::strategy_converter;
  281. self_get_turn_points
  282. <
  283. Reverse,
  284. AssignPolicy,
  285. decltype(strategy_converter<Strategy>::get(strategy))
  286. >::apply(geometry,
  287. strategy_converter<Strategy>::get(strategy),
  288. robust_policy,
  289. turns,
  290. interrupt_policy,
  291. source_index,
  292. skip_adjacent);
  293. }
  294. };
  295. } // namespace resolve_strategy
  296. #ifndef DOXYGEN_NO_DETAIL
  297. namespace detail { namespace self_get_turn_points
  298. {
  299. // Version where Reverse can be specified manually. TODO:
  300. // can most probably be merged with self_get_turn_points::get_turn
  301. template
  302. <
  303. bool Reverse,
  304. typename AssignPolicy,
  305. typename Geometry,
  306. typename Strategy,
  307. typename RobustPolicy,
  308. typename Turns,
  309. typename InterruptPolicy
  310. >
  311. inline void self_turns(Geometry const& geometry,
  312. Strategy const& strategy,
  313. RobustPolicy const& robust_policy,
  314. Turns& turns,
  315. InterruptPolicy& interrupt_policy,
  316. int source_index = 0,
  317. bool skip_adjacent = false)
  318. {
  319. concepts::check<Geometry const>();
  320. resolve_strategy::self_get_turn_points
  321. <
  322. Reverse, AssignPolicy, Strategy
  323. >::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
  324. source_index, skip_adjacent);
  325. }
  326. }} // namespace detail::self_get_turn_points
  327. #endif // DOXYGEN_NO_DETAIL
  328. /*!
  329. \brief Calculate self intersections of a geometry
  330. \ingroup overlay
  331. \tparam Geometry geometry type
  332. \tparam Turns type of intersection container
  333. (e.g. vector of "intersection/turn point"'s)
  334. \param geometry geometry
  335. \param strategy strategy to be used
  336. \param robust_policy policy to handle robustness issues
  337. \param turns container which will contain intersection points
  338. \param interrupt_policy policy determining if process is stopped
  339. when intersection is found
  340. \param source_index source index for generated turns
  341. \param skip_adjacent indicates if adjacent turns should be skipped
  342. */
  343. template
  344. <
  345. typename AssignPolicy,
  346. typename Geometry,
  347. typename Strategy,
  348. typename RobustPolicy,
  349. typename Turns,
  350. typename InterruptPolicy
  351. >
  352. inline void self_turns(Geometry const& geometry,
  353. Strategy const& strategy,
  354. RobustPolicy const& robust_policy,
  355. Turns& turns,
  356. InterruptPolicy& interrupt_policy,
  357. int source_index = 0,
  358. bool skip_adjacent = false)
  359. {
  360. concepts::check<Geometry const>();
  361. static bool const reverse = detail::overlay::do_reverse
  362. <
  363. geometry::point_order<Geometry>::value
  364. >::value;
  365. resolve_strategy::self_get_turn_points
  366. <
  367. reverse, AssignPolicy, Strategy
  368. >::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
  369. source_index, skip_adjacent);
  370. }
  371. }} // namespace boost::geometry
  372. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP