]>
Commit | Line | Data |
---|---|---|
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) | |
2 | ||
3 | // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. | |
4 | // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. | |
5 | // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. | |
6 | ||
7 | // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library | |
8 | // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. | |
9 | ||
10 | // Use, modification and distribution is subject to the Boost Software License, | |
11 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
12 | // http://www.boost.org/LICENSE_1_0.txt) | |
13 | ||
14 | #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP | |
15 | #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP | |
16 | ||
17 | ||
18 | #include <boost/geometry/core/access.hpp> | |
19 | ||
20 | #include <boost/geometry/strategies/distance.hpp> | |
21 | ||
22 | #include <boost/geometry/util/math.hpp> | |
23 | #include <boost/geometry/util/calculation_type.hpp> | |
24 | ||
25 | ||
26 | namespace boost { namespace geometry | |
27 | { | |
28 | ||
29 | namespace strategy { namespace distance | |
30 | { | |
31 | ||
32 | #ifndef DOXYGEN_NO_DETAIL | |
33 | namespace detail | |
34 | { | |
35 | ||
36 | template <size_t I, typename T> | |
37 | struct compute_pythagoras | |
38 | { | |
39 | template <typename Point1, typename Point2> | |
40 | static inline T apply(Point1 const& p1, Point2 const& p2) | |
41 | { | |
42 | T const c1 = boost::numeric_cast<T>(get<I-1>(p1)); | |
43 | T const c2 = boost::numeric_cast<T>(get<I-1>(p2)); | |
44 | T const d = c1 - c2; | |
45 | return d * d + compute_pythagoras<I-1, T>::apply(p1, p2); | |
46 | } | |
47 | }; | |
48 | ||
49 | template <typename T> | |
50 | struct compute_pythagoras<0, T> | |
51 | { | |
52 | template <typename Point1, typename Point2> | |
53 | static inline T apply(Point1 const&, Point2 const&) | |
54 | { | |
55 | return boost::numeric_cast<T>(0); | |
56 | } | |
57 | }; | |
58 | ||
59 | } | |
60 | #endif // DOXYGEN_NO_DETAIL | |
61 | ||
62 | ||
63 | namespace comparable | |
64 | { | |
65 | ||
66 | /*! | |
67 | \brief Strategy to calculate comparable distance between two points | |
68 | \ingroup strategies | |
69 | \tparam Point1 \tparam_first_point | |
70 | \tparam Point2 \tparam_second_point | |
71 | \tparam CalculationType \tparam_calculation | |
72 | */ | |
73 | template <typename CalculationType = void> | |
74 | class pythagoras | |
75 | { | |
76 | public : | |
77 | ||
78 | template <typename Point1, typename Point2> | |
79 | struct calculation_type | |
80 | : util::calculation_type::geometric::binary | |
81 | < | |
82 | Point1, | |
83 | Point2, | |
84 | CalculationType, | |
85 | double, | |
86 | double | |
87 | > | |
88 | {}; | |
89 | ||
90 | template <typename Point1, typename Point2> | |
91 | static inline typename calculation_type<Point1, Point2>::type | |
92 | apply(Point1 const& p1, Point2 const& p2) | |
93 | { | |
94 | BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point1>) ); | |
95 | BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point2>) ); | |
96 | ||
97 | // Calculate distance using Pythagoras | |
98 | // (Leave comment above for Doxygen) | |
99 | ||
100 | assert_dimension_equal<Point1, Point2>(); | |
101 | ||
102 | return detail::compute_pythagoras | |
103 | < | |
104 | dimension<Point1>::value, | |
105 | typename calculation_type<Point1, Point2>::type | |
106 | >::apply(p1, p2); | |
107 | } | |
108 | }; | |
109 | ||
110 | } // namespace comparable | |
111 | ||
112 | ||
113 | /*! | |
114 | \brief Strategy to calculate the distance between two points | |
115 | \ingroup strategies | |
116 | \tparam CalculationType \tparam_calculation | |
117 | ||
118 | \qbk{ | |
119 | [heading Notes] | |
120 | [note Can be used for points with two\, three or more dimensions] | |
121 | [heading See also] | |
122 | [link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)] | |
123 | } | |
124 | ||
125 | */ | |
126 | template | |
127 | < | |
128 | typename CalculationType = void | |
129 | > | |
130 | class pythagoras | |
131 | { | |
132 | public : | |
133 | ||
134 | template <typename P1, typename P2> | |
135 | struct calculation_type | |
136 | : util::calculation_type::geometric::binary | |
137 | < | |
138 | P1, | |
139 | P2, | |
140 | CalculationType, | |
141 | double, | |
142 | double // promote integer to double | |
143 | > | |
144 | {}; | |
145 | ||
146 | /*! | |
147 | \brief applies the distance calculation using pythagoras | |
148 | \return the calculated distance (including taking the square root) | |
149 | \param p1 first point | |
150 | \param p2 second point | |
151 | */ | |
152 | template <typename P1, typename P2> | |
153 | static inline typename calculation_type<P1, P2>::type | |
154 | apply(P1 const& p1, P2 const& p2) | |
155 | { | |
156 | // The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call | |
157 | return math::sqrt | |
158 | ( | |
159 | boost::numeric_cast<typename calculation_type<P1, P2>::type> | |
160 | ( | |
161 | comparable::pythagoras<CalculationType>::apply(p1, p2) | |
162 | ) | |
163 | ); | |
164 | } | |
165 | }; | |
166 | ||
167 | ||
168 | #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS | |
169 | namespace services | |
170 | { | |
171 | ||
172 | template <typename CalculationType> | |
173 | struct tag<pythagoras<CalculationType> > | |
174 | { | |
175 | typedef strategy_tag_distance_point_point type; | |
176 | }; | |
177 | ||
178 | ||
179 | template <typename CalculationType, typename P1, typename P2> | |
180 | struct return_type<distance::pythagoras<CalculationType>, P1, P2> | |
181 | : pythagoras<CalculationType>::template calculation_type<P1, P2> | |
182 | {}; | |
183 | ||
184 | ||
185 | template <typename CalculationType> | |
186 | struct comparable_type<pythagoras<CalculationType> > | |
187 | { | |
188 | typedef comparable::pythagoras<CalculationType> type; | |
189 | }; | |
190 | ||
191 | ||
192 | template <typename CalculationType> | |
193 | struct get_comparable<pythagoras<CalculationType> > | |
194 | { | |
195 | typedef comparable::pythagoras<CalculationType> comparable_type; | |
196 | public : | |
197 | static inline comparable_type apply(pythagoras<CalculationType> const& ) | |
198 | { | |
199 | return comparable_type(); | |
200 | } | |
201 | }; | |
202 | ||
203 | ||
204 | template <typename CalculationType, typename Point1, typename Point2> | |
205 | struct result_from_distance<pythagoras<CalculationType>, Point1, Point2> | |
206 | { | |
207 | private : | |
208 | typedef typename return_type<pythagoras<CalculationType>, Point1, Point2>::type return_type; | |
209 | public : | |
210 | template <typename T> | |
211 | static inline return_type apply(pythagoras<CalculationType> const& , T const& value) | |
212 | { | |
213 | return return_type(value); | |
214 | } | |
215 | }; | |
216 | ||
217 | ||
218 | // Specializations for comparable::pythagoras | |
219 | template <typename CalculationType> | |
220 | struct tag<comparable::pythagoras<CalculationType> > | |
221 | { | |
222 | typedef strategy_tag_distance_point_point type; | |
223 | }; | |
224 | ||
225 | ||
226 | template <typename CalculationType, typename P1, typename P2> | |
227 | struct return_type<comparable::pythagoras<CalculationType>, P1, P2> | |
228 | : comparable::pythagoras<CalculationType>::template calculation_type<P1, P2> | |
229 | {}; | |
230 | ||
231 | ||
232 | ||
233 | ||
234 | template <typename CalculationType> | |
235 | struct comparable_type<comparable::pythagoras<CalculationType> > | |
236 | { | |
237 | typedef comparable::pythagoras<CalculationType> type; | |
238 | }; | |
239 | ||
240 | ||
241 | template <typename CalculationType> | |
242 | struct get_comparable<comparable::pythagoras<CalculationType> > | |
243 | { | |
244 | typedef comparable::pythagoras<CalculationType> comparable_type; | |
245 | public : | |
246 | static inline comparable_type apply(comparable::pythagoras<CalculationType> const& ) | |
247 | { | |
248 | return comparable_type(); | |
249 | } | |
250 | }; | |
251 | ||
252 | ||
253 | template <typename CalculationType, typename Point1, typename Point2> | |
254 | struct result_from_distance<comparable::pythagoras<CalculationType>, Point1, Point2> | |
255 | { | |
256 | private : | |
257 | typedef typename return_type<comparable::pythagoras<CalculationType>, Point1, Point2>::type return_type; | |
258 | public : | |
259 | template <typename T> | |
260 | static inline return_type apply(comparable::pythagoras<CalculationType> const& , T const& value) | |
261 | { | |
262 | return_type const v = value; | |
263 | return v * v; | |
264 | } | |
265 | }; | |
266 | ||
267 | ||
268 | template <typename Point1, typename Point2> | |
269 | struct default_strategy | |
270 | < | |
271 | point_tag, point_tag, Point1, Point2, cartesian_tag, cartesian_tag | |
272 | > | |
273 | { | |
274 | typedef pythagoras<> type; | |
275 | }; | |
276 | ||
277 | ||
278 | } // namespace services | |
279 | #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS | |
280 | ||
281 | ||
282 | }} // namespace strategy::distance | |
283 | ||
284 | ||
285 | }} // namespace boost::geometry | |
286 | ||
287 | ||
288 | #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP |