]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/test/strategies/vincenty.cpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
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.
8 // This file was modified by Oracle on 2014, 2015, 2016.
9 // Modifications copyright (c) 2014-2016 Oracle and/or its affiliates.
11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
13 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
14 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16 // Use, modification and distribution is subject to the Boost Software License,
17 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
18 // http://www.boost.org/LICENSE_1_0.txt)
21 #include <geometry_test_common.hpp>
23 #include <boost/concept_check.hpp>
25 #include <boost/geometry/strategies/geographic/distance_vincenty.hpp>
26 #include <boost/geometry/strategies/geographic/side_vincenty.hpp>
27 #include <boost/geometry/formulas/vincenty_inverse.hpp>
28 #include <boost/geometry/formulas/vincenty_direct.hpp>
30 #include <boost/geometry/core/srs.hpp>
31 #include <boost/geometry/strategies/strategies.hpp>
32 #include <boost/geometry/algorithms/assign.hpp>
33 #include <boost/geometry/geometries/point.hpp>
34 #include <test_common/test_point.hpp>
37 # include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
41 void normalize_deg(T
& deg
)
43 while ( deg
> T(180) )
45 while ( deg
<= T(-180) )
50 T
difference_deg(T
const& a1
, T
const& a2
)
58 void check_deg(std::string
const& name
, T
const& a1
, T
const& a2
, T
const& percent
, T
const& error
)
60 T diff
= bg::math::abs(difference_deg(a1
, a2
));
62 if ( bg::math::equals(a1
, T(0)) || bg::math::equals(a2
, T(0)) )
66 BOOST_ERROR(name
<< " - the difference {" << diff
<< "} between {" << a1
<< "} and {" << a2
<< "} exceeds {" << error
<< "}");
71 T greater
= (std::max
)(bg::math::abs(a1
), bg::math::abs(a2
));
73 if ( diff
> greater
* percent
/ T(100) )
75 BOOST_ERROR(name
<< " the difference {" << diff
<< "} between {" << a1
<< "} and {" << a2
<< "} exceeds {" << percent
<< "}%");
80 double azimuth(double deg
, double min
, double sec
)
91 return deg
+ min
/60.0 + sec
/3600.0;
94 double azimuth(double deg
, double min
)
96 return azimuth(deg
, min
, 0.0);
100 bool non_precise_ct()
102 typedef typename
bg::coordinate_type
<P
>::type ct
;
103 return boost::is_integral
<ct
>::value
|| boost::is_float
<ct
>::value
;
106 template <typename P1
, typename P2
, typename Spheroid
>
107 void test_vincenty(double lon1
, double lat1
, double lon2
, double lat2
,
108 double expected_distance
,
109 double expected_azimuth_12
,
110 double /*expected_azimuth_21*/,
111 Spheroid
const& spheroid
)
113 typedef typename
bg::promote_floating_point
115 typename
bg::select_calculation_type
<P1
, P2
, void>::type
118 calc_t tolerance
= non_precise_ct
<P1
>() || non_precise_ct
<P2
>() ?
120 calc_t error
= non_precise_ct
<P1
>() || non_precise_ct
<P2
>() ?
125 double const d2r
= bg::math::d2r
<double>();
126 double const r2d
= bg::math::r2d
<double>();
128 typedef bg::formula::vincenty_inverse
<calc_t
, true, true> inverse_formula
;
129 typename
inverse_formula::result_type
130 result_i
= inverse_formula::apply(lon1
* d2r
,
135 calc_t dist
= result_i
.distance
;
136 calc_t az12
= result_i
.azimuth
;
137 //calc_t az21 = vi.azimuth21();
139 calc_t az12_deg
= az12
* r2d
;
140 //calc_t az21_deg = az21 * r2d;
142 BOOST_CHECK_CLOSE(dist
, calc_t(expected_distance
), tolerance
);
143 check_deg("az12_deg", az12_deg
, calc_t(expected_azimuth_12
), tolerance
, error
);
144 //check_deg("az21_deg", az21_deg, calc_t(expected_azimuth_21), tolerance, error);
146 typedef bg::formula::vincenty_direct
<calc_t
> direct_formula
;
147 typename
direct_formula::result_type
148 result_d
= direct_formula::apply(lon1
* d2r
,
153 calc_t direct_lon2
= result_d
.lon2
;
154 calc_t direct_lat2
= result_d
.lat2
;
155 //calc_t direct_az21 = vd.azimuth21();
157 calc_t direct_lon2_deg
= direct_lon2
* r2d
;
158 calc_t direct_lat2_deg
= direct_lat2
* r2d
;
159 //calc_t direct_az21_deg = direct_az21 * r2d;
161 check_deg("direct_lon2_deg", direct_lon2_deg
, calc_t(lon2
), tolerance
, error
);
162 check_deg("direct_lat2_deg", direct_lat2_deg
, calc_t(lat2
), tolerance
, error
);
163 //check_deg("direct_az21_deg", direct_az21_deg, az21_deg, tolerance, error);
168 typedef bg::strategy::distance::vincenty
<Spheroid
> vincenty_type
;
170 BOOST_CONCEPT_ASSERT(
172 bg::concepts::PointDistanceStrategy
<vincenty_type
, P1
, P2
>)
175 vincenty_type
vincenty(spheroid
);
176 typedef typename
bg::strategy::distance::services::return_type
<vincenty_type
, P1
, P2
>::type return_type
;
181 bg::assign_values(p1
, lon1
, lat1
);
182 bg::assign_values(p2
, lon2
, lat2
);
184 BOOST_CHECK_CLOSE(vincenty
.apply(p1
, p2
), return_type(expected_distance
), tolerance
);
185 BOOST_CHECK_CLOSE(bg::distance(p1
, p2
, vincenty
), return_type(expected_distance
), tolerance
);
189 template <typename P1
, typename P2
>
190 void test_vincenty(double lon1
, double lat1
, double lon2
, double lat2
,
191 double expected_distance
,
192 double expected_azimuth_12
,
193 double expected_azimuth_21
)
195 test_vincenty
<P1
, P2
>(lon1
, lat1
, lon2
, lat2
,
196 expected_distance
, expected_azimuth_12
, expected_azimuth_21
,
197 bg::srs::spheroid
<double>());
200 template <typename PS
, typename P
>
201 void test_side(double lon1
, double lat1
,
202 double lon2
, double lat2
,
203 double lon
, double lat
,
206 // Set radius type, but for integer coordinates we want to have floating point radius type
207 typedef typename
bg::promote_floating_point
209 typename
bg::coordinate_type
<PS
>::type
212 typedef bg::srs::spheroid
<rtype
> stype
;
214 typedef bg::strategy::side::vincenty
<stype
> strategy_type
;
216 strategy_type strategy
;
221 bg::assign_values(p1
, lon1
, lat1
);
222 bg::assign_values(p2
, lon2
, lat2
);
223 bg::assign_values(p
, lon
, lat
);
225 int side
= strategy
.apply(p1
, p2
, p
);
227 BOOST_CHECK_EQUAL(side
, expected_side
);
230 template <typename P1
, typename P2
>
234 // - http://www.ga.gov.au/geodesy/datums/vincenty_inverse.jsp
235 // - http://www.ga.gov.au/geodesy/datums/vincenty_direct.jsp
236 // Values in the comments below was calculated using the above pages
237 // in some cases distances may be different, previously used values was left
240 double gda_a
= 6378.1370;
241 double gda_f
= 1.0 / 298.25722210;
242 double gda_b
= gda_a
* ( 1.0 - gda_f
);
243 bg::srs::spheroid
<double> gda_spheroid(gda_a
, gda_b
);
245 // Test fractional coordinates only for non-integral types
246 if ( BOOST_GEOMETRY_CONDITION(
247 ! boost::is_integral
<typename
bg::coordinate_type
<P1
>::type
>::value
248 && ! boost::is_integral
<typename
bg::coordinate_type
<P2
>::type
>::value
) )
250 // Flinders Peak -> Buninyong
251 test_vincenty
<P1
, P2
>(azimuth(144,25,29.52440), azimuth(-37,57,3.72030),
252 azimuth(143,55,35.38390), azimuth(-37,39,10.15610),
253 54.972271, azimuth(306,52,5.37), azimuth(127,10,25.07),
258 test_vincenty
<P1
, P2
>(azimuth(19,28), azimuth(51,47),
259 azimuth(10,21), azimuth(63,23),
260 1399.032724, azimuth(340,54,25.14), azimuth(153,10,0.19),
262 // London -> New York
263 test_vincenty
<P1
, P2
>(azimuth(0,7,39), azimuth(51,30,26),
264 azimuth(-74,0,21), azimuth(40,42,46),
265 5602.044851, azimuth(288,31,36.82), azimuth(51,10,33.43),
268 // Shanghai -> San Francisco
269 test_vincenty
<P1
, P2
>(azimuth(121,30), azimuth(31,12),
270 azimuth(-122,25), azimuth(37,47),
271 9899.698550, azimuth(45,12,44.76), azimuth(309,50,20.88),
274 test_vincenty
<P1
, P2
>(0, 0, 0, 50, 5540.847042, 0, 180, gda_spheroid
); // N
275 test_vincenty
<P1
, P2
>(0, 0, 0, -50, 5540.847042, 180, 0, gda_spheroid
); // S
276 test_vincenty
<P1
, P2
>(0, 0, 50, 0, 5565.974540, 90, -90, gda_spheroid
); // E
277 test_vincenty
<P1
, P2
>(0, 0, -50, 0, 5565.974540, -90, 90, gda_spheroid
); // W
279 test_vincenty
<P1
, P2
>(0, 0, 50, 50, 7284.879297, azimuth(32,51,55.87), azimuth(237,24,50.12), gda_spheroid
); // NE
281 // The original distance values, azimuths calculated using the web form mentioned above
282 // Using default spheroid units (meters)
283 test_vincenty
<P1
, P2
>(0, 89, 1, 80, 1005153.5769, azimuth(178,53,23.85), azimuth(359,53,18.35)); // sub-polar
284 test_vincenty
<P1
, P2
>(4, 52, 4, 52, 0.0, 0, 0); // no point difference
285 test_vincenty
<P1
, P2
>(4, 52, 3, 40, 1336039.890, azimuth(183,41,29.08), azimuth(2,58,5.13)); // normal case
287 test_side
<P1
, P2
>(0, 0, 0, 1, 0, 2, 0);
288 test_side
<P1
, P2
>(0, 0, 0, 1, 0, -2, 0);
289 test_side
<P1
, P2
>(10, 0, 10, 1, 10, 2, 0);
290 test_side
<P1
, P2
>(10, 0, 10, -1, 10, 2, 0);
292 test_side
<P1
, P2
>(10, 0, 10, 1, 0, 2, 1); // left
293 test_side
<P1
, P2
>(10, 0, 10, -1, 0, 2, -1); // right
295 test_side
<P1
, P2
>(-10, -10, 10, 10, 10, 0, -1); // right
296 test_side
<P1
, P2
>(-10, -10, 10, 10, -10, 0, 1); // left
297 test_side
<P1
, P2
>(170, -10, -170, 10, -170, 0, -1); // right
298 test_side
<P1
, P2
>(170, -10, -170, 10, 170, 0, 1); // left
301 template <typename P
>
307 int test_main(int, char* [])
309 //test_all<float[2]>();
310 //test_all<double[2]>();
311 test_all
<bg::model::point
<double, 2, bg::cs::geographic
<bg::degree
> > >();
312 test_all
<bg::model::point
<float, 2, bg::cs::geographic
<bg::degree
> > >();
313 test_all
<bg::model::point
<int, 2, bg::cs::geographic
<bg::degree
> > >();
315 #if defined(HAVE_TTMATH)
316 test_all
<bg::model::point
<ttmath::Big
<1,4>, 2, bg::cs::geographic
<bg::degree
> > >();
317 test_all
<bg::model::point
<ttmath_big
, 2, bg::cs::geographic
<bg::degree
> > >();