]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/geometry/test/strategies/vincenty.cpp
bump version to 19.2.0-pve1
[ceph.git] / ceph / src / boost / libs / geometry / test / strategies / vincenty.cpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2// Unit Test
3
4// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
5// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
6// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
7
1e59de90
TL
8// This file was modified by Oracle on 2014-2021.
9// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
7c673cae
FG
10// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11
12// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
13// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
14
15// Use, modification and distribution is subject to the Boost Software License,
16// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
17// http://www.boost.org/LICENSE_1_0.txt)
18
19
20#include <geometry_test_common.hpp>
21
22#include <boost/concept_check.hpp>
23
11fdf7f2
TL
24#include <boost/geometry/algorithms/assign.hpp>
25#include <boost/geometry/algorithms/distance.hpp>
b32b8144
FG
26#include <boost/geometry/formulas/vincenty_inverse.hpp>
27#include <boost/geometry/formulas/vincenty_direct.hpp>
7c673cae 28#include <boost/geometry/geometries/point.hpp>
11fdf7f2
TL
29#include <boost/geometry/srs/spheroid.hpp>
30#include <boost/geometry/strategies/concepts/distance_concept.hpp>
31#include <boost/geometry/strategies/geographic/distance_vincenty.hpp>
32#include <boost/geometry/strategies/geographic/side_vincenty.hpp>
33
7c673cae
FG
34#include <test_common/test_point.hpp>
35
7c673cae
FG
36template <typename T>
37void normalize_deg(T & deg)
38{
39 while ( deg > T(180) )
40 deg -= T(360);
41 while ( deg <= T(-180) )
42 deg += T(360);
43}
44
45template <typename T>
46T difference_deg(T const& a1, T const& a2)
47{
48 T d = a1 - a2;
49 normalize_deg(d);
50 return d;
51}
52
53template <typename T>
54void check_deg(std::string const& name, T const& a1, T const& a2, T const& percent, T const& error)
55{
56 T diff = bg::math::abs(difference_deg(a1, a2));
57
58 if ( bg::math::equals(a1, T(0)) || bg::math::equals(a2, T(0)) )
59 {
60 if ( diff > error )
61 {
62 BOOST_ERROR(name << " - the difference {" << diff << "} between {" << a1 << "} and {" << a2 << "} exceeds {" << error << "}");
63 }
64 }
65 else
66 {
67 T greater = (std::max)(bg::math::abs(a1), bg::math::abs(a2));
68
69 if ( diff > greater * percent / T(100) )
70 {
71 BOOST_ERROR(name << " the difference {" << diff << "} between {" << a1 << "} and {" << a2 << "} exceeds {" << percent << "}%");
72 }
73 }
74}
75
76double azimuth(double deg, double min, double sec)
77{
78 min = fabs(min);
79 sec = fabs(sec);
80
81 if ( deg < 0 )
82 {
83 min = -min;
84 sec = -sec;
85 }
86
87 return deg + min/60.0 + sec/3600.0;
88}
89
90double azimuth(double deg, double min)
91{
92 return azimuth(deg, min, 0.0);
93}
94
95template <typename P>
96bool non_precise_ct()
97{
1e59de90
TL
98 using ct = typename bg::coordinate_type<P>::type;
99 return std::is_integral<ct>::value || std::is_floating_point<ct>::value;
7c673cae
FG
100}
101
102template <typename P1, typename P2, typename Spheroid>
103void test_vincenty(double lon1, double lat1, double lon2, double lat2,
104 double expected_distance,
105 double expected_azimuth_12,
106 double /*expected_azimuth_21*/,
107 Spheroid const& spheroid)
108{
109 typedef typename bg::promote_floating_point
110 <
111 typename bg::select_calculation_type<P1, P2, void>::type
112 >::type calc_t;
113
114 calc_t tolerance = non_precise_ct<P1>() || non_precise_ct<P2>() ?
115 5.0 : 0.001;
116 calc_t error = non_precise_ct<P1>() || non_precise_ct<P2>() ?
117 1e-5 : 1e-12;
118
119 // formula
120 {
121 double const d2r = bg::math::d2r<double>();
122 double const r2d = bg::math::r2d<double>();
123
b32b8144 124 typedef bg::formula::vincenty_inverse<calc_t, true, true> inverse_formula;
7c673cae
FG
125 typename inverse_formula::result_type
126 result_i = inverse_formula::apply(lon1 * d2r,
127 lat1 * d2r,
128 lon2 * d2r,
129 lat2 * d2r,
130 spheroid);
131 calc_t dist = result_i.distance;
132 calc_t az12 = result_i.azimuth;
133 //calc_t az21 = vi.azimuth21();
134
135 calc_t az12_deg = az12 * r2d;
136 //calc_t az21_deg = az21 * r2d;
137
138 BOOST_CHECK_CLOSE(dist, calc_t(expected_distance), tolerance);
139 check_deg("az12_deg", az12_deg, calc_t(expected_azimuth_12), tolerance, error);
140 //check_deg("az21_deg", az21_deg, calc_t(expected_azimuth_21), tolerance, error);
141
b32b8144 142 typedef bg::formula::vincenty_direct<calc_t> direct_formula;
7c673cae
FG
143 typename direct_formula::result_type
144 result_d = direct_formula::apply(lon1 * d2r,
145 lat1 * d2r,
146 dist,
147 az12,
148 spheroid);
149 calc_t direct_lon2 = result_d.lon2;
150 calc_t direct_lat2 = result_d.lat2;
151 //calc_t direct_az21 = vd.azimuth21();
152
153 calc_t direct_lon2_deg = direct_lon2 * r2d;
154 calc_t direct_lat2_deg = direct_lat2 * r2d;
155 //calc_t direct_az21_deg = direct_az21 * r2d;
156
157 check_deg("direct_lon2_deg", direct_lon2_deg, calc_t(lon2), tolerance, error);
158 check_deg("direct_lat2_deg", direct_lat2_deg, calc_t(lat2), tolerance, error);
159 //check_deg("direct_az21_deg", direct_az21_deg, az21_deg, tolerance, error);
160 }
161
11fdf7f2 162 // distance strategies
7c673cae
FG
163 {
164 typedef bg::strategy::distance::vincenty<Spheroid> vincenty_type;
11fdf7f2 165 typedef bg::strategy::distance::geographic<bg::strategy::vincenty, Spheroid> geographic_type;
7c673cae
FG
166
167 BOOST_CONCEPT_ASSERT(
168 (
169 bg::concepts::PointDistanceStrategy<vincenty_type, P1, P2>)
170 );
171
172 vincenty_type vincenty(spheroid);
11fdf7f2 173 geographic_type geographic(spheroid);
7c673cae
FG
174 typedef typename bg::strategy::distance::services::return_type<vincenty_type, P1, P2>::type return_type;
175
176 P1 p1;
177 P2 p2;
178
179 bg::assign_values(p1, lon1, lat1);
180 bg::assign_values(p2, lon2, lat2);
181
182 BOOST_CHECK_CLOSE(vincenty.apply(p1, p2), return_type(expected_distance), tolerance);
11fdf7f2 183 BOOST_CHECK_CLOSE(geographic.apply(p1, p2), return_type(expected_distance), tolerance);
7c673cae
FG
184 BOOST_CHECK_CLOSE(bg::distance(p1, p2, vincenty), return_type(expected_distance), tolerance);
185 }
186}
187
188template <typename P1, typename P2>
189void test_vincenty(double lon1, double lat1, double lon2, double lat2,
190 double expected_distance,
191 double expected_azimuth_12,
192 double expected_azimuth_21)
193{
194 test_vincenty<P1, P2>(lon1, lat1, lon2, lat2,
195 expected_distance, expected_azimuth_12, expected_azimuth_21,
196 bg::srs::spheroid<double>());
197}
198
199template <typename PS, typename P>
200void test_side(double lon1, double lat1,
201 double lon2, double lat2,
202 double lon, double lat,
203 int expected_side)
204{
205 // Set radius type, but for integer coordinates we want to have floating point radius type
206 typedef typename bg::promote_floating_point
207 <
208 typename bg::coordinate_type<PS>::type
209 >::type rtype;
210
211 typedef bg::srs::spheroid<rtype> stype;
212
213 typedef bg::strategy::side::vincenty<stype> strategy_type;
11fdf7f2 214 typedef bg::strategy::side::geographic<bg::strategy::vincenty, stype> strategy2_type;
7c673cae
FG
215
216 strategy_type strategy;
11fdf7f2 217 strategy2_type strategy2;
7c673cae
FG
218
219 PS p1, p2;
220 P p;
221
222 bg::assign_values(p1, lon1, lat1);
223 bg::assign_values(p2, lon2, lat2);
224 bg::assign_values(p, lon, lat);
225
226 int side = strategy.apply(p1, p2, p);
11fdf7f2 227 int side2 = strategy2.apply(p1, p2, p);
7c673cae
FG
228
229 BOOST_CHECK_EQUAL(side, expected_side);
11fdf7f2 230 BOOST_CHECK_EQUAL(side2, expected_side);
7c673cae
FG
231}
232
233template <typename P1, typename P2>
234void test_all()
235{
236 // See:
237 // - http://www.ga.gov.au/geodesy/datums/vincenty_inverse.jsp
238 // - http://www.ga.gov.au/geodesy/datums/vincenty_direct.jsp
239 // Values in the comments below was calculated using the above pages
240 // in some cases distances may be different, previously used values was left
241
242 // use km
243 double gda_a = 6378.1370;
244 double gda_f = 1.0 / 298.25722210;
245 double gda_b = gda_a * ( 1.0 - gda_f );
246 bg::srs::spheroid<double> gda_spheroid(gda_a, gda_b);
247
248 // Test fractional coordinates only for non-integral types
249 if ( BOOST_GEOMETRY_CONDITION(
1e59de90
TL
250 ! std::is_integral<typename bg::coordinate_type<P1>::type>::value
251 && ! std::is_integral<typename bg::coordinate_type<P2>::type>::value ) )
7c673cae
FG
252 {
253 // Flinders Peak -> Buninyong
254 test_vincenty<P1, P2>(azimuth(144,25,29.52440), azimuth(-37,57,3.72030),
255 azimuth(143,55,35.38390), azimuth(-37,39,10.15610),
256 54.972271, azimuth(306,52,5.37), azimuth(127,10,25.07),
257 gda_spheroid);
258 }
259
260 // Lodz -> Trondheim
261 test_vincenty<P1, P2>(azimuth(19,28), azimuth(51,47),
262 azimuth(10,21), azimuth(63,23),
263 1399.032724, azimuth(340,54,25.14), azimuth(153,10,0.19),
264 gda_spheroid);
265 // London -> New York
266 test_vincenty<P1, P2>(azimuth(0,7,39), azimuth(51,30,26),
267 azimuth(-74,0,21), azimuth(40,42,46),
268 5602.044851, azimuth(288,31,36.82), azimuth(51,10,33.43),
269 gda_spheroid);
270
271 // Shanghai -> San Francisco
272 test_vincenty<P1, P2>(azimuth(121,30), azimuth(31,12),
273 azimuth(-122,25), azimuth(37,47),
274 9899.698550, azimuth(45,12,44.76), azimuth(309,50,20.88),
275 gda_spheroid);
276
277 test_vincenty<P1, P2>(0, 0, 0, 50, 5540.847042, 0, 180, gda_spheroid); // N
278 test_vincenty<P1, P2>(0, 0, 0, -50, 5540.847042, 180, 0, gda_spheroid); // S
b32b8144 279 test_vincenty<P1, P2>(0, 0, 50, 0, 5565.974540, 90, -90, gda_spheroid); // E
7c673cae
FG
280 test_vincenty<P1, P2>(0, 0, -50, 0, 5565.974540, -90, 90, gda_spheroid); // W
281
282 test_vincenty<P1, P2>(0, 0, 50, 50, 7284.879297, azimuth(32,51,55.87), azimuth(237,24,50.12), gda_spheroid); // NE
283
284 // The original distance values, azimuths calculated using the web form mentioned above
285 // Using default spheroid units (meters)
286 test_vincenty<P1, P2>(0, 89, 1, 80, 1005153.5769, azimuth(178,53,23.85), azimuth(359,53,18.35)); // sub-polar
287 test_vincenty<P1, P2>(4, 52, 4, 52, 0.0, 0, 0); // no point difference
288 test_vincenty<P1, P2>(4, 52, 3, 40, 1336039.890, azimuth(183,41,29.08), azimuth(2,58,5.13)); // normal case
289
290 test_side<P1, P2>(0, 0, 0, 1, 0, 2, 0);
291 test_side<P1, P2>(0, 0, 0, 1, 0, -2, 0);
292 test_side<P1, P2>(10, 0, 10, 1, 10, 2, 0);
293 test_side<P1, P2>(10, 0, 10, -1, 10, 2, 0);
294
295 test_side<P1, P2>(10, 0, 10, 1, 0, 2, 1); // left
296 test_side<P1, P2>(10, 0, 10, -1, 0, 2, -1); // right
297
298 test_side<P1, P2>(-10, -10, 10, 10, 10, 0, -1); // right
299 test_side<P1, P2>(-10, -10, 10, 10, -10, 0, 1); // left
300 test_side<P1, P2>(170, -10, -170, 10, -170, 0, -1); // right
301 test_side<P1, P2>(170, -10, -170, 10, 170, 0, 1); // left
302}
303
304template <typename P>
305void test_all()
306{
307 test_all<P, P>();
308}
309
310int test_main(int, char* [])
311{
312 //test_all<float[2]>();
313 //test_all<double[2]>();
314 test_all<bg::model::point<double, 2, bg::cs::geographic<bg::degree> > >();
315 test_all<bg::model::point<float, 2, bg::cs::geographic<bg::degree> > >();
316 test_all<bg::model::point<int, 2, bg::cs::geographic<bg::degree> > >();
317
7c673cae
FG
318 return 0;
319}