]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/test/algorithms/area.cpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
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.
8 // This file was modified by Oracle on 2015, 2016.
9 // Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
13 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
14 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16 // Use, modification and distribution is subject to the Boost Software License,
17 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
18 // http://www.boost.org/LICENSE_1_0.txt)
21 #include <algorithms/test_area.hpp>
23 #include <boost/geometry/geometries/point_xy.hpp>
24 #include <boost/geometry/geometries/point.hpp>
25 #include <boost/geometry/geometries/box.hpp>
26 #include <boost/geometry/geometries/ring.hpp>
27 #include <boost/geometry/geometries/polygon.hpp>
29 #include <test_geometries/all_custom_ring.hpp>
30 #include <test_geometries/all_custom_polygon.hpp>
31 //#define BOOST_GEOMETRY_TEST_DEBUG
33 #include <boost/variant/variant.hpp>
35 template <typename Polygon
>
38 // Rotated square, length=sqrt(2) -> area=2
39 test_geometry
<Polygon
>("POLYGON((1 1,2 2,3 1,2 0,1 1))", 2.0);
40 test_geometry
<Polygon
>("POLYGON((1 1,2 2,3 1,2 0,1 1))", 2.0);
41 test_geometry
<Polygon
>("POLYGON((0 0,0 7,4 2,2 0,0 0))", 16.0);
42 test_geometry
<Polygon
>("POLYGON((1 1,2 1,2 2,1 2,1 1))", -1.0);
43 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);
50 test_geometry
<bg::model::box
<P
> >("POLYGON((0 0,2 2))", 4.0);
51 test_geometry
<bg::model::box
<P
> >("POLYGON((2 2,0 0))", 4.0);
53 test_polygon
<bg::model::polygon
<P
> >();
54 test_polygon
<all_custom_polygon
<P
> >();
56 // clockwise rings (second is wrongly ordered)
57 test_geometry
<bg::model::ring
<P
> >("POLYGON((0 0,0 7,4 2,2 0,0 0))", 16.0);
58 test_geometry
<bg::model::ring
<P
> >("POLYGON((0 0,2 0,4 2,0 7,0 0))", -16.0);
60 test_geometry
<all_custom_ring
<P
> >("POLYGON((0 0,0 7,4 2,2 0,0 0))", 16.0);
63 test_geometry
<bg::model::polygon
<P
, false> >
64 ("POLYGON((0 0,0 7,4 2,2 0,0 0), (1 1,2 1,2 2,1 2,1 1))", -15.0);
66 test_geometry
<bg::model::polygon
<P
, false> >
67 ("POLYGON((1 0,0 1,-1 0,0 -1,1 0))", 2);
69 typedef typename
bg::coordinate_type
<P
>::type coord_type
;
70 if (BOOST_GEOMETRY_CONDITION((boost::is_same
<coord_type
, double>::value
)))
72 test_geometry
<bg::model::polygon
<P
, false, false> >
73 ("POLYGON((100000001 100000000, 100000000 100000001, \
74 99999999 100000000, 100000000 99999999))", 2);
76 else if (BOOST_GEOMETRY_CONDITION((boost::is_same
<coord_type
, float>::value
)))
78 test_geometry
<bg::model::polygon
<P
, false, false> >
79 ("POLYGON((100001 100000, 100000 100001, \
80 99999 100000, 100000 99999))", 2);
84 template <typename Point
>
85 void test_spherical(bool polar
= false)
87 typedef typename
bg::coordinate_type
<Point
>::type ct
;
88 bg::model::polygon
<Point
> geometry
;
90 // unit-sphere has area of 4-PI. Polygon covering 1/8 of it:
91 // calculations splitted for ttmath
94 ct expected
= four
* boost::geometry::math::pi
<ct
>() / eight
;
95 bg::read_wkt("POLYGON((0 0,0 90,90 0,0 0))", geometry
);
97 ct area
= bg::area(geometry
);
98 BOOST_CHECK_CLOSE(area
, expected
, 0.0001);
100 // With strategy, radius 2 -> 4 pi r^2
101 bg::strategy::area::huiller
103 typename
bg::point_type
<Point
>::type
106 area
= bg::area(geometry
, strategy
);
108 BOOST_CHECK_CLOSE(area
, two
* two
* expected
, 0.0001);
110 // Wrangel Island (dateline crossing)
111 // With (spherical) Earth strategy
112 bg::strategy::area::huiller
114 typename
bg::point_type
<Point
>::type
115 > spherical_earth(6373);
116 bg::read_wkt("POLYGON((-178.7858 70.7852, 177.4758 71.2333, 179.7436 71.5733, -178.7858 70.7852))", geometry
);
117 area
= bg::area(geometry
, spherical_earth
);
118 // SQL Server gives: 4537.9654419375
119 // PostGIS gives: 4537.9311668307
120 // Note: those are Geographic, this test is Spherical
121 BOOST_CHECK_CLOSE(area
, 4506.6389, 0.001);
123 // Wrangel, more in detail
124 bg::read_wkt("POLYGON((-178.568604 71.564148,-178.017548 71.449692,-177.833313 71.3461,-177.502838 71.277466 ,-177.439453 71.226929,-177.620026 71.116638,-177.9389 71.037491,-178.8186 70.979965,-179.274445 70.907761,-180 70.9972,179.678314 70.895538,179.272766 70.888596,178.791016 70.7964,178.617737 71.035538,178.872192 71.217484,179.530273 71.4383 ,-180 71.535843 ,-179.628601 71.577194,-179.305298 71.551361,-179.03421 71.597748,-178.568604 71.564148))", geometry
);
125 area
= bg::area(geometry
, spherical_earth
);
126 // SQL Server gives: 7669.10402181435
127 // PostGIS gives: 7669.55565459832
128 BOOST_CHECK_CLOSE(area
, 7616.523769, 0.001);
130 // Check more at the equator
132 select 1,geography::STGeomFromText('POLYGON((-178.7858 10.7852 , 179.7436 11.5733 , 177.4758 11.2333 , -178.7858 10.7852))',4326) .STArea()/1000000.0
133 union select 2,geography::STGeomFromText('POLYGON((-178.7858 20.7852 , 179.7436 21.5733 , 177.4758 21.2333 , -178.7858 20.7852))',4326) .STArea()/1000000.0
134 union select 3,geography::STGeomFromText('POLYGON((-178.7858 30.7852 , 179.7436 31.5733 , 177.4758 31.2333 , -178.7858 30.7852))',4326) .STArea()/1000000.0
135 union select 0,geography::STGeomFromText('POLYGON((-178.7858 0.7852 , 179.7436 1.5733 , 177.4758 1.2333 , -178.7858 0.7852))',4326) .STArea()/1000000.0
136 union select 4,geography::STGeomFromText('POLYGON((-178.7858 40.7852 , 179.7436 41.5733 , 177.4758 41.2333 , -178.7858 40.7852))',4326) .STArea()/1000000.0
139 bg::read_wkt("POLYGON((-178.7858 0.7852, 177.4758 1.2333, 179.7436 1.5733, -178.7858 0.7852))", geometry
);
140 area
= bg::area(geometry
, spherical_earth
);
141 BOOST_CHECK_CLOSE(area
, 14136.09946, 0.001); // SQL Server gives: 14064.1902284513
144 bg::read_wkt("POLYGON((-178.7858 10.7852, 177.4758 11.2333, 179.7436 11.5733, -178.7858 10.7852))", geometry
);
145 area
= bg::area(geometry
, spherical_earth
);
146 BOOST_CHECK_CLOSE(area
, 13760.2456, 0.001); // SQL Server gives: 13697.0941155193
148 bg::read_wkt("POLYGON((-178.7858 20.7852, 177.4758 21.2333, 179.7436 21.5733, -178.7858 20.7852))", geometry
);
149 area
= bg::area(geometry
, spherical_earth
);
150 BOOST_CHECK_CLOSE(area
, 12987.8682, 0.001); // SQL Server gives: 12944.3970990317 -> -39m^2
152 bg::read_wkt("POLYGON((-178.7858 30.7852, 177.4758 31.2333, 179.7436 31.5733, -178.7858 30.7852))", geometry
);
153 area
= bg::area(geometry
, spherical_earth
);
154 BOOST_CHECK_CLOSE(area
, 11856.3935, 0.001); // SQL Server gives: 11838.5338423574 -> -18m^2
156 bg::read_wkt("POLYGON((-178.7858 40.7852, 177.4758 41.2333, 179.7436 41.5733, -178.7858 40.7852))", geometry
);
157 area
= bg::area(geometry
, spherical_earth
);
158 BOOST_CHECK_CLOSE(area
, 10404.627685523914, 0.001); // SQL Server gives: 10412.0607137119, -> +8m^2
161 bg::read_wkt("POLYGON((0 40,1 42,0 44,2 43,4 44,3 42,4 40,2 41,0 40))", geometry
);
162 area
= bg::area(geometry
, spherical_earth
);
163 BOOST_CHECK_CLOSE(area
, 73538.2958, 0.001); // SQL Server gives: 73604.2047689719
165 // With hole POLYGON((0 40,4 40,4 44,0 44,0 40),(1 41,2 43,3 42,1 41))
166 bg::read_wkt("POLYGON((0 40,0 44,4 44,4 40,0 40),(1 41,3 42,2 43,1 41))", geometry
);
167 area
= bg::area(geometry
, spherical_earth
);
168 BOOST_CHECK_CLOSE(area
, 133233.844876, 0.001); // SQL Server gives: 133353.335
172 bg::read_wkt("POLYGON((-10 0,-10 10,0 10,0 0,-10 0))", geometry
);
173 ct area1
= bg::area(geometry
);
174 bg::read_wkt("POLYGON((0 0,0 10,10 10,10 0,0 0))", geometry
);
175 ct area2
= bg::area(geometry
);
176 bg::read_wkt("POLYGON((-5 0,-5 10,5 10,5 0,-5 0))", geometry
);
177 ct area3
= bg::area(geometry
);
178 BOOST_CHECK_CLOSE(area1
, area2
, 0.001);
179 BOOST_CHECK_CLOSE(area2
, area3
, 0.001);
180 BOOST_CHECK_CLOSE(area1
, 0.0303822, 0.001);
183 bg::read_wkt("POLYGON((-10 -5,-10 5,0 5,0 -5,-10 -5))", geometry
);
184 ct area1
= bg::area(geometry
);
185 bg::read_wkt("POLYGON((0 -5,0 5,10 5,10 -5,0 -5))", geometry
);
186 ct area2
= bg::area(geometry
);
187 bg::read_wkt("POLYGON((-5 -5,-5 5,5 5,5 -5,-5 -5))", geometry
);
188 ct area3
= bg::area(geometry
);
189 BOOST_CHECK_CLOSE(area1
, area2
, 0.001);
190 BOOST_CHECK_CLOSE(area2
, area3
, 0.001);
191 BOOST_CHECK_CLOSE(area1
, 0.0305, 0.001);
193 // around 180 meridian
195 bg::read_wkt("POLYGON((-180 0,-180 10,-170 10,-170 0,-180 0))", geometry
);
196 ct area1
= bg::area(geometry
);
197 bg::read_wkt("POLYGON((175 0,175 10,-175 10,-175 0,175 0))", geometry
);
198 ct area2
= bg::area(geometry
);
199 bg::read_wkt("POLYGON((170 0,170 10,180 10,180 0,170 0))", geometry
);
200 ct area3
= bg::area(geometry
);
201 bg::read_wkt("POLYGON((170 0,170 10,-180 10,-180 0,170 0))", geometry
);
202 ct area4
= bg::area(geometry
);
203 bg::read_wkt("POLYGON((180 0,180 10,-170 10,-170 0,180 0))", geometry
);
204 ct area5
= bg::area(geometry
);
205 BOOST_CHECK_CLOSE(area1
, area2
, 0.001);
206 BOOST_CHECK_CLOSE(area2
, area3
, 0.001);
207 BOOST_CHECK_CLOSE(area3
, area4
, 0.001);
208 BOOST_CHECK_CLOSE(area4
, area5
, 0.001);
209 BOOST_CHECK_CLOSE(area1
, 0.0303822, 0.001);
212 bg::read_wkt("POLYGON((-180 -5,-180 5,-170 5,-170 -5,-180 -5))", geometry
);
213 ct area1
= bg::area(geometry
);
214 bg::read_wkt("POLYGON((175 -5,175 5,-175 5,-175 -5,175 -5))", geometry
);
215 ct area2
= bg::area(geometry
);
216 bg::read_wkt("POLYGON((170 -5,170 5,180 5,180 -5,170 -5))", geometry
);
217 ct area3
= bg::area(geometry
);
218 bg::read_wkt("POLYGON((170 -5,170 5,-180 5,-180 -5,170 -5))", geometry
);
219 ct area4
= bg::area(geometry
);
220 bg::read_wkt("POLYGON((180 -5,180 5,-170 5,-170 -5,180 -5))", geometry
);
221 ct area5
= bg::area(geometry
);
222 BOOST_CHECK_CLOSE(area1
, area2
, 0.001);
223 BOOST_CHECK_CLOSE(area2
, area3
, 0.001);
224 BOOST_CHECK_CLOSE(area3
, area4
, 0.001);
225 BOOST_CHECK_CLOSE(area4
, area5
, 0.001);
226 BOOST_CHECK_CLOSE(area1
, 0.0305, 0.001);
229 #ifdef BOOST_GEOMETRY_ENABLE_FAILING_TESTS
231 bg::read_wkt("POLYGON((0 80,-90 80,-180 80,90 80,0 80))", geometry
);
232 ct area1
= bg::area(geometry
);
233 bg::read_wkt("POLYGON((0 80,-90 80,180 80,90 80,0 80))", geometry
);
234 ct area2
= bg::area(geometry
);
235 bg::read_wkt("POLYGON((0 -80,90 -80,-180 -80,-90 -80,0 -80))", geometry
);
236 ct area3
= bg::area(geometry
);
237 bg::read_wkt("POLYGON((0 -80,90 -80,180 -80,-90 -80,0 -80))", geometry
);
238 ct area4
= bg::area(geometry
);
239 BOOST_CHECK_CLOSE(area1
, area2
, 0.001);
240 BOOST_CHECK_CLOSE(area2
, area3
, 0.001);
241 BOOST_CHECK_CLOSE(area3
, area4
, 0.001);
246 bg::model::ring
<Point
> aurha
; // a'dam-utr-rott.-den haag-a'dam
247 bg::read_wkt("POLYGON((4.892 52.373,5.119 52.093,4.479 51.930,4.23 52.08,4.892 52.373))", aurha
);
250 // Create colatitudes (measured from pole)
251 BOOST_FOREACH(Point
& p
, aurha
)
253 bg::set
<1>(p
, ct(90) - bg::get
<1>(p
));
257 bg::strategy::area::huiller
259 typename
bg::point_type
<Point
>::type
261 area
= bg::area(aurha
, huiller
);
262 BOOST_CHECK_CLOSE(area
, 1476.645675, 0.0001);
264 // SQL Server gives: 1481.55595960659
265 // for select geography::STGeomFromText('POLYGON((4.892 52.373,4.23 52.08,4.479 51.930,5.119 52.093,4.892 52.373))',4326).STArea()/1000000.0
269 template <typename P
>
272 typedef bg::model::polygon
<P
, false> ccw_polygon
;
273 // counterclockwise rings (second is wrongly ordered)
274 test_geometry
<ccw_polygon
>("POLYGON((1 1,2 2,3 1,2 0,1 1))", -2.0);
275 test_geometry
<ccw_polygon
>("POLYGON((1 1,2 0,3 1,2 2,1 1))", +2.0);
276 test_geometry
<ccw_polygon
>("POLYGON((0 0,0 7,4 2,2 0,0 0))", -16.0);
277 test_geometry
<ccw_polygon
>("POLYGON((0 0,2 0,4 2,0 7,0 0))", +16.0);
280 template <typename P
>
283 typedef bg::model::polygon
<P
, true, false> open_polygon
;
284 test_geometry
<open_polygon
>("POLYGON((1 1,2 2,3 1,2 0))", 2.0);
285 // Note the triangular testcase used in CCW is not sensible for open/close
288 template <typename P
>
291 typedef bg::model::polygon
<P
, false, false> open_polygon
;
292 test_geometry
<open_polygon
>("POLYGON((1 1,2 0,3 1,2 2))", 2.0);
293 // Note the triangular testcase used in CCW is not sensible for open/close
296 template <typename P
>
297 void test_empty_input()
299 bg::model::polygon
<P
> poly_empty
;
300 bg::model::ring
<P
> ring_empty
;
302 test_empty_input(poly_empty
);
303 test_empty_input(ring_empty
);
306 void test_large_integers()
308 typedef bg::model::point
<int, 2, bg::cs::cartesian
> int_point_type
;
309 typedef bg::model::point
<double, 2, bg::cs::cartesian
> double_point_type
;
311 bg::model::polygon
<int_point_type
> int_poly
;
312 bg::model::polygon
<double_point_type
> double_poly
;
314 std::string
const polygon_li
= "POLYGON((1872000 528000,1872000 192000,1536119 192000,1536000 528000,1200000 528000,1200000 863880,1536000 863880,1872000 863880,1872000 528000))";
315 bg::read_wkt(polygon_li
, int_poly
);
316 bg::read_wkt(polygon_li
, double_poly
);
318 double int_area
= bg::area(int_poly
);
319 double double_area
= bg::area(double_poly
);
321 BOOST_CHECK_CLOSE(int_area
, double_area
, 0.0001);
326 typedef bg::model::point
<double, 2, bg::cs::cartesian
> double_point_type
;
327 typedef bg::model::polygon
<double_point_type
> polygon_type
;
328 typedef bg::model::box
<double_point_type
> box_type
;
331 std::string
const polygon_li
= "POLYGON((18 5,18 1,15 1,15 5,12 5,12 8,15 8,18 8,18 5))";
332 bg::read_wkt(polygon_li
, poly
);
335 std::string
const box_li
= "BOX(0 0,2 2)";
336 bg::read_wkt(box_li
, box
);
338 boost::variant
<polygon_type
, box_type
> v
;
341 BOOST_CHECK_CLOSE(bg::area(v
), bg::area(poly
), 0.0001);
343 BOOST_CHECK_CLOSE(bg::area(v
), bg::area(box
), 0.0001);
346 int test_main(int, char* [])
348 test_all
<bg::model::point
<int, 2, bg::cs::cartesian
> >();
349 test_all
<bg::model::point
<float, 2, bg::cs::cartesian
> >();
350 test_all
<bg::model::point
<double, 2, bg::cs::cartesian
> >();
352 test_spherical
<bg::model::point
<double, 2, bg::cs::spherical_equatorial
<bg::degree
> > >();
353 //test_spherical<bg::model::point<double, 2, bg::cs::spherical<bg::degree> > >(true);
355 test_ccw
<bg::model::point
<double, 2, bg::cs::cartesian
> >();
356 test_open
<bg::model::point
<double, 2, bg::cs::cartesian
> >();
357 test_open_ccw
<bg::model::point
<double, 2, bg::cs::cartesian
> >();
360 test_all
<bg::model::d2::point_xy
<ttmath_big
> >();
361 test_spherical
<bg::model::point
<ttmath_big
, 2, bg::cs::spherical_equatorial
<bg::degree
> > >();
364 test_large_integers();
368 // test_empty_input<bg::model::d2::point_xy<int> >();