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