1 // Boost.Geometry (aka GGL, Generic Geometry Library)
4 // Copyright (c) 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
13 #ifndef BOOST_TEST_MODULE
14 #define BOOST_TEST_MODULE test_distance_spherical_equatorial_point_box
17 #include <boost/range.hpp>
18 #include <boost/type_traits/is_same.hpp>
20 #include <boost/test/included/unit_test.hpp>
21 #include <boost/geometry/util/condition.hpp>
22 #include <boost/geometry/strategies/strategies.hpp>
24 #include "test_distance_se_common.hpp"
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::multi_point
<point_type
> multi_point_type
;
30 typedef bg::model::segment
<point_type
> segment_type
;
31 typedef bg::model::box
<point_type
> box_type
;
33 namespace distance
= bg::strategy::distance
;
34 namespace services
= distance::services
;
35 typedef bg::default_distance_result
<point_type
, point_type
>::type return_type
;
37 typedef distance::cross_track_point_box
<> point_box_strategy
;
38 typedef distance::cross_track_point_box
40 void, distance::comparable::cross_track
<>
41 > comparable_point_box_strategy
;
43 //===========================================================================
45 inline bg::distance_result
47 point_type
, point_type
, distance::haversine
<double>
49 distance_pp(std::string
const& wkt1
,
50 std::string
const& wkt2
,
54 bg::read_wkt(wkt1
, p1
);
55 bg::read_wkt(wkt2
, p2
);
57 distance::haversine
<double> strategy(radius
);
58 return bg::distance(p1
, p2
, strategy
);
61 inline bg::default_comparable_distance_result
<point_type
>::type
62 comparable_distance_pp(std::string
const& wkt1
,
63 std::string
const& wkt2
)
66 bg::read_wkt(wkt1
, p1
);
67 bg::read_wkt(wkt2
, p2
);
68 return bg::comparable_distance(p1
, p2
);
71 inline bg::distance_result
73 point_type
, point_type
, distance::cross_track
<>
75 distance_ps(std::string
const& wkt_point
,
76 std::string
const& wkt_segment
,
81 bg::read_wkt(wkt_point
, point
);
82 bg::read_wkt(wkt_segment
, segment
);
84 distance::cross_track
<> strategy(radius
);
85 return bg::distance(point
, segment
, strategy
);
88 inline bg::default_comparable_distance_result
<point_type
>::type
89 comparable_distance_ps(std::string
const& wkt_point
,
90 std::string
const& wkt_segment
)
94 bg::read_wkt(wkt_point
, point
);
95 bg::read_wkt(wkt_segment
, segment
);
96 return bg::comparable_distance(point
, segment
);
99 enum features_type
{ pp
, ps
};
101 template <typename Geometry1
, typename Geometry2
>
102 struct test_distances
104 template <typename Strategy
>
105 static inline void apply(std::string
const& case_id
,
106 std::string
const& wkt1
,
107 std::string
const& wkt2
,
108 double expected_distance
,
109 double expected_comparable_distance
,
110 Strategy
const& strategy
)
112 typedef test_distance_of_geometries
<Geometry1
, Geometry2
> tester
;
114 bool const is_comparable
= boost::is_same
117 typename
services::comparable_type
<Strategy
>::type
120 if (BOOST_GEOMETRY_CONDITION(is_comparable
))
122 tester::apply(case_id
, wkt1
, wkt2
,
123 expected_comparable_distance
,
124 expected_comparable_distance
,
129 tester::apply(case_id
, wkt1
, wkt2
,
131 expected_comparable_distance
,
136 template <typename Strategy
>
137 static inline void apply(std::string
const& case_id
,
138 std::string
const& wkt1
,
139 std::string
const& wkt2
,
140 std::string
const& feature1
,
141 std::string
const& feature2
,
143 Strategy
const& strategy
)
145 double const radius
= strategy
.radius();
146 double expected_distance
, expected_comparable_distance
;
150 expected_distance
= distance_pp(feature1
, feature2
, radius
);
151 expected_comparable_distance
152 = comparable_distance_pp(feature1
, feature2
);
156 expected_distance
= distance_ps(feature1
, feature2
, radius
);
157 expected_comparable_distance
158 = comparable_distance_ps(feature1
, feature2
);
161 apply(case_id
, wkt1
, wkt2
,
162 expected_distance
, expected_comparable_distance
,
167 template <typename T
, typename U
>
168 T
to_comparable(T
const& value
, U
const& radius
)
170 T x
= sin(value
/ (radius
* 2.0));
174 //===========================================================================
176 template <typename Strategy
>
177 void test_distance_point_box(Strategy
const& strategy
)
179 #ifdef BOOST_GEOMETRY_TEST_DEBUG
180 std::cout
<< std::endl
;
181 std::cout
<< "point/box distance tests" << std::endl
;
183 typedef test_distances
<point_type
, box_type
> tester
;
185 double const radius
= strategy
.radius();
186 double const d2r
= bg::math::d2r
<double>();
188 // Cases for relative location of a point wrt to a box
202 // and also the following cases
216 // and finally we have the corners
230 // for each relative position we also have to test the shifted point
231 // (this is due to the fact that boxes have longitudes in the
234 std::string
const box1
= "BOX(10 10,20 20)";
237 tester::apply("pb1-1a", "POINT(5 25)", box1
,
238 "POINT(5 25)", "POINT(10 20)", pp
,
242 tester::apply("pb1-1b", "POINT(3 12)", box1
,
243 "POINT(3 12)", "SEGMENT(10 10,10 20)", ps
,
247 tester::apply("pb1-1c", "POINT(3 17)", box1
,
248 "POINT(3 17)", "SEGMENT(10 10,10 20)", ps
,
252 tester::apply("pb1-1d", "POINT(5 4)", box1
,
253 "POINT(5 4)", "POINT(10 10)", pp
,
257 tester::apply("pb1-1e", "POINT(-100 20)", box1
,
258 "POINT(-100 20)", "POINT(10 20)", pp
,
262 tester::apply("pb1-1g", "POINT(-100 10)", box1
,
263 "POINT(-100 10)", "SEGMENT(10 10,10 20)", ps
,
267 tester::apply("pb1-2a", "POINT(31 25)", box1
,
268 "POINT(31 25)", "POINT(20 20)", pp
,
272 tester::apply("pb1-2b", "POINT(23 17)", box1
,
273 "POINT(23 17)", "SEGMENT(20 10,20 20)", ps
,
277 tester::apply("pb1-2c", "POINT(29 3)", box1
,
278 "POINT(29 3)", "POINT(20 10)", pp
,
282 tester::apply("pb1-2d", "POINT(131 65)", box1
,
283 "POINT(131 65)", "POINT(20 20)", pp
,
287 tester::apply("pb1-2e", "POINT(110 10)", box1
,
288 "POINT(110 10)", "SEGMENT(20 10,20 20)", ps
,
292 tester::apply("pb1-2f", "POINT(150 20)", box1
,
293 "POINT(150 20)", "POINT(20 20)", pp
,
297 tester::apply("pb1-3a", "POINT(11 25)", box1
,
299 to_comparable(5.0 * d2r
* radius
, radius
),
303 tester::apply("pb1-3b", "POINT(15 25)", box1
,
305 to_comparable(5.0 * d2r
* radius
, radius
),
309 tester::apply("pb1-3c", "POINT(18 25)", box1
,
311 to_comparable(5.0 * d2r
* radius
, radius
),
315 tester::apply("pb1-4a", "POINT(13 4)", box1
,
317 to_comparable(6.0 * radius
* d2r
, radius
),
321 tester::apply("pb1-4b", "POINT(19 4)", box1
,
323 to_comparable(6.0 * radius
* d2r
, radius
),
327 tester::apply("pb1-5", "POINT(15 14)", box1
, 0, 0, strategy
);
330 tester::apply("pb1-A", "POINT(10 28)", box1
,
332 to_comparable(8.0 * d2r
* radius
, radius
),
336 tester::apply("pb1-B", "POINT(20 28)", box1
,
338 to_comparable(8.0 * d2r
* radius
, radius
),
342 tester::apply("pb1-C", "POINT(14 20)", box1
, 0, 0, strategy
);
345 tester::apply("pb1-D", "POINT(10 17)", box1
, 0, 0, strategy
);
348 tester::apply("pb1-E", "POINT(20 11)", box1
, 0, 0, strategy
);
351 tester::apply("pb1-F", "POINT(19 10)", box1
, 0, 0, strategy
);
354 tester::apply("pb1-G", "POINT(10 -40)", box1
,
356 to_comparable(50.0 * d2r
* radius
, radius
),
360 tester::apply("pb1-H",
361 "POINT(20 -50)", box1
,
363 to_comparable(60.0 * d2r
* radius
, radius
),
367 tester::apply("pb1-a", "POINT(10 20)", box1
, 0, 0, strategy
);
369 tester::apply("pb1-b", "POINT(20 20)", box1
, 0, 0, strategy
);
371 tester::apply("pb1-c", "POINT(10 10)", box1
, 0, 0, strategy
);
373 tester::apply("pb1-d", "POINT(20 10)", box1
, 0, 0, strategy
);
377 std::string
const box2
= "BOX(170 -60,400 80)";
379 // case 1 - point is closer to western meridian
380 tester::apply("pb2-1a", "POINT(160 0)", box2
,
381 "POINT(160 0)", "SEGMENT(170 -60,170 80)", ps
,
384 // case 1 - point is closer to eastern meridian
385 tester::apply("pb2-1b", "POINT(50 0)", box2
,
386 "POINT(50 0)", "SEGMENT(40 -60,40 80)", ps
,
389 // case 3 - equivalent point POINT(390 85) is above the box
390 tester::apply("pb2-3", "POINT(30 85)", box2
,
392 to_comparable(5.0 * d2r
* radius
, radius
),
395 // case 4 - equivalent point POINT(390 -75) is below the box
396 tester::apply("pb2-4", "POINT(30 -75)", box2
,
398 to_comparable(15.0 * d2r
* radius
, radius
),
401 // case 5 - equivalent point POINT(390 0) is inside box
402 tester::apply("pb2-5", "POINT(30 0)", box2
, 0, 0, strategy
);
405 std::string
const box3
= "BOX(-150 -50,-40 70)";
407 // case 1 - point is closer to western meridian
408 tester::apply("pb3-1a", "POINT(-170 10)", box3
,
409 "POINT(-170 10)", "SEGMENT(-150 -50,-150 70)", ps
,
412 // case 2 - point is closer to eastern meridian
413 tester::apply("pb3-2a", "POINT(5 10)", box3
,
414 "POINT(5 10)", "SEGMENT(-40 -50,-40 70)", ps
,
417 // case 2 - point is closer to western meridian
418 tester::apply("pb3-2a", "POINT(160 10)", box3
,
419 "POINT(160 10)", "SEGMENT(-150 -50,-150 70)", ps
,
422 // case 2 - point is at equal distance from eastern and western meridian
423 tester::apply("pb3-2c1", "POINT(85 20)", box3
,
424 "POINT(85 20)", "SEGMENT(-150 -50,-150 70)", ps
,
427 // case 2 - point is at equal distance from eastern and western meridian
428 tester::apply("pb3-2c2", "POINT(85 20)", box3
,
429 "POINT(85 20)", "SEGMENT(-40 -50,-40 70)", ps
,
432 // box that is symmetric wrt the prime meridian
433 std::string
const box4
= "BOX(-75 -45,75 65)";
435 // case 1 - point is closer to western meridian
436 tester::apply("pb4-1a", "POINT(-100 10)", box4
,
437 "POINT(-100 10)", "SEGMENT(-75 -45,-75 65)", ps
,
440 // case 2 - point is closer to eastern meridian
441 tester::apply("pb4-2a", "POINT(90 15)", box4
,
442 "POINT(90 15)", "SEGMENT(75 -45,75 65)", ps
,
445 // case 2 - point is at equal distance from eastern and western meridian
446 tester::apply("pb4-2c1", "POINT(-180 20)", box4
,
447 "POINT(-180 20)", "SEGMENT(-75 -45,-75 65)", ps
,
450 // case 2 - point is at equal distance from eastern and western meridian
451 tester::apply("pb4-2c2", "POINT(-180 20)", box4
,
452 "POINT(-180 20)", "SEGMENT(75 -45,75 65)", ps
,
457 template <typename Strategy
>
458 void test_distance_multipoint_box(Strategy
const& strategy
)
461 #ifdef BOOST_GEOMETRY_TEST_DEBUG
462 std::cout
<< std::endl
;
463 std::cout
<< "multipoint/box distance tests" << std::endl
;
465 typedef test_distances
<multi_point_type
, box_type
> tester
;
467 std::string
const box1
= "BOX(10 10,20 20)";
469 tester::apply("mpb1-1a", "MULTIPOINT(5 25,25 26)", box1
,
470 "POINT(5 25)", "POINT(10 20)", pp
,
473 tester::apply("mpb1-2e", "MULTIPOINT(110 10,110 9,110 0)", box1
,
474 "POINT(110 10)", "SEGMENT(20 10,20 20)", ps
,
478 BOOST_AUTO_TEST_CASE( test_point_box
)
480 test_distance_point_box(point_box_strategy());
481 test_distance_point_box(point_box_strategy(earth_radius_km
));
482 test_distance_point_box(point_box_strategy(earth_radius_miles
));
484 test_distance_point_box(comparable_point_box_strategy());
485 test_distance_point_box(comparable_point_box_strategy(earth_radius_km
));
486 test_distance_point_box(comparable_point_box_strategy(earth_radius_miles
));
488 test_distance_multipoint_box(point_box_strategy());
489 test_distance_multipoint_box(point_box_strategy(earth_radius_km
));
490 test_distance_multipoint_box(point_box_strategy(earth_radius_miles
));