turns.hpp 9.4 KB

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