1 // Boost.Geometry (aka GGL, Generic Geometry Library)
4 // Copyright (c) 2014-2015, Oracle and/or its affiliates.
6 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
8 // Licensed under the Boost Software License version 1.0.
9 // http://www.boost.org/users/license.html
11 #ifndef BOOST_GEOMETRY_TEST_DISTANCE_COMMON_HPP
12 #define BOOST_GEOMETRY_TEST_DISTANCE_COMMON_HPP
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>
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>
33 #include <boost/geometry/io/wkt/write.hpp>
34 #include <boost/geometry/io/dsv/write.hpp>
36 #include <boost/geometry/algorithms/num_interior_rings.hpp>
37 #include <boost/geometry/algorithms/distance.hpp>
38 #include <boost/geometry/algorithms/comparable_distance.hpp>
40 #include <from_wkt.hpp>
41 #include <string_from_type.hpp>
44 #ifndef BOOST_GEOMETRY_TEST_DISTANCE_HPP
46 namespace bg = ::boost::geometry;
48 // function copied from BG's test_distance.hpp
50 template <typename Geometry1, typename Geometry2>
51 void test_empty_input(Geometry1 const& geometry1, Geometry2 const& geometry2)
55 bg::distance(geometry1, geometry2);
57 catch(bg::empty_input_exception const& )
61 BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" );
63 #endif // BOOST_GEOMETRY_TEST_DISTANCE_HPP
67 //========================================================================
71 #ifdef BOOST_GEOMETRY_TEST_DEBUG
72 // pretty print geometry -- START
73 template <typename Geometry, typename GeometryTag>
74 struct pretty_print_geometry_dispatch
76 template <typename Stream>
77 static inline Stream& apply(Geometry const& geometry, Stream& os)
79 os << bg::wkt(geometry);
84 template <typename Geometry>
85 struct pretty_print_geometry_dispatch<Geometry, bg::segment_tag>
87 template <typename Stream>
88 static inline Stream& apply(Geometry const& geometry, Stream& os)
90 os << "SEGMENT" << bg::dsv(geometry);
95 template <typename Geometry>
96 struct pretty_print_geometry_dispatch<Geometry, bg::box_tag>
98 template <typename Stream>
99 static inline Stream& apply(Geometry const& geometry, Stream& os)
101 os << "BOX" << bg::dsv(geometry);
107 template <typename Geometry>
108 struct pretty_print_geometry
110 template <typename Stream>
111 static inline Stream& apply(Geometry const& geometry, Stream& os)
113 return pretty_print_geometry_dispatch
115 Geometry, typename bg::tag<Geometry>::type
116 >::apply(geometry, os);
119 // pretty print geometry -- END
120 #endif // BOOST_GEOMETRY_TEST_DEBUG
123 //========================================================================
126 template <typename T>
129 static inline void apply(T const& detected, T const& expected,
134 BOOST_CHECK(detected == expected);
138 BOOST_CHECK(! boost::math::isfinite(detected));
144 struct check_equal<double>
146 static inline void apply(double detected, double expected,
151 BOOST_CHECK_CLOSE(detected, expected, 0.0001);
155 BOOST_CHECK(! boost::math::isfinite(detected));
161 //========================================================================
165 typename Geometry1, typename Geometry2,
166 int id1 = bg::geometry_id<Geometry1>::value,
167 int id2 = bg::geometry_id<Geometry2>::value
169 struct test_distance_of_geometries
170 : public test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
174 template <typename Geometry1, typename Geometry2>
175 class test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
182 typename DistanceType,
183 typename ComparableDistanceType,
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,
194 typedef typename bg::default_distance_result
197 >::type default_distance_result;
199 typedef typename bg::strategy::distance::services::return_type
202 >::type distance_result_from_strategy;
204 static const bool same_regular = boost::is_same
206 default_distance_result,
207 distance_result_from_strategy
210 BOOST_CHECK( same_regular );
213 typedef typename bg::default_comparable_distance_result
216 >::type default_comparable_distance_result;
218 typedef typename bg::strategy::distance::services::return_type
220 typename bg::strategy::distance::services::comparable_type
226 >::type comparable_distance_result_from_strategy;
228 static const bool same_comparable = boost::is_same
230 default_comparable_distance_result,
231 comparable_distance_result_from_strategy
234 BOOST_CHECK( same_comparable );
237 // check distance with default strategy
238 default_distance_result dist_def = bg::distance(g1, g2);
242 default_distance_result
243 >::apply(dist_def, expected_distance, is_finite);
246 // check distance with passed strategy
247 distance_result_from_strategy dist = bg::distance(g1, g2, strategy);
251 default_distance_result
252 >::apply(dist, expected_distance, is_finite);
255 // check comparable distance with default strategy
256 default_comparable_distance_result cdist_def =
257 bg::comparable_distance(g1, g2);
261 default_comparable_distance_result
262 >::apply(cdist_def, expected_comparable_distance, is_finite);
265 // check comparable distance with passed strategy
266 comparable_distance_result_from_strategy cdist =
267 bg::comparable_distance(g1, g2, strategy);
271 default_comparable_distance_result
272 >::apply(cdist, expected_comparable_distance, is_finite);
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()
278 << string_from_type<default_distance_result>::name()
279 << string_from_type<default_comparable_distance_result>::name()
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;
296 typename DistanceType,
297 typename ComparableDistanceType,
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)
308 Geometry1 geometry1 = from_wkt<Geometry1>(wkt1);
309 Geometry2 geometry2 = from_wkt<Geometry2>(wkt2);
311 apply(geometry1, geometry2,
312 expected_distance, expected_comparable_distance,
313 strategy, is_finite);
319 typename DistanceType,
320 typename ComparableDistanceType,
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)
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);
336 PPG2::apply(geometry2, std::cout);
337 std::cout << std::endl;
340 base_test("", geometry1, geometry2,
341 expected_distance, expected_comparable_distance,
342 strategy, is_finite);
344 base_test("[reversed args]", geometry2, geometry1,
345 expected_distance, expected_comparable_distance,
346 strategy, is_finite);
348 #ifdef BOOST_GEOMETRY_TEST_DEBUG
349 std::cout << std::endl;
355 //========================================================================
357 template <typename Segment, typename Polygon>
358 struct test_distance_of_geometries
361 92 /* segment */, 3 /* polygon */
363 : public test_distance_of_geometries<Segment, Polygon, 0, 0>
365 typedef test_distance_of_geometries<Segment, Polygon, 0, 0> base;
367 typedef typename bg::ring_type<Polygon>::type ring_type;
371 typename DistanceType,
372 typename ComparableDistanceType,
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)
383 Segment segment = from_wkt<Segment>(wkt_segment);
384 Polygon polygon = from_wkt<Polygon>(wkt_polygon);
388 expected_comparable_distance,
396 typename DistanceType,
397 typename ComparableDistanceType,
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)
408 base::apply(segment, polygon, expected_distance,
409 expected_comparable_distance, strategy, is_finite);
411 if ( bg::num_interior_rings(polygon) == 0 ) {
412 #ifdef BOOST_GEOMETRY_TEST_DEBUG
413 std::cout << "... testing also exterior ring ..." << std::endl;
415 test_distance_of_geometries
419 bg::exterior_ring(polygon),
421 expected_comparable_distance,
428 //========================================================================
430 template <typename Box, typename Segment>
431 struct test_distance_of_geometries
434 94 /* box */, 92 /* segment */
439 typename DistanceType,
440 typename ComparableDistanceType,
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)
451 test_distance_of_geometries
454 >::apply(wkt_segment,
457 expected_comparable_distance,
464 template <typename Segment, typename Box>
465 struct test_distance_of_geometries
468 92 /* segment */, 94 /* box */
470 : public test_distance_of_geometries<Segment, Box, 0, 0>
472 typedef test_distance_of_geometries<Segment, Box, 0, 0> base;
476 typename DistanceType,
477 typename ComparableDistanceType,
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)
488 Segment segment = from_wkt<Segment>(wkt_segment);
489 Box box = from_wkt<Box>(wkt_box);
493 expected_comparable_distance,
501 typename DistanceType,
502 typename ComparableDistanceType,
506 void apply(Segment const& segment,
508 DistanceType const& expected_distance,
509 ComparableDistanceType const& expected_comparable_distance,
510 Strategy const& strategy,
511 bool is_finite = true)
513 typedef typename bg::strategy::distance::services::return_type
515 Strategy, Segment, Box
516 >::type distance_result_type;
518 typedef typename bg::strategy::distance::services::comparable_type
521 >::type comparable_strategy;
523 typedef typename bg::strategy::distance::services::return_type
525 comparable_strategy, Segment, Box
526 >::type comparable_distance_result_type;
529 base::apply(segment, box, expected_distance,
530 expected_comparable_distance, strategy, is_finite);
532 comparable_strategy cstrategy =
533 bg::strategy::distance::services::get_comparable
538 distance_result_type distance_generic =
539 bg::detail::distance::segment_to_box_2D_generic
541 Segment, Box, Strategy
542 >::apply(segment, box, strategy);
544 comparable_distance_result_type comparable_distance_generic =
545 bg::detail::distance::segment_to_box_2D_generic
547 Segment, Box, comparable_strategy
548 >::apply(segment, box, cstrategy);
554 >::apply(distance_generic, expected_distance, is_finite);
558 comparable_distance_result_type
559 >::apply(comparable_distance_generic,
560 expected_comparable_distance,
563 #ifdef BOOST_GEOMETRY_TEST_DEBUG
564 std::cout << "... testing with naive seg-box distance algorithm..."
566 std::cout << "distance (generic algorithm) = "
567 << distance_generic << " ; "
568 << "comp. distance (generic algorithm) = "
569 << comparable_distance_generic
571 std::cout << std::endl << std::endl;
576 //========================================================================
579 template <typename Geometry1, typename Geometry2, typename Strategy>
580 void test_empty_input(Geometry1 const& geometry1,
581 Geometry2 const& geometry2,
582 Strategy const& strategy)
586 bg::distance(geometry1, geometry2, strategy);
588 catch(bg::empty_input_exception const& )
592 BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" );
596 bg::distance(geometry2, geometry1, strategy);
598 catch(bg::empty_input_exception const& )
602 BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" );
605 #endif // BOOST_GEOMETRY_TEST_DISTANCE_COMMON_HPP