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