]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/test/strategies/segment_intersection_sph.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / geometry / test / strategies / segment_intersection_sph.hpp
1 // Boost.Geometry
2 // Unit Test
3
4 // Copyright (c) 2016, Oracle and/or its affiliates.
5 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
6
7 // Use, modification and distribution is subject to the Boost Software License,
8 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10
11 #ifndef BOOST_GEOMETRY_TEST_STRATEGIES_SEGMENT_INTERSECTION_SPH_HPP
12 #define BOOST_GEOMETRY_TEST_STRATEGIES_SEGMENT_INTERSECTION_SPH_HPP
13
14
15 #include <geometry_test_common.hpp>
16
17 #include <boost/geometry/algorithms/equals.hpp>
18
19 #include <boost/geometry/geometries/point.hpp>
20 #include <boost/geometry/geometries/segment.hpp>
21
22 #include <boost/geometry/io/wkt/read.hpp>
23 #include <boost/geometry/io/wkt/write.hpp>
24
25 #include <boost/geometry/policies/relate/direction.hpp>
26 #include <boost/geometry/policies/relate/intersection_points.hpp>
27 #include <boost/geometry/policies/relate/tupled.hpp>
28
29 template <typename T>
30 bool equals_relaxed_val(T const& v1, T const& v2, T const& eps_scale)
31 {
32 T const c1 = 1;
33 T relaxed_eps = std::numeric_limits<T>::epsilon()
34 * bg::math::detail::greatest(c1, bg::math::abs(v1), bg::math::abs(v2))
35 * eps_scale;
36 return bg::math::abs(v1 - v2) <= relaxed_eps;
37 }
38
39 template <typename P1, typename P2, typename T>
40 bool equals_relaxed(P1 const& p1, P2 const& p2, T const& eps_scale)
41 {
42 typedef typename bg::select_coordinate_type<P1, P2>::type calc_t;
43 calc_t c1 = 1;
44 calc_t p10 = bg::get<0>(p1);
45 calc_t p11 = bg::get<1>(p1);
46 calc_t p20 = bg::get<0>(p2);
47 calc_t p21 = bg::get<1>(p2);
48 calc_t relaxed_eps = std::numeric_limits<calc_t>::epsilon()
49 * bg::math::detail::greatest(c1, bg::math::abs(p10), bg::math::abs(p11), bg::math::abs(p20), bg::math::abs(p21))
50 * eps_scale;
51 calc_t diff0 = p10 - p20;
52 // needed e.g. for -179.999999 - 180.0
53 if (diff0 < -180)
54 diff0 += 360;
55 return bg::math::abs(diff0) <= relaxed_eps
56 && bg::math::abs(p11 - p21) <= relaxed_eps;
57 }
58
59 template <typename S1, typename S2, typename Strategy, typename P>
60 void test_strategy_one(S1 const& s1, S2 const& s2,
61 Strategy const& strategy,
62 char m, std::size_t expected_count,
63 P const& ip0 = P(), P const& ip1 = P(),
64 int opposite_id = -1)
65 {
66 typedef typename bg::coordinate_type<P>::type coord_t;
67 typedef bg::policies::relate::segments_tupled
68 <
69 bg::policies::relate::segments_intersection_points
70 <
71 bg::segment_intersection_points<P, bg::segment_ratio<coord_t> >
72 >,
73 bg::policies::relate::segments_direction
74 > policy_t;
75
76 typedef typename policy_t::return_type return_type;
77
78 // NOTE: robust policy is currently ignored
79 return_type res = strategy.apply(s1, s2, policy_t(), 0);
80
81 size_t const res_count = boost::get<0>(res).count;
82 char const res_method = boost::get<1>(res).how;
83
84 BOOST_CHECK_MESSAGE(res_method == m,
85 "IP method: " << res_method << " different than expected: " << m
86 << " for " << bg::wkt(s1) << " and " << bg::wkt(s2));
87
88 BOOST_CHECK_MESSAGE(res_count == expected_count,
89 "IP count: " << res_count << " different than expected: " << expected_count
90 << " for " << bg::wkt(s1) << " and " << bg::wkt(s2));
91
92 // The EPS is scaled because during the conversion various angles may be not converted
93 // to cartesian 3d the same way which results in a different intersection point
94 // For more information read the info in spherical intersection strategy file.
95
96 // Plus in geographic CS the result strongly depends on the compiler,
97 // probably due to differences in FP trigonometric function implementations
98
99 int eps_scale = 1;
100 bool is_geographic = boost::is_same<typename bg::cs_tag<S1>::type, bg::geographic_tag>::value;
101 if (is_geographic)
102 {
103 eps_scale = 100000;
104 }
105 else
106 {
107 eps_scale = res_method != 'i' ? 1 : 1000;
108 }
109
110 if (res_count > 0 && expected_count > 0)
111 {
112 P const& res_i0 = boost::get<0>(res).intersections[0];
113 BOOST_CHECK_MESSAGE(equals_relaxed(res_i0, ip0, eps_scale),
114 "IP0: " << std::setprecision(16) << bg::wkt(res_i0) << " different than expected: " << bg::wkt(ip0)
115 << " for " << bg::wkt(s1) << " and " << bg::wkt(s2));
116 }
117 if (res_count > 1 && expected_count > 1)
118 {
119 P const& res_i1 = boost::get<0>(res).intersections[1];
120 BOOST_CHECK_MESSAGE(equals_relaxed(res_i1, ip1, eps_scale),
121 "IP1: " << std::setprecision(16) << bg::wkt(res_i1) << " different than expected: " << bg::wkt(ip1)
122 << " for " << bg::wkt(s1) << " and " << bg::wkt(s2));
123 }
124
125 if (opposite_id >= 0)
126 {
127 bool opposite = opposite_id != 0;
128 BOOST_CHECK_MESSAGE(opposite == boost::get<1>(res).opposite,
129 bg::wkt(s1) << " and " << bg::wkt(s2) << (opposite_id == 0 ? " are not " : " are ") << "opposite" );
130 }
131 }
132
133 template <typename T>
134 T translated(T v, double t)
135 {
136 v += T(t);
137 if (v > 180)
138 v -= 360;
139 return v;
140 }
141
142 template <typename S1, typename S2, typename Strategy, typename P>
143 void test_strategy(S1 const& s1, S2 const& s2,
144 Strategy const& strategy,
145 char m, std::size_t expected_count,
146 P const& ip0 = P(), P const& ip1 = P(),
147 int opposite_id = -1)
148 {
149 S1 s1t = s1;
150 S2 s2t = s2;
151 P ip0t = ip0;
152 P ip1t = ip1;
153
154 #ifndef BOOST_GEOMETRY_TEST_GEO_INTERSECTION_TEST_SIMILAR
155 test_strategy_one(s1t, s2t, strategy, m, expected_count, ip0t, ip1t, opposite_id);
156 #else
157 double t = 0;
158 for (int i = 0; i < 4; ++i, t += 90)
159 {
160 bg::set<0, 0>(s1t, translated(bg::get<0, 0>(s1), t));
161 bg::set<1, 0>(s1t, translated(bg::get<1, 0>(s1), t));
162 bg::set<0, 0>(s2t, translated(bg::get<0, 0>(s2), t));
163 bg::set<1, 0>(s2t, translated(bg::get<1, 0>(s2), t));
164 if (expected_count > 0)
165 bg::set<0>(ip0t, translated(bg::get<0>(ip0), t));
166 if (expected_count > 1)
167 bg::set<0>(ip1t, translated(bg::get<0>(ip1), t));
168
169 test_strategy_one(s1t, s2t, strategy, m, expected_count, ip0t, ip1t, opposite_id);
170 }
171 #endif
172 }
173
174 template <typename S1, typename S2, typename P, typename Strategy>
175 void test_strategy(std::string const& s1_wkt, std::string const& s2_wkt,
176 Strategy const& strategy,
177 char m, std::size_t expected_count,
178 std::string const& ip0_wkt = "", std::string const& ip1_wkt = "",
179 int opposite_id = -1)
180 {
181 S1 s1;
182 S2 s2;
183 P ip0, ip1;
184
185 bg::read_wkt(s1_wkt, s1);
186 bg::read_wkt(s2_wkt, s2);
187 if (! ip0_wkt.empty())
188 bg::read_wkt(ip0_wkt, ip0);
189 if (!ip1_wkt.empty())
190 bg::read_wkt(ip1_wkt, ip1);
191
192 test_strategy(s1, s2, strategy, m, expected_count, ip0, ip1, opposite_id);
193 }
194
195 template <typename S, typename P, typename Strategy>
196 void test_strategy(std::string const& s1_wkt, std::string const& s2_wkt,
197 Strategy const& strategy,
198 char m, std::size_t expected_count,
199 std::string const& ip0_wkt = "", std::string const& ip1_wkt = "",
200 int opposite_id = -1)
201 {
202 test_strategy<S, S, P>(s1_wkt, s2_wkt, strategy, m, expected_count, ip0_wkt, ip1_wkt, opposite_id);
203 }
204
205 #endif // BOOST_GEOMETRY_TEST_STRATEGIES_SEGMENT_INTERSECTION_SPH_HPP