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