diff options
Diffstat (limited to 'boost/geometry/io/wkt/write.hpp')
-rw-r--r-- | boost/geometry/io/wkt/write.hpp | 215 |
1 files changed, 174 insertions, 41 deletions
diff --git a/boost/geometry/io/wkt/write.hpp b/boost/geometry/io/wkt/write.hpp index a3e3173d05..6c1a2e153e 100644 --- a/boost/geometry/io/wkt/write.hpp +++ b/boost/geometry/io/wkt/write.hpp @@ -3,6 +3,7 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. @@ -18,24 +19,36 @@ #include <string> #include <boost/array.hpp> -#include <boost/concept/assert.hpp> #include <boost/range.hpp> -#include <boost/typeof/typeof.hpp> +#include <boost/variant/apply_visitor.hpp> +#include <boost/variant/static_visitor.hpp> +#include <boost/variant/variant_fwd.hpp> +#include <boost/geometry/algorithms/detail/interior_iterator.hpp> #include <boost/geometry/algorithms/assign.hpp> #include <boost/geometry/algorithms/convert.hpp> +#include <boost/geometry/algorithms/disjoint.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> #include <boost/geometry/core/exterior_ring.hpp> #include <boost/geometry/core/interior_rings.hpp> #include <boost/geometry/core/ring_type.hpp> +#include <boost/geometry/core/tags.hpp> #include <boost/geometry/geometries/concepts/check.hpp> #include <boost/geometry/geometries/ring.hpp> #include <boost/geometry/io/wkt/detail/prefix.hpp> + namespace boost { namespace geometry { +// Silence warning C4512: 'boost::geometry::wkt_manipulator<Geometry>' : assignment operator could not be generated +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4512) +#endif + #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace wkt { @@ -109,31 +122,49 @@ struct wkt_range { template <typename Char, typename Traits> static inline void apply(std::basic_ostream<Char, Traits>& os, - Range const& range) + Range const& range, bool force_closed) { typedef typename boost::range_iterator<Range const>::type iterator_type; + typedef stream_coordinate + < + point_type, 0, dimension<point_type>::type::value + > stream_type; + bool first = true; os << PrefixPolicy::apply(); // TODO: check EMPTY here - for (iterator_type it = boost::begin(range); - it != boost::end(range); - ++it) + iterator_type begin = boost::begin(range); + iterator_type end = boost::end(range); + for (iterator_type it = begin; it != end; ++it) { os << (first ? "" : ","); - stream_coordinate - < - point_type, 0, dimension<point_type>::type::value - >::apply(os, *it); + stream_type::apply(os, *it); first = false; } + // optionally, close range to ring by repeating the first point + if (force_closed + && boost::size(range) > 1 + && geometry::disjoint(*begin, *(end - 1))) + { + os << ","; + stream_type::apply(os, *begin); + } + os << SuffixPolicy::apply(); } + template <typename Char, typename Traits> + static inline void apply(std::basic_ostream<Char, Traits>& os, + Range const& range) + { + apply(os, range, false); + } + private: typedef typename boost::range_value<Range>::type point_type; }; @@ -160,23 +191,52 @@ struct wkt_poly Polygon const& poly) { typedef typename ring_type<Polygon const>::type ring; + bool const force_closed = true; os << PrefixPolicy::apply(); // TODO: check EMPTY here os << "("; - wkt_sequence<ring>::apply(os, exterior_ring(poly)); + wkt_sequence<ring>::apply(os, exterior_ring(poly), force_closed); - typename interior_return_type<Polygon const>::type rings - = interior_rings(poly); - for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it) + typename interior_return_type<Polygon const>::type + rings = interior_rings(poly); + for (typename detail::interior_iterator<Polygon const>::type + it = boost::begin(rings); it != boost::end(rings); ++it) { os << ","; - wkt_sequence<ring>::apply(os, *it); + wkt_sequence<ring>::apply(os, *it, force_closed); } os << ")"; } }; +template <typename Multi, typename StreamPolicy, typename PrefixPolicy> +struct wkt_multi +{ + template <typename Char, typename Traits> + static inline void apply(std::basic_ostream<Char, Traits>& os, + Multi const& geometry) + { + os << PrefixPolicy::apply(); + // TODO: check EMPTY here + os << "("; + + for (typename boost::range_iterator<Multi const>::type + it = boost::begin(geometry); + it != boost::end(geometry); + ++it) + { + if (it != boost::begin(geometry)) + { + os << ","; + } + StreamPolicy::apply(os, *it); + } + + os << ")"; + } +}; + template <typename Box> struct wkt_box { @@ -240,18 +300,12 @@ struct wkt_segment namespace dispatch { -template <typename Tag, typename Geometry> -struct wkt -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE - , (types<Geometry>) - ); -}; +template <typename Geometry, typename Tag = typename tag<Geometry>::type> +struct wkt: not_implemented<Tag> +{}; template <typename Point> -struct wkt<point_tag, Point> +struct wkt<Point, point_tag> : detail::wkt::wkt_point < Point, @@ -260,7 +314,7 @@ struct wkt<point_tag, Point> {}; template <typename Linestring> -struct wkt<linestring_tag, Linestring> +struct wkt<Linestring, linestring_tag> : detail::wkt::wkt_range < Linestring, @@ -275,12 +329,12 @@ struct wkt<linestring_tag, Linestring> It is therefore streamed as a polygon */ template <typename Box> -struct wkt<box_tag, Box> +struct wkt<Box, box_tag> : detail::wkt::wkt_box<Box> {}; template <typename Segment> -struct wkt<segment_tag, Segment> +struct wkt<Segment, segment_tag> : detail::wkt::wkt_segment<Segment> {}; @@ -291,7 +345,7 @@ A ring is equivalent to a polygon without inner rings It is therefore streamed as a polygon */ template <typename Ring> -struct wkt<ring_tag, Ring> +struct wkt<Ring, ring_tag> : detail::wkt::wkt_range < Ring, @@ -304,7 +358,7 @@ struct wkt<ring_tag, Ring> \brief Specialization to stream polygon as WKT */ template <typename Polygon> -struct wkt<polygon_tag, Polygon> +struct wkt<Polygon, polygon_tag> : detail::wkt::wkt_poly < Polygon, @@ -312,6 +366,88 @@ struct wkt<polygon_tag, Polygon> > {}; +template <typename Multi> +struct wkt<Multi, multi_point_tag> + : detail::wkt::wkt_multi + < + Multi, + detail::wkt::wkt_point + < + typename boost::range_value<Multi>::type, + detail::wkt::prefix_null + >, + detail::wkt::prefix_multipoint + > +{}; + +template <typename Multi> +struct wkt<Multi, multi_linestring_tag> + : detail::wkt::wkt_multi + < + Multi, + detail::wkt::wkt_sequence + < + typename boost::range_value<Multi>::type + >, + detail::wkt::prefix_multilinestring + > +{}; + +template <typename Multi> +struct wkt<Multi, multi_polygon_tag> + : detail::wkt::wkt_multi + < + Multi, + detail::wkt::wkt_poly + < + typename boost::range_value<Multi>::type, + detail::wkt::prefix_null + >, + detail::wkt::prefix_multipolygon + > +{}; + + +template <typename Geometry> +struct devarianted_wkt +{ + template <typename OutputStream> + static inline void apply(OutputStream& os, Geometry const& geometry) + { + wkt<Geometry>::apply(os, geometry); + } +}; + +template <BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct devarianted_wkt<variant<BOOST_VARIANT_ENUM_PARAMS(T)> > +{ + template <typename OutputStream> + struct visitor: static_visitor<void> + { + OutputStream& m_os; + + visitor(OutputStream& os) + : m_os(os) + {} + + template <typename Geometry> + inline void operator()(Geometry const& geometry) const + { + devarianted_wkt<Geometry>::apply(m_os, geometry); + } + }; + + template <typename OutputStream> + static inline void apply( + OutputStream& os, + variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry + ) + { + apply_visitor(visitor<OutputStream>(os), geometry); + } +}; + + } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH @@ -340,11 +476,7 @@ public: std::basic_ostream<Char, Traits>& os, wkt_manipulator const& m) { - dispatch::wkt - < - typename tag<Geometry>::type, - Geometry - >::apply(os, m.m_geometry); + dispatch::devarianted_wkt<Geometry>::apply(os, m.m_geometry); os.flush(); return os; } @@ -355,13 +487,10 @@ private: /*! \brief Main WKT-streaming function +\tparam Geometry \tparam_geometry +\param geometry \param_geometry \ingroup wkt -\par Example: -Small example showing how to use the wkt helper function -\dontinclude doxygen_1.cpp -\skip example_as_wkt_vector -\line { -\until } +\qbk{[include reference/io/wkt.qbk]} */ template <typename Geometry> inline wkt_manipulator<Geometry> wkt(Geometry const& geometry) @@ -371,6 +500,10 @@ inline wkt_manipulator<Geometry> wkt(Geometry const& geometry) return wkt_manipulator<Geometry>(geometry); } +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + }} // namespace boost::geometry #endif // BOOST_GEOMETRY_IO_WKT_WRITE_HPP |