• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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