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