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