diff --git a/doc/imports.qbk b/doc/imports.qbk index c2b9dd2b9..8d7ae0f6a 100644 --- a/doc/imports.qbk +++ b/doc/imports.qbk @@ -156,6 +156,8 @@ [import src/examples/io/svg_mapper_custom.cpp] [import src/examples/io/wkt.cpp] [import src/examples/io/read_wkt.cpp] +[import src/examples/io/to_wkt.cpp] +[import src/examples/io/from_wkt.cpp] [import src/examples/strategies/buffer_join_round.cpp] [import src/examples/strategies/buffer_join_miter.cpp] diff --git a/doc/quickref.xml b/doc/quickref.xml index 092a7f2ae..359c6db34 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -719,6 +719,8 @@ read_wkt wkt + to_wkt + from_wkt diff --git a/doc/reference/io/from_wkt.qbk b/doc/reference/io/from_wkt.qbk new file mode 100644 index 000000000..97578f7a2 --- /dev/null +++ b/doc/reference/io/from_wkt.qbk @@ -0,0 +1,23 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2020 Baidyanath Kundu, Haldia, India. + + Use, modification and distribution is subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +=============================================================================/] + +[heading Conformance] +Other libraries refer to this functionality as [*ST_GeomFromText] or [*STGeomFromText]. +That is not done here because Boost.Geometry support more text formats. The name GeomFromText +is reserved for future usage, which will then have an indication of the used text format. + + +[heading Example] +[from_wkt] + +[heading See also] +* [link geometry.reference.io.wkt.wkt WKT streaming manipulator] +* [link geometry.reference.io.wkt.read_wkt Read WKT] +* [link geometry.reference.io.wkt.to_wkt To WKT] diff --git a/doc/reference/io/read_wkt.qbk b/doc/reference/io/read_wkt.qbk index 8022d8474..16d8aedf2 100644 --- a/doc/reference/io/read_wkt.qbk +++ b/doc/reference/io/read_wkt.qbk @@ -19,4 +19,6 @@ is reserved for future usage, which will then have an indication of the used tex [read_wkt] [heading See also] +* [link geometry.reference.io.wkt.from_wkt From WKT] +* [link geometry.reference.io.wkt.to_wkt To WKT] * [link geometry.reference.io.wkt.wkt WKT streaming manipulator] diff --git a/doc/reference/io/to_wkt.qbk b/doc/reference/io/to_wkt.qbk new file mode 100644 index 000000000..e4f5bd79e --- /dev/null +++ b/doc/reference/io/to_wkt.qbk @@ -0,0 +1,25 @@ +[/============================================================================ + Boost.Geometry (aka GGL, Generic Geometry Library) + + Copyright (c) 2009-2014 Barend Gehrels, Amsterdam, the Netherlands. + Copyright (c) 2020 Baidyanath Kundu, Haldia, India. + + Use, modification and distribution is subject to the Boost Software License, + Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +=============================================================================/] + +[def __this_function__ to_wkt] + +[heading_conformance_ogc __this_function__..AsText] +[note __this_function__ is not named "AsText" or "as_text" because Boost.Geometry +also supports other textformats (svg, dsv)] + +[heading Example] +[to_wkt] +[to_wkt_output] + +[heading See also] +* [link geometry.reference.io.wkt.read_wkt Read WKT] +* [link geometry.reference.io.wkt.from_wkt From WKT] +* [link geometry.reference.io.wkt.wkt WKT streaming manipulator] \ No newline at end of file diff --git a/doc/reference/io/wkt.qbk b/doc/reference/io/wkt.qbk index 7c45a9f67..04b6f0208 100644 --- a/doc/reference/io/wkt.qbk +++ b/doc/reference/io/wkt.qbk @@ -20,3 +20,5 @@ also supports other textformats (svg, dsv)] [heading See also] * [link geometry.reference.io.wkt.read_wkt Read WKT] +* [link geometry.reference.io.wkt.from_wkt From WKT] +* [link geometry.reference.io.wkt.from_wkt To WKT] diff --git a/doc/src/examples/io/Jamfile b/doc/src/examples/io/Jamfile index 3c013d8b6..eeab7e162 100644 --- a/doc/src/examples/io/Jamfile +++ b/doc/src/examples/io/Jamfile @@ -18,3 +18,5 @@ exe svg : svg.cpp ; exe svg_mapper_custom : svg_mapper_custom.cpp ; exe wkt : wkt.cpp ; exe read_wkt : read_wkt.cpp ; +exe to_wkt : to_wkt.cpp ; +exe from_wkt : from_wkt.cpp ; diff --git a/doc/src/examples/io/from_wkt.cpp b/doc/src/examples/io/from_wkt.cpp new file mode 100644 index 000000000..bccdeb942 --- /dev/null +++ b/doc/src/examples/io/from_wkt.cpp @@ -0,0 +1,36 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2020 Baidyanath Kundu, Haldia, India. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +//[from_wkt +//` Shows the usage of from_wkt + +#include +#include +#include +#include + +int main() +{ + using point_type = boost::geometry::model::d2::point_xy; + using box_type = boost::geometry::model::box; + using segment_type = boost::geometry::model::segment; + using polygon_type = boost::geometry::model::polygon; + using linestring_type = boost::geometry::model::linestring; + + auto const a = boost::geometry::from_wkt("POINT(1 2)"); + auto const d = boost::geometry::from_wkt("BOX(0 0,3 3)"); + auto const e = boost::geometry::from_wkt("SEGMENT(1 0,3 4)"); + auto const c = boost::geometry::from_wkt("POLYGON((0 0,0 7,4 2,2 0,0 0))"); + auto const b = boost::geometry::from_wkt("LINESTRING(0 0,2 2,3 1)"); + + return 0; +} + +//] diff --git a/doc/src/examples/io/to_wkt.cpp b/doc/src/examples/io/to_wkt.cpp new file mode 100644 index 000000000..fc04b51b6 --- /dev/null +++ b/doc/src/examples/io/to_wkt.cpp @@ -0,0 +1,64 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) +// QuickBook Example + +// Copyright (c) 2020 Baidyanath Kundu, Haldia, India. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +//[to_wkt +//` Shows the usage of to_wkt + +#include + +#include +#include +#include + +int main() +{ + namespace geom = boost::geometry; + typedef geom::model::d2::point_xy point_type; + + point_type point = geom::make(3, 2); + geom::model::polygon polygon; + geom::append(geom::exterior_ring(polygon), geom::make(0, 0)); + geom::append(geom::exterior_ring(polygon), geom::make(0, 4)); + geom::append(geom::exterior_ring(polygon), geom::make(4, 4)); + geom::append(geom::exterior_ring(polygon), geom::make(4, 0)); + geom::append(geom::exterior_ring(polygon), geom::make(0, 0)); + + std::cout << boost::geometry::to_wkt(point) << std::endl; + std::cout << boost::geometry::to_wkt(polygon) << std::endl; + + point_type point_frac = geom::make(3.141592654, 27.18281828); + geom::model::polygon polygon_frac; + geom::append(geom::exterior_ring(polygon_frac), geom::make(0.00000, 0.00000)); + geom::append(geom::exterior_ring(polygon_frac), geom::make(0.00000, 4.00001)); + geom::append(geom::exterior_ring(polygon_frac), geom::make(4.00001, 4.00001)); + geom::append(geom::exterior_ring(polygon_frac), geom::make(4.00001, 0.00000)); + geom::append(geom::exterior_ring(polygon_frac), geom::make(0.00000, 0.00000)); + + std::cout << boost::geometry::to_wkt(point_frac, 3) << std::endl; + std::cout << boost::geometry::to_wkt(polygon_frac, 3) << std::endl; + + return 0; +} + +//] + + +//[to_wkt_output +/*` +Output: +[pre +POINT(3 2) +POLYGON((0 0,0 4,4 4,4 0,0 0)) +POINT(3.14 27.2) +POLYGON((0 0,0 4,4 4,4 0,0 0)) +] + + +*/ +//] diff --git a/doc/src/examples/io/wkt.cpp b/doc/src/examples/io/wkt.cpp index ffde1b094..40d54fa71 100644 --- a/doc/src/examples/io/wkt.cpp +++ b/doc/src/examples/io/wkt.cpp @@ -42,7 +42,9 @@ int main() /*` Output: [pre -POINT(3 6) +POINT(3 2) +POLYGON((0 0,0 4,4 4,4 0,0 0)) +POINT(3.14 27.2) POLYGON((0 0,0 4,4 4,4 0,0 0)) ] diff --git a/include/boost/geometry/io/wkt/read.hpp b/include/boost/geometry/io/wkt/read.hpp index d75a44fd1..7e136af83 100644 --- a/include/boost/geometry/io/wkt/read.hpp +++ b/include/boost/geometry/io/wkt/read.hpp @@ -4,6 +4,7 @@ // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2020 Baidyanath Kundu, Haldia, India // This file was modified by Oracle on 2014-2020. // Modifications copyright (c) 2014-2020 Oracle and/or its affiliates. @@ -911,6 +912,23 @@ inline void read_wkt(std::string const& wkt, Geometry& geometry) dispatch::read_wkt::type, Geometry>::apply(wkt, geometry); } +/*! +\brief Parses OGC Well-Known Text (\ref WKT) into a geometry (any geometry) and returns it +\ingroup wkt +\tparam Geometry \tparam_geometry +\param wkt string containing \ref WKT +\ingroup wkt +\qbk{[include reference/io/from_wkt.qbk]} +*/ +template +inline Geometry from_wkt(std::string const& wkt) +{ + Geometry geometry; + geometry::concepts::check(); + dispatch::read_wkt::type, Geometry>::apply(wkt, geometry); + return geometry; +} + }} // namespace boost::geometry #endif // BOOST_GEOMETRY_IO_WKT_READ_HPP diff --git a/include/boost/geometry/io/wkt/write.hpp b/include/boost/geometry/io/wkt/write.hpp index 6b1ca59a0..27d48a060 100644 --- a/include/boost/geometry/io/wkt/write.hpp +++ b/include/boost/geometry/io/wkt/write.hpp @@ -4,6 +4,7 @@ // Copyright (c) 2008-2017 Bruno Lalande, Paris, France. // Copyright (c) 2009-2017 Mateusz Loskot, London, UK. // Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2020 Baidyanath Kundu, Haldia, India. // This file was modified by Oracle on 2015-2020. // Modifications copyright (c) 2015-2020, Oracle and/or its affiliates. @@ -558,6 +559,31 @@ inline wkt_manipulator wkt(Geometry const& geometry) return wkt_manipulator(geometry); } +/*! +\brief WKT-string formulating function +\tparam Geometry \tparam_geometry +\param geometry \param_geometry +\param significant_digits Specifies the no of significant digits to use in the output wkt +\ingroup wkt +\qbk{[include reference/io/to_wkt.qbk]} +*/ +template +inline std::string to_wkt(Geometry const& geometry) +{ + std::stringstream ss; + ss << boost::geometry::wkt(geometry); + return ss.str(); +} + +template +inline std::string to_wkt(Geometry const& geometry, int significant_digits) +{ + std::stringstream ss; + ss.precision(significant_digits); + ss << boost::geometry::wkt(geometry); + return ss.str(); +} + #if defined(_MSC_VER) #pragma warning(pop) #endif diff --git a/test/io/wkt/wkt.cpp b/test/io/wkt/wkt.cpp index ac418505d..ad2ea4f3d 100644 --- a/test/io/wkt/wkt.cpp +++ b/test/io/wkt/wkt.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -48,14 +49,33 @@ void check_wkt(G const& geometry, std::string const& expected) } template -void test_wkt(std::string const& wkt, std::string const& expected, +void check_to_wkt(G const& geometry, std::string const& expected) +{ + std::string out_string; + out_string = bg::to_wkt(geometry); + BOOST_CHECK_EQUAL(boost::to_upper_copy(out_string), + boost::to_upper_copy(expected)); +} + +template +void check_precise_to_wkt(G const& geometry, std::string const& expected, + int significant_digits) +{ + std::string out_string; + out_string = bg::to_wkt(geometry, significant_digits); + BOOST_CHECK_EQUAL(boost::to_upper_copy(out_string), + boost::to_upper_copy(expected)); +} + +template +void test_wkt_read_write(std::string const& wkt, std::string const& expected, std::size_t n, double len = 0, double ar = 0, double peri = 0) { G geometry; bg::read_wkt(wkt, geometry); - /* + #ifdef BOOST_GEOMETRY_TEST_DEBUG std::cout << "n=" << bg::num_points(geometry) << " dim=" << bg::topological_dimension::value << " length=" << bg::length(geometry) @@ -63,7 +83,7 @@ void test_wkt(std::string const& wkt, std::string const& expected, << " perimeter=" << bg::perimeter(geometry) << std::endl << "\t\tgeometry=" << dsv(geometry) << std::endl; - */ + #endif BOOST_CHECK_EQUAL(bg::num_points(geometry), n); if (n > 0) @@ -77,6 +97,44 @@ void test_wkt(std::string const& wkt, std::string const& expected, check_wkt(boost::variant(geometry), expected); } +template +void test_wkt_to_from(std::string const& wkt, std::string const& expected, + std::size_t n, double len = 0, double ar = 0, double peri = 0) +{ + G geometry; + + geometry = bg::from_wkt(wkt); + + #ifdef BOOST_GEOMETRY_TEST_DEBUG + std::cout << "n=" << bg::num_points(geometry) + << " dim=" << bg::topological_dimension::value + << " length=" << bg::length(geometry) + << " area=" << bg::area(geometry) + << " perimeter=" << bg::perimeter(geometry) + << std::endl << "\t\tgeometry=" << dsv(geometry) + << std::endl; + #endif + + BOOST_CHECK_EQUAL(bg::num_points(geometry), n); + if (n > 0) + { + BOOST_CHECK_CLOSE(double(bg::length(geometry)), len, 0.0001); + BOOST_CHECK_CLOSE(double(bg::area(geometry)), ar, 0.0001); + BOOST_CHECK_CLOSE(double(bg::perimeter(geometry)), peri, 0.0001); + } + + check_to_wkt(geometry, expected); + check_to_wkt(boost::variant(geometry), expected); +} + +template +void test_wkt(std::string const& wkt, std::string const& expected, + std::size_t n, double len = 0, double ar = 0, double peri = 0) +{ + test_wkt_read_write(wkt, expected, n, len, ar, peri); + test_wkt_to_from(wkt, expected, n, len, ar, peri); +} + template void test_wkt(std::string const& wkt, std::size_t n, double len = 0, double ar = 0, double peri = 0) @@ -85,7 +143,7 @@ void test_wkt(std::string const& wkt, } template -void test_relaxed_wkt(std::string const& wkt, std::string const& expected) +void test_relaxed_wkt_read_write(std::string const& wkt, std::string const& expected) { std::string e; G geometry; @@ -96,17 +154,72 @@ void test_relaxed_wkt(std::string const& wkt, std::string const& expected) BOOST_CHECK_EQUAL(boost::to_upper_copy(out.str()), boost::to_upper_copy(expected)); } +template +void test_relaxed_wkt_to_from(std::string const& wkt, std::string const& expected) +{ + std::string e; + G geometry; + geometry = bg::from_wkt(wkt); + std::string out; + out = bg::to_wkt(geometry); - + BOOST_CHECK_EQUAL(boost::to_upper_copy(out), boost::to_upper_copy(expected)); +} template -void test_wrong_wkt(std::string const& wkt, std::string const& start) +void test_relaxed_wkt(std::string const& wkt, std::string const& expected) +{ + test_relaxed_wkt_read_write(wkt, expected); + test_relaxed_wkt_to_from(wkt, expected); +} + +template +void test_wrong_wkt_read_write(std::string const& wkt, std::string const& start) { std::string e("no exception"); G geometry; try { - bg::read_wkt(wkt, geometry); + bg::read_wkt(wkt, geometry); + } + catch(bg::read_wkt_exception const& ex) + { + e = ex.what(); + boost::to_lower(e); + } + catch(...) + { + e = "other exception"; + } + + bool check = true; + +#if defined(HAVE_TTMATH) + // For ttmath we skip bad lexical casts + typedef typename bg::coordinate_type::type ct; + + if (boost::is_same::type::value + && boost::starts_with(start, "bad lexical cast")) + { + check = false; + } +#endif + + if (check) + { + BOOST_CHECK_MESSAGE(boost::starts_with(e, start), " Expected:" + << start << " Got:" << e << " with WKT: " << wkt); + } +} + +template +void test_wrong_wkt_to_from(std::string const& wkt, std::string const& start) +{ + std::string e("no exception"); + G geometry; + try + { + geometry = bg::from_wkt(wkt); } catch(bg::read_wkt_exception const& ex) { @@ -122,6 +235,13 @@ void test_wrong_wkt(std::string const& wkt, std::string const& start) << start << " Got:" << e << " with WKT: " << wkt); } +template +void test_wrong_wkt(std::string const& wkt, std::string const& start) +{ + test_wrong_wkt_read_write(wkt, start); + test_wrong_wkt_to_from(wkt, start); +} + template void test_wkt_output_iterator(std::string const& wkt) { @@ -129,7 +249,19 @@ void test_wkt_output_iterator(std::string const& wkt) bg::read_wkt(wkt, std::back_inserter(geometry)); } - +void test_precise_to_wkt() +{ + typedef boost::geometry::model::d2::point_xy point_type; + point_type point = boost::geometry::make(1.2345, 6.7890); + boost::geometry::model::polygon polygon; + boost::geometry::append(boost::geometry::exterior_ring(polygon), boost::geometry::make(0.00000, 0.00000)); + boost::geometry::append(boost::geometry::exterior_ring(polygon), boost::geometry::make(0.00000, 4.00001)); + boost::geometry::append(boost::geometry::exterior_ring(polygon), boost::geometry::make(4.00001, 4.00001)); + boost::geometry::append(boost::geometry::exterior_ring(polygon), boost::geometry::make(4.00001, 0.00000)); + boost::geometry::append(boost::geometry::exterior_ring(polygon), boost::geometry::make(0.00000, 0.00000)); + check_precise_to_wkt(point,"POINT(1.23 6.79)",3); + check_precise_to_wkt(polygon,"POLYGON((0 0,0 4,4 4,4 0,0 0))",3); +} #ifndef GEOMETRY_TEST_MULTI template @@ -193,6 +325,8 @@ void test_all() test_wkt >("POLYGON((),(),())", 0); // which all make no valid geometries, but they can exist. + + // These WKT's are incomplete or abnormal but they are considered OK test_relaxed_wkt

("POINT(1)", "POINT(1 0)"); test_relaxed_wkt

("POINT()", "POINT(0 0)"); @@ -245,6 +379,11 @@ int test_main(int, char* []) { test_all(); test_all(); + test_precise_to_wkt(); + +#if defined(HAVE_TTMATH) + test_all(); +#endif return 0; }