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.
9 // Modifications copyright (c) 2014, Oracle and/or its affiliates.
11 // Contributed and/or modified by Menelaos Karavelas, 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>
31 #include <boost/timer.hpp>
33 #include <boost/concept/requires.hpp>
34 #include <boost/concept_check.hpp>
36 #include <boost/geometry/algorithms/assign.hpp>
37 #include <boost/geometry/algorithms/expand.hpp>
38 #include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>
39 #include <boost/geometry/strategies/concepts/distance_concept.hpp>
42 #include <boost/geometry/geometries/point.hpp>
43 #include <boost/geometry/geometries/box.hpp>
44 #include <boost/geometry/geometries/adapted/c_array.hpp>
45 #include <boost/geometry/geometries/adapted/boost_tuple.hpp>
47 #include <test_common/test_point.hpp>
50 # include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
54 namespace bg
= boost::geometry
;
57 BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian
)
58 BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian
)
61 template <typename Box
, typename Coordinate
>
62 inline void assign_values(Box
& box
,
70 typename
bg::point_type
<Box
>::type p1
, p2
;
71 bg::assign_values(p1
, x1
, y1
, z1
);
72 bg::assign_values(p2
, x2
, y2
, z2
);
77 template <typename Point
, typename Box
>
78 inline void test_null_distance_3d()
81 bg::assign_values(p
, 1, 2, 4);
83 assign_values(b
, 1, 2, 3, 4, 5, 6);
85 typedef bg::strategy::distance::pythagoras_point_box
<> pythagoras_pb_type
;
86 typedef typename
bg::strategy::distance::services::return_type
88 pythagoras_pb_type
, Point
, Box
91 pythagoras_pb_type pythagoras_pb
;
92 return_type result
= pythagoras_pb
.apply(p
, b
);
94 BOOST_CHECK_EQUAL(result
, return_type(0));
96 bg::assign_values(p
, 1, 3, 4);
97 result
= pythagoras_pb
.apply(p
, b
);
98 BOOST_CHECK_EQUAL(result
, return_type(0));
100 bg::assign_values(p
, 2, 3, 4);
101 result
= pythagoras_pb
.apply(p
, b
);
102 BOOST_CHECK_EQUAL(result
, return_type(0));
105 template <typename Point
, typename Box
>
106 inline void test_axis_3d()
109 assign_values(b
, 0, 0, 0, 1, 1, 1);
111 bg::assign_values(p
, 2, 0, 0);
113 typedef bg::strategy::distance::pythagoras_point_box
<> pythagoras_pb_type
;
114 typedef typename
bg::strategy::distance::services::return_type
116 pythagoras_pb_type
, Point
, Box
119 pythagoras_pb_type pythagoras_pb
;
121 return_type result
= pythagoras_pb
.apply(p
, b
);
122 BOOST_CHECK_EQUAL(result
, return_type(1));
124 bg::assign_values(p
, 0, 2, 0);
125 result
= pythagoras_pb
.apply(p
, b
);
126 BOOST_CHECK_EQUAL(result
, return_type(1));
128 bg::assign_values(p
, 0, 0, 2);
129 result
= pythagoras_pb
.apply(p
, b
);
130 BOOST_CHECK_CLOSE(result
, return_type(1), 0.001);
133 template <typename Point
, typename Box
>
134 inline void test_arbitrary_3d()
137 assign_values(b
, 0, 0, 0, 1, 2, 3);
139 bg::assign_values(p
, 9, 8, 7);
142 typedef bg::strategy::distance::pythagoras_point_box
<> strategy_type
;
143 typedef typename
bg::strategy::distance::services::return_type
145 strategy_type
, Point
, Box
148 strategy_type strategy
;
149 return_type result
= strategy
.apply(p
, b
);
150 BOOST_CHECK_CLOSE(result
, return_type(10.77032961427), 0.001);
154 // Check comparable distance
155 typedef bg::strategy::distance::comparable::pythagoras_point_box
<>
158 typedef typename
bg::strategy::distance::services::return_type
160 strategy_type
, Point
, Box
163 strategy_type strategy
;
164 return_type result
= strategy
.apply(p
, b
);
165 BOOST_CHECK_EQUAL(result
, return_type(116));
169 template <typename Point
, typename Box
, typename CalculationType
>
170 inline void test_services()
172 namespace bgsd
= bg::strategy::distance
;
173 namespace services
= bg::strategy::distance::services
;
176 // Compile-check if there is a strategy for this type
177 typedef typename
services::default_strategy
179 bg::point_tag
, bg::box_tag
, Point
, Box
180 >::type pythagoras_pb_strategy_type
;
182 // reverse geometry tags
183 typedef typename
services::default_strategy
185 bg::box_tag
, bg::point_tag
, Box
, Point
186 >::type reversed_pythagoras_pb_strategy_type
;
190 pythagoras_pb_strategy_type
,
191 reversed_pythagoras_pb_strategy_type
196 bg::assign_values(p
, 1, 2, 3);
199 assign_values(b
, 4, 5, 6, 14, 15, 16);
201 double const sqr_expected
= 3*3 + 3*3 + 3*3; // 27
202 double const expected
= sqrt(sqr_expected
); // sqrt(27)=5.1961524227
204 // 1: normal, calculate distance:
206 typedef bgsd::pythagoras_point_box
<CalculationType
> strategy_type
;
209 ( (bg::concepts::PointDistanceStrategy
<strategy_type
, Point
, Box
>) );
211 typedef typename
bgsd::services::return_type
213 strategy_type
, Point
, Box
216 strategy_type strategy
;
217 return_type result
= strategy
.apply(p
, b
);
218 BOOST_CHECK_CLOSE(result
, return_type(expected
), 0.001);
220 // 2: the strategy should return the same result if we reverse parameters
221 // result = strategy.apply(p2, p1);
222 // BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
225 // 3: "comparable" to construct a "comparable strategy" for Point/Box
226 // a "comparable strategy" is a strategy which does not calculate the exact distance, but
227 // which returns results which can be mutually compared (e.g. avoid sqrt)
229 // 3a: "comparable_type"
230 typedef typename
services::comparable_type
233 >::type comparable_type
;
235 // 3b: "get_comparable"
236 comparable_type comparable
= bgsd::services::get_comparable
241 typedef typename
bgsd::services::return_type
243 comparable_type
, Point
, Box
244 >::type comparable_return_type
;
246 comparable_return_type c_result
= comparable
.apply(p
, b
);
247 BOOST_CHECK_CLOSE(c_result
, return_type(sqr_expected
), 0.001);
249 // 4: the comparable_type should have a distance_strategy_constructor as well,
250 // knowing how to compare something with a fixed distance
251 comparable_return_type c_dist5
= services::result_from_distance
253 comparable_type
, Point
, Box
254 >::apply(comparable
, 5.0);
256 comparable_return_type c_dist6
= services::result_from_distance
258 comparable_type
, Point
, Box
259 >::apply(comparable
, 6.0);
261 // If this is the case:
262 BOOST_CHECK(c_dist5
< c_result
&& c_result
< c_dist6
);
264 // This should also be the case
265 return_type dist5
= services::result_from_distance
267 strategy_type
, Point
, Box
268 >::apply(strategy
, 5.0);
269 return_type dist6
= services::result_from_distance
271 strategy_type
, Point
, Box
272 >::apply(strategy
, 6.0);
273 BOOST_CHECK(dist5
< result
&& result
< dist6
);
278 typename CoordinateType
,
279 typename CalculationType
,
282 inline void test_big_2d_with(AssignType
const& x1
, AssignType
const& y1
,
283 AssignType
const& x2
, AssignType
const& y2
,
284 AssignType
const& zero
)
286 typedef bg::model::point
<CoordinateType
, 2, bg::cs::cartesian
> point_type
;
287 typedef bg::model::box
<point_type
> box_type
;
288 typedef bg::strategy::distance::pythagoras_point_box
291 > pythagoras_pb_type
;
293 pythagoras_pb_type pythagoras_pb
;
294 typedef typename
bg::strategy::distance::services::return_type
296 pythagoras_pb_type
, point_type
, box_type
302 bg::assign_values(b
, zero
, zero
, x1
, y1
);
303 bg::assign_values(p
, x2
, y2
);
304 return_type d
= pythagoras_pb
.apply(p
, b
);
306 BOOST_CHECK_CLOSE(d
, return_type(1076554.5485833955678294387789057), 0.001);
309 template <typename CoordinateType
, typename CalculationType
>
310 inline void test_big_2d()
312 test_big_2d_with
<CoordinateType
, CalculationType
>
313 (123456.78900001, 234567.89100001,
314 987654.32100001, 876543.21900001,
318 template <typename CoordinateType
, typename CalculationType
>
319 inline void test_big_2d_string()
321 test_big_2d_with
<CoordinateType
, CalculationType
>
322 ("123456.78900001", "234567.89100001",
323 "987654.32100001", "876543.21900001",
327 template <typename CoordinateType
>
328 inline void test_integer(bool check_types
)
330 typedef bg::model::point
<CoordinateType
, 2, bg::cs::cartesian
> point_type
;
331 typedef bg::model::box
<point_type
> box_type
;
335 bg::assign_values(b
, 0, 0, 12345678, 23456789);
336 bg::assign_values(p
, 98765432, 87654321);
338 typedef bg::strategy::distance::pythagoras_point_box
<> pythagoras_type
;
339 typedef typename
bg::strategy::distance::services::comparable_type
342 >::type comparable_type
;
344 typedef typename
bg::strategy::distance::services::return_type
346 pythagoras_type
, point_type
, box_type
347 >::type distance_type
;
348 typedef typename
bg::strategy::distance::services::return_type
350 comparable_type
, point_type
, box_type
351 >::type cdistance_type
;
353 pythagoras_type pythagoras
;
354 distance_type distance
= pythagoras
.apply(p
, b
);
355 BOOST_CHECK_CLOSE(distance
, 107655455.02347542, 0.001);
357 comparable_type comparable
;
358 cdistance_type cdistance
= comparable
.apply(p
, b
);
359 BOOST_CHECK_EQUAL(cdistance
, 11589696996311540);
361 distance_type distance2
= sqrt(distance_type(cdistance
));
362 BOOST_CHECK_CLOSE(distance
, distance2
, 0.001);
366 BOOST_CHECK((boost::is_same
<distance_type
, double>::type::value
));
367 BOOST_CHECK((boost::is_same
<cdistance_type
, boost::long_long_type
>::type::value
));
371 template <typename P1
, typename P2
>
374 test_null_distance_3d
<P1
, bg::model::box
<P2
> >();
375 test_axis_3d
<P1
, bg::model::box
<P2
> >();
376 test_arbitrary_3d
<P1
, bg::model::box
<P2
> >();
378 test_null_distance_3d
<P2
, bg::model::box
<P1
> >();
379 test_axis_3d
<P2
, bg::model::box
<P1
> >();
380 test_arbitrary_3d
<P2
, bg::model::box
<P1
> >();
383 template <typename P
>
386 test_all_3d
<P
, int[3]>();
387 test_all_3d
<P
, float[3]>();
388 test_all_3d
<P
, double[3]>();
389 test_all_3d
<P
, test::test_point
>();
390 test_all_3d
<P
, bg::model::point
<int, 3, bg::cs::cartesian
> >();
391 test_all_3d
<P
, bg::model::point
<float, 3, bg::cs::cartesian
> >();
392 test_all_3d
<P
, bg::model::point
<double, 3, bg::cs::cartesian
> >();
395 template <typename P
, typename Strategy
>
396 void time_compare_s(int const n
)
398 typedef bg::model::box
<P
> box_type
;
403 bg::assign_values(b
, 0, 0, 1, 1);
404 bg::assign_values(p
, 2, 2);
406 typename
bg::strategy::distance::services::return_type
408 Strategy
, P
, box_type
410 for (int i
= 0; i
< n
; i
++)
412 for (int j
= 0; j
< n
; j
++)
414 bg::set
<0>(p
, bg::get
<0>(p
) + 0.001);
415 s
+= strategy
.apply(p
, b
);
418 std::cout
<< "s: " << s
<< " t: " << t
.elapsed() << std::endl
;
421 template <typename P
>
422 inline void time_compare(int const n
)
424 time_compare_s
<P
, bg::strategy::distance::pythagoras_point_box
<> >(n
);
427 P
, bg::strategy::distance::comparable::pythagoras_point_box
<>
434 BOOST_AUTO_TEST_CASE( test_integer_all
)
436 test_integer
<int>(true);
437 test_integer
<boost::long_long_type
>(true);
438 test_integer
<double>(false);
442 BOOST_AUTO_TEST_CASE( test_3d_all
)
444 test_all_3d
<int[3]>();
445 test_all_3d
<float[3]>();
446 test_all_3d
<double[3]>();
448 test_all_3d
<test::test_point
>();
450 test_all_3d
<bg::model::point
<int, 3, bg::cs::cartesian
> >();
451 test_all_3d
<bg::model::point
<float, 3, bg::cs::cartesian
> >();
452 test_all_3d
<bg::model::point
<double, 3, bg::cs::cartesian
> >();
456 BOOST_AUTO_TEST_CASE( test_big_2d_all
)
458 test_big_2d
<float, float>();
459 test_big_2d
<double, double>();
460 test_big_2d
<long double, long double>();
461 test_big_2d
<float, long double>();
465 BOOST_AUTO_TEST_CASE( test_services_all
)
469 bg::model::point
<float, 3, bg::cs::cartesian
>,
470 bg::model::box
<double[3]>,
473 test_services
<double[3], bg::model::box
<test::test_point
>, float>();
475 // reverse the point and box types
479 bg::model::box
<bg::model::point
<float, 3, bg::cs::cartesian
> >,
482 test_services
<test::test_point
, bg::model::box
<double[3]>, float>();
486 BOOST_AUTO_TEST_CASE( test_time_compare
)
488 // TODO move this to another non-unit test
489 // time_compare<bg::model::point<double, 2, bg::cs::cartesian> >(10000);
493 #if defined(HAVE_TTMATH)
494 BOOST_AUTO_TEST_CASE( test_ttmath_all
)
496 typedef ttmath::Big
<1,4> tt
;
497 typedef bg::model::point
<tt
, 3, bg::cs::cartesian
> tt_point
;
499 //test_all_3d<tt[3]>();
500 test_all_3d
<tt_point
>();
501 test_all_3d
<tt_point
, tt_point
>();
502 test_big_2d
<tt
, tt
>();
503 test_big_2d_string
<tt
, tt
>();