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