]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | // Unit Test | |
3 | ||
4 | // Copyright (c) 2016, Oracle and/or its affiliates. | |
5 | ||
6 | // Contributed and/or modified by Vissarion Fysikopoulos, 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 | #include <iostream> | |
12 | ||
13 | #ifndef BOOST_TEST_MODULE | |
14 | #define BOOST_TEST_MODULE test_distance_spherical_equatorial_box_box | |
15 | #endif | |
16 | ||
17 | #include <boost/range.hpp> | |
18 | #include <boost/type_traits/is_same.hpp> | |
19 | ||
20 | #include <boost/test/included/unit_test.hpp> | |
21 | #include <boost/geometry/util/condition.hpp> | |
22 | #include <boost/geometry/strategies/strategies.hpp> | |
23 | ||
24 | #include "test_distance_se_common.hpp" | |
25 | ||
26 | ||
27 | typedef bg::cs::spherical_equatorial<bg::degree> cs_type; | |
28 | typedef bg::model::point<double, 2, cs_type> point_type; | |
29 | typedef bg::model::segment<point_type> segment_type; | |
30 | typedef bg::model::box<point_type> box_type; | |
31 | ||
32 | namespace distance = bg::strategy::distance; | |
33 | namespace services = distance::services; | |
34 | typedef bg::default_distance_result<point_type, point_type>::type return_type; | |
35 | ||
36 | typedef distance::cross_track_box_box<> box_box_strategy; | |
37 | typedef distance::cross_track_box_box | |
38 | < | |
39 | void, distance::comparable::cross_track<> | |
40 | > comparable_box_box_strategy; | |
41 | ||
42 | //=========================================================================== | |
43 | ||
44 | inline bg::distance_result | |
45 | < | |
46 | point_type, point_type, distance::haversine<double> | |
47 | >::type | |
48 | distance_pp(std::string const& wkt1, | |
49 | std::string const& wkt2, | |
50 | double radius) | |
51 | { | |
52 | point_type p1, p2; | |
53 | bg::read_wkt(wkt1, p1); | |
54 | bg::read_wkt(wkt2, p2); | |
55 | ||
56 | distance::haversine<double> strategy(radius); | |
57 | return bg::distance(p1, p2, strategy); | |
58 | } | |
59 | ||
60 | inline bg::default_comparable_distance_result<point_type>::type | |
61 | comparable_distance_pp(std::string const& wkt1, | |
62 | std::string const& wkt2) | |
63 | { | |
64 | point_type p1, p2; | |
65 | bg::read_wkt(wkt1, p1); | |
66 | bg::read_wkt(wkt2, p2); | |
67 | return bg::comparable_distance(p1, p2); | |
68 | } | |
69 | ||
70 | inline bg::distance_result | |
71 | < | |
72 | point_type, point_type, distance::cross_track<> | |
73 | >::type | |
74 | distance_ps(std::string const& wkt_point, | |
75 | std::string const& wkt_segment, | |
76 | double radius) | |
77 | { | |
78 | point_type point; | |
79 | segment_type segment; | |
80 | bg::read_wkt(wkt_point, point); | |
81 | bg::read_wkt(wkt_segment, segment); | |
82 | ||
83 | distance::cross_track<> strategy(radius); | |
84 | return bg::distance(point, segment, strategy); | |
85 | } | |
86 | ||
87 | inline bg::default_comparable_distance_result<point_type>::type | |
88 | comparable_distance_ps(std::string const& wkt_point, | |
89 | std::string const& wkt_segment) | |
90 | { | |
91 | point_type point; | |
92 | segment_type segment; | |
93 | bg::read_wkt(wkt_point, point); | |
94 | bg::read_wkt(wkt_segment, segment); | |
95 | return bg::comparable_distance(point, segment); | |
96 | } | |
97 | ||
98 | enum features_type { pp, ps }; | |
99 | ||
100 | template <typename Geometry1, typename Geometry2> | |
101 | struct test_distances | |
102 | { | |
103 | template <typename Strategy> | |
104 | static inline void apply(std::string const& case_id, | |
105 | std::string const& wkt1, | |
106 | std::string const& wkt2, | |
107 | double expected_distance, | |
108 | double expected_comparable_distance, | |
109 | Strategy const& strategy) | |
110 | { | |
111 | typedef test_distance_of_geometries<Geometry1, Geometry2> tester; | |
112 | ||
113 | bool const is_comparable = boost::is_same | |
114 | < | |
115 | Strategy, | |
116 | typename services::comparable_type<Strategy>::type | |
117 | >::value; | |
118 | ||
119 | if (BOOST_GEOMETRY_CONDITION(is_comparable)) | |
120 | { | |
121 | tester::apply(case_id, wkt1, wkt2, | |
122 | expected_comparable_distance, | |
123 | expected_comparable_distance, | |
124 | strategy); | |
125 | } | |
126 | else | |
127 | { | |
128 | tester::apply(case_id, wkt1, wkt2, | |
129 | expected_distance, | |
130 | expected_comparable_distance, | |
131 | strategy); | |
132 | } | |
133 | } | |
134 | ||
135 | template <typename Strategy> | |
136 | static inline void apply(std::string const& case_id, | |
137 | std::string const& wkt1, | |
138 | std::string const& wkt2, | |
139 | std::string const& feature1, | |
140 | std::string const& feature2, | |
141 | features_type ftype, | |
142 | Strategy const& strategy) | |
143 | { | |
144 | double const radius = strategy.radius(); | |
145 | double expected_distance, expected_comparable_distance; | |
146 | ||
147 | if (ftype == pp) | |
148 | { | |
149 | expected_distance = distance_pp(feature1, feature2, radius); | |
150 | expected_comparable_distance | |
151 | = comparable_distance_pp(feature1, feature2); | |
152 | } | |
153 | else | |
154 | { | |
155 | expected_distance = distance_ps(feature1, feature2, radius); | |
156 | expected_comparable_distance | |
157 | = comparable_distance_ps(feature1, feature2); | |
158 | } | |
159 | ||
160 | apply(case_id, wkt1, wkt2, | |
161 | expected_distance, expected_comparable_distance, | |
162 | strategy); | |
163 | } | |
164 | }; | |
165 | ||
166 | template <typename T, typename U> | |
167 | T to_comparable(T const& value, U const& radius) | |
168 | { | |
169 | T x = sin(value / (radius * 2.0)); | |
170 | return x * x; | |
171 | } | |
172 | ||
173 | ||
174 | //=========================================================================== | |
175 | ||
176 | ||
177 | // Cases for relative location of box2 wrt to box1 | |
178 | // | |
179 | // | | | |
180 | // 11 | 7 | 4 | |
181 | // | | | |
182 | // --10---+---------+---3--- | |
183 | // | | | |
184 | // 9 | 6 | 2 | |
185 | // | | | |
186 | // -------+---------+------- | |
187 | // | | | |
188 | // 8 | 5 | 1 | |
189 | // | | | |
190 | // | |
191 | // case 6 includes all possible intersections | |
192 | // The picture assumes northern hemisphere location | |
193 | // southern hemisphere picture is mirrored wrt the equator | |
194 | ||
195 | template <typename Strategy> | |
196 | void test_distance_box_box(Strategy const& strategy) | |
197 | { | |
198 | typedef test_distances<box_type, box_type> tester; | |
199 | ||
200 | std::string const box1 = "BOX(10 10,20 20)"; | |
201 | ||
202 | // case 1 | |
203 | tester::apply("bb1", box1, "BOX(30 0,40 5)", | |
204 | "POINT(20 10)", "POINT(30 5)", pp, | |
205 | strategy); | |
206 | ||
207 | // case 2 | |
208 | tester::apply("bb2-a", box1, "BOX(30 12, 40 17)", | |
209 | "POINT(30 17)", "SEGMENT(20 10,20 20)", ps, | |
210 | strategy); | |
211 | ||
212 | tester::apply("bb2-b", box1, "BOX(30 10, 40 17)", | |
213 | "POINT(30 17)", "SEGMENT(20 10,20 20)", ps, | |
214 | strategy); | |
215 | ||
216 | tester::apply("bb2-c", box1, "BOX(30 8, 40 17)", | |
217 | "POINT(30 17)", "SEGMENT(20 10,20 20)", ps, | |
218 | strategy); | |
219 | ||
220 | ||
221 | // case 3 | |
222 | tester::apply("bb3-a", box1, "BOX(30 15, 40 25)", | |
223 | "POINT(20 20)", "SEGMENT(30 15,30 25)", ps, | |
224 | strategy); | |
225 | ||
226 | tester::apply("bb3-b", box1, "BOX(30 20, 40 40)", | |
227 | "POINT(20 20)", "SEGMENT(30 20,30 40)", ps, | |
228 | strategy); | |
229 | ||
230 | // case 4 | |
231 | tester::apply("bb4", box1, "BOX(30 25, 40 40)", | |
232 | "POINT(20 20)", "POINT(30 25)", pp, | |
233 | strategy); | |
234 | ||
235 | // case 5 | |
236 | tester::apply("bb5", box1, "BOX(12 2, 17 7)", | |
237 | "POINT(17 7)", "POINT(17 10)", pp, | |
238 | strategy); | |
239 | ||
240 | // case 6, boxes intersect thus distance is 0 | |
241 | tester::apply("bb6-a", box1, "BOX(12 2, 17 10)", | |
242 | "POINT(0 0)", "POINT(0 0)", pp, | |
243 | strategy); | |
244 | ||
245 | tester::apply("bb6-b", box1, "BOX(12 2, 17 17)", | |
246 | "POINT(0 0)", "POINT(0 0)", pp, | |
247 | strategy); | |
248 | ||
249 | tester::apply("bb6-c", box1, "BOX(20 2, 30 10)", | |
250 | "POINT(0 0)", "POINT(0 0)", pp, | |
251 | strategy); | |
252 | ||
253 | tester::apply("bb6-d", box1, "BOX(20 11, 30 15)", | |
254 | "POINT(0 0)", "POINT(0 0)", pp, | |
255 | strategy); | |
256 | ||
257 | tester::apply("bb6-e", box1, "BOX(20 20, 30 30)", | |
258 | "POINT(0 0)", "POINT(0 0)", pp, | |
259 | strategy); | |
260 | ||
261 | tester::apply("bb6-f", box1, "BOX(15 20, 17 30)", | |
262 | "POINT(0 0)", "POINT(0 0)", pp, | |
263 | strategy); | |
264 | ||
265 | tester::apply("bb6-g", box1, "BOX(8 20, 10 25)", | |
266 | "POINT(0 0)", "POINT(0 0)", pp, | |
267 | strategy); | |
268 | ||
269 | tester::apply("bb6-h", box1, "BOX(8 15 , 10 17)", | |
270 | "POINT(0 0)", "POINT(0 0)", pp, | |
271 | strategy); | |
272 | ||
273 | tester::apply("bb6-i", box1, "BOX(8 8, 10 10)", | |
274 | "POINT(0 0)", "POINT(0 0)", pp, | |
275 | strategy); | |
276 | ||
277 | tester::apply("bb6-j", box1, "BOX(15 8, 17 10)", | |
278 | "POINT(0 0)", "POINT(0 0)", pp, | |
279 | strategy); | |
280 | ||
281 | // case 7 | |
282 | tester::apply("bb7", box1, "BOX(12 22, 17 27)", | |
283 | "POINT(17 20)", "POINT(17 22)", pp, | |
284 | strategy); | |
285 | ||
286 | // case 8 | |
287 | tester::apply("bb8", box1, "BOX(4 4, 8 8)", | |
288 | "POINT(8 8)", "POINT(10 10)", pp, | |
289 | strategy); | |
290 | ||
291 | // case 9 | |
292 | tester::apply("bb9-a", box1, "BOX(4 14, 8 18)", | |
293 | "POINT(8 18)", "SEGMENT(10 10, 10 20)", ps, | |
294 | strategy); | |
295 | ||
296 | tester::apply("bb9-b", box1, "BOX(4 10, 8 18)", | |
297 | "POINT(8 18)", "SEGMENT(10 10, 10 20)", ps, | |
298 | strategy); | |
299 | ||
300 | tester::apply("bb9-c", box1, "BOX(4 8, 8 18)", | |
301 | "POINT(8 18)", "SEGMENT(10 10, 10 20)", ps, | |
302 | strategy); | |
303 | ||
304 | // case 10 | |
305 | tester::apply("bb10", box1, "BOX(4 18, 8 22)", | |
306 | "POINT(10 20)", "SEGMENT(8 18, 8 22)", ps, | |
307 | strategy); | |
308 | ||
309 | tester::apply("bb10", box1, "BOX(4 20, 8 22)", | |
310 | "POINT(10 20)", "SEGMENT(8 20, 8 22)", ps, | |
311 | strategy); | |
312 | ||
313 | // case 11 | |
314 | tester::apply("bb11", box1, "BOX(4 22, 8 24)", | |
315 | "POINT(8 22)", "POINT(10 20)", pp, | |
316 | strategy); | |
317 | ||
318 | // far away boxes | |
319 | tester::apply("bb-far", "BOX(150 15, 170 25)", box1, | |
320 | "POINT(20 20)", "SEGMENT(150 15, 150 25)", ps, | |
321 | strategy); | |
322 | ||
323 | // crosses antimeridian | |
324 | tester::apply("bb-anti1", "BOX(170 15, -160 25)", box1, | |
325 | "POINT(20 20)", "SEGMENT(170 15, 170 25)", ps, | |
326 | strategy); | |
327 | ||
328 | tester::apply("bb-anti2", "BOX(170 15, -160 25)", "BOX(160 10, -170 20)", | |
329 | "POINT(20 20)", "POINT(20 20)", pp, | |
330 | strategy); | |
331 | ||
332 | tester::apply("bb-anti3", "BOX(170 15, -160 25)", "BOX(160 10, 170 20)", | |
333 | "POINT(20 20)", "POINT(20 20)", pp, | |
334 | strategy); | |
335 | ||
336 | tester::apply("bb-anti4", "BOX(170 10, -160 20)", "BOX(160 30, -170 40)", | |
337 | "POINT(180 20)", "POINT(180 30)", pp, | |
338 | strategy); | |
339 | ||
340 | // South hemisphere | |
341 | ||
342 | tester::apply("bb-south1", "BOX(10 -20, 20 -10)", "BOX(30 -15, 40 -12)", | |
343 | "POINT(30 -15)", "SEGMENT(20 -10, 20 -20)", ps, | |
344 | strategy); | |
345 | ||
346 | tester::apply("bb-south2", "BOX(10 -20, 20 -10)", "BOX(30 -30, 40 -25)", | |
347 | "POINT(30 -25)", "POINT(20 -20)", pp, | |
348 | strategy); | |
349 | ||
350 | tester::apply("bb-south3", "BOX(10 -20, 20 -10)", "BOX(30 -25, 40 -15)", | |
351 | "POINT(20 -20)", "SEGMENT(30 -15, 30 -25)", ps, | |
352 | strategy); | |
353 | ||
354 | tester::apply("bb-south4", "BOX(10 -20, 20 -10)", "BOX(5 -30, 30 -25)", | |
355 | "POINT(10 -25)", "POINT(10 -20)", pp, | |
356 | strategy); | |
357 | ||
358 | tester::apply("bb-south4", "BOX(10 -20, 20 -10)", "BOX(5 -7, 30 -5)", | |
359 | "POINT(10 -7)", "POINT(10 -10)", pp, | |
360 | strategy); | |
361 | ||
362 | ||
363 | // Crosses equator | |
364 | ||
365 | tester::apply("bb-eq1", "BOX(30 -15, 40 30)", "BOX(10 -20, 20 25)", | |
366 | "POINT(20 25)", "SEGMENT(30 -15, 30 30)", ps, | |
367 | strategy); | |
368 | ||
369 | tester::apply("bb-eq2", "BOX(30 -15, 40 20)", "BOX(10 -20, 20 25)", | |
370 | "POINT(30 20)", "SEGMENT(20 -20, 20 25)", ps, | |
371 | strategy); | |
372 | ||
373 | tester::apply("bb-eq3", "BOX(30 5, 40 20)", "BOX(10 -20, 20 25)", | |
374 | "POINT(30 20)", "SEGMENT(20 -20, 20 25)", ps, | |
375 | strategy); | |
376 | ||
377 | tester::apply("bb-eq4", "BOX(5 -30, 40 -25)", "BOX(10 -20, 20 25)", | |
378 | "POINT(10 -25)", "POINT(10 -20)", pp, | |
379 | strategy); | |
380 | ||
381 | tester::apply("bb-eq5", "BOX(30 5, 40 20)", "BOX(10 -20, 50 25)", | |
382 | "POINT(30 20)", "POINT(30 20)", pp, | |
383 | strategy); | |
384 | ||
385 | tester::apply("bb-eq6", "BOX(30 5, 40 20)", "BOX(10 -20, 35 25)", | |
386 | "POINT(30 20)", "POINT(30 20)", pp, | |
387 | strategy); | |
388 | ||
389 | // One box in the north and one in the south hemisphere | |
390 | ||
391 | tester::apply("bb-ns1", "BOX(30 15, 40 20)", "BOX(10 -20, 20 -15)", | |
392 | "POINT(30 15)", "POINT(20 -15)", pp, | |
393 | strategy); | |
394 | ||
395 | tester::apply("bb-ns2", "BOX(30 15, 40 20)", "BOX(25 -20, 50 -15)", | |
396 | "POINT(30 15)", "POINT(30 -15)", pp, | |
397 | strategy); | |
398 | } | |
399 | ||
400 | template <typename Strategy> | |
401 | void test_distance_box_box_negative(Strategy const& strategy) | |
402 | { | |
403 | typedef test_distances<box_type, box_type> tester; | |
404 | std::string const box1neg = "BOX(-20 10,-10 20)"; | |
405 | ||
406 | // case 1 | |
407 | tester::apply("bb1", box1neg, "BOX(-40 0,-30 5)", | |
408 | "POINT(-20 10)", "POINT(-30 5)", pp, | |
409 | strategy); | |
410 | ||
411 | // case 2 | |
412 | tester::apply("bb2-a", box1neg, "BOX(-40 12, -30 17)", | |
413 | "POINT(-30 17)", "SEGMENT(-20 10,-20 20)", ps, | |
414 | strategy); | |
415 | ||
416 | tester::apply("bb2-b", box1neg, "BOX(-40 10, -30 17)", | |
417 | "POINT(-30 17)", "SEGMENT(-20 10,-20 20)", ps, | |
418 | strategy); | |
419 | ||
420 | tester::apply("bb2-c", box1neg, "BOX(-40 8, -30 17)", | |
421 | "POINT(-30 17)", "SEGMENT(-20 10,-20 20)", ps, | |
422 | strategy); | |
423 | ||
424 | ||
425 | // case 3 | |
426 | tester::apply("bb3-a", box1neg, "BOX(-40 15, -30 25)", | |
427 | "POINT(-20 20)", "SEGMENT(-30 15,-30 25)", ps, | |
428 | strategy); | |
429 | ||
430 | tester::apply("bb3-b", box1neg, "BOX(-40 20, -30 40)", | |
431 | "POINT(-20 20)", "SEGMENT(-30 20,-30 40)", ps, | |
432 | strategy); | |
433 | ||
434 | // case 4 | |
435 | tester::apply("bb4", box1neg, "BOX(-40 25, -30 40)", | |
436 | "POINT(-20 20)", "POINT(-30 25)", pp, | |
437 | strategy); | |
438 | ||
439 | // case 5 | |
440 | tester::apply("bb5", box1neg, "BOX(-17 2,-12 7)", | |
441 | "POINT(-17 7)", "POINT(-17 10)", pp, | |
442 | strategy); | |
443 | ||
444 | // case 6, boxes intersect thus distance is 0 | |
445 | tester::apply("bb6-a", box1neg, "BOX(-17 2, -12 10)", | |
446 | "POINT(0 0)", "POINT(0 0)", pp, | |
447 | strategy); | |
448 | ||
449 | tester::apply("bb6-b", box1neg, "BOX(-17 2, -12 17)", | |
450 | "POINT(0 0)", "POINT(0 0)", pp, | |
451 | strategy); | |
452 | ||
453 | tester::apply("bb6-c", box1neg, "BOX(-30 2, -20 10)", | |
454 | "POINT(0 0)", "POINT(0 0)", pp, | |
455 | strategy); | |
456 | ||
457 | tester::apply("bb6-d", box1neg, "BOX(-30 11, -20 15)", | |
458 | "POINT(0 0)", "POINT(0 0)", pp, | |
459 | strategy); | |
460 | ||
461 | tester::apply("bb6-e", box1neg, "BOX(-30 20, -20 30)", | |
462 | "POINT(0 0)", "POINT(0 0)", pp, | |
463 | strategy); | |
464 | ||
465 | tester::apply("bb6-f", box1neg, "BOX(-17 20, -15 30)", | |
466 | "POINT(0 0)", "POINT(0 0)", pp, | |
467 | strategy); | |
468 | ||
469 | tester::apply("bb6-g", box1neg, "BOX(-10 20, -8 25)", | |
470 | "POINT(0 0)", "POINT(0 0)", pp, | |
471 | strategy); | |
472 | ||
473 | tester::apply("bb6-h", box1neg, "BOX(-10 15 , -8 17)", | |
474 | "POINT(0 0)", "POINT(0 0)", pp, | |
475 | strategy); | |
476 | ||
477 | tester::apply("bb6-i", box1neg, "BOX(-10 8, -8 10)", | |
478 | "POINT(0 0)", "POINT(0 0)", pp, | |
479 | strategy); | |
480 | ||
481 | tester::apply("bb6-j", box1neg, "BOX(-17 8, -15 10)", | |
482 | "POINT(0 0)", "POINT(0 0)", pp, | |
483 | strategy); | |
484 | ||
485 | // case 7 | |
486 | tester::apply("bb7", box1neg, "BOX(-17 22, -12 27)", | |
487 | "POINT(-17 20)", "POINT(-17 22)", pp, | |
488 | strategy); | |
489 | ||
490 | // case 8 | |
491 | tester::apply("bb8", box1neg, "BOX(-8 4, -4 8)", | |
492 | "POINT(-8 8)", "POINT(-10 10)", pp, | |
493 | strategy); | |
494 | ||
495 | // case 9 | |
496 | tester::apply("bb9-a", box1neg, "BOX(-8 14, -4 18)", | |
497 | "POINT(-8 18)", "SEGMENT(-10 10, -10 20)", ps, | |
498 | strategy); | |
499 | ||
500 | tester::apply("bb9-b", box1neg, "BOX(-8 10, -4 18)", | |
501 | "POINT(-8 18)", "SEGMENT(-10 10, -10 20)", ps, | |
502 | strategy); | |
503 | ||
504 | tester::apply("bb9-c", box1neg, "BOX(-8 8, -4 18)", | |
505 | "POINT(-8 18)", "SEGMENT(-10 10, -10 20)", ps, | |
506 | strategy); | |
507 | ||
508 | // case 10 | |
509 | tester::apply("bb10", box1neg, "BOX(-8 18, -4 22)", | |
510 | "POINT(-10 20)", "SEGMENT(-8 18, -8 22)", ps, | |
511 | strategy); | |
512 | ||
513 | tester::apply("bb10", box1neg, "BOX(-8 20, -4 22)", | |
514 | "POINT(-10 20)", "SEGMENT(-8 20, -8 22)", ps, | |
515 | strategy); | |
516 | ||
517 | // case 11 | |
518 | tester::apply("bb11", box1neg, "BOX(-8 22, -4 24)", | |
519 | "POINT(-8 22)", "POINT(-10 20)", pp, | |
520 | strategy); | |
521 | } | |
522 | ||
523 | BOOST_AUTO_TEST_CASE( test_box_box ) | |
524 | { | |
525 | test_distance_box_box(box_box_strategy()); | |
526 | test_distance_box_box_negative(box_box_strategy()); | |
527 | } |