]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/test/algorithms/distance/test_distance_geo_common.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / geometry / test / algorithms / distance / test_distance_geo_common.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3
4 // Copyright (c) 2016-2021, Oracle and/or its affiliates.
5 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
6 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
7
8 // Licensed under the Boost Software License version 1.0.
9 // http://www.boost.org/users/license.html
10
11 #ifndef BOOST_GEOMETRY_TEST_DISTANCE_GEO_COMMON_HPP
12 #define BOOST_GEOMETRY_TEST_DISTANCE_GEO_COMMON_HPP
13
14 #include <iostream>
15 #include <string>
16
17 #include <boost/geometry/algorithms/distance.hpp>
18 #include <boost/geometry/algorithms/num_interior_rings.hpp>
19
20 #include <boost/geometry/geometries/geometries.hpp>
21
22 #include <boost/geometry/io/wkt/write.hpp>
23 #include <boost/geometry/io/dsv/write.hpp>
24
25 #include <boost/geometry/strategies/strategies.hpp>
26
27 #include <boost/geometry/util/condition.hpp>
28
29 #include <from_wkt.hpp>
30 #include <string_from_type.hpp>
31
32 #include "distance_brute_force.hpp"
33
34 namespace bg = ::boost::geometry;
35
36 typedef bg::srs::spheroid<double> stype;
37
38 // Spherical strategy for point-point distance
39
40 typedef bg::strategy::distance::haversine<double> spherical_pp;
41
42 // Geo strategies for point-point distance
43
44 typedef bg::strategy::distance::andoyer<stype> andoyer_pp;
45 typedef bg::strategy::distance::thomas<stype> thomas_pp;
46 typedef bg::strategy::distance::vincenty<stype> vincenty_pp;
47 typedef bg::strategy::distance::karney<stype> karney_pp;
48
49 // Spherical strategy for point-segment distance
50
51 typedef bg::strategy::distance::cross_track<> spherical_ps;
52
53 // Geo strategies for point-segment distance
54
55 typedef bg::strategy::distance::geographic_cross_track<bg::strategy::andoyer, stype, double>
56 andoyer_ps;
57
58 typedef bg::strategy::distance::geographic_cross_track<bg::strategy::thomas, stype, double>
59 thomas_ps;
60
61 typedef bg::strategy::distance::geographic_cross_track<bg::strategy::vincenty, stype, double>
62 vincenty_ps;
63
64 typedef bg::strategy::distance::geographic_cross_track<bg::strategy::karney, stype, double>
65 karney_ps;
66
67 typedef bg::strategy::distance::detail::geographic_cross_track<bg::strategy::vincenty, stype, double, true>
68 vincenty_ps_bisection;
69
70 // Spherical strategy for point-box distance
71
72 typedef bg::strategy::distance::cross_track_point_box<> spherical_pb;
73
74 // Geo strategies for point-box distance
75
76 typedef bg::strategy::distance::geographic_cross_track_point_box
77 <
78 bg::strategy::andoyer,
79 stype,
80 double
81 > andoyer_pb;
82
83 typedef bg::strategy::distance::geographic_cross_track_point_box
84 <
85 bg::strategy::thomas,
86 stype,
87 double
88 > thomas_pb;
89
90 typedef bg::strategy::distance::geographic_cross_track_point_box
91 <
92 bg::strategy::vincenty,
93 stype,
94 double
95 > vincenty_pb;
96
97 typedef bg::strategy::distance::geographic_cross_track_point_box
98 <
99 bg::strategy::karney,
100 stype,
101 double
102 > karney_pb;
103
104 // Spherical strategy for segment-box distance
105
106 typedef bg::strategy::distance::spherical_segment_box<> spherical_sb;
107
108 // Geo strategies for segment-box distance
109
110 typedef bg::strategy::distance::geographic_segment_box<bg::strategy::andoyer, stype, double>
111 andoyer_sb;
112
113 typedef bg::strategy::distance::geographic_segment_box<bg::strategy::thomas, stype, double>
114 thomas_sb;
115
116 typedef bg::strategy::distance::geographic_segment_box<bg::strategy::vincenty, stype, double>
117 vincenty_sb;
118
119 typedef bg::strategy::distance::geographic_segment_box<bg::strategy::karney, stype, double>
120 karney_sb;
121
122 // Strategies for box-box distance
123
124 typedef bg::strategy::distance::cross_track_box_box<> spherical_bb;
125
126 typedef bg::strategy::distance::geographic_cross_track_box_box
127 <
128 bg::strategy::andoyer,
129 stype,
130 double
131 > andoyer_bb;
132
133 typedef bg::strategy::distance::geographic_cross_track_box_box
134 <
135 bg::strategy::thomas,
136 stype,
137 double
138 > thomas_bb;
139
140 typedef bg::strategy::distance::geographic_cross_track_box_box
141 <
142 bg::strategy::vincenty,
143 stype,
144 double
145 > vincenty_bb;
146
147 typedef bg::strategy::distance::geographic_cross_track_box_box
148 <
149 bg::strategy::karney,
150 stype,
151 double
152 > karney_bb;
153
154 //===========================================================================
155
156 template <typename Point, typename Strategy>
157 inline typename bg::default_distance_result<Point>::type
158 pp_distance(std::string const& wkt1,
159 std::string const& wkt2,
160 Strategy const& strategy)
161 {
162 Point p1, p2;
163 bg::read_wkt(wkt1, p1);
164 bg::read_wkt(wkt2, p2);
165 return bg::distance(p1, p2, strategy);
166 }
167
168 //===========================================================================
169
170 template <typename Point, typename Strategy>
171 inline typename bg::default_distance_result<Point>::type
172 ps_distance(std::string const& wkt1,
173 std::string const& wkt2,
174 Strategy const& strategy)
175 {
176 Point p;
177 typedef bg::model::segment<Point> segment_type;
178 segment_type s;
179 bg::read_wkt(wkt1, p);
180 bg::read_wkt(wkt2, s);
181 return bg::distance(p, s, strategy);
182 }
183
184 //===========================================================================
185
186 template <typename Point, typename Strategy>
187 inline typename bg::default_distance_result<Point>::type
188 sb_distance(std::string const& wkt1,
189 std::string const& wkt2,
190 Strategy const& strategy)
191 {
192 typedef bg::model::segment<Point> segment_type;
193 typedef bg::model::box<Point> box_type;
194 segment_type s;
195 box_type b;
196 bg::read_wkt(wkt1, s);
197 bg::read_wkt(wkt2, b);
198 return bg::distance(s, b, strategy);
199 }
200
201 //===================================================================
202
203 template <typename Tag> struct dispatch
204 {
205 //tag dispatching for swaping arguments in segments
206 template <typename T>
207 static inline T swap(T const& t)
208 {
209 return t;
210 }
211
212 // mirror geometry w.r.t. equator
213 template <typename T>
214 static inline T mirror(T const& t)
215 {
216 return t;
217 }
218 };
219
220 // Specialization for segments
221 template <> struct dispatch<bg::segment_tag>
222 {
223 template <typename Segment>
224 static inline Segment swap(Segment const& s)
225 {
226 Segment s_swaped;
227
228 bg::set<0, 0>(s_swaped, bg::get<1, 0>(s));
229 bg::set<0, 1>(s_swaped, bg::get<1, 1>(s));
230 bg::set<1, 0>(s_swaped, bg::get<0, 0>(s));
231 bg::set<1, 1>(s_swaped, bg::get<0, 1>(s));
232
233 return s_swaped;
234 }
235
236 template <typename Segment>
237 static inline Segment mirror(Segment const& s)
238 {
239 Segment s_mirror;
240
241 bg::set<0, 0>(s_mirror, bg::get<0, 0>(s));
242 bg::set<0, 1>(s_mirror, bg::get<0, 1>(s) * -1);
243 bg::set<1, 0>(s_mirror, bg::get<1, 0>(s));
244 bg::set<1, 1>(s_mirror, bg::get<1, 1>(s) * -1);
245
246 return s_mirror;
247 }
248 };
249
250 // Specialization for boxes
251 template <> struct dispatch<bg::box_tag>
252 {
253 template <typename T>
254 static inline T swap(T const& t)
255 {
256 return t;
257 }
258
259 template <typename Box>
260 static inline Box mirror(Box const& b)
261 {
262 Box b_mirror;
263
264 bg::set<0, 0>(b_mirror, bg::get<bg::min_corner, 0>(b));
265 bg::set<0, 1>(b_mirror, bg::get<bg::max_corner, 1>(b) * -1);
266 bg::set<1, 0>(b_mirror, bg::get<bg::max_corner, 0>(b));
267 bg::set<1, 1>(b_mirror, bg::get<bg::min_corner, 1>(b) * -1);
268
269 return b_mirror;
270 }
271 };
272
273
274 // Specialization for points
275 template <> struct dispatch<bg::point_tag>
276 {
277 template <typename T>
278 static inline T swap(T const& t)
279 {
280 return t;
281 }
282
283 template <typename Point>
284 static inline Point mirror(Point const& p)
285 {
286 Point p_mirror;
287
288 bg::set<0>(p_mirror, bg::get<0>(p));
289 bg::set<1>(p_mirror, bg::get<1>(p) * -1);
290
291 return p_mirror;
292 }
293 };
294
295 //========================================================================
296
297
298 template <typename T>
299 struct check_equal
300 {
301 template <typename Value, typename = void>
302 struct equal_to
303 {
304 static inline void apply(Value const& x, Value const& y)
305 {
306 BOOST_CHECK(x == y);
307 }
308 };
309
310 template <typename Dummy>
311 struct equal_to<double, Dummy>
312 {
313 static inline void apply(double x, double y)
314 {
315 BOOST_CHECK_CLOSE(x, y, 0.001);
316 }
317 };
318
319 template <typename Geometry1, typename Geometry2>
320 static inline void apply(std::string const& /*case_id*/,
321 std::string const& /*subcase_id*/,
322 Geometry1 const& /*geometry1*/,
323 Geometry2 const& /*geometry2*/,
324 T const& detected,
325 T const& expected)
326 {
327 equal_to<T>::apply(expected, detected);
328 }
329 };
330
331 //========================================================================
332
333 template
334 <
335 typename Geometry1, typename Geometry2,
336 int id1 = bg::geometry_id<Geometry1>::value,
337 int id2 = bg::geometry_id<Geometry2>::value
338 >
339 struct test_distance_of_geometries
340 : public test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
341 {};
342
343
344 template <typename Geometry1, typename Geometry2>
345 struct test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
346 {
347 template <typename DistanceType, typename Strategy>
348 static inline
349 void apply(std::string const& case_id,
350 std::string const& wkt1,
351 std::string const& wkt2,
352 DistanceType const& expected_distance,
353 Strategy const& strategy,
354 bool test_reversed = true,
355 bool swap_geometry_args = false,
356 bool mirror_geometry = true)
357 {
358 Geometry1 geometry1 = from_wkt<Geometry1>(wkt1);
359 Geometry2 geometry2 = from_wkt<Geometry2>(wkt2);
360
361 apply(case_id, geometry1, geometry2,
362 expected_distance,
363 strategy, test_reversed, swap_geometry_args,
364 mirror_geometry);
365 }
366
367
368 template
369 <
370 typename DistanceType,
371 typename Strategy
372 >
373 static inline
374 void apply(std::string const& case_id,
375 Geometry1 const& geometry1,
376 Geometry2 const& geometry2,
377 DistanceType const& expected_distance,
378 Strategy const& strategy,
379 bool test_reversed = true,
380 bool swap_geometry_args = false,
381 bool mirror_geometry = true)
382 {
383 #ifdef BOOST_GEOMETRY_TEST_DEBUG
384 std::cout << "case ID: " << case_id << "; "
385 << "G1: " << bg::wkt(geometry1)
386 << " - "
387 << "G2: " << bg::wkt(geometry2)
388 << std::endl;
389 #endif
390 namespace services = bg::strategy::distance::services;
391
392 using bg::unit_test::distance_brute_force;
393
394 typedef typename bg::default_distance_result
395 <
396 Geometry1, Geometry2
397 >::type default_distance_result;
398
399 typedef typename services::return_type
400 <
401 Strategy, Geometry1, Geometry2
402 >::type distance_result_from_strategy;
403
404 static const bool same_regular = std::is_same
405 <
406 default_distance_result,
407 distance_result_from_strategy
408 >::value;
409
410 BOOST_CHECK(same_regular);
411
412 // check distance with passed strategy
413 distance_result_from_strategy dist =
414 bg::distance(geometry1, geometry2, strategy);
415
416 check_equal
417 <
418 distance_result_from_strategy
419 >::apply(case_id, "a", geometry1, geometry2,
420 dist, expected_distance);
421
422 // check against the comparable distance computed in a
423 // brute-force manner
424 default_distance_result dist_brute_force
425 = distance_brute_force(geometry1, geometry2, strategy);
426
427 check_equal
428 <
429 default_distance_result
430 >::apply(case_id, "b", geometry1, geometry2,
431 dist_brute_force, expected_distance);
432
433 #ifdef BOOST_GEOMETRY_TEST_DEBUG
434 std::cout << string_from_type<typename bg::coordinate_type<Geometry1>::type>::name()
435 << string_from_type<typename bg::coordinate_type<Geometry2>::type>::name()
436 << " -> "
437 << string_from_type<default_distance_result>::name()
438 << std::endl;
439 std::cout << "expected distance = " << std::setprecision(10)
440 << expected_distance << " ; "
441 << std::endl;
442 std::cout << "distance = " << std::setprecision(10)
443 << dist << " ; "
444 << std::endl;
445
446 if ( !test_reversed )
447 {
448 std::cout << std::endl;
449 }
450 #endif
451
452 if ( test_reversed )
453 {
454 // check distance with given strategy
455 dist = bg::distance(geometry2, geometry1, strategy);
456
457 check_equal
458 <
459 default_distance_result
460 >::apply(case_id, "ra", geometry2, geometry1,
461 dist, expected_distance);
462
463 #ifdef BOOST_GEOMETRY_TEST_DEBUG
464 std::cout << "distance[reversed args] = " << std::setprecision(10)
465 << dist
466 << std::endl;
467 #endif
468 }
469
470 if (swap_geometry_args)
471 {
472 Geometry1 g1 = dispatch
473 <
474 typename bg::tag<Geometry1>::type
475 >::swap(geometry1);
476
477 Geometry2 g2 = dispatch
478 <
479 typename bg::tag<Geometry2>::type
480 >::swap(geometry2);
481
482 // check distance with given strategy
483 dist = bg::distance(g1, g2, strategy);
484
485 check_equal
486 <
487 default_distance_result
488 >::apply(case_id, "swap", g1, g2,
489 dist, expected_distance);
490
491 #ifdef BOOST_GEOMETRY_TEST_DEBUG
492 std::cout << "distance[swap geometry args] = " << std::setprecision(10)
493 << dist
494 << std::endl;
495 std::cout << std::endl;
496 #endif
497 }
498 if (mirror_geometry)
499 {
500 Geometry1 g1 = dispatch
501 <
502 typename bg::tag<Geometry1>::type
503 >::mirror(geometry1);
504
505 Geometry2 g2 = dispatch
506 <
507 typename bg::tag<Geometry2>::type
508 >::mirror(geometry2);
509
510 // check distance with given strategy
511 dist = bg::distance(g1, g2, strategy);
512
513 check_equal
514 <
515 default_distance_result
516 >::apply(case_id, "mirror", g1, g2,
517 dist, expected_distance);
518
519 #ifdef BOOST_GEOMETRY_TEST_DEBUG
520 std::cout << "distance[mirror geometries] = " << std::setprecision(10)
521 << dist
522 << std::endl;
523 std::cout << std::endl;
524 #endif
525 }
526 #ifdef BOOST_GEOMETRY_TEST_DEBUG
527 std::cout << std::endl;
528 #endif
529
530 }
531 };
532
533
534 //========================================================================
535
536
537 template <typename Geometry1, typename Geometry2, typename Strategy>
538 void test_empty_input(Geometry1 const& geometry1,
539 Geometry2 const& geometry2,
540 Strategy const& strategy)
541 {
542 try
543 {
544 bg::distance(geometry1, geometry2);
545 }
546 catch(bg::empty_input_exception const& )
547 {
548 return;
549 }
550 BOOST_CHECK_MESSAGE(false,
551 "A empty_input_exception should have been thrown");
552
553 try
554 {
555 bg::distance(geometry2, geometry1);
556 }
557 catch(bg::empty_input_exception const& )
558 {
559 return;
560 }
561 BOOST_CHECK_MESSAGE(false,
562 "A empty_input_exception should have been thrown");
563
564 try
565 {
566 bg::distance(geometry1, geometry2, strategy);
567 }
568 catch(bg::empty_input_exception const& )
569 {
570 return;
571 }
572 BOOST_CHECK_MESSAGE(false,
573 "A empty_input_exception should have been thrown");
574
575 try
576 {
577 bg::distance(geometry2, geometry1, strategy);
578 }
579 catch(bg::empty_input_exception const& )
580 {
581 return;
582 }
583 BOOST_CHECK_MESSAGE(false,
584 "A empty_input_exception should have been thrown");
585 }
586
587 #endif // BOOST_GEOMETRY_TEST_DISTANCE_GEO_COMMON_HPP