• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Geometry
2 // Unit Test
3 
4 // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
5 
6 // Copyright (c) 2017, Oracle and/or its affiliates.
7 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
8 
9 // Use, modification and distribution is subject to the Boost Software License,
10 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
12 
13 #include <iostream>
14 #include <string>
15 
16 #include "test_union.hpp"
17 
18 #include <boost/geometry/geometries/point_xy.hpp>
19 
20 
21 struct exterior_points_counter
22 {
exterior_points_counterexterior_points_counter23     exterior_points_counter() : count(0) {}
24 
25     template <typename Polygon>
operator ()exterior_points_counter26     void operator()(Polygon const& poly)
27     {
28         count += boost::size(bg::exterior_ring(poly));
29     }
30 
31     std::size_t count;
32 };
33 
34 struct interiors_counter
35     : exterior_points_counter
36 {
37     template <typename Polygon>
operator ()interiors_counter38     void operator()(Polygon const& poly)
39     {
40         count += boost::size(bg::interior_rings(poly));
41     }
42 };
43 
test_geographic_one(std::string const & wkt1,std::string const & wkt2,std::size_t count,std::size_t exterior_points_count,std::size_t interiors_count,double expected_area)44 void test_geographic_one(std::string const& wkt1, std::string const& wkt2,
45                          std::size_t count, std::size_t exterior_points_count, std::size_t interiors_count,
46                          double expected_area)
47 {
48     typedef bg::model::point<double, 2, bg::cs::geographic<bg::degree> > point;
49     typedef bg::model::polygon<point> polygon;
50     typedef bg::model::multi_polygon<polygon> multipolygon;
51 
52     bg::srs::spheroid<double> sph(6378137.0000000000, 6356752.3142451793);
53 
54     bg::strategy::intersection::geographic_segments<> is(sph);
55     bg::strategy::area::geographic<> as(sph);
56 
57     polygon p1, p2;
58 
59     boost::geometry::read_wkt(wkt1, p1);
60     boost::geometry::read_wkt(wkt2, p2);
61 
62     multipolygon result;
63 
64     enum test_mode { expect_valid, expect_empty, expect_exception };
65 
66 #if defined(BOOST_GEOMETRY_UNION_THROW_INVALID_OUTPUT_EXCEPTION)
67     test_mode mode = expected_area >= 0 ? expect_valid : expect_exception;
68 #elif defined(BOOST_GEOMETRY_UNION_RETURN_INVALID)
69     test_mode mode = expect_valid;
70 #else
71     // default
72     test_mode mode = expected_area >= 0 ? expect_valid : expect_empty;
73 #endif
74 
75     if (mode == expect_exception)
76     {
77         BOOST_CHECK_THROW(boost::geometry::union_(p1, p2, result, is),
78                           bg::invalid_output_exception);
79     }
80     else
81     {
82 
83         boost::geometry::union_(p1, p2, result, is);
84 
85         double result_area = bg::area(result, as);
86 
87         std::size_t result_count = boost::size(result);
88         std::size_t result_exterior_points = std::for_each(boost::begin(result),
89                                                            boost::end(result),
90                                                            exterior_points_counter()).count;
91         std::size_t result_interiors = std::for_each(boost::begin(result),
92                                                      boost::end(result),
93                                                      interiors_counter()).count;
94         if (mode == expect_valid)
95         {
96             BOOST_CHECK_EQUAL(result_count, count);
97             BOOST_CHECK_EQUAL(result_exterior_points, exterior_points_count);
98             BOOST_CHECK_EQUAL(result_interiors, interiors_count);
99             BOOST_CHECK_CLOSE(result_area, expected_area, 0.001);
100         }
101         else
102         {
103             BOOST_CHECK_EQUAL(result_count, 0u);
104             BOOST_CHECK_EQUAL(result_area, 0.0);
105         }
106     }
107 }
108 
109 
test_geographic()110 void test_geographic()
111 {
112     // input ok and the result is ok
113     test_geographic_one("POLYGON((16 15,-132 10,-56 89,67 5,16 15))",
114                         "POLYGON((101 49,12 40,-164 10,117 0,101 49))",
115                         1, 9, 0, 144265751613509.06);
116 
117     // input ok but the result is too big
118     test_geographic_one("POLYGON((16 -15,-132 -22,-56 89,67 -29,16 -15))",
119                         "POLYGON((101 49,12 40,-164 -21,117 -61,101 49))",
120                         1, 9, 0, -163427005620080.0);
121 
122     // the second polygon is reversed i.e. it covers more than half of the globe
123     // so the result is also too big
124     test_geographic_one("POLYGON((16 -15,-132 -22,-56 89,67 -29,16 -15))",
125                         "POLYGON((101 49,117 -61,-164 -21,12 40,101 49))",
126                         1, 7, 0, -125258931656228.08);
127 }
128 
129 
test_main(int,char * [])130 int test_main(int, char* [])
131 {
132     test_geographic();
133 
134     return 0;
135 }
136