From a1ccbcdea7d14fda9ba9a63a99a2891dcb9d6b79 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Thu, 20 May 2021 00:42:04 +0200 Subject: [PATCH] [io][util] Add support for DynamicGeometry in read_wkt() Replace variant support in wkt write. Add util::sequence_find_if. --- include/boost/geometry/io/wkt/read.hpp | 129 ++++++++++++++++++++--- include/boost/geometry/io/wkt/write.hpp | 47 ++------- include/boost/geometry/util/sequence.hpp | 30 ++++++ test/io/wkt/wkt.cpp | 9 +- 4 files changed, 161 insertions(+), 54 deletions(-) diff --git a/include/boost/geometry/io/wkt/read.hpp b/include/boost/geometry/io/wkt/read.hpp index 10d4634c4..1d50af480 100644 --- a/include/boost/geometry/io/wkt/read.hpp +++ b/include/boost/geometry/io/wkt/read.hpp @@ -44,12 +44,14 @@ #include #include #include +#include #include #include #include #include #include +#include // For consistency with other functions #include #include @@ -60,6 +62,7 @@ #include #include +#include #include namespace boost { namespace geometry @@ -791,7 +794,6 @@ struct segment_parser } }; - }} // namespace detail::wkt #endif // DOXYGEN_NO_DETAIL @@ -799,12 +801,12 @@ struct segment_parser namespace dispatch { -template +template ::type> struct read_wkt {}; template -struct read_wkt +struct read_wkt : detail::wkt::geometry_parser < Point, @@ -815,7 +817,7 @@ struct read_wkt template -struct read_wkt +struct read_wkt : detail::wkt::geometry_parser < L, @@ -825,7 +827,7 @@ struct read_wkt {}; template -struct read_wkt +struct read_wkt : detail::wkt::geometry_parser < Ring, @@ -835,7 +837,7 @@ struct read_wkt {}; template -struct read_wkt +struct read_wkt : detail::wkt::geometry_parser < Geometry, @@ -846,7 +848,7 @@ struct read_wkt template -struct read_wkt +struct read_wkt : detail::wkt::multi_point_parser < MultiGeometry, @@ -855,7 +857,7 @@ struct read_wkt {}; template -struct read_wkt +struct read_wkt : detail::wkt::multi_parser < MultiGeometry, @@ -865,7 +867,7 @@ struct read_wkt {}; template -struct read_wkt +struct read_wkt : detail::wkt::multi_parser < MultiGeometry, @@ -877,17 +879,118 @@ struct read_wkt // Box (Non-OGC) template -struct read_wkt +struct read_wkt : detail::wkt::box_parser {}; // Segment (Non-OGC) template -struct read_wkt +struct read_wkt : detail::wkt::segment_parser {}; +template +struct read_wkt +{ + static inline void apply(std::string const& wkt, DynamicGeometry& dynamic_geometry) + { + detail::wkt::tokenizer tokens(wkt, boost::char_separator(" ", ",()")); + detail::wkt::tokenizer::iterator it = tokens.begin(); + detail::wkt::tokenizer::iterator end = tokens.end(); + if (it == end) + { + throw_unknown_name(wkt); + } + + if (boost::iequals(*it, "POINT")) + { + parse_geometry("POINT", wkt, dynamic_geometry); + } + else if (boost::iequals(*it, "MULTIPOINT")) + { + parse_geometry("MULTIPOINT", wkt, dynamic_geometry); + } + else if (boost::iequals(*it, "SEGMENT")) + { + parse_geometry("SEGMENT", wkt, dynamic_geometry); + } + else if (boost::iequals(*it, "LINESTRING")) + { + parse_geometry("LINESTRING", wkt, dynamic_geometry, false) + || parse_geometry("LINESTRING", wkt, dynamic_geometry); + } + else if (boost::iequals(*it, "MULTILINESTRING")) + { + parse_geometry("MULTILINESTRING", wkt, dynamic_geometry); + } + else if (boost::iequals(*it, "BOX")) + { + parse_geometry("BOX", wkt, dynamic_geometry); + } + else if (boost::iequals(*it, "POLYGON")) + { + parse_geometry("POLYGON", wkt, dynamic_geometry, false) + || parse_geometry("POLYGON", wkt, dynamic_geometry, false) + || parse_geometry("POLYGON", wkt, dynamic_geometry); + } + else if (boost::iequals(*it, "MULTIPOLYGON")) + { + parse_geometry("MULTIPOLYGON", wkt, dynamic_geometry); + } + else + { + throw_unknown_name(wkt); + } + } + + static void throw_unknown_name(std::string const& wkt) + { + BOOST_THROW_EXCEPTION(read_wkt_exception( + "Should start with geometry's name, e.g. 'POINT', 'LINESTRING', 'POLYGON', etc.", + wkt)); + } + + template + < + template class UnaryPred, + typename Geometry = typename util::sequence_find_if + < + typename traits::geometry_types::type, UnaryPred + >::type, + std::enable_if_t::value, int> = 0 + > + static bool parse_geometry(const char * , std::string const& wkt, DynamicGeometry & dynamic_geometry, bool = true) + { + Geometry g; + read_wkt::apply(wkt, g); + dynamic_geometry = std::move(g); + + return true; + } + + template + < + template class UnaryPred, + typename Geometry = typename util::sequence_find_if + < + typename traits::geometry_types::type, UnaryPred + >::type, + std::enable_if_t::value, int> = 0 + > + static bool parse_geometry(const char * name, std::string const& wkt, DynamicGeometry & , bool throw_on_misfit = true) + { + if (throw_on_misfit) + { + std::string msg = std::string("Unable to store '") + name + "' in this geometry"; + BOOST_THROW_EXCEPTION(read_wkt_exception(msg, wkt)); + } + + return false; + } +}; + + } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH @@ -904,7 +1007,7 @@ template inline void read_wkt(std::string const& wkt, Geometry& geometry) { geometry::concepts::check(); - dispatch::read_wkt::type, Geometry>::apply(wkt, geometry); + dispatch::read_wkt::apply(wkt, geometry); } /*! @@ -920,7 +1023,7 @@ inline Geometry from_wkt(std::string const& wkt) { Geometry geometry; geometry::concepts::check(); - dispatch::read_wkt::type, Geometry>::apply(wkt, geometry); + dispatch::read_wkt::apply(wkt, geometry); return geometry; } diff --git a/include/boost/geometry/io/wkt/write.hpp b/include/boost/geometry/io/wkt/write.hpp index 27d48a060..a1ceca9c2 100644 --- a/include/boost/geometry/io/wkt/write.hpp +++ b/include/boost/geometry/io/wkt/write.hpp @@ -6,8 +6,8 @@ // 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. +// This file was modified by Oracle on 2015-2021. +// Modifications copyright (c) 2015-2021, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -30,9 +30,6 @@ #include #include #include -#include -#include -#include #include #include @@ -43,7 +40,9 @@ #include #include #include +#include +#include // For backward compatibility #include #include @@ -458,44 +457,16 @@ struct wkt template -struct devarianted_wkt +struct wkt { template static inline void apply(OutputStream& os, Geometry const& geometry, bool force_closure) { - wkt::apply(os, geometry, force_closure); - } -}; - -template -struct devarianted_wkt > -{ - template - struct visitor: static_visitor - { - OutputStream& m_os; - bool m_force_closure; - - visitor(OutputStream& os, bool force_closure) - : m_os(os) - , m_force_closure(force_closure) - {} - - template - inline void operator()(Geometry const& geometry) const + traits::visit::apply([&](auto const& g) { - devarianted_wkt::apply(m_os, geometry, m_force_closure); - } - }; - - template - static inline void apply( - OutputStream& os, - variant const& geometry, - bool force_closure) - { - boost::apply_visitor(visitor(os, force_closure), geometry); + wkt>::apply(os, g, force_closure); + }, geometry); } }; @@ -534,7 +505,7 @@ public: std::basic_ostream& os, wkt_manipulator const& m) { - dispatch::devarianted_wkt::apply(os, m.m_geometry, m.m_force_closure); + dispatch::wkt::apply(os, m.m_geometry, m.m_force_closure); os.flush(); return os; } diff --git a/include/boost/geometry/util/sequence.hpp b/include/boost/geometry/util/sequence.hpp index 81400bac3..80e3b7b23 100644 --- a/include/boost/geometry/util/sequence.hpp +++ b/include/boost/geometry/util/sequence.hpp @@ -112,6 +112,36 @@ struct sequence_empty {}; +template +< + typename Sequence, + template class UnaryPred +> +struct sequence_find_if {}; + +template +< + typename T, typename ...Ts, + template class UnaryPred +> +struct sequence_find_if, UnaryPred> + : std::conditional + < + UnaryPred::value, + T, + // TODO: prevent instantiation for the rest of the sequence if value is true + typename sequence_find_if, UnaryPred>::type + > +{}; + +template