disjoint_segment_box.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. // Boost.Geometry
  2. // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
  5. // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
  6. // This file was modified by Oracle on 2013-2019.
  7. // Modifications copyright (c) 2013-2019, Oracle and/or its affiliates.
  8. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  9. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  10. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  11. // Use, modification and distribution is subject to the Boost Software License,
  12. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  13. // http://www.boost.org/LICENSE_1_0.txt)
  14. #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP
  15. #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP
  16. #include <cstddef>
  17. #include <utility>
  18. #include <boost/geometry/core/access.hpp>
  19. #include <boost/geometry/core/tags.hpp>
  20. #include <boost/geometry/core/coordinate_dimension.hpp>
  21. #include <boost/geometry/core/point_type.hpp>
  22. #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
  23. #include <boost/geometry/strategies/cartesian/point_in_box.hpp>
  24. #include <boost/geometry/strategies/disjoint.hpp>
  25. #include <boost/geometry/util/math.hpp>
  26. #include <boost/geometry/util/numeric_cast.hpp>
  27. #include <boost/geometry/util/calculation_type.hpp>
  28. namespace boost { namespace geometry { namespace strategy { namespace disjoint
  29. {
  30. namespace detail
  31. {
  32. template <std::size_t I>
  33. struct compute_tmin_tmax_per_dim
  34. {
  35. template <typename SegmentPoint, typename Box, typename RelativeDistance>
  36. static inline void apply(SegmentPoint const& p0,
  37. SegmentPoint const& p1,
  38. Box const& box,
  39. RelativeDistance& ti_min,
  40. RelativeDistance& ti_max,
  41. RelativeDistance& diff)
  42. {
  43. using box_coordinate_type = coordinate_type_t<Box>;
  44. using point_coordinate_type = coordinate_type_t<SegmentPoint>;
  45. RelativeDistance c_p0 = util::numeric_cast
  46. <
  47. point_coordinate_type
  48. >( geometry::get<I>(p0) );
  49. RelativeDistance c_p1 = util::numeric_cast
  50. <
  51. point_coordinate_type
  52. >( geometry::get<I>(p1) );
  53. RelativeDistance c_b_min = util::numeric_cast
  54. <
  55. box_coordinate_type
  56. >( geometry::get<geometry::min_corner, I>(box) );
  57. RelativeDistance c_b_max = util::numeric_cast
  58. <
  59. box_coordinate_type
  60. >( geometry::get<geometry::max_corner, I>(box) );
  61. if ( geometry::get<I>(p1) >= geometry::get<I>(p0) )
  62. {
  63. diff = c_p1 - c_p0;
  64. ti_min = c_b_min - c_p0;
  65. ti_max = c_b_max - c_p0;
  66. }
  67. else
  68. {
  69. diff = c_p0 - c_p1;
  70. ti_min = c_p0 - c_b_max;
  71. ti_max = c_p0 - c_b_min;
  72. }
  73. }
  74. };
  75. template
  76. <
  77. typename RelativeDistance,
  78. typename SegmentPoint,
  79. typename Box,
  80. std::size_t I,
  81. std::size_t Dimension
  82. >
  83. struct disjoint_segment_box_impl
  84. {
  85. template <typename RelativeDistancePair>
  86. static inline bool apply(SegmentPoint const& p0,
  87. SegmentPoint const& p1,
  88. Box const& box,
  89. RelativeDistancePair& t_min,
  90. RelativeDistancePair& t_max)
  91. {
  92. RelativeDistance ti_min, ti_max, diff;
  93. compute_tmin_tmax_per_dim<I>::apply(p0, p1, box, ti_min, ti_max, diff);
  94. if ( geometry::math::equals(diff, 0) )
  95. {
  96. if ( (geometry::math::equals(t_min.second, 0)
  97. && t_min.first > ti_max)
  98. ||
  99. (geometry::math::equals(t_max.second, 0)
  100. && t_max.first < ti_min)
  101. ||
  102. (math::sign(ti_min) * math::sign(ti_max) > 0) )
  103. {
  104. return true;
  105. }
  106. }
  107. RelativeDistance t_min_x_diff = t_min.first * diff;
  108. RelativeDistance t_max_x_diff = t_max.first * diff;
  109. if ( t_min_x_diff > ti_max * t_min.second
  110. || t_max_x_diff < ti_min * t_max.second )
  111. {
  112. return true;
  113. }
  114. if ( ti_min * t_min.second > t_min_x_diff )
  115. {
  116. t_min.first = ti_min;
  117. t_min.second = diff;
  118. }
  119. if ( ti_max * t_max.second < t_max_x_diff )
  120. {
  121. t_max.first = ti_max;
  122. t_max.second = diff;
  123. }
  124. if ( t_min.first > t_min.second || t_max.first < 0 )
  125. {
  126. return true;
  127. }
  128. return disjoint_segment_box_impl
  129. <
  130. RelativeDistance,
  131. SegmentPoint,
  132. Box,
  133. I + 1,
  134. Dimension
  135. >::apply(p0, p1, box, t_min, t_max);
  136. }
  137. };
  138. template
  139. <
  140. typename RelativeDistance,
  141. typename SegmentPoint,
  142. typename Box,
  143. std::size_t Dimension
  144. >
  145. struct disjoint_segment_box_impl
  146. <
  147. RelativeDistance, SegmentPoint, Box, 0, Dimension
  148. >
  149. {
  150. static inline bool apply(SegmentPoint const& p0,
  151. SegmentPoint const& p1,
  152. Box const& box)
  153. {
  154. std::pair<RelativeDistance, RelativeDistance> t_min, t_max;
  155. RelativeDistance diff;
  156. compute_tmin_tmax_per_dim<0>::apply(p0, p1, box,
  157. t_min.first, t_max.first, diff);
  158. if ( geometry::math::equals(diff, 0) )
  159. {
  160. if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; }
  161. if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; }
  162. if (math::sign(t_min.first) * math::sign(t_max.first) > 0)
  163. {
  164. return true;
  165. }
  166. }
  167. if ( t_min.first > diff || t_max.first < 0 )
  168. {
  169. return true;
  170. }
  171. t_min.second = t_max.second = diff;
  172. return disjoint_segment_box_impl
  173. <
  174. RelativeDistance, SegmentPoint, Box, 1, Dimension
  175. >::apply(p0, p1, box, t_min, t_max);
  176. }
  177. };
  178. template
  179. <
  180. typename RelativeDistance,
  181. typename SegmentPoint,
  182. typename Box,
  183. std::size_t Dimension
  184. >
  185. struct disjoint_segment_box_impl
  186. <
  187. RelativeDistance, SegmentPoint, Box, Dimension, Dimension
  188. >
  189. {
  190. template <typename RelativeDistancePair>
  191. static inline bool apply(SegmentPoint const&, SegmentPoint const&,
  192. Box const&,
  193. RelativeDistancePair&, RelativeDistancePair&)
  194. {
  195. return false;
  196. }
  197. };
  198. } // namespace detail
  199. // NOTE: This may be temporary place for this or corresponding strategy
  200. // It seems to be more appropriate to implement the opposite of it
  201. // e.g. intersection::segment_box because in disjoint() algorithm
  202. // other strategies that are used are intersection and covered_by strategies.
  203. struct segment_box
  204. {
  205. typedef covered_by::cartesian_point_box disjoint_point_box_strategy_type;
  206. static inline disjoint_point_box_strategy_type get_disjoint_point_box_strategy()
  207. {
  208. return disjoint_point_box_strategy_type();
  209. }
  210. template <typename Segment, typename Box>
  211. static inline bool apply(Segment const& segment, Box const& box)
  212. {
  213. assert_dimension_equal<Segment, Box>();
  214. using relative_distance_type = typename util::calculation_type::geometric::binary
  215. <
  216. Segment, Box, void
  217. >::type;
  218. using segment_point_type = point_type_t<Segment>;
  219. segment_point_type p0, p1;
  220. geometry::detail::assign_point_from_index<0>(segment, p0);
  221. geometry::detail::assign_point_from_index<1>(segment, p1);
  222. return detail::disjoint_segment_box_impl
  223. <
  224. relative_distance_type, segment_point_type, Box,
  225. 0, dimension<Box>::value
  226. >::apply(p0, p1, box);
  227. }
  228. };
  229. #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  230. namespace services
  231. {
  232. template <typename Linear, typename Box, typename LinearTag>
  233. struct default_strategy<Linear, Box, LinearTag, box_tag, 1, 2, cartesian_tag, cartesian_tag>
  234. {
  235. typedef disjoint::segment_box type;
  236. };
  237. template <typename Box, typename Linear, typename LinearTag>
  238. struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1, cartesian_tag, cartesian_tag>
  239. {
  240. typedef disjoint::segment_box type;
  241. };
  242. } // namespace services
  243. #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  244. }}}} // namespace boost::geometry::strategy::disjoint
  245. #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP