]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/geometry/test/algorithms/envelope_expand/envelope_on_spheroid.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / geometry / test / algorithms / envelope_expand / envelope_on_spheroid.cpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2// Unit Test
3
1e59de90 4// Copyright (c) 2015-2022, Oracle and/or its affiliates.
7c673cae 5
b32b8144 6// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
7c673cae
FG
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
14#ifndef BOOST_TEST_MODULE
b32b8144 15#define BOOST_TEST_MODULE test_envelope_on_sphere_or_spheroid
7c673cae
FG
16#endif
17
18#include <boost/test/included/unit_test.hpp>
19
20#include <cstddef>
21#include <limits>
22#include <iostream>
23#include <string>
24
7c673cae 25#include <boost/numeric/conversion/bounds.hpp>
7c673cae 26
1e59de90
TL
27#include <from_wkt.hpp>
28#include <geometry_test_common.hpp>
29#include "test_envelope_expand_on_spheroid.hpp"
30
31#include <boost/geometry/algorithms/convert.hpp>
32#include <boost/geometry/algorithms/envelope.hpp>
33#include <boost/geometry/algorithms/reverse.hpp>
7c673cae
FG
34#include <boost/geometry/core/coordinate_dimension.hpp>
35#include <boost/geometry/core/tag.hpp>
36#include <boost/geometry/core/tags.hpp>
7c673cae 37#include <boost/geometry/geometries/geometries.hpp>
1e59de90 38#include <boost/geometry/index/detail/algorithms/is_valid.hpp>
7c673cae
FG
39#include <boost/geometry/io/dsv/write.hpp>
40#include <boost/geometry/io/wkt/wkt.hpp>
1e59de90
TL
41#include <boost/geometry/util/condition.hpp>
42#include <boost/geometry/util/type_traits.hpp>
20effc67 43
7c673cae 44
b32b8144
FG
45template <typename FormulaPolicy, typename CS_Tag>
46struct test_envelope
47{
48 template <typename Geometry, typename Box>
49 static inline void apply(Geometry& geometry, Box& detected)
50 {
51 bg::envelope(geometry, detected);
52 }
53};
54
55template <typename FormulaPolicy>
56struct test_envelope<FormulaPolicy, bg::geographic_tag>
57{
58 template <typename Geometry, typename Box>
59 static inline void apply(Geometry& geometry,
60 Box& detected)
61 {
92f5a8d4
TL
62 typedef bg::strategy::envelope::spherical_point point_strategy_t;
63 typedef bg::strategy::envelope::spherical_multipoint multi_point_strategy_t;
64 typedef bg::strategy::envelope::spherical_box box_strategy_t;
65 typedef bg::strategy::envelope::geographic<FormulaPolicy, bg::srs::spheroid<double>, double> strategy_t;
b32b8144 66
1e59de90 67 std::conditional_t
92f5a8d4 68 <
1e59de90 69 std::is_same<typename bg::tag<Geometry>::type, bg::point_tag>::value,
92f5a8d4 70 point_strategy_t,
1e59de90 71 std::conditional_t
92f5a8d4 72 <
1e59de90 73 std::is_same<typename bg::tag<Geometry>::type, bg::multi_point_tag>::value,
92f5a8d4 74 multi_point_strategy_t,
1e59de90 75 std::conditional_t
92f5a8d4 76 <
1e59de90 77 std::is_same<typename bg::tag<Geometry>::type, bg::box_tag>::value,
92f5a8d4
TL
78 box_strategy_t,
79 strategy_t
1e59de90
TL
80 >
81 >
82 > strategy;
92f5a8d4
TL
83
84 bg::envelope(geometry, detected, strategy);
b32b8144
FG
85 }
86};
87
88template <typename MBR, typename FormulaPolicy = bg::strategy::thomas>
7c673cae
FG
89class envelope_on_spheroid_basic_tester
90{
91private:
92 template
93 <
94 typename Geometry,
95 typename Tag = typename bg::tag<Geometry>::type
96 >
97 struct write_geometry
98 {
99 template <typename OutputStream>
100 static inline OutputStream& apply(OutputStream& os,
101 Geometry const& geometry)
102 {
103 os << bg::wkt(geometry);
104 return os;
105 }
106 };
107
108 template <typename Segment>
109 struct write_geometry<Segment, bg::segment_tag>
110 {
111 template <typename OutputStream>
112 static inline OutputStream& apply(OutputStream& os,
113 Segment const& segment)
114 {
115 os << "SEGMENT" << bg::dsv(segment);
116 return os;
117 }
118 };
119
120 template <typename Box>
121 struct write_geometry<Box, bg::box_tag>
122 {
123 template <typename OutputStream>
124 static inline OutputStream& apply(OutputStream& os,
125 Box const& box)
126 {
127 os << "BOX" << bg::dsv(box);
128 return os;
129 }
130 };
131
132 template <typename Geometry, typename Box>
133 static inline void check_message(bool same_boxes,
134 std::string const& case_id,
135 std::string const& units_str,
136 Geometry const& geometry,
137 Box const& expected,
138 Box const& detected)
139 {
140 std::ostringstream stream;
141 stream << "case ID: " << case_id << ", "
142 << "MBR units: " << units_str << "; "
143 << "geometry: ";
144
145 write_geometry<Geometry>::apply(stream, geometry);
146
147 stream << std::setprecision(17);
148
149 stream << "; " << "expected: " << bg::dsv(expected)
150 << ", " << "detected: " << bg::dsv(detected);
151
152 BOOST_CHECK_MESSAGE(same_boxes, stream.str());
153 }
154
b32b8144
FG
155 template
156 <
157 typename Geometry, typename Box,
158 typename T1, typename T2, typename T3, typename T4
159 >
160 static inline void check_message(bool same_boxes,
161 std::string const& case_id,
162 std::string const& units_str,
163 Geometry const& geometry,
164 T1 const& lon_min, T2 const& lat_min, double height_min,
165 T3 const& lon_max, T4 const& lat_max, double height_max,
166 Box const& detected)
167 {
168 std::ostringstream stream;
169 stream << "case ID: " << case_id << ", "
170 << "MBR units: " << units_str << "; "
171 << "geometry: ";
172
173 write_geometry<Geometry>::apply(stream, geometry);
174
175 stream << std::setprecision(17);
176
177 stream << "; " << "expected: ";
178
179 if (BOOST_GEOMETRY_CONDITION(bg::dimension<Box>::value == 2))
180 {
181 stream << "(" << lon_min << " " << lat_min
182 << ", " << lon_max << " " << lat_max << ")";
183 }
184 else
185 {
186 stream << "(" << lon_min << " " << lat_min << " " << height_min
187 << ", " << lon_max << " " << lat_max << " " << height_max << ")";
188 }
189 stream << ", " << "detected: " << bg::dsv(detected);
190
191 BOOST_CHECK_MESSAGE(same_boxes, stream.str());
192 }
193
194 template
195 <
196 typename Box, typename Geometry,
197 typename T1, typename T2, typename T3, typename T4
198 >
7c673cae
FG
199 static inline void base_test(std::string const& case_id,
200 Geometry const& geometry,
b32b8144
FG
201 T1 const& lon_min, T2 const& lat_min, double height_min,
202 T3 const& lon_max, T4 const& lat_max, double height_max,
7c673cae
FG
203 double tolerance)
204 {
205 typedef typename bg::coordinate_system<Box>::type::units box_units_type;
206
207 std::string const units_str = units2string<box_units_type>();
208
209 Box detected;
b32b8144
FG
210 test_envelope<FormulaPolicy, typename bg::cs_tag<Geometry>::type>
211 ::apply(geometry, detected);
7c673cae
FG
212
213#ifdef BOOST_GEOMETRY_TEST_DEBUG
214 std::cout << "geometry: ";
215 write_geometry<Geometry>::apply(std::cout, geometry);
216
217 std::cout << std::endl
218 << "MBR units: " << units_str
b32b8144
FG
219 << std::endl;
220 std::cout << "expected: ";
221 if (BOOST_GEOMETRY_CONDITION(bg::dimension<Box>::value == 2))
222 {
223 std::cout << "(" << lon_min << " " << lat_min
224 << ", " << lon_max << " " << lat_max << ")";
225 }
226 else
227 {
228 std::cout << "(" << lon_min << " " << lat_min << " " << height_min
229 << ", " << lon_max << " " << lat_max << " " << height_max << ")";
230 }
231 std::cout << std::endl
7c673cae
FG
232 << "detected: " << bg::dsv(detected)
233 << std::endl << std::endl;
234#endif
235
b32b8144
FG
236 bool check = box_check_equals<Box>::apply(detected,
237 lon_min, lat_min, height_min,
238 lon_max, lat_max, height_max,
239 tolerance);
240
241 check_message(check,
7c673cae 242 case_id, units_str,
b32b8144
FG
243 geometry,
244 lon_min, lat_min, height_min,
245 lon_max, lat_max, height_max,
246 detected);
7c673cae
FG
247
248 // if valid box is expected, check the validity
249 if (lon_min <= lon_max && lat_min <= lat_max && height_min <= height_max)
250 {
251 BOOST_CHECK_MESSAGE(bg::index::detail::is_valid(detected),
252 "Case ID: " << case_id << ", "
253 << "MBR units: " << units_str << "; "
254 << "Invalid Box: " << bg::dsv(detected));
255 }
256 }
257
258public:
b32b8144
FG
259 template
260 <
261 typename Geometry,
262 typename T1, typename T2, typename T3, typename T4
263 >
7c673cae
FG
264 static inline void apply(std::string const& case_id,
265 Geometry const& geometry,
b32b8144
FG
266 T1 const& lon_min, T2 const& lat_min, double height_min,
267 T3 const& lon_max, T4 const& lat_max, double height_max,
7c673cae
FG
268 double tolerance)
269 {
270 typedef other_system_info
271 <
272 typename bg::coordinate_system<MBR>::type
273 > other;
274
275 typedef bg::model::box
276 <
277 bg::model::point
278 <
279 typename bg::coordinate_type<MBR>::type,
280 bg::dimension<MBR>::value,
281 typename other::type
282 >
283 > other_mbr_type;
284
285#ifdef BOOST_GEOMETRY_TEST_DEBUG
286 std::cout << std::endl << std::endl;
287 std::cout << "case ID: " << case_id << std::endl << std::endl;
288#endif
289
290 base_test<MBR>(case_id, geometry,
291 lon_min, lat_min, height_min,
292 lon_max, lat_max, height_max,
293 tolerance);
294
295 if (lon_max < lon_min)
296 {
297 // we are in the case were a special MBR is returned;
298 // makes no sense to change units
299 base_test<other_mbr_type>(case_id, geometry,
300 lon_min, lat_min, height_min,
301 lon_max, lat_max, height_max,
302 tolerance);
303 }
304 else
305 {
306 base_test<other_mbr_type>(case_id, geometry,
307 other::convert(lon_min),
308 other::convert(lat_min),
309 height_min,
310 other::convert(lon_max),
311 other::convert(lat_max),
312 height_max,
313 tolerance);
314 }
315 }
316};
317
318
319// test the reverse of a geometry if it is either linear or ring
1e59de90 320template <typename Geometry>
7c673cae
FG
321struct test_reverse_geometry
322{
1e59de90 323 static bool const is_linear = bg::util::is_linear<Geometry>::value;
7c673cae
FG
324
325 // currently disable rings
326 static bool const is_ring = false;
1e59de90 327 // static bool const is_ring = bg::util::is_ring<Geometry>::value;
7c673cae 328
1e59de90 329 static bool const value = (is_linear || is_ring);
7c673cae
FG
330};
331
332template
333<
334 typename Geometry,
335 typename MBR,
336 typename Tag = typename bg::tag<Geometry>::type,
b32b8144
FG
337 bool TestReverse = test_reverse_geometry<Geometry>::value,
338 typename FormulaPolicy = bg::strategy::thomas
7c673cae 339>
b32b8144 340struct test_envelope_on_sphere_or_spheroid
7c673cae 341{
b32b8144
FG
342 template <typename T1, typename T2, typename T3, typename T4,
343 typename T5, typename T6, typename T7, typename T8>
7c673cae
FG
344 static inline void apply(std::string const& case_id,
345 Geometry const& geometry,
b32b8144
FG
346 T1 const& lon_min1, T2 const& lat_min1, double height_min1,
347 T3 const& lon_max1, T4 const& lat_max1, double height_max1,
348 T5 const& lon_min2, T6 const& lat_min2, double height_min2,
349 T7 const& lon_max2, T8 const& lat_max2, double height_max2,
7c673cae
FG
350 double tolerance = std::numeric_limits<double>::epsilon())
351 {
352 envelope_on_spheroid_basic_tester
353 <
b32b8144 354 MBR, FormulaPolicy
7c673cae
FG
355 >::apply(case_id, geometry,
356 lon_min1, lat_min1, height_min1,
357 lon_max1, lat_max1, height_max1,
358 tolerance);
359
360 if (BOOST_GEOMETRY_CONDITION(TestReverse))
361 {
362 std::string reversed_case_id = case_id + "-reverse";
363
364 Geometry reversed_geometry = geometry;
365 bg::reverse(reversed_geometry);
366 envelope_on_spheroid_basic_tester
367 <
b32b8144 368 MBR, FormulaPolicy
7c673cae
FG
369 >::apply(reversed_case_id, reversed_geometry,
370 lon_min2, lat_min2, height_min2,
371 lon_max2, lat_max2, height_max2,
b32b8144 372 tolerance);
7c673cae
FG
373 }
374
375#ifdef BOOST_GEOMETRY_TEST_DEBUG
376 std::cout << "=================="
377 << std::endl << std::endl;
378#endif
379 }
380
b32b8144
FG
381 template <typename T1, typename T2, typename T3, typename T4,
382 typename T5, typename T6, typename T7, typename T8>
7c673cae
FG
383 static inline void apply(std::string const& case_id,
384 Geometry const& geometry,
b32b8144
FG
385 T1 const& lon_min1, T2 const& lat_min1,
386 T3 const& lon_max1, T4 const& lat_max1,
387 T5 const& lon_min2, T6 const& lat_min2,
388 T7 const& lon_max2, T8 const& lat_max2,
7c673cae
FG
389 double tolerance = std::numeric_limits<double>::epsilon())
390 {
391 apply(case_id, geometry,
392 lon_min1, lat_min1, 0, lon_max1, lat_max1, 0,
393 lon_min2, lat_min2, 0, lon_max2, lat_max2, 0,
394 tolerance);
395 }
396
b32b8144 397 template <typename T1, typename T2, typename T3, typename T4>
7c673cae
FG
398 static inline void apply(std::string const& case_id,
399 Geometry const& geometry,
b32b8144
FG
400 T1 const& lon_min, T2 const& lat_min, double height_min,
401 T3 const& lon_max, T4 const& lat_max, double height_max,
7c673cae
FG
402 double tolerance = std::numeric_limits<double>::epsilon())
403 {
404 apply(case_id, geometry,
405 lon_min, lat_min, height_min,
406 lon_max, lat_max, height_max,
407 lon_min, lat_min, height_min,
408 lon_max, lat_max, height_max,
409 tolerance);
410 }
411
b32b8144 412 template <typename T1, typename T2, typename T3, typename T4>
7c673cae
FG
413 static inline void apply(std::string const& case_id,
414 Geometry const& geometry,
b32b8144
FG
415 T1 const& lon_min, T2 const& lat_min,
416 T3 const& lon_max, T4 const& lat_max,
7c673cae
FG
417 double tolerance = std::numeric_limits<double>::epsilon())
418 {
419 apply(case_id, geometry,
420 lon_min, lat_min, 0, lon_max, lat_max, 0,
421 tolerance);
422 }
423};
424
425
426// special tester for rings
427template <typename Geometry, typename MBR, bool TestReverse>
b32b8144 428struct test_envelope_on_sphere_or_spheroid<Geometry, MBR, bg::ring_tag, TestReverse>
7c673cae 429{
b32b8144
FG
430 template <typename T1, typename T2, typename T3, typename T4,
431 typename T5, typename T6, typename T7, typename T8>
7c673cae
FG
432 static inline void apply(std::string const& case_id,
433 Geometry const& geometry,
b32b8144
FG
434 T1 const& lon_min1, T2 const& lat_min1,
435 T3 const& lon_max1, T4 const& lat_max1,
436 T5 const& lon_min2, T6 const& lat_min2,
437 T7 const& lon_max2, T8 const& lat_max2,
438 double const& tolerance = std::numeric_limits<double>::epsilon())
7c673cae
FG
439 {
440 envelope_on_spheroid_basic_tester
441 <
442 MBR
443 >::apply(case_id, geometry,
92f5a8d4
TL
444 lon_min1, lat_min1, 0,
445 lon_max1, lat_max1, 0,
7c673cae
FG
446 tolerance);
447
448 std::string ccw_case_id = case_id + "-2ccw";
449
450 bg::model::ring
451 <
452 typename bg::point_type<Geometry>::type, false
453 > ccw_ring;
454 bg::convert(geometry, ccw_ring);
b32b8144 455
7c673cae
FG
456 envelope_on_spheroid_basic_tester
457 <
458 MBR
459 >::apply(ccw_case_id, ccw_ring,
92f5a8d4
TL
460 lon_min2, lat_min2, 0,
461 lon_max2, lat_max2, 0,
7c673cae
FG
462 tolerance);
463
464#ifdef BOOST_GEOMETRY_TEST_DEBUG
465 std::cout << "=================="
466 << std::endl << std::endl;
467#endif
468 }
469
b32b8144 470 template <typename T1, typename T2, typename T3, typename T4>
7c673cae
FG
471 static inline void apply(std::string const& case_id,
472 Geometry const& geometry,
b32b8144
FG
473 T1 const& lon_min, T2 const& lat_min,
474 T3 const& lon_max, T4 const& lat_max,
7c673cae
FG
475 double tolerance = std::numeric_limits<double>::epsilon())
476 {
477 apply(case_id, geometry,
478 lon_min, lat_min, lon_max, lat_max,
479 lon_min, lat_min, lon_max, lat_max,
480 tolerance);
481 }
482};
483
484
485template <typename CoordinateSystem, typename Geometry>
486void test_empty_geometry(std::string const& case_id, std::string const& wkt)
487{
488 std::size_t const dim = bg::dimension<Geometry>::value;
489
490 typedef bg::model::point<double, dim, CoordinateSystem> point_type;
491 typedef bg::model::box<point_type> B;
b32b8144 492 typedef test_envelope_on_sphere_or_spheroid<Geometry, B> tester;
7c673cae
FG
493
494 typedef typename bg::coordinate_type<Geometry>::type ct;
495 ct high_val = boost::numeric::bounds<ct>::highest();
496 ct low_val = boost::numeric::bounds<ct>::lowest();
497
498 if (BOOST_GEOMETRY_CONDITION(dim == 2))
499 {
500 tester::apply(case_id,
501 from_wkt<Geometry>(wkt),
502 high_val, high_val, low_val, low_val);
503 }
504 else
505 {
506 tester::apply(case_id,
507 from_wkt<Geometry>(wkt),
508 high_val, high_val, high_val, low_val, low_val, low_val);
509 }
510}
511
512
513template <typename CoordinateSystem>
514void test_envelope_point()
515{
516 typedef bg::model::point<double, 2, CoordinateSystem> point_type;
517 typedef point_type G;
518 typedef bg::model::box<point_type> B;
b32b8144 519 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
7c673cae
FG
520
521 tester::apply("p01",
522 from_wkt<G>("POINT(10 10)"),
523 10, 10, 10, 10);
524
525 tester::apply("p02",
526 from_wkt<G>("POINT(370 10)"),
527 10, 10, 10, 10);
528
529#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
530 tester::apply("p03",
531 from_wkt<G>("POINT(370 -350)"),
532 10, 10, 10, 10);
533#endif
534
535 // north and south poles
536 tester::apply("p04",
537 from_wkt<G>("POINT(0 90)"),
538 0, 90, 0, 90);
539
540 tester::apply("p04a",
541 from_wkt<G>("POINT(10 90)"),
542 0, 90, 0, 90);
543
544 tester::apply("p04b",
545 from_wkt<G>("POINT(270 90)"),
546 0, 90, 0, 90);
547
548#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
549 tester::apply("p04c",
550 from_wkt<G>("POINT(270 450)"),
551 0, 90, 0, 90);
552#endif
553
554 tester::apply("p04d",
555 from_wkt<G>("POINT(190 90)"),
556 0, 90, 0, 90);
557
558 tester::apply("p04e",
559 from_wkt<G>("POINT(-100 90)"),
560 0, 90, 0, 90);
561
562 tester::apply("p05",
563 from_wkt<G>("POINT(0 -90)"),
564 0, -90, 0, -90);
565
566 tester::apply("p05a",
567 from_wkt<G>("POINT(10 -90)"),
568 0, -90, 0, -90);
569
570 tester::apply("p05b",
571 from_wkt<G>("POINT(270 -90)"),
572 0, -90, 0, -90);
573
574#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
575 tester::apply("p05c",
576 from_wkt<G>("POINT(270 -450)"),
577 0, -90, 0, -90);
578#endif
579
580 tester::apply("p05d",
581 from_wkt<G>("POINT(190 -90)"),
582 0, -90, 0, -90);
583
584 tester::apply("p05e",
585 from_wkt<G>("POINT(-100 -90)"),
586 0, -90, 0, -90);
587
588 tester::apply("p05f",
589 from_wkt<G>("POINT(-100 -90)"),
590 0, -90, 0, -90);
591}
592
593BOOST_AUTO_TEST_CASE( envelope_point )
594{
595 test_envelope_point<bg::cs::spherical_equatorial<bg::degree> >();
596 test_envelope_point<bg::cs::geographic<bg::degree> >();
597}
598
599
600template <typename CoordinateSystem>
601void test_envelope_point_with_height()
602{
603 typedef bg::model::point<double, 3, CoordinateSystem> point_type;
604 typedef point_type G;
605 typedef bg::model::box<point_type> B;
b32b8144 606 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
7c673cae
FG
607
608 tester::apply("ph01",
609 from_wkt<G>("POINT(10 10 1256)"),
610 10, 10, 1256, 10, 10, 1256);
611}
612
613BOOST_AUTO_TEST_CASE( envelope_point_with_height )
614{
615 test_envelope_point_with_height
616 <
617 bg::cs::spherical_equatorial<bg::degree>
618 >();
619 test_envelope_point_with_height<bg::cs::geographic<bg::degree> >();
620}
621
622
b32b8144 623BOOST_AUTO_TEST_CASE( envelope_segment_sphere )
7c673cae
FG
624{
625 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
626 typedef bg::model::point<double, 2, coordinate_system_type> P;
627 typedef bg::model::segment<P> G;
628 typedef bg::model::box<P> B;
b32b8144 629 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
7c673cae
FG
630
631 double const eps = std::numeric_limits<double>::epsilon();
632
633 tester::apply("s01",
634 from_wkt<G>("SEGMENT(10 10,40 40)"),
635 10, 10, 40, 40);
636
637 tester::apply("s02",
638 from_wkt<G>("SEGMENT(10 10,40 10)"),
b32b8144
FG
639 10, 10, 40, 10.345270046149988);
640/*
641 tester::apply("s02",
642 from_wkt<G>("SEGMENT(1 2,70 1)"),
643 1, 1, 70, 2.01);
644*/
7c673cae
FG
645 tester::apply("s02a",
646 from_wkt<G>("SEGMENT(40 10,10 10)"),
647 10, 10, 40, 10.34527004614999);
648
649 tester::apply("s03",
650 from_wkt<G>("SEGMENT(160 10,-170 10)"),
651 160, 10, 190, 10.34527004614999);
652
653 tester::apply("s03a",
654 from_wkt<G>("SEGMENT(-170 10,160 10)"),
655 160, 10, 190, 10.34527004614999);
656
657 tester::apply("s03b",
658 from_wkt<G>("SEGMENT(-170 -10,160 -10)"),
659 160, -10.34527004614999, 190, -10);
660
661 tester::apply("s04",
662 from_wkt<G>("SEGMENT(-40 45,140 60)"),
663 -40, 45, 140, 90);
664
665 tester::apply("s04a",
666 from_wkt<G>("SEGMENT(-40 45,140 25)"),
667 -40, 25, 140, 90);
668
669 // segment ending at the north pole
670 tester::apply("s05",
671 from_wkt<G>("SEGMENT(40 45,80 90)"),
672 40, 45, 40, 90);
673
674 // segment starting at the north pole
675 tester::apply("s05a",
676 from_wkt<G>("SEGMENT(80 90,40 45)"),
677 40, 45, 40, 90);
678
679 // segment ending at the north pole
680 tester::apply("s06",
681 from_wkt<G>("SEGMENT(-40 45,80 90)"),
682 -40, 45, -40, 90);
683
684 // segment starting at the north pole
685 tester::apply("s06a",
686 from_wkt<G>("SEGMENT(70 90,-40 45)"),
687 -40, 45, -40, 90);
688
689 // segment ending at the north pole
690 tester::apply("s07",
691 from_wkt<G>("SEGMENT(40 -45,80 90)"),
692 40, -45, 40, 90);
693
694 // segment passing through the south pole
695 tester::apply("s08",
696 from_wkt<G>("SEGMENT(-170 -45,10 -30)"),
697 -170, -90, 10, -30);
698
699 tester::apply("s09",
700 from_wkt<G>("SEGMENT(1 -45,179 30)"),
701 1, -85.28884376852969, 179, 30,
702 3 * eps);
703
704 tester::apply("s09a",
705 from_wkt<G>("SEGMENT(2 -45,181 30)"),
706 2, -87.63659983704832, 181, 30);
707
708 // very long segment
709 tester::apply("s10",
710 from_wkt<G>("SEGMENT(0 -45,181 30)"),
b32b8144 711 -179, -87.636599837048323, 0, 30,
7c673cae
FG
712 2.0 * eps);
713
714 tester::apply("s11",
715 from_wkt<G>("SEGMENT(260 30,20 45)"),
716 -100, 30, 20, 57.93195594009233);
717
718 tester::apply("s11a",
719 from_wkt<G>("SEGMENT(260 45,20 30)"),
b32b8144 720 -100, 30, 20, 57.931955940092337);
7c673cae
FG
721
722 // segment degenerating to the north pole
723 tester::apply("s12",
724 from_wkt<G>("SEGMENT(10 90,20 90)"),
725 0, 90, 0, 90);
726
727 // segment degenerating to the south pole
728 tester::apply("s13",
729 from_wkt<G>("SEGMENT(10 -90,20 -90)"),
730 0, -90, 0, -90);
731
732 tester::apply("s14",
733 from_wkt<G>("SEGMENT(20 20,10 30)"),
734 10, 20, 20, 30);//48.87458730907602);
735
736 tester::apply("s15",
737 from_wkt<G>("SEGMENT(50 45,185 45)"),
738 50, 45, 185, 69.05897952775615);
739
740 // segment that lies on the equator
741 tester::apply("s16",
742 from_wkt<G>("SEGMENT(0 0,50 0)"),
743 0, 0, 50, 0);
744
745 // segment that lies on the equator
746 tester::apply("s16a",
747 from_wkt<G>("SEGMENT(-50 0,50 0)"),
748 -50, 0, 50, 0);
749
750 // segment that lies on the equator and touches antimeridian
751 tester::apply("s16b",
752 from_wkt<G>("SEGMENT(50 0,180 0)"),
753 50, 0, 180, 0);
754
755 // segment that lies on the equator and crosses antimeridian
756 tester::apply("s16c",
757 from_wkt<G>("SEGMENT(-170 0,160 0)"),
758 160, 0, 190, 0);
759
760 tester::apply("s17",
761 from_wkt<G>("SEGMENT(140 10, -140 80)"),
762 140, 10, 220, 80);
763
764 tester::apply("s17-r",
765 from_wkt<G>("SEGMENT(-140 80, 140 10)"),
766 140, 10, 220, 80);
767
768 tester::apply("s18",
769 from_wkt<G>("SEGMENT(20 10, 100 80)"),
770 20, 10, 100, 80);
771
772 tester::apply("s18-r",
773 from_wkt<G>("SEGMENT(100 80, 20 10)"),
774 20, 10, 100, 80);
775
776 // segment connecting the north and south pole
777 //
778 // this should be forbidden actually, as it is not well-defined
779 // with this test we demonstrate that the algorithm still returns
780 // something meaningful
781 tester::apply("s99",
782 from_wkt<G>("SEGMENT(10 90,20 -90)"),
783 0, -90, 0, 90);
784
785 // https://svn.boost.org/trac/boost/ticket/12106
786 tester::apply("s100_ticket_12106",
787 G(P(11.488323611111111, 53.687086666666673), P(11.488324166666667, 53.687086666666673)),
788 11.488323611111111, 53.687086666666673, 11.488324166666667, 53.687086666666673);
789
790 double const heps = eps / 2;
791
792 tester::apply("s101",
793 G(P(1, 1), P(1-heps, 1-heps)),
794 1-heps, 1-heps, 1, 1);
795 tester::apply("s102",
796 G(P(1, 1), P(1, 1-heps)),
797 1, 1-heps, 1, 1);
798 tester::apply("s103",
799 G(P(1, 1), P(1-heps, 1)),
800 1-heps, 1, 1, 1);
801 tester::apply("s104",
802 G(P(2, 1), P(1, 1-heps)),
803 1, 1-heps, 2, 1.000038070652770505);
804 tester::apply("s105",
805 G(P(1, 2), P(1-heps, 1)),
806 1-heps, 1, 1, 2);
807}
808
b32b8144
FG
809BOOST_AUTO_TEST_CASE( envelope_segment_spherical_polar )
810{
811 typedef bg::cs::spherical<bg::degree> coordinate_system_type;
812 typedef bg::model::point<double, 2, coordinate_system_type> P;
813 typedef bg::model::segment<P> G;
814 typedef bg::model::box<P> B;
815 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
816
817 tester::apply("s01",
818 from_wkt<G>("SEGMENT(10 10,40 40)"),
819 10, 10, 40, 40);
820
821 tester::apply("s02",
822 from_wkt<G>("SEGMENT(10 80,40 80)"),
823 10, 90 - 10.345270046149988, 40, 80);
824
825 tester::apply("s03",
826 from_wkt<G>("SEGMENT(160 80,-170 80)"),
827 160, 90 - 10.34527004614999, 190, 80);
828
829 // segment ending at the north pole
830 tester::apply("s05",
831 from_wkt<G>("SEGMENT(40 45,80 0)"),
832 40, 0, 40, 45);
833}
834
835
836BOOST_AUTO_TEST_CASE( envelope_segment_spheroid )
837{
838 typedef bg::cs::geographic<bg::degree> coordinate_system_type;
839 typedef bg::model::point<double, 2, coordinate_system_type> P;
840 typedef bg::model::segment<P> G;
841 typedef bg::model::box<P> B;
842 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
843
844 double const eps = std::numeric_limits<double>::epsilon();
845
846 tester::apply("s01",
847 from_wkt<G>("SEGMENT(10 10,40 40)"),
848 10, 10, 40, 40);
849
850 tester::apply("s02",
851 from_wkt<G>("SEGMENT(10 10,40 10)"),
852 10, 10, 40, 10.347587605817942);
853
854 tester::apply("s02a",
855 from_wkt<G>("SEGMENT(40 10,10 10)"),
856 10, 10, 40, 10.347587605817942);
857
858 tester::apply("s03",
859 from_wkt<G>("SEGMENT(160 10,-170 10)"),
860 160, 10, 190, 10.347587605817942);
861
862 tester::apply("s03a",
863 from_wkt<G>("SEGMENT(-170 10,160 10)"),
864 160, 10, 190, 10.347587605817942);
865
866 tester::apply("s03b",
867 from_wkt<G>("SEGMENT(-170 -10,160 -10)"),
868 160, -10.347587605817942, 190, -10);
869
870 tester::apply("s04",
871 from_wkt<G>("SEGMENT(-40 45,140 60)"),
872 -40, 45, 140, 90);
873
874 tester::apply("s04a",
875 from_wkt<G>("SEGMENT(-40 45,140 25)"),
876 -40, 25, 140, 90);
877
878 // segment ending at the north pole
879 tester::apply("s05",
880 from_wkt<G>("SEGMENT(40 45,80 90)"),
881 40, 45, 40, 90);
882
883 // segment starting at the north pole
884 tester::apply("s05a",
885 from_wkt<G>("SEGMENT(80 90,40 45)"),
886 40, 45, 40, 90);
887
888 // segment ending at the north pole
889 tester::apply("s06",
890 from_wkt<G>("SEGMENT(-40 45,80 90)"),
891 -40, 45, -40, 90);
892
893 // segment starting at the north pole
894 tester::apply("s06a",
895 from_wkt<G>("SEGMENT(70 90,-40 45)"),
896 -40, 45, -40, 90);
897
898 // segment ending at the north pole
899 tester::apply("s07",
900 from_wkt<G>("SEGMENT(40 -45,80 90)"),
901 40, -45, 40, 90);
902
903 // segment passing through the south pole
904 tester::apply("s08",
905 from_wkt<G>("SEGMENT(-170 -45,10 -30)"),
906 -170, -90, 10, -30);
907
908 tester::apply("s09",
909 from_wkt<G>("SEGMENT(1 -45,179 30)"),
910 1, rng(-85.392785243526134, -85.392785243525253), 179, 30);
911
912 tester::apply("s09a",
913 from_wkt<G>("SEGMENT(2 -45,181 30)"),
914 2, rng(-87.689300911353811, -87.689300911353371), 181, 30);
915
916 // very long segment
917 tester::apply("s10",
918 from_wkt<G>("SEGMENT(0 -45,181 30)"),
919 -179, rng(-87.689300911353797, -87.689300911353385), 0, 30);
920
921 tester::apply("s11",
922 from_wkt<G>("SEGMENT(260 30,20 45)"),
923 -100, 30, 20, rng(57.990810958016482, 57.990810958016965));
924
925 tester::apply("s11a",
926 from_wkt<G>("SEGMENT(260 45,20 30)"),
927 -100, 30, 20, rng(57.990810958016453, 57.990810958016965));
928
929 // segment degenerating to the north pole
930 tester::apply("s12",
931 from_wkt<G>("SEGMENT(10 90,20 90)"),
932 0, 90, 0, 90);
933
934 // segment degenerating to the south pole
935 tester::apply("s13",
936 from_wkt<G>("SEGMENT(10 -90,20 -90)"),
937 0, -90, 0, -90);
938
939 tester::apply("s14",
940 from_wkt<G>("SEGMENT(20 20,10 30)"),
941 10, 20, 20, 30);//48.87458730907602);
942
943 tester::apply("s15",
944 from_wkt<G>("SEGMENT(50 45,185 45)"),
945 50, 45, 185, rng(69.098479073902851, 69.098479073903178));
946
947 // segment that lies on the equator
948 tester::apply("s16",
949 from_wkt<G>("SEGMENT(0 0,50 0)"),
950 0, 0, 50, 0);
951
952 // segment that lies on the equator
953 tester::apply("s16a",
954 from_wkt<G>("SEGMENT(-50 0,50 0)"),
955 -50, 0, 50, 0);
956
957 // segment that lies on the equator and touches antimeridian
958 tester::apply("s16b",
959 from_wkt<G>("SEGMENT(50 0,180 0)"),
960 50, 0, 180, 0);
961
962 // segment that lies on the equator and crosses antimeridian
963 tester::apply("s16c",
964 from_wkt<G>("SEGMENT(-170 0,160 0)"),
965 160, 0, 190, 0);
966
967 tester::apply("s17",
968 from_wkt<G>("SEGMENT(140 10, -140 80)"),
969 140, 10, 220, 80);
970
971 tester::apply("s17-r",
972 from_wkt<G>("SEGMENT(-140 80, 140 10)"),
973 140, 10, 220, 80);
974
975 tester::apply("s18",
976 from_wkt<G>("SEGMENT(20 10, 100 80)"),
977 20, 10, 100, 80);
978
979 tester::apply("s18-r",
980 from_wkt<G>("SEGMENT(100 80, 20 10)"),
981 20, 10, 100, 80);
982
983 // segment connecting the north and south pole
984 //
985 // this should be forbidden actually, as it is not well-defined
986 // with this test we demonstrate that the algorithm still returns
987 // something meaningful
988 tester::apply("s99",
989 from_wkt<G>("SEGMENT(10 90,20 -90)"),
990 0, -90, 0, 90);
991
992 // https://svn.boost.org/trac/boost/ticket/12106
993 tester::apply("s100_ticket_12106",
994 G(P(11.488323611111111, 53.687086666666673), P(11.488324166666667, 53.687086666666673)),
995 11.488323611111111, 53.687086666666673, 11.488324166666667, 53.687086666666673);
996
997 double const heps = eps / 2;
998
999 tester::apply("s101",
1000 G(P(1, 1), P(1-heps, 1-heps)),
1001 1-heps, 1-heps, 1, 1);
1002 tester::apply("s102",
1003 G(P(1, 1), P(1, 1-heps)),
1004 1, 1-heps, 1, 1);
1005 tester::apply("s103",
1006 G(P(1, 1), P(1-heps, 1)),
1007 1-heps, 1, 1, 1);
1008 tester::apply("s104",
1009 G(P(2, 1), P(1, 1-heps)),
1010 1, 1-heps, 2, rng(1.0000383271568751, 1.0000383271569036));
1011 tester::apply("s105",
1012 G(P(1, 2), P(1-heps, 1)),
1013 1-heps, 1, 1, 2);
1014}
1015
1016BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_thomas )
1017{
1018
1019 typedef bg::cs::geographic<bg::degree> coordinate_system_type;
1020 typedef bg::model::point<double, 2, coordinate_system_type> P;
1021 typedef bg::model::segment<P> G;
1022 typedef bg::model::box<P> B;
1023 typedef test_envelope_on_sphere_or_spheroid
1024 <
1025 G, B,
1026 bg::tag<G>::type,
1027 test_reverse_geometry<G>::value,
1028 bg::strategy::thomas
1029 > tester;
1030
1031 tester::apply("s01",
1032 from_wkt<G>("SEGMENT(10 10,40 40)"),
1033 10, 10, 40, 40);
1034
1035 tester::apply("s02",
1036 from_wkt<G>("SEGMENT(10 10,40 10)"),
1037 10, 10, 40, 10.347587605817942);
1038
1039 tester::apply("s02a",
1040 from_wkt<G>("SEGMENT(40 10,10 10)"),
1041 10, 10, 40, 10.347587605817942);
1042
1043 tester::apply("s03",
1044 from_wkt<G>("SEGMENT(160 10,-170 10)"),
1045 160, 10, 190, 10.347587605817942);
1046
1047 tester::apply("s03a",
1048 from_wkt<G>("SEGMENT(-170 10,160 10)"),
1049 160, 10, 190, 10.347587605817942);
1050
1051 tester::apply("s03b",
1052 from_wkt<G>("SEGMENT(-170 -10,160 -10)"),
1053 160, -10.347587605817942, 190, -10);
1054
1055 tester::apply("s04",
1056 from_wkt<G>("SEGMENT(-40 45,140 60)"),
1057 -40, 45, 140, 90);
1058
1059 tester::apply("s04a",
1060 from_wkt<G>("SEGMENT(-40 45,140 25)"),
1061 -40, 25, 140, 90);
1062
1063 // segment ending at the north pole
1064 tester::apply("s05",
1065 from_wkt<G>("SEGMENT(40 45,80 90)"),
1066 40, 45, 40, 90);
1067
1068 // segment starting at the north pole
1069 tester::apply("s05a",
1070 from_wkt<G>("SEGMENT(80 90,40 45)"),
1071 40, 45, 40, 90);
1072
1073 // segment ending at the north pole
1074 tester::apply("s06",
1075 from_wkt<G>("SEGMENT(-40 45,80 90)"),
1076 -40, 45, -40, 90);
1077
1078 // segment starting at the north pole
1079 tester::apply("s06a",
1080 from_wkt<G>("SEGMENT(70 90,-40 45)"),
1081 -40, 45, -40, 90);
1082
1083 // segment ending at the north pole
1084 tester::apply("s07",
1085 from_wkt<G>("SEGMENT(40 -45,80 90)"),
1086 40, -45, 40, 90);
1087
1088 // segment passing through the south pole
1089 tester::apply("s08",
1090 from_wkt<G>("SEGMENT(-170 -45,10 -30)"),
1091 -170, -90, 10, -30);
1092
1093 tester::apply("s09",
1094 from_wkt<G>("SEGMENT(1 -45,179 30)"),
1095 1, rng(-85.392785243526134, -85.392785243525253), 179, 30);
1096
1097 tester::apply("s09a",
1098 from_wkt<G>("SEGMENT(2 -45,181 30)"),
1099 2, rng(-87.689300911353811, -87.689300911353371), 181, 30);
1100
1101 // very long segment
1102 tester::apply("s10",
1103 from_wkt<G>("SEGMENT(0 -45,181 30)"),
1104 -179, rng(-87.689300911353797, -87.689300911353385), 0, 30);
1105
1106 tester::apply("s11",
1107 from_wkt<G>("SEGMENT(260 30,20 45)"),
1108 -100, 30, 20, rng(57.990810958016482, 57.990810958016965));
1109
1110 tester::apply("s11a",
1111 from_wkt<G>("SEGMENT(260 45,20 30)"),
1112 -100, 30, 20, rng(57.990810958016453, 57.990810958016965));
1113
1114 // segment degenerating to the north pole
1115 tester::apply("s12",
1116 from_wkt<G>("SEGMENT(10 90,20 90)"),
1117 0, 90, 0, 90);
1118
1119 // segment degenerating to the south pole
1120 tester::apply("s13",
1121 from_wkt<G>("SEGMENT(10 -90,20 -90)"),
1122 0, -90, 0, -90);
1123
1124 tester::apply("s14",
1125 from_wkt<G>("SEGMENT(20 20,10 30)"),
1126 10, 20, 20, 30);//48.87458730907602);
1127
1128 tester::apply("s15",
1129 from_wkt<G>("SEGMENT(50 45,185 45)"),
1130 50, 45, 185, rng(69.098479073902851, 69.098479073903178));
1131
1132 // segment that lies on the equator
1133 tester::apply("s16",
1134 from_wkt<G>("SEGMENT(0 0,50 0)"),
1135 0, 0, 50, 0);
1136
1137 // segment that lies on the equator
1138 tester::apply("s16a",
1139 from_wkt<G>("SEGMENT(-50 0,50 0)"),
1140 -50, 0, 50, 0);
1141
1142 // segment that lies on the equator and touches antimeridian
1143 tester::apply("s16b",
1144 from_wkt<G>("SEGMENT(50 0,180 0)"),
1145 50, 0, 180, 0);
1146
1147 // segment that lies on the equator and crosses antimeridian
1148 tester::apply("s16c",
1149 from_wkt<G>("SEGMENT(-170 0,160 0)"),
1150 160, 0, 190, 0);
1151
1152 tester::apply("s17",
1153 from_wkt<G>("SEGMENT(140 10, -140 80)"),
1154 140, 10, 220, 80);
1155
1156 tester::apply("s17-r",
1157 from_wkt<G>("SEGMENT(-140 80, 140 10)"),
1158 140, 10, 220, 80);
1159
1160 tester::apply("s18",
1161 from_wkt<G>("SEGMENT(20 10, 100 80)"),
1162 20, 10, 100, 80);
1163
1164 tester::apply("s18-r",
1165 from_wkt<G>("SEGMENT(100 80, 20 10)"),
1166 20, 10, 100, 80);
1167
1168}
1169
1170BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_andoyer )
1171{
1172
1173 typedef bg::cs::geographic<bg::degree> coordinate_system_type;
1174 typedef bg::model::point<double, 2, coordinate_system_type> P;
1175 typedef bg::model::segment<P> G;
1176 typedef bg::model::box<P> B;
1177 typedef test_envelope_on_sphere_or_spheroid
1178 <
1179 G, B,
1180 bg::tag<G>::type,
1181 test_reverse_geometry<G>::value,
1182 bg::strategy::andoyer
1183 > tester;
1184
1185 tester::apply("s01",
1186 from_wkt<G>("SEGMENT(10 10,40 40)"),
1187 10, 10, 40, 40);
1188
1189 tester::apply("s02",
1190 from_wkt<G>("SEGMENT(10 10,40 10)"),
1191 10, 10, 40, 10.34758709960203);
1192
1193 tester::apply("s02a",
1194 from_wkt<G>("SEGMENT(40 10,10 10)"),
1195 10, 10, 40, 10.34758709960203);
1196
1197 tester::apply("s03",
1198 from_wkt<G>("SEGMENT(160 10,-170 10)"),
1199 160, 10, 190, 10.34758709960203);
1200
1201 tester::apply("s03a",
1202 from_wkt<G>("SEGMENT(-170 10,160 10)"),
1203 160, 10, 190, 10.34758709960203);
1204
1205 tester::apply("s03b",
1206 from_wkt<G>("SEGMENT(-170 -10,160 -10)"),
1207 160, -10.34758709960203, 190, -10);
1208
1209 tester::apply("s04",
1210 from_wkt<G>("SEGMENT(-40 45,140 60)"),
1211 -40, 45, 140, 90);
1212
1213 tester::apply("s04a",
1214 from_wkt<G>("SEGMENT(-40 45,140 25)"),
1215 -40, 25, 140, 90);
1216
1217 // segment ending at the north pole
1218 tester::apply("s05",
1219 from_wkt<G>("SEGMENT(40 45,80 90)"),
1220 40, 45, 40, 90);
1221
1222 // segment starting at the north pole
1223 tester::apply("s05a",
1224 from_wkt<G>("SEGMENT(80 90,40 45)"),
1225 40, 45, 40, 90);
1226
1227 // segment ending at the north pole
1228 tester::apply("s06",
1229 from_wkt<G>("SEGMENT(-40 45,80 90)"),
1230 -40, 45, -40, 90);
1231
1232 // segment starting at the north pole
1233 tester::apply("s06a",
1234 from_wkt<G>("SEGMENT(70 90,-40 45)"),
1235 -40, 45, -40, 90);
1236
1237 // segment ending at the north pole
1238 tester::apply("s07",
1239 from_wkt<G>("SEGMENT(40 -45,80 90)"),
1240 40, -45, 40, 90);
1241
1242 // segment passing through the south pole
1243 tester::apply("s08",
1244 from_wkt<G>("SEGMENT(-170 -45,10 -30)"),
1245 -170, -90, 10, -30);
1246
1247 tester::apply("s09",
1248 from_wkt<G>("SEGMENT(1 -45,179 30)"),
1249 1, rng(-85.394745211091248, -85.394745211090353), 179, 30);
1250
1251 tester::apply("s09a",
1252 from_wkt<G>("SEGMENT(2 -45,181 30)"),
1253 2, rng(-87.690317839849726, -87.690317839849271), 181, 30);
1254
1255 // very long segment
1256 tester::apply("s10",
1257 from_wkt<G>("SEGMENT(0 -45,181 30)"),
1258 -179, rng(-87.69031783984974, -87.690317839849271), 0, 30);
1259
1260 tester::apply("s11",
1261 from_wkt<G>("SEGMENT(260 30,20 45)"),
1262 -100, 30, 20, rng(57.990742552279649, 57.990742552280153));
1263
1264 tester::apply("s11a",
1265 from_wkt<G>("SEGMENT(260 45,20 30)"),
1266 -100, 30, 20, rng(57.99074255227962, 57.990742552280118));
1267
1268 // segment degenerating to the north pole
1269 tester::apply("s12",
1270 from_wkt<G>("SEGMENT(10 90,20 90)"),
1271 0, 90, 0, 90);
1272
1273 // segment degenerating to the south pole
1274 tester::apply("s13",
1275 from_wkt<G>("SEGMENT(10 -90,20 -90)"),
1276 0, -90, 0, -90);
1277
1278 tester::apply("s14",
1279 from_wkt<G>("SEGMENT(20 20,10 30)"),
1280 10, 20, 20, 30);//48.87458730907602);
1281
1282 tester::apply("s15",
1283 from_wkt<G>("SEGMENT(50 45,185 45)"),
1284 50, 45, 185, rng(69.098446893408124, 69.09844689340845));
1285
1286 // segment that lies on the equator
1287 tester::apply("s16",
1288 from_wkt<G>("SEGMENT(0 0,50 0)"),
1289 0, 0, 50, 0);
1290
1291 // segment that lies on the equator
1292 tester::apply("s16a",
1293 from_wkt<G>("SEGMENT(-50 0,50 0)"),
1294 -50, 0, 50, 0);
1295
1296 // segment that lies on the equator and touches antimeridian
1297 tester::apply("s16b",
1298 from_wkt<G>("SEGMENT(50 0,180 0)"),
1299 50, 0, 180, 0);
1300
1301 // segment that lies on the equator and crosses antimeridian
1302 tester::apply("s16c",
1303 from_wkt<G>("SEGMENT(-170 0,160 0)"),
1304 160, 0, 190, 0);
1305
1306 tester::apply("s17",
1307 from_wkt<G>("SEGMENT(140 10, -140 80)"),
1308 140, 10, 220, 80);
1309
1310 tester::apply("s17-r",
1311 from_wkt<G>("SEGMENT(-140 80, 140 10)"),
1312 140, 10, 220, 80);
1313
1314 tester::apply("s18",
1315 from_wkt<G>("SEGMENT(20 10, 100 80)"),
1316 20, 10, 100, 80);
1317
1318 tester::apply("s18-r",
1319 from_wkt<G>("SEGMENT(100 80, 20 10)"),
1320 20, 10, 100, 80);
1321
1322 // segments intersecting pole
1323 tester::apply("s19",
1324 from_wkt<G>("SEGMENT(0 0, 180 0)"),
1325 0, 0, 180, 90);
1326 tester::apply("s20",
1327 from_wkt<G>("SEGMENT(0 0, -180 0)"),
1328 0, 0, 180, 90);
1329 tester::apply("s21",
1330 from_wkt<G>("SEGMENT(0 1, 180 1)"),
1331 0, 1, 180, 90,
1332 std::numeric_limits<double>::epsilon() * 10);
1333 tester::apply("s22",
1334 from_wkt<G>("SEGMENT(0 -1, 180 -1)"),
1335 0, -90, 180, -1,
1336 std::numeric_limits<double>::epsilon() * 10);
1337
1338}
1339
1340BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_vincenty )
1341{
1342
1343 typedef bg::cs::geographic<bg::degree> coordinate_system_type;
1344 typedef bg::model::point<double, 2, coordinate_system_type> P;
1345 typedef bg::model::segment<P> G;
1346 typedef bg::model::box<P> B;
1347 typedef test_envelope_on_sphere_or_spheroid
1348 <
1349 G, B,
1350 bg::tag<G>::type,
1351 test_reverse_geometry<G>::value,
1352 bg::strategy::vincenty
1353 > tester;
1354
1355 tester::apply("s01",
1356 from_wkt<G>("SEGMENT(10 10,40 40)"),
1357 10, 10, 40, 40);
1358
1359 tester::apply("s02",
1360 from_wkt<G>("SEGMENT(10 10,40 10)"),
1361 10, 10, 40, rng(10.347587628821937, 10.347587628821941));
1362
1363 tester::apply("s02a",
1364 from_wkt<G>("SEGMENT(40 10,10 10)"),
1365 10, 10, 40, rng(10.347587628821937, 10.347587628821941));
1366
1367 tester::apply("s03",
1368 from_wkt<G>("SEGMENT(160 10,-170 10)"),
1369 160, 10, 190, rng(10.347587628821937, 10.347587628821941));
1370
1371 tester::apply("s03a",
1372 from_wkt<G>("SEGMENT(-170 10,160 10)"),
1373 160, 10, 190, rng(10.347587628821937, 10.347587628821941));
1374
1375 tester::apply("s03b",
1376 from_wkt<G>("SEGMENT(-170 -10,160 -10)"),
1377 160, rng(-10.347587628821941, -10.347587628821937), 190, -10);
1378
1379 tester::apply("s04",
1380 from_wkt<G>("SEGMENT(-40 45,140 60)"),
1381 -40, 45, 140, 90);
1382
1383 tester::apply("s04a",
1384 from_wkt<G>("SEGMENT(-40 45,140 25)"),
1385 -40, 25, 140, 90);
1386
1387 // segment ending at the north pole
1388 tester::apply("s05",
1389 from_wkt<G>("SEGMENT(40 45,80 90)"),
1390 40, 45, 40, 90);
1391
1392 // segment starting at the north pole
1393 tester::apply("s05a",
1394 from_wkt<G>("SEGMENT(80 90,40 45)"),
1395 40, 45, 40, 90);
1396
1397 // segment ending at the north pole
1398 tester::apply("s06",
1399 from_wkt<G>("SEGMENT(-40 45,80 90)"),
1400 -40, 45, -40, 90);
1401
1402 // segment starting at the north pole
1403 tester::apply("s06a",
1404 from_wkt<G>("SEGMENT(70 90,-40 45)"),
1405 -40, 45, -40, 90);
1406
1407 // segment ending at the north pole
1408 tester::apply("s07",
1409 from_wkt<G>("SEGMENT(40 -45,80 90)"),
1410 40, -45, 40, 90);
1411
1412 // segment passing through the south pole
1413 tester::apply("s08",
1414 from_wkt<G>("SEGMENT(-170 -45,10 -30)"),
1415 -170, -90, 10, -30);
1416
1417 tester::apply("s09",
1418 from_wkt<G>("SEGMENT(1 -45,179 30)"),
1419 1, rng(-85.392840929577218, -85.392840929576352), 179, 30);
1420
1421 tester::apply("s09a",
1422 from_wkt<G>("SEGMENT(2 -45,181 30)"),
1423 2, rng(-87.689330275867817, -87.689330275867405), 181, 30);
1424
1425 // very long segment
1426 tester::apply("s10",
1427 from_wkt<G>("SEGMENT(0 -45,181 30)"),
1428 -179, rng(-87.689330275867832, -87.689330275867405), 0, 30);
1429
1430 tester::apply("s11",
1431 from_wkt<G>("SEGMENT(260 30,20 45)"),
1432 -100, 30, 20, rng(57.990810647056549, 57.990810647057032));
1433
1434 tester::apply("s11a",
1435 from_wkt<G>("SEGMENT(260 45,20 30)"),
1436 -100, 30, 20, rng(57.990810647056541, 57.990810647057032));
1437
1438 // segment degenerating to the north pole
1439 tester::apply("s12",
1440 from_wkt<G>("SEGMENT(10 90,20 90)"),
1441 0, 90, 0, 90);
1442
1443 // segment degenerating to the south pole
1444 tester::apply("s13",
1445 from_wkt<G>("SEGMENT(10 -90,20 -90)"),
1446 0, -90, 0, -90);
1447
1448 tester::apply("s14",
1449 from_wkt<G>("SEGMENT(20 20,10 30)"),
1450 10, 20, 20, 30);//48.87458730907602);
1451
1452 tester::apply("s15",
1453 from_wkt<G>("SEGMENT(50 45,185 45)"),
1454 50, 45, 185, rng(69.098479136978156, 69.098479136978497));
1455
1456 // segment that lies on the equator
1457 tester::apply("s16",
1458 from_wkt<G>("SEGMENT(0 0,50 0)"),
1459 0, 0, 50, 0);
1460
1461 // segment that lies on the equator
1462 tester::apply("s16a",
1463 from_wkt<G>("SEGMENT(-50 0,50 0)"),
1464 -50, 0, 50, 0);
1465
1466 // segment that lies on the equator and touches antimeridian
1467 tester::apply("s16b",
1468 from_wkt<G>("SEGMENT(50 0,180 0)"),
1469 50, 0, 180, 0);
1470
1471 // segment that lies on the equator and crosses antimeridian
1472 tester::apply("s16c",
1473 from_wkt<G>("SEGMENT(-170 0,160 0)"),
1474 160, 0, 190, 0);
1475
1476 tester::apply("s17",
1477 from_wkt<G>("SEGMENT(140 10, -140 80)"),
1478 140, 10, 220, 80);
1479
1480 tester::apply("s17-r",
1481 from_wkt<G>("SEGMENT(-140 80, 140 10)"),
1482 140, 10, 220, 80);
1483
1484 tester::apply("s18",
1485 from_wkt<G>("SEGMENT(20 10, 100 80)"),
1486 20, 10, 100, 80);
1487
1488 tester::apply("s18-r",
1489 from_wkt<G>("SEGMENT(100 80, 20 10)"),
1490 20, 10, 100, 80);
1491
1492}
1493
1494BOOST_AUTO_TEST_CASE( envelope_segment_sphere_with_height )
1495{
1496 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
1497 typedef bg::model::point<double, 3, coordinate_system_type> point_type;
1498 typedef bg::model::segment<point_type> G;
1499 typedef bg::model::box<point_type> B;
1500 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
1501
1502 tester::apply("sh01",
1503 from_wkt<G>("SEGMENT(10 10 567,40 40 1356)"),
1504 10, 10, 567, 40, 40, 1356);
1505
1506 tester::apply("sh02",
1507 from_wkt<G>("SEGMENT(10 10 1356,40 40 567)"),
1508 10, 10, 567, 40, 40, 1356);
1509}
7c673cae 1510
b32b8144 1511BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_height )
7c673cae 1512{
b32b8144 1513 typedef bg::cs::geographic<bg::degree> coordinate_system_type;
7c673cae
FG
1514 typedef bg::model::point<double, 3, coordinate_system_type> point_type;
1515 typedef bg::model::segment<point_type> G;
1516 typedef bg::model::box<point_type> B;
b32b8144 1517 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
7c673cae
FG
1518
1519 tester::apply("sh01",
1520 from_wkt<G>("SEGMENT(10 10 567,40 40 1356)"),
1521 10, 10, 567, 40, 40, 1356);
1522
1523 tester::apply("sh02",
1524 from_wkt<G>("SEGMENT(10 10 1356,40 40 567)"),
1525 10, 10, 567, 40, 40, 1356);
1526}
1527
7c673cae
FG
1528template <typename CoordinateSystem>
1529void test_envelope_multipoint()
1530{
1531 typedef bg::model::point<double, 2, CoordinateSystem> P;
1532 typedef bg::model::multi_point<P> G;
1533 typedef bg::model::box<P> B;
b32b8144 1534 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
7c673cae
FG
1535
1536 // empty multipoint
1537 test_empty_geometry<CoordinateSystem, G>("mp00", "MULTIPOINT()");
1538
1539 tester::apply("mp01",
1540 from_wkt<G>("MULTIPOINT(0 0,10 10)"),
1541 0, 0, 10, 10);
1542
1543 tester::apply("mp02",
1544 from_wkt<G>("MULTIPOINT(0 10,10 0)"),
1545 0, 0, 10, 10);
1546
1547 tester::apply("mp03",
1548 from_wkt<G>("MULTIPOINT(-10 20,0 10,10 0)"),
1549 -10, 0, 10, 20);
1550
1551 tester::apply("mp04",
1552 from_wkt<G>("MULTIPOINT(-10 20,0 10,10 -15)"),
1553 -10, -15, 10, 20);
1554
1555 tester::apply("mp05",
1556 from_wkt<G>("MULTIPOINT(-85 10,85 -20)"),
1557 -85, -20, 85, 10);
1558
1559 tester::apply("mp06",
1560 from_wkt<G>("MULTIPOINT(-95 10,85 -20)"),
1561 -95, -20, 85, 10);
1562
1563 tester::apply("mp07",
1564 from_wkt<G>("MULTIPOINT(-96 10,85 -20)"),
1565 85, -20, -96+360, 10);
1566
1567 tester::apply("mp08",
1568 from_wkt<G>("MULTIPOINT(175 15,-175 -20)"),
1569 175, -20, -175+360, 15);
1570
1571 tester::apply("mp09",
1572 from_wkt<G>("MULTIPOINT(170 15,170 20,-175 10,-90 10,10 10)"),
1573 170, 10, 10+360, 20);
1574
1575 // this should fail
1576 tester::apply("mp09a",
1577 from_wkt<G>("MULTIPOINT(10 10,170 15,170 20,-175 10,-90 10)"),
1578 170, 10, 10+360, 20);
1579
1580
1581 tester::apply("mp10",
1582 from_wkt<G>("MULTIPOINT(10 10,20 90,30 -90)"),
1583 10, -90, 10, 90);
1584
1585 // this should fail
1586 tester::apply("mp11",
1587 from_wkt<G>("MULTIPOINT(179 90,-179 -90,10 10)"),
1588 10, -90, 10, 90);
1589
1590 tester::apply("mp11a",
1591 from_wkt<G>("MULTIPOINT(10 10,179 90,-179 -90)"),
1592 10, -90, 10, 90);
1593
1594 // this should fail
1595 tester::apply("mp11b",
1596 from_wkt<G>("MULTIPOINT(179 90,-179 -90,-90 0)"),
1597 -90, -90, -90, 90);
1598
1599 tester::apply("mp11c",
1600 from_wkt<G>("MULTIPOINT(-90 0,179 90,-179 -90,-90 0)"),
1601 -90, -90, -90, 90);
1602
1603 tester::apply("mp12",
1604 from_wkt<G>("MULTIPOINT(170 -30,175 60,-178 10)"),
1605 170, -30, -178+360, 60);
1606
1607 tester::apply("mp13",
1608 from_wkt<G>("MULTIPOINT(-170 -30,-175 40,178 50)"),
1609 178, -30, -170+360, 50);
1610
1611 tester::apply("mp13a",
1612 from_wkt<G>("MULTIPOINT(-170 -30,178 50)"),
1613 178, -30, -170+360, 50);
1614
1615 tester::apply("mp13b",
1616 from_wkt<G>("MULTIPOINT(-170 -30,178 50,-175 40)"),
1617 178, -30, -170+360, 50);
1618
1619 tester::apply("mp15",
1620 from_wkt<G>("MULTIPOINT(10 -20)"),
1621 10, -20, 10, -20);
1622
1623 tester::apply("mp16",
1624 from_wkt<G>("MULTIPOINT(0 90,10 90)"),
1625 0, 90, 0, 90);
1626
1627 tester::apply("mp17",
1628 from_wkt<G>("MULTIPOINT(179 80,-179 -80,10 10)"),
1629 10, -80, -179+360, 80);
1630
1631 tester::apply("mp17a",
1632 from_wkt<G>("MULTIPOINT(10 10,179 80,-179 -80)"),
1633 10, -80, -179+360, 80);
1634
1635 tester::apply("mp17b",
1636 from_wkt<G>("MULTIPOINT(179 80,-179 -80,-90 0)"),
1637 179, -80, -90+360, 80);
1638
1639 tester::apply("mp17c",
1640 from_wkt<G>("MULTIPOINT(-90 0,179 80,-179 -80,-90 0)"),
1641 179, -80, -90+360, 80);
1642
1643 tester::apply("mp18",
1644 from_wkt<G>("MULTIPOINT(-170 45,20 25,40 40)"),
1645 20, 25, 190, 45);
1646
1647#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
1648 tester::apply("mp18a",
1649 from_wkt<G>("MULTIPOINT(10 135,20 25,40 40)"),
1650 20, 25, 190, 45);
1651#endif
1652
1653 tester::apply("mp19",
1654 from_wkt<G>("MULTIPOINT(350 45,20 25,40 40)"),
1655 -10, 25, 40, 45);
1656
1657#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
1658 tester::apply("mp19a",
1659 from_wkt<G>("MULTIPOINT(170 135,20 25,40 40)"),
1660 -10, 25, 40, 45);
1661#endif
1662
1663 double eps = std::numeric_limits<double>::epsilon();
1664 double heps = eps / 2;
1665 {
1666 G mp;
1667 mp.push_back(P(1, 1));
1668 mp.push_back(P(1-heps, 1-heps));
1669 tester::apply("mp20", mp, 1-heps, 1-heps, 1, 1);
1670 }
1671}
1672
1673BOOST_AUTO_TEST_CASE( envelope_multipoint )
1674{
1675 test_envelope_multipoint<bg::cs::spherical_equatorial<bg::degree> >();
1676 test_envelope_multipoint<bg::cs::geographic<bg::degree> >();
1677}
1678
1679
1680template <typename CoordinateSystem>
1681void test_envelope_multipoint_with_height()
1682{
1683 typedef bg::model::point<double, 3, CoordinateSystem> point_type;
1684 typedef bg::model::multi_point<point_type> G;
1685 typedef bg::model::box<point_type> B;
b32b8144 1686 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
7c673cae
FG
1687
1688 // empty multipoint
1689 test_empty_geometry<CoordinateSystem, G>("mph00", "MULTIPOINT()");
1690
1691 tester::apply("mph01",
1692 from_wkt<G>("MULTIPOINT(0 0 567,10 10 1456)"),
1693 0, 0, 567, 10, 10, 1456);
1694
1695 tester::apply("mph02",
1696 from_wkt<G>("MULTIPOINT(0 0 567,10 10 1456,20 90 967)"),
1697 0, 0, 567, 10, 90, 1456);
1698}
1699
1700BOOST_AUTO_TEST_CASE( envelope_multipoint_with_height )
1701{
1702 test_envelope_multipoint_with_height
1703 <
1704 bg::cs::spherical_equatorial<bg::degree>
1705 >();
1706 test_envelope_multipoint_with_height<bg::cs::geographic<bg::degree> >();
1707}
1708
1709
1710template <typename CoordinateSystem>
1711void test_envelope_box()
1712{
b32b8144 1713 typedef bg::model::point<double, 2, CoordinateSystem> P;
7c673cae
FG
1714 typedef bg::model::box<P> G;
1715 typedef bg::model::box<P> B;
b32b8144 1716 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
7c673cae
FG
1717
1718 tester::apply("b01",
1719 from_wkt<G>("BOX(10 10,20 20)"),
1720 10, 10, 20, 20);
1721
1722#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
1723 tester::apply("b02",
1724 from_wkt<G>("BOX(10 370,20 20)"),
1725 10, 10, 20, 20);
1726#endif
1727
1728 // box crosses anti-meridian
1729 tester::apply("b02a",
1730 from_wkt<G>("BOX(170 10,-170 20)"),
1731 170, 10, 190, 20);
1732
1733 tester::apply("b03",
1734 from_wkt<G>("BOX(-170 10,170 20)"),
1735 -170, 10, 170, 20);
1736
1737 tester::apply("b04",
1738 from_wkt<G>("BOX(10 10,350 20)"),
1739 10, 10, 350, 20);
1740
1741 tester::apply("b04a",
1742 from_wkt<G>("BOX(10 10,-10 20)"),
1743 10, 10, 350, 20);
1744
1745 // box is a band
1746 tester::apply("b05",
1747 from_wkt<G>("BOX(0 10,360 20)"),
1748 -180, 10, 180, 20);
1749
1750 tester::apply("b05a",
1751 from_wkt<G>("BOX(0 10,0 20)"),
1752 0, 10, 0, 20);
1753
1754 // box is almost a band
1755 tester::apply("b06",
1756 from_wkt<G>("BOX(10 10,5 20)"),
1757 10, 10, 365, 20);
1758
1759 // initial box is a band that crosses itself
1760 tester::apply("b07",
1761 from_wkt<G>("BOX(0 10,540 20)"),
1762 -180, 10, 180, 20);
1763
1764 // initial box is a band that crosses itself
1765 tester::apply("b08",
1766 from_wkt<G>("BOX(0 10,720 20)"),
1767 -180, 10, 180, 20);
1768
1769 tester::apply("b09",
1770 from_wkt<G>("BOX(10 10,10 10)"),
1771 10, 10, 10, 10);
1772
1773 tester::apply("b09a",
1774 from_wkt<G>("BOX(370 10,370 10)"),
1775 10, 10, 10, 10);
1776
1777 // box contains north and south pole
1778 tester::apply("b10",
1779 from_wkt<G>("BOX(0 -90,0 90)"),
1780 0, -90, 0, 90);
1781
1782 // box contains north and south pole
1783 tester::apply("b10a",
1784 from_wkt<G>("BOX(10 -90,10 90)"),
1785 10, -90, 10, 90);
1786
1787 // box contains north and south pole
1788 tester::apply("b10b",
1789 from_wkt<G>("BOX(0 -90,10 90)"),
1790 0, -90, 10, 90);
1791
1792 // box contains north and south pole
1793 tester::apply("b11",
1794 from_wkt<G>("BOX(0 -90,180 90)"),
1795 0, -90, 180, 90);
1796
1797 // box contains north and south pole
1798 tester::apply("b11a",
1799 from_wkt<G>("BOX(10 -90,190 90)"),
1800 10, -90, 190, 90);
1801
1802 // box contains north and south pole
1803 tester::apply("b11b",
1804 from_wkt<G>("BOX(10 -90,110 90)"),
1805 10, -90, 110, 90);
1806
1807 // box contains north and south pole and is a band
1808 // (box covers the entire spheroid)
1809 tester::apply("b12",
1810 from_wkt<G>("BOX(0 -90,360 90)"),
1811 -180, -90, 180, 90);
1812
1813 // box contains north and south pole and is a band
1814 // (box covers the entire spheroid)
1815 tester::apply("b12a",
1816 from_wkt<G>("BOX(10 -90,370 90)"),
1817 -180, -90, 180, 90);
1818
1819 // box contains north and south pole and is a band
1820 // (box covers the entire spheroid)
1821 tester::apply("b12b",
1822 from_wkt<G>("BOX(-175 -90,185 90)"),
1823 -180, -90, 180, 90);
1824
1825 // box contains north and south pole and is a band
1826 // (box covers the entire spheroid)
1827 tester::apply("b12c",
1828 from_wkt<G>("BOX(-175 -90,185 90)"),
1829 -180, -90, 180, 90);
1830
1831 // box contains north and south pole and is a band and is self-intersecting
1832 // (box covers the entire spheroid)
1833 tester::apply("b12d",
1834 from_wkt<G>("BOX(-175 -90,186 90)"),
1835 -180, -90, 180, 90);
1836
1837 // box contains north and south pole and is a band and is self-intersecting
1838 // (box covers the entire spheroid)
1839 tester::apply("b12e",
1840 from_wkt<G>("BOX(0 -90,540 90)"),
1841 -180, -90, 180, 90);
1842
1843 // box contains north and south pole and is a band and is self-intersecting
1844 // (box covers the entire spheroid)
1845 tester::apply("b12f",
1846 from_wkt<G>("BOX(10 -90,540 90)"),
1847 -180, -90, 180, 90);
1848
1849 // box is a band
1850 tester::apply("b13",
1851 from_wkt<G>("BOX(180 -10,-180 10)"),
1852 -180, -10, 180, 10);
1853
1854 // box contains north and south pole and is a band
1855 // (box covers the entire spheroid)
1856 tester::apply("b13a",
1857 from_wkt<G>("BOX(180 -90,-180 90)"),
1858 -180, -90, 180, 90);
1859
1860 tester::apply("b14",
1861 from_wkt<G>("BOX(0 10,30 90)"),
1862 0, 10, 30, 90);
1863
1864 tester::apply("b15",
1865 from_wkt<G>("BOX(179 10,178 70)"),
1866 179, 10, 538, 70);
1867
1868 // box contains north pole
1869 tester::apply("b16",
1870 from_wkt<G>("BOX(10 40,20 90)"),
1871 10, 40, 20, 90);
1872
1873 tester::apply("b16a",
1874 from_wkt<G>("BOX(170 40,-170 90)"),
1875 170, 40, 190, 90);
1876
1877 // box contains south pole
1878 tester::apply("b17",
1879 from_wkt<G>("BOX(10 -90,20 40)"),
1880 10, -90, 20, 40);
1881
1882 tester::apply("b17a",
1883 from_wkt<G>("BOX(150 -90,-150 40)"),
1884 150, -90, 210, 40);
1885
1886 // box degenerates to the north pole
1887 tester::apply("b98",
1888 from_wkt<G>("BOX(10 90,20 90)"),
1889 0, 90, 0, 90);
1890
1891 // box degenerates to the south pole
1892 tester::apply("b99",
1893 from_wkt<G>("BOX(10 -90,20 -90)"),
1894 0, -90, 0, -90);
1895
1896 double eps = std::numeric_limits<double>::epsilon();
1897 double heps = eps / 2;
1898
1899 tester::apply("b100", G(P(1-heps, 1-heps), P(1, 1)), 1-heps, 1-heps, 1, 1);
1900}
1901
b32b8144
FG
1902template <typename CoordinateSystem>
1903void test_envelope_box_polar()
1904{
1905 typedef bg::model::point<double, 2, CoordinateSystem> P;
1906 typedef bg::model::box<P> G;
1907 typedef bg::model::box<P> B;
1908 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
1909
1910 tester::apply("b01",
1911 from_wkt<G>("BOX(10 10,20 20)"),
1912 10, 10, 20, 20);
1913
1914 tester::apply("b02a",
1915 from_wkt<G>("BOX(170 10,-170 20)"),
1916 170, 10, 190, 20);
1917
1918 tester::apply("b10b",
1919 from_wkt<G>("BOX(0 0,10 180)"),
1920 0, 0, 10, 180);
1921
1922 tester::apply("b16a",
1923 from_wkt<G>("BOX(170 40,-170 180)"),
1924 170, 40, 190, 180);
1925}
1926
7c673cae
FG
1927BOOST_AUTO_TEST_CASE( envelope_box )
1928{
1929 test_envelope_box<bg::cs::spherical_equatorial<bg::degree> >();
1930 test_envelope_box<bg::cs::geographic<bg::degree> >();
b32b8144 1931 test_envelope_box_polar<bg::cs::spherical<bg::degree> >();
7c673cae
FG
1932}
1933
1934
1935template <typename CoordinateSystem>
1936void test_envelope_box_with_height()
1937{
1938 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
1939 typedef bg::model::point<double, 3, coordinate_system_type> point_type;
1940 typedef bg::model::box<point_type> G;
1941 typedef bg::model::box<point_type> B;
b32b8144 1942 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
7c673cae
FG
1943
1944 tester::apply("bh01",
1945 from_wkt<G>("BOX(10 10 567,20 20 2834)"),
1946 10, 10, 567, 20, 20, 2834);
1947
1948 tester::apply("bh02",
1949 from_wkt<G>("BOX(10 10 567,20 20 567)"),
1950 10, 10, 567, 20, 20, 567);
1951
1952 tester::apply("bh03",
1953 from_wkt<G>("BOX(0 10 567,170 90 1567)"),
1954 0, 10, 567, 170, 90, 1567);
1955}
1956
1957BOOST_AUTO_TEST_CASE( envelope_box_with_height )
1958{
1959 test_envelope_box_with_height<bg::cs::spherical_equatorial<bg::degree> >();
1960 test_envelope_box_with_height<bg::cs::geographic<bg::degree> >();
1961}
1962
1963
b32b8144 1964BOOST_AUTO_TEST_CASE( envelope_sphere_linestring )
7c673cae
FG
1965{
1966 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
1967 typedef bg::model::point<double, 2, coordinate_system_type> P;
1968 typedef bg::model::linestring<P> G;
1969 typedef bg::model::box<P> B;
b32b8144 1970 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
7c673cae
FG
1971
1972 // empty linestring
1973 test_empty_geometry<coordinate_system_type, G>("l00", "LINESTRING()");
1974
1975 tester::apply("l01",
1976 from_wkt<G>("LINESTRING(10 15)"),
1977 10, 15, 10, 15);
1978
1979 tester::apply("l01a",
1980 from_wkt<G>("LINESTRING(370 15)"),
1981 10, 15, 10, 15);
1982
1983 tester::apply("l01b",
1984 from_wkt<G>("LINESTRING(370 90)"),
1985 0, 90, 0, 90);
1986
1987 tester::apply("l02",
1988 from_wkt<G>("LINESTRING(10 10,20 20,10 30)"),
1989 10, 10, 20, 30);
1990
1991 // linestring that circles the entire globe
1992 tester::apply("l03",
1993 from_wkt<G>("LINESTRING(-185 0,-170 25,-50 10,10 10,20 20,100 5,180 15)"),
b32b8144 1994 -180, 0, 180, 33.587539971516854,
7c673cae
FG
1995 4.0 * std::numeric_limits<double>::epsilon());
1996
1997 // linestring that crosses the antimeridian but staying close to it
1998 tester::apply("l04",
1999 from_wkt<G>("LINESTRING(-170 10,170 45,160 5,-160 25)"),
2000 160, 5, 200, 45);
2001
2002 // linestring that goes through the north pole (twice)
2003 tester::apply("l05",
2004 from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30)"),
2005 -170, 30, 20, 90);
2006
2007 // linestring that goes through the north pole (three times)
2008 tester::apply("l05a",
2009 from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70)"),
2010 -170, 30, 30, 90);
2011
2012 // linestring that goes through the north pole (four times)
2013 tester::apply("l05b",
2014 from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70,40 85,-140 25)"),
2015 -170, 25, 40, 90);
2016
2017 // linestring that goes through the north pole (five times)
2018 tester::apply("l05c",
2019 from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70,40 85,-140 25,-130 25,50 45)"),
2020 -170, 25, 50, 90);
2021
2022 // linestring that goes through the north pole (five times)
2023 tester::apply("l05d",
2024 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)"),
2025 -170, 25, 185, 90);
2026
2027 // linestring that crosses the antimeridian
2028 tester::apply("l06",
2029 from_wkt<G>("LINESTRING(-160 85,-170 80,170 40,160 80)"),
2030 160, 40, 200, 85);
2031
2032 // linestring that crosses the antimeridian
2033 tester::apply("l06a",
2034 from_wkt<G>("LINESTRING(-130 85,-170 84,170 40,160 80)"),
2035 160, 40, 230, 85.02629680862029);
2036
2037 // linestring that goes through the north pole
2038 tester::apply("l07",
2039 from_wkt<G>("LINESTRING(-160 40,-170 90,-140 40,-50 30)"),
2040 -160, 30, -50, 90);
2041
2042 // linestring that degenerates to the north pole
2043 tester::apply("l08",
2044 from_wkt<G>("LINESTRING(-40 90,-30 90,-140 90,10 90)"),
2045 0, 90, 0, 90);
2046
2047 // linestring with duplicate points
2048 tester::apply("l09",
2049 from_wkt<G>("LINESTRING(-40 20,-40 20,-140 85,-10 5,-10 5)"),
b32b8144
FG
2050 -140, 5, -10, 86.184540574427757);
2051
2052 // linestring with duplicate points
2053 tester::apply("l09a",
2054 from_wkt<G>("LINESTRING(-40 20,320 20,-140 85,-10 5,350 5)"),
2055 -140, 5, -10, 86.184540574427757);
2056
2057 // linestring that lies on the equator
2058 tester::apply("l10",
2059 from_wkt<G>("LINESTRING(0 0,50 0)"),
2060 0, 0, 50, 0);
2061
2062 // linestring that lies on the equator
2063 tester::apply("l10a",
2064 from_wkt<G>("LINESTRING(-50 0,50 0)"),
2065 -50, 0, 50, 0);
2066
2067 // linestring that lies on the equator and touches antimeridian
2068 tester::apply("l10b",
2069 from_wkt<G>("LINESTRING(50 0,180 0)"),
2070 50, 0, 180, 0);
2071
2072 // linestring that lies on the equator and crosses antimeridian
2073 tester::apply("l10c",
2074 from_wkt<G>("LINESTRING(-170 0,160 0)"),
2075 160, 0, 190, 0);
2076
1e59de90
TL
2077 // https://github.com/boostorg/geometry/issues/935
2078 tester::apply("github_issue_935",
2079 from_wkt<G>("LINESTRING(4.5055430885891123e-05 -2.7518149670422367e-06,\
2080 4.5055130529987143e-05 8.2400127103300943e-07,\
2081 4.5054830174083163e-05 4.3998175091082556e-06)"),
2082 4.5054830174083163e-05, -2.7518149670422367e-06,
2083 4.5055430885891123e-05, 4.3998175091082556e-06);
2084
2085
b32b8144
FG
2086 double eps = std::numeric_limits<double>::epsilon();
2087 double heps = eps / 2;
2088
2089 {
2090 G l;
2091 l.push_back(P(1, 1));
2092 l.push_back(P(1-heps, 1-heps));
2093 tester::apply("l11", l, 1-heps, 1-heps, 1, 1);
2094 }
2095
2096 {
2097 G l;
2098 l.push_back(P(0, 0));
2099 l.push_back(P(1-heps, 1-heps));
2100 l.push_back(P(0, 0));
2101 l.push_back(P(1, 1));
2102 tester::apply("l12", l, 0, 0, 1, 1);
2103 }
2104}
2105
2106BOOST_AUTO_TEST_CASE( envelope_spheroid_linestring )
2107{
2108 typedef bg::cs::geographic<bg::degree> coordinate_system_type;
2109 typedef bg::model::point<double, 2, coordinate_system_type> P;
2110 typedef bg::model::linestring<P> G;
2111 typedef bg::model::box<P> B;
2112 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
2113
2114 // empty linestring
2115 test_empty_geometry<coordinate_system_type, G>("l00", "LINESTRING()");
2116
2117 tester::apply("l01",
2118 from_wkt<G>("LINESTRING(10 15)"),
2119 10, 15, 10, 15);
2120
2121 tester::apply("l01a",
2122 from_wkt<G>("LINESTRING(370 15)"),
2123 10, 15, 10, 15);
2124
2125 tester::apply("l01b",
2126 from_wkt<G>("LINESTRING(370 90)"),
2127 0, 90, 0, 90);
2128
2129 tester::apply("l02",
2130 from_wkt<G>("LINESTRING(10 10,20 20,10 30)"),
2131 10, 10, 20, 30);
2132
2133 // linestring that circles the entire globe
2134 tester::apply("l03",
2135 from_wkt<G>("LINESTRING(-185 0,-170 25,-50 10,10 10,20 20,100 5,180 15)"),
2136 -180, 0, 180, rng(33.702476580412359, 33.702476580413318));
2137
2138 // linestring that crosses the antimeridian but staying close to it
2139 tester::apply("l04",
2140 from_wkt<G>("LINESTRING(-170 10,170 45,160 5,-160 25)"),
2141 160, 5, 200, 45);
2142
2143 // linestring that goes through the north pole (twice)
2144 tester::apply("l05",
2145 from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30)"),
2146 -170, 30, 20, 90);
2147
2148 // linestring that goes through the north pole (three times)
2149 tester::apply("l05a",
2150 from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70)"),
2151 -170, 30, 30, 90);
2152
2153 // linestring that goes through the north pole (four times)
2154 tester::apply("l05b",
2155 from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70,40 85,-140 25)"),
2156 -170, 25, 40, 90);
2157
2158 // linestring that goes through the north pole (five times)
2159 tester::apply("l05c",
2160 from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70,40 85,-140 25,-130 25,50 45)"),
2161 -170, 25, 50, 90);
2162
2163 // linestring that goes through the north pole (five times)
2164 tester::apply("l05d",
2165 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)"),
2166 -170, 25, 185, 90);
2167
2168 // linestring that crosses the antimeridian
2169 tester::apply("l06",
2170 from_wkt<G>("LINESTRING(-160 85,-170 80,170 40,160 80)"),
2171 160, 40, 200, 85);
2172
2173 // linestring that crosses the antimeridian
2174 tester::apply("l06a",
2175 from_wkt<G>("LINESTRING(-130 85,-170 84,170 40,160 80)"),
2176 160, 40, 230, 85.02630556315151);
2177
2178 // linestring that goes through the north pole
2179 tester::apply("l07",
2180 from_wkt<G>("LINESTRING(-160 40,-170 90,-140 40,-50 30)"),
2181 -160, 30, -50, 90);
2182
2183 // linestring that degenerates to the north pole
2184 tester::apply("l08",
2185 from_wkt<G>("LINESTRING(-40 90,-30 90,-140 90,10 90)"),
2186 0, 90, 0, 90);
2187
2188 // linestring with duplicate points
2189 tester::apply("l09",
2190 from_wkt<G>("LINESTRING(-40 20,-40 20,-140 85,-10 5,-10 5)"),
2191 -140, 5, -10, 86.18564770636192);
7c673cae
FG
2192
2193 // linestring with duplicate points
2194 tester::apply("l09a",
2195 from_wkt<G>("LINESTRING(-40 20,320 20,-140 85,-10 5,350 5)"),
b32b8144 2196 -140, 5, -10, 86.18564770636192);
7c673cae
FG
2197
2198 // linestring that lies on the equator
2199 tester::apply("l10",
2200 from_wkt<G>("LINESTRING(0 0,50 0)"),
2201 0, 0, 50, 0);
2202
2203 // linestring that lies on the equator
2204 tester::apply("l10a",
2205 from_wkt<G>("LINESTRING(-50 0,50 0)"),
2206 -50, 0, 50, 0);
2207
2208 // linestring that lies on the equator and touches antimeridian
2209 tester::apply("l10b",
2210 from_wkt<G>("LINESTRING(50 0,180 0)"),
2211 50, 0, 180, 0);
2212
2213 // linestring that lies on the equator and crosses antimeridian
2214 tester::apply("l10c",
2215 from_wkt<G>("LINESTRING(-170 0,160 0)"),
2216 160, 0, 190, 0);
2217
1e59de90
TL
2218 // https://github.com/boostorg/geometry/issues/935
2219 tester::apply("github_issue_935",
2220 from_wkt<G>("LINESTRING(4.5055430885891123e-05 -2.7518149670422367e-06,\
2221 4.5055130529987143e-05 8.2400127103300943e-07,\
2222 4.5054830174083163e-05 4.3998175091082556e-06)"),
2223 4.5054830174083163e-05, -2.7518149670422367e-06,
2224 4.5055430885891123e-05, 4.3998175091082556e-06);
2225
7c673cae
FG
2226 double eps = std::numeric_limits<double>::epsilon();
2227 double heps = eps / 2;
2228
2229 {
2230 G l;
2231 l.push_back(P(1, 1));
2232 l.push_back(P(1-heps, 1-heps));
2233 tester::apply("l11", l, 1-heps, 1-heps, 1, 1);
2234 }
2235
2236 {
2237 G l;
2238 l.push_back(P(0, 0));
2239 l.push_back(P(1-heps, 1-heps));
2240 l.push_back(P(0, 0));
2241 l.push_back(P(1, 1));
2242 tester::apply("l12", l, 0, 0, 1, 1);
2243 }
2244}
2245
2246
b32b8144 2247BOOST_AUTO_TEST_CASE( envelope_linestring_sphere_with_height )
7c673cae
FG
2248{
2249 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
2250 typedef bg::model::point<double, 3, coordinate_system_type> point_type;
2251 typedef bg::model::linestring<point_type> G;
2252 typedef bg::model::box<point_type> B;
b32b8144 2253 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
7c673cae
FG
2254
2255 // empty linestring
2256 test_empty_geometry<coordinate_system_type, G>("lh00", "LINESTRING()");
2257
2258 tester::apply("lh01",
2259 from_wkt<G>("LINESTRING(10 15 30,20 25 434,30 35 186)"),
2260 10, 15, 30, 30, 35, 434);
2261}
2262
b32b8144
FG
2263BOOST_AUTO_TEST_CASE( envelope_linestring_spheroid_with_height )
2264{
2265 typedef bg::cs::geographic<bg::degree> coordinate_system_type;
2266 typedef bg::model::point<double, 3, coordinate_system_type> point_type;
2267 typedef bg::model::linestring<point_type> G;
2268 typedef bg::model::box<point_type> B;
2269 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
2270
2271 // empty linestring
2272 test_empty_geometry<coordinate_system_type, G>("lh00", "LINESTRING()");
2273
2274 tester::apply("lh01",
2275 from_wkt<G>("LINESTRING(10 15 30,20 25 434,30 35 186)"),
2276 10, 15, 30, 30, 35, 434);
2277}
7c673cae 2278
b32b8144 2279BOOST_AUTO_TEST_CASE( envelope_sphere_multilinestring )
7c673cae
FG
2280{
2281 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
2282 typedef bg::model::point<double, 2, coordinate_system_type> point_type;
2283 typedef bg::model::multi_linestring<bg::model::linestring<point_type> > G;
2284 typedef bg::model::box<point_type> B;
b32b8144 2285 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
7c673cae
FG
2286
2287 // empty multilinestring
2288 test_empty_geometry<coordinate_system_type, G>("ml00", "MULTILINESTRING()");
2289
2290 // invalid multilinestring
2291 test_empty_geometry<coordinate_system_type, G>("ml00a",
2292 "MULTILINESTRING(())");
2293
2294 // invalid multilinestring
2295 test_empty_geometry<coordinate_system_type, G>("ml00b",
2296 "MULTILINESTRING((),())");
2297
2298 // invalid multilinestring
2299 tester::apply("ml00c",
2300 from_wkt<G>("MULTILINESTRING((10 15),(),())"),
2301 10, 15, 10, 15);
2302
2303 // invalid multilinestring
2304 tester::apply("ml00d",
2305 from_wkt<G>("MULTILINESTRING((),(10 15),())"),
2306 10, 15, 10, 15);
2307
2308 tester::apply("ml01",
2309 from_wkt<G>("MULTILINESTRING((10 15))"),
2310 10, 15, 10, 15);
2311
92f5a8d4 2312#ifdef BOOST_GEOMETRY_TEST_FAILURES
7c673cae
FG
2313 tester::apply("ml01a",
2314 from_wkt<G>("MULTILINESTRING((),(),(10 15),())"),
2315 10, 15, 10, 15);
92f5a8d4 2316#endif
7c673cae
FG
2317
2318 tester::apply("ml02",
2319 from_wkt<G>("MULTILINESTRING((-170 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"),
b32b8144 2320 -180, 25, 180, 81.113793608034072);
7c673cae
FG
2321
2322 tester::apply("ml03",
2323 from_wkt<G>("MULTILINESTRING((-150 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"),
b32b8144 2324 -150, 25, 200, 81.113793608034072);
7c673cae
FG
2325
2326 tester::apply("ml04",
2327 from_wkt<G>("MULTILINESTRING((-150 40,-100 80),(10 35,100 80))"),
2328 -150, 35, 100, 80.07385383411011);
2329
2330 tester::apply("ml04a",
2331 from_wkt<G>("MULTILINESTRING((-150 40,-100 80),(10 35,100 80),(170 25,-160 80))"),
2332 10, 25, 260, 80.07385383411011);
2333
2334 tester::apply("ml05",
2335 from_wkt<G>("MULTILINESTRING((-140 40,-100 80),(10 35,100 80))"),
2336 -140, 35, 100, 80.07385383411011);
2337
2338 tester::apply("ml05a",
2339 from_wkt<G>("MULTILINESTRING((-140 40,-100 80),(10 35,100 80),(170 25,-160 80))"),
2340 10, 25, 260, 80.07385383411011);
2341}
2342
b32b8144
FG
2343BOOST_AUTO_TEST_CASE( envelope_spheroid_multilinestring )
2344{
2345 typedef bg::cs::geographic<bg::degree> coordinate_system_type;
2346 typedef bg::model::point<double, 2, coordinate_system_type> point_type;
2347 typedef bg::model::multi_linestring<bg::model::linestring<point_type> > G;
2348 typedef bg::model::box<point_type> B;
2349 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
2350
2351 // empty multilinestring
2352 test_empty_geometry<coordinate_system_type, G>("ml00", "MULTILINESTRING()");
2353
2354 // invalid multilinestring
2355 test_empty_geometry<coordinate_system_type, G>("ml00a",
2356 "MULTILINESTRING(())");
2357
2358 // invalid multilinestring
2359 test_empty_geometry<coordinate_system_type, G>("ml00b",
2360 "MULTILINESTRING((),())");
2361
2362 // invalid multilinestring
2363 tester::apply("ml00c",
2364 from_wkt<G>("MULTILINESTRING((10 15),(),())"),
2365 10, 15, 10, 15);
2366
2367 // invalid multilinestring
2368 tester::apply("ml00d",
2369 from_wkt<G>("MULTILINESTRING((),(10 15),())"),
2370 10, 15, 10, 15);
2371
2372 tester::apply("ml01",
2373 from_wkt<G>("MULTILINESTRING((10 15))"),
2374 10, 15, 10, 15);
2375
92f5a8d4 2376#ifdef BOOST_GEOMETRY_TEST_FAILURES
b32b8144
FG
2377 tester::apply("ml01a",
2378 from_wkt<G>("MULTILINESTRING((),(),(10 15),())"),
2379 10, 15, 10, 15);
92f5a8d4 2380#endif
b32b8144
FG
2381
2382 tester::apply("ml02",
2383 from_wkt<G>("MULTILINESTRING((-170 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"),
2384 -180, 25, 180, 81.115885076701147);
2385
2386 tester::apply("ml03",
2387 from_wkt<G>("MULTILINESTRING((-150 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"),
2388 -150, 25, 200, 81.115885076701147);
2389
2390 tester::apply("ml04",
2391 from_wkt<G>("MULTILINESTRING((-150 40,-100 80),(10 35,100 80))"),
2392 -150, 35, 100, rng(80.07385383411011, 80.082544902477267));
2393
2394 tester::apply("ml04a",
2395 from_wkt<G>("MULTILINESTRING((-150 40,-100 80),(10 35,100 80),(170 25,-160 80))"),
2396 10, 25, 260, rng(80.07385383411011, 80.082544902477267));
2397
2398 tester::apply("ml05",
2399 from_wkt<G>("MULTILINESTRING((-140 40,-100 80),(10 35,100 80))"),
2400 -140, 35, 100, rng(80.07385383411011, 80.082544902477267));
2401
2402 tester::apply("ml05a",
2403 from_wkt<G>("MULTILINESTRING((-140 40,-100 80),(10 35,100 80),(170 25,-160 80))"),
2404 10, 25, 260, rng(80.07385383411011, 80.082544902477267));
2405}
2406
7c673cae 2407
b32b8144 2408BOOST_AUTO_TEST_CASE( envelope_multilinestring_sphere_with_height )
7c673cae
FG
2409{
2410 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
2411 typedef bg::model::point<double, 3, coordinate_system_type> point_type;
2412 typedef bg::model::multi_linestring<bg::model::linestring<point_type> > G;
2413 typedef bg::model::box<point_type> B;
b32b8144
FG
2414 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
2415
2416 tester::apply("mlh01",
2417 from_wkt<G>("MULTILINESTRING((10 15 1000))"),
2418 10, 15, 1000, 10, 15, 1000);
2419
92f5a8d4 2420#ifdef BOOST_GEOMETRY_TEST_FAILURES
b32b8144
FG
2421 tester::apply("mlh01a",
2422 from_wkt<G>("MULTILINESTRING((),(),(10 15 1000),())"),
2423 10, 15, 1000, 10, 15, 1000);
92f5a8d4 2424#endif
b32b8144
FG
2425
2426 tester::apply("mlh02",
2427 from_wkt<G>("MULTILINESTRING((-170 40 400,-100 80 300),(-10 25 600,10 35 700,120 45 450))"),
2428 -10, 25, 300, 260, 80, 700);
2429}
2430
2431BOOST_AUTO_TEST_CASE( envelope_multilinestring_spheroid_with_height )
2432{
2433 typedef bg::cs::geographic<bg::degree> coordinate_system_type;
2434 typedef bg::model::point<double, 3, coordinate_system_type> point_type;
2435 typedef bg::model::multi_linestring<bg::model::linestring<point_type> > G;
2436 typedef bg::model::box<point_type> B;
2437 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
7c673cae
FG
2438
2439 tester::apply("mlh01",
2440 from_wkt<G>("MULTILINESTRING((10 15 1000))"),
2441 10, 15, 1000, 10, 15, 1000);
2442
92f5a8d4 2443#ifdef BOOST_GEOMETRY_TEST_FAILURES
7c673cae
FG
2444 tester::apply("mlh01a",
2445 from_wkt<G>("MULTILINESTRING((),(),(10 15 1000),())"),
2446 10, 15, 1000, 10, 15, 1000);
92f5a8d4 2447#endif
7c673cae
FG
2448
2449 tester::apply("mlh02",
2450 from_wkt<G>("MULTILINESTRING((-170 40 400,-100 80 300),(-10 25 600,10 35 700,120 45 450))"),
2451 -10, 25, 300, 260, 80, 700);
2452}
2453
92f5a8d4
TL
2454//Test spherical polygons and rings (geographic should be similar)
2455BOOST_AUTO_TEST_CASE( envelope_polygon )
2456{
2457 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
2458 typedef bg::model::point<double, 2, coordinate_system_type> point_type;
2459 typedef bg::model::polygon<point_type> G;
2460 typedef bg::model::box<point_type> B;
2461 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
2462
2463 typedef bg::model::ring<point_type> R;
2464 typedef test_envelope_on_sphere_or_spheroid<R, B> testerR;
2465 R ring1;
2466 bg::append(ring1, point_type(0.0, 0.0));
2467 bg::append(ring1, point_type(0.0, 5.0));
2468 bg::append(ring1, point_type(5.0, 5.0));
2469 bg::append(ring1, point_type(5.0, 0.0));
2470 bg::append(ring1, point_type(0.0, 0.0));
2471
2472 testerR::apply("r01",
2473 ring1,
2474 0, 0, 5, 5.0047392446083938);
2475 tester::apply("p01",
2476 from_wkt<G>("POLYGON((0 0,1 0,1 1,0 1,0 0))"),
2477 0, 0, 1, 1.0000380706527705);
2478 tester::apply("p02",
2479 from_wkt<G>("POLYGON((0 0,1 0,1 1,0 1,0 0),(0.5 0.5,0.7 0.5,0.7 0.7,0.5 0.5))"),
2480 0, 0, 1, 1.0000380706527705);
2481 tester::apply("p03",
2482 from_wkt<G>("POLYGON((),(0.5 0.5,0.5 0.7,0.7 0.7,0.5 0.5))"),
2483 0.5, 0.5, 0.7, 0.70000106605644807);
2484 tester::apply("p04",
2485 from_wkt<G>("POLYGON((),(0.5 0.5,0.5 0.7,0.7 0.7,0.5 0.5),\
2486 (0.7 0.5,0.9 0.5,0.9 0.7,0.7 0.5))"),
2487 0.5, 0.5, 0.9, 0.70000106605644807);
2488
2489 // https://github.com/boostorg/geometry/issues/466
2490 tester::apply("p5-issue466",
2491 from_wkt<G>("POLYGON((2.4 48.9021,2.4 48.89,2.3 48.89,2.3 48.9021,2.4 48.9021))"),
2492 2.3, 48.89, 2.4, 48.902110807274966);
2493 tester::apply("p6-issue466",
2494 from_wkt<G>("POLYGON((2.4 48.90215,2.4 48.89,2.3 48.89,2.3 48.90215,2.4 48.90215))"),
2495 2.3, 48.89, 2.4, 48.902160807272381);
2496 tester::apply("p7-issue466",
2497 from_wkt<G>("POLYGON((2.4 48.9022,2.4 48.89,2.3 48.89,2.3 48.9022,2.4 48.9022))"),
2498 2.3, 48.89, 2.4, 48.902210807269796);
2499}
7c673cae 2500
7c673cae
FG
2501// unit test for rings de-activated for now (current implementation
2502// for area on the spherical equatorial coordinate system is not complete)
2503// TODO: re-activate once implementation is done
92f5a8d4 2504// right now implementation does not distinguish between ccw and cw rings
7c673cae
FG
2505BOOST_AUTO_TEST_CASE( envelope_cw_ring )
2506{
b32b8144
FG
2507 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
2508 typedef bg::model::point<double, 2, coordinate_system_type> point_type;
2509 typedef bg::model::polygon<point_type> G;
2510 typedef bg::model::box<point_type> B;
2511 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
7c673cae 2512
1e59de90 2513 double const eps = std::numeric_limits<double>::epsilon();
7c673cae
FG
2514
2515 tester::apply("r01cw",
2516 from_wkt<G>("POLYGON((0 10,0 45,50 10,0 10))"),
2517 0, 10, 50, 45);
1e59de90
TL
2518
2519#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING
7c673cae
FG
2520 // ring that contains both the north and south poles in its interior
2521 tester::apply("r01cw-r",
2522 from_wkt<G>("POLYGON((0 10,50 10,0 45,0 10))"),
2523 -180, -90, 180, 90);
1e59de90 2524#endif
7c673cae
FG
2525
2526 // ring that contains the north pole in its interior
2527 tester::apply("r02cw",
2528 from_wkt<G>("POLYGON((0 0,-50 0,-170 0,180 0,100 0,0 0))"),
2529 -180, 0, 180, 90);
2530 // -180, -90, 180, 0);
2531
2532 // ring that contains the south pole in its interior
2533 tester::apply("r02cw-r",
2534 from_wkt<G>("POLYGON((0 0,100 0,180 0,-170 0,-50 0,0 0))"),
2535 -180, -90, 180, 0);
2536 // -180, 0, 180, 90);
2537
2538 // ring that contains the north pole in its interior
2539 tester::apply("r03cw",
2540 from_wkt<G>("POLYGON((0 -10,-50 -10,-170 -10,180 -10,100 -10,0 -10))"),
2541 -180, -19.42540014068282, 180, 90);
2542 // -180, -90, 180, -10);
2543
2544 // ring that contains both the south and north poles in its interior
2545 tester::apply("r03cw-r",
2546 from_wkt<G>("POLYGON((0 -10,100 -10,180 -10,-170 -10,-50 -10,0 -10))"),
2547 -180, -90, 180, -10);
2548 // -180, -19.42540014068282, 180, 90);
2549
1e59de90 2550#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING
7c673cae
FG
2551 // ring that has the north pole as vertex and contains the south pole
2552 tester::apply("r04cw",
2553 from_wkt<G>("POLYGON((0 0,-50 90,-50 0,0 0))"),
2554 -180, -90, 180, 90);
1e59de90 2555#endif
7c673cae
FG
2556
2557 // ring that has the north pole as vertex
2558 tester::apply("r04cw-r",
2559 from_wkt<G>("POLYGON((0 0,-50 0,-50 90,0 0))"),
2560 -50, 0, 0, 90);
2561
2562 // ring that crosses antimeridian but does not contain any pole
2563 tester::apply("r05cw",
2564 from_wkt<G>("POLYGON((-140 0,140 10,-140 80,-140 0))"),
2565 140, 0, 220, 80);
2566
2567 // ring that crosses antimeridian multiple times but does not
2568 // contain any pole
2569 tester::apply("r06cw",
2570 from_wkt<G>("POLYGON((-140 10,140 10,140 80,-140 80,-140 10))"),
2571 140, 10, 220, 82.30737118075496,
2572 2 * eps);
2573
2574 // ring that crosses antimeridian multiple times but does not
2575 // contain any pole
2576 tester::apply("r07cw",
2577 from_wkt<G>("POLYGON((-140 10,140 10,180 80,-140 10))"),
2578 140, 10, 220, 80);
2579
2580 // ring that goes through the north pole
2581 tester::apply("r08cw",
2582 from_wkt<G>("POLYGON((0 0,-50 0,-50 90,0 0))"),
2583 -50, 0, 0, 90);
2584
1e59de90 2585#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING
7c673cae
FG
2586 // ring that goes through the south pole and contains the north pole
2587 tester::apply("r09cw",
2588 from_wkt<G>("POLYGON((0 0,0 -90,50 0,0 0))"),
2589 -180, -90, 180, 90);
1e59de90 2590#endif
7c673cae
FG
2591
2592 // ring that goes through the south pole
2593 tester::apply("r09cw-r",
2594 from_wkt<G>("POLYGON((0 0,50 0,50 -90,0 0))"),
2595 0, -90, 50, 0);
2596
2597 // ring that goes through both south and north pole
2598 tester::apply("r10cw",
2599 from_wkt<G>("POLYGON((50 0,50 -90,40 0,40 90,50 0))"),
2600 40, -90, 50, 90);
2601
2602 // ring that goes through both south and north pole and crosses antimeridian
2603 tester::apply("r11cw",
2604 from_wkt<G>("POLYGON((-170 0,-170 -90,160 0,160 90,-170 0))"),
2605 160, -90, 190, 90);
2606
2607 // ring with edge that goes through the north pole and contains
2608 // south pole (the bounding box is the entire globe)
2609 tester::apply("r12cw",
2610 from_wkt<G>("POLYGON((-50 40,130 10,170 80,-50 40))"),
2611 -180, -90, 180, 90);
2612 // -180, 10, 180, 90);
2613
2614 // ring with edge that goes through the north pole
2615 tester::apply("r12cw-r",
2616 from_wkt<G>("POLYGON((-50 40,170 80,130 10,-50 40))"),
2617 -180, 10, 180, 90);
2618 // -180, -90, 180, 90);
2619
2620 // ring that represents a spherical cap near the north pole
2621 tester::apply("r13cw",
2622 from_wkt<G>("POLYGON((100 45,0 45,-100 45,-100 90,100 45))"),
2623 -100, 45, 100, 90);
2624
1e59de90 2625#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING
7c673cae
FG
2626 // ring that represents the complement of a spherical cap
2627 // near the north pole
2628 tester::apply("r13cw-r",
2629 from_wkt<G>("POLYGON((-100 45,0 45,100 45,100 90,-100 45))"),
2630 -180, -90, 180, 90);
1e59de90 2631#endif
7c673cae
FG
2632
2633 // ring that represents the complement of a spherical cap
2634 // that touches the south pole
2635 tester::apply("r14cw",
2636 from_wkt<G>("POLYGON((-100 45,0 45,100 45,100 -90,-100 45))"),
2637 -100, -90, 100, 57.26759279038765);
2638
1e59de90 2639#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING
7c673cae
FG
2640 // ring that represents a spherical cap that touches the south pole
2641 tester::apply("r14cw-r",
2642 from_wkt<G>("POLYGON((100 45,0 45,-100 45,-100 -90,100 45))"),
2643 -180, -90, 180, 90);
1e59de90 2644#endif
7c673cae
FG
2645
2646 // ring with edge that goes through the south pole
2647 tester::apply("r15cw",
2648 from_wkt<G>("POLYGON((-50 -40,130 -10,170 -80,-50 -40))"),
2649 -180, -90, 180, -10);
2650
2651 // ring with edge that goes through the south pole and contains
2652 // north pole (the bounding box is the entire globe)
2653 tester::apply("r15cw-r",
2654 from_wkt<G>("POLYGON((-50 -40,170 -80,130 -10,-50 -40))"),
2655 -180, -90, 180, 90);
2656
2657 // ring that does not contain any pole and lies in the lower hemisphere
2658 tester::apply("r16",
2659 from_wkt<G>("POLYGON((-50 -80,-50 -40,-30 -40,-30 -80,-50 -80))"),
2660 -50, -80.14892388341609, -30, -40);
2661
1e59de90 2662#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING
7c673cae
FG
2663 // ring that lies in the lower hemisphere and contains both poles
2664 tester::apply("r16-r",
2665 from_wkt<G>("POLYGON((-50 -80,-30 -80,-30 -40,-50 -40,-50 -80))"),
2666 -180, -90, 180, 90);
2667
2668 // ring that goes through the south pole and contains the north pole
2669 tester::apply("r17cw",
2670 from_wkt<G>("POLYGON((50 0,50 -90,100 0,50 0))"),
2671 -180, -90, 180, 90);
1e59de90 2672#endif
7c673cae
FG
2673
2674 // ring that goes through the south pole
2675 tester::apply("r17cw-r",
2676 from_wkt<G>("POLYGON((50 0,100 0,100 -90,50 0))"),
2677 50, -90, 100, 0);
2678
1e59de90 2679#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING
7c673cae
FG
2680 // ring that goes through the south pole and contains the north pole
2681 tester::apply("r18cw",
2682 from_wkt<G>("POLYGON((50 0,50 -90,460 0,50 0))"),
2683 -180, -90, 180, 90);
1e59de90 2684#endif
7c673cae
FG
2685
2686 // ring that goes through the south pole
2687 tester::apply("r18cw-r",
2688 from_wkt<G>("POLYGON((50 0,460 0,100 -90,50 0))"),
2689 50, -90, 100, 0);
2690
1e59de90 2691#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING
7c673cae
FG
2692 // ring that goes through the south pole and contains the north pole
2693 tester::apply("r19cw",
2694 from_wkt<G>("POLYGON((50 0,50 -90,-260 0,50 0))"),
2695 -180, -90, 180, 90);
1e59de90 2696#endif
7c673cae
FG
2697
2698 // ring that goes through the south pole
2699 tester::apply("r19cw-r",
2700 from_wkt<G>("POLYGON((50 0,-260 0,100 -90,50 0))"),
2701 50, -90, 100, 0);
2702
2703 // ring that goes through both poles
2704 tester::apply("r20cw",
2705 from_wkt<G>("POLYGON((10 0,10 90,20 0,20 -90,10 0))"),
2706 10, -90, 20, 90); // SUCCEEDS FOR WRONG REASON
2707
1e59de90 2708#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING
7c673cae
FG
2709 // ring that goes through both poles
2710 tester::apply("r20cw-r",
2711 from_wkt<G>("POLYGON((10 0,10 -90,20 0,20 90,10 0))"),
1e59de90
TL
2712 -180, -90, 180, 90);
2713#endif
7c673cae
FG
2714
2715 // ring that goes through both poles and its boundary forms
2716 // a great circle
2717 tester::apply("r21cw",
2718 from_wkt<G>("POLYGON((-10 0,-10 90,170 0,170 -90,-10 0))"),
2719 -10, -90, 170, 90); // SUCCEEDS FOR WRONG REASON
2720
1e59de90 2721#ifdef BOOST_GEOMETRY_TEST_ENABLE_FAILING
7c673cae
FG
2722 // ring that goes through both poles and its boundary forms
2723 // a great circle
2724 tester::apply("r21cw-r",
2725 from_wkt<G>("POLYGON((-10 0,-10 -90,170 0,170 90,-10 0))"),
1e59de90 2726 170, -90, 350, 90);
7c673cae 2727#endif
1e59de90
TL
2728
2729 // From disjoint https://svn.boost.org/trac/boost/ticket/9162
2730 // Polygons containing poles
2731 tester::apply("r22cw",
2732 from_wkt<G>("POLYGON((0 80,-90 80,-180 80,90 80,0 80))"),
2733 -180, 80, 180, 90);
2734 tester::apply("r23cw",
2735 from_wkt<G>("POLYGON((0 -80,90 -80,-180 -80,-90 -80,0 -80))"),
2736 -180, -90, 180, -80);
2737 // Polygons greater than half of the globe
2738 tester::apply("r24cw",
2739 from_wkt<G>("POLYGON((0 80,90 80,-180 80,-90 80,0 80))"),
2740 -180, -90, 180, 82.892923889553458);
2741 tester::apply("r25cw",
2742 from_wkt<G>("POLYGON((0 -80,-90 -80,-180 -80,90 -80,0 -80))"),
2743 -180, -82.892923889553458, 180, 90);
2744 // Normal test case
2745 tester::apply("r26cw",
2746 from_wkt<G>("POLYGON((30 0,30 30,90 30, 90 0, 30 0))"),
2747 30, 0, 90, 33.690067525979771);
2748
2749 // Invalid polygons with holes containing poles
2750 tester::apply("r27cw",
2751 from_wkt<G>("POLYGON((),(0 80,90 80,-180 80,-90 80,0 80))"),
2752 -180, 80, 180, 90);
2753 tester::apply("r28cw",
2754 from_wkt<G>("POLYGON((),(0 -80,-90 -80,-180 -80,90 -80,0 -80))"),
2755 -180, -90, 180, -80);
b32b8144
FG
2756}
2757
1e59de90
TL
2758BOOST_AUTO_TEST_CASE(envelope_ccw_ring)
2759{
2760 typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
2761 typedef bg::model::point<double, 2, coordinate_system_type> point_type;
2762 typedef bg::model::polygon<point_type, false> G;
2763 typedef bg::model::box<point_type> B;
2764 typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
2765
2766 tester::apply("r27ccw",
2767 from_wkt<G>("POLYGON((),(0 80,-90 80,-180 80,90 80,0 80))"),
2768 -180, 80, 180, 90);
2769 tester::apply("r28ccw",
2770 from_wkt<G>("POLYGON((),(0 -80,90 -80,-180 -80,-90 -80,0 -80))"),
2771 -180, -90, 180, -80);
2772}