• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 // Unit Test
3 
4 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
6 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
7 
8 // This file was modified by Oracle on 2015, 2016, 2017.
9 // Modifications copyright (c) 2015-2017, Oracle and/or its affiliates.
10 
11 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
12 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
13 
14 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
15 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16 
17 // Use, modification and distribution is subject to the Boost Software License,
18 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
19 // http://www.boost.org/LICENSE_1_0.txt)
20 
21 
22 #include <algorithms/area/test_area.hpp>
23 
24 #include <boost/geometry/geometries/point_xy.hpp>
25 #include <boost/geometry/geometries/point.hpp>
26 #include <boost/geometry/geometries/box.hpp>
27 #include <boost/geometry/geometries/ring.hpp>
28 #include <boost/geometry/geometries/polygon.hpp>
29 
30 #include <test_geometries/all_custom_ring.hpp>
31 #include <test_geometries/all_custom_polygon.hpp>
32 //#define BOOST_GEOMETRY_TEST_DEBUG
33 
34 #include <boost/variant/variant.hpp>
35 
36 template <typename Polygon>
test_polygon()37 void test_polygon()
38 {
39     // Rotated square, length=sqrt(2) -> area=2
40     test_geometry<Polygon>("POLYGON((1 1,2 2,3 1,2 0,1 1))", 2.0);
41     test_geometry<Polygon>("POLYGON((1 1,2 2,3 1,2 0,1 1))", 2.0);
42     test_geometry<Polygon>("POLYGON((0 0,0 7,4 2,2 0,0 0))", 16.0);
43     test_geometry<Polygon>("POLYGON((1 1,2 1,2 2,1 2,1 1))", -1.0);
44     test_geometry<Polygon>("POLYGON((0 0,0 7,4 2,2 0,0 0), (1 1,2 1,2 2,1 2,1 1))", 15.0);
45 }
46 
47 
48 template <typename P>
test_all()49 void test_all()
50 {
51     test_geometry<bg::model::box<P> >("POLYGON((0 0,2 2))", 4.0);
52     test_geometry<bg::model::box<P> >("POLYGON((2 2,0 0))", 4.0);
53 
54     test_polygon<bg::model::polygon<P> >();
55     test_polygon<all_custom_polygon<P> >();
56 
57     // clockwise rings (second is wrongly ordered)
58     test_geometry<bg::model::ring<P> >("POLYGON((0 0,0 7,4 2,2 0,0 0))", 16.0);
59     test_geometry<bg::model::ring<P> >("POLYGON((0 0,2 0,4 2,0 7,0 0))", -16.0);
60 
61     test_geometry<all_custom_ring<P> >("POLYGON((0 0,0 7,4 2,2 0,0 0))", 16.0);
62 
63     // ccw
64     test_geometry<bg::model::polygon<P, false> >
65         ("POLYGON((0 0,0 7,4 2,2 0,0 0), (1 1,2 1,2 2,1 2,1 1))", -15.0);
66 
67     test_geometry<bg::model::polygon<P, false> >
68         ("POLYGON((1 0,0 1,-1 0,0 -1,1 0))", 2);
69 
70     typedef typename bg::coordinate_type<P>::type coord_type;
71     if (BOOST_GEOMETRY_CONDITION((boost::is_same<coord_type, double>::value)))
72     {
73         test_geometry<bg::model::polygon<P, false, false> >
74             ("POLYGON((100000001 100000000, 100000000 100000001, \
75                        99999999 100000000, 100000000  99999999))", 2);
76     }
77     else if (BOOST_GEOMETRY_CONDITION((boost::is_same<coord_type, float>::value)))
78     {
79         test_geometry<bg::model::polygon<P, false, false> >
80             ("POLYGON((100001 100000, 100000 100001, \
81                        99999 100000, 100000  99999))", 2);
82     }
83 }
84 
85 template <typename P>
test_ccw()86 void test_ccw()
87 {
88     typedef typename bg::coordinate_type<P>::type ct;
89     bg::model::polygon<P, false> ccw_polygon;
90     // counterclockwise rings (second is wrongly ordered)
91     std::string poly1 = "POLYGON((1 1,2 2,3 1,2 0,1 1))";
92     std::string poly2 = "POLYGON((1 1,2 0,3 1,2 2,1 1))";
93     std::string poly3 = "POLYGON((0 0,0 7,4 2,2 0,0 0))";
94     std::string poly4 = "POLYGON((0 0,2 0,4 2,0 7,0 0))";
95 
96     bg::read_wkt(poly1, ccw_polygon);
97     ct area1 = bg::area(ccw_polygon);
98     bg::read_wkt(poly2, ccw_polygon);
99     ct area2 = bg::area(ccw_polygon);
100     bg::read_wkt(poly3, ccw_polygon);
101     ct area3 = bg::area(ccw_polygon);
102     bg::read_wkt(poly4, ccw_polygon);
103     ct area4 = bg::area(ccw_polygon);
104     BOOST_CHECK_CLOSE(area1, -1 * area2, 0.001);
105     BOOST_CHECK_CLOSE(area3, -1 * area4, 0.001);
106 }
107 
108 template <typename P, typename CT>
test_open(CT expected_area)109 void test_open(CT expected_area)
110 {
111     typedef bg::model::polygon<P, true, false> open_polygon;
112     test_geometry<open_polygon>("POLYGON((1 1,2 2,3 1,2 0))", expected_area);
113     // Note the triangular testcase used in CCW is not sensible for open/close
114 }
115 
116 template <typename P, typename CT>
test_open_ccw(CT expected_area)117 void test_open_ccw(CT expected_area)
118 {
119     typedef bg::model::polygon<P, false, false> open_polygon;
120     test_geometry<open_polygon>("POLYGON((1 1,2 0,3 1,2 2))", expected_area);
121     // Note the triangular testcase used in CCW is not sensible for open/close
122 }
123 
124 template <typename P>
test_poles_ccw()125 void test_poles_ccw()
126 {
127     typedef typename bg::coordinate_type<P>::type ct;
128     bg::model::polygon<P, false> polygon;
129 
130     std::string poly1 = "POLYGON((45 45,45 95,95 45,45 45))";
131     std::string poly2 = "POLYGON((45 45,95 45,45 95,45 45))";
132     std::string poly3 = "POLYGON((45 -45,45 -95,95 -45,45 -45))";
133     std::string poly4 = "POLYGON((45 -45,95 -45,45 -95,45 -45))";
134 
135     bg::read_wkt(poly1, polygon);
136     ct area1 = bg::area(polygon);
137     bg::read_wkt(poly2, polygon);
138     ct area2 = bg::area(polygon);
139     bg::read_wkt(poly3, polygon);
140     ct area3 = bg::area(polygon);
141     bg::read_wkt(poly4, polygon);
142     ct area4 = bg::area(polygon);
143     BOOST_CHECK_CLOSE(area1, -1 * area2, 0.001);
144     BOOST_CHECK_CLOSE(area3, -1 * area4, 0.001);
145 }
146 
147 template <typename P>
test_empty_input()148 void test_empty_input()
149 {
150     bg::model::polygon<P> poly_empty;
151     bg::model::ring<P> ring_empty;
152 
153     test_empty_input(poly_empty);
154     test_empty_input(ring_empty);
155 }
156 
test_large_integers()157 void test_large_integers()
158 {
159     typedef bg::model::point<int, 2, bg::cs::cartesian> int_point_type;
160     typedef bg::model::point<double, 2, bg::cs::cartesian> double_point_type;
161 
162     bg::model::polygon<int_point_type> int_poly;
163     bg::model::polygon<double_point_type> double_poly;
164 
165     std::string const polygon_li = "POLYGON((1872000 528000,1872000 192000,\
166                                    1536119 192000,1536000 528000,1200000 528000,\
167                                    1200000 863880,1536000 863880,1872000 863880,\
168                                    1872000 528000))";
169     bg::read_wkt(polygon_li, int_poly);
170     bg::read_wkt(polygon_li, double_poly);
171 
172     double int_area = bg::area(int_poly);
173     double double_area = bg::area(double_poly);
174 
175     BOOST_CHECK_CLOSE(int_area, double_area, 0.0001);
176 }
177 
test_variant()178 void test_variant()
179 {
180     typedef bg::model::point<double, 2, bg::cs::cartesian> double_point_type;
181     typedef bg::model::polygon<double_point_type> polygon_type;
182     typedef bg::model::box<double_point_type> box_type;
183 
184     polygon_type poly;
185     std::string const polygon_li = "POLYGON((18 5,18 1,15 1,15 5,12 5,12 8,15 8,18 8,18 5))";
186     bg::read_wkt(polygon_li, poly);
187 
188     box_type box;
189     std::string const box_li = "BOX(0 0,2 2)";
190     bg::read_wkt(box_li, box);
191 
192     boost::variant<polygon_type, box_type> v;
193 
194     v = poly;
195     BOOST_CHECK_CLOSE(bg::area(v), bg::area(poly), 0.0001);
196     v = box;
197     BOOST_CHECK_CLOSE(bg::area(v), bg::area(box), 0.0001);
198 }
199 
test_main(int,char * [])200 int test_main(int, char* [])
201 {
202 
203     test_all<bg::model::point<int, 2, bg::cs::cartesian> >();
204     test_all<bg::model::point<float, 2, bg::cs::cartesian> >();
205     test_all<bg::model::point<double, 2, bg::cs::cartesian> >();
206 
207     typedef bg::model::point<double, 2, bg::cs::cartesian> pt_crt;
208     typedef bg::model::point<double, 2, bg::cs::spherical_equatorial<bg::degree> > pt_sph;
209     typedef bg::model::point<double, 2, bg::cs::geographic<bg::degree> > pt_geo;
210 
211     // mean Earth's radius^2
212     double r2 = bg::math::sqr(bg::get_radius<0>(bg::srs::sphere<double>()));
213 
214     test_ccw<pt_crt>();
215     test_ccw<pt_sph>();
216     test_ccw<pt_geo>();
217 
218     test_open<pt_crt>(2.0);
219     test_open<pt_sph>(24726179921.523518 / r2);
220     test_open<pt_geo >(24615492936.977146);
221 
222     test_open_ccw<pt_crt>(2.0);
223     test_open_ccw<pt_sph>(24726179921.523518 / r2);
224     test_open_ccw<pt_geo >(24615492936.977146);
225 
226     test_poles_ccw<pt_crt>();
227     test_poles_ccw<pt_sph>();
228     test_poles_ccw<pt_geo >();
229 
230 #ifdef HAVE_TTMATH
231     test_all<bg::model::d2::point_xy<ttmath_big> >();
232     test_spherical_geo<ttmath_big>();
233 #endif
234 
235     test_large_integers();
236 
237     test_variant();
238 
239     // test_empty_input<bg::model::d2::point_xy<int> >();
240 
241     return 0;
242 }
243