]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/test/algorithms/envelope_expand/expand_on_spheroid.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / geometry / test / algorithms / envelope_expand / expand_on_spheroid.cpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3
4 // Copyright (c) 2015-2021, Oracle and/or its affiliates.
5 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
6 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
7 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
8
9 // Licensed under the Boost Software License version 1.0.
10 // http://www.boost.org/users/license.html
11
12 #ifndef BOOST_TEST_MODULE
13 #define BOOST_TEST_MODULE test_expand_on_spheroid
14 #endif
15
16 #include <boost/test/included/unit_test.hpp>
17
18 #include <cstddef>
19 #include <iostream>
20 #include <string>
21
22 #include <geometry_test_common.hpp>
23 #include <from_wkt.hpp>
24
25 #include <boost/geometry/algorithms/assign.hpp>
26 #include <boost/geometry/algorithms/envelope.hpp>
27 #include <boost/geometry/algorithms/expand.hpp>
28 #include <boost/geometry/algorithms/make.hpp>
29 #include <boost/geometry/algorithms/transform.hpp>
30
31 #include <boost/geometry/core/coordinate_dimension.hpp>
32 #include <boost/geometry/core/tag.hpp>
33 #include <boost/geometry/core/tags.hpp>
34
35 #include <boost/geometry/geometries/geometries.hpp>
36
37 #include <boost/geometry/io/dsv/write.hpp>
38 #include <boost/geometry/io/wkt/wkt.hpp>
39
40 #include <boost/geometry/util/condition.hpp>
41
42 #include <boost/geometry/views/detail/indexed_point_view.hpp>
43
44 #include "test_envelope_expand_on_spheroid.hpp"
45
46
47 class test_expand_on_spheroid
48 {
49 private:
50 template
51 <
52 typename Geometry,
53 typename Tag = typename bg::tag<Geometry>::type
54 >
55 struct write_geometry
56 {
57 template <typename OutputStream>
58 static inline OutputStream& apply(OutputStream& os,
59 Geometry const& geometry)
60 {
61 os << bg::wkt(geometry);
62 return os;
63 }
64 };
65
66 template <typename Segment>
67 struct write_geometry<Segment, bg::segment_tag>
68 {
69 template <typename OutputStream>
70 static inline OutputStream& apply(OutputStream& os,
71 Segment const& segment)
72 {
73 os << "SEGMENT" << bg::dsv(segment);
74 return os;
75 }
76 };
77
78 template <typename Box>
79 struct write_geometry<Box, bg::box_tag>
80 {
81 template <typename OutputStream>
82 static inline OutputStream& apply(OutputStream& os,
83 Box const& box)
84 {
85 os << "BOX" << bg::dsv(box);
86 return os;
87 }
88 };
89
90 template <typename Box, typename Geometry>
91 static inline void check_message(bool same_boxes,
92 std::string const& case_id,
93 std::string const& units_str,
94 Box const& box,
95 Geometry const& geometry,
96 bool expected_are_different,
97 Box const& expected1,
98 Box const& expected2,
99 Box const& detected)
100 {
101 std::ostringstream stream;
102 stream << "case ID: " << case_id << ", "
103 << "MBR units: " << units_str << "; "
104 << "input box: BOX" << bg::dsv(box) << ", "
105 << "geometry: ";
106
107 write_geometry<Geometry>::apply(stream, geometry);
108
109 stream << std::setprecision(17);
110
111 stream << "; " << "expected: " << bg::dsv(expected1);
112
113 if (expected_are_different)
114 {
115 stream << " or: " << bg::dsv(expected2);
116 }
117 stream << ", " << "detected: " << bg::dsv(detected);
118
119 BOOST_CHECK_MESSAGE(same_boxes, stream.str());
120 }
121
122
123 template <bool Reverse = false, typename = void>
124 struct basic_tester
125 {
126 template <typename Box, typename Geometry>
127 static inline void base_test(std::string const& case_id,
128 Box const& box,
129 Geometry const& geometry,
130 double lon_min1, double lat_min1,
131 double height_min1,
132 double lon_max1, double lat_max1,
133 double height_max1,
134 double lon_min2, double lat_min2,
135 double height_min2,
136 double lon_max2, double lat_max2,
137 double height_max2,
138 double tolerance)
139 {
140 typedef typename bg::coordinate_system
141 <
142 Box
143 >::type::units box_units_type;
144
145 std::string const units_str = units2string<box_units_type>();
146
147 Box detected;
148 bg::convert(box, detected);
149 bg::expand(detected, geometry);
150
151 bool expected_are_different =
152 (lon_min1 != lon_min2) || (lat_min1 != lat_min2)
153 || (lon_max1 != lon_max2) || (lat_max1 != lat_max2);
154
155 Box expected1;
156 initialize_box<Box>::apply(expected1,
157 lon_min1, lat_min1, height_min1,
158 lon_max1, lat_max1, height_max1);
159
160 Box expected2;
161 initialize_box<Box>::apply(expected2,
162 lon_min2, lat_min2, height_min2,
163 lon_max2, lat_max2, height_max2);
164
165 #ifdef BOOST_GEOMETRY_TEST_DEBUG
166 std::cout << "input box: BOX" << bg::dsv(box) << std::endl;
167
168 std::cout << "geometry: ";
169 write_geometry<Geometry>::apply(std::cout, geometry);
170
171 std::cout << std::endl
172 << "MBR units: " << units_str
173 << std::endl
174 << "expected: " << bg::dsv(expected1);
175
176 if (expected_are_different)
177 {
178 std::cout << " or: " << bg::dsv(expected2);
179 }
180
181 std::cout << std::endl
182 << "detected: " << bg::dsv(detected)
183 << std::endl << std::endl;
184 #endif
185 bool same_boxes
186 = box_equals<Box>::apply(detected, expected1, tolerance);
187
188 if (expected_are_different)
189 {
190 same_boxes = same_boxes
191 || box_equals<Box>::apply(detected, expected2, tolerance);
192 }
193
194 check_message(same_boxes, case_id, units_str,
195 box, geometry, expected_are_different,
196 expected1, expected2, detected);
197 }
198
199 template <typename Box, typename Geometry>
200 static inline void apply(std::string const& case_id,
201 Box const& box,
202 Geometry const& geometry,
203 double lon_min1, double lat_min1,
204 double height_min1,
205 double lon_max1, double lat_max1,
206 double height_max1,
207 double lon_min2, double lat_min2,
208 double height_min2,
209 double lon_max2, double lat_max2,
210 double height_max2,
211 double tolerance)
212 {
213 typedef other_system_info
214 <
215 typename bg::coordinate_system<Box>::type
216 > other;
217
218 typedef bg::model::box
219 <
220 bg::model::point
221 <
222 typename bg::coordinate_type<Box>::type,
223 bg::dimension<Box>::value,
224 typename other::type
225 >
226 > other_mbr_type;
227
228 #ifdef BOOST_GEOMETRY_TEST_DEBUG
229 std::cout << "case ID: " << case_id
230 << std::endl << std::endl;
231 #endif
232
233 base_test(case_id, box, geometry,
234 lon_min1, lat_min1, height_min1,
235 lon_max1, lat_max1, height_max1,
236 lon_min2, lat_min2, height_min2,
237 lon_max2, lat_max2, height_max2,
238 tolerance);
239
240 other_mbr_type other_box;
241
242 //if the input box is the special one made from make_inverse
243 //do not convert coordinates
244 if (!is_inverse_spheroidal_coordinates(box))
245 {
246 bg::detail::indexed_point_view<Box const, 0> p_min(box);
247 bg::detail::indexed_point_view<Box const, 1> p_max(box);
248
249 bg::detail::indexed_point_view
250 <
251 other_mbr_type, 0
252 > other_min(other_box);
253
254 bg::detail::indexed_point_view
255 <
256 other_mbr_type, 1
257 > other_max(other_box);
258
259 bg::transform(p_min, other_min);
260 bg::transform(p_max, other_max);
261 } else {
262 bg::set<bg::min_corner, 0>(other_box, bg::get<0, 0>(box));
263 bg::set<bg::min_corner, 1>(other_box, bg::get<0, 1>(box));
264 bg::set<bg::max_corner, 0>(other_box, bg::get<1, 0>(box));
265 bg::set<bg::max_corner, 1>(other_box, bg::get<1, 1>(box));
266 }
267
268 base_test(case_id, other_box, geometry,
269 other::convert(lon_min1),
270 other::convert(lat_min1),
271 height_min1,
272 other::convert(lon_max1),
273 other::convert(lat_max1),
274 height_max1,
275 other::convert(lon_min2),
276 other::convert(lat_min2),
277 height_min2,
278 other::convert(lon_max2),
279 other::convert(lat_max2),
280 height_max2,
281 tolerance);
282
283 #ifdef BOOST_GEOMETRY_TEST_DEBUG
284 std::cout << "=================="
285 << std::endl << std::endl;
286 #endif
287 }
288 };
289
290 template <typename Dummy>
291 struct basic_tester<true, Dummy>
292 {
293 template <typename Box, typename Geometry>
294 static inline void apply(std::string const& case_id,
295 Box const& box,
296 Geometry const& geometry,
297 double lon_min1, double lat_min1,
298 double height_min1,
299 double lon_max1, double lat_max1,
300 double height_max1,
301 double lon_min2, double lat_min2,
302 double height_min2,
303 double lon_max2, double lat_max2,
304 double height_max2,
305 double tolerance)
306 {
307 basic_tester
308 <
309 false
310 >::apply(case_id, box, geometry,
311 lon_min1, lat_min1, height_min1,
312 lon_max1, lat_max1, height_max1,
313 lon_min2, lat_min2, height_min1,
314 lon_max2, lat_max2, height_max2,
315 tolerance);
316
317 std::string case_id_r = case_id + "[R]";
318
319 basic_tester
320 <
321 false
322 >::apply(case_id_r, geometry, box,
323 lon_min1, lat_min1, height_min1,
324 lon_max1, lat_max1, height_max1,
325 lon_min2, lat_min2, height_min2,
326 lon_max2, lat_max2, height_max2,
327 tolerance);
328 }
329 };
330
331
332 public:
333 template <typename Box, typename Geometry>
334 static inline void apply(std::string const& case_id,
335 Box const& box,
336 Geometry const& geometry,
337 double lon_min1, double lat_min1, double height_min1,
338 double lon_max1, double lat_max1, double height_max1,
339 double lon_min2, double lat_min2, double height_min2,
340 double lon_max2, double lat_max2, double height_max2,
341 double tolerance = std::numeric_limits<double>::epsilon())
342 {
343
344 basic_tester
345 <
346 std::is_same
347 <
348 typename bg::tag<Geometry>::type,
349 bg::box_tag
350 >::value
351 >::apply(case_id, box, geometry,
352 lon_min1, lat_min1, height_min1,
353 lon_max1, lat_max1, height_max1,
354 lon_min2, lat_min2, height_min2,
355 lon_max2, lat_max2, height_max2,
356 tolerance);
357 }
358
359 template <typename Box, typename Geometry>
360 static inline void apply(std::string const& case_id,
361 Box const& box,
362 Geometry const& geometry,
363 double lon_min1, double lat_min1,
364 double lon_max1, double lat_max1,
365 double lon_min2, double lat_min2,
366 double lon_max2, double lat_max2,
367 double tolerance = std::numeric_limits<double>::epsilon())
368 {
369 apply(case_id, box, geometry,
370 lon_min1, lat_min1, 0, lon_max1, lat_max1, 0,
371 lon_min2, lat_min2, 0, lon_max2, lat_max2, 0,
372 tolerance);
373 }
374
375 template <typename Box, typename Geometry>
376 static inline void apply(std::string const& case_id,
377 Box const& box,
378 Geometry const& geometry,
379 double lon_min, double lat_min,
380 double lon_max, double lat_max,
381 double tolerance = std::numeric_limits<double>::epsilon())
382 {
383 apply(case_id, box, geometry,
384 lon_min, lat_min, 0, lon_max, lat_max, 0,
385 lon_min, lat_min, 0, lon_max, lat_max, 0,
386 tolerance);
387 }
388
389 template <typename Box, typename Geometry>
390 static inline void apply(std::string const& case_id,
391 Box const& box,
392 Geometry const& geometry,
393 double lon_min, double lat_min, double height_min,
394 double lon_max, double lat_max, double height_max,
395 double tolerance = std::numeric_limits<double>::epsilon())
396 {
397 apply(case_id, box, geometry,
398 lon_min, lat_min, height_min, lon_max, lat_max, height_max,
399 lon_min, lat_min, height_min, lon_max, lat_max, height_max,
400 tolerance);
401 }
402 };
403
404
405 template <typename CoordinateSystem>
406 void test_expand_point()
407 {
408 typedef bg::model::point<double, 2, CoordinateSystem> point_type;
409 typedef bg::model::box<point_type> B;
410 typedef point_type G;
411 typedef test_expand_on_spheroid tester;
412
413 tester::apply("p01",
414 from_wkt<B>("BOX(0 0,5 5)"),
415 from_wkt<G>("POINT(10 10)"),
416 0, 0, 10, 10);
417
418 tester::apply("p02",
419 from_wkt<B>("BOX(0 0,5 5)"),
420 from_wkt<G>("POINT(370 10)"),
421 0, 0, 10, 10);
422
423 tester::apply("p03",
424 from_wkt<B>("BOX(10 10,10 10)"),
425 from_wkt<G>("POINT(20 20)"),
426 10, 10, 20, 20);
427
428 tester::apply("p04",
429 from_wkt<B>("BOX(10 10,10 10)"),
430 from_wkt<G>("POINT(10 20)"),
431 10, 10, 10, 20);
432
433 // there are two possible valid longitude ranges:
434 // [10, 190] and [-170, 10]
435 tester::apply("p05",
436 from_wkt<B>("BOX(10 10,10 10)"),
437 from_wkt<G>("POINT(190 20)"),
438 10, 10, 190, 20);
439
440 // there are two possible valid longitude ranges:
441 // [10, 190] and [-170, 10]
442 tester::apply("p05a",
443 from_wkt<B>("BOX(10 10,10 10)"),
444 from_wkt<G>("POINT(-170 20)"),
445 10, 10, 190, 20,
446 -170, 10, 10, 20);
447
448 tester::apply("p06",
449 from_wkt<B>("BOX(170 10,175 20)"),
450 from_wkt<G>("POINT(-170 15)"),
451 170, 10, 190, 20);
452
453 tester::apply("p06a",
454 from_wkt<B>("BOX(170 10,175 20)"),
455 from_wkt<G>("POINT(-170 -6)"),
456 170, -6, 190, 20);
457
458 tester::apply("p06b",
459 from_wkt<B>("BOX(170 10,175 20)"),
460 from_wkt<G>("POINT(-170 36)"),
461 170, 10, 190, 36);
462
463 // point is inside box
464 tester::apply("p07",
465 from_wkt<B>("BOX(-30 -45,60 55)"),
466 from_wkt<G>("POINT(0 0)"),
467 -30, -45, 60, 55);
468
469 // point is inside box
470 tester::apply("p07a",
471 from_wkt<B>("BOX(-30 -45,60 55)"),
472 from_wkt<G>("POINT(360 0)"),
473 -30, -45, 60, 55);
474
475 tester::apply("p08",
476 from_wkt<B>("BOX(-100 -45,-90 55)"),
477 from_wkt<G>("POINT(80 60)"),
478 -100, -45, 80, 60);
479
480 tester::apply("p09",
481 from_wkt<B>("BOX(-100 -45,-90 55)"),
482 from_wkt<G>("POINT(170 60)"),
483 170, -45, 270, 60);
484
485 // point is north pole
486 tester::apply("p10",
487 from_wkt<B>("BOX(-100 -45,-90 55)"),
488 from_wkt<G>("POINT(-80 90)"),
489 -100, -45, -90, 90);
490
491 // point is north pole
492 tester::apply("p10a",
493 from_wkt<B>("BOX(-100 -45,-90 55)"),
494 from_wkt<G>("POINT(170 90)"),
495 -100, -45, -90, 90);
496
497 tester::apply("p10b",
498 from_wkt<B>("BOX(-100 -45,-90 55)"),
499 from_wkt<G>("POINT(170 80)"),
500 170, -45, 270, 80);
501
502 // box is north pole
503 tester::apply("p11",
504 from_wkt<B>("BOX(10 90,20 90)"),
505 from_wkt<G>("POINT(15 89)"),
506 15, 89, 15, 90);
507
508 // box is south pole
509 tester::apply("p11a",
510 from_wkt<B>("BOX(10 -90,20 -90)"),
511 from_wkt<G>("POINT(15 89)"),
512 15, -90, 15, 89);
513
514 // point is south pole
515 tester::apply("p12",
516 from_wkt<B>("BOX(10 80,20 85)"),
517 from_wkt<G>("POINT(15 -90)"),
518 10, -90, 20, 85);
519
520 // point is south pole
521 tester::apply("p12a",
522 from_wkt<B>("BOX(10 80,20 85)"),
523 from_wkt<G>("POINT(25 -90)"),
524 10, -90, 20, 85);
525
526 // box is north pole and point is south pole
527 tester::apply("p13",
528 from_wkt<B>("BOX(10 90,20 90)"),
529 from_wkt<G>("POINT(25 -90)"),
530 0, -90, 0, 90);
531
532 // box contains north pole and point is south pole
533 tester::apply("p14",
534 from_wkt<B>("BOX(10 80,20 90)"),
535 from_wkt<G>("POINT(25 -90)"),
536 10, -90, 20, 90);
537
538 // box contains south pole and point is north pole
539 tester::apply("p15",
540 from_wkt<B>("BOX(10 -90,30 0)"),
541 from_wkt<G>("POINT(25 90)"),
542 10, -90, 30, 90);
543
544 // box and point are north pole
545 tester::apply("p15",
546 from_wkt<B>("BOX(10 90,20 90)"),
547 from_wkt<G>("POINT(25 90)"),
548 0, 90, 0, 90);
549
550 // box and point are south pole
551 tester::apply("p16",
552 from_wkt<B>("BOX(10 -90,20 -90)"),
553 from_wkt<G>("POINT(-25 -90)"),
554 0, -90, 0, -90);
555
556 // box contains both poles
557 tester::apply("p17",
558 from_wkt<B>("BOX(10 -90,10 90)"),
559 from_wkt<G>("POINT(10 80)"),
560 10, -90, 10, 90);
561
562 // box contains both poles
563 tester::apply("p17a",
564 from_wkt<B>("BOX(10 -90,10 90)"),
565 from_wkt<G>("POINT(25 80)"),
566 10, -90, 25, 90);
567
568 // box contains both poles
569 tester::apply("p18",
570 from_wkt<B>("BOX(10 -90,100 90)"),
571 from_wkt<G>("POINT(25 80)"),
572 10, -90, 100, 90);
573
574 // box contains both poles
575 tester::apply("p18a",
576 from_wkt<B>("BOX(10 -90,100 90)"),
577 from_wkt<G>("POINT(-175 80)"),
578 10, -90, 185, 90);
579
580 // box contains both poles
581 tester::apply("p18b",
582 from_wkt<B>("BOX(10 -90,100 90)"),
583 from_wkt<G>("POINT(-95 80)"),
584 -95, -90, 100, 90);
585
586 // box contains both poles and point is north pole
587 tester::apply("p19",
588 from_wkt<B>("BOX(10 -90,100 90)"),
589 from_wkt<G>("POINT(-95 90)"),
590 10, -90, 100, 90);
591
592 // box contains both poles and point is south pole
593 tester::apply("p20",
594 from_wkt<B>("BOX(10 -90,100 90)"),
595 from_wkt<G>("POINT(-95 -90)"),
596 10, -90, 100, 90);
597 }
598
599 BOOST_AUTO_TEST_CASE( expand_point )
600 {
601 test_expand_point<bg::cs::spherical_equatorial<bg::degree> >();
602 test_expand_point<bg::cs::geographic<bg::degree> >();
603 }
604
605
606 template <typename CoordinateSystem>
607 void test_expand_point_with_height()
608 {
609 typedef bg::model::point<double, 3, CoordinateSystem> point_type;
610 typedef bg::model::box<point_type> B;
611 typedef point_type G;
612 typedef test_expand_on_spheroid tester;
613
614 // deactivate this for now
615 tester::apply("ph01",
616 from_wkt<B>("BOX(0 0 20,5 5 100)"),
617 from_wkt<G>("POINT(10 10 80)"),
618 0, 0, 20, 10, 10, 100);
619
620 tester::apply("ph02",
621 from_wkt<B>("BOX(0 0 20,5 5 100)"),
622 from_wkt<G>("POINT(10 10 120)"),
623 0, 0, 20, 10, 10, 120);
624
625 tester::apply("ph03",
626 from_wkt<B>("BOX(0 0 20,5 5 100)"),
627 from_wkt<G>("POINT(10 10 5)"),
628 0, 0, 5, 10, 10, 100);
629 }
630
631 BOOST_AUTO_TEST_CASE( expand_point_with_height )
632 {
633 test_expand_point_with_height<bg::cs::spherical_equatorial<bg::degree> >();
634 test_expand_point_with_height<bg::cs::geographic<bg::degree> >();
635 }
636
637
638 BOOST_AUTO_TEST_CASE( expand_segment_sphere )
639 {
640 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
641 typedef bg::model::point<double, 2, coordinate_system_type> point_type;
642 typedef bg::model::box<point_type> B;
643 typedef bg::model::segment<point_type> G;
644 typedef test_expand_on_spheroid tester;
645
646 tester::apply("s01",
647 from_wkt<B>("BOX(20 20,50 50)"),
648 from_wkt<G>("SEGMENT(10 10,40 40)"),
649 10, 10, 50, 50);
650
651 tester::apply("s02",
652 from_wkt<B>("BOX(20 20,50 50)"),
653 from_wkt<G>("SEGMENT(10 10,40 10)"),
654 10, 10, 50, 50);
655
656 tester::apply("s03",
657 from_wkt<B>("BOX(5 5,50 10)"),
658 from_wkt<G>("SEGMENT(40 10,10 10)"),
659 5, 5, 50, 10.34527004614999,
660 4.0 * std::numeric_limits<double>::epsilon());
661
662 // segment ending at the north pole
663 tester::apply("s04",
664 from_wkt<B>("BOX(5 15,50 50)"),
665 from_wkt<G>("SEGMENT(40 45,80 90)"),
666 5, 15, 50, 90);
667
668 // segment ending at the north pole
669 tester::apply("s04a",
670 from_wkt<B>("BOX(5 15,30 30)"),
671 from_wkt<G>("SEGMENT(40 45,80 90)"),
672 5, 15, 40, 90);
673
674 // segment starting at the north pole
675 tester::apply("s05",
676 from_wkt<B>("BOX(5 15,50 50)"),
677 from_wkt<G>("SEGMENT(80 90,40 45)"),
678 5, 15, 50, 90);
679
680 // segment starting at the north pole
681 tester::apply("s05a",
682 from_wkt<B>("BOX(5 15,30 30)"),
683 from_wkt<G>("SEGMENT(80 90,40 45)"),
684 5, 15, 40, 90);
685
686 // segment passing through the south pole
687 tester::apply("s06",
688 from_wkt<B>("BOX(5 15,30 40)"),
689 from_wkt<G>("SEGMENT(-170 -45,10 -30)"),
690 -170, -90, 30, 40);
691
692 // segment degenerating to the north pole
693 tester::apply("s07",
694 from_wkt<B>("BOX(5 15,30 40)"),
695 from_wkt<G>("SEGMENT(10 90,20 90)"),
696 5, 15, 30, 90);
697
698 // segment degenerating to the south pole
699 tester::apply("s08",
700 from_wkt<B>("BOX(5 15,30 40)"),
701 from_wkt<G>("SEGMENT(10 -90,20 -90)"),
702 5, -90, 30, 40);
703
704 // box degenerating to the south pole
705 tester::apply("s09",
706 from_wkt<B>("BOX(10 -90,30 -90)"),
707 from_wkt<G>("SEGMENT(10 -30,100 45)"),
708 10, -90, 100, 45);
709
710 // box degenerating to the south pole
711 tester::apply("s09a",
712 from_wkt<B>("BOX(10 -90,130 -90)"),
713 from_wkt<G>("SEGMENT(10 -30,100 45)"),
714 10, -90, 100, 45);
715 }
716
717 BOOST_AUTO_TEST_CASE( expand_segment_spherical_polar )
718 {
719 typedef bg::cs::spherical<bg::degree> coordinate_system_type;
720 typedef bg::model::point<double, 2, coordinate_system_type> point_type;
721 typedef bg::model::box<point_type> B;
722 typedef bg::model::segment<point_type> G;
723 typedef test_expand_on_spheroid tester;
724
725 tester::apply("s02",
726 from_wkt<B>("BOX(20 20,50 50)"),
727 from_wkt<G>("SEGMENT(10 10,40 20)"),
728 10, 10, 50, 50);
729
730 // segment ending at the north pole
731 tester::apply("s04",
732 from_wkt<B>("BOX(5 15,50 50)"),
733 from_wkt<G>("SEGMENT(40 45,80 0)"),
734 5, 0, 50, 50);
735 }
736
737 BOOST_AUTO_TEST_CASE( expand_segment_spheroid )
738 {
739 typedef bg::cs::geographic<bg::degree> coordinate_system_type;
740 typedef bg::model::point<double, 2, coordinate_system_type> point_type;
741 typedef bg::model::box<point_type> B;
742 typedef bg::model::segment<point_type> G;
743 typedef test_expand_on_spheroid tester;
744
745 tester::apply("s01",
746 from_wkt<B>("BOX(20 20,50 50)"),
747 from_wkt<G>("SEGMENT(10 10,40 40)"),
748 10, 10, 50, 50);
749
750 tester::apply("s02",
751 from_wkt<B>("BOX(20 20,50 50)"),
752 from_wkt<G>("SEGMENT(10 10,40 10)"),
753 10, 10, 50, 50);
754
755 tester::apply("s03",
756 from_wkt<B>("BOX(5 5,50 10)"),
757 from_wkt<G>("SEGMENT(40 10,10 10)"),
758 5, 5, 50, 10.347587099602029,
759 4.0 * std::numeric_limits<double>::epsilon());
760
761 // segment ending at the north pole
762 tester::apply("s04",
763 from_wkt<B>("BOX(5 15,50 50)"),
764 from_wkt<G>("SEGMENT(40 45,80 90)"),
765 5, 15, 50, 90);
766
767 // segment ending at the north pole
768 tester::apply("s04a",
769 from_wkt<B>("BOX(5 15,30 30)"),
770 from_wkt<G>("SEGMENT(40 45,80 90)"),
771 5, 15, 40, 90);
772
773 // segment starting at the north pole
774 tester::apply("s05",
775 from_wkt<B>("BOX(5 15,50 50)"),
776 from_wkt<G>("SEGMENT(80 90,40 45)"),
777 5, 15, 50, 90);
778
779 // segment starting at the north pole
780 tester::apply("s05a",
781 from_wkt<B>("BOX(5 15,30 30)"),
782 from_wkt<G>("SEGMENT(80 90,40 45)"),
783 5, 15, 40, 90);
784
785 // segment passing through the south pole
786 tester::apply("s06",
787 from_wkt<B>("BOX(5 15,30 40)"),
788 from_wkt<G>("SEGMENT(-170 -45,10 -30)"),
789 -170, -90, 30, 40);
790
791 // segment degenerating to the north pole
792 tester::apply("s07",
793 from_wkt<B>("BOX(5 15,30 40)"),
794 from_wkt<G>("SEGMENT(10 90,20 90)"),
795 5, 15, 30, 90);
796
797 // segment degenerating to the south pole
798 tester::apply("s08",
799 from_wkt<B>("BOX(5 15,30 40)"),
800 from_wkt<G>("SEGMENT(10 -90,20 -90)"),
801 5, -90, 30, 40);
802
803 // box degenerating to the south pole
804 tester::apply("s09",
805 from_wkt<B>("BOX(10 -90,30 -90)"),
806 from_wkt<G>("SEGMENT(10 -30,100 45)"),
807 10, -90, 100, 45);
808
809 // box degenerating to the south pole
810 tester::apply("s09a",
811 from_wkt<B>("BOX(10 -90,130 -90)"),
812 from_wkt<G>("SEGMENT(10 -30,100 45)"),
813 10, -90, 100, 45);
814 }
815
816 BOOST_AUTO_TEST_CASE( expand_segment_sphere_with_height )
817 {
818 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
819 typedef bg::model::point<double, 3, coordinate_system_type> point_type;
820 typedef bg::model::box<point_type> B;
821 typedef bg::model::segment<point_type> G;
822 typedef test_expand_on_spheroid tester;
823
824 tester::apply("sh01",
825 from_wkt<B>("BOX(20 20 100,50 50 1000)"),
826 from_wkt<G>("SEGMENT(10 10 150,40 40 500)"),
827 10, 10, 100, 50, 50, 1000);
828
829 tester::apply("sh02",
830 from_wkt<B>("BOX(20 20 100,50 50 1000)"),
831 from_wkt<G>("SEGMENT(10 10 60,40 40 1500)"),
832 10, 10, 60, 50, 50, 1500);
833
834 tester::apply("sh03",
835 from_wkt<B>("BOX(20 20 100,50 50 1000)"),
836 from_wkt<G>("SEGMENT(10 10 150,40 40 1500)"),
837 10, 10, 100, 50, 50, 1500);
838
839 tester::apply("sh04",
840 from_wkt<B>("BOX(20 20 100,50 50 1000)"),
841 from_wkt<G>("SEGMENT(10 10 60,40 40 800)"),
842 10, 10, 60, 50, 50, 1000);
843 }
844
845 BOOST_AUTO_TEST_CASE( expand_segment_spheroid_with_height )
846 {
847 typedef bg::cs::geographic<bg::degree> coordinate_system_type;
848 typedef bg::model::point<double, 3, coordinate_system_type> point_type;
849 typedef bg::model::box<point_type> B;
850 typedef bg::model::segment<point_type> G;
851 typedef test_expand_on_spheroid tester;
852
853 tester::apply("sh01",
854 from_wkt<B>("BOX(20 20 100,50 50 1000)"),
855 from_wkt<G>("SEGMENT(10 10 150,40 40 500)"),
856 10, 10, 100, 50, 50, 1000);
857
858 tester::apply("sh02",
859 from_wkt<B>("BOX(20 20 100,50 50 1000)"),
860 from_wkt<G>("SEGMENT(10 10 60,40 40 1500)"),
861 10, 10, 60, 50, 50, 1500);
862
863 tester::apply("sh03",
864 from_wkt<B>("BOX(20 20 100,50 50 1000)"),
865 from_wkt<G>("SEGMENT(10 10 150,40 40 1500)"),
866 10, 10, 100, 50, 50, 1500);
867
868 tester::apply("sh04",
869 from_wkt<B>("BOX(20 20 100,50 50 1000)"),
870 from_wkt<G>("SEGMENT(10 10 60,40 40 800)"),
871 10, 10, 60, 50, 50, 1000);
872 }
873
874
875 template <typename CoordinateSystem>
876 void test_expand_box()
877 {
878 typedef bg::model::point<double, 2, CoordinateSystem> point_type;
879 typedef bg::model::box<point_type> B;
880 typedef bg::model::box<point_type> G;
881 typedef test_expand_on_spheroid tester;
882
883 tester::apply("b01",
884 from_wkt<B>("BOX(11 11,19 19)"),
885 from_wkt<G>("BOX(10 10,20 20)"),
886 10, 10, 20, 20);
887
888 tester::apply("b02",
889 from_wkt<B>("BOX(11 11,29 29)"),
890 from_wkt<G>("BOX(10 10,20 20)"),
891 10, 10, 29, 29);
892
893 tester::apply("b03",
894 from_wkt<B>("BOX(21 21,29 29)"),
895 from_wkt<G>("BOX(10 10,20 20)"),
896 10, 10, 29, 29);
897
898 tester::apply("b04",
899 from_wkt<B>("BOX(150 -10,200 60)"),
900 from_wkt<G>("BOX(-175 -20,-150 55)"),
901 150, -20, 210, 60);
902
903 tester::apply("b04a",
904 from_wkt<B>("BOX(150 -10,200 60)"),
905 from_wkt<G>("BOX(-175 -20,-170 55)"),
906 150, -20, 200, 60);
907
908 tester::apply("b04b",
909 from_wkt<B>("BOX(150 -10,200 60)"),
910 from_wkt<G>("BOX(-175 -20,-140 55)"),
911 150, -20, 220, 60);
912
913 tester::apply("b05",
914 from_wkt<B>("BOX(150 -10,170 60)"),
915 from_wkt<G>("BOX(179 -20,535 55)"),
916 179, -20, 535, 60);
917
918 tester::apply("b06",
919 from_wkt<B>("BOX(150 -10,170 60)"),
920 from_wkt<G>("BOX(179 -20,520 55)"),
921 179, -20, 530, 60);
922
923 tester::apply("b07",
924 from_wkt<B>("BOX(-100 -10,170 60)"),
925 from_wkt<G>("BOX(100 -20,400 55)"),
926 -180, -20, 180, 60);
927
928 tester::apply("b08",
929 from_wkt<B>("BOX(-100 -10,100 60)"),
930 from_wkt<G>("BOX(150 -20,150 55)"),
931 -100, -20, 150, 60);
932
933 tester::apply("b09",
934 from_wkt<B>("BOX(100 -10,400 60)"),
935 from_wkt<G>("BOX(0 -20,0 55)"),
936 100, -20, 400, 60);
937
938 // this is a border case:
939 // there are two possible MBRs with longitude intervals:
940 // [100, 430] and [70, 400]
941 tester::apply("b10",
942 from_wkt<B>("BOX(100 -10,400 60)"),
943 from_wkt<G>("BOX(70 -20,70 55)"),
944 70, -20, 400, 60,
945 100, -20, 430, 60);
946
947 tester::apply("b10a",
948 from_wkt<B>("BOX(100 -10,400 60)"),
949 from_wkt<G>("BOX(71 -20,71 55)"),
950 71, -20, 400, 60);
951
952 tester::apply("b10b",
953 from_wkt<B>("BOX(100 -10,400 60)"),
954 from_wkt<G>("BOX(69 -20,69 55)"),
955 100, -20, 429, 60);
956
957 tester::apply("b11",
958 from_wkt<B>("BOX(-90 -10,-90 60)"),
959 from_wkt<G>("BOX(90 -20,90 55)"),
960 -90, -20, 90, 60);
961
962 // first box is the south pole
963 tester::apply("b12",
964 from_wkt<B>("BOX(-90 -90,80 -90)"),
965 from_wkt<G>("BOX(90 -20,90 55)"),
966 90, -90, 90, 55);
967
968 // first box is the south pole
969 tester::apply("b12a",
970 from_wkt<B>("BOX(-90 -90,80 -90)"),
971 from_wkt<G>("BOX(90 -20,130 55)"),
972 90, -90, 130, 55);
973
974 // first box is the north pole
975 tester::apply("b13",
976 from_wkt<B>("BOX(-90 90,80 90)"),
977 from_wkt<G>("BOX(90 -20,90 55)"),
978 90, -20, 90, 90);
979
980 // first box is the north pole
981 tester::apply("b13a",
982 from_wkt<B>("BOX(-90 90,80 90)"),
983 from_wkt<G>("BOX(90 -20,190 55)"),
984 90, -20, 190, 90);
985
986 // both boxes are the north pole
987 tester::apply("b14",
988 from_wkt<B>("BOX(-90 90,80 90)"),
989 from_wkt<G>("BOX(90 90,190 90)"),
990 0, 90, 0, 90);
991
992 // both boxes are the south pole
993 tester::apply("b15",
994 from_wkt<B>("BOX(-90 -90,80 -90)"),
995 from_wkt<G>("BOX(90 -90,190 -90)"),
996 0, -90, 0, -90);
997
998 // one box is the south pole and the other the north pole
999 tester::apply("b16",
1000 from_wkt<B>("BOX(-90 -90,80 -90)"),
1001 from_wkt<G>("BOX(90 90,190 90)"),
1002 0, -90, 0, 90);
1003
1004 // both boxes contain both poles but at different longitudes
1005 tester::apply("b17",
1006 from_wkt<B>("BOX(10 -90,10 90)"),
1007 from_wkt<G>("BOX(20 -90,20 90)"),
1008 10, -90, 20, 90);
1009
1010 // both boxes contain both poles but at different longitude ranges
1011 tester::apply("b17",
1012 from_wkt<B>("BOX(10 -90,20 90)"),
1013 from_wkt<G>("BOX(40 -90,60 90)"),
1014 10, -90, 60, 90);
1015
1016
1017 // first box is a band
1018 tester::apply("b18",
1019 from_wkt<B>("BOX(0 10,360 20)"),
1020 from_wkt<G>("BOX(-10 -40,20 10)"),
1021 -180, -40, 180, 20);
1022
1023 // first box contains south and north pole and is a band
1024 // (box covers the entire spheroid)
1025 tester::apply("b19",
1026 from_wkt<B>("BOX(0 -90,360 90)"),
1027 from_wkt<G>("BOX(-10 -40,20 10)"),
1028 -180, -90, 180, 90);
1029
1030 // the envelope of the two boxes is a band
1031 tester::apply("b20",
1032 from_wkt<B>("BOX(-180 -40,0 -30)"),
1033 from_wkt<G>("BOX(0 -10,180 50)"),
1034 -180, -40, 180, 50);
1035
1036 // the envelope of the two boxes is a band
1037 tester::apply("b20a",
1038 from_wkt<B>("BOX(-180 -40,0 -30)"),
1039 from_wkt<G>("BOX(0 -10,185 50)"),
1040 -180, -40, 180, 50);
1041
1042 // the envelope of the two boxes is a band
1043 tester::apply("b20b",
1044 from_wkt<B>("BOX(-179 -40,0 -30)"),
1045 from_wkt<G>("BOX(0 -10,185 50)"),
1046 -180, -40, 180, 50);
1047 }
1048
1049 BOOST_AUTO_TEST_CASE( expand_box )
1050 {
1051 test_expand_box<bg::cs::spherical_equatorial<bg::degree> >();
1052 test_expand_box<bg::cs::geographic<bg::degree> >();
1053 }
1054
1055 template <typename CoordinateSystem>
1056 void test_expand_make_inverse()
1057 {
1058 typedef bg::model::point<double, 2, CoordinateSystem> point_type;
1059 typedef bg::model::box<point_type> box_type;
1060 typedef bg::model::segment<point_type> segment_type;
1061 typedef test_expand_on_spheroid tester;
1062
1063 box_type box = bg::make_inverse<box_type>();
1064
1065 tester::apply("bi01",
1066 box,
1067 from_wkt<box_type>("BOX(10 10,20 20)"),
1068 10, 10, 20, 20);
1069 tester::apply("bi02",
1070 box,
1071 from_wkt<point_type>("POINT(0 0)"),
1072 0, 0, 0, 0);
1073 tester::apply("bi03",
1074 box,
1075 from_wkt<point_type>("POINT(5 0)"),
1076 5, 0, 5, 0);
1077 tester::apply("bi04",
1078 box,
1079 from_wkt<segment_type>("SEGMENT(5 0,0 5)"),
1080 0, 0, 5, 5);
1081 }
1082
1083 BOOST_AUTO_TEST_CASE( expand_make_inverse )
1084 {
1085 test_expand_make_inverse<bg::cs::spherical_equatorial<bg::degree> >();
1086 test_expand_make_inverse<bg::cs::geographic<bg::degree> >();
1087 }
1088
1089 template <typename CoordinateSystem>
1090 void test_expand_box_with_height()
1091 {
1092 typedef bg::model::point<double, 3, CoordinateSystem> point_type;
1093 typedef bg::model::box<point_type> B;
1094 typedef bg::model::box<point_type> G;
1095 typedef test_expand_on_spheroid tester;
1096
1097 tester::apply("bh01",
1098 from_wkt<B>("BOX(11 11 100,19 19 1000)"),
1099 from_wkt<G>("BOX(10 10 200,20 20 800)"),
1100 10, 10, 100, 20, 20, 1000);
1101
1102 tester::apply("bh02",
1103 from_wkt<B>("BOX(11 11 200,19 19 1000)"),
1104 from_wkt<G>("BOX(10 10 100,20 20 800)"),
1105 10, 10, 100, 20, 20, 1000);
1106
1107 tester::apply("bh03",
1108 from_wkt<B>("BOX(11 11 100,19 19 800)"),
1109 from_wkt<G>("BOX(10 10 200,20 20 1000)"),
1110 10, 10, 100, 20, 20, 1000);
1111
1112 tester::apply("bh04",
1113 from_wkt<B>("BOX(11 11 200,19 19 1000)"),
1114 from_wkt<G>("BOX(10 10 100,20 20 800)"),
1115 10, 10, 100, 20, 20, 1000);
1116 }
1117
1118 BOOST_AUTO_TEST_CASE( expand_box_with_height )
1119 {
1120 test_expand_box_with_height<bg::cs::spherical_equatorial<bg::degree> >();
1121 test_expand_box_with_height<bg::cs::geographic<bg::degree> >();
1122 }