]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/geometry/strategies/spherical/distance_haversine.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / geometry / strategies / spherical / distance_haversine.hpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
3// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4
11fdf7f2
TL
5// This file was modified by Oracle on 2017, 2018.
6// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates.
7
8// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
9// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10
7c673cae
FG
11// Use, modification and distribution is subject to the Boost Software License,
12// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13// http://www.boost.org/LICENSE_1_0.txt)
14
15#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP
16#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP
17
18
7c673cae 19#include <boost/geometry/core/access.hpp>
1e59de90 20#include <boost/geometry/core/coordinate_promotion.hpp>
11fdf7f2 21#include <boost/geometry/core/cs.hpp>
7c673cae
FG
22#include <boost/geometry/core/radian_access.hpp>
23
11fdf7f2 24#include <boost/geometry/srs/sphere.hpp>
7c673cae
FG
25
26#include <boost/geometry/strategies/distance.hpp>
11fdf7f2 27#include <boost/geometry/strategies/spherical/get_radius.hpp>
7c673cae 28
11fdf7f2 29#include <boost/geometry/util/math.hpp>
11fdf7f2 30#include <boost/geometry/util/select_calculation_type.hpp>
7c673cae
FG
31
32
33namespace boost { namespace geometry
34{
35
36
37namespace strategy { namespace distance
38{
39
40
41namespace comparable
42{
43
44// Comparable haversine.
45// To compare distances, we can avoid:
46// - multiplication with radius and 2.0
47// - applying sqrt
48// - applying asin (which is strictly (monotone) increasing)
49template
50<
11fdf7f2 51 typename RadiusTypeOrSphere = double,
7c673cae
FG
52 typename CalculationType = void
53>
54class haversine
55{
56public :
57 template <typename Point1, typename Point2>
58 struct calculation_type
59 : promote_floating_point
60 <
61 typename select_calculation_type
62 <
63 Point1,
64 Point2,
65 CalculationType
66 >::type
67 >
68 {};
69
11fdf7f2
TL
70 typedef typename strategy_detail::get_radius
71 <
72 RadiusTypeOrSphere
73 >::type radius_type;
74
75 inline haversine()
76 : m_radius(1.0)
77 {}
7c673cae 78
11fdf7f2
TL
79 template <typename RadiusOrSphere>
80 explicit inline haversine(RadiusOrSphere const& radius_or_sphere)
81 : m_radius(strategy_detail::get_radius
82 <
83 RadiusOrSphere
84 >::apply(radius_or_sphere))
7c673cae
FG
85 {}
86
87 template <typename Point1, typename Point2>
88 static inline typename calculation_type<Point1, Point2>::type
89 apply(Point1 const& p1, Point2 const& p2)
90 {
91 return calculate<typename calculation_type<Point1, Point2>::type>(
92 get_as_radian<0>(p1), get_as_radian<1>(p1),
93 get_as_radian<0>(p2), get_as_radian<1>(p2)
94 );
95 }
96
11fdf7f2 97 inline radius_type radius() const
7c673cae
FG
98 {
99 return m_radius;
100 }
101
102
103private :
104 template <typename R, typename T1, typename T2>
105 static inline R calculate(T1 const& lon1, T1 const& lat1,
106 T2 const& lon2, T2 const& lat2)
107 {
108 return math::hav(lat2 - lat1)
109 + cos(lat1) * cos(lat2) * math::hav(lon2 - lon1);
110 }
111
11fdf7f2 112 radius_type m_radius;
7c673cae
FG
113};
114
115
116
117} // namespace comparable
118
119/*!
120\brief Distance calculation for spherical coordinates
121on a perfect sphere using haversine
122\ingroup strategies
11fdf7f2 123\tparam RadiusTypeOrSphere \tparam_radius_or_sphere
7c673cae
FG
124\tparam CalculationType \tparam_calculation
125\author Adapted from: http://williams.best.vwh.net/avform.htm
126\see http://en.wikipedia.org/wiki/Great-circle_distance
127\note (from Wiki:) The great circle distance d between two
128points with coordinates {lat1,lon1} and {lat2,lon2} is given by:
129 d=acos(sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lon1-lon2))
130A mathematically equivalent formula, which is less subject
131 to rounding error for short distances is:
132 d=2*asin(sqrt((sin((lat1-lat2) / 2))^2
133 + cos(lat1)*cos(lat2)*(sin((lon1-lon2) / 2))^2))
7c673cae
FG
134\qbk{
135[heading See also]
136[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
137}
7c673cae
FG
138*/
139template
140<
11fdf7f2 141 typename RadiusTypeOrSphere = double,
7c673cae
FG
142 typename CalculationType = void
143>
144class haversine
145{
11fdf7f2 146 typedef comparable::haversine<RadiusTypeOrSphere, CalculationType> comparable_type;
7c673cae
FG
147
148public :
149 template <typename Point1, typename Point2>
150 struct calculation_type
151 : services::return_type<comparable_type, Point1, Point2>
152 {};
153
11fdf7f2
TL
154 typedef typename strategy_detail::get_radius
155 <
156 RadiusTypeOrSphere
157 >::type radius_type;
158
159 /*!
160 \brief Default constructor, radius set to 1.0 for the unit sphere
161 */
162 inline haversine()
163 : m_radius(1.0)
164 {}
7c673cae
FG
165
166 /*!
167 \brief Constructor
11fdf7f2 168 \param radius_or_sphere radius of the sphere or sphere model
7c673cae 169 */
11fdf7f2
TL
170 template <typename RadiusOrSphere>
171 explicit inline haversine(RadiusOrSphere const& radius_or_sphere)
172 : m_radius(strategy_detail::get_radius
173 <
174 RadiusOrSphere
175 >::apply(radius_or_sphere))
7c673cae
FG
176 {}
177
178 /*!
179 \brief applies the distance calculation
180 \return the calculated distance (including multiplying with radius)
181 \param p1 first point
182 \param p2 second point
183 */
184 template <typename Point1, typename Point2>
185 inline typename calculation_type<Point1, Point2>::type
186 apply(Point1 const& p1, Point2 const& p2) const
187 {
188 typedef typename calculation_type<Point1, Point2>::type calculation_type;
189 calculation_type const a = comparable_type::apply(p1, p2);
190 calculation_type const c = calculation_type(2.0) * asin(math::sqrt(a));
191 return calculation_type(m_radius) * c;
192 }
193
194 /*!
195 \brief access to radius value
196 \return the radius
197 */
11fdf7f2 198 inline radius_type radius() const
7c673cae
FG
199 {
200 return m_radius;
201 }
202
203private :
11fdf7f2 204 radius_type m_radius;
7c673cae
FG
205};
206
207
208#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
209namespace services
210{
211
212template <typename RadiusType, typename CalculationType>
213struct tag<haversine<RadiusType, CalculationType> >
214{
215 typedef strategy_tag_distance_point_point type;
216};
217
218
219template <typename RadiusType, typename CalculationType, typename P1, typename P2>
220struct return_type<haversine<RadiusType, CalculationType>, P1, P2>
221 : haversine<RadiusType, CalculationType>::template calculation_type<P1, P2>
222{};
223
224
225template <typename RadiusType, typename CalculationType>
226struct comparable_type<haversine<RadiusType, CalculationType> >
227{
228 typedef comparable::haversine<RadiusType, CalculationType> type;
229};
230
231
232template <typename RadiusType, typename CalculationType>
233struct get_comparable<haversine<RadiusType, CalculationType> >
234{
235private :
236 typedef haversine<RadiusType, CalculationType> this_type;
237 typedef comparable::haversine<RadiusType, CalculationType> comparable_type;
238public :
239 static inline comparable_type apply(this_type const& input)
240 {
241 return comparable_type(input.radius());
242 }
243};
244
245template <typename RadiusType, typename CalculationType, typename P1, typename P2>
246struct result_from_distance<haversine<RadiusType, CalculationType>, P1, P2>
247{
248private :
249 typedef haversine<RadiusType, CalculationType> this_type;
250 typedef typename return_type<this_type, P1, P2>::type return_type;
251public :
252 template <typename T>
253 static inline return_type apply(this_type const& , T const& value)
254 {
255 return return_type(value);
256 }
257};
258
259
260// Specializations for comparable::haversine
261template <typename RadiusType, typename CalculationType>
262struct tag<comparable::haversine<RadiusType, CalculationType> >
263{
264 typedef strategy_tag_distance_point_point type;
265};
266
267
268template <typename RadiusType, typename CalculationType, typename P1, typename P2>
269struct return_type<comparable::haversine<RadiusType, CalculationType>, P1, P2>
270 : comparable::haversine<RadiusType, CalculationType>::template calculation_type<P1, P2>
271{};
272
273
274template <typename RadiusType, typename CalculationType>
275struct comparable_type<comparable::haversine<RadiusType, CalculationType> >
276{
277 typedef comparable::haversine<RadiusType, CalculationType> type;
278};
279
280
281template <typename RadiusType, typename CalculationType>
282struct get_comparable<comparable::haversine<RadiusType, CalculationType> >
283{
284private :
285 typedef comparable::haversine<RadiusType, CalculationType> this_type;
286public :
287 static inline this_type apply(this_type const& input)
288 {
289 return input;
290 }
291};
292
293
294template <typename RadiusType, typename CalculationType, typename P1, typename P2>
295struct result_from_distance<comparable::haversine<RadiusType, CalculationType>, P1, P2>
296{
297private :
298 typedef comparable::haversine<RadiusType, CalculationType> strategy_type;
299 typedef typename return_type<strategy_type, P1, P2>::type return_type;
300public :
301 template <typename T>
302 static inline return_type apply(strategy_type const& strategy, T const& distance)
303 {
304 return_type const s = sin((distance / strategy.radius()) / return_type(2));
305 return s * s;
306 }
307};
308
309
310// Register it as the default for point-types
311// in a spherical equatorial coordinate system
312template <typename Point1, typename Point2>
313struct default_strategy
314 <
315 point_tag, point_tag, Point1, Point2,
316 spherical_equatorial_tag, spherical_equatorial_tag
317 >
318{
319 typedef strategy::distance::haversine<typename select_coordinate_type<Point1, Point2>::type> type;
320};
321
322// Note: spherical polar coordinate system requires "get_as_radian_equatorial"
323
324
325} // namespace services
326#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
327
328
329}} // namespace strategy::distance
330
331
332}} // namespace boost::geometry
333
334
335#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP