]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/test/algorithms/distance/distance_se_point_box.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / geometry / test / algorithms / distance / distance_se_point_box.cpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3
4 // Copyright (c) 2015, Oracle and/or its affiliates.
5
6 // Contributed and/or modified by Menelaos Karavelas, 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_point_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_point_box<> point_box_strategy;
37 typedef distance::cross_track_point_box
38 <
39 void, distance::comparable::cross_track<>
40 > comparable_point_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 template <typename Strategy>
176 void test_distance_point_box(Strategy const& strategy)
177 {
178 #ifdef BOOST_GEOMETRY_TEST_DEBUG
179 std::cout << std::endl;
180 std::cout << "point/box distance tests" << std::endl;
181 #endif
182 typedef test_distances<point_type, box_type> tester;
183
184 double const radius = strategy.radius();
185 double const d2r = bg::math::d2r<double>();
186
187 // Cases for relative location of a point wrt to a box
188 //
189 // | |
190 // | 3 |
191 // | |
192 // +---------+
193 // | |
194 // 1 | 5 | 2
195 // | |
196 // +---------+
197 // | |
198 // | 4 |
199 // | |
200 //
201 // and also the following cases
202 //
203 // | |
204 // A B
205 // | |
206 // +----C----+
207 // | |
208 // D E
209 // | |
210 // +----F----+
211 // | |
212 // G H
213 // | |
214 //
215 // and finally we have the corners
216 //
217 // | |
218 // | |
219 // | |
220 // a---------b
221 // | |
222 // | |
223 // | |
224 // c---------d
225 // | |
226 // | |
227 // | |
228 //
229 // for each relative position we also have to test the shifted point
230 // (this is due to the fact that boxes have longitudes in the
231 // range [-180, 540)
232
233 std::string const box1 = "BOX(10 10,20 20)";
234
235 // case 1
236 tester::apply("pb1-1a", "POINT(5 25)", box1,
237 "POINT(5 25)", "POINT(10 20)", pp,
238 strategy);
239
240 // case 1
241 tester::apply("pb1-1b", "POINT(3 12)", box1,
242 "POINT(3 12)", "SEGMENT(10 10,10 20)", ps,
243 strategy);
244
245 // case 1
246 tester::apply("pb1-1c", "POINT(3 17)", box1,
247 "POINT(3 17)", "SEGMENT(10 10,10 20)", ps,
248 strategy);
249
250 // case 1
251 tester::apply("pb1-1d", "POINT(5 4)", box1,
252 "POINT(5 4)", "POINT(10 10)", pp,
253 strategy);
254
255 // case 1
256 tester::apply("pb1-1e", "POINT(-100 20)", box1,
257 "POINT(-100 20)", "POINT(10 20)", pp,
258 strategy);
259
260 // case 1
261 tester::apply("pb1-1g", "POINT(-100 10)", box1,
262 "POINT(-100 10)", "SEGMENT(10 10,10 20)", ps,
263 strategy);
264
265 // case 2
266 tester::apply("pb1-2a", "POINT(31 25)", box1,
267 "POINT(31 25)", "POINT(20 20)", pp,
268 strategy);
269
270 // case 2
271 tester::apply("pb1-2b", "POINT(23 17)", box1,
272 "POINT(23 17)", "SEGMENT(20 10,20 20)", ps,
273 strategy);
274
275 // case 2
276 tester::apply("pb1-2c", "POINT(29 3)", box1,
277 "POINT(29 3)", "POINT(20 10)", pp,
278 strategy);
279
280 // case 2
281 tester::apply("pb1-2d", "POINT(131 65)", box1,
282 "POINT(131 65)", "POINT(20 20)", pp,
283 strategy);
284
285 // case 2
286 tester::apply("pb1-2e", "POINT(110 10)", box1,
287 "POINT(110 10)", "SEGMENT(20 10,20 20)", ps,
288 strategy);
289
290 // case 2
291 tester::apply("pb1-2f", "POINT(150 20)", box1,
292 "POINT(150 20)", "POINT(20 20)", pp,
293 strategy);
294
295 // case 3
296 tester::apply("pb1-3a", "POINT(11 25)", box1,
297 5.0 * d2r * radius,
298 to_comparable(5.0 * d2r * radius, radius),
299 strategy);
300
301 // case 3
302 tester::apply("pb1-3b", "POINT(15 25)", box1,
303 5.0 * d2r * radius,
304 to_comparable(5.0 * d2r * radius, radius),
305 strategy);
306
307 // case 3
308 tester::apply("pb1-3c", "POINT(18 25)", box1,
309 5.0 * d2r * radius,
310 to_comparable(5.0 * d2r * radius, radius),
311 strategy);
312
313 // case 4
314 tester::apply("pb1-4a", "POINT(13 4)", box1,
315 6.0 * radius * d2r,
316 to_comparable(6.0 * radius * d2r, radius),
317 strategy);
318
319 // case 4
320 tester::apply("pb1-4b", "POINT(19 4)", box1,
321 6.0 * radius * d2r,
322 to_comparable(6.0 * radius * d2r, radius),
323 strategy);
324
325 // case 5
326 tester::apply("pb1-5", "POINT(15 14)", box1, 0, 0, strategy);
327
328 // case A
329 tester::apply("pb1-A", "POINT(10 28)", box1,
330 8.0 * d2r * radius,
331 to_comparable(8.0 * d2r * radius, radius),
332 strategy);
333
334 // case B
335 tester::apply("pb1-B", "POINT(20 28)", box1,
336 8.0 * d2r * radius,
337 to_comparable(8.0 * d2r * radius, radius),
338 strategy);
339
340 // case C
341 tester::apply("pb1-C", "POINT(14 20)", box1, 0, 0, strategy);
342
343 // case D
344 tester::apply("pb1-D", "POINT(10 17)", box1, 0, 0, strategy);
345
346 // case E
347 tester::apply("pb1-E", "POINT(20 11)", box1, 0, 0, strategy);
348
349 // case F
350 tester::apply("pb1-F", "POINT(19 10)", box1, 0, 0, strategy);
351
352 // case G
353 tester::apply("pb1-G", "POINT(10 -40)", box1,
354 50.0 * d2r * radius,
355 to_comparable(50.0 * d2r * radius, radius),
356 strategy);
357
358 // case H
359 tester::apply("pb1-H",
360 "POINT(20 -50)", box1,
361 60.0 * d2r * radius,
362 to_comparable(60.0 * d2r * radius, radius),
363 strategy);
364
365 // case a
366 tester::apply("pb1-a", "POINT(10 20)", box1, 0, 0, strategy);
367 // case b
368 tester::apply("pb1-b", "POINT(20 20)", box1, 0, 0, strategy);
369 // case c
370 tester::apply("pb1-c", "POINT(10 10)", box1, 0, 0, strategy);
371 // case d
372 tester::apply("pb1-d", "POINT(20 10)", box1, 0, 0, strategy);
373
374
375
376 std::string const box2 = "BOX(170 -60,400 80)";
377
378 // case 1 - point is closer to western meridian
379 tester::apply("pb2-1a", "POINT(160 0)", box2,
380 "POINT(160 0)", "SEGMENT(170 -60,170 80)", ps,
381 strategy);
382
383 // case 1 - point is closer to eastern meridian
384 tester::apply("pb2-1b", "POINT(50 0)", box2,
385 "POINT(50 0)", "SEGMENT(40 -60,40 80)", ps,
386 strategy);
387
388 // case 3 - equivalent point POINT(390 85) is above the box
389 tester::apply("pb2-3", "POINT(30 85)", box2,
390 5.0 * d2r * radius,
391 to_comparable(5.0 * d2r * radius, radius),
392 strategy);
393
394 // case 4 - equivalent point POINT(390 -75) is below the box
395 tester::apply("pb2-4", "POINT(30 -75)", box2,
396 15.0 * d2r * radius,
397 to_comparable(15.0 * d2r * radius, radius),
398 strategy);
399
400 // case 5 - equivalent point POINT(390 0) is inside box
401 tester::apply("pb2-5", "POINT(30 0)", box2, 0, 0, strategy);
402
403
404 std::string const box3 = "BOX(-150 -50,-40 70)";
405
406 // case 1 - point is closer to western meridian
407 tester::apply("pb3-1a", "POINT(-170 10)", box3,
408 "POINT(-170 10)", "SEGMENT(-150 -50,-150 70)", ps,
409 strategy);
410
411 // case 2 - point is closer to eastern meridian
412 tester::apply("pb3-2a", "POINT(5 10)", box3,
413 "POINT(5 10)", "SEGMENT(-40 -50,-40 70)", ps,
414 strategy);
415
416 // case 2 - point is closer to western meridian
417 tester::apply("pb3-2a", "POINT(160 10)", box3,
418 "POINT(160 10)", "SEGMENT(-150 -50,-150 70)", ps,
419 strategy);
420
421 // case 2 - point is at equal distance from eastern and western meridian
422 tester::apply("pb3-2c1", "POINT(85 20)", box3,
423 "POINT(85 20)", "SEGMENT(-150 -50,-150 70)", ps,
424 strategy);
425
426 // case 2 - point is at equal distance from eastern and western meridian
427 tester::apply("pb3-2c2", "POINT(85 20)", box3,
428 "POINT(85 20)", "SEGMENT(-40 -50,-40 70)", ps,
429 strategy);
430
431 // box that is symmetric wrt the prime meridian
432 std::string const box4 = "BOX(-75 -45,75 65)";
433
434 // case 1 - point is closer to western meridian
435 tester::apply("pb4-1a", "POINT(-100 10)", box4,
436 "POINT(-100 10)", "SEGMENT(-75 -45,-75 65)", ps,
437 strategy);
438
439 // case 2 - point is closer to eastern meridian
440 tester::apply("pb4-2a", "POINT(90 15)", box4,
441 "POINT(90 15)", "SEGMENT(75 -45,75 65)", ps,
442 strategy);
443
444 // case 2 - point is at equal distance from eastern and western meridian
445 tester::apply("pb4-2c1", "POINT(-180 20)", box4,
446 "POINT(-180 20)", "SEGMENT(-75 -45,-75 65)", ps,
447 strategy);
448
449 // case 2 - point is at equal distance from eastern and western meridian
450 tester::apply("pb4-2c2", "POINT(-180 20)", box4,
451 "POINT(-180 20)", "SEGMENT(75 -45,75 65)", ps,
452 strategy);
453 }
454
455 BOOST_AUTO_TEST_CASE( test_point_box )
456 {
457 test_distance_point_box(point_box_strategy());
458 test_distance_point_box(point_box_strategy(earth_radius_km));
459 test_distance_point_box(point_box_strategy(earth_radius_miles));
460
461 test_distance_point_box(comparable_point_box_strategy());
462 test_distance_point_box(comparable_point_box_strategy(earth_radius_km));
463 test_distance_point_box(comparable_point_box_strategy(earth_radius_miles));
464 }