disjoint_segment_box.hpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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-2017.
  7. // Modifications copyright (c) 2013-2017, 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/numeric/conversion/cast.hpp>
  19. #include <boost/geometry/util/math.hpp>
  20. #include <boost/geometry/util/calculation_type.hpp>
  21. #include <boost/geometry/core/access.hpp>
  22. #include <boost/geometry/core/tags.hpp>
  23. #include <boost/geometry/core/coordinate_dimension.hpp>
  24. #include <boost/geometry/core/point_type.hpp>
  25. #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
  26. #include <boost/geometry/strategies/disjoint.hpp>
  27. namespace boost { namespace geometry { namespace strategy { namespace disjoint
  28. {
  29. namespace detail
  30. {
  31. template <std::size_t I>
  32. struct compute_tmin_tmax_per_dim
  33. {
  34. template <typename SegmentPoint, typename Box, typename RelativeDistance>
  35. static inline void apply(SegmentPoint const& p0,
  36. SegmentPoint const& p1,
  37. Box const& box,
  38. RelativeDistance& ti_min,
  39. RelativeDistance& ti_max,
  40. RelativeDistance& diff)
  41. {
  42. typedef typename coordinate_type<Box>::type box_coordinate_type;
  43. typedef typename coordinate_type
  44. <
  45. SegmentPoint
  46. >::type point_coordinate_type;
  47. RelativeDistance c_p0 = boost::numeric_cast
  48. <
  49. point_coordinate_type
  50. >( geometry::get<I>(p0) );
  51. RelativeDistance c_p1 = boost::numeric_cast
  52. <
  53. point_coordinate_type
  54. >( geometry::get<I>(p1) );
  55. RelativeDistance c_b_min = boost::numeric_cast
  56. <
  57. box_coordinate_type
  58. >( geometry::get<geometry::min_corner, I>(box) );
  59. RelativeDistance c_b_max = boost::numeric_cast
  60. <
  61. box_coordinate_type
  62. >( geometry::get<geometry::max_corner, I>(box) );
  63. if ( geometry::get<I>(p1) >= geometry::get<I>(p0) )
  64. {
  65. diff = c_p1 - c_p0;
  66. ti_min = c_b_min - c_p0;
  67. ti_max = c_b_max - c_p0;
  68. }
  69. else
  70. {
  71. diff = c_p0 - c_p1;
  72. ti_min = c_p0 - c_b_max;
  73. ti_max = c_p0 - c_b_min;
  74. }
  75. }
  76. };
  77. template
  78. <
  79. typename RelativeDistance,
  80. typename SegmentPoint,
  81. typename Box,
  82. std::size_t I,
  83. std::size_t Dimension
  84. >
  85. struct disjoint_segment_box_impl
  86. {
  87. template <typename RelativeDistancePair>
  88. static inline bool apply(SegmentPoint const& p0,
  89. SegmentPoint const& p1,
  90. Box const& box,
  91. RelativeDistancePair& t_min,
  92. RelativeDistancePair& t_max)
  93. {
  94. RelativeDistance ti_min, ti_max, diff;
  95. compute_tmin_tmax_per_dim<I>::apply(p0, p1, box, ti_min, ti_max, diff);
  96. if ( geometry::math::equals(diff, 0) )
  97. {
  98. if ( (geometry::math::equals(t_min.second, 0)
  99. && t_min.first > ti_max)
  100. ||
  101. (geometry::math::equals(t_max.second, 0)
  102. && t_max.first < ti_min)
  103. ||
  104. (math::sign(ti_min) * math::sign(ti_max) > 0) )
  105. {
  106. return true;
  107. }
  108. }
  109. RelativeDistance t_min_x_diff = t_min.first * diff;
  110. RelativeDistance t_max_x_diff = t_max.first * diff;
  111. if ( t_min_x_diff > ti_max * t_min.second
  112. || t_max_x_diff < ti_min * t_max.second )
  113. {
  114. return true;
  115. }
  116. if ( ti_min * t_min.second > t_min_x_diff )
  117. {
  118. t_min.first = ti_min;
  119. t_min.second = diff;
  120. }
  121. if ( ti_max * t_max.second < t_max_x_diff )
  122. {
  123. t_max.first = ti_max;
  124. t_max.second = diff;
  125. }
  126. if ( t_min.first > t_min.second || t_max.first < 0 )
  127. {
  128. return true;
  129. }
  130. return disjoint_segment_box_impl
  131. <
  132. RelativeDistance,
  133. SegmentPoint,
  134. Box,
  135. I + 1,
  136. Dimension
  137. >::apply(p0, p1, box, t_min, t_max);
  138. }
  139. };
  140. template
  141. <
  142. typename RelativeDistance,
  143. typename SegmentPoint,
  144. typename Box,
  145. std::size_t Dimension
  146. >
  147. struct disjoint_segment_box_impl
  148. <
  149. RelativeDistance, SegmentPoint, Box, 0, Dimension
  150. >
  151. {
  152. static inline bool apply(SegmentPoint const& p0,
  153. SegmentPoint const& p1,
  154. Box const& box)
  155. {
  156. std::pair<RelativeDistance, RelativeDistance> t_min, t_max;
  157. RelativeDistance diff;
  158. compute_tmin_tmax_per_dim<0>::apply(p0, p1, box,
  159. t_min.first, t_max.first, diff);
  160. if ( geometry::math::equals(diff, 0) )
  161. {
  162. if ( geometry::math::equals(t_min.first, 0) ) { t_min.first = -1; }
  163. if ( geometry::math::equals(t_max.first, 0) ) { t_max.first = 1; }
  164. if (math::sign(t_min.first) * math::sign(t_max.first) > 0)
  165. {
  166. return true;
  167. }
  168. }
  169. if ( t_min.first > diff || t_max.first < 0 )
  170. {
  171. return true;
  172. }
  173. t_min.second = t_max.second = diff;
  174. return disjoint_segment_box_impl
  175. <
  176. RelativeDistance, SegmentPoint, Box, 1, Dimension
  177. >::apply(p0, p1, box, t_min, t_max);
  178. }
  179. };
  180. template
  181. <
  182. typename RelativeDistance,
  183. typename SegmentPoint,
  184. typename Box,
  185. std::size_t Dimension
  186. >
  187. struct disjoint_segment_box_impl
  188. <
  189. RelativeDistance, SegmentPoint, Box, Dimension, Dimension
  190. >
  191. {
  192. template <typename RelativeDistancePair>
  193. static inline bool apply(SegmentPoint const&, SegmentPoint const&,
  194. Box const&,
  195. RelativeDistancePair&, RelativeDistancePair&)
  196. {
  197. return false;
  198. }
  199. };
  200. } // namespace detail
  201. // NOTE: This may be temporary place for this or corresponding strategy
  202. // It seems to be more appropriate to implement the opposite of it
  203. // e.g. intersection::segment_box because in disjoint() algorithm
  204. // other strategies that are used are intersection and covered_by strategies.
  205. struct segment_box
  206. {
  207. template <typename Segment, typename Box>
  208. struct point_in_geometry_strategy
  209. : services::default_strategy
  210. <
  211. typename point_type<Segment>::type,
  212. Box
  213. >
  214. {};
  215. template <typename Segment, typename Box>
  216. static inline typename point_in_geometry_strategy<Segment, Box>::type
  217. get_point_in_geometry_strategy()
  218. {
  219. typedef typename point_in_geometry_strategy<Segment, Box>::type strategy_type;
  220. return strategy_type();
  221. }
  222. template <typename Segment, typename Box>
  223. static inline bool apply(Segment const& segment, Box const& box)
  224. {
  225. assert_dimension_equal<Segment, Box>();
  226. typedef typename util::calculation_type::geometric::binary
  227. <
  228. Segment, Box, void
  229. >::type relative_distance_type;
  230. typedef typename point_type<Segment>::type segment_point_type;
  231. segment_point_type p0, p1;
  232. geometry::detail::assign_point_from_index<0>(segment, p0);
  233. geometry::detail::assign_point_from_index<1>(segment, p1);
  234. return detail::disjoint_segment_box_impl
  235. <
  236. relative_distance_type, segment_point_type, Box,
  237. 0, dimension<Box>::value
  238. >::apply(p0, p1, box);
  239. }
  240. };
  241. #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  242. namespace services
  243. {
  244. template <typename Linear, typename Box, typename LinearTag>
  245. struct default_strategy<Linear, Box, LinearTag, box_tag, 1, 2, cartesian_tag, cartesian_tag>
  246. {
  247. typedef disjoint::segment_box type;
  248. };
  249. template <typename Box, typename Linear, typename LinearTag>
  250. struct default_strategy<Box, Linear, box_tag, LinearTag, 2, 1, cartesian_tag, cartesian_tag>
  251. {
  252. typedef disjoint::segment_box type;
  253. };
  254. } // namespace services
  255. #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
  256. }}}} // namespace boost::geometry::strategy::disjoint
  257. #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISJOINT_SEGMENT_BOX_HPP