1 // Boost.Geometry (aka GGL, Generic Geometry Library)
4 // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
5 // Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
6 // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
8 // This file was modified by Oracle on 2014-2021.
9 // Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
10 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
13 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
14 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16 // Use, modification and distribution is subject to the Boost Software License,
17 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
18 // http://www.boost.org/LICENSE_1_0.txt)
20 #ifndef BOOST_TEST_MODULE
21 #define BOOST_TEST_MODULE test_pythagoras_point_box
24 #include <boost/test/included/unit_test.hpp>
27 # pragma warning( disable : 4101 )
30 #include <boost/core/ignore_unused.hpp>
32 // TODO move this to another non-unit test
33 //#include <boost/timer.hpp>
35 #include <boost/concept/requires.hpp>
36 #include <boost/concept_check.hpp>
38 #include <boost/geometry/algorithms/assign.hpp>
39 #include <boost/geometry/algorithms/expand.hpp>
40 #include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>
41 #include <boost/geometry/strategies/concepts/distance_concept.hpp>
44 #include <boost/geometry/geometries/point.hpp>
45 #include <boost/geometry/geometries/box.hpp>
46 #include <boost/geometry/geometries/adapted/c_array.hpp>
47 #include <boost/geometry/geometries/adapted/boost_tuple.hpp>
49 #include <test_common/test_point.hpp>
52 #include <boost/geometry/strategies/cartesian.hpp>
53 #include <boost/geometry/strategies/geographic.hpp>
54 #include <boost/geometry/strategies/spherical.hpp>
57 namespace bg
= boost::geometry
;
60 BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian
)
61 BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian
)
64 template <typename Box
, typename Coordinate
>
65 inline void assign_values(Box
& box
,
73 typename
bg::point_type
<Box
>::type p1
, p2
;
74 bg::assign_values(p1
, x1
, y1
, z1
);
75 bg::assign_values(p2
, x2
, y2
, z2
);
80 template <typename Point
, typename Box
>
81 inline void test_null_distance_3d()
84 bg::assign_values(p
, 1, 2, 4);
86 assign_values(b
, 1, 2, 3, 4, 5, 6);
88 typedef bg::strategy::distance::pythagoras_point_box
<> pythagoras_pb_type
;
89 typedef typename
bg::strategy::distance::services::return_type
91 pythagoras_pb_type
, Point
, Box
94 pythagoras_pb_type pythagoras_pb
;
95 return_type result
= pythagoras_pb
.apply(p
, b
);
97 BOOST_CHECK_EQUAL(result
, return_type(0));
99 bg::assign_values(p
, 1, 3, 4);
100 result
= pythagoras_pb
.apply(p
, b
);
101 BOOST_CHECK_EQUAL(result
, return_type(0));
103 bg::assign_values(p
, 2, 3, 4);
104 result
= pythagoras_pb
.apply(p
, b
);
105 BOOST_CHECK_EQUAL(result
, return_type(0));
108 template <typename Point
, typename Box
>
109 inline void test_axis_3d()
112 assign_values(b
, 0, 0, 0, 1, 1, 1);
114 bg::assign_values(p
, 2, 0, 0);
116 typedef bg::strategy::distance::pythagoras_point_box
<> pythagoras_pb_type
;
117 typedef typename
bg::strategy::distance::services::return_type
119 pythagoras_pb_type
, Point
, Box
122 pythagoras_pb_type pythagoras_pb
;
124 return_type result
= pythagoras_pb
.apply(p
, b
);
125 BOOST_CHECK_EQUAL(result
, return_type(1));
127 bg::assign_values(p
, 0, 2, 0);
128 result
= pythagoras_pb
.apply(p
, b
);
129 BOOST_CHECK_EQUAL(result
, return_type(1));
131 bg::assign_values(p
, 0, 0, 2);
132 result
= pythagoras_pb
.apply(p
, b
);
133 BOOST_CHECK_CLOSE(result
, return_type(1), 0.001);
136 template <typename Point
, typename Box
>
137 inline void test_arbitrary_3d()
140 assign_values(b
, 0, 0, 0, 1, 2, 3);
142 bg::assign_values(p
, 9, 8, 7);
145 typedef bg::strategy::distance::pythagoras_point_box
<> strategy_type
;
146 typedef typename
bg::strategy::distance::services::return_type
148 strategy_type
, Point
, Box
151 strategy_type strategy
;
152 return_type result
= strategy
.apply(p
, b
);
153 BOOST_CHECK_CLOSE(result
, return_type(10.77032961427), 0.001);
157 // Check comparable distance
158 typedef bg::strategy::distance::comparable::pythagoras_point_box
<>
161 typedef typename
bg::strategy::distance::services::return_type
163 strategy_type
, Point
, Box
166 strategy_type strategy
;
167 return_type result
= strategy
.apply(p
, b
);
168 BOOST_CHECK_EQUAL(result
, return_type(116));
172 template <typename Point
, typename Box
, typename CalculationType
>
173 inline void test_services()
175 namespace bgsd
= bg::strategy::distance
;
176 namespace services
= bg::strategy::distance::services
;
179 // Compile-check if there is a strategy for this type
180 typedef typename
services::default_strategy
182 bg::point_tag
, bg::box_tag
, Point
, Box
183 >::type pythagoras_pb_strategy_type
;
185 // reverse geometry tags
186 typedef typename
services::default_strategy
188 bg::box_tag
, bg::point_tag
, Box
, Point
189 >::type reversed_pythagoras_pb_strategy_type
;
193 pythagoras_pb_strategy_type
,
194 reversed_pythagoras_pb_strategy_type
199 bg::assign_values(p
, 1, 2, 3);
202 assign_values(b
, 4, 5, 6, 14, 15, 16);
204 double const sqr_expected
= 3*3 + 3*3 + 3*3; // 27
205 double const expected
= sqrt(sqr_expected
); // sqrt(27)=5.1961524227
207 // 1: normal, calculate distance:
209 typedef bgsd::pythagoras_point_box
<CalculationType
> strategy_type
;
212 ( (bg::concepts::PointDistanceStrategy
<strategy_type
, Point
, Box
>) );
214 typedef typename
bgsd::services::return_type
216 strategy_type
, Point
, Box
219 strategy_type strategy
;
220 return_type result
= strategy
.apply(p
, b
);
221 BOOST_CHECK_CLOSE(result
, return_type(expected
), 0.001);
223 // 2: the strategy should return the same result if we reverse parameters
224 // result = strategy.apply(p2, p1);
225 // BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
228 // 3: "comparable" to construct a "comparable strategy" for Point/Box
229 // a "comparable strategy" is a strategy which does not calculate the exact distance, but
230 // which returns results which can be mutually compared (e.g. avoid sqrt)
232 // 3a: "comparable_type"
233 typedef typename
services::comparable_type
236 >::type comparable_type
;
238 // 3b: "get_comparable"
239 comparable_type comparable
= bgsd::services::get_comparable
244 typedef typename
bgsd::services::return_type
246 comparable_type
, Point
, Box
247 >::type comparable_return_type
;
249 comparable_return_type c_result
= comparable
.apply(p
, b
);
250 BOOST_CHECK_CLOSE(c_result
, return_type(sqr_expected
), 0.001);
252 // 4: the comparable_type should have a distance_strategy_constructor as well,
253 // knowing how to compare something with a fixed distance
254 comparable_return_type c_dist5
= services::result_from_distance
256 comparable_type
, Point
, Box
257 >::apply(comparable
, 5.0);
259 comparable_return_type c_dist6
= services::result_from_distance
261 comparable_type
, Point
, Box
262 >::apply(comparable
, 6.0);
264 // If this is the case:
265 BOOST_CHECK(c_dist5
< c_result
&& c_result
< c_dist6
);
267 // This should also be the case
268 return_type dist5
= services::result_from_distance
270 strategy_type
, Point
, Box
271 >::apply(strategy
, 5.0);
272 return_type dist6
= services::result_from_distance
274 strategy_type
, Point
, Box
275 >::apply(strategy
, 6.0);
276 BOOST_CHECK(dist5
< result
&& result
< dist6
);
281 typename CoordinateType
,
282 typename CalculationType
,
285 inline void test_big_2d_with(AssignType
const& x1
, AssignType
const& y1
,
286 AssignType
const& x2
, AssignType
const& y2
,
287 AssignType
const& zero
)
289 typedef bg::model::point
<CoordinateType
, 2, bg::cs::cartesian
> point_type
;
290 typedef bg::model::box
<point_type
> box_type
;
291 typedef bg::strategy::distance::pythagoras_point_box
294 > pythagoras_pb_type
;
296 pythagoras_pb_type pythagoras_pb
;
297 typedef typename
bg::strategy::distance::services::return_type
299 pythagoras_pb_type
, point_type
, box_type
305 bg::assign_values(b
, zero
, zero
, x1
, y1
);
306 bg::assign_values(p
, x2
, y2
);
307 return_type d
= pythagoras_pb
.apply(p
, b
);
309 BOOST_CHECK_CLOSE(d
, return_type(1076554.5485833955678294387789057), 0.001);
312 template <typename CoordinateType
, typename CalculationType
>
313 inline void test_big_2d()
315 test_big_2d_with
<CoordinateType
, CalculationType
>
316 (123456.78900001, 234567.89100001,
317 987654.32100001, 876543.21900001,
321 template <typename CoordinateType
, typename CalculationType
>
322 inline void test_big_2d_string()
324 test_big_2d_with
<CoordinateType
, CalculationType
>
325 ("123456.78900001", "234567.89100001",
326 "987654.32100001", "876543.21900001",
330 template <typename CoordinateType
>
331 inline void test_integer(bool check_types
)
333 typedef bg::model::point
<CoordinateType
, 2, bg::cs::cartesian
> point_type
;
334 typedef bg::model::box
<point_type
> box_type
;
338 bg::assign_values(b
, 0, 0, 12345678, 23456789);
339 bg::assign_values(p
, 98765432, 87654321);
341 typedef bg::strategy::distance::pythagoras_point_box
<> pythagoras_type
;
342 typedef typename
bg::strategy::distance::services::comparable_type
345 >::type comparable_type
;
347 typedef typename
bg::strategy::distance::services::return_type
349 pythagoras_type
, point_type
, box_type
350 >::type distance_type
;
351 typedef typename
bg::strategy::distance::services::return_type
353 comparable_type
, point_type
, box_type
354 >::type cdistance_type
;
356 pythagoras_type pythagoras
;
357 distance_type distance
= pythagoras
.apply(p
, b
);
358 BOOST_CHECK_CLOSE(distance
, 107655455.02347542, 0.001);
360 comparable_type comparable
;
361 cdistance_type cdistance
= comparable
.apply(p
, b
);
362 BOOST_CHECK_EQUAL(cdistance
, 11589696996311540.0);
364 distance_type distance2
= sqrt(distance_type(cdistance
));
365 BOOST_CHECK_CLOSE(distance
, distance2
, 0.001);
369 BOOST_CHECK((std::is_same
<distance_type
, double>::type::value
));
370 BOOST_CHECK((std::is_same
<cdistance_type
, long long>::type::value
));
374 template <typename P1
, typename P2
>
377 test_null_distance_3d
<P1
, bg::model::box
<P2
> >();
378 test_axis_3d
<P1
, bg::model::box
<P2
> >();
379 test_arbitrary_3d
<P1
, bg::model::box
<P2
> >();
381 test_null_distance_3d
<P2
, bg::model::box
<P1
> >();
382 test_axis_3d
<P2
, bg::model::box
<P1
> >();
383 test_arbitrary_3d
<P2
, bg::model::box
<P1
> >();
386 template <typename P
>
389 test_all_3d
<P
, int[3]>();
390 test_all_3d
<P
, float[3]>();
391 test_all_3d
<P
, double[3]>();
392 test_all_3d
<P
, test::test_point
>();
393 test_all_3d
<P
, bg::model::point
<int, 3, bg::cs::cartesian
> >();
394 test_all_3d
<P
, bg::model::point
<float, 3, bg::cs::cartesian
> >();
395 test_all_3d
<P
, bg::model::point
<double, 3, bg::cs::cartesian
> >();
399 // TODO move this to another non-unit test
400 //template <typename P, typename Strategy>
401 //void time_compare_s(int const n)
403 // typedef bg::model::box<P> box_type;
408 // bg::assign_values(b, 0, 0, 1, 1);
409 // bg::assign_values(p, 2, 2);
410 // Strategy strategy;
411 // typename bg::strategy::distance::services::return_type
413 // Strategy, P, box_type
415 // for (int i = 0; i < n; i++)
417 // for (int j = 0; j < n; j++)
419 // bg::set<0>(p, bg::get<0>(p) + 0.001);
420 // s += strategy.apply(p, b);
423 // std::cout << "s: " << s << " t: " << t.elapsed() << std::endl;
426 //template <typename P>
427 //inline void time_compare(int const n)
429 // time_compare_s<P, bg::strategy::distance::pythagoras_point_box<> >(n);
432 // P, bg::strategy::distance::comparable::pythagoras_point_box<>
439 BOOST_AUTO_TEST_CASE( test_integer_all
)
441 test_integer
<int>(true);
442 test_integer
<long long>(true);
443 test_integer
<double>(false);
447 BOOST_AUTO_TEST_CASE( test_3d_all
)
449 test_all_3d
<int[3]>();
450 test_all_3d
<float[3]>();
451 test_all_3d
<double[3]>();
453 test_all_3d
<test::test_point
>();
455 test_all_3d
<bg::model::point
<int, 3, bg::cs::cartesian
> >();
456 test_all_3d
<bg::model::point
<float, 3, bg::cs::cartesian
> >();
457 test_all_3d
<bg::model::point
<double, 3, bg::cs::cartesian
> >();
461 BOOST_AUTO_TEST_CASE( test_big_2d_all
)
463 test_big_2d
<float, float>();
464 test_big_2d
<double, double>();
465 test_big_2d
<long double, long double>();
466 test_big_2d
<float, long double>();
470 BOOST_AUTO_TEST_CASE( test_services_all
)
474 bg::model::point
<float, 3, bg::cs::cartesian
>,
475 bg::model::box
<double[3]>,
478 test_services
<double[3], bg::model::box
<test::test_point
>, float>();
480 // reverse the point and box types
484 bg::model::box
<bg::model::point
<float, 3, bg::cs::cartesian
> >,
487 test_services
<test::test_point
, bg::model::box
<double[3]>, float>();
491 BOOST_AUTO_TEST_CASE( test_time_compare
)
493 // TODO move this to another non-unit test
494 // time_compare<bg::model::point<double, 2, bg::cs::cartesian> >(10000);