turns.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
  3. // This file was modified by Oracle on 2013-2022.
  4. // Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
  5. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  6. // Contributed and/or modified by Menelaos Karavelas, 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_RELATE_TURNS_HPP
  11. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP
  12. #include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
  13. #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
  14. #include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
  15. #include <boost/geometry/geometries/helper_geometry.hpp>
  16. #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
  17. #include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
  18. #include <boost/geometry/strategies/cartesian/point_in_point.hpp>
  19. #include <boost/geometry/strategies/spherical/point_in_point.hpp>
  20. #include <boost/geometry/strategies/distance.hpp>
  21. namespace boost { namespace geometry {
  22. #ifndef DOXYGEN_NO_DETAIL
  23. namespace detail { namespace relate { namespace turns {
  24. template <bool IncludeDegenerate = false>
  25. struct assign_policy
  26. : overlay::assign_null_policy
  27. {
  28. static bool const include_degenerate = IncludeDegenerate;
  29. };
  30. // turn retriever, calling get_turns
  31. template
  32. <
  33. typename Geometry1,
  34. typename Geometry2,
  35. typename GetTurnPolicy = detail::get_turns::get_turn_info_type
  36. <
  37. Geometry1, Geometry2, assign_policy<>
  38. >
  39. >
  40. struct get_turns
  41. {
  42. using turn_point_type = typename helper_geometry
  43. <
  44. typename geometry::point_type<Geometry1>::type
  45. >::type;
  46. template <typename Strategy>
  47. struct robust_policy_type
  48. : geometry::rescale_overlay_policy_type
  49. <
  50. Geometry1,
  51. Geometry2,
  52. typename Strategy::cs_tag
  53. >
  54. {};
  55. template
  56. <
  57. typename Strategy,
  58. typename RobustPolicy = typename robust_policy_type<Strategy>::type
  59. >
  60. struct turn_info_type
  61. {
  62. using ratio_type = typename segment_ratio_type<turn_point_type, RobustPolicy>::type;
  63. using type = overlay::turn_info
  64. <
  65. turn_point_type,
  66. ratio_type,
  67. typename detail::get_turns::turn_operation_type
  68. <
  69. Geometry1, Geometry2, turn_point_type, ratio_type
  70. >::type
  71. >;
  72. };
  73. template <typename Turns, typename InterruptPolicy, typename Strategy>
  74. static inline void apply(Turns & turns,
  75. Geometry1 const& geometry1,
  76. Geometry2 const& geometry2,
  77. InterruptPolicy & interrupt_policy,
  78. Strategy const& strategy)
  79. {
  80. typedef typename robust_policy_type<Strategy>::type robust_policy_t;
  81. robust_policy_t robust_policy
  82. = geometry::get_rescale_policy<robust_policy_t>(
  83. geometry1, geometry2, strategy);
  84. apply(turns, geometry1, geometry2, interrupt_policy, strategy, robust_policy);
  85. }
  86. template <typename Turns, typename InterruptPolicy, typename Strategy, typename RobustPolicy>
  87. static inline void apply(Turns & turns,
  88. Geometry1 const& geometry1,
  89. Geometry2 const& geometry2,
  90. InterruptPolicy & interrupt_policy,
  91. Strategy const& strategy,
  92. RobustPolicy const& robust_policy)
  93. {
  94. static const bool reverse1 = detail::overlay::do_reverse
  95. <
  96. geometry::point_order<Geometry1>::value
  97. >::value;
  98. static const bool reverse2 = detail::overlay::do_reverse
  99. <
  100. geometry::point_order<Geometry2>::value
  101. >::value;
  102. dispatch::get_turns
  103. <
  104. typename geometry::tag<Geometry1>::type,
  105. typename geometry::tag<Geometry2>::type,
  106. Geometry1,
  107. Geometry2,
  108. reverse1,
  109. reverse2,
  110. GetTurnPolicy
  111. >::apply(0, geometry1, 1, geometry2,
  112. strategy, robust_policy,
  113. turns, interrupt_policy);
  114. }
  115. };
  116. // TURNS SORTING AND SEARCHING
  117. template <int N = 0, int U = 1, int I = 2, int B = 3, int C = 4, int O = 0>
  118. struct op_to_int
  119. {
  120. template <typename Operation>
  121. inline int operator()(Operation const& op) const
  122. {
  123. switch(op.operation)
  124. {
  125. case detail::overlay::operation_none : return N;
  126. case detail::overlay::operation_union : return U;
  127. case detail::overlay::operation_intersection : return I;
  128. case detail::overlay::operation_blocked : return B;
  129. case detail::overlay::operation_continue : return C;
  130. case detail::overlay::operation_opposite : return O;
  131. }
  132. return -1;
  133. }
  134. };
  135. template <std::size_t OpId, typename OpToInt>
  136. struct less_op_xxx_linear
  137. {
  138. template <typename Turn>
  139. inline bool operator()(Turn const& left, Turn const& right) const
  140. {
  141. static OpToInt op_to_int;
  142. return op_to_int(left.operations[OpId]) < op_to_int(right.operations[OpId]);
  143. }
  144. };
  145. template <std::size_t OpId>
  146. struct less_op_linear_linear
  147. : less_op_xxx_linear< OpId, op_to_int<0,2,3,1,4,0> > // xuic
  148. {};
  149. template <std::size_t OpId>
  150. struct less_op_linear_areal_single
  151. {
  152. template <typename Turn>
  153. inline bool operator()(Turn const& left, Turn const& right) const
  154. {
  155. static const std::size_t other_op_id = (OpId + 1) % 2;
  156. static turns::op_to_int<0,2,3,1,4,0> op_to_int_xuic;
  157. static turns::op_to_int<0,3,2,1,4,0> op_to_int_xiuc;
  158. segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;
  159. segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;
  160. typedef typename Turn::turn_operation_type operation_type;
  161. operation_type const& left_operation = left.operations[OpId];
  162. operation_type const& right_operation = right.operations[OpId];
  163. if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )
  164. {
  165. return op_to_int_xuic(left_operation)
  166. < op_to_int_xuic(right_operation);
  167. }
  168. else
  169. {
  170. return op_to_int_xiuc(left_operation)
  171. < op_to_int_xiuc(right_operation);
  172. }
  173. }
  174. };
  175. template <std::size_t OpId>
  176. struct less_op_areal_linear
  177. : less_op_xxx_linear< OpId, op_to_int<0,1,0,0,2,0> >
  178. {};
  179. template <std::size_t OpId>
  180. struct less_op_areal_areal
  181. {
  182. template <typename Turn>
  183. inline bool operator()(Turn const& left, Turn const& right) const
  184. {
  185. static const std::size_t other_op_id = (OpId + 1) % 2;
  186. static op_to_int<0, 1, 2, 3, 4, 0> op_to_int_uixc;
  187. static op_to_int<0, 2, 1, 3, 4, 0> op_to_int_iuxc;
  188. segment_identifier const& left_other_seg_id = left.operations[other_op_id].seg_id;
  189. segment_identifier const& right_other_seg_id = right.operations[other_op_id].seg_id;
  190. typedef typename Turn::turn_operation_type operation_type;
  191. operation_type const& left_operation = left.operations[OpId];
  192. operation_type const& right_operation = right.operations[OpId];
  193. if ( left_other_seg_id.multi_index == right_other_seg_id.multi_index )
  194. {
  195. if ( left_other_seg_id.ring_index == right_other_seg_id.ring_index )
  196. {
  197. return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation);
  198. }
  199. else
  200. {
  201. if ( left_other_seg_id.ring_index == -1 )
  202. {
  203. if ( left_operation.operation == overlay::operation_union )
  204. return false;
  205. else if ( left_operation.operation == overlay::operation_intersection )
  206. return true;
  207. }
  208. else if ( right_other_seg_id.ring_index == -1 )
  209. {
  210. if ( right_operation.operation == overlay::operation_union )
  211. return true;
  212. else if ( right_operation.operation == overlay::operation_intersection )
  213. return false;
  214. }
  215. return op_to_int_iuxc(left_operation) < op_to_int_iuxc(right_operation);
  216. }
  217. }
  218. else
  219. {
  220. return op_to_int_uixc(left_operation) < op_to_int_uixc(right_operation);
  221. }
  222. }
  223. };
  224. template <std::size_t OpId>
  225. struct less_other_multi_index
  226. {
  227. static const std::size_t other_op_id = (OpId + 1) % 2;
  228. template <typename Turn>
  229. inline bool operator()(Turn const& left, Turn const& right) const
  230. {
  231. return left.operations[other_op_id].seg_id.multi_index
  232. < right.operations[other_op_id].seg_id.multi_index;
  233. }
  234. };
  235. // sort turns by G1 - source_index == 0 by:
  236. // seg_id -> distance and coordinates -> operation
  237. template <std::size_t OpId, typename LessOp, typename Strategy>
  238. struct less
  239. {
  240. BOOST_STATIC_ASSERT(OpId < 2);
  241. template <typename Turn>
  242. static inline bool use_fraction(Turn const& left, Turn const& right)
  243. {
  244. using eq_pp_strategy_type = decltype(std::declval<Strategy>().relate(
  245. detail::dummy_point(), detail::dummy_point()));
  246. static LessOp less_op;
  247. // NOTE: Assuming fraction is more permissive and faster than
  248. // comparison of points with strategy.
  249. return geometry::math::equals(left.operations[OpId].fraction,
  250. right.operations[OpId].fraction)
  251. && eq_pp_strategy_type::apply(left.point, right.point)
  252. ?
  253. less_op(left, right)
  254. :
  255. (left.operations[OpId].fraction < right.operations[OpId].fraction)
  256. ;
  257. }
  258. template <typename Turn>
  259. inline bool operator()(Turn const& left, Turn const& right) const
  260. {
  261. segment_identifier const& sl = left.operations[OpId].seg_id;
  262. segment_identifier const& sr = right.operations[OpId].seg_id;
  263. return sl < sr || ( sl == sr && use_fraction(left, right) );
  264. }
  265. };
  266. }}} // namespace detail::relate::turns
  267. #endif // DOXYGEN_NO_DETAIL
  268. }} // namespace boost::geometry
  269. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_TURNS_HPP