self_turn_points.hpp 11 KB

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