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