]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/test/algorithms/distance/test_distance_common.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / geometry / test / algorithms / distance / test_distance_common.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3
4 // Copyright (c) 2014-2021, Oracle and/or its affiliates.
5 // Contributed and/or modified by Menelaos Karavelas, 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_COMMON_HPP
12 #define BOOST_GEOMETRY_TEST_DISTANCE_COMMON_HPP
13
14 #include <iostream>
15 #include <string>
16
17 #include <boost/math/special_functions/fpclassify.hpp>
18
19 #include <boost/geometry/algorithms/distance.hpp>
20 #include <boost/geometry/algorithms/comparable_distance.hpp>
21 #include <boost/geometry/algorithms/num_interior_rings.hpp>
22
23 #include <boost/geometry/geometries/geometries.hpp>
24
25 #include <boost/geometry/io/wkt/write.hpp>
26 #include <boost/geometry/io/dsv/write.hpp>
27
28 #include <boost/geometry/strategies/strategies.hpp>
29
30 #include <from_wkt.hpp>
31 #include <string_from_type.hpp>
32
33
34 #ifndef BOOST_GEOMETRY_TEST_DISTANCE_HPP
35
36 namespace bg = ::boost::geometry;
37
38 // function copied from BG's test_distance.hpp
39
40 template <typename Geometry1, typename Geometry2>
41 void test_empty_input(Geometry1 const& geometry1, Geometry2 const& geometry2)
42 {
43 try
44 {
45 bg::distance(geometry1, geometry2);
46 }
47 catch(bg::empty_input_exception const& )
48 {
49 return;
50 }
51 BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" );
52 }
53 #endif // BOOST_GEOMETRY_TEST_DISTANCE_HPP
54
55 //========================================================================
56
57
58
59 #ifdef BOOST_GEOMETRY_TEST_DEBUG
60 // pretty print geometry -- START
61 template <typename Geometry, typename GeometryTag>
62 struct pretty_print_geometry_dispatch
63 {
64 template <typename Stream>
65 static inline Stream& apply(Geometry const& geometry, Stream& os)
66 {
67 os << bg::wkt(geometry);
68 return os;
69 }
70 };
71
72 template <typename Geometry>
73 struct pretty_print_geometry_dispatch<Geometry, bg::segment_tag>
74 {
75 template <typename Stream>
76 static inline Stream& apply(Geometry const& geometry, Stream& os)
77 {
78 os << "SEGMENT" << bg::dsv(geometry);
79 return os;
80 }
81 };
82
83 template <typename Geometry>
84 struct pretty_print_geometry_dispatch<Geometry, bg::box_tag>
85 {
86 template <typename Stream>
87 static inline Stream& apply(Geometry const& geometry, Stream& os)
88 {
89 os << "BOX" << bg::dsv(geometry);
90 return os;
91 }
92 };
93
94
95 template <typename Geometry>
96 struct pretty_print_geometry
97 {
98 template <typename Stream>
99 static inline Stream& apply(Geometry const& geometry, Stream& os)
100 {
101 return pretty_print_geometry_dispatch
102 <
103 Geometry, typename bg::tag<Geometry>::type
104 >::apply(geometry, os);
105 }
106 };
107 // pretty print geometry -- END
108 #endif // BOOST_GEOMETRY_TEST_DEBUG
109
110
111 //========================================================================
112
113
114 template <typename T>
115 struct check_equal
116 {
117 static inline void apply(T const& detected, T const& expected,
118 bool is_finite)
119 {
120 if (is_finite)
121 {
122 BOOST_CHECK(detected == expected);
123 }
124 else
125 {
126 BOOST_CHECK(! boost::math::isfinite(detected));
127 }
128 }
129 };
130
131 template <>
132 struct check_equal<double>
133 {
134 static inline void apply(double detected, double expected,
135 bool is_finite)
136 {
137 if (is_finite)
138 {
139 BOOST_CHECK_CLOSE(detected, expected, 0.0001);
140 }
141 else
142 {
143 BOOST_CHECK(! boost::math::isfinite(detected));
144 }
145 }
146 };
147
148
149 //========================================================================
150
151 template
152 <
153 typename Geometry1, typename Geometry2,
154 int id1 = bg::geometry_id<Geometry1>::value,
155 int id2 = bg::geometry_id<Geometry2>::value
156 >
157 struct test_distance_of_geometries
158 : public test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
159 {};
160
161 #ifdef BOOST_GEOMETRY_TEST_DEBUG
162 #define ENABLE_IF_DEBUG(ID) ID
163 #else
164 #define ENABLE_IF_DEBUG(ID)
165 #endif
166
167 template <typename Geometry1, typename Geometry2>
168 class test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
169 {
170 private:
171 template
172 <
173 typename G1,
174 typename G2,
175 typename DistanceType,
176 typename ComparableDistanceType,
177 typename Strategy
178 >
179 static inline
180 void base_test(std::string const& ENABLE_IF_DEBUG(header),
181 G1 const& g1, G2 const& g2,
182 DistanceType const& expected_distance,
183 ComparableDistanceType const& expected_comparable_distance,
184 Strategy const& strategy,
185 bool is_finite)
186 {
187 typedef typename bg::default_distance_result
188 <
189 G1, G2
190 >::type default_distance_result;
191
192 typedef typename bg::strategy::distance::services::return_type
193 <
194 Strategy, G1, G2
195 >::type distance_result_from_strategy;
196
197 static const bool same_regular = std::is_same
198 <
199 default_distance_result,
200 distance_result_from_strategy
201 >::value;
202
203 BOOST_CHECK( same_regular );
204
205
206 typedef typename bg::default_comparable_distance_result
207 <
208 G1, G2
209 >::type default_comparable_distance_result;
210
211 typedef typename bg::strategy::distance::services::return_type
212 <
213 typename bg::strategy::distance::services::comparable_type
214 <
215 Strategy
216 >::type,
217 G1,
218 G2
219 >::type comparable_distance_result_from_strategy;
220
221 static const bool same_comparable = std::is_same
222 <
223 default_comparable_distance_result,
224 comparable_distance_result_from_strategy
225 >::value;
226
227 BOOST_CHECK( same_comparable );
228
229
230 // check distance with default strategy
231 default_distance_result dist_def = bg::distance(g1, g2);
232
233 check_equal
234 <
235 default_distance_result
236 >::apply(dist_def, expected_distance, is_finite);
237
238
239 // check distance with passed strategy
240 distance_result_from_strategy dist = bg::distance(g1, g2, strategy);
241
242 check_equal
243 <
244 default_distance_result
245 >::apply(dist, expected_distance, is_finite);
246
247
248 // check comparable distance with default strategy
249 default_comparable_distance_result cdist_def =
250 bg::comparable_distance(g1, g2);
251
252 check_equal
253 <
254 default_comparable_distance_result
255 >::apply(cdist_def, expected_comparable_distance, is_finite);
256
257
258 // check comparable distance with passed strategy
259 comparable_distance_result_from_strategy cdist =
260 bg::comparable_distance(g1, g2, strategy);
261
262 check_equal
263 <
264 default_comparable_distance_result
265 >::apply(cdist, expected_comparable_distance, is_finite);
266
267 #ifdef BOOST_GEOMETRY_TEST_DEBUG
268 std::cout << string_from_type<typename bg::coordinate_type<Geometry1>::type>::name()
269 << string_from_type<typename bg::coordinate_type<Geometry2>::type>::name()
270 << " -> "
271 << string_from_type<default_distance_result>::name()
272 << string_from_type<default_comparable_distance_result>::name()
273 << std::endl;
274
275 std::cout << "distance" << header
276 << " (def. strategy) = " << dist_def << " ; "
277 << "distance" << header
278 <<" (passed strategy) = " << dist << " ; "
279 << "comp. distance" << header <<" (def. strategy) = "
280 << cdist_def << " ; "
281 << "comp. distance" << header <<" (passed strategy) = "
282 << cdist << std::endl;
283 #endif
284 }
285
286 public:
287 template
288 <
289 typename DistanceType,
290 typename ComparableDistanceType,
291 typename Strategy
292 >
293 static inline
294 void apply(std::string const& wkt1,
295 std::string const& wkt2,
296 DistanceType const& expected_distance,
297 ComparableDistanceType const& expected_comparable_distance,
298 Strategy const& strategy,
299 bool is_finite = true)
300 {
301 Geometry1 geometry1 = from_wkt<Geometry1>(wkt1);
302 Geometry2 geometry2 = from_wkt<Geometry2>(wkt2);
303
304 apply(geometry1, geometry2,
305 expected_distance, expected_comparable_distance,
306 strategy, is_finite);
307 }
308
309
310 template
311 <
312 typename DistanceType,
313 typename ComparableDistanceType,
314 typename Strategy
315 >
316 static inline
317 void apply(Geometry1 const& geometry1,
318 Geometry2 const& geometry2,
319 DistanceType const& expected_distance,
320 ComparableDistanceType const& expected_comparable_distance,
321 Strategy const& strategy,
322 bool is_finite = true)
323 {
324 #ifdef BOOST_GEOMETRY_TEST_DEBUG
325 typedef pretty_print_geometry<Geometry1> PPG1;
326 typedef pretty_print_geometry<Geometry2> PPG2;
327 PPG1::apply(geometry1, std::cout);
328 std::cout << " - ";
329 PPG2::apply(geometry2, std::cout);
330 std::cout << std::endl;
331 #endif
332
333 base_test("", geometry1, geometry2,
334 expected_distance, expected_comparable_distance,
335 strategy, is_finite);
336
337 base_test("[reversed args]", geometry2, geometry1,
338 expected_distance, expected_comparable_distance,
339 strategy, is_finite);
340
341 #ifdef BOOST_GEOMETRY_TEST_DEBUG
342 std::cout << std::endl;
343 #endif
344 }
345 };
346
347
348 //========================================================================
349
350 template <typename Segment, typename Polygon>
351 struct test_distance_of_geometries
352 <
353 Segment, Polygon,
354 92 /* segment */, 3 /* polygon */
355 >
356 : public test_distance_of_geometries<Segment, Polygon, 0, 0>
357 {
358 typedef test_distance_of_geometries<Segment, Polygon, 0, 0> base;
359
360 typedef typename bg::ring_type<Polygon>::type ring_type;
361
362 template
363 <
364 typename DistanceType,
365 typename ComparableDistanceType,
366 typename Strategy
367 >
368 static inline
369 void apply(std::string const& wkt_segment,
370 std::string const& wkt_polygon,
371 DistanceType const& expected_distance,
372 ComparableDistanceType const& expected_comparable_distance,
373 Strategy const& strategy,
374 bool is_finite = true)
375 {
376 Segment segment = from_wkt<Segment>(wkt_segment);
377 Polygon polygon = from_wkt<Polygon>(wkt_polygon);
378 apply(segment,
379 polygon,
380 expected_distance,
381 expected_comparable_distance,
382 strategy,
383 is_finite);
384 }
385
386
387 template
388 <
389 typename DistanceType,
390 typename ComparableDistanceType,
391 typename Strategy
392 >
393 static inline
394 void apply(Segment const& segment,
395 Polygon const& polygon,
396 DistanceType const& expected_distance,
397 ComparableDistanceType const& expected_comparable_distance,
398 Strategy const& strategy,
399 bool is_finite = true)
400 {
401 base::apply(segment, polygon, expected_distance,
402 expected_comparable_distance, strategy, is_finite);
403
404 if ( bg::num_interior_rings(polygon) == 0 ) {
405 #ifdef BOOST_GEOMETRY_TEST_DEBUG
406 std::cout << "... testing also exterior ring ..." << std::endl;
407 #endif
408 test_distance_of_geometries
409 <
410 Segment, ring_type
411 >::apply(segment,
412 bg::exterior_ring(polygon),
413 expected_distance,
414 expected_comparable_distance,
415 strategy,
416 is_finite);
417 }
418 }
419 };
420
421 //========================================================================
422
423 template <typename Box, typename Segment>
424 struct test_distance_of_geometries
425 <
426 Box, Segment,
427 94 /* box */, 92 /* segment */
428 >
429 {
430 template
431 <
432 typename DistanceType,
433 typename ComparableDistanceType,
434 typename Strategy
435 >
436 static inline
437 void apply(std::string const& wkt_box,
438 std::string const& wkt_segment,
439 DistanceType const& expected_distance,
440 ComparableDistanceType const& expected_comparable_distance,
441 Strategy const& strategy,
442 bool is_finite = true)
443 {
444 test_distance_of_geometries
445 <
446 Segment, Box, 92, 94
447 >::apply(wkt_segment,
448 wkt_box,
449 expected_distance,
450 expected_comparable_distance,
451 strategy,
452 is_finite);
453 }
454 };
455
456
457 template <typename Segment, typename Box>
458 struct test_distance_of_geometries
459 <
460 Segment, Box,
461 92 /* segment */, 94 /* box */
462 >
463 : public test_distance_of_geometries<Segment, Box, 0, 0>
464 {
465 typedef test_distance_of_geometries<Segment, Box, 0, 0> base;
466
467 template
468 <
469 typename DistanceType,
470 typename ComparableDistanceType,
471 typename Strategy
472 >
473 static inline
474 void apply(std::string const& wkt_segment,
475 std::string const& wkt_box,
476 DistanceType const& expected_distance,
477 ComparableDistanceType const& expected_comparable_distance,
478 Strategy const& strategy,
479 bool is_finite = true)
480 {
481 Segment segment = from_wkt<Segment>(wkt_segment);
482 Box box = from_wkt<Box>(wkt_box);
483 apply(segment,
484 box,
485 expected_distance,
486 expected_comparable_distance,
487 strategy,
488 is_finite);
489 }
490
491
492 template
493 <
494 typename DistanceType,
495 typename ComparableDistanceType,
496 typename Strategy
497 >
498 static inline
499 void apply(Segment const& segment,
500 Box const& box,
501 DistanceType const& expected_distance,
502 ComparableDistanceType const& expected_comparable_distance,
503 Strategy const& strategy,
504 bool is_finite = true)
505 {
506 typedef typename bg::strategy::distance::services::return_type
507 <
508 Strategy, Segment, Box
509 >::type distance_result_type;
510
511 typedef typename bg::strategy::distance::services::comparable_type
512 <
513 Strategy
514 >::type comparable_strategy;
515
516 typedef typename bg::strategy::distance::services::return_type
517 <
518 comparable_strategy, Segment, Box
519 >::type comparable_distance_result_type;
520
521
522 base::apply(segment, box, expected_distance,
523 expected_comparable_distance, strategy, is_finite);
524
525 auto strategies = bg::strategies::distance::services::strategy_converter<Strategy>::get(strategy);
526 auto cstrategies = bg::strategies::distance::detail::make_comparable(strategies);
527
528 // TODO: these algorithms are used only here. Remove them?
529
530 distance_result_type distance_generic =
531 bg::detail::distance::segment_to_box_2D_generic
532 <
533 Segment, Box, decltype(strategies), false
534 >::apply(segment, box, strategies);
535
536 comparable_distance_result_type comparable_distance_generic =
537 bg::detail::distance::segment_to_box_2D_generic
538 <
539 Segment, Box, decltype(cstrategies), false
540 >::apply(segment, box, cstrategies);
541
542 check_equal
543 <
544 distance_result_type
545 >::apply(distance_generic, expected_distance, is_finite);
546
547 check_equal
548 <
549 comparable_distance_result_type
550 >::apply(comparable_distance_generic,
551 expected_comparable_distance,
552 is_finite);
553
554 distance_generic =
555 bg::detail::distance::segment_to_box_2D_generic
556 <
557 Segment, Box, decltype(strategies), true
558 >::apply(segment, box, strategies);
559
560 comparable_distance_generic =
561 bg::detail::distance::segment_to_box_2D_generic
562 <
563 Segment, Box, decltype(cstrategies), true
564 >::apply(segment, box, cstrategies);
565
566 check_equal
567 <
568 distance_result_type
569 >::apply(distance_generic, expected_distance, is_finite);
570
571 check_equal
572 <
573 comparable_distance_result_type
574 >::apply(comparable_distance_generic,
575 expected_comparable_distance,
576 is_finite);
577
578 #ifdef BOOST_GEOMETRY_TEST_DEBUG
579 std::cout << "... testing with naive seg-box distance algorithm..."
580 << std::endl;
581 std::cout << "distance (generic algorithm) = "
582 << distance_generic << " ; "
583 << "comp. distance (generic algorithm) = "
584 << comparable_distance_generic
585 << std::endl;
586 std::cout << std::endl << std::endl;
587 #endif
588 }
589 };
590
591 //========================================================================
592
593
594 template <typename Geometry1, typename Geometry2, typename Strategy>
595 void test_empty_input(Geometry1 const& geometry1,
596 Geometry2 const& geometry2,
597 Strategy const& strategy)
598 {
599 try
600 {
601 bg::distance(geometry1, geometry2, strategy);
602 }
603 catch(bg::empty_input_exception const& )
604 {
605 return;
606 }
607 BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" );
608
609 try
610 {
611 bg::distance(geometry2, geometry1, strategy);
612 }
613 catch(bg::empty_input_exception const& )
614 {
615 return;
616 }
617 BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" );
618 }
619
620 #endif // BOOST_GEOMETRY_TEST_DISTANCE_COMMON_HPP