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::segment
<point_type
> segment_type
;
30 typedef bg::model::box
<point_type
> box_type
;
32 namespace distance
= bg::strategy::distance
;
33 namespace services
= distance::services
;
34 typedef bg::default_distance_result
<point_type
, point_type
>::type return_type
;
36 typedef distance::cross_track_point_box
<> point_box_strategy
;
37 typedef distance::cross_track_point_box
39 void, distance::comparable::cross_track
<>
40 > comparable_point_box_strategy
;
42 //===========================================================================
44 inline bg::distance_result
46 point_type
, point_type
, distance::haversine
<double>
48 distance_pp(std::string
const& wkt1
,
49 std::string
const& wkt2
,
53 bg::read_wkt(wkt1
, p1
);
54 bg::read_wkt(wkt2
, p2
);
56 distance::haversine
<double> strategy(radius
);
57 return bg::distance(p1
, p2
, strategy
);
60 inline bg::default_comparable_distance_result
<point_type
>::type
61 comparable_distance_pp(std::string
const& wkt1
,
62 std::string
const& wkt2
)
65 bg::read_wkt(wkt1
, p1
);
66 bg::read_wkt(wkt2
, p2
);
67 return bg::comparable_distance(p1
, p2
);
70 inline bg::distance_result
72 point_type
, point_type
, distance::cross_track
<>
74 distance_ps(std::string
const& wkt_point
,
75 std::string
const& wkt_segment
,
80 bg::read_wkt(wkt_point
, point
);
81 bg::read_wkt(wkt_segment
, segment
);
83 distance::cross_track
<> strategy(radius
);
84 return bg::distance(point
, segment
, strategy
);
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
)
93 bg::read_wkt(wkt_point
, point
);
94 bg::read_wkt(wkt_segment
, segment
);
95 return bg::comparable_distance(point
, segment
);
98 enum features_type
{ pp
, ps
};
100 template <typename Geometry1
, typename Geometry2
>
101 struct test_distances
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
)
111 typedef test_distance_of_geometries
<Geometry1
, Geometry2
> tester
;
113 bool const is_comparable
= boost::is_same
116 typename
services::comparable_type
<Strategy
>::type
119 if (BOOST_GEOMETRY_CONDITION(is_comparable
))
121 tester::apply(case_id
, wkt1
, wkt2
,
122 expected_comparable_distance
,
123 expected_comparable_distance
,
128 tester::apply(case_id
, wkt1
, wkt2
,
130 expected_comparable_distance
,
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
,
142 Strategy
const& strategy
)
144 double const radius
= strategy
.radius();
145 double expected_distance
, expected_comparable_distance
;
149 expected_distance
= distance_pp(feature1
, feature2
, radius
);
150 expected_comparable_distance
151 = comparable_distance_pp(feature1
, feature2
);
155 expected_distance
= distance_ps(feature1
, feature2
, radius
);
156 expected_comparable_distance
157 = comparable_distance_ps(feature1
, feature2
);
160 apply(case_id
, wkt1
, wkt2
,
161 expected_distance
, expected_comparable_distance
,
166 template <typename T
, typename U
>
167 T
to_comparable(T
const& value
, U
const& radius
)
169 T x
= sin(value
/ (radius
* 2.0));
173 //===========================================================================
175 template <typename Strategy
>
176 void test_distance_point_box(Strategy
const& strategy
)
178 #ifdef BOOST_GEOMETRY_TEST_DEBUG
179 std::cout
<< std::endl
;
180 std::cout
<< "point/box distance tests" << std::endl
;
182 typedef test_distances
<point_type
, box_type
> tester
;
184 double const radius
= strategy
.radius();
185 double const d2r
= bg::math::d2r
<double>();
187 // Cases for relative location of a point wrt to a box
201 // and also the following cases
215 // and finally we have the corners
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
233 std::string
const box1
= "BOX(10 10,20 20)";
236 tester::apply("pb1-1a", "POINT(5 25)", box1
,
237 "POINT(5 25)", "POINT(10 20)", pp
,
241 tester::apply("pb1-1b", "POINT(3 12)", box1
,
242 "POINT(3 12)", "SEGMENT(10 10,10 20)", ps
,
246 tester::apply("pb1-1c", "POINT(3 17)", box1
,
247 "POINT(3 17)", "SEGMENT(10 10,10 20)", ps
,
251 tester::apply("pb1-1d", "POINT(5 4)", box1
,
252 "POINT(5 4)", "POINT(10 10)", pp
,
256 tester::apply("pb1-1e", "POINT(-100 20)", box1
,
257 "POINT(-100 20)", "POINT(10 20)", pp
,
261 tester::apply("pb1-1g", "POINT(-100 10)", box1
,
262 "POINT(-100 10)", "SEGMENT(10 10,10 20)", ps
,
266 tester::apply("pb1-2a", "POINT(31 25)", box1
,
267 "POINT(31 25)", "POINT(20 20)", pp
,
271 tester::apply("pb1-2b", "POINT(23 17)", box1
,
272 "POINT(23 17)", "SEGMENT(20 10,20 20)", ps
,
276 tester::apply("pb1-2c", "POINT(29 3)", box1
,
277 "POINT(29 3)", "POINT(20 10)", pp
,
281 tester::apply("pb1-2d", "POINT(131 65)", box1
,
282 "POINT(131 65)", "POINT(20 20)", pp
,
286 tester::apply("pb1-2e", "POINT(110 10)", box1
,
287 "POINT(110 10)", "SEGMENT(20 10,20 20)", ps
,
291 tester::apply("pb1-2f", "POINT(150 20)", box1
,
292 "POINT(150 20)", "POINT(20 20)", pp
,
296 tester::apply("pb1-3a", "POINT(11 25)", box1
,
298 to_comparable(5.0 * d2r
* radius
, radius
),
302 tester::apply("pb1-3b", "POINT(15 25)", box1
,
304 to_comparable(5.0 * d2r
* radius
, radius
),
308 tester::apply("pb1-3c", "POINT(18 25)", box1
,
310 to_comparable(5.0 * d2r
* radius
, radius
),
314 tester::apply("pb1-4a", "POINT(13 4)", box1
,
316 to_comparable(6.0 * radius
* d2r
, radius
),
320 tester::apply("pb1-4b", "POINT(19 4)", box1
,
322 to_comparable(6.0 * radius
* d2r
, radius
),
326 tester::apply("pb1-5", "POINT(15 14)", box1
, 0, 0, strategy
);
329 tester::apply("pb1-A", "POINT(10 28)", box1
,
331 to_comparable(8.0 * d2r
* radius
, radius
),
335 tester::apply("pb1-B", "POINT(20 28)", box1
,
337 to_comparable(8.0 * d2r
* radius
, radius
),
341 tester::apply("pb1-C", "POINT(14 20)", box1
, 0, 0, strategy
);
344 tester::apply("pb1-D", "POINT(10 17)", box1
, 0, 0, strategy
);
347 tester::apply("pb1-E", "POINT(20 11)", box1
, 0, 0, strategy
);
350 tester::apply("pb1-F", "POINT(19 10)", box1
, 0, 0, strategy
);
353 tester::apply("pb1-G", "POINT(10 -40)", box1
,
355 to_comparable(50.0 * d2r
* radius
, radius
),
359 tester::apply("pb1-H",
360 "POINT(20 -50)", box1
,
362 to_comparable(60.0 * d2r
* radius
, radius
),
366 tester::apply("pb1-a", "POINT(10 20)", box1
, 0, 0, strategy
);
368 tester::apply("pb1-b", "POINT(20 20)", box1
, 0, 0, strategy
);
370 tester::apply("pb1-c", "POINT(10 10)", box1
, 0, 0, strategy
);
372 tester::apply("pb1-d", "POINT(20 10)", box1
, 0, 0, strategy
);
376 std::string
const box2
= "BOX(170 -60,400 80)";
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
,
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
,
388 // case 3 - equivalent point POINT(390 85) is above the box
389 tester::apply("pb2-3", "POINT(30 85)", box2
,
391 to_comparable(5.0 * d2r
* radius
, radius
),
394 // case 4 - equivalent point POINT(390 -75) is below the box
395 tester::apply("pb2-4", "POINT(30 -75)", box2
,
397 to_comparable(15.0 * d2r
* radius
, radius
),
400 // case 5 - equivalent point POINT(390 0) is inside box
401 tester::apply("pb2-5", "POINT(30 0)", box2
, 0, 0, strategy
);
404 std::string
const box3
= "BOX(-150 -50,-40 70)";
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
,
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
,
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
,
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
,
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
,
431 // box that is symmetric wrt the prime meridian
432 std::string
const box4
= "BOX(-75 -45,75 65)";
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
,
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
,
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
,
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
,
455 BOOST_AUTO_TEST_CASE( test_point_box
)
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
));
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
));