]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // Boost.Geometry |
2 | // Unit Test | |
3 | ||
92f5a8d4 | 4 | // Copyright (c) 2016-2019 Oracle and/or its affiliates. |
b32b8144 FG |
5 | |
6 | // Contributed and/or modified by Adam Wulkiewicz, 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 | #ifndef BOOST_GEOMETRY_TEST_FORMULA_HPP | |
13 | #define BOOST_GEOMETRY_TEST_FORMULA_HPP | |
14 | ||
15 | #include <geometry_test_common.hpp> | |
16 | ||
1e59de90 | 17 | #include <boost/geometry/formulas/result_inverse.hpp> |
b32b8144 FG |
18 | #include <boost/geometry/util/math.hpp> |
19 | ||
20 | void normalize_deg(double & deg) | |
21 | { | |
22 | while (deg > 180.0) | |
23 | deg -= 360.0; | |
24 | while (deg <= -180.0) | |
25 | deg += 360.0; | |
26 | } | |
27 | ||
28 | ||
29 | #define BOOST_GEOMETRY_CHECK_CLOSE( L, R, T, M ) BOOST_TEST_TOOL_IMPL( 0, \ | |
30 | ::boost::test_tools::check_is_close_t(), M, CHECK, CHECK_MSG, (L)(R)(::boost::math::fpc::percent_tolerance(T)) ) | |
31 | ||
32 | ||
92f5a8d4 TL |
33 | void check_one(std::string const& name, double result, double expected) |
34 | { | |
35 | std::string id = name.empty() ? "" : (name + " : "); | |
36 | ||
37 | double eps = std::numeric_limits<double>::epsilon(); | |
38 | double abs_result = bg::math::abs(result); | |
39 | double abs_expected = bg::math::abs(expected); | |
40 | double res_max = (std::max)(abs_result, abs_expected); | |
41 | double res_min = (std::min)(abs_result, abs_expected); | |
42 | if (res_min <= eps) // including 0 | |
43 | { | |
44 | bool is_close = abs_result <= 30 * eps && abs_expected <= 30 * eps; | |
45 | BOOST_CHECK_MESSAGE((is_close), | |
1e59de90 TL |
46 | id << std::setprecision(20) << "result {" << result |
47 | << "} different than expected {" << expected << "}."); | |
92f5a8d4 TL |
48 | } |
49 | else if (res_max > 100 * eps) | |
50 | { | |
51 | BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 0.1, | |
1e59de90 TL |
52 | id << std::setprecision(20) << "result {" << result |
53 | << "} different than expected {" << expected << "}."); | |
92f5a8d4 TL |
54 | } |
55 | else if (res_max > 10 * eps) | |
56 | { | |
57 | BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 10, | |
1e59de90 TL |
58 | id << std::setprecision(20) << "result {" << result |
59 | << "} different than expected {" << expected << "}."); | |
92f5a8d4 TL |
60 | } |
61 | else if (res_max > eps) | |
62 | { | |
63 | BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 1000, | |
1e59de90 TL |
64 | id << std::setprecision(20) << "result {" << result |
65 | << "} different than expected {" << expected << "}."); | |
92f5a8d4 TL |
66 | } |
67 | } | |
68 | ||
b32b8144 FG |
69 | void check_one(std::string const& name, |
70 | double result, double expected, double reference, double reference_error, | |
71 | bool normalize = false, bool check_reference_only = false) | |
72 | { | |
73 | std::string id = name.empty() ? "" : (name + " : "); | |
74 | ||
75 | if (normalize) | |
76 | { | |
77 | normalize_deg(result); | |
78 | normalize_deg(expected); | |
79 | normalize_deg(reference); | |
80 | } | |
81 | ||
82 | if (! check_reference_only) | |
83 | { | |
92f5a8d4 | 84 | check_one(name, result, expected); |
b32b8144 FG |
85 | } |
86 | ||
87 | // NOTE: in some cases it probably will be necessary to normalize | |
88 | // the differences between the result and expected result | |
89 | double ref_diff = bg::math::abs(result - reference); | |
90 | double ref_max = (std::max)(bg::math::abs(result), bg::math::abs(reference)); | |
91 | bool is_ref_close = ref_diff <= reference_error || ref_diff <= reference_error * ref_max; | |
92 | BOOST_CHECK_MESSAGE((is_ref_close), | |
1e59de90 TL |
93 | id << std::setprecision(20) << "result {" << result << "} and reference {" |
94 | << reference << "} not close enough."); | |
b32b8144 FG |
95 | } |
96 | ||
97 | void check_one(double result, double expected, double reference, double reference_error, | |
98 | bool normalize = false, bool check_reference_only = false) | |
99 | { | |
1e59de90 TL |
100 | check_one("", result, expected, reference, reference_error, normalize, |
101 | check_reference_only); | |
102 | } | |
103 | ||
104 | template <typename Result, typename ExpectedResult> | |
105 | void check_inverse(std::string const& name, | |
106 | Result const& results, | |
107 | boost::geometry::formula::result_inverse<double> const& result, | |
108 | ExpectedResult const& expected, | |
109 | ExpectedResult const& reference, | |
110 | double reference_error) | |
111 | { | |
112 | std::stringstream ss; | |
113 | ss << "(" << results.p1.lon << " " << results.p1.lat << ")->(" | |
114 | << results.p2.lon << " " << results.p2.lat << ")"; | |
115 | ||
116 | check_one(name + "_d " + ss.str(), | |
117 | result.distance, expected.distance, reference.distance, reference_error); | |
118 | check_one(name + "_a " + ss.str(), | |
119 | result.azimuth, expected.azimuth, reference.azimuth, reference_error, true); | |
120 | check_one(name + "_ra " + ss.str(), | |
121 | result.reverse_azimuth, expected.reverse_azimuth, reference.reverse_azimuth, | |
122 | reference_error, true); | |
123 | check_one(name + "_rl " + ss.str(), | |
124 | result.reduced_length, expected.reduced_length, reference.reduced_length, | |
125 | reference_error); | |
126 | check_one(name + "_gs " + ss.str(), | |
127 | result.geodesic_scale, expected.geodesic_scale, reference.geodesic_scale, | |
128 | reference_error); | |
b32b8144 FG |
129 | } |
130 | ||
131 | #endif // BOOST_GEOMETRY_TEST_FORMULA_HPP |