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