]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/test/strategies/pythagoras_point_box.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / geometry / test / strategies / pythagoras_point_box.cpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3
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.
7
8 // This file was modified by Oracle on 2014-2020.
9 // Modifications copyright (c) 2014-2020, Oracle and/or its affiliates.
10
11 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
12 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
13
14 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
15 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16
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)
20
21 #ifndef BOOST_TEST_MODULE
22 #define BOOST_TEST_MODULE test_pythagoras_point_box
23 #endif
24
25 #include <boost/test/included/unit_test.hpp>
26
27 #if defined(_MSC_VER)
28 # pragma warning( disable : 4101 )
29 #endif
30
31 #include <boost/core/ignore_unused.hpp>
32 #include <boost/timer.hpp>
33
34 #include <boost/concept/requires.hpp>
35 #include <boost/concept_check.hpp>
36
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>
41
42
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>
47
48 #include <test_common/test_point.hpp>
49
50 // TEST
51 #include <boost/geometry/strategies/cartesian.hpp>
52 #include <boost/geometry/strategies/geographic.hpp>
53 #include <boost/geometry/strategies/spherical.hpp>
54
55
56 namespace bg = boost::geometry;
57
58
59 BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian)
60 BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
61
62
63 template <typename Box, typename Coordinate>
64 inline void assign_values(Box& box,
65 Coordinate const& x1,
66 Coordinate const& y1,
67 Coordinate const& z1,
68 Coordinate const& x2,
69 Coordinate const& y2,
70 Coordinate const& z2)
71 {
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);
75 bg::assign(box, p1);
76 bg::expand(box, p2);
77 }
78
79 template <typename Point, typename Box>
80 inline void test_null_distance_3d()
81 {
82 Point p;
83 bg::assign_values(p, 1, 2, 4);
84 Box b;
85 assign_values(b, 1, 2, 3, 4, 5, 6);
86
87 typedef bg::strategy::distance::pythagoras_point_box<> pythagoras_pb_type;
88 typedef typename bg::strategy::distance::services::return_type
89 <
90 pythagoras_pb_type, Point, Box
91 >::type return_type;
92
93 pythagoras_pb_type pythagoras_pb;
94 return_type result = pythagoras_pb.apply(p, b);
95
96 BOOST_CHECK_EQUAL(result, return_type(0));
97
98 bg::assign_values(p, 1, 3, 4);
99 result = pythagoras_pb.apply(p, b);
100 BOOST_CHECK_EQUAL(result, return_type(0));
101
102 bg::assign_values(p, 2, 3, 4);
103 result = pythagoras_pb.apply(p, b);
104 BOOST_CHECK_EQUAL(result, return_type(0));
105 }
106
107 template <typename Point, typename Box>
108 inline void test_axis_3d()
109 {
110 Box b;
111 assign_values(b, 0, 0, 0, 1, 1, 1);
112 Point p;
113 bg::assign_values(p, 2, 0, 0);
114
115 typedef bg::strategy::distance::pythagoras_point_box<> pythagoras_pb_type;
116 typedef typename bg::strategy::distance::services::return_type
117 <
118 pythagoras_pb_type, Point, Box
119 >::type return_type;
120
121 pythagoras_pb_type pythagoras_pb;
122
123 return_type result = pythagoras_pb.apply(p, b);
124 BOOST_CHECK_EQUAL(result, return_type(1));
125
126 bg::assign_values(p, 0, 2, 0);
127 result = pythagoras_pb.apply(p, b);
128 BOOST_CHECK_EQUAL(result, return_type(1));
129
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);
133 }
134
135 template <typename Point, typename Box>
136 inline void test_arbitrary_3d()
137 {
138 Box b;
139 assign_values(b, 0, 0, 0, 1, 2, 3);
140 Point p;
141 bg::assign_values(p, 9, 8, 7);
142
143 {
144 typedef bg::strategy::distance::pythagoras_point_box<> strategy_type;
145 typedef typename bg::strategy::distance::services::return_type
146 <
147 strategy_type, Point, Box
148 >::type return_type;
149
150 strategy_type strategy;
151 return_type result = strategy.apply(p, b);
152 BOOST_CHECK_CLOSE(result, return_type(10.77032961427), 0.001);
153 }
154
155 {
156 // Check comparable distance
157 typedef bg::strategy::distance::comparable::pythagoras_point_box<>
158 strategy_type;
159
160 typedef typename bg::strategy::distance::services::return_type
161 <
162 strategy_type, Point, Box
163 >::type return_type;
164
165 strategy_type strategy;
166 return_type result = strategy.apply(p, b);
167 BOOST_CHECK_EQUAL(result, return_type(116));
168 }
169 }
170
171 template <typename Point, typename Box, typename CalculationType>
172 inline void test_services()
173 {
174 namespace bgsd = bg::strategy::distance;
175 namespace services = bg::strategy::distance::services;
176
177 {
178 // Compile-check if there is a strategy for this type
179 typedef typename services::default_strategy
180 <
181 bg::point_tag, bg::box_tag, Point, Box
182 >::type pythagoras_pb_strategy_type;
183
184 // reverse geometry tags
185 typedef typename services::default_strategy
186 <
187 bg::box_tag, bg::point_tag, Box, Point
188 >::type reversed_pythagoras_pb_strategy_type;
189
190 boost::ignore_unused
191 <
192 pythagoras_pb_strategy_type,
193 reversed_pythagoras_pb_strategy_type
194 >();
195 }
196
197 Point p;
198 bg::assign_values(p, 1, 2, 3);
199
200 Box b;
201 assign_values(b, 4, 5, 6, 14, 15, 16);
202
203 double const sqr_expected = 3*3 + 3*3 + 3*3; // 27
204 double const expected = sqrt(sqr_expected); // sqrt(27)=5.1961524227
205
206 // 1: normal, calculate distance:
207
208 typedef bgsd::pythagoras_point_box<CalculationType> strategy_type;
209
210 BOOST_CONCEPT_ASSERT
211 ( (bg::concepts::PointDistanceStrategy<strategy_type, Point, Box>) );
212
213 typedef typename bgsd::services::return_type
214 <
215 strategy_type, Point, Box
216 >::type return_type;
217
218 strategy_type strategy;
219 return_type result = strategy.apply(p, b);
220 BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
221
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);
225
226
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)
230
231 // 3a: "comparable_type"
232 typedef typename services::comparable_type
233 <
234 strategy_type
235 >::type comparable_type;
236
237 // 3b: "get_comparable"
238 comparable_type comparable = bgsd::services::get_comparable
239 <
240 strategy_type
241 >::apply(strategy);
242
243 typedef typename bgsd::services::return_type
244 <
245 comparable_type, Point, Box
246 >::type comparable_return_type;
247
248 comparable_return_type c_result = comparable.apply(p, b);
249 BOOST_CHECK_CLOSE(c_result, return_type(sqr_expected), 0.001);
250
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
254 <
255 comparable_type, Point, Box
256 >::apply(comparable, 5.0);
257
258 comparable_return_type c_dist6 = services::result_from_distance
259 <
260 comparable_type, Point, Box
261 >::apply(comparable, 6.0);
262
263 // If this is the case:
264 BOOST_CHECK(c_dist5 < c_result && c_result < c_dist6);
265
266 // This should also be the case
267 return_type dist5 = services::result_from_distance
268 <
269 strategy_type, Point, Box
270 >::apply(strategy, 5.0);
271 return_type dist6 = services::result_from_distance
272 <
273 strategy_type, Point, Box
274 >::apply(strategy, 6.0);
275 BOOST_CHECK(dist5 < result && result < dist6);
276 }
277
278 template
279 <
280 typename CoordinateType,
281 typename CalculationType,
282 typename AssignType
283 >
284 inline void test_big_2d_with(AssignType const& x1, AssignType const& y1,
285 AssignType const& x2, AssignType const& y2,
286 AssignType const& zero)
287 {
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
291 <
292 CalculationType
293 > pythagoras_pb_type;
294
295 pythagoras_pb_type pythagoras_pb;
296 typedef typename bg::strategy::distance::services::return_type
297 <
298 pythagoras_pb_type, point_type, box_type
299 >::type return_type;
300
301
302 point_type p;
303 box_type b;
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);
307
308 BOOST_CHECK_CLOSE(d, return_type(1076554.5485833955678294387789057), 0.001);
309 }
310
311 template <typename CoordinateType, typename CalculationType>
312 inline void test_big_2d()
313 {
314 test_big_2d_with<CoordinateType, CalculationType>
315 (123456.78900001, 234567.89100001,
316 987654.32100001, 876543.21900001,
317 0.0);
318 }
319
320 template <typename CoordinateType, typename CalculationType>
321 inline void test_big_2d_string()
322 {
323 test_big_2d_with<CoordinateType, CalculationType>
324 ("123456.78900001", "234567.89100001",
325 "987654.32100001", "876543.21900001",
326 "0.0000000000000");
327 }
328
329 template <typename CoordinateType>
330 inline void test_integer(bool check_types)
331 {
332 typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type;
333 typedef bg::model::box<point_type> box_type;
334
335 point_type p;
336 box_type b;
337 bg::assign_values(b, 0, 0, 12345678, 23456789);
338 bg::assign_values(p, 98765432, 87654321);
339
340 typedef bg::strategy::distance::pythagoras_point_box<> pythagoras_type;
341 typedef typename bg::strategy::distance::services::comparable_type
342 <
343 pythagoras_type
344 >::type comparable_type;
345
346 typedef typename bg::strategy::distance::services::return_type
347 <
348 pythagoras_type, point_type, box_type
349 >::type distance_type;
350 typedef typename bg::strategy::distance::services::return_type
351 <
352 comparable_type, point_type, box_type
353 >::type cdistance_type;
354
355 pythagoras_type pythagoras;
356 distance_type distance = pythagoras.apply(p, b);
357 BOOST_CHECK_CLOSE(distance, 107655455.02347542, 0.001);
358
359 comparable_type comparable;
360 cdistance_type cdistance = comparable.apply(p, b);
361 BOOST_CHECK_EQUAL(cdistance, 11589696996311540.0);
362
363 distance_type distance2 = sqrt(distance_type(cdistance));
364 BOOST_CHECK_CLOSE(distance, distance2, 0.001);
365
366 if (check_types)
367 {
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));
370 }
371 }
372
373 template <typename P1, typename P2>
374 void test_all_3d()
375 {
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> >();
379
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> >();
383 }
384
385 template <typename P>
386 void test_all_3d()
387 {
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> >();
395 }
396
397 template <typename P, typename Strategy>
398 void time_compare_s(int const n)
399 {
400 typedef bg::model::box<P> box_type;
401
402 boost::timer t;
403 P p;
404 box_type b;
405 bg::assign_values(b, 0, 0, 1, 1);
406 bg::assign_values(p, 2, 2);
407 Strategy strategy;
408 typename bg::strategy::distance::services::return_type
409 <
410 Strategy, P, box_type
411 >::type s = 0;
412 for (int i = 0; i < n; i++)
413 {
414 for (int j = 0; j < n; j++)
415 {
416 bg::set<0>(p, bg::get<0>(p) + 0.001);
417 s += strategy.apply(p, b);
418 }
419 }
420 std::cout << "s: " << s << " t: " << t.elapsed() << std::endl;
421 }
422
423 template <typename P>
424 inline void time_compare(int const n)
425 {
426 time_compare_s<P, bg::strategy::distance::pythagoras_point_box<> >(n);
427 time_compare_s
428 <
429 P, bg::strategy::distance::comparable::pythagoras_point_box<>
430 >(n);
431 }
432
433
434
435
436 BOOST_AUTO_TEST_CASE( test_integer_all )
437 {
438 test_integer<int>(true);
439 test_integer<boost::long_long_type>(true);
440 test_integer<double>(false);
441 }
442
443
444 BOOST_AUTO_TEST_CASE( test_3d_all )
445 {
446 test_all_3d<int[3]>();
447 test_all_3d<float[3]>();
448 test_all_3d<double[3]>();
449
450 test_all_3d<test::test_point>();
451
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> >();
455 }
456
457
458 BOOST_AUTO_TEST_CASE( test_big_2d_all )
459 {
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>();
464 }
465
466
467 BOOST_AUTO_TEST_CASE( test_services_all )
468 {
469 test_services
470 <
471 bg::model::point<float, 3, bg::cs::cartesian>,
472 bg::model::box<double[3]>,
473 long double
474 >();
475 test_services<double[3], bg::model::box<test::test_point>, float>();
476
477 // reverse the point and box types
478 test_services
479 <
480 double[3],
481 bg::model::box<bg::model::point<float, 3, bg::cs::cartesian> >,
482 long double
483 >();
484 test_services<test::test_point, bg::model::box<double[3]>, float>();
485 }
486
487
488 BOOST_AUTO_TEST_CASE( test_time_compare )
489 {
490 // TODO move this to another non-unit test
491 // time_compare<bg::model::point<double, 2, bg::cs::cartesian> >(10000);
492 }
493