turns.hpp 10 KB

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