segment_intersection.hpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Boost.Geometry Index
  2. //
  3. // n-dimensional box-segment intersection
  4. //
  5. // Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
  6. //
  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_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP
  11. #define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP
  12. namespace boost { namespace geometry { namespace index { namespace detail {
  13. //template <typename Indexable, typename Point>
  14. //struct default_relative_distance_type
  15. //{
  16. // typedef typename select_most_precise<
  17. // typename select_most_precise<
  18. // typename coordinate_type<Indexable>::type,
  19. // typename coordinate_type<Point>::type
  20. // >::type,
  21. // float // TODO - use bigger type, calculated from the size of coordinate types
  22. // >::type type;
  23. //
  24. //
  25. // BOOST_MPL_ASSERT_MSG((!::boost::is_unsigned<type>::value),
  26. // THIS_TYPE_SHOULDNT_BE_UNSIGNED, (type));
  27. //};
  28. namespace dispatch {
  29. template <typename Box, typename Point, size_t I>
  30. struct box_segment_intersection_dim
  31. {
  32. BOOST_STATIC_ASSERT(0 <= dimension<Box>::value);
  33. BOOST_STATIC_ASSERT(0 <= dimension<Point>::value);
  34. BOOST_STATIC_ASSERT(I < size_t(dimension<Box>::value));
  35. BOOST_STATIC_ASSERT(I < size_t(dimension<Point>::value));
  36. BOOST_STATIC_ASSERT(dimension<Point>::value == dimension<Box>::value);
  37. // WARNING! - RelativeDistance must be IEEE float for this to work
  38. template <typename RelativeDistance>
  39. static inline bool apply(Box const& b, Point const& p0, Point const& p1,
  40. RelativeDistance & t_near, RelativeDistance & t_far)
  41. {
  42. RelativeDistance ray_d = geometry::get<I>(p1) - geometry::get<I>(p0);
  43. RelativeDistance tn = ( geometry::get<min_corner, I>(b) - geometry::get<I>(p0) ) / ray_d;
  44. RelativeDistance tf = ( geometry::get<max_corner, I>(b) - geometry::get<I>(p0) ) / ray_d;
  45. if ( tf < tn )
  46. ::std::swap(tn, tf);
  47. if ( t_near < tn )
  48. t_near = tn;
  49. if ( tf < t_far )
  50. t_far = tf;
  51. return 0 <= t_far && t_near <= t_far;
  52. }
  53. };
  54. template <typename Box, typename Point, size_t CurrentDimension>
  55. struct box_segment_intersection
  56. {
  57. BOOST_STATIC_ASSERT(0 < CurrentDimension);
  58. typedef box_segment_intersection_dim<Box, Point, CurrentDimension - 1> for_dim;
  59. template <typename RelativeDistance>
  60. static inline bool apply(Box const& b, Point const& p0, Point const& p1,
  61. RelativeDistance & t_near, RelativeDistance & t_far)
  62. {
  63. return box_segment_intersection<Box, Point, CurrentDimension - 1>::apply(b, p0, p1, t_near, t_far)
  64. && for_dim::apply(b, p0, p1, t_near, t_far);
  65. }
  66. };
  67. template <typename Box, typename Point>
  68. struct box_segment_intersection<Box, Point, 1>
  69. {
  70. typedef box_segment_intersection_dim<Box, Point, 0> for_dim;
  71. template <typename RelativeDistance>
  72. static inline bool apply(Box const& b, Point const& p0, Point const& p1,
  73. RelativeDistance & t_near, RelativeDistance & t_far)
  74. {
  75. return for_dim::apply(b, p0, p1, t_near, t_far);
  76. }
  77. };
  78. template <typename Indexable, typename Point, typename Tag>
  79. struct segment_intersection
  80. {
  81. BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_GEOMETRY, (segment_intersection));
  82. };
  83. template <typename Indexable, typename Point>
  84. struct segment_intersection<Indexable, Point, point_tag>
  85. {
  86. BOOST_MPL_ASSERT_MSG((false), SEGMENT_POINT_INTERSECTION_UNAVAILABLE, (segment_intersection));
  87. };
  88. template <typename Indexable, typename Point>
  89. struct segment_intersection<Indexable, Point, box_tag>
  90. {
  91. typedef dispatch::box_segment_intersection<Indexable, Point, dimension<Indexable>::value> impl;
  92. template <typename RelativeDistance>
  93. static inline bool apply(Indexable const& b, Point const& p0, Point const& p1, RelativeDistance & relative_distance)
  94. {
  95. // TODO: this ASSERT CHECK is wrong for user-defined CoordinateTypes!
  96. static const bool check = !::boost::is_integral<RelativeDistance>::value;
  97. BOOST_MPL_ASSERT_MSG(check, RELATIVE_DISTANCE_MUST_BE_FLOATING_POINT_TYPE, (RelativeDistance));
  98. RelativeDistance t_near = -(::std::numeric_limits<RelativeDistance>::max)();
  99. RelativeDistance t_far = (::std::numeric_limits<RelativeDistance>::max)();
  100. return impl::apply(b, p0, p1, t_near, t_far) &&
  101. (t_near <= 1) &&
  102. ( relative_distance = 0 < t_near ? t_near : 0, true );
  103. }
  104. };
  105. } // namespace dispatch
  106. template <typename Indexable, typename Point, typename RelativeDistance> inline
  107. bool segment_intersection(Indexable const& b,
  108. Point const& p0,
  109. Point const& p1,
  110. RelativeDistance & relative_distance)
  111. {
  112. // TODO check Indexable and Point concepts
  113. return dispatch::segment_intersection<
  114. Indexable, Point,
  115. typename tag<Indexable>::type
  116. >::apply(b, p0, p1, relative_distance);
  117. }
  118. }}}} // namespace boost::geometry::index::detail
  119. #endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP