summaryrefslogtreecommitdiff
path: root/boost/geometry/io/wkt/write.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/io/wkt/write.hpp')
-rw-r--r--boost/geometry/io/wkt/write.hpp215
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