segment_to_segment.hpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2014, 2019, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  4. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  5. // Licensed under the Boost Software License version 1.0.
  6. // http://www.boost.org/users/license.html
  7. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP
  8. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP
  9. #include <algorithm>
  10. #include <iterator>
  11. #include <boost/core/addressof.hpp>
  12. #include <boost/geometry/core/point_type.hpp>
  13. #include <boost/geometry/core/tags.hpp>
  14. #include <boost/geometry/util/condition.hpp>
  15. #include <boost/geometry/strategies/distance.hpp>
  16. #include <boost/geometry/strategies/tags.hpp>
  17. #include <boost/geometry/algorithms/assign.hpp>
  18. #include <boost/geometry/algorithms/intersects.hpp>
  19. #include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
  20. #include <boost/geometry/algorithms/dispatch/distance.hpp>
  21. namespace boost { namespace geometry
  22. {
  23. #ifndef DOXYGEN_NO_DETAIL
  24. namespace detail { namespace distance
  25. {
  26. // compute segment-segment distance
  27. template<typename Segment1, typename Segment2, typename Strategy>
  28. class segment_to_segment
  29. {
  30. private:
  31. typedef typename strategy::distance::services::comparable_type
  32. <
  33. Strategy
  34. >::type comparable_strategy;
  35. typedef typename strategy::distance::services::return_type
  36. <
  37. comparable_strategy,
  38. typename point_type<Segment1>::type,
  39. typename point_type<Segment2>::type
  40. >::type comparable_return_type;
  41. public:
  42. typedef typename strategy::distance::services::return_type
  43. <
  44. Strategy,
  45. typename point_type<Segment1>::type,
  46. typename point_type<Segment2>::type
  47. >::type return_type;
  48. static inline return_type
  49. apply(Segment1 const& segment1, Segment2 const& segment2,
  50. Strategy const& strategy)
  51. {
  52. if (geometry::intersects(segment1, segment2, strategy.get_relate_segment_segment_strategy()))
  53. {
  54. return 0;
  55. }
  56. typename point_type<Segment1>::type p[2];
  57. detail::assign_point_from_index<0>(segment1, p[0]);
  58. detail::assign_point_from_index<1>(segment1, p[1]);
  59. typename point_type<Segment2>::type q[2];
  60. detail::assign_point_from_index<0>(segment2, q[0]);
  61. detail::assign_point_from_index<1>(segment2, q[1]);
  62. comparable_strategy cstrategy =
  63. strategy::distance::services::get_comparable
  64. <
  65. Strategy
  66. >::apply(strategy);
  67. comparable_return_type d[4];
  68. d[0] = cstrategy.apply(q[0], p[0], p[1]);
  69. d[1] = cstrategy.apply(q[1], p[0], p[1]);
  70. d[2] = cstrategy.apply(p[0], q[0], q[1]);
  71. d[3] = cstrategy.apply(p[1], q[0], q[1]);
  72. std::size_t imin = std::distance(boost::addressof(d[0]),
  73. std::min_element(d, d + 4));
  74. if (BOOST_GEOMETRY_CONDITION(is_comparable<Strategy>::value))
  75. {
  76. return d[imin];
  77. }
  78. switch (imin)
  79. {
  80. case 0:
  81. return strategy.apply(q[0], p[0], p[1]);
  82. case 1:
  83. return strategy.apply(q[1], p[0], p[1]);
  84. case 2:
  85. return strategy.apply(p[0], q[0], q[1]);
  86. default:
  87. return strategy.apply(p[1], q[0], q[1]);
  88. }
  89. }
  90. };
  91. }} // namespace detail::distance
  92. #endif // DOXYGEN_NO_DETAIL
  93. #ifndef DOXYGEN_NO_DISPATCH
  94. namespace dispatch
  95. {
  96. // segment-segment
  97. template <typename Segment1, typename Segment2, typename Strategy>
  98. struct distance
  99. <
  100. Segment1, Segment2, Strategy, segment_tag, segment_tag,
  101. strategy_tag_distance_point_segment, false
  102. >
  103. : detail::distance::segment_to_segment<Segment1, Segment2, Strategy>
  104. {};
  105. } // namespace dispatch
  106. #endif // DOXYGEN_NO_DISPATCH
  107. }} // namespace boost::geometry
  108. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_SEGMENT_HPP