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