4 // Copyright (c) 2016-2019 Oracle and/or its affiliates.
6 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
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)
12 #ifndef BOOST_GEOMETRY_TEST_FORMULA_HPP
13 #define BOOST_GEOMETRY_TEST_FORMULA_HPP
15 #include <geometry_test_common.hpp>
17 #include <boost/geometry/formulas/result_inverse.hpp>
18 #include <boost/geometry/util/math.hpp>
20 void normalize_deg(double & deg)
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)) )
33 void check_one(std::string const& name, double result, double expected)
35 std::string id = name.empty() ? "" : (name + " : ");
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
44 bool is_close = abs_result <= 30 * eps && abs_expected <= 30 * eps;
45 BOOST_CHECK_MESSAGE((is_close),
46 id << std::setprecision(20) << "result {" << result
47 << "} different than expected {" << expected << "}.");
49 else if (res_max > 100 * eps)
51 BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 0.1,
52 id << std::setprecision(20) << "result {" << result
53 << "} different than expected {" << expected << "}.");
55 else if (res_max > 10 * eps)
57 BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 10,
58 id << std::setprecision(20) << "result {" << result
59 << "} different than expected {" << expected << "}.");
61 else if (res_max > eps)
63 BOOST_GEOMETRY_CHECK_CLOSE(result, expected, 1000,
64 id << std::setprecision(20) << "result {" << result
65 << "} different than expected {" << expected << "}.");
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)
73 std::string id = name.empty() ? "" : (name + " : ");
77 normalize_deg(result);
78 normalize_deg(expected);
79 normalize_deg(reference);
82 if (! check_reference_only)
84 check_one(name, result, expected);
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),
93 id << std::setprecision(20) << "result {" << result << "} and reference {"
94 << reference << "} not close enough.");
97 void check_one(double result, double expected, double reference, double reference_error,
98 bool normalize = false, bool check_reference_only = false)
100 check_one("", result, expected, reference, reference_error, normalize,
101 check_reference_only);
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)
112 std::stringstream ss;
113 ss << "(" << results.p1.lon << " " << results.p1.lat << ")->("
114 << results.p2.lon << " " << results.p2.lat << ")";
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,
126 check_one(name + "_gs " + ss.str(),
127 result.geodesic_scale, expected.geodesic_scale, reference.geodesic_scale,
131 #endif // BOOST_GEOMETRY_TEST_FORMULA_HPP