]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | // Unit Test | |
3 | ||
b32b8144 | 4 | // Copyright (c) 2014-2017, Oracle and/or its affiliates. |
7c673cae FG |
5 | |
6 | // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle | |
b32b8144 | 7 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle |
7c673cae FG |
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_SE_COMMON_HPP | |
13 | #define BOOST_GEOMETRY_TEST_DISTANCE_SE_COMMON_HPP | |
14 | ||
15 | #include <iostream> | |
16 | #include <string> | |
17 | ||
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 | ||
b32b8144 FG |
40 | #include <boost/geometry/strategies/strategies.hpp> |
41 | ||
7c673cae FG |
42 | #include <from_wkt.hpp> |
43 | #include <string_from_type.hpp> | |
44 | ||
45 | #include "distance_brute_force.hpp" | |
46 | ||
47 | namespace bg = ::boost::geometry; | |
48 | ||
49 | static const double earth_radius_km = 6371.0; | |
50 | static const double earth_radius_miles = 3959.0; | |
51 | ||
52 | ||
53 | //======================================================================== | |
54 | ||
55 | ||
56 | template <typename T> | |
57 | struct check_equal | |
58 | { | |
59 | template <typename Value, typename = void> | |
60 | struct equal_to | |
61 | { | |
62 | static inline void apply(Value const& x, Value const& y) | |
63 | { | |
64 | BOOST_CHECK(x == y); | |
65 | } | |
66 | }; | |
67 | ||
68 | template <typename Dummy> | |
69 | struct equal_to<double, Dummy> | |
70 | { | |
71 | static inline void apply(double x, double y) | |
72 | { | |
73 | BOOST_CHECK_CLOSE(x, y, 0.001); | |
74 | } | |
75 | }; | |
76 | ||
77 | template <typename Geometry1, typename Geometry2> | |
78 | static inline void apply(std::string const& /*case_id*/, | |
79 | std::string const& /*subcase_id*/, | |
80 | Geometry1 const& /*geometry1*/, | |
81 | Geometry2 const& /*geometry2*/, | |
82 | T const& detected, | |
83 | T const& expected) | |
84 | { | |
85 | equal_to<T>::apply(expected, detected); | |
86 | /* | |
87 | TODO: | |
88 | Ideally we would want the following, but it does not work well | |
89 | approximate equality test. | |
90 | ||
91 | BOOST_CHECK_MESSAGE(equal_to<T>::apply(expected, detected), | |
92 | "case ID: " << case_id << "-" << subcase_id << "; " | |
93 | << "G1: " << bg::wkt(geometry1) | |
94 | << " - " | |
95 | << "G2: " << bg::wkt(geometry2) | |
96 | << " -> Detected: " << detected | |
97 | << "; Expected: " << expected); | |
98 | */ | |
99 | } | |
100 | }; | |
101 | ||
102 | //======================================================================== | |
103 | ||
104 | template | |
105 | < | |
106 | typename Geometry1, typename Geometry2, | |
107 | int id1 = bg::geometry_id<Geometry1>::value, | |
108 | int id2 = bg::geometry_id<Geometry2>::value | |
109 | > | |
110 | struct test_distance_of_geometries | |
111 | : public test_distance_of_geometries<Geometry1, Geometry2, 0, 0> | |
112 | {}; | |
113 | ||
114 | ||
115 | template <typename Geometry1, typename Geometry2> | |
116 | struct test_distance_of_geometries<Geometry1, Geometry2, 0, 0> | |
117 | { | |
118 | template | |
119 | < | |
120 | typename DistanceType, | |
121 | typename ComparableDistanceType, | |
122 | typename Strategy | |
123 | > | |
124 | static inline | |
125 | void apply(std::string const& case_id, | |
126 | std::string const& wkt1, | |
127 | std::string const& wkt2, | |
128 | DistanceType const& expected_distance, | |
129 | ComparableDistanceType const& expected_comparable_distance, | |
130 | Strategy const& strategy, | |
131 | bool test_reversed = true) | |
132 | { | |
133 | Geometry1 geometry1 = from_wkt<Geometry1>(wkt1); | |
134 | Geometry2 geometry2 = from_wkt<Geometry2>(wkt2); | |
135 | ||
136 | apply(case_id, geometry1, geometry2, | |
137 | expected_distance, expected_comparable_distance, | |
138 | strategy, test_reversed); | |
139 | } | |
140 | ||
141 | template <typename DistanceType, typename Strategy> | |
142 | static inline | |
143 | void apply(std::string const& case_id, | |
144 | std::string const& wkt1, | |
145 | std::string const& wkt2, | |
146 | DistanceType const& expected_distance, | |
147 | Strategy const& strategy, | |
148 | bool test_reversed = true) | |
149 | { | |
150 | Geometry1 geometry1 = from_wkt<Geometry1>(wkt1); | |
151 | Geometry2 geometry2 = from_wkt<Geometry2>(wkt2); | |
152 | ||
153 | apply(case_id, geometry1, geometry2, | |
154 | expected_distance, expected_distance, | |
155 | strategy, test_reversed); | |
156 | } | |
157 | ||
158 | ||
159 | template | |
160 | < | |
161 | typename DistanceType, | |
162 | typename ComparableDistanceType, | |
163 | typename Strategy | |
164 | > | |
165 | static inline | |
166 | void apply(std::string const& case_id, | |
167 | Geometry1 const& geometry1, | |
168 | Geometry2 const& geometry2, | |
169 | DistanceType const& expected_distance, | |
170 | ComparableDistanceType const& expected_comparable_distance, | |
171 | Strategy const& strategy, | |
172 | bool test_reversed = true) | |
173 | { | |
174 | #ifdef BOOST_GEOMETRY_TEST_DEBUG | |
175 | std::cout << "case ID: " << case_id << "; " | |
176 | << "G1: " << bg::wkt(geometry1) | |
177 | << " - " | |
178 | << "G2: " << bg::wkt(geometry2) | |
179 | << std::endl; | |
180 | #endif | |
181 | namespace services = bg::strategy::distance::services; | |
182 | ||
183 | using bg::unit_test::distance_brute_force; | |
184 | ||
185 | typedef typename bg::default_distance_result | |
186 | < | |
187 | Geometry1, Geometry2 | |
188 | >::type default_distance_result; | |
189 | ||
190 | typedef typename services::return_type | |
191 | < | |
192 | Strategy, Geometry1, Geometry2 | |
193 | >::type distance_result_from_strategy; | |
194 | ||
195 | static const bool same_regular = boost::is_same | |
196 | < | |
197 | default_distance_result, | |
198 | distance_result_from_strategy | |
199 | >::type::value; | |
200 | ||
201 | BOOST_CHECK(same_regular); | |
202 | ||
203 | typedef typename bg::default_comparable_distance_result | |
204 | < | |
205 | Geometry1, Geometry2 | |
206 | >::type default_comparable_distance_result; | |
207 | ||
208 | typedef typename services::return_type | |
209 | < | |
210 | typename services::comparable_type<Strategy>::type, | |
211 | Geometry1, | |
212 | Geometry2 | |
213 | >::type comparable_distance_result_from_strategy; | |
214 | ||
215 | static const bool same_comparable = boost::is_same | |
216 | < | |
217 | default_comparable_distance_result, | |
218 | comparable_distance_result_from_strategy | |
219 | >::type::value; | |
220 | ||
221 | BOOST_CHECK( same_comparable ); | |
222 | ||
223 | // check distance with passed strategy | |
224 | distance_result_from_strategy dist = | |
225 | bg::distance(geometry1, geometry2, strategy); | |
226 | ||
227 | check_equal | |
228 | < | |
229 | distance_result_from_strategy | |
230 | >::apply(case_id, "a", geometry1, geometry2, | |
231 | dist, expected_distance); | |
232 | ||
233 | // check against the comparable distance computed in a | |
234 | // brute-force manner | |
235 | default_distance_result dist_brute_force | |
236 | = distance_brute_force(geometry1, geometry2, strategy); | |
237 | ||
238 | check_equal | |
239 | < | |
240 | default_distance_result | |
241 | >::apply(case_id, "b", geometry1, geometry2, | |
242 | dist_brute_force, expected_distance); | |
243 | ||
244 | // check comparable distance with passed strategy | |
245 | comparable_distance_result_from_strategy cdist = | |
246 | bg::comparable_distance(geometry1, geometry2, strategy); | |
247 | ||
248 | check_equal | |
249 | < | |
250 | default_comparable_distance_result | |
251 | >::apply(case_id, "c", geometry1, geometry2, | |
252 | cdist, expected_comparable_distance); | |
253 | ||
254 | // check against the comparable distance computed in a | |
255 | // brute-force manner | |
256 | default_comparable_distance_result cdist_brute_force | |
257 | = distance_brute_force(geometry1, | |
258 | geometry2, | |
259 | services::get_comparable | |
260 | < | |
261 | Strategy | |
262 | >::apply(strategy)); | |
263 | ||
264 | check_equal | |
265 | < | |
266 | default_comparable_distance_result | |
267 | >::apply(case_id, "d", geometry1, geometry2, | |
268 | cdist_brute_force, expected_comparable_distance); | |
269 | ||
270 | #ifdef BOOST_GEOMETRY_TEST_DEBUG | |
271 | std::cout << string_from_type<typename bg::coordinate_type<Geometry1>::type>::name() | |
272 | << string_from_type<typename bg::coordinate_type<Geometry2>::type>::name() | |
273 | << " -> " | |
274 | << string_from_type<default_distance_result>::name() | |
275 | << string_from_type<default_comparable_distance_result>::name() | |
276 | << std::endl; | |
277 | std::cout << "strategy radius: " << strategy.radius() << std::endl; | |
278 | std::cout << "expected distance = " | |
279 | << expected_distance << " ; " | |
280 | << "expected comp. distance = " | |
281 | << expected_comparable_distance | |
282 | << std::endl; | |
283 | std::cout << "distance = " | |
284 | << dist << " ; " | |
285 | << "comp. distance = " | |
286 | << cdist | |
287 | << std::endl; | |
288 | ||
289 | if ( !test_reversed ) | |
290 | { | |
291 | std::cout << std::endl; | |
292 | } | |
293 | #endif | |
294 | ||
295 | if ( test_reversed ) | |
296 | { | |
297 | // check distance with given strategy | |
298 | dist = bg::distance(geometry2, geometry1, strategy); | |
299 | ||
300 | check_equal | |
301 | < | |
302 | default_distance_result | |
303 | >::apply(case_id, "ra", geometry2, geometry1, | |
304 | dist, expected_distance); | |
305 | ||
306 | // check comparable distance with given strategy | |
307 | cdist = bg::comparable_distance(geometry2, geometry1, strategy); | |
308 | ||
309 | check_equal | |
310 | < | |
311 | default_comparable_distance_result | |
312 | >::apply(case_id, "rc", geometry2, geometry1, | |
313 | cdist, expected_comparable_distance); | |
314 | ||
315 | #ifdef BOOST_GEOMETRY_TEST_DEBUG | |
316 | std::cout << "distance[reversed args] = " | |
317 | << dist << " ; " | |
318 | << "comp. distance[reversed args] = " | |
319 | << cdist | |
320 | << std::endl; | |
321 | std::cout << std::endl; | |
322 | #endif | |
323 | } | |
324 | } | |
325 | }; | |
326 | ||
327 | ||
328 | //======================================================================== | |
329 | ||
330 | ||
331 | template <typename Geometry1, typename Geometry2, typename Strategy> | |
332 | void test_empty_input(Geometry1 const& geometry1, | |
333 | Geometry2 const& geometry2, | |
334 | Strategy const& strategy) | |
335 | { | |
336 | try | |
337 | { | |
338 | bg::distance(geometry1, geometry2); | |
339 | } | |
340 | catch(bg::empty_input_exception const& ) | |
341 | { | |
342 | return; | |
343 | } | |
344 | BOOST_CHECK_MESSAGE(false, | |
345 | "A empty_input_exception should have been thrown"); | |
346 | ||
347 | try | |
348 | { | |
349 | bg::distance(geometry2, geometry1); | |
350 | } | |
351 | catch(bg::empty_input_exception const& ) | |
352 | { | |
353 | return; | |
354 | } | |
355 | BOOST_CHECK_MESSAGE(false, | |
356 | "A empty_input_exception should have been thrown"); | |
357 | ||
358 | try | |
359 | { | |
360 | bg::distance(geometry1, geometry2, strategy); | |
361 | } | |
362 | catch(bg::empty_input_exception const& ) | |
363 | { | |
364 | return; | |
365 | } | |
366 | BOOST_CHECK_MESSAGE(false, | |
367 | "A empty_input_exception should have been thrown"); | |
368 | ||
369 | try | |
370 | { | |
371 | bg::distance(geometry2, geometry1, strategy); | |
372 | } | |
373 | catch(bg::empty_input_exception const& ) | |
374 | { | |
375 | return; | |
376 | } | |
377 | BOOST_CHECK_MESSAGE(false, | |
378 | "A empty_input_exception should have been thrown"); | |
379 | } | |
380 | ||
381 | #endif // BOOST_GEOMETRY_TEST_DISTANCE_SE_COMMON_HPP |