]>
Commit | Line | Data |
---|---|---|
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) | |
2 | // Unit Test | |
3 | ||
4 | // Copyright (c) 2015-2017, Oracle and/or its affiliates. | |
5 | ||
6 | // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle | |
7 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle | |
8 | ||
9 | // Licensed under the Boost Software License version 1.0. | |
10 | // http://www.boost.org/users/license.html | |
11 | ||
12 | #ifndef BOOST_GEOMETRY_TEST_ENVELOPE_EXPAND_ON_SPHEROID_HPP | |
13 | #define BOOST_GEOMETRY_TEST_ENVELOPE_EXPAND_ON_SPHEROID_HPP | |
14 | ||
15 | ||
16 | #include <algorithm> | |
17 | #include <cmath> | |
18 | #include <cstddef> | |
19 | #include <iostream> | |
20 | ||
21 | #include <boost/type_traits/is_same.hpp> | |
22 | ||
23 | #include <boost/geometry/core/access.hpp> | |
24 | #include <boost/geometry/core/coordinate_dimension.hpp> | |
25 | #include <boost/geometry/core/cs.hpp> | |
26 | ||
27 | #include <boost/geometry/util/condition.hpp> | |
28 | #include <boost/geometry/util/math.hpp> | |
29 | ||
30 | #include <boost/geometry/views/detail/indexed_point_view.hpp> | |
31 | ||
32 | #include <boost/geometry/algorithms/assign.hpp> | |
33 | ||
34 | ||
35 | struct rng | |
36 | { | |
37 | typedef double type; | |
38 | ||
39 | rng(double l, double h) | |
40 | : lo(l), hi(h) | |
41 | { | |
42 | BOOST_GEOMETRY_ASSERT(lo <= hi); | |
43 | } | |
44 | ||
45 | friend rng operator*(rng const& l, double v) { return rng(l.lo * v, l.hi * v); } | |
46 | ||
47 | friend bool operator<=(rng const& l, rng const& r) { return l.lo <= r.hi; } | |
48 | friend bool operator<=(double l, rng const& r) { return l <= r.hi; } | |
49 | friend bool operator<=(rng const& l, double r) { return l.lo <= r; } | |
50 | ||
51 | friend bool operator<(rng const& l, rng const& r) { return !operator<=(r, l); } | |
52 | friend bool operator<(double l, rng const& r) { return !operator<=(r, l); } | |
53 | friend bool operator<(rng const& l, double r) { return !operator<=(r, l); } | |
54 | ||
55 | friend bool operator==(double l, rng const& r) { return r.lo <= l && l <= r.hi; } | |
56 | ||
57 | friend std::ostream & operator<<(std::ostream & os, rng const& v) | |
58 | { | |
59 | return (os << "[" << v.lo << ", " << v.hi << "]"); | |
60 | } | |
61 | ||
62 | double lo, hi; | |
63 | }; | |
64 | ||
65 | ||
66 | template <typename Units> | |
67 | char const* units2string() | |
68 | { | |
69 | if (BOOST_GEOMETRY_CONDITION((boost::is_same<Units, bg::degree>::value))) | |
70 | { | |
71 | return "degrees"; | |
72 | } | |
73 | return "radians"; | |
74 | } | |
75 | ||
76 | template <typename CoordinateSystem> | |
77 | struct other_system_info | |
78 | {}; | |
79 | ||
80 | template <> | |
81 | struct other_system_info<bg::cs::spherical_equatorial<bg::radian> > | |
82 | { | |
83 | typedef bg::degree units; | |
84 | typedef bg::cs::spherical_equatorial<units> type; | |
85 | ||
86 | static inline double convert(double value) | |
87 | { | |
88 | return value * bg::math::r2d<double>(); | |
89 | } | |
90 | ||
91 | static inline rng convert(rng const& value) | |
92 | { | |
93 | return value * bg::math::r2d<double>(); | |
94 | } | |
95 | }; | |
96 | ||
97 | template <> | |
98 | struct other_system_info<bg::cs::spherical_equatorial<bg::degree> > | |
99 | { | |
100 | typedef bg::radian units; | |
101 | typedef bg::cs::spherical_equatorial<units> type; | |
102 | ||
103 | static inline double convert(double value) | |
104 | { | |
105 | return value * bg::math::d2r<double>(); | |
106 | } | |
107 | ||
108 | static inline rng convert(rng const& value) | |
109 | { | |
110 | return value * bg::math::d2r<double>(); | |
111 | } | |
112 | }; | |
113 | ||
114 | template <> | |
115 | struct other_system_info<bg::cs::spherical<bg::radian> > | |
116 | { | |
117 | typedef bg::degree units; | |
118 | typedef bg::cs::spherical<units> type; | |
119 | ||
120 | static inline double convert(double value) | |
121 | { | |
122 | return value * bg::math::r2d<double>(); | |
123 | } | |
124 | ||
125 | static inline rng convert(rng const& value) | |
126 | { | |
127 | return value * bg::math::r2d<double>(); | |
128 | } | |
129 | }; | |
130 | ||
131 | template <> | |
132 | struct other_system_info<bg::cs::spherical<bg::degree> > | |
133 | { | |
134 | typedef bg::radian units; | |
135 | typedef bg::cs::spherical<units> type; | |
136 | ||
137 | static inline double convert(double value) | |
138 | { | |
139 | return value * bg::math::d2r<double>(); | |
140 | } | |
141 | ||
142 | static inline rng convert(rng const& value) | |
143 | { | |
144 | return value * bg::math::d2r<double>(); | |
145 | } | |
146 | }; | |
147 | ||
148 | template <> | |
149 | struct other_system_info<bg::cs::geographic<bg::radian> > | |
150 | { | |
151 | typedef bg::degree units; | |
152 | typedef bg::cs::geographic<units> type; | |
153 | ||
154 | static inline double convert(double value) | |
155 | { | |
156 | return value * bg::math::r2d<double>(); | |
157 | } | |
158 | ||
159 | static inline rng convert(rng const& value) | |
160 | { | |
161 | return value * bg::math::r2d<double>(); | |
162 | } | |
163 | }; | |
164 | ||
165 | template <> | |
166 | struct other_system_info<bg::cs::geographic<bg::degree> > | |
167 | { | |
168 | typedef bg::radian units; | |
169 | typedef bg::cs::geographic<units> type; | |
170 | ||
171 | static inline double convert(double value) | |
172 | { | |
173 | return value * bg::math::d2r<double>(); | |
174 | } | |
175 | ||
176 | static inline rng convert(rng const& value) | |
177 | { | |
178 | return value * bg::math::d2r<double>(); | |
179 | } | |
180 | }; | |
181 | ||
182 | ||
183 | class equals_with_tolerance | |
184 | { | |
185 | private: | |
186 | double m_tolerence; | |
187 | ||
188 | template <typename T> | |
189 | static inline T const& get_max(T const& a, T const& b, T const& c) | |
190 | { | |
191 | return (std::max)((std::max)(a, b), c); | |
192 | } | |
193 | ||
194 | template <typename T> | |
195 | static inline bool check_close(T const& a, T const& b, double tol) | |
196 | { | |
197 | return (a == b) | |
198 | || (std::abs(a - b) <= tol * get_max(std::abs(a), std::abs(b), 1.0)); | |
199 | } | |
200 | ||
201 | public: | |
202 | equals_with_tolerance(double tolerence) : m_tolerence(tolerence) {} | |
203 | ||
204 | inline bool operator()(double value1, double value2) const | |
205 | { | |
206 | return check_close(value1, value2, m_tolerence); | |
207 | } | |
208 | ||
209 | inline bool operator()(double l, rng const& r) const | |
210 | { | |
211 | return (r.lo < l && l < r.hi) | |
212 | || check_close(l, r.lo, m_tolerence) | |
213 | || check_close(l, r.hi, m_tolerence); | |
214 | } | |
215 | }; | |
216 | ||
217 | ||
218 | bool equals_with_eps(double l, double r) | |
219 | { | |
220 | return bg::math::equals(l, r); | |
221 | } | |
222 | ||
223 | bool equals_with_eps(double l, rng r) | |
224 | { | |
225 | return (r.lo < l && l < r.hi) | |
226 | || bg::math::equals(l, r.lo) | |
227 | || bg::math::equals(l, r.hi); | |
228 | } | |
229 | ||
230 | ||
231 | template | |
232 | < | |
233 | typename Box, | |
234 | std::size_t DimensionCount = bg::dimension<Box>::value | |
235 | > | |
236 | struct box_check_equals | |
237 | { | |
238 | template <typename T1, typename T2, typename T3, typename T4> | |
239 | static inline bool apply(Box const& box, | |
240 | T1 const& lon_min, T2 const& lat_min, double, | |
241 | T3 const& lon_max, T4 const& lat_max, double, | |
242 | double tol) | |
243 | { | |
244 | equals_with_tolerance equals(tol); | |
245 | ||
246 | #ifndef BOOST_GEOMETRY_TEST_ENABLE_FAILING | |
247 | // check latitude with tolerance when necessary | |
248 | return equals_with_eps(bg::get<0, 0>(box), lon_min) | |
249 | && (bg::get<0, 1>(box) < 0 | |
250 | ? equals(bg::get<0, 1>(box), lat_min) | |
251 | : equals_with_eps(bg::get<0, 1>(box), lat_min)) | |
252 | && equals_with_eps(bg::get<1, 0>(box), lon_max) | |
253 | && (bg::get<1, 1>(box) > 0 | |
254 | ? equals(bg::get<1, 1>(box), lat_max) | |
255 | : equals_with_eps(bg::get<1, 1>(box), lat_max)); | |
256 | #else | |
257 | // check latitude with tolerance when necessary | |
258 | return bg::get<0, 0>(box) == lon_min | |
259 | && (bg::get<0, 1>(box) < 0 | |
260 | ? equals(bg::get<0, 1>(box), lat_min) | |
261 | : bg::get<0, 1>(box) == lat_min) | |
262 | && bg::get<1, 0>(box) == lon_max | |
263 | && (bg::get<1, 1>(box) > 0 | |
264 | ? equals(bg::get<1, 1>(box), lat_max) | |
265 | : bg::get<1, 1>(box) == lat_max); | |
266 | #endif | |
267 | } | |
268 | }; | |
269 | ||
270 | template <typename Box> | |
271 | struct box_check_equals<Box, 3> | |
272 | { | |
273 | template <typename T1, typename T2, typename T3, typename T4> | |
274 | static inline bool apply(Box const& box, | |
275 | T1 const& lon_min, T2 const& lat_min, double height_min, | |
276 | T3 const& lon_max, T4 const& lat_max, double height_max, | |
277 | double tol) | |
278 | { | |
279 | #ifndef BOOST_GEOMETRY_TEST_ENABLE_FAILING | |
280 | equals_with_tolerance equals(tol); | |
281 | ||
282 | return box_check_equals<Box, 2>::apply(box, | |
283 | lon_min, lat_min, height_min, | |
284 | lon_max, lat_max, height_max, | |
285 | tol) | |
286 | && equals(bg::get<0, 2>(box), height_min) | |
287 | && equals(bg::get<1, 2>(box), height_max); | |
288 | #else | |
289 | return box_equals<Box, 2>::apply(box, | |
290 | lon_min, lat_min, height_min, | |
291 | lon_max, lat_max, height_max, | |
292 | tol) | |
293 | && bg::get<0, 2>(box) == height_min | |
294 | && bg::get<1, 2>(box) == height_max; | |
295 | #endif | |
296 | } | |
297 | }; | |
298 | ||
299 | ||
300 | template | |
301 | < | |
302 | typename Box1, | |
303 | typename Box2 = Box1, | |
304 | std::size_t DimensionCount = bg::dimension<Box1>::value | |
305 | > | |
306 | struct box_equals | |
307 | { | |
308 | static inline bool apply(Box1 const& box1, Box2 const& box2, double tol) | |
309 | { | |
310 | return box_check_equals<Box1>::apply(box1, | |
311 | bg::get<0, 0>(box2), bg::get<0, 1>(box2), 0.0, | |
312 | bg::get<1, 0>(box2), bg::get<1, 1>(box2), 0.0, | |
313 | tol); | |
314 | } | |
315 | }; | |
316 | ||
317 | template<typename Box1, typename Box2> | |
318 | struct box_equals<Box1, Box2, 3> | |
319 | { | |
320 | static inline bool apply(Box1 const& box1, Box2 const& box2, double tol) | |
321 | { | |
322 | return box_check_equals<Box1>::apply(box1, | |
323 | bg::get<0, 0>(box2), bg::get<0, 1>(box2), bg::get<0, 2>(box2), | |
324 | bg::get<1, 0>(box2), bg::get<1, 1>(box2), bg::get<1, 2>(box2), | |
325 | tol); | |
326 | } | |
327 | }; | |
328 | ||
329 | ||
330 | template <typename Box, std::size_t Dimension = bg::dimension<Box>::value> | |
331 | struct initialize_box | |
332 | { | |
333 | static inline void apply(Box& box, | |
334 | double lon_min, double lat_min, double, | |
335 | double lon_max, double lat_max, double) | |
336 | { | |
337 | bg::detail::indexed_point_view<Box, bg::min_corner> p_min(box); | |
338 | bg::detail::indexed_point_view<Box, bg::max_corner> p_max(box); | |
339 | ||
340 | bg::assign_values(p_min, lon_min, lat_min); | |
341 | bg::assign_values(p_max, lon_max, lat_max); | |
342 | } | |
343 | }; | |
344 | ||
345 | template <typename Box> | |
346 | struct initialize_box<Box, 3> | |
347 | { | |
348 | static inline void apply(Box& box, | |
349 | double lon_min, double lat_min, double height_min, | |
350 | double lon_max, double lat_max, double height_max) | |
351 | { | |
352 | bg::detail::indexed_point_view<Box, bg::min_corner> p_min(box); | |
353 | bg::detail::indexed_point_view<Box, bg::max_corner> p_max(box); | |
354 | ||
355 | bg::assign_values(p_min, lon_min, lat_min, height_min); | |
356 | bg::assign_values(p_max, lon_max, lat_max, height_max); | |
357 | } | |
358 | }; | |
359 | ||
360 | #endif // BOOST_GEOMETRY_TEST_ENVELOPE_EXPAND_ON_SPHEROID_HPP |