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_SE_COMMON_HPP
12 #define BOOST_GEOMETRY_TEST_DISTANCE_SE_COMMON_HPP
17 #include <boost/mpl/assert.hpp>
18 #include <boost/type_traits/is_integral.hpp>
19 #include <boost/type_traits/is_same.hpp>
21 #include <boost/geometry/geometries/point.hpp>
22 #include <boost/geometry/geometries/point_xy.hpp>
23 #include <boost/geometry/geometries/segment.hpp>
24 #include <boost/geometry/geometries/linestring.hpp>
25 #include <boost/geometry/geometries/polygon.hpp>
26 #include <boost/geometry/geometries/ring.hpp>
27 #include <boost/geometry/geometries/box.hpp>
28 #include <boost/geometry/geometries/multi_point.hpp>
29 #include <boost/geometry/geometries/multi_linestring.hpp>
30 #include <boost/geometry/geometries/multi_polygon.hpp>
32 #include <boost/geometry/io/wkt/write.hpp>
33 #include <boost/geometry/io/dsv/write.hpp>
35 #include <boost/geometry/algorithms/num_interior_rings.hpp>
36 #include <boost/geometry/algorithms/distance.hpp>
37 #include <boost/geometry/algorithms/comparable_distance.hpp>
39 #include <from_wkt.hpp>
40 #include <string_from_type.hpp>
42 #include "distance_brute_force.hpp"
44 namespace bg = ::boost::geometry;
46 static const double earth_radius_km = 6371.0;
47 static const double earth_radius_miles = 3959.0;
50 //========================================================================
56 template <typename Value, typename = void>
59 static inline void apply(Value const& x, Value const& y)
65 template <typename Dummy>
66 struct equal_to<double, Dummy>
68 static inline void apply(double x, double y)
70 BOOST_CHECK_CLOSE(x, y, 0.001);
74 template <typename Geometry1, typename Geometry2>
75 static inline void apply(std::string const& /*case_id*/,
76 std::string const& /*subcase_id*/,
77 Geometry1 const& /*geometry1*/,
78 Geometry2 const& /*geometry2*/,
82 equal_to<T>::apply(expected, detected);
85 Ideally we would want the following, but it does not work well
86 approximate equality test.
88 BOOST_CHECK_MESSAGE(equal_to<T>::apply(expected, detected),
89 "case ID: " << case_id << "-" << subcase_id << "; "
90 << "G1: " << bg::wkt(geometry1)
92 << "G2: " << bg::wkt(geometry2)
93 << " -> Detected: " << detected
94 << "; Expected: " << expected);
99 //========================================================================
103 typename Geometry1, typename Geometry2,
104 int id1 = bg::geometry_id<Geometry1>::value,
105 int id2 = bg::geometry_id<Geometry2>::value
107 struct test_distance_of_geometries
108 : public test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
112 template <typename Geometry1, typename Geometry2>
113 struct test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
117 typename DistanceType,
118 typename ComparableDistanceType,
122 void apply(std::string const& case_id,
123 std::string const& wkt1,
124 std::string const& wkt2,
125 DistanceType const& expected_distance,
126 ComparableDistanceType const& expected_comparable_distance,
127 Strategy const& strategy,
128 bool test_reversed = true)
130 Geometry1 geometry1 = from_wkt<Geometry1>(wkt1);
131 Geometry2 geometry2 = from_wkt<Geometry2>(wkt2);
133 apply(case_id, geometry1, geometry2,
134 expected_distance, expected_comparable_distance,
135 strategy, test_reversed);
138 template <typename DistanceType, typename Strategy>
140 void apply(std::string const& case_id,
141 std::string const& wkt1,
142 std::string const& wkt2,
143 DistanceType const& expected_distance,
144 Strategy const& strategy,
145 bool test_reversed = true)
147 Geometry1 geometry1 = from_wkt<Geometry1>(wkt1);
148 Geometry2 geometry2 = from_wkt<Geometry2>(wkt2);
150 apply(case_id, geometry1, geometry2,
151 expected_distance, expected_distance,
152 strategy, test_reversed);
158 typename DistanceType,
159 typename ComparableDistanceType,
163 void apply(std::string const& case_id,
164 Geometry1 const& geometry1,
165 Geometry2 const& geometry2,
166 DistanceType const& expected_distance,
167 ComparableDistanceType const& expected_comparable_distance,
168 Strategy const& strategy,
169 bool test_reversed = true)
171 #ifdef BOOST_GEOMETRY_TEST_DEBUG
172 std::cout << "case ID: " << case_id << "; "
173 << "G1: " << bg::wkt(geometry1)
175 << "G2: " << bg::wkt(geometry2)
178 namespace services = bg::strategy::distance::services;
180 using bg::unit_test::distance_brute_force;
182 typedef typename bg::default_distance_result
185 >::type default_distance_result;
187 typedef typename services::return_type
189 Strategy, Geometry1, Geometry2
190 >::type distance_result_from_strategy;
192 static const bool same_regular = boost::is_same
194 default_distance_result,
195 distance_result_from_strategy
198 BOOST_CHECK(same_regular);
200 typedef typename bg::default_comparable_distance_result
203 >::type default_comparable_distance_result;
205 typedef typename services::return_type
207 typename services::comparable_type<Strategy>::type,
210 >::type comparable_distance_result_from_strategy;
212 static const bool same_comparable = boost::is_same
214 default_comparable_distance_result,
215 comparable_distance_result_from_strategy
218 BOOST_CHECK( same_comparable );
220 // check distance with passed strategy
221 distance_result_from_strategy dist =
222 bg::distance(geometry1, geometry2, strategy);
226 distance_result_from_strategy
227 >::apply(case_id, "a", geometry1, geometry2,
228 dist, expected_distance);
230 // check against the comparable distance computed in a
231 // brute-force manner
232 default_distance_result dist_brute_force
233 = distance_brute_force(geometry1, geometry2, strategy);
237 default_distance_result
238 >::apply(case_id, "b", geometry1, geometry2,
239 dist_brute_force, expected_distance);
241 // check comparable distance with passed strategy
242 comparable_distance_result_from_strategy cdist =
243 bg::comparable_distance(geometry1, geometry2, strategy);
247 default_comparable_distance_result
248 >::apply(case_id, "c", geometry1, geometry2,
249 cdist, expected_comparable_distance);
251 // check against the comparable distance computed in a
252 // brute-force manner
253 default_comparable_distance_result cdist_brute_force
254 = distance_brute_force(geometry1,
256 services::get_comparable
263 default_comparable_distance_result
264 >::apply(case_id, "d", geometry1, geometry2,
265 cdist_brute_force, expected_comparable_distance);
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()
271 << string_from_type<default_distance_result>::name()
272 << string_from_type<default_comparable_distance_result>::name()
274 std::cout << "strategy radius: " << strategy.radius() << std::endl;
275 std::cout << "expected distance = "
276 << expected_distance << " ; "
277 << "expected comp. distance = "
278 << expected_comparable_distance
280 std::cout << "distance = "
282 << "comp. distance = "
286 if ( !test_reversed )
288 std::cout << std::endl;
294 // check distance with given strategy
295 dist = bg::distance(geometry2, geometry1, strategy);
299 default_distance_result
300 >::apply(case_id, "ra", geometry2, geometry1,
301 dist, expected_distance);
303 // check comparable distance with given strategy
304 cdist = bg::comparable_distance(geometry2, geometry1, strategy);
308 default_comparable_distance_result
309 >::apply(case_id, "rc", geometry2, geometry1,
310 cdist, expected_comparable_distance);
312 #ifdef BOOST_GEOMETRY_TEST_DEBUG
313 std::cout << "distance[reversed args] = "
315 << "comp. distance[reversed args] = "
318 std::cout << std::endl;
325 //========================================================================
328 template <typename Geometry1, typename Geometry2, typename Strategy>
329 void test_empty_input(Geometry1 const& geometry1,
330 Geometry2 const& geometry2,
331 Strategy const& strategy)
335 bg::distance(geometry1, geometry2);
337 catch(bg::empty_input_exception const& )
341 BOOST_CHECK_MESSAGE(false,
342 "A empty_input_exception should have been thrown");
346 bg::distance(geometry2, geometry1);
348 catch(bg::empty_input_exception const& )
352 BOOST_CHECK_MESSAGE(false,
353 "A empty_input_exception should have been thrown");
357 bg::distance(geometry1, geometry2, strategy);
359 catch(bg::empty_input_exception const& )
363 BOOST_CHECK_MESSAGE(false,
364 "A empty_input_exception should have been thrown");
368 bg::distance(geometry2, geometry1, strategy);
370 catch(bg::empty_input_exception const& )
374 BOOST_CHECK_MESSAGE(false,
375 "A empty_input_exception should have been thrown");
378 #endif // BOOST_GEOMETRY_TEST_DISTANCE_SE_COMMON_HPP