1 // Boost.Geometry
2 // Unit Test
3 
4 // Copyright (c) 2019 Oracle and/or its affiliates.
5 
6 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
7 
8 // Use, modification and distribution is subject to the Boost Software License,
9 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
11 
12 #include <geometry_test_common.hpp>
13 
14 #include <boost/geometry/formulas/karney_direct.hpp>
15 #include <boost/geometry/srs/srs.hpp>
16 
17 #ifdef BOOST_GEOEMTRY_TEST_WITH_GEOGRAPHICLIB
18 #include <GeographicLib/Geodesic.hpp>
19 #include <GeographicLib/Constants.hpp>
20 #endif // BOOST_GEOEMTRY_TEST_WITH_GEOGRAPHICLIB
21 
test_main(int,char * [])22 int test_main(int, char*[])
23 {
24 
25 #ifdef BOOST_GEOEMTRY_TEST_WITH_GEOGRAPHICLIB
26     // accuracy test from https://github.com/boostorg/geometry/issues/560
27     using namespace GeographicLib;
28 
29     const long double wgs84_a = 6378137.0L;
30     const long double wgs84_f = 1.0L / 298.257223563L;
31     const long double one_minus_f = 1.0L - wgs84_f;
32     const long double wgs84_b = wgs84_a * one_minus_f;
33 
34     const boost::geometry::srs::spheroid<long double> BoostWGS84(wgs84_a, wgs84_b);
35 
36     // boost karney_direct function class with azimuth output and SeriesOrder = 6
37     typedef boost::geometry::formula::karney_direct <double, true, true, false, false, 6u>
38             BoostKarneyDirect_6;
39 
40     // boost karney_direct function class with azimuth output and SeriesOrder = 8
41     typedef boost::geometry::formula::karney_direct <double, true, true, false, false, 8u>
42             BoostKarneyDirect_8;
43 
44     // boost test BOOST_CHECK_CLOSE macro takes a percentage accuracy parameter
45     const double EPSILON = std::numeric_limits<double>::epsilon();
46     const double CALCULATION_TOLERANCE = 100 * EPSILON;
47 
48     const Geodesic GeographicLibWGS84(Geodesic::WGS84());
49 
50     // Loop around latitudes: 0 to 89 degrees
51     for (int i=0; i < 90; ++i)
52     {
53         // The latitude in degrees.
54         double latitude(1.0 * i);
55 
56         // Loop around longitudes: 1 to 179 degrees
57         for (int j=1; j < 180; ++j)
58         {
59             // The longitude in degrees.
60             double longitude(1.0 * j);
61 
62             // The Geodesic: distance in metres, start azimuth and finish azimuth in degrees.
63             double distance_m, azimuth, azi2;
64             GeographicLibWGS84.Inverse(0.0, 0.0, latitude, longitude, distance_m, azimuth, azi2);
65 
66             // The GeographicLib position and azimuth at the distance in metres
67             double lat2k, lon2k, azi2k;
68             GeographicLibWGS84.Direct(0.0, 0.0, azimuth, distance_m, lat2k, lon2k, azi2k);
69             BOOST_CHECK_CLOSE(latitude, lat2k, 140 * CALCULATION_TOLERANCE);
70             BOOST_CHECK_CLOSE(longitude, lon2k, 120 * CALCULATION_TOLERANCE);
71 
72             // The boost karney_direct order 6 position at the azimuth and distance in metres.
73             boost::geometry::formula::result_direct<double> results_6
74                     = BoostKarneyDirect_6::apply(0.0, 0.0, distance_m, azimuth, BoostWGS84);
75             BOOST_CHECK_CLOSE(azi2, results_6.reverse_azimuth, 140 * CALCULATION_TOLERANCE);
76             BOOST_CHECK_CLOSE(latitude, results_6.lat2, 220 * CALCULATION_TOLERANCE);
77 
78             /******** Test below only passes with >= 10172000 * CALCULATION_TOLERANCE !! ********/
79             BOOST_CHECK_CLOSE(longitude, results_6.lon2, 10171000 * CALCULATION_TOLERANCE);
80             /*****************************************************************************/
81 
82             // The boost karney_direct order 8 position at the azimuth and distance in metres.
83             boost::geometry::formula::result_direct<double> results_8
84                     = BoostKarneyDirect_8::apply(0.0, 0.0, distance_m, azimuth, BoostWGS84);
85             BOOST_CHECK_CLOSE(azi2, results_8.reverse_azimuth, 140 * CALCULATION_TOLERANCE);
86             BOOST_CHECK_CLOSE(latitude, results_8.lat2, 220 * CALCULATION_TOLERANCE);
87 
88             /******** Test below only passes with >= 10174000 * CALCULATION_TOLERANCE !! ********/
89             BOOST_CHECK_CLOSE(longitude, results_8.lon2, 10173000 * CALCULATION_TOLERANCE);
90             /*****************************************************************************/
91         }
92     }
93 #endif // BOOST_GEOEMTRY_TEST_WITH_GEOGRAPHICLIB
94 
95     return 0;
96 }
97 
98