]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | |
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 |