]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/test/algorithms/envelope_expand/envelope_on_spheroid.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / geometry / test / algorithms / envelope_expand / envelope_on_spheroid.cpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3
4 // Copyright (c) 2015-2016, Oracle and/or its affiliates.
5
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
13 #ifndef BOOST_TEST_MODULE
14 #define BOOST_TEST_MODULE test_envelope_on_spheroid
15 #endif
16
17 #include <boost/test/included/unit_test.hpp>
18
19 #include <cstddef>
20 #include <limits>
21 #include <iostream>
22 #include <string>
23
24 #include <geometry_test_common.hpp>
25 #include <from_wkt.hpp>
26
27 #include <boost/numeric/conversion/bounds.hpp>
28 #include <boost/type_traits/is_same.hpp>
29
30 #include <boost/geometry/core/coordinate_dimension.hpp>
31 #include <boost/geometry/core/tag.hpp>
32 #include <boost/geometry/core/tags.hpp>
33
34 #include <boost/geometry/geometries/geometries.hpp>
35
36 #include <boost/geometry/util/condition.hpp>
37
38 #include <boost/geometry/io/dsv/write.hpp>
39 #include <boost/geometry/io/wkt/wkt.hpp>
40
41 #include <boost/geometry/algorithms/convert.hpp>
42 #include <boost/geometry/algorithms/envelope.hpp>
43 #include <boost/geometry/algorithms/reverse.hpp>
44
45 #include <boost/geometry/index/detail/algorithms/is_valid.hpp>
46
47 #include "test_envelope_expand_on_spheroid.hpp"
48
49
50 template <typename MBR>
51 class envelope_on_spheroid_basic_tester
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>
62 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>
74 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>
86 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 Geometry, typename Box>
95 static inline void check_message(bool same_boxes,
96 std::string const& case_id,
97 std::string const& units_str,
98 Geometry const& geometry,
99 Box const& expected,
100 Box const& detected)
101 {
102 std::ostringstream stream;
103 stream << "case ID: " << case_id << ", "
104 << "MBR units: " << units_str << "; "
105 << "geometry: ";
106
107 write_geometry<Geometry>::apply(stream, geometry);
108
109 stream << std::setprecision(17);
110
111 stream << "; " << "expected: " << bg::dsv(expected)
112 << ", " << "detected: " << bg::dsv(detected);
113
114 BOOST_CHECK_MESSAGE(same_boxes, stream.str());
115 }
116
117 template <typename Box, typename Geometry>
118 static inline void base_test(std::string const& case_id,
119 Geometry const& geometry,
120 double lon_min, double lat_min, double height_min,
121 double lon_max, double lat_max, double height_max,
122 double tolerance)
123 {
124 typedef typename bg::coordinate_system<Box>::type::units box_units_type;
125
126 std::string const units_str = units2string<box_units_type>();
127
128 Box detected;
129 bg::envelope(geometry, detected);
130
131 Box expected;
132 initialize_box<Box>::apply(expected,
133 lon_min, lat_min, height_min,
134 lon_max, lat_max, height_max);
135
136 #ifdef BOOST_GEOMETRY_TEST_DEBUG
137 std::cout << "geometry: ";
138 write_geometry<Geometry>::apply(std::cout, geometry);
139
140 std::cout << std::endl
141 << "MBR units: " << units_str
142 << std::endl
143 << "expected: " << bg::dsv(expected)
144 << std::endl
145 << "detected: " << bg::dsv(detected)
146 << std::endl << std::endl;
147 #endif
148
149 check_message(box_equals<Box>::apply(detected, expected, tolerance),
150 case_id, units_str,
151 geometry, expected, detected);
152
153 // if valid box is expected, check the validity
154 if (lon_min <= lon_max && lat_min <= lat_max && height_min <= height_max)
155 {
156 BOOST_CHECK_MESSAGE(bg::index::detail::is_valid(detected),
157 "Case ID: " << case_id << ", "
158 << "MBR units: " << units_str << "; "
159 << "Invalid Box: " << bg::dsv(detected));
160 }
161 }
162
163 public:
164 template <typename Geometry>
165 static inline void apply(std::string const& case_id,
166 Geometry const& geometry,
167 double lon_min, double lat_min, double height_min,
168 double lon_max, double lat_max, double height_max,
169 double tolerance)
170 {
171 typedef other_system_info
172 <
173 typename bg::coordinate_system<MBR>::type
174 > other;
175
176 typedef bg::model::box
177 <
178 bg::model::point
179 <
180 typename bg::coordinate_type<MBR>::type,
181 bg::dimension<MBR>::value,
182 typename other::type
183 >
184 > other_mbr_type;
185
186 #ifdef BOOST_GEOMETRY_TEST_DEBUG
187 std::cout << std::endl << std::endl;
188 std::cout << "case ID: " << case_id << std::endl << std::endl;
189 #endif
190
191 base_test<MBR>(case_id, geometry,
192 lon_min, lat_min, height_min,
193 lon_max, lat_max, height_max,
194 tolerance);
195
196 if (lon_max < lon_min)
197 {
198 // we are in the case were a special MBR is returned;
199 // makes no sense to change units
200 base_test<other_mbr_type>(case_id, geometry,
201 lon_min, lat_min, height_min,
202 lon_max, lat_max, height_max,
203 tolerance);
204 }
205 else
206 {
207 base_test<other_mbr_type>(case_id, geometry,
208 other::convert(lon_min),
209 other::convert(lat_min),
210 height_min,
211 other::convert(lon_max),
212 other::convert(lat_max),
213 height_max,
214 tolerance);
215 }
216 }
217 };
218
219
220 // test the reverse of a geometry if it is either linear or ring
221 template <typename Geometry, typename Tag = typename bg::tag<Geometry>::type>
222 struct test_reverse_geometry
223 {
224 static bool const is_linear =
225 boost::is_same<Tag, bg::segment_tag>::value
226 || boost::is_same<Tag, bg::linestring_tag>::value
227 || boost::is_same<Tag, bg::multi_linestring_tag>::value;
228
229 // currently disable rings
230 static bool const is_ring = false;
231 // static bool const is_ring = boost::is_same<Tag, bg::ring_tag>::value;
232
233 typedef typename boost::mpl::if_c
234 <
235 is_linear || is_ring,
236 boost::true_type,
237 boost::false_type
238 >::type type;
239
240 static bool const value = type::value;
241 };
242
243 template
244 <
245 typename Geometry,
246 typename MBR,
247 typename Tag = typename bg::tag<Geometry>::type,
248 bool TestReverse = test_reverse_geometry<Geometry>::value
249 >
250 struct test_envelope_on_spheroid
251 {
252 static inline void apply(std::string const& case_id,
253 Geometry const& geometry,
254 double lon_min1, double lat_min1, double height_min1,
255 double lon_max1, double lat_max1, double height_max1,
256 double lon_min2, double lat_min2, double height_min2,
257 double lon_max2, double lat_max2, double height_max2,
258 double tolerance = std::numeric_limits<double>::epsilon())
259 {
260 envelope_on_spheroid_basic_tester
261 <
262 MBR
263 >::apply(case_id, geometry,
264 lon_min1, lat_min1, height_min1,
265 lon_max1, lat_max1, height_max1,
266 tolerance);
267
268 if (BOOST_GEOMETRY_CONDITION(TestReverse))
269 {
270 std::string reversed_case_id = case_id + "-reverse";
271
272 Geometry reversed_geometry = geometry;
273 bg::reverse(reversed_geometry);
274 envelope_on_spheroid_basic_tester
275 <
276 MBR
277 >::apply(reversed_case_id, reversed_geometry,
278 lon_min2, lat_min2, height_min2,
279 lon_max2, lat_max2, height_max2,
280 tolerance);
281 }
282
283 #ifdef BOOST_GEOMETRY_TEST_DEBUG
284 std::cout << "=================="
285 << std::endl << std::endl;
286 #endif
287 }
288
289 static inline void apply(std::string const& case_id,
290 Geometry const& geometry,
291 double lon_min1, double lat_min1,
292 double lon_max1, double lat_max1,
293 double lon_min2, double lat_min2,
294 double lon_max2, double lat_max2,
295 double tolerance = std::numeric_limits<double>::epsilon())
296 {
297 apply(case_id, geometry,
298 lon_min1, lat_min1, 0, lon_max1, lat_max1, 0,
299 lon_min2, lat_min2, 0, lon_max2, lat_max2, 0,
300 tolerance);
301 }
302
303 static inline void apply(std::string const& case_id,
304 Geometry const& geometry,
305 double lon_min, double lat_min, double height_min,
306 double lon_max, double lat_max, double height_max,
307 double tolerance = std::numeric_limits<double>::epsilon())
308 {
309 apply(case_id, geometry,
310 lon_min, lat_min, height_min,
311 lon_max, lat_max, height_max,
312 lon_min, lat_min, height_min,
313 lon_max, lat_max, height_max,
314 tolerance);
315 }
316
317 static inline void apply(std::string const& case_id,
318 Geometry const& geometry,
319 double lon_min, double lat_min,
320 double lon_max, double lat_max,
321 double tolerance = std::numeric_limits<double>::epsilon())
322 {
323 apply(case_id, geometry,
324 lon_min, lat_min, 0, lon_max, lat_max, 0,
325 tolerance);
326 }
327 };
328
329
330 // special tester for rings
331 template <typename Geometry, typename MBR, bool TestReverse>
332 struct test_envelope_on_spheroid<Geometry, MBR, bg::ring_tag, TestReverse>
333 {
334 static inline void apply(std::string const& case_id,
335 Geometry const& geometry,
336 double lon_min1, double lat_min1,
337 double lon_max1, double lat_max1,
338 double lon_min2, double lat_min2,
339 double lon_max2, double lat_max2,
340 double tolerance = std::numeric_limits<double>::epsilon())
341 {
342 envelope_on_spheroid_basic_tester
343 <
344 MBR
345 >::apply(case_id, geometry,
346 lon_min1, lat_min1, lon_max1, lat_max1,
347 tolerance);
348
349 std::string ccw_case_id = case_id + "-2ccw";
350
351 bg::model::ring
352 <
353 typename bg::point_type<Geometry>::type, false
354 > ccw_ring;
355 bg::convert(geometry, ccw_ring);
356
357 envelope_on_spheroid_basic_tester
358 <
359 MBR
360 >::apply(ccw_case_id, ccw_ring,
361 lon_min2, lat_min2, lon_max2, lat_max2,
362 tolerance);
363
364 #ifdef BOOST_GEOMETRY_TEST_DEBUG
365 std::cout << "=================="
366 << std::endl << std::endl;
367 #endif
368 }
369
370 static inline void apply(std::string const& case_id,
371 Geometry const& geometry,
372 double lon_min, double lat_min,
373 double lon_max, double lat_max,
374 double tolerance = std::numeric_limits<double>::epsilon())
375 {
376 apply(case_id, geometry,
377 lon_min, lat_min, lon_max, lat_max,
378 lon_min, lat_min, lon_max, lat_max,
379 tolerance);
380 }
381 };
382
383
384 template <typename CoordinateSystem, typename Geometry>
385 void test_empty_geometry(std::string const& case_id, std::string const& wkt)
386 {
387 std::size_t const dim = bg::dimension<Geometry>::value;
388
389 typedef bg::model::point<double, dim, CoordinateSystem> point_type;
390 typedef bg::model::box<point_type> B;
391 typedef test_envelope_on_spheroid<Geometry, B> tester;
392
393 typedef typename bg::coordinate_type<Geometry>::type ct;
394 ct high_val = boost::numeric::bounds<ct>::highest();
395 ct low_val = boost::numeric::bounds<ct>::lowest();
396
397 if (BOOST_GEOMETRY_CONDITION(dim == 2))
398 {
399 tester::apply(case_id,
400 from_wkt<Geometry>(wkt),
401 high_val, high_val, low_val, low_val);
402 }
403 else
404 {
405 tester::apply(case_id,
406 from_wkt<Geometry>(wkt),
407 high_val, high_val, high_val, low_val, low_val, low_val);
408 }
409 }
410
411
412 template <typename CoordinateSystem>
413 void test_envelope_point()
414 {
415 typedef bg::model::point<double, 2, CoordinateSystem> point_type;
416 typedef point_type G;
417 typedef bg::model::box<point_type> B;
418 typedef test_envelope_on_spheroid<G, B> tester;
419
420 tester::apply("p01",
421 from_wkt<G>("POINT(10 10)"),
422 10, 10, 10, 10);
423
424 tester::apply("p02",
425 from_wkt<G>("POINT(370 10)"),
426 10, 10, 10, 10);
427
428 #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
429 tester::apply("p03",
430 from_wkt<G>("POINT(370 -350)"),
431 10, 10, 10, 10);
432 #endif
433
434 // north and south poles
435 tester::apply("p04",
436 from_wkt<G>("POINT(0 90)"),
437 0, 90, 0, 90);
438
439 tester::apply("p04a",
440 from_wkt<G>("POINT(10 90)"),
441 0, 90, 0, 90);
442
443 tester::apply("p04b",
444 from_wkt<G>("POINT(270 90)"),
445 0, 90, 0, 90);
446
447 #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
448 tester::apply("p04c",
449 from_wkt<G>("POINT(270 450)"),
450 0, 90, 0, 90);
451 #endif
452
453 tester::apply("p04d",
454 from_wkt<G>("POINT(190 90)"),
455 0, 90, 0, 90);
456
457 tester::apply("p04e",
458 from_wkt<G>("POINT(-100 90)"),
459 0, 90, 0, 90);
460
461 tester::apply("p05",
462 from_wkt<G>("POINT(0 -90)"),
463 0, -90, 0, -90);
464
465 tester::apply("p05a",
466 from_wkt<G>("POINT(10 -90)"),
467 0, -90, 0, -90);
468
469 tester::apply("p05b",
470 from_wkt<G>("POINT(270 -90)"),
471 0, -90, 0, -90);
472
473 #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
474 tester::apply("p05c",
475 from_wkt<G>("POINT(270 -450)"),
476 0, -90, 0, -90);
477 #endif
478
479 tester::apply("p05d",
480 from_wkt<G>("POINT(190 -90)"),
481 0, -90, 0, -90);
482
483 tester::apply("p05e",
484 from_wkt<G>("POINT(-100 -90)"),
485 0, -90, 0, -90);
486
487 tester::apply("p05f",
488 from_wkt<G>("POINT(-100 -90)"),
489 0, -90, 0, -90);
490 }
491
492 BOOST_AUTO_TEST_CASE( envelope_point )
493 {
494 test_envelope_point<bg::cs::spherical_equatorial<bg::degree> >();
495 test_envelope_point<bg::cs::geographic<bg::degree> >();
496 }
497
498
499 template <typename CoordinateSystem>
500 void test_envelope_point_with_height()
501 {
502 typedef bg::model::point<double, 3, CoordinateSystem> point_type;
503 typedef point_type G;
504 typedef bg::model::box<point_type> B;
505 typedef test_envelope_on_spheroid<G, B> tester;
506
507 tester::apply("ph01",
508 from_wkt<G>("POINT(10 10 1256)"),
509 10, 10, 1256, 10, 10, 1256);
510 }
511
512 BOOST_AUTO_TEST_CASE( envelope_point_with_height )
513 {
514 test_envelope_point_with_height
515 <
516 bg::cs::spherical_equatorial<bg::degree>
517 >();
518 test_envelope_point_with_height<bg::cs::geographic<bg::degree> >();
519 }
520
521
522 BOOST_AUTO_TEST_CASE( envelope_segment )
523 {
524 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
525 typedef bg::model::point<double, 2, coordinate_system_type> P;
526 typedef bg::model::segment<P> G;
527 typedef bg::model::box<P> B;
528 typedef test_envelope_on_spheroid<G, B> tester;
529
530 double const eps = std::numeric_limits<double>::epsilon();
531
532 tester::apply("s01",
533 from_wkt<G>("SEGMENT(10 10,40 40)"),
534 10, 10, 40, 40);
535
536 tester::apply("s02",
537 from_wkt<G>("SEGMENT(10 10,40 10)"),
538 10, 10, 40, 10.34527004614999);
539
540 tester::apply("s02a",
541 from_wkt<G>("SEGMENT(40 10,10 10)"),
542 10, 10, 40, 10.34527004614999);
543
544 tester::apply("s03",
545 from_wkt<G>("SEGMENT(160 10,-170 10)"),
546 160, 10, 190, 10.34527004614999);
547
548 tester::apply("s03a",
549 from_wkt<G>("SEGMENT(-170 10,160 10)"),
550 160, 10, 190, 10.34527004614999);
551
552 tester::apply("s03b",
553 from_wkt<G>("SEGMENT(-170 -10,160 -10)"),
554 160, -10.34527004614999, 190, -10);
555
556 tester::apply("s04",
557 from_wkt<G>("SEGMENT(-40 45,140 60)"),
558 -40, 45, 140, 90);
559
560 tester::apply("s04a",
561 from_wkt<G>("SEGMENT(-40 45,140 25)"),
562 -40, 25, 140, 90);
563
564 // segment ending at the north pole
565 tester::apply("s05",
566 from_wkt<G>("SEGMENT(40 45,80 90)"),
567 40, 45, 40, 90);
568
569 // segment starting at the north pole
570 tester::apply("s05a",
571 from_wkt<G>("SEGMENT(80 90,40 45)"),
572 40, 45, 40, 90);
573
574 // segment ending at the north pole
575 tester::apply("s06",
576 from_wkt<G>("SEGMENT(-40 45,80 90)"),
577 -40, 45, -40, 90);
578
579 // segment starting at the north pole
580 tester::apply("s06a",
581 from_wkt<G>("SEGMENT(70 90,-40 45)"),
582 -40, 45, -40, 90);
583
584 // segment ending at the north pole
585 tester::apply("s07",
586 from_wkt<G>("SEGMENT(40 -45,80 90)"),
587 40, -45, 40, 90);
588
589 // segment passing through the south pole
590 tester::apply("s08",
591 from_wkt<G>("SEGMENT(-170 -45,10 -30)"),
592 -170, -90, 10, -30);
593
594 tester::apply("s09",
595 from_wkt<G>("SEGMENT(1 -45,179 30)"),
596 1, -85.28884376852969, 179, 30,
597 3 * eps);
598
599 tester::apply("s09a",
600 from_wkt<G>("SEGMENT(2 -45,181 30)"),
601 2, -87.63659983704832, 181, 30);
602
603 // very long segment
604 tester::apply("s10",
605 from_wkt<G>("SEGMENT(0 -45,181 30)"),
606 -179, -88.07047433509489, 0, 30,
607 2.0 * eps);
608
609 tester::apply("s11",
610 from_wkt<G>("SEGMENT(260 30,20 45)"),
611 -100, 30, 20, 57.93195594009233);
612
613 tester::apply("s11a",
614 from_wkt<G>("SEGMENT(260 45,20 30)"),
615 -100, 30, 20, 49.43962741846035);
616
617 // segment degenerating to the north pole
618 tester::apply("s12",
619 from_wkt<G>("SEGMENT(10 90,20 90)"),
620 0, 90, 0, 90);
621
622 // segment degenerating to the south pole
623 tester::apply("s13",
624 from_wkt<G>("SEGMENT(10 -90,20 -90)"),
625 0, -90, 0, -90);
626
627 tester::apply("s14",
628 from_wkt<G>("SEGMENT(20 20,10 30)"),
629 10, 20, 20, 30);//48.87458730907602);
630
631 tester::apply("s15",
632 from_wkt<G>("SEGMENT(50 45,185 45)"),
633 50, 45, 185, 69.05897952775615);
634
635 // segment that lies on the equator
636 tester::apply("s16",
637 from_wkt<G>("SEGMENT(0 0,50 0)"),
638 0, 0, 50, 0);
639
640 // segment that lies on the equator
641 tester::apply("s16a",
642 from_wkt<G>("SEGMENT(-50 0,50 0)"),
643 -50, 0, 50, 0);
644
645 // segment that lies on the equator and touches antimeridian
646 tester::apply("s16b",
647 from_wkt<G>("SEGMENT(50 0,180 0)"),
648 50, 0, 180, 0);
649
650 // segment that lies on the equator and crosses antimeridian
651 tester::apply("s16c",
652 from_wkt<G>("SEGMENT(-170 0,160 0)"),
653 160, 0, 190, 0);
654
655 tester::apply("s17",
656 from_wkt<G>("SEGMENT(140 10, -140 80)"),
657 140, 10, 220, 80);
658
659 tester::apply("s17-r",
660 from_wkt<G>("SEGMENT(-140 80, 140 10)"),
661 140, 10, 220, 80);
662
663 tester::apply("s18",
664 from_wkt<G>("SEGMENT(20 10, 100 80)"),
665 20, 10, 100, 80);
666
667 tester::apply("s18-r",
668 from_wkt<G>("SEGMENT(100 80, 20 10)"),
669 20, 10, 100, 80);
670
671 // segment connecting the north and south pole
672 //
673 // this should be forbidden actually, as it is not well-defined
674 // with this test we demonstrate that the algorithm still returns
675 // something meaningful
676 tester::apply("s99",
677 from_wkt<G>("SEGMENT(10 90,20 -90)"),
678 0, -90, 0, 90);
679
680 // https://svn.boost.org/trac/boost/ticket/12106
681 tester::apply("s100_ticket_12106",
682 G(P(11.488323611111111, 53.687086666666673), P(11.488324166666667, 53.687086666666673)),
683 11.488323611111111, 53.687086666666673, 11.488324166666667, 53.687086666666673);
684
685 double const heps = eps / 2;
686
687 tester::apply("s101",
688 G(P(1, 1), P(1-heps, 1-heps)),
689 1-heps, 1-heps, 1, 1);
690 tester::apply("s102",
691 G(P(1, 1), P(1, 1-heps)),
692 1, 1-heps, 1, 1);
693 tester::apply("s103",
694 G(P(1, 1), P(1-heps, 1)),
695 1-heps, 1, 1, 1);
696 tester::apply("s104",
697 G(P(2, 1), P(1, 1-heps)),
698 1, 1-heps, 2, 1.000038070652770505);
699 tester::apply("s105",
700 G(P(1, 2), P(1-heps, 1)),
701 1-heps, 1, 1, 2);
702 }
703
704
705 BOOST_AUTO_TEST_CASE( envelope_segment_with_height )
706 {
707 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
708 typedef bg::model::point<double, 3, coordinate_system_type> point_type;
709 typedef bg::model::segment<point_type> G;
710 typedef bg::model::box<point_type> B;
711 typedef test_envelope_on_spheroid<G, B> tester;
712
713 tester::apply("sh01",
714 from_wkt<G>("SEGMENT(10 10 567,40 40 1356)"),
715 10, 10, 567, 40, 40, 1356);
716
717 tester::apply("sh02",
718 from_wkt<G>("SEGMENT(10 10 1356,40 40 567)"),
719 10, 10, 567, 40, 40, 1356);
720 }
721
722
723 template <typename CoordinateSystem>
724 void test_envelope_multipoint()
725 {
726 typedef bg::model::point<double, 2, CoordinateSystem> P;
727 typedef bg::model::multi_point<P> G;
728 typedef bg::model::box<P> B;
729 typedef test_envelope_on_spheroid<G, B> tester;
730
731 // empty multipoint
732 test_empty_geometry<CoordinateSystem, G>("mp00", "MULTIPOINT()");
733
734 tester::apply("mp01",
735 from_wkt<G>("MULTIPOINT(0 0,10 10)"),
736 0, 0, 10, 10);
737
738 tester::apply("mp02",
739 from_wkt<G>("MULTIPOINT(0 10,10 0)"),
740 0, 0, 10, 10);
741
742 tester::apply("mp03",
743 from_wkt<G>("MULTIPOINT(-10 20,0 10,10 0)"),
744 -10, 0, 10, 20);
745
746 tester::apply("mp04",
747 from_wkt<G>("MULTIPOINT(-10 20,0 10,10 -15)"),
748 -10, -15, 10, 20);
749
750 tester::apply("mp05",
751 from_wkt<G>("MULTIPOINT(-85 10,85 -20)"),
752 -85, -20, 85, 10);
753
754 tester::apply("mp06",
755 from_wkt<G>("MULTIPOINT(-95 10,85 -20)"),
756 -95, -20, 85, 10);
757
758 tester::apply("mp07",
759 from_wkt<G>("MULTIPOINT(-96 10,85 -20)"),
760 85, -20, -96+360, 10);
761
762 tester::apply("mp08",
763 from_wkt<G>("MULTIPOINT(175 15,-175 -20)"),
764 175, -20, -175+360, 15);
765
766 tester::apply("mp09",
767 from_wkt<G>("MULTIPOINT(170 15,170 20,-175 10,-90 10,10 10)"),
768 170, 10, 10+360, 20);
769
770 // this should fail
771 tester::apply("mp09a",
772 from_wkt<G>("MULTIPOINT(10 10,170 15,170 20,-175 10,-90 10)"),
773 170, 10, 10+360, 20);
774
775
776 tester::apply("mp10",
777 from_wkt<G>("MULTIPOINT(10 10,20 90,30 -90)"),
778 10, -90, 10, 90);
779
780 // this should fail
781 tester::apply("mp11",
782 from_wkt<G>("MULTIPOINT(179 90,-179 -90,10 10)"),
783 10, -90, 10, 90);
784
785 tester::apply("mp11a",
786 from_wkt<G>("MULTIPOINT(10 10,179 90,-179 -90)"),
787 10, -90, 10, 90);
788
789 // this should fail
790 tester::apply("mp11b",
791 from_wkt<G>("MULTIPOINT(179 90,-179 -90,-90 0)"),
792 -90, -90, -90, 90);
793
794 tester::apply("mp11c",
795 from_wkt<G>("MULTIPOINT(-90 0,179 90,-179 -90,-90 0)"),
796 -90, -90, -90, 90);
797
798 tester::apply("mp12",
799 from_wkt<G>("MULTIPOINT(170 -30,175 60,-178 10)"),
800 170, -30, -178+360, 60);
801
802 tester::apply("mp13",
803 from_wkt<G>("MULTIPOINT(-170 -30,-175 40,178 50)"),
804 178, -30, -170+360, 50);
805
806 tester::apply("mp13a",
807 from_wkt<G>("MULTIPOINT(-170 -30,178 50)"),
808 178, -30, -170+360, 50);
809
810 tester::apply("mp13b",
811 from_wkt<G>("MULTIPOINT(-170 -30,178 50,-175 40)"),
812 178, -30, -170+360, 50);
813
814 tester::apply("mp15",
815 from_wkt<G>("MULTIPOINT(10 -20)"),
816 10, -20, 10, -20);
817
818 tester::apply("mp16",
819 from_wkt<G>("MULTIPOINT(0 90,10 90)"),
820 0, 90, 0, 90);
821
822 tester::apply("mp17",
823 from_wkt<G>("MULTIPOINT(179 80,-179 -80,10 10)"),
824 10, -80, -179+360, 80);
825
826 tester::apply("mp17a",
827 from_wkt<G>("MULTIPOINT(10 10,179 80,-179 -80)"),
828 10, -80, -179+360, 80);
829
830 tester::apply("mp17b",
831 from_wkt<G>("MULTIPOINT(179 80,-179 -80,-90 0)"),
832 179, -80, -90+360, 80);
833
834 tester::apply("mp17c",
835 from_wkt<G>("MULTIPOINT(-90 0,179 80,-179 -80,-90 0)"),
836 179, -80, -90+360, 80);
837
838 tester::apply("mp18",
839 from_wkt<G>("MULTIPOINT(-170 45,20 25,40 40)"),
840 20, 25, 190, 45);
841
842 #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
843 tester::apply("mp18a",
844 from_wkt<G>("MULTIPOINT(10 135,20 25,40 40)"),
845 20, 25, 190, 45);
846 #endif
847
848 tester::apply("mp19",
849 from_wkt<G>("MULTIPOINT(350 45,20 25,40 40)"),
850 -10, 25, 40, 45);
851
852 #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
853 tester::apply("mp19a",
854 from_wkt<G>("MULTIPOINT(170 135,20 25,40 40)"),
855 -10, 25, 40, 45);
856 #endif
857
858 double eps = std::numeric_limits<double>::epsilon();
859 double heps = eps / 2;
860 {
861 G mp;
862 mp.push_back(P(1, 1));
863 mp.push_back(P(1-heps, 1-heps));
864 tester::apply("mp20", mp, 1-heps, 1-heps, 1, 1);
865 }
866 }
867
868 BOOST_AUTO_TEST_CASE( envelope_multipoint )
869 {
870 test_envelope_multipoint<bg::cs::spherical_equatorial<bg::degree> >();
871 test_envelope_multipoint<bg::cs::geographic<bg::degree> >();
872 }
873
874
875 template <typename CoordinateSystem>
876 void test_envelope_multipoint_with_height()
877 {
878 typedef bg::model::point<double, 3, CoordinateSystem> point_type;
879 typedef bg::model::multi_point<point_type> G;
880 typedef bg::model::box<point_type> B;
881 typedef test_envelope_on_spheroid<G, B> tester;
882
883 // empty multipoint
884 test_empty_geometry<CoordinateSystem, G>("mph00", "MULTIPOINT()");
885
886 tester::apply("mph01",
887 from_wkt<G>("MULTIPOINT(0 0 567,10 10 1456)"),
888 0, 0, 567, 10, 10, 1456);
889
890 tester::apply("mph02",
891 from_wkt<G>("MULTIPOINT(0 0 567,10 10 1456,20 90 967)"),
892 0, 0, 567, 10, 90, 1456);
893 }
894
895 BOOST_AUTO_TEST_CASE( envelope_multipoint_with_height )
896 {
897 test_envelope_multipoint_with_height
898 <
899 bg::cs::spherical_equatorial<bg::degree>
900 >();
901 test_envelope_multipoint_with_height<bg::cs::geographic<bg::degree> >();
902 }
903
904
905 template <typename CoordinateSystem>
906 void test_envelope_box()
907 {
908 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
909 typedef bg::model::point<double, 2, coordinate_system_type> P;
910 typedef bg::model::box<P> G;
911 typedef bg::model::box<P> B;
912 typedef test_envelope_on_spheroid<G, B> tester;
913
914 tester::apply("b01",
915 from_wkt<G>("BOX(10 10,20 20)"),
916 10, 10, 20, 20);
917
918 #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
919 tester::apply("b02",
920 from_wkt<G>("BOX(10 370,20 20)"),
921 10, 10, 20, 20);
922 #endif
923
924 // box crosses anti-meridian
925 tester::apply("b02a",
926 from_wkt<G>("BOX(170 10,-170 20)"),
927 170, 10, 190, 20);
928
929 tester::apply("b03",
930 from_wkt<G>("BOX(-170 10,170 20)"),
931 -170, 10, 170, 20);
932
933 tester::apply("b04",
934 from_wkt<G>("BOX(10 10,350 20)"),
935 10, 10, 350, 20);
936
937 tester::apply("b04a",
938 from_wkt<G>("BOX(10 10,-10 20)"),
939 10, 10, 350, 20);
940
941 // box is a band
942 tester::apply("b05",
943 from_wkt<G>("BOX(0 10,360 20)"),
944 -180, 10, 180, 20);
945
946 tester::apply("b05a",
947 from_wkt<G>("BOX(0 10,0 20)"),
948 0, 10, 0, 20);
949
950 // box is almost a band
951 tester::apply("b06",
952 from_wkt<G>("BOX(10 10,5 20)"),
953 10, 10, 365, 20);
954
955 // initial box is a band that crosses itself
956 tester::apply("b07",
957 from_wkt<G>("BOX(0 10,540 20)"),
958 -180, 10, 180, 20);
959
960 // initial box is a band that crosses itself
961 tester::apply("b08",
962 from_wkt<G>("BOX(0 10,720 20)"),
963 -180, 10, 180, 20);
964
965 tester::apply("b09",
966 from_wkt<G>("BOX(10 10,10 10)"),
967 10, 10, 10, 10);
968
969 tester::apply("b09a",
970 from_wkt<G>("BOX(370 10,370 10)"),
971 10, 10, 10, 10);
972
973 // box contains north and south pole
974 tester::apply("b10",
975 from_wkt<G>("BOX(0 -90,0 90)"),
976 0, -90, 0, 90);
977
978 // box contains north and south pole
979 tester::apply("b10a",
980 from_wkt<G>("BOX(10 -90,10 90)"),
981 10, -90, 10, 90);
982
983 // box contains north and south pole
984 tester::apply("b10b",
985 from_wkt<G>("BOX(0 -90,10 90)"),
986 0, -90, 10, 90);
987
988 // box contains north and south pole
989 tester::apply("b11",
990 from_wkt<G>("BOX(0 -90,180 90)"),
991 0, -90, 180, 90);
992
993 // box contains north and south pole
994 tester::apply("b11a",
995 from_wkt<G>("BOX(10 -90,190 90)"),
996 10, -90, 190, 90);
997
998 // box contains north and south pole
999 tester::apply("b11b",
1000 from_wkt<G>("BOX(10 -90,110 90)"),
1001 10, -90, 110, 90);
1002
1003 // box contains north and south pole and is a band
1004 // (box covers the entire spheroid)
1005 tester::apply("b12",
1006 from_wkt<G>("BOX(0 -90,360 90)"),
1007 -180, -90, 180, 90);
1008
1009 // box contains north and south pole and is a band
1010 // (box covers the entire spheroid)
1011 tester::apply("b12a",
1012 from_wkt<G>("BOX(10 -90,370 90)"),
1013 -180, -90, 180, 90);
1014
1015 // box contains north and south pole and is a band
1016 // (box covers the entire spheroid)
1017 tester::apply("b12b",
1018 from_wkt<G>("BOX(-175 -90,185 90)"),
1019 -180, -90, 180, 90);
1020
1021 // box contains north and south pole and is a band
1022 // (box covers the entire spheroid)
1023 tester::apply("b12c",
1024 from_wkt<G>("BOX(-175 -90,185 90)"),
1025 -180, -90, 180, 90);
1026
1027 // box contains north and south pole and is a band and is self-intersecting
1028 // (box covers the entire spheroid)
1029 tester::apply("b12d",
1030 from_wkt<G>("BOX(-175 -90,186 90)"),
1031 -180, -90, 180, 90);
1032
1033 // box contains north and south pole and is a band and is self-intersecting
1034 // (box covers the entire spheroid)
1035 tester::apply("b12e",
1036 from_wkt<G>("BOX(0 -90,540 90)"),
1037 -180, -90, 180, 90);
1038
1039 // box contains north and south pole and is a band and is self-intersecting
1040 // (box covers the entire spheroid)
1041 tester::apply("b12f",
1042 from_wkt<G>("BOX(10 -90,540 90)"),
1043 -180, -90, 180, 90);
1044
1045 // box is a band
1046 tester::apply("b13",
1047 from_wkt<G>("BOX(180 -10,-180 10)"),
1048 -180, -10, 180, 10);
1049
1050 // box contains north and south pole and is a band
1051 // (box covers the entire spheroid)
1052 tester::apply("b13a",
1053 from_wkt<G>("BOX(180 -90,-180 90)"),
1054 -180, -90, 180, 90);
1055
1056 tester::apply("b14",
1057 from_wkt<G>("BOX(0 10,30 90)"),
1058 0, 10, 30, 90);
1059
1060 tester::apply("b15",
1061 from_wkt<G>("BOX(179 10,178 70)"),
1062 179, 10, 538, 70);
1063
1064 // box contains north pole
1065 tester::apply("b16",
1066 from_wkt<G>("BOX(10 40,20 90)"),
1067 10, 40, 20, 90);
1068
1069 tester::apply("b16a",
1070 from_wkt<G>("BOX(170 40,-170 90)"),
1071 170, 40, 190, 90);
1072
1073 // box contains south pole
1074 tester::apply("b17",
1075 from_wkt<G>("BOX(10 -90,20 40)"),
1076 10, -90, 20, 40);
1077
1078 tester::apply("b17a",
1079 from_wkt<G>("BOX(150 -90,-150 40)"),
1080 150, -90, 210, 40);
1081
1082 // box degenerates to the north pole
1083 tester::apply("b98",
1084 from_wkt<G>("BOX(10 90,20 90)"),
1085 0, 90, 0, 90);
1086
1087 // box degenerates to the south pole
1088 tester::apply("b99",
1089 from_wkt<G>("BOX(10 -90,20 -90)"),
1090 0, -90, 0, -90);
1091
1092 double eps = std::numeric_limits<double>::epsilon();
1093 double heps = eps / 2;
1094
1095 tester::apply("b100", G(P(1-heps, 1-heps), P(1, 1)), 1-heps, 1-heps, 1, 1);
1096 }
1097
1098 BOOST_AUTO_TEST_CASE( envelope_box )
1099 {
1100 test_envelope_box<bg::cs::spherical_equatorial<bg::degree> >();
1101 test_envelope_box<bg::cs::geographic<bg::degree> >();
1102 }
1103
1104
1105 template <typename CoordinateSystem>
1106 void test_envelope_box_with_height()
1107 {
1108 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
1109 typedef bg::model::point<double, 3, coordinate_system_type> point_type;
1110 typedef bg::model::box<point_type> G;
1111 typedef bg::model::box<point_type> B;
1112 typedef test_envelope_on_spheroid<G, B> tester;
1113
1114 tester::apply("bh01",
1115 from_wkt<G>("BOX(10 10 567,20 20 2834)"),
1116 10, 10, 567, 20, 20, 2834);
1117
1118 tester::apply("bh02",
1119 from_wkt<G>("BOX(10 10 567,20 20 567)"),
1120 10, 10, 567, 20, 20, 567);
1121
1122 tester::apply("bh03",
1123 from_wkt<G>("BOX(0 10 567,170 90 1567)"),
1124 0, 10, 567, 170, 90, 1567);
1125 }
1126
1127 BOOST_AUTO_TEST_CASE( envelope_box_with_height )
1128 {
1129 test_envelope_box_with_height<bg::cs::spherical_equatorial<bg::degree> >();
1130 test_envelope_box_with_height<bg::cs::geographic<bg::degree> >();
1131 }
1132
1133
1134 BOOST_AUTO_TEST_CASE( envelope_linestring )
1135 {
1136 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
1137 typedef bg::model::point<double, 2, coordinate_system_type> P;
1138 typedef bg::model::linestring<P> G;
1139 typedef bg::model::box<P> B;
1140 typedef test_envelope_on_spheroid<G, B> tester;
1141
1142 // empty linestring
1143 test_empty_geometry<coordinate_system_type, G>("l00", "LINESTRING()");
1144
1145 tester::apply("l01",
1146 from_wkt<G>("LINESTRING(10 15)"),
1147 10, 15, 10, 15);
1148
1149 tester::apply("l01a",
1150 from_wkt<G>("LINESTRING(370 15)"),
1151 10, 15, 10, 15);
1152
1153 tester::apply("l01b",
1154 from_wkt<G>("LINESTRING(370 90)"),
1155 0, 90, 0, 90);
1156
1157 tester::apply("l02",
1158 from_wkt<G>("LINESTRING(10 10,20 20,10 30)"),
1159 10, 10, 20, 30);
1160
1161 // linestring that circles the entire globe
1162 tester::apply("l03",
1163 from_wkt<G>("LINESTRING(-185 0,-170 25,-50 10,10 10,20 20,100 5,180 15)"),
1164 -180, 0, 180, 25.15036418555258,
1165 4.0 * std::numeric_limits<double>::epsilon());
1166
1167 // linestring that crosses the antimeridian but staying close to it
1168 tester::apply("l04",
1169 from_wkt<G>("LINESTRING(-170 10,170 45,160 5,-160 25)"),
1170 160, 5, 200, 45);
1171
1172 // linestring that goes through the north pole (twice)
1173 tester::apply("l05",
1174 from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30)"),
1175 -170, 30, 20, 90);
1176
1177 // linestring that goes through the north pole (three times)
1178 tester::apply("l05a",
1179 from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70)"),
1180 -170, 30, 30, 90);
1181
1182 // linestring that goes through the north pole (four times)
1183 tester::apply("l05b",
1184 from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70,40 85,-140 25)"),
1185 -170, 25, 40, 90);
1186
1187 // linestring that goes through the north pole (five times)
1188 tester::apply("l05c",
1189 from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70,40 85,-140 25,-130 25,50 45)"),
1190 -170, 25, 50, 90);
1191
1192 // linestring that goes through the north pole (five times)
1193 tester::apply("l05d",
1194 from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70,40 85,-140 25,-130 25,50 45,185 45)"),
1195 -170, 25, 185, 90);
1196
1197 // linestring that crosses the antimeridian
1198 tester::apply("l06",
1199 from_wkt<G>("LINESTRING(-160 85,-170 80,170 40,160 80)"),
1200 160, 40, 200, 85);
1201
1202 // linestring that crosses the antimeridian
1203 tester::apply("l06a",
1204 from_wkt<G>("LINESTRING(-130 85,-170 84,170 40,160 80)"),
1205 160, 40, 230, 85.02629680862029);
1206
1207 // linestring that goes through the north pole
1208 tester::apply("l07",
1209 from_wkt<G>("LINESTRING(-160 40,-170 90,-140 40,-50 30)"),
1210 -160, 30, -50, 90);
1211
1212 // linestring that degenerates to the north pole
1213 tester::apply("l08",
1214 from_wkt<G>("LINESTRING(-40 90,-30 90,-140 90,10 90)"),
1215 0, 90, 0, 90);
1216
1217 // linestring with duplicate points
1218 tester::apply("l09",
1219 from_wkt<G>("LINESTRING(-40 20,-40 20,-140 85,-10 5,-10 5)"),
1220 -140, 5, -10, 85);
1221
1222 // linestring with duplicate points
1223 tester::apply("l09a",
1224 from_wkt<G>("LINESTRING(-40 20,320 20,-140 85,-10 5,350 5)"),
1225 -140, 5, -10, 85);
1226
1227 // linestring that lies on the equator
1228 tester::apply("l10",
1229 from_wkt<G>("LINESTRING(0 0,50 0)"),
1230 0, 0, 50, 0);
1231
1232 // linestring that lies on the equator
1233 tester::apply("l10a",
1234 from_wkt<G>("LINESTRING(-50 0,50 0)"),
1235 -50, 0, 50, 0);
1236
1237 // linestring that lies on the equator and touches antimeridian
1238 tester::apply("l10b",
1239 from_wkt<G>("LINESTRING(50 0,180 0)"),
1240 50, 0, 180, 0);
1241
1242 // linestring that lies on the equator and crosses antimeridian
1243 tester::apply("l10c",
1244 from_wkt<G>("LINESTRING(-170 0,160 0)"),
1245 160, 0, 190, 0);
1246
1247 double eps = std::numeric_limits<double>::epsilon();
1248 double heps = eps / 2;
1249
1250 {
1251 G l;
1252 l.push_back(P(1, 1));
1253 l.push_back(P(1-heps, 1-heps));
1254 tester::apply("l11", l, 1-heps, 1-heps, 1, 1);
1255 }
1256
1257 {
1258 G l;
1259 l.push_back(P(0, 0));
1260 l.push_back(P(1-heps, 1-heps));
1261 l.push_back(P(0, 0));
1262 l.push_back(P(1, 1));
1263 tester::apply("l12", l, 0, 0, 1, 1);
1264 }
1265 }
1266
1267
1268 BOOST_AUTO_TEST_CASE( envelope_linestring_with_height )
1269 {
1270 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
1271 typedef bg::model::point<double, 3, coordinate_system_type> point_type;
1272 typedef bg::model::linestring<point_type> G;
1273 typedef bg::model::box<point_type> B;
1274 typedef test_envelope_on_spheroid<G, B> tester;
1275
1276 // empty linestring
1277 test_empty_geometry<coordinate_system_type, G>("lh00", "LINESTRING()");
1278
1279 tester::apply("lh01",
1280 from_wkt<G>("LINESTRING(10 15 30,20 25 434,30 35 186)"),
1281 10, 15, 30, 30, 35, 434);
1282 }
1283
1284
1285 BOOST_AUTO_TEST_CASE( envelope_multilinestring )
1286 {
1287 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
1288 typedef bg::model::point<double, 2, coordinate_system_type> point_type;
1289 typedef bg::model::multi_linestring<bg::model::linestring<point_type> > G;
1290 typedef bg::model::box<point_type> B;
1291 typedef test_envelope_on_spheroid<G, B> tester;
1292
1293 // empty multilinestring
1294 test_empty_geometry<coordinate_system_type, G>("ml00", "MULTILINESTRING()");
1295
1296 // invalid multilinestring
1297 test_empty_geometry<coordinate_system_type, G>("ml00a",
1298 "MULTILINESTRING(())");
1299
1300 // invalid multilinestring
1301 test_empty_geometry<coordinate_system_type, G>("ml00b",
1302 "MULTILINESTRING((),())");
1303
1304 // invalid multilinestring
1305 tester::apply("ml00c",
1306 from_wkt<G>("MULTILINESTRING((10 15),(),())"),
1307 10, 15, 10, 15);
1308
1309 // invalid multilinestring
1310 tester::apply("ml00d",
1311 from_wkt<G>("MULTILINESTRING((),(10 15),())"),
1312 10, 15, 10, 15);
1313
1314 tester::apply("ml01",
1315 from_wkt<G>("MULTILINESTRING((10 15))"),
1316 10, 15, 10, 15);
1317
1318 #ifdef BOOST_GEOMETRY_INCLUDE_FAILING_TESTS
1319 tester::apply("ml01a",
1320 from_wkt<G>("MULTILINESTRING((),(),(10 15),())"),
1321 10, 15, 10, 15);
1322 #endif // BOOST_GEOMETRY_INCLUDE_FAILING_TESTS
1323
1324 tester::apply("ml02",
1325 from_wkt<G>("MULTILINESTRING((-170 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"),
1326 -180, 25, 180, 80);
1327
1328 tester::apply("ml03",
1329 from_wkt<G>("MULTILINESTRING((-150 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"),
1330 -150, 25, 200, 80);
1331
1332 tester::apply("ml04",
1333 from_wkt<G>("MULTILINESTRING((-150 40,-100 80),(10 35,100 80))"),
1334 -150, 35, 100, 80.07385383411011);
1335
1336 tester::apply("ml04a",
1337 from_wkt<G>("MULTILINESTRING((-150 40,-100 80),(10 35,100 80),(170 25,-160 80))"),
1338 10, 25, 260, 80.07385383411011);
1339
1340 tester::apply("ml05",
1341 from_wkt<G>("MULTILINESTRING((-140 40,-100 80),(10 35,100 80))"),
1342 -140, 35, 100, 80.07385383411011);
1343
1344 tester::apply("ml05a",
1345 from_wkt<G>("MULTILINESTRING((-140 40,-100 80),(10 35,100 80),(170 25,-160 80))"),
1346 10, 25, 260, 80.07385383411011);
1347 }
1348
1349
1350 BOOST_AUTO_TEST_CASE( envelope_multilinestring_with_height )
1351 {
1352 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
1353 typedef bg::model::point<double, 3, coordinate_system_type> point_type;
1354 typedef bg::model::multi_linestring<bg::model::linestring<point_type> > G;
1355 typedef bg::model::box<point_type> B;
1356 typedef test_envelope_on_spheroid<G, B> tester;
1357
1358 tester::apply("mlh01",
1359 from_wkt<G>("MULTILINESTRING((10 15 1000))"),
1360 10, 15, 1000, 10, 15, 1000);
1361
1362 #ifdef BOOST_GEOMETRY_INCLUDE_FAILING_TESTS
1363 tester::apply("mlh01a",
1364 from_wkt<G>("MULTILINESTRING((),(),(10 15 1000),())"),
1365 10, 15, 1000, 10, 15, 1000);
1366 #endif // BOOST_GEOMETRY_INCLUDE_FAILING_TESTS
1367
1368 tester::apply("mlh02",
1369 from_wkt<G>("MULTILINESTRING((-170 40 400,-100 80 300),(-10 25 600,10 35 700,120 45 450))"),
1370 -10, 25, 300, 260, 80, 700);
1371 }
1372
1373
1374 #if 0
1375 // unit test for rings de-activated for now (current implementation
1376 // for area on the spherical equatorial coordinate system is not complete)
1377 // TODO: re-activate once implementation is done
1378 BOOST_AUTO_TEST_CASE( envelope_cw_ring )
1379 {
1380 typedef deg_cw_ring_type G;
1381 typedef test_envelope_on_spheroid<G, deg_box_type> tester;
1382
1383 double const eps = std::numeric_limits<double>::epsilon();
1384
1385 tester::apply("r01cw",
1386 from_wkt<G>("POLYGON((0 10,0 45,50 10,0 10))"),
1387 0, 10, 50, 45);
1388
1389 // ring that contains both the north and south poles in its interior
1390 tester::apply("r01cw-r",
1391 from_wkt<G>("POLYGON((0 10,50 10,0 45,0 10))"),
1392 -180, -90, 180, 90);
1393
1394 // ring that contains the north pole in its interior
1395 tester::apply("r02cw",
1396 from_wkt<G>("POLYGON((0 0,-50 0,-170 0,180 0,100 0,0 0))"),
1397 -180, 0, 180, 90);
1398 // -180, -90, 180, 0);
1399
1400 // ring that contains the south pole in its interior
1401 tester::apply("r02cw-r",
1402 from_wkt<G>("POLYGON((0 0,100 0,180 0,-170 0,-50 0,0 0))"),
1403 -180, -90, 180, 0);
1404 // -180, 0, 180, 90);
1405
1406 // ring that contains the north pole in its interior
1407 tester::apply("r03cw",
1408 from_wkt<G>("POLYGON((0 -10,-50 -10,-170 -10,180 -10,100 -10,0 -10))"),
1409 -180, -19.42540014068282, 180, 90);
1410 // -180, -90, 180, -10);
1411
1412 // ring that contains both the south and north poles in its interior
1413 tester::apply("r03cw-r",
1414 from_wkt<G>("POLYGON((0 -10,100 -10,180 -10,-170 -10,-50 -10,0 -10))"),
1415 -180, -90, 180, -10);
1416 // -180, -19.42540014068282, 180, 90);
1417
1418 // ring that has the north pole as vertex and contains the south pole
1419 tester::apply("r04cw",
1420 from_wkt<G>("POLYGON((0 0,-50 90,-50 0,0 0))"),
1421 -180, -90, 180, 90);
1422
1423 // ring that has the north pole as vertex
1424 tester::apply("r04cw-r",
1425 from_wkt<G>("POLYGON((0 0,-50 0,-50 90,0 0))"),
1426 -50, 0, 0, 90);
1427
1428 // ring that crosses antimeridian but does not contain any pole
1429 tester::apply("r05cw",
1430 from_wkt<G>("POLYGON((-140 0,140 10,-140 80,-140 0))"),
1431 140, 0, 220, 80);
1432
1433 // ring that crosses antimeridian multiple times but does not
1434 // contain any pole
1435 tester::apply("r06cw",
1436 from_wkt<G>("POLYGON((-140 10,140 10,140 80,-140 80,-140 10))"),
1437 140, 10, 220, 82.30737118075496,
1438 2 * eps);
1439
1440 // ring that crosses antimeridian multiple times but does not
1441 // contain any pole
1442 tester::apply("r07cw",
1443 from_wkt<G>("POLYGON((-140 10,140 10,180 80,-140 10))"),
1444 140, 10, 220, 80);
1445
1446 // ring that goes through the north pole
1447 tester::apply("r08cw",
1448 from_wkt<G>("POLYGON((0 0,-50 0,-50 90,0 0))"),
1449 -50, 0, 0, 90);
1450
1451 // ring that goes through the south pole and contains the north pole
1452 tester::apply("r09cw",
1453 from_wkt<G>("POLYGON((0 0,0 -90,50 0,0 0))"),
1454 -180, -90, 180, 90);
1455
1456 // ring that goes through the south pole
1457 tester::apply("r09cw-r",
1458 from_wkt<G>("POLYGON((0 0,50 0,50 -90,0 0))"),
1459 0, -90, 50, 0);
1460
1461 // ring that goes through both south and north pole
1462 tester::apply("r10cw",
1463 from_wkt<G>("POLYGON((50 0,50 -90,40 0,40 90,50 0))"),
1464 40, -90, 50, 90);
1465
1466 // ring that goes through both south and north pole and crosses antimeridian
1467 tester::apply("r11cw",
1468 from_wkt<G>("POLYGON((-170 0,-170 -90,160 0,160 90,-170 0))"),
1469 160, -90, 190, 90);
1470
1471 // ring with edge that goes through the north pole and contains
1472 // south pole (the bounding box is the entire globe)
1473 tester::apply("r12cw",
1474 from_wkt<G>("POLYGON((-50 40,130 10,170 80,-50 40))"),
1475 -180, -90, 180, 90);
1476 // -180, 10, 180, 90);
1477
1478 // ring with edge that goes through the north pole
1479 tester::apply("r12cw-r",
1480 from_wkt<G>("POLYGON((-50 40,170 80,130 10,-50 40))"),
1481 -180, 10, 180, 90);
1482 // -180, -90, 180, 90);
1483
1484 // ring that represents a spherical cap near the north pole
1485 tester::apply("r13cw",
1486 from_wkt<G>("POLYGON((100 45,0 45,-100 45,-100 90,100 45))"),
1487 -100, 45, 100, 90);
1488
1489 // ring that represents the complement of a spherical cap
1490 // near the north pole
1491 tester::apply("r13cw-r",
1492 from_wkt<G>("POLYGON((-100 45,0 45,100 45,100 90,-100 45))"),
1493 -180, -90, 180, 90);
1494
1495 // ring that represents the complement of a spherical cap
1496 // that touches the south pole
1497 tester::apply("r14cw",
1498 from_wkt<G>("POLYGON((-100 45,0 45,100 45,100 -90,-100 45))"),
1499 -100, -90, 100, 57.26759279038765);
1500
1501 // ring that represents a spherical cap that touches the south pole
1502 tester::apply("r14cw-r",
1503 from_wkt<G>("POLYGON((100 45,0 45,-100 45,-100 -90,100 45))"),
1504 -180, -90, 180, 90);
1505
1506 // ring with edge that goes through the south pole
1507 tester::apply("r15cw",
1508 from_wkt<G>("POLYGON((-50 -40,130 -10,170 -80,-50 -40))"),
1509 -180, -90, 180, -10);
1510
1511 // ring with edge that goes through the south pole and contains
1512 // north pole (the bounding box is the entire globe)
1513 tester::apply("r15cw-r",
1514 from_wkt<G>("POLYGON((-50 -40,170 -80,130 -10,-50 -40))"),
1515 -180, -90, 180, 90);
1516
1517 // ring that does not contain any pole and lies in the lower hemisphere
1518 tester::apply("r16",
1519 from_wkt<G>("POLYGON((-50 -80,-50 -40,-30 -40,-30 -80,-50 -80))"),
1520 -50, -80.14892388341609, -30, -40);
1521
1522 // ring that lies in the lower hemisphere and contains both poles
1523 tester::apply("r16-r",
1524 from_wkt<G>("POLYGON((-50 -80,-30 -80,-30 -40,-50 -40,-50 -80))"),
1525 -180, -90, 180, 90);
1526
1527 // ring that goes through the south pole and contains the north pole
1528 tester::apply("r17cw",
1529 from_wkt<G>("POLYGON((50 0,50 -90,100 0,50 0))"),
1530 -180, -90, 180, 90);
1531
1532 // ring that goes through the south pole
1533 tester::apply("r17cw-r",
1534 from_wkt<G>("POLYGON((50 0,100 0,100 -90,50 0))"),
1535 50, -90, 100, 0);
1536
1537 // ring that goes through the south pole and contains the north pole
1538 tester::apply("r18cw",
1539 from_wkt<G>("POLYGON((50 0,50 -90,460 0,50 0))"),
1540 -180, -90, 180, 90);
1541
1542 // ring that goes through the south pole
1543 tester::apply("r18cw-r",
1544 from_wkt<G>("POLYGON((50 0,460 0,100 -90,50 0))"),
1545 50, -90, 100, 0);
1546
1547 // ring that goes through the south pole and contains the north pole
1548 tester::apply("r19cw",
1549 from_wkt<G>("POLYGON((50 0,50 -90,-260 0,50 0))"),
1550 -180, -90, 180, 90);
1551
1552 // ring that goes through the south pole
1553 tester::apply("r19cw-r",
1554 from_wkt<G>("POLYGON((50 0,-260 0,100 -90,50 0))"),
1555 50, -90, 100, 0);
1556
1557 // ring that goes through both poles
1558 tester::apply("r20cw",
1559 from_wkt<G>("POLYGON((10 0,10 90,20 0,20 -90,10 0))"),
1560 10, -90, 20, 90); // SUCCEEDS FOR WRONG REASON
1561
1562 // ring that goes through both poles
1563 tester::apply("r20cw-r",
1564 from_wkt<G>("POLYGON((10 0,10 -90,20 0,20 90,10 0))"),
1565 -180, -90, 180, 90); // FAILS NOW
1566
1567 // ring that goes through both poles and its boundary forms
1568 // a great circle
1569 tester::apply("r21cw",
1570 from_wkt<G>("POLYGON((-10 0,-10 90,170 0,170 -90,-10 0))"),
1571 -10, -90, 170, 90); // SUCCEEDS FOR WRONG REASON
1572
1573 // ring that goes through both poles and its boundary forms
1574 // a great circle
1575 tester::apply("r21cw-r",
1576 from_wkt<G>("POLYGON((-10 0,-10 -90,170 0,170 90,-10 0))"),
1577 170, -90, 350, 90); // FAILS NOW
1578 }
1579 #endif