1
// Generic Geometry Library
3
// Copyright Barend Gehrels 2008-2009, Geodan, Amsterdam, the Netherlands.
4
// Use, modification and distribution is subject to the Boost Software License,
5
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6
// http://www.boost.org/LICENSE_1_0.txt)
8
#ifndef GGL_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_HPP
9
#define GGL_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_HPP
14
#include <boost/concept/assert.hpp>
15
#include <boost/range/functions.hpp>
16
#include <boost/range/metafunctions.hpp>
18
#include <ggl/algorithms/convert.hpp>
19
#include <ggl/core/concepts/point_concept.hpp>
20
#include <ggl/core/exterior_ring.hpp>
21
#include <ggl/core/interior_rings.hpp>
22
#include <ggl/core/ring_type.hpp>
23
#include <ggl/geometries/linear_ring.hpp>
25
#include <ggl/extensions/gis/io/wkt/detail/wkt.hpp>
28
\defgroup wkt wkt: parse and stream WKT (Well-Known Text)
29
The wkt classes stream the specified geometry as \ref OGC Well Known Text (\ref WKT). It is defined for OGC geometries.
30
It is therefore not defined for all geometries (e.g. not for circle)
31
\note The implementation is independant from point type, point_xy and point_ll are supported,
32
as well as points with more than two coordinates.
38
#ifndef DOXYGEN_NO_DETAIL
39
namespace detail { namespace wkt {
41
template <typename P, int I, int Count>
42
struct stream_coordinate
44
template <typename Char, typename Traits>
45
static inline void apply(std::basic_ostream<Char, Traits>& os, P const& p)
47
os << (I > 0 ? " " : "") << get<I>(p);
48
stream_coordinate<P, I + 1, Count>::apply(os, p);
52
template <typename P, int Count>
53
struct stream_coordinate<P, Count, Count>
55
template <typename Char, typename Traits>
56
static inline void apply(std::basic_ostream<Char, Traits>&, P const&)
60
struct prefix_linestring_par
62
static inline const char* apply() { return "LINESTRING("; }
65
struct prefix_ring_par_par
67
// Note, double parentheses are intentional, indicating WKT ring begin/end
68
static inline const char* apply() { return "POLYGON(("; }
71
struct opening_parenthesis
73
static inline const char* apply() { return "("; }
76
struct closing_parenthesis
78
static inline const char* apply() { return ")"; }
81
struct double_closing_parenthesis
83
static inline const char* apply() { return "))"; }
90
\brief Stream points as \ref WKT
92
template <typename Point, typename Policy>
95
template <typename Char, typename Traits>
96
static inline void apply(std::basic_ostream<Char, Traits>& os, Point const& p)
98
os << Policy::apply() << "(";
99
stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p);
104
BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point>) );
108
\brief Stream ranges as WKT
109
\note policy is used to stream prefix/postfix, enabling derived classes to override this
111
template <typename Range, typename PrefixPolicy, typename SuffixPolicy>
114
template <typename Char, typename Traits>
115
static inline void apply(std::basic_ostream<Char, Traits>& os,
118
typedef typename boost::range_const_iterator<Range>::type iterator_type;
122
os << PrefixPolicy::apply();
124
// TODO: check EMPTY here
126
for (iterator_type it = boost::begin(range);
127
it != boost::end(range);
130
os << (first ? "" : ",");
131
stream_coordinate<point, 0, dimension<point>::type::value>::apply(os, *it);
135
os << SuffixPolicy::apply();
139
typedef typename boost::range_value<Range>::type point;
140
BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point>) );
144
\brief Stream sequence of points as WKT-part, e.g. (1 2),(3 4)
145
\note Used in polygon, all multi-geometries
150
template <typename Range>
161
template <typename Polygon, typename PrefixPolicy>
164
template <typename Char, typename Traits>
165
static inline void apply(std::basic_ostream<Char, Traits>& os,
168
typedef typename ring_type<Polygon>::type ring;
169
typedef typename boost::range_const_iterator<
170
typename interior_type<Polygon>::type>::type iterator;
172
os << PrefixPolicy::apply();
173
// TODO: check EMPTY here
175
wkt_sequence<ring>::apply(os, exterior_ring(poly));
176
for (iterator it = boost::begin(interior_rings(poly));
177
it != boost::end(interior_rings(poly));
181
wkt_sequence<ring>::apply(os, *it);
187
BOOST_CONCEPT_ASSERT( (concept::ConstPoint<typename point_type<Polygon>::type>) );
191
template <typename Box>
194
typedef typename point_type<Box>::type point_type;
196
template <typename Char, typename Traits>
197
static inline void apply(std::basic_ostream<Char, Traits>& os,
200
// Convert to linear ring, then stream
201
typedef linear_ring<point_type> ring_type;
203
ggl::convert(box, ring);
205
wkt_sequence<ring_type>::apply(os, ring);
210
BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
214
// Only streaming of boxes with two dimensions is support, otherwise it is a polyhedron!
215
//assert_dimension<B, 2>();
219
}} // namespace detail::wkt
220
#endif // DOXYGEN_NO_DETAIL
223
#ifndef DOXYGEN_NO_DISPATCH
226
template <typename Tag, typename Geometry>
230
template <typename Point>
231
struct wkt<point_tag, Point>
232
: detail::wkt::wkt_point
235
detail::wkt::prefix_point
240
template <typename Linestring>
241
struct wkt<linestring_tag, Linestring>
242
: detail::wkt::wkt_range
245
detail::wkt::prefix_linestring_par,
246
detail::wkt::closing_parenthesis
252
\brief Specialization to stream a box as WKT
253
\details A "box" does not exist in WKT.
254
It is therefore streamed as a polygon
256
template <typename Box>
257
struct wkt<box_tag, Box>
258
: detail::wkt::wkt_box<Box>
263
\brief Specialization to stream a ring as WKT
264
\details A "linear_ring" does not exist in WKT.
265
A linear ring is equivalent to a polygon without inner rings
266
It is therefore streamed as a polygon
268
template <typename Ring>
269
struct wkt<ring_tag, Ring>
270
: detail::wkt::wkt_range
273
detail::wkt::prefix_ring_par_par,
274
detail::wkt::double_closing_parenthesis
280
\brief Specialization to stream polygon as WKT
282
template <typename Polygon>
283
struct wkt<polygon_tag, Polygon>
284
: detail::wkt::wkt_poly
287
detail::wkt::prefix_polygon
292
} // namespace dispatch
293
#endif // DOXYGEN_NO_DISPATCH
297
\brief Generic geometry template manipulator class, takes corresponding output class from traits class
299
\details Stream manipulator, streams geometry classes as \ref WKT streams
301
Small example showing how to use the wkt class
302
\dontinclude doxygen_examples.cpp
303
\skip example_as_wkt_point
307
template <typename Geometry>
308
class wkt_manipulator
312
inline wkt_manipulator(Geometry const& g)
316
template <typename Char, typename Traits>
317
inline friend std::basic_ostream<Char, Traits>& operator<<(
318
std::basic_ostream<Char, Traits>& os,
319
wkt_manipulator const& m)
323
typename tag<Geometry>::type,
325
>::apply(os, m.m_geometry);
331
Geometry const& m_geometry;
335
\brief Main WKT-streaming function
338
Small example showing how to use the wkt helper function
339
\dontinclude doxygen_examples.cpp
340
\skip example_as_wkt_vector
344
template <typename Geometry>
345
inline wkt_manipulator<Geometry> wkt(Geometry const& geometry)
347
return wkt_manipulator<Geometry>(geometry);
351
// Backward compatibility
352
template <typename Geometry>
353
inline wkt_manipulator<Geometry> make_wkt(Geometry const& geometry)
355
return wkt_manipulator<Geometry>(geometry);
360
#endif // GGL_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_HPP