1 // Boost.Geometry (aka GGL, Generic Geometry Library)
4 // Copyright (c) 2014-2017, Oracle and/or its affiliates.
6 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
7 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
9 // Licensed under the Boost Software License version 1.0.
10 // http://www.boost.org/users/license.html
12 #ifndef BOOST_GEOMETRY_TEST_DISTANCE_COMMON_HPP
13 #define BOOST_GEOMETRY_TEST_DISTANCE_COMMON_HPP
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>
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>
34 #include <boost/geometry/io/wkt/write.hpp>
35 #include <boost/geometry/io/dsv/write.hpp>
37 #include <boost/geometry/algorithms/num_interior_rings.hpp>
38 #include <boost/geometry/algorithms/distance.hpp>
39 #include <boost/geometry/algorithms/comparable_distance.hpp>
41 #include <boost/geometry/strategies/strategies.hpp>
43 #include <from_wkt.hpp>
44 #include <string_from_type.hpp>
47 #ifndef BOOST_GEOMETRY_TEST_DISTANCE_HPP
49 namespace bg = ::boost::geometry;
51 // function copied from BG's test_distance.hpp
53 template <typename Geometry1, typename Geometry2>
54 void test_empty_input(Geometry1 const& geometry1, Geometry2 const& geometry2)
58 bg::distance(geometry1, geometry2);
60 catch(bg::empty_input_exception const& )
64 BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" );
66 #endif // BOOST_GEOMETRY_TEST_DISTANCE_HPP
70 //========================================================================
74 #ifdef BOOST_GEOMETRY_TEST_DEBUG
75 // pretty print geometry -- START
76 template <typename Geometry, typename GeometryTag>
77 struct pretty_print_geometry_dispatch
79 template <typename Stream>
80 static inline Stream& apply(Geometry const& geometry, Stream& os)
82 os << bg::wkt(geometry);
87 template <typename Geometry>
88 struct pretty_print_geometry_dispatch<Geometry, bg::segment_tag>
90 template <typename Stream>
91 static inline Stream& apply(Geometry const& geometry, Stream& os)
93 os << "SEGMENT" << bg::dsv(geometry);
98 template <typename Geometry>
99 struct pretty_print_geometry_dispatch<Geometry, bg::box_tag>
101 template <typename Stream>
102 static inline Stream& apply(Geometry const& geometry, Stream& os)
104 os << "BOX" << bg::dsv(geometry);
110 template <typename Geometry>
111 struct pretty_print_geometry
113 template <typename Stream>
114 static inline Stream& apply(Geometry const& geometry, Stream& os)
116 return pretty_print_geometry_dispatch
118 Geometry, typename bg::tag<Geometry>::type
119 >::apply(geometry, os);
122 // pretty print geometry -- END
123 #endif // BOOST_GEOMETRY_TEST_DEBUG
126 //========================================================================
129 template <typename T>
132 static inline void apply(T const& detected, T const& expected,
137 BOOST_CHECK(detected == expected);
141 BOOST_CHECK(! boost::math::isfinite(detected));
147 struct check_equal<double>
149 static inline void apply(double detected, double expected,
154 BOOST_CHECK_CLOSE(detected, expected, 0.0001);
158 BOOST_CHECK(! boost::math::isfinite(detected));
164 //========================================================================
168 typename Geometry1, typename Geometry2,
169 int id1 = bg::geometry_id<Geometry1>::value,
170 int id2 = bg::geometry_id<Geometry2>::value
172 struct test_distance_of_geometries
173 : public test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
176 #ifdef BOOST_GEOMETRY_TEST_DEBUG
177 #define ENABLE_IF_DEBUG(ID) ID
179 #define ENABLE_IF_DEBUG(ID)
182 template <typename Geometry1, typename Geometry2>
183 class test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
190 typename DistanceType,
191 typename ComparableDistanceType,
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,
202 typedef typename bg::default_distance_result
205 >::type default_distance_result;
207 typedef typename bg::strategy::distance::services::return_type
210 >::type distance_result_from_strategy;
212 static const bool same_regular = boost::is_same
214 default_distance_result,
215 distance_result_from_strategy
218 BOOST_CHECK( same_regular );
221 typedef typename bg::default_comparable_distance_result
224 >::type default_comparable_distance_result;
226 typedef typename bg::strategy::distance::services::return_type
228 typename bg::strategy::distance::services::comparable_type
234 >::type comparable_distance_result_from_strategy;
236 static const bool same_comparable = boost::is_same
238 default_comparable_distance_result,
239 comparable_distance_result_from_strategy
242 BOOST_CHECK( same_comparable );
245 // check distance with default strategy
246 default_distance_result dist_def = bg::distance(g1, g2);
250 default_distance_result
251 >::apply(dist_def, expected_distance, is_finite);
254 // check distance with passed strategy
255 distance_result_from_strategy dist = bg::distance(g1, g2, strategy);
259 default_distance_result
260 >::apply(dist, expected_distance, is_finite);
263 // check comparable distance with default strategy
264 default_comparable_distance_result cdist_def =
265 bg::comparable_distance(g1, g2);
269 default_comparable_distance_result
270 >::apply(cdist_def, expected_comparable_distance, is_finite);
273 // check comparable distance with passed strategy
274 comparable_distance_result_from_strategy cdist =
275 bg::comparable_distance(g1, g2, strategy);
279 default_comparable_distance_result
280 >::apply(cdist, expected_comparable_distance, is_finite);
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()
286 << string_from_type<default_distance_result>::name()
287 << string_from_type<default_comparable_distance_result>::name()
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;
304 typename DistanceType,
305 typename ComparableDistanceType,
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)
316 Geometry1 geometry1 = from_wkt<Geometry1>(wkt1);
317 Geometry2 geometry2 = from_wkt<Geometry2>(wkt2);
319 apply(geometry1, geometry2,
320 expected_distance, expected_comparable_distance,
321 strategy, is_finite);
327 typename DistanceType,
328 typename ComparableDistanceType,
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)
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);
344 PPG2::apply(geometry2, std::cout);
345 std::cout << std::endl;
348 base_test("", geometry1, geometry2,
349 expected_distance, expected_comparable_distance,
350 strategy, is_finite);
352 base_test("[reversed args]", geometry2, geometry1,
353 expected_distance, expected_comparable_distance,
354 strategy, is_finite);
356 #ifdef BOOST_GEOMETRY_TEST_DEBUG
357 std::cout << std::endl;
363 //========================================================================
365 template <typename Segment, typename Polygon>
366 struct test_distance_of_geometries
369 92 /* segment */, 3 /* polygon */
371 : public test_distance_of_geometries<Segment, Polygon, 0, 0>
373 typedef test_distance_of_geometries<Segment, Polygon, 0, 0> base;
375 typedef typename bg::ring_type<Polygon>::type ring_type;
379 typename DistanceType,
380 typename ComparableDistanceType,
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)
391 Segment segment = from_wkt<Segment>(wkt_segment);
392 Polygon polygon = from_wkt<Polygon>(wkt_polygon);
396 expected_comparable_distance,
404 typename DistanceType,
405 typename ComparableDistanceType,
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)
416 base::apply(segment, polygon, expected_distance,
417 expected_comparable_distance, strategy, is_finite);
419 if ( bg::num_interior_rings(polygon) == 0 ) {
420 #ifdef BOOST_GEOMETRY_TEST_DEBUG
421 std::cout << "... testing also exterior ring ..." << std::endl;
423 test_distance_of_geometries
427 bg::exterior_ring(polygon),
429 expected_comparable_distance,
436 //========================================================================
438 template <typename Box, typename Segment>
439 struct test_distance_of_geometries
442 94 /* box */, 92 /* segment */
447 typename DistanceType,
448 typename ComparableDistanceType,
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)
459 test_distance_of_geometries
462 >::apply(wkt_segment,
465 expected_comparable_distance,
472 template <typename Segment, typename Box>
473 struct test_distance_of_geometries
476 92 /* segment */, 94 /* box */
478 : public test_distance_of_geometries<Segment, Box, 0, 0>
480 typedef test_distance_of_geometries<Segment, Box, 0, 0> base;
484 typename DistanceType,
485 typename ComparableDistanceType,
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)
496 Segment segment = from_wkt<Segment>(wkt_segment);
497 Box box = from_wkt<Box>(wkt_box);
501 expected_comparable_distance,
509 typename DistanceType,
510 typename ComparableDistanceType,
514 void apply(Segment const& segment,
516 DistanceType const& expected_distance,
517 ComparableDistanceType const& expected_comparable_distance,
518 Strategy const& strategy,
519 bool is_finite = true)
521 typedef typename bg::strategy::distance::services::return_type
523 Strategy, Segment, Box
524 >::type distance_result_type;
526 typedef typename bg::strategy::distance::services::comparable_type
529 >::type comparable_strategy;
531 typedef typename bg::strategy::distance::services::return_type
533 comparable_strategy, Segment, Box
534 >::type comparable_distance_result_type;
537 base::apply(segment, box, expected_distance,
538 expected_comparable_distance, strategy, is_finite);
540 comparable_strategy cstrategy =
541 bg::strategy::distance::services::get_comparable
546 distance_result_type distance_generic =
547 bg::detail::distance::segment_to_box_2D_generic
549 Segment, Box, Strategy
550 >::apply(segment, box, strategy);
552 comparable_distance_result_type comparable_distance_generic =
553 bg::detail::distance::segment_to_box_2D_generic
555 Segment, Box, comparable_strategy
556 >::apply(segment, box, cstrategy);
562 >::apply(distance_generic, expected_distance, is_finite);
566 comparable_distance_result_type
567 >::apply(comparable_distance_generic,
568 expected_comparable_distance,
571 #ifdef BOOST_GEOMETRY_TEST_DEBUG
572 std::cout << "... testing with naive seg-box distance algorithm..."
574 std::cout << "distance (generic algorithm) = "
575 << distance_generic << " ; "
576 << "comp. distance (generic algorithm) = "
577 << comparable_distance_generic
579 std::cout << std::endl << std::endl;
584 //========================================================================
587 template <typename Geometry1, typename Geometry2, typename Strategy>
588 void test_empty_input(Geometry1 const& geometry1,
589 Geometry2 const& geometry2,
590 Strategy const& strategy)
594 bg::distance(geometry1, geometry2, strategy);
596 catch(bg::empty_input_exception const& )
600 BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" );
604 bg::distance(geometry2, geometry1, strategy);
606 catch(bg::empty_input_exception const& )
610 BOOST_CHECK_MESSAGE(false, "A empty_input_exception should have been thrown" );
613 #endif // BOOST_GEOMETRY_TEST_DISTANCE_COMMON_HPP