diff --git a/include/boost/geometry/io/wkt/write.hpp b/include/boost/geometry/io/wkt/write.hpp index b98c894b3..344c0ef0f 100644 --- a/include/boost/geometry/io/wkt/write.hpp +++ b/include/boost/geometry/io/wkt/write.hpp @@ -1,12 +1,12 @@ // Boost.Geometry (aka GGL, Generic Geometry Library) -// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. -// Copyright (c) 2008-2015 Bruno Lalande, Paris, France. -// Copyright (c) 2009-2015 Mateusz Loskot, London, UK. -// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland. +// Copyright (c) 2007-2017 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2008-2017 Bruno Lalande, Paris, France. +// Copyright (c) 2009-2017 Mateusz Loskot, London, UK. +// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland. // This file was modified by Oracle on 2015. -// Modifications copyright (c) 2015, Oracle and/or its affiliates. +// Modifications copyright (c) 2015-2017, Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle @@ -111,7 +111,7 @@ template struct wkt_point { template - static inline void apply(std::basic_ostream& os, Point const& p) + static inline void apply(std::basic_ostream& os, Point const& p, bool) { os << Policy::apply() << "("; stream_coordinate::type::value>::apply(os, p); @@ -123,12 +123,18 @@ struct wkt_point \brief Stream ranges as WKT \note policy is used to stream prefix/postfix, enabling derived classes to override this */ -template +template +< + typename Range, + bool ForceClosurePossible, + typename PrefixPolicy, + typename SuffixPolicy +> struct wkt_range { template static inline void apply(std::basic_ostream& os, - Range const& range, bool force_closed) + Range const& range, bool force_closure) { typedef typename boost::range_iterator::type iterator_type; @@ -153,7 +159,8 @@ struct wkt_range } // optionally, close range to ring by repeating the first point - if (force_closed + if (ForceClosurePossible + && force_closure && boost::size(range) > 1 && detail::disjoint::disjoint_point_point(*begin, *(end - 1))) { @@ -164,12 +171,6 @@ struct wkt_range os << SuffixPolicy::apply(); } - template - static inline void apply(std::basic_ostream& os, - Range const& range) - { - apply(os, range, false); - } private: typedef typename boost::range_value::type point_type; @@ -179,11 +180,12 @@ private: \brief Stream sequence of points as WKT-part, e.g. (1 2),(3 4) \note Used in polygon, all multi-geometries */ -template +template struct wkt_sequence : wkt_range < Range, + ForceClosurePossible, opening_parenthesis, closing_parenthesis > @@ -194,15 +196,14 @@ struct wkt_poly { template static inline void apply(std::basic_ostream& os, - Polygon const& poly) + Polygon const& poly, bool force_closure) { typedef typename ring_type::type ring; - bool const force_closed = true; os << PrefixPolicy::apply(); // TODO: check EMPTY here os << "("; - wkt_sequence::apply(os, exterior_ring(poly), force_closed); + wkt_sequence::apply(os, exterior_ring(poly), force_closure); typename interior_return_type::type rings = interior_rings(poly); @@ -210,10 +211,11 @@ struct wkt_poly it = boost::begin(rings); it != boost::end(rings); ++it) { os << ","; - wkt_sequence::apply(os, *it, force_closed); + wkt_sequence::apply(os, *it, force_closure); } os << ")"; } + }; template @@ -221,7 +223,7 @@ struct wkt_multi { template static inline void apply(std::basic_ostream& os, - Multi const& geometry) + Multi const& geometry, bool force_closure) { os << PrefixPolicy::apply(); // TODO: check EMPTY here @@ -236,7 +238,7 @@ struct wkt_multi { os << ","; } - StreamPolicy::apply(os, *it); + StreamPolicy::apply(os, *it, force_closure); } os << ")"; @@ -250,14 +252,14 @@ struct wkt_box template static inline void apply(std::basic_ostream& os, - Box const& box) + Box const& box, bool force_closure) { - // Convert to ring, then stream - typedef model::ring ring_type; + // Convert to open cw ring, then stream + typedef model::ring ring_type; ring_type ring; geometry::convert(box, ring); os << "POLYGON("; - wkt_sequence::apply(os, ring); + wkt_sequence::apply(os, ring, force_closure); os << ")"; } @@ -278,7 +280,7 @@ struct wkt_segment template static inline void apply(std::basic_ostream& os, - Segment const& segment) + Segment const& segment, bool) { // Convert to two points, then stream typedef boost::array sequence; @@ -290,7 +292,7 @@ struct wkt_segment // In Boost.Geometry a segment is represented // in WKT-format like (for 2D): LINESTRING(x y,x y) os << "LINESTRING"; - wkt_sequence::apply(os, points); + wkt_sequence::apply(os, points, false); } private: @@ -324,6 +326,7 @@ struct wkt : detail::wkt::wkt_range < Linestring, + false, detail::wkt::prefix_linestring_par, detail::wkt::closing_parenthesis > @@ -355,6 +358,7 @@ struct wkt : detail::wkt::wkt_range < Ring, + true, detail::wkt::prefix_ring_par_par, detail::wkt::double_closing_parenthesis > @@ -393,7 +397,8 @@ struct wkt Multi, detail::wkt::wkt_sequence < - typename boost::range_value::type + typename boost::range_value::type, + false >, detail::wkt::prefix_multilinestring > @@ -418,9 +423,10 @@ template struct devarianted_wkt { template - static inline void apply(OutputStream& os, Geometry const& geometry) + static inline void apply(OutputStream& os, Geometry const& geometry, + bool force_closure) { - wkt::apply(os, geometry); + wkt::apply(os, geometry, force_closure); } }; @@ -431,25 +437,27 @@ struct devarianted_wkt > struct visitor: static_visitor { OutputStream& m_os; + bool m_force_closure; - visitor(OutputStream& os) + visitor(OutputStream& os, bool force_closure) : m_os(os) + , m_force_closure(force_closure) {} template inline void operator()(Geometry const& geometry) const { - devarianted_wkt::apply(m_os, geometry); + devarianted_wkt::apply(m_os, geometry, m_force_closure); } }; template static inline void apply( OutputStream& os, - variant const& geometry - ) + variant const& geometry, + bool force_closure) { - boost::apply_visitor(visitor(os), geometry); + boost::apply_visitor(visitor(os, force_closure), geometry); } }; @@ -473,8 +481,9 @@ class wkt_manipulator { public: - inline wkt_manipulator(Geometry const& g) + inline wkt_manipulator(Geometry const& g, bool force_closure = true) : m_geometry(g) + , m_force_closure(force_closure) {} template @@ -482,13 +491,14 @@ public: std::basic_ostream& os, wkt_manipulator const& m) { - dispatch::devarianted_wkt::apply(os, m.m_geometry); + dispatch::devarianted_wkt::apply(os, m.m_geometry, m.m_force_closure); os.flush(); return os; } private: Geometry const& m_geometry; + bool m_force_closure; }; /*!