]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/geometry/test/io/wkt/wkt.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / geometry / test / io / wkt / wkt.cpp
CommitLineData
7c673cae
FG
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
1e59de90
TL
8// This file was modified by Oracle on 2014-2021.
9// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
7c673cae
FG
10
11// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
12
13// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
14// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
15
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)
19
20#include <sstream>
21#include <string>
20effc67 22#include <type_traits>
7c673cae
FG
23
24#include <boost/algorithm/string.hpp>
25
26#include <geometry_test_common.hpp>
27
28#include <boost/geometry/geometries/geometries.hpp>
29
30#include <boost/geometry/algorithms/area.hpp>
1e59de90 31#include <boost/geometry/algorithms/make.hpp>
7c673cae
FG
32#include <boost/geometry/algorithms/length.hpp>
33#include <boost/geometry/algorithms/num_points.hpp>
34#include <boost/geometry/algorithms/perimeter.hpp>
35#include <boost/geometry/strategies/strategies.hpp>
36#include <boost/geometry/core/point_type.hpp>
37#include <boost/geometry/core/topological_dimension.hpp>
38#include <boost/geometry/io/wkt/read.hpp>
39#include <boost/geometry/io/wkt/write.hpp>
40#include <boost/variant/variant.hpp>
41
42template <typename G>
43void check_wkt(G const& geometry, std::string const& expected)
44{
45 std::ostringstream out;
46 out << bg::wkt(geometry);
47 BOOST_CHECK_EQUAL(boost::to_upper_copy(out.str()),
48 boost::to_upper_copy(expected));
49}
50
51template <typename G>
1e59de90
TL
52void check_to_wkt(G const& geometry, std::string const& expected)
53{
54 std::string out_string;
55 out_string = bg::to_wkt(geometry);
56 BOOST_CHECK_EQUAL(boost::to_upper_copy(out_string),
57 boost::to_upper_copy(expected));
58}
59
60template <typename G>
61void check_precise_to_wkt(G const& geometry, std::string const& expected,
62 int significant_digits)
63{
64 std::string out_string;
65 out_string = bg::to_wkt(geometry, significant_digits);
66 BOOST_CHECK_EQUAL(boost::to_upper_copy(out_string),
67 boost::to_upper_copy(expected));
68}
69
70template <typename G>
71void test_wkt_read_write(std::string const& wkt, std::string const& expected,
7c673cae
FG
72 std::size_t n, double len = 0, double ar = 0, double peri = 0)
73{
74 G geometry;
75
76 bg::read_wkt(wkt, geometry);
77
1e59de90 78 #ifdef BOOST_GEOMETRY_TEST_DEBUG
7c673cae
FG
79 std::cout << "n=" << bg::num_points(geometry)
80 << " dim=" << bg::topological_dimension<G>::value
81 << " length=" << bg::length(geometry)
82 << " area=" << bg::area(geometry)
83 << " perimeter=" << bg::perimeter(geometry)
84 << std::endl << "\t\tgeometry=" << dsv(geometry)
85 << std::endl;
1e59de90 86 #endif
7c673cae
FG
87
88 BOOST_CHECK_EQUAL(bg::num_points(geometry), n);
89 if (n > 0)
90 {
91 BOOST_CHECK_CLOSE(double(bg::length(geometry)), len, 0.0001);
92 BOOST_CHECK_CLOSE(double(bg::area(geometry)), ar, 0.0001);
93 BOOST_CHECK_CLOSE(double(bg::perimeter(geometry)), peri, 0.0001);
94 }
95
96 check_wkt(geometry, expected);
1e59de90
TL
97
98 boost::variant<G> v;
99 bg::read_wkt(wkt, v);
100 check_wkt(v, expected);
101
102 bg::model::geometry_collection<boost::variant<G>> gc1{v};
103 bg::read_wkt(std::string("GEOMETRYCOLLECTION(") + wkt + ')', gc1);
104 check_wkt(gc1, std::string("GEOMETRYCOLLECTION(") + expected + ')');
105
106 bg::model::geometry_collection<boost::variant<G>> gc2{v, v};
107 bg::read_wkt(std::string("GEOMETRYCOLLECTION(") + wkt + ',' + wkt + ')', gc2);
108 check_wkt(gc2, std::string("GEOMETRYCOLLECTION(") + expected + ',' + expected + ')');
109}
110
111template <typename G>
112void test_wkt_to_from(std::string const& wkt, std::string const& expected,
113 std::size_t n, double len = 0, double ar = 0, double peri = 0)
114{
115 G geometry;
116
117 geometry = bg::from_wkt<G>(wkt);
118
119 #ifdef BOOST_GEOMETRY_TEST_DEBUG
120 std::cout << "n=" << bg::num_points(geometry)
121 << " dim=" << bg::topological_dimension<G>::value
122 << " length=" << bg::length(geometry)
123 << " area=" << bg::area(geometry)
124 << " perimeter=" << bg::perimeter(geometry)
125 << std::endl << "\t\tgeometry=" << dsv(geometry)
126 << std::endl;
127 #endif
128
129 BOOST_CHECK_EQUAL(bg::num_points(geometry), n);
130 if (n > 0)
131 {
132 BOOST_CHECK_CLOSE(double(bg::length(geometry)), len, 0.0001);
133 BOOST_CHECK_CLOSE(double(bg::area(geometry)), ar, 0.0001);
134 BOOST_CHECK_CLOSE(double(bg::perimeter(geometry)), peri, 0.0001);
135 }
136
137 check_to_wkt(geometry, expected);
138 check_to_wkt(boost::variant<G>(geometry), expected);
139}
140
141template <typename G>
142void test_wkt(std::string const& wkt, std::string const& expected,
143 std::size_t n, double len = 0, double ar = 0, double peri = 0)
144{
145 test_wkt_read_write<G>(wkt, expected, n, len, ar, peri);
146 test_wkt_to_from<G>(wkt, expected, n, len, ar, peri);
7c673cae
FG
147}
148
149template <typename G>
150void test_wkt(std::string const& wkt,
151 std::size_t n, double len = 0, double ar = 0, double peri = 0)
152{
153 test_wkt<G>(wkt, wkt, n, len, ar, peri);
154}
155
156template <typename G>
1e59de90 157void test_relaxed_wkt_read_write(std::string const& wkt, std::string const& expected)
7c673cae
FG
158{
159 std::string e;
160 G geometry;
161 bg::read_wkt(wkt, geometry);
162 std::ostringstream out;
163 out << bg::wkt(geometry);
164
165 BOOST_CHECK_EQUAL(boost::to_upper_copy(out.str()), boost::to_upper_copy(expected));
166}
167
1e59de90
TL
168template <typename G>
169void test_relaxed_wkt_to_from(std::string const& wkt, std::string const& expected)
170{
171 std::string e;
172 G geometry;
173 geometry = bg::from_wkt<G>(wkt);
174 std::string out;
175 out = bg::to_wkt(geometry);
7c673cae 176
1e59de90
TL
177 BOOST_CHECK_EQUAL(boost::to_upper_copy(out), boost::to_upper_copy(expected));
178}
7c673cae 179
1e59de90
TL
180template <typename G>
181void test_relaxed_wkt(std::string const& wkt, std::string const& expected)
182{
183 test_relaxed_wkt_read_write<G>(wkt, expected);
184 test_relaxed_wkt_to_from<G>(wkt, expected);
185}
7c673cae
FG
186
187template <typename G>
1e59de90 188void test_wrong_wkt_read_write(std::string const& wkt, std::string const& start)
7c673cae
FG
189{
190 std::string e("no exception");
191 G geometry;
192 try
193 {
1e59de90
TL
194 bg::read_wkt<G>(wkt, geometry);
195 }
196 catch(bg::read_wkt_exception const& ex)
197 {
198 e = ex.what();
199 boost::to_lower(e);
200 }
201 catch(...)
202 {
203 e = "other exception";
204 }
205
206 bool check = true;
207
208#if defined(HAVE_TTMATH)
209 // For ttmath we skip bad lexical casts
210 typedef typename bg::coordinate_type<G>::type ct;
211
212 if (boost::is_same<ct, ttmath_big>::type::value
213 && boost::starts_with(start, "bad lexical cast"))
214 {
215 check = false;
216 }
217#endif
218
219 if (check)
220 {
221 BOOST_CHECK_MESSAGE(boost::starts_with(e, start), " Expected:"
222 << start << " Got:" << e << " with WKT: " << wkt);
223 }
224}
225
226template <typename G>
227void test_wrong_wkt_to_from(std::string const& wkt, std::string const& start)
228{
229 std::string e("no exception");
230 G geometry;
231 try
232 {
233 geometry = bg::from_wkt<G>(wkt);
7c673cae
FG
234 }
235 catch(bg::read_wkt_exception const& ex)
236 {
237 e = ex.what();
238 boost::to_lower(e);
239 }
240 catch(...)
241 {
242 e = "other exception";
243 }
244
20effc67 245 BOOST_CHECK_MESSAGE(boost::starts_with(e, start), " Expected:"
7c673cae 246 << start << " Got:" << e << " with WKT: " << wkt);
7c673cae
FG
247}
248
1e59de90
TL
249template <typename G>
250void test_wrong_wkt(std::string const& wkt, std::string const& start)
251{
252 test_wrong_wkt_read_write<G>(wkt, start);
253 test_wrong_wkt_to_from<G>(wkt, start);
254}
255
7c673cae
FG
256template <typename G>
257void test_wkt_output_iterator(std::string const& wkt)
258{
259 G geometry;
260 bg::read_wkt<G>(wkt, std::back_inserter(geometry));
261}
262
1e59de90
TL
263void test_precise_to_wkt()
264{
265 typedef boost::geometry::model::d2::point_xy<double> point_type;
266 point_type point = boost::geometry::make<point_type>(1.2345, 6.7890);
267 boost::geometry::model::polygon<point_type> polygon;
268 boost::geometry::append(boost::geometry::exterior_ring(polygon), boost::geometry::make<point_type>(0.00000, 0.00000));
269 boost::geometry::append(boost::geometry::exterior_ring(polygon), boost::geometry::make<point_type>(0.00000, 4.00001));
270 boost::geometry::append(boost::geometry::exterior_ring(polygon), boost::geometry::make<point_type>(4.00001, 4.00001));
271 boost::geometry::append(boost::geometry::exterior_ring(polygon), boost::geometry::make<point_type>(4.00001, 0.00000));
272 boost::geometry::append(boost::geometry::exterior_ring(polygon), boost::geometry::make<point_type>(0.00000, 0.00000));
273 check_precise_to_wkt(point,"POINT(1.23 6.79)",3);
274 check_precise_to_wkt(polygon,"POLYGON((0 0,0 4,4 4,4 0,0 0))",3);
275}
7c673cae
FG
276
277#ifndef GEOMETRY_TEST_MULTI
278template <typename T>
279void test_order_closure()
280{
281 using namespace boost::geometry;
282 typedef bg::model::point<T, 2, bg::cs::cartesian> Pt;
283 typedef bg::model::polygon<Pt, true, true> PCWC;
284 typedef bg::model::polygon<Pt, true, false> PCWO;
285 typedef bg::model::polygon<Pt, false, true> PCCWC;
286 typedef bg::model::polygon<Pt, false, false> PCCWO;
287
288 {
289 std::string wkt_cwc = "POLYGON((0 0,0 2,2 2,2 0,0 0))";
290 std::string wkt_cwo = "POLYGON((0 0,0 2,2 2,2 0))";
291 std::string wkt_ccwc = "POLYGON((0 0,2 0,2 2,0 2,0 0))";
292 std::string wkt_ccwo = "POLYGON((0 0,2 0,2 2,0 2))";
293
294 test_wkt<PCWC>(wkt_cwc, 5, 0, 4, 8);
295 test_wkt<PCWO>(wkt_cwc, 4, 0, 4, 8);
296 test_wkt<PCWO>(wkt_cwo, wkt_cwc, 4, 0, 4, 8);
297 test_wkt<PCCWC>(wkt_ccwc, 5, 0, 4, 8);
298 test_wkt<PCCWO>(wkt_ccwc, 4, 0, 4, 8);
299 test_wkt<PCCWO>(wkt_ccwo, wkt_ccwc, 4, 0, 4, 8);
300 }
301 {
302 std::string wkt_cwc = "POLYGON((0 0,0 3,3 3,3 0,0 0),(1 1,2 1,2 2,1 2,1 1))";
303 std::string wkt_cwo = "POLYGON((0 0,0 3,3 3,3 0),(1 1,2 1,2 2,1 2))";
304 std::string wkt_ccwc = "POLYGON((0 0,3 0,3 3,0 3,0 0),(1 1,1 2,2 2,2 1,1 1))";
305 std::string wkt_ccwo = "POLYGON((0 0,3 0,3 3,0 3),(1 1,1 2,2 2,2 1,1 1))";
306
307 test_wkt<PCWC>(wkt_cwc, 10, 0, 8, 16);
308 test_wkt<PCWO>(wkt_cwc, 8, 0, 8, 16);
309 test_wkt<PCWO>(wkt_cwo, wkt_cwc, 8, 0, 8, 16);
310 test_wkt<PCCWC>(wkt_ccwc, 10, 0, 8, 16);
311 test_wkt<PCCWO>(wkt_ccwc, 8, 0, 8, 16);
312 test_wkt<PCCWO>(wkt_ccwo, wkt_ccwc, 8, 0, 8, 16);
313 }
314}
315
316template <typename T>
317void test_all()
318{
319 using namespace boost::geometry;
320 typedef bg::model::point<T, 2, bg::cs::cartesian> P;
321
322 test_wkt<P>("POINT(1 2)", 1);
323 test_wkt<bg::model::linestring<P> >("LINESTRING(1 1,2 2,3 3)", 3, 2 * sqrt(2.0));
324 test_wkt<bg::model::polygon<P> >("POLYGON((0 0,0 4,4 4,4 0,0 0)"
325 ",(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))", 15, 0, 18, 24);
326
327 // Non OGC: a box defined by a polygon
328 //test_wkt<box<P> >("POLYGON((0 0,0 1,1 1,1 0,0 0))", 4, 0, 1, 4);
329 test_wkt<bg::model::ring<P> >("POLYGON((0 0,0 1,1 1,1 0,0 0))", 5, 0, 1, 4);
330
331 // We accept empty sequences as well (much better than EMPTY)...
332 // ...or even POINT() (see below)
333 test_wkt<bg::model::linestring<P> >("LINESTRING()", 0, 0);
334 test_wkt<bg::model::polygon<P> >("POLYGON(())", 0);
335 // ... or even with empty holes
336 test_wkt<bg::model::polygon<P> >("POLYGON((),(),())", 0);
337 // which all make no valid geometries, but they can exist.
338
1e59de90
TL
339
340
7c673cae
FG
341 // These WKT's are incomplete or abnormal but they are considered OK
342 test_relaxed_wkt<P>("POINT(1)", "POINT(1 0)");
343 test_relaxed_wkt<P>("POINT()", "POINT(0 0)");
344 test_relaxed_wkt<bg::model::linestring<P> >("LINESTRING(1,2,3)",
345 "LINESTRING(1 0,2 0,3 0)");
346 test_relaxed_wkt<P>("POINT ( 1 2) ", "POINT(1 2)");
347 test_relaxed_wkt<P>("POINT M ( 1 2)", "POINT(1 2)");
348 test_relaxed_wkt<bg::model::box<P> >("BOX(1 1,2 2)", "POLYGON((1 1,1 2,2 2,2 1,1 1))");
349
350 test_relaxed_wkt<bg::model::linestring<P> >("LINESTRING EMPTY", "LINESTRING()");
351
352 test_relaxed_wkt<bg::model::polygon<P> >("POLYGON( ( ) , ( ) , ( ) )",
353 "POLYGON((),(),())");
354
355 // Wrong WKT's
356 test_wrong_wkt<P>("POINT(1 2", "expected ')'");
357 test_wrong_wkt<P>("POINT 1 2)", "expected '('");
358 test_wrong_wkt<P>("POINT(1 2,)", "expected ')'");
b32b8144 359 test_wrong_wkt<P>("POINT(1 2)foo", "too many tokens at 'foo'");
7c673cae
FG
360 test_wrong_wkt<P>("POINT(1 2 3)", "expected ')'");
361 test_wrong_wkt<P>("POINT(a 2 3)", "bad lexical cast");
362 test_wrong_wkt<P>("POINT 2 3", "expected '('");
363 test_wrong_wkt<P>("POINT Z (1 2 3)", "z only allowed");
364
365 test_wrong_wkt<P>("PIONT (1 2)", "should start with 'point'");
366
b32b8144 367 test_wrong_wkt<bg::model::linestring<P> >("LINESTRING())", "too many tokens");
7c673cae
FG
368
369 test_wrong_wkt<bg::model::polygon<P> >("POLYGON((1 1,1 4,4 4,4 1,1 1)"
370 ",((2 2,2 3,3 3,3 2,2 2))", "bad lexical cast");
371
372 test_wrong_wkt<bg::model::box<P> >("BOX(1 1,2 2,3 3)", "box should have 2");
b32b8144 373 test_wrong_wkt<bg::model::box<P> >("BOX(1 1,2 2) )", "too many tokens");
7c673cae 374
20effc67
TL
375 if ( BOOST_GEOMETRY_CONDITION(std::is_floating_point<T>::value
376 || ! std::is_fundamental<T>::value ) )
7c673cae
FG
377 {
378 test_wkt<P>("POINT(1.1 2.1)", 1);
379 }
380
381 // Deprecated:
382 // test_wkt_output_iterator<bg::model::linestring<P> >("LINESTRING(1 1,2 2,3 3)");
383 // test_wkt_output_iterator<bg::model::ring<P> >("POLYGON((1 1,2 2,3 3))");
384
385 test_order_closure<T>();
386}
387#endif
388
389int test_main(int, char* [])
390{
391 test_all<double>();
392 test_all<int>();
1e59de90
TL
393 test_precise_to_wkt();
394
395#if defined(HAVE_TTMATH)
396 test_all<ttmath_big>();
397#endif
7c673cae 398
7c673cae
FG
399 return 0;
400}
401
402/*
403
404Results can be checked in PostGIS by query below,
405or by MySQL (but replace length by glength and remove the perimeter)
406
407Note:
408- PostGIS gives "3" for a numpoints of a multi-linestring of 6 points in total (!)
409 --> "npoints" should be taken for all geometries
410- SQL Server 2008 gives "6"
411 select geometry::STGeomFromText('MULTILINESTRING((1 1,2 2,3 3),(4 4,5 5,6 6))',0).STNumPoints()
412- MySQL gives "NULL"
413
414select 1 as code,'np p' as header,npoints(geomfromtext('POINT(1 2)')) as contents
415union select 2,'length point', length(geomfromtext('POINT(1 2)'))
416union select 3,'peri point', perimeter(geomfromtext('POINT(1 2)'))
417union select 4,'area point',area(geomfromtext('POINT(1 2)'))
418
419
420union select 5,'# ls',npoints(geomfromtext('LINESTRING(1 1,2 2,3 3)'))
421union select 6,'length ls',length(geomfromtext('LINESTRING(1 1,2 2,3 3)'))
422union select 7,'peri ls',perimeter(geomfromtext('LINESTRING(1 1,2 2,3 3)'))
423union select 8,'aera ls',area(geomfromtext('LINESTRING(1 1,2 2,3 3)'))
424
425union select 9,'# poly',npoints(geomfromtext('POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))'))
426union select 10,'length poly',length(geomfromtext('POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))'))
427union select 11,'peri poly',perimeter(geomfromtext('POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))'))
428union select 12,'area poly',area(geomfromtext('POLYGON((0 0,0 4,4 4,4 0,0 0),(1 1,1 2,2 2,2 1,1 1),(1 1,1 2,2 2,2 1,1 1))'))
429
430*/