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-2020.
9 // Modifications copyright (c) 2014-2020, Oracle and/or its affiliates.
11 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
12 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
14 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
15 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
17 // Use, modification and distribution is subject to the Boost Software License,
18 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
19 // http://www.boost.org/LICENSE_1_0.txt)
21 #ifndef BOOST_TEST_MODULE
22 #define BOOST_TEST_MODULE test_pythagoras_point_box
25 #include <boost/test/included/unit_test.hpp>
28 # pragma warning( disable : 4101 )
31 #include <boost/core/ignore_unused.hpp>
32 #include <boost/timer.hpp>
34 #include <boost/concept/requires.hpp>
35 #include <boost/concept_check.hpp>
37 #include <boost/geometry/algorithms/assign.hpp>
38 #include <boost/geometry/algorithms/expand.hpp>
39 #include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>
40 #include <boost/geometry/strategies/concepts/distance_concept.hpp>
43 #include <boost/geometry/geometries/point.hpp>
44 #include <boost/geometry/geometries/box.hpp>
45 #include <boost/geometry/geometries/adapted/c_array.hpp>
46 #include <boost/geometry/geometries/adapted/boost_tuple.hpp>
48 #include <test_common/test_point.hpp>
51 #include <boost/geometry/strategies/cartesian.hpp>
52 #include <boost/geometry/strategies/geographic.hpp>
53 #include <boost/geometry/strategies/spherical.hpp>
56 namespace bg
= boost::geometry
;
59 BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian
)
60 BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian
)
63 template <typename Box
, typename Coordinate
>
64 inline void assign_values(Box
& box
,
72 typename
bg::point_type
<Box
>::type p1
, p2
;
73 bg::assign_values(p1
, x1
, y1
, z1
);
74 bg::assign_values(p2
, x2
, y2
, z2
);
79 template <typename Point
, typename Box
>
80 inline void test_null_distance_3d()
83 bg::assign_values(p
, 1, 2, 4);
85 assign_values(b
, 1, 2, 3, 4, 5, 6);
87 typedef bg::strategy::distance::pythagoras_point_box
<> pythagoras_pb_type
;
88 typedef typename
bg::strategy::distance::services::return_type
90 pythagoras_pb_type
, Point
, Box
93 pythagoras_pb_type pythagoras_pb
;
94 return_type result
= pythagoras_pb
.apply(p
, b
);
96 BOOST_CHECK_EQUAL(result
, return_type(0));
98 bg::assign_values(p
, 1, 3, 4);
99 result
= pythagoras_pb
.apply(p
, b
);
100 BOOST_CHECK_EQUAL(result
, return_type(0));
102 bg::assign_values(p
, 2, 3, 4);
103 result
= pythagoras_pb
.apply(p
, b
);
104 BOOST_CHECK_EQUAL(result
, return_type(0));
107 template <typename Point
, typename Box
>
108 inline void test_axis_3d()
111 assign_values(b
, 0, 0, 0, 1, 1, 1);
113 bg::assign_values(p
, 2, 0, 0);
115 typedef bg::strategy::distance::pythagoras_point_box
<> pythagoras_pb_type
;
116 typedef typename
bg::strategy::distance::services::return_type
118 pythagoras_pb_type
, Point
, Box
121 pythagoras_pb_type pythagoras_pb
;
123 return_type result
= pythagoras_pb
.apply(p
, b
);
124 BOOST_CHECK_EQUAL(result
, return_type(1));
126 bg::assign_values(p
, 0, 2, 0);
127 result
= pythagoras_pb
.apply(p
, b
);
128 BOOST_CHECK_EQUAL(result
, return_type(1));
130 bg::assign_values(p
, 0, 0, 2);
131 result
= pythagoras_pb
.apply(p
, b
);
132 BOOST_CHECK_CLOSE(result
, return_type(1), 0.001);
135 template <typename Point
, typename Box
>
136 inline void test_arbitrary_3d()
139 assign_values(b
, 0, 0, 0, 1, 2, 3);
141 bg::assign_values(p
, 9, 8, 7);
144 typedef bg::strategy::distance::pythagoras_point_box
<> strategy_type
;
145 typedef typename
bg::strategy::distance::services::return_type
147 strategy_type
, Point
, Box
150 strategy_type strategy
;
151 return_type result
= strategy
.apply(p
, b
);
152 BOOST_CHECK_CLOSE(result
, return_type(10.77032961427), 0.001);
156 // Check comparable distance
157 typedef bg::strategy::distance::comparable::pythagoras_point_box
<>
160 typedef typename
bg::strategy::distance::services::return_type
162 strategy_type
, Point
, Box
165 strategy_type strategy
;
166 return_type result
= strategy
.apply(p
, b
);
167 BOOST_CHECK_EQUAL(result
, return_type(116));
171 template <typename Point
, typename Box
, typename CalculationType
>
172 inline void test_services()
174 namespace bgsd
= bg::strategy::distance
;
175 namespace services
= bg::strategy::distance::services
;
178 // Compile-check if there is a strategy for this type
179 typedef typename
services::default_strategy
181 bg::point_tag
, bg::box_tag
, Point
, Box
182 >::type pythagoras_pb_strategy_type
;
184 // reverse geometry tags
185 typedef typename
services::default_strategy
187 bg::box_tag
, bg::point_tag
, Box
, Point
188 >::type reversed_pythagoras_pb_strategy_type
;
192 pythagoras_pb_strategy_type
,
193 reversed_pythagoras_pb_strategy_type
198 bg::assign_values(p
, 1, 2, 3);
201 assign_values(b
, 4, 5, 6, 14, 15, 16);
203 double const sqr_expected
= 3*3 + 3*3 + 3*3; // 27
204 double const expected
= sqrt(sqr_expected
); // sqrt(27)=5.1961524227
206 // 1: normal, calculate distance:
208 typedef bgsd::pythagoras_point_box
<CalculationType
> strategy_type
;
211 ( (bg::concepts::PointDistanceStrategy
<strategy_type
, Point
, Box
>) );
213 typedef typename
bgsd::services::return_type
215 strategy_type
, Point
, Box
218 strategy_type strategy
;
219 return_type result
= strategy
.apply(p
, b
);
220 BOOST_CHECK_CLOSE(result
, return_type(expected
), 0.001);
222 // 2: the strategy should return the same result if we reverse parameters
223 // result = strategy.apply(p2, p1);
224 // BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
227 // 3: "comparable" to construct a "comparable strategy" for Point/Box
228 // a "comparable strategy" is a strategy which does not calculate the exact distance, but
229 // which returns results which can be mutually compared (e.g. avoid sqrt)
231 // 3a: "comparable_type"
232 typedef typename
services::comparable_type
235 >::type comparable_type
;
237 // 3b: "get_comparable"
238 comparable_type comparable
= bgsd::services::get_comparable
243 typedef typename
bgsd::services::return_type
245 comparable_type
, Point
, Box
246 >::type comparable_return_type
;
248 comparable_return_type c_result
= comparable
.apply(p
, b
);
249 BOOST_CHECK_CLOSE(c_result
, return_type(sqr_expected
), 0.001);
251 // 4: the comparable_type should have a distance_strategy_constructor as well,
252 // knowing how to compare something with a fixed distance
253 comparable_return_type c_dist5
= services::result_from_distance
255 comparable_type
, Point
, Box
256 >::apply(comparable
, 5.0);
258 comparable_return_type c_dist6
= services::result_from_distance
260 comparable_type
, Point
, Box
261 >::apply(comparable
, 6.0);
263 // If this is the case:
264 BOOST_CHECK(c_dist5
< c_result
&& c_result
< c_dist6
);
266 // This should also be the case
267 return_type dist5
= services::result_from_distance
269 strategy_type
, Point
, Box
270 >::apply(strategy
, 5.0);
271 return_type dist6
= services::result_from_distance
273 strategy_type
, Point
, Box
274 >::apply(strategy
, 6.0);
275 BOOST_CHECK(dist5
< result
&& result
< dist6
);
280 typename CoordinateType
,
281 typename CalculationType
,
284 inline void test_big_2d_with(AssignType
const& x1
, AssignType
const& y1
,
285 AssignType
const& x2
, AssignType
const& y2
,
286 AssignType
const& zero
)
288 typedef bg::model::point
<CoordinateType
, 2, bg::cs::cartesian
> point_type
;
289 typedef bg::model::box
<point_type
> box_type
;
290 typedef bg::strategy::distance::pythagoras_point_box
293 > pythagoras_pb_type
;
295 pythagoras_pb_type pythagoras_pb
;
296 typedef typename
bg::strategy::distance::services::return_type
298 pythagoras_pb_type
, point_type
, box_type
304 bg::assign_values(b
, zero
, zero
, x1
, y1
);
305 bg::assign_values(p
, x2
, y2
);
306 return_type d
= pythagoras_pb
.apply(p
, b
);
308 BOOST_CHECK_CLOSE(d
, return_type(1076554.5485833955678294387789057), 0.001);
311 template <typename CoordinateType
, typename CalculationType
>
312 inline void test_big_2d()
314 test_big_2d_with
<CoordinateType
, CalculationType
>
315 (123456.78900001, 234567.89100001,
316 987654.32100001, 876543.21900001,
320 template <typename CoordinateType
, typename CalculationType
>
321 inline void test_big_2d_string()
323 test_big_2d_with
<CoordinateType
, CalculationType
>
324 ("123456.78900001", "234567.89100001",
325 "987654.32100001", "876543.21900001",
329 template <typename CoordinateType
>
330 inline void test_integer(bool check_types
)
332 typedef bg::model::point
<CoordinateType
, 2, bg::cs::cartesian
> point_type
;
333 typedef bg::model::box
<point_type
> box_type
;
337 bg::assign_values(b
, 0, 0, 12345678, 23456789);
338 bg::assign_values(p
, 98765432, 87654321);
340 typedef bg::strategy::distance::pythagoras_point_box
<> pythagoras_type
;
341 typedef typename
bg::strategy::distance::services::comparable_type
344 >::type comparable_type
;
346 typedef typename
bg::strategy::distance::services::return_type
348 pythagoras_type
, point_type
, box_type
349 >::type distance_type
;
350 typedef typename
bg::strategy::distance::services::return_type
352 comparable_type
, point_type
, box_type
353 >::type cdistance_type
;
355 pythagoras_type pythagoras
;
356 distance_type distance
= pythagoras
.apply(p
, b
);
357 BOOST_CHECK_CLOSE(distance
, 107655455.02347542, 0.001);
359 comparable_type comparable
;
360 cdistance_type cdistance
= comparable
.apply(p
, b
);
361 BOOST_CHECK_EQUAL(cdistance
, 11589696996311540.0);
363 distance_type distance2
= sqrt(distance_type(cdistance
));
364 BOOST_CHECK_CLOSE(distance
, distance2
, 0.001);
368 BOOST_CHECK((boost::is_same
<distance_type
, double>::type::value
));
369 BOOST_CHECK((boost::is_same
<cdistance_type
, boost::long_long_type
>::type::value
));
373 template <typename P1
, typename P2
>
376 test_null_distance_3d
<P1
, bg::model::box
<P2
> >();
377 test_axis_3d
<P1
, bg::model::box
<P2
> >();
378 test_arbitrary_3d
<P1
, bg::model::box
<P2
> >();
380 test_null_distance_3d
<P2
, bg::model::box
<P1
> >();
381 test_axis_3d
<P2
, bg::model::box
<P1
> >();
382 test_arbitrary_3d
<P2
, bg::model::box
<P1
> >();
385 template <typename P
>
388 test_all_3d
<P
, int[3]>();
389 test_all_3d
<P
, float[3]>();
390 test_all_3d
<P
, double[3]>();
391 test_all_3d
<P
, test::test_point
>();
392 test_all_3d
<P
, bg::model::point
<int, 3, bg::cs::cartesian
> >();
393 test_all_3d
<P
, bg::model::point
<float, 3, bg::cs::cartesian
> >();
394 test_all_3d
<P
, bg::model::point
<double, 3, bg::cs::cartesian
> >();
397 template <typename P
, typename Strategy
>
398 void time_compare_s(int const n
)
400 typedef bg::model::box
<P
> box_type
;
405 bg::assign_values(b
, 0, 0, 1, 1);
406 bg::assign_values(p
, 2, 2);
408 typename
bg::strategy::distance::services::return_type
410 Strategy
, P
, box_type
412 for (int i
= 0; i
< n
; i
++)
414 for (int j
= 0; j
< n
; j
++)
416 bg::set
<0>(p
, bg::get
<0>(p
) + 0.001);
417 s
+= strategy
.apply(p
, b
);
420 std::cout
<< "s: " << s
<< " t: " << t
.elapsed() << std::endl
;
423 template <typename P
>
424 inline void time_compare(int const n
)
426 time_compare_s
<P
, bg::strategy::distance::pythagoras_point_box
<> >(n
);
429 P
, bg::strategy::distance::comparable::pythagoras_point_box
<>
436 BOOST_AUTO_TEST_CASE( test_integer_all
)
438 test_integer
<int>(true);
439 test_integer
<boost::long_long_type
>(true);
440 test_integer
<double>(false);
444 BOOST_AUTO_TEST_CASE( test_3d_all
)
446 test_all_3d
<int[3]>();
447 test_all_3d
<float[3]>();
448 test_all_3d
<double[3]>();
450 test_all_3d
<test::test_point
>();
452 test_all_3d
<bg::model::point
<int, 3, bg::cs::cartesian
> >();
453 test_all_3d
<bg::model::point
<float, 3, bg::cs::cartesian
> >();
454 test_all_3d
<bg::model::point
<double, 3, bg::cs::cartesian
> >();
458 BOOST_AUTO_TEST_CASE( test_big_2d_all
)
460 test_big_2d
<float, float>();
461 test_big_2d
<double, double>();
462 test_big_2d
<long double, long double>();
463 test_big_2d
<float, long double>();
467 BOOST_AUTO_TEST_CASE( test_services_all
)
471 bg::model::point
<float, 3, bg::cs::cartesian
>,
472 bg::model::box
<double[3]>,
475 test_services
<double[3], bg::model::box
<test::test_point
>, float>();
477 // reverse the point and box types
481 bg::model::box
<bg::model::point
<float, 3, bg::cs::cartesian
> >,
484 test_services
<test::test_point
, bg::model::box
<double[3]>, float>();
488 BOOST_AUTO_TEST_CASE( test_time_compare
)
490 // TODO move this to another non-unit test
491 // time_compare<bg::model::point<double, 2, bg::cs::cartesian> >(10000);