Chris@16
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@16
|
2
|
Chris@16
|
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@16
|
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
Chris@16
|
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
Chris@101
|
6 // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
Chris@16
|
7
|
Chris@16
|
8 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
Chris@16
|
9 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
Chris@16
|
10
|
Chris@16
|
11 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@16
|
12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
13 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_GEOMETRY_IO_WKT_WRITE_HPP
|
Chris@16
|
16 #define BOOST_GEOMETRY_IO_WKT_WRITE_HPP
|
Chris@16
|
17
|
Chris@16
|
18 #include <ostream>
|
Chris@16
|
19 #include <string>
|
Chris@16
|
20
|
Chris@16
|
21 #include <boost/array.hpp>
|
Chris@16
|
22 #include <boost/range.hpp>
|
Chris@16
|
23
|
Chris@101
|
24 #include <boost/variant/apply_visitor.hpp>
|
Chris@101
|
25 #include <boost/variant/static_visitor.hpp>
|
Chris@101
|
26 #include <boost/variant/variant_fwd.hpp>
|
Chris@101
|
27
|
Chris@101
|
28 #include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
Chris@16
|
29 #include <boost/geometry/algorithms/assign.hpp>
|
Chris@16
|
30 #include <boost/geometry/algorithms/convert.hpp>
|
Chris@101
|
31 #include <boost/geometry/algorithms/disjoint.hpp>
|
Chris@16
|
32 #include <boost/geometry/algorithms/not_implemented.hpp>
|
Chris@16
|
33 #include <boost/geometry/core/exterior_ring.hpp>
|
Chris@16
|
34 #include <boost/geometry/core/interior_rings.hpp>
|
Chris@16
|
35 #include <boost/geometry/core/ring_type.hpp>
|
Chris@101
|
36 #include <boost/geometry/core/tags.hpp>
|
Chris@16
|
37
|
Chris@16
|
38 #include <boost/geometry/geometries/concepts/check.hpp>
|
Chris@16
|
39 #include <boost/geometry/geometries/ring.hpp>
|
Chris@16
|
40
|
Chris@16
|
41 #include <boost/geometry/io/wkt/detail/prefix.hpp>
|
Chris@16
|
42
|
Chris@16
|
43
|
Chris@16
|
44 namespace boost { namespace geometry
|
Chris@16
|
45 {
|
Chris@16
|
46
|
Chris@16
|
47 // Silence warning C4512: 'boost::geometry::wkt_manipulator<Geometry>' : assignment operator could not be generated
|
Chris@16
|
48 #if defined(_MSC_VER)
|
Chris@16
|
49 #pragma warning(push)
|
Chris@16
|
50 #pragma warning(disable : 4512)
|
Chris@16
|
51 #endif
|
Chris@16
|
52
|
Chris@16
|
53 #ifndef DOXYGEN_NO_DETAIL
|
Chris@16
|
54 namespace detail { namespace wkt
|
Chris@16
|
55 {
|
Chris@16
|
56
|
Chris@16
|
57 template <typename P, int I, int Count>
|
Chris@16
|
58 struct stream_coordinate
|
Chris@16
|
59 {
|
Chris@16
|
60 template <typename Char, typename Traits>
|
Chris@16
|
61 static inline void apply(std::basic_ostream<Char, Traits>& os, P const& p)
|
Chris@16
|
62 {
|
Chris@16
|
63 os << (I > 0 ? " " : "") << get<I>(p);
|
Chris@16
|
64 stream_coordinate<P, I + 1, Count>::apply(os, p);
|
Chris@16
|
65 }
|
Chris@16
|
66 };
|
Chris@16
|
67
|
Chris@16
|
68 template <typename P, int Count>
|
Chris@16
|
69 struct stream_coordinate<P, Count, Count>
|
Chris@16
|
70 {
|
Chris@16
|
71 template <typename Char, typename Traits>
|
Chris@16
|
72 static inline void apply(std::basic_ostream<Char, Traits>&, P const&)
|
Chris@16
|
73 {}
|
Chris@16
|
74 };
|
Chris@16
|
75
|
Chris@16
|
76 struct prefix_linestring_par
|
Chris@16
|
77 {
|
Chris@16
|
78 static inline const char* apply() { return "LINESTRING("; }
|
Chris@16
|
79 };
|
Chris@16
|
80
|
Chris@16
|
81 struct prefix_ring_par_par
|
Chris@16
|
82 {
|
Chris@16
|
83 // Note, double parentheses are intentional, indicating WKT ring begin/end
|
Chris@16
|
84 static inline const char* apply() { return "POLYGON(("; }
|
Chris@16
|
85 };
|
Chris@16
|
86
|
Chris@16
|
87 struct opening_parenthesis
|
Chris@16
|
88 {
|
Chris@16
|
89 static inline const char* apply() { return "("; }
|
Chris@16
|
90 };
|
Chris@16
|
91
|
Chris@16
|
92 struct closing_parenthesis
|
Chris@16
|
93 {
|
Chris@16
|
94 static inline const char* apply() { return ")"; }
|
Chris@16
|
95 };
|
Chris@16
|
96
|
Chris@16
|
97 struct double_closing_parenthesis
|
Chris@16
|
98 {
|
Chris@16
|
99 static inline const char* apply() { return "))"; }
|
Chris@16
|
100 };
|
Chris@16
|
101
|
Chris@16
|
102 /*!
|
Chris@16
|
103 \brief Stream points as \ref WKT
|
Chris@16
|
104 */
|
Chris@16
|
105 template <typename Point, typename Policy>
|
Chris@16
|
106 struct wkt_point
|
Chris@16
|
107 {
|
Chris@16
|
108 template <typename Char, typename Traits>
|
Chris@16
|
109 static inline void apply(std::basic_ostream<Char, Traits>& os, Point const& p)
|
Chris@16
|
110 {
|
Chris@16
|
111 os << Policy::apply() << "(";
|
Chris@16
|
112 stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p);
|
Chris@16
|
113 os << ")";
|
Chris@16
|
114 }
|
Chris@16
|
115 };
|
Chris@16
|
116
|
Chris@16
|
117 /*!
|
Chris@16
|
118 \brief Stream ranges as WKT
|
Chris@16
|
119 \note policy is used to stream prefix/postfix, enabling derived classes to override this
|
Chris@16
|
120 */
|
Chris@16
|
121 template <typename Range, typename PrefixPolicy, typename SuffixPolicy>
|
Chris@16
|
122 struct wkt_range
|
Chris@16
|
123 {
|
Chris@16
|
124 template <typename Char, typename Traits>
|
Chris@16
|
125 static inline void apply(std::basic_ostream<Char, Traits>& os,
|
Chris@101
|
126 Range const& range, bool force_closed)
|
Chris@16
|
127 {
|
Chris@16
|
128 typedef typename boost::range_iterator<Range const>::type iterator_type;
|
Chris@16
|
129
|
Chris@101
|
130 typedef stream_coordinate
|
Chris@101
|
131 <
|
Chris@101
|
132 point_type, 0, dimension<point_type>::type::value
|
Chris@101
|
133 > stream_type;
|
Chris@101
|
134
|
Chris@16
|
135 bool first = true;
|
Chris@16
|
136
|
Chris@16
|
137 os << PrefixPolicy::apply();
|
Chris@16
|
138
|
Chris@16
|
139 // TODO: check EMPTY here
|
Chris@16
|
140
|
Chris@101
|
141 iterator_type begin = boost::begin(range);
|
Chris@101
|
142 iterator_type end = boost::end(range);
|
Chris@101
|
143 for (iterator_type it = begin; it != end; ++it)
|
Chris@16
|
144 {
|
Chris@16
|
145 os << (first ? "" : ",");
|
Chris@101
|
146 stream_type::apply(os, *it);
|
Chris@16
|
147 first = false;
|
Chris@16
|
148 }
|
Chris@16
|
149
|
Chris@101
|
150 // optionally, close range to ring by repeating the first point
|
Chris@101
|
151 if (force_closed
|
Chris@101
|
152 && boost::size(range) > 1
|
Chris@101
|
153 && geometry::disjoint(*begin, *(end - 1)))
|
Chris@101
|
154 {
|
Chris@101
|
155 os << ",";
|
Chris@101
|
156 stream_type::apply(os, *begin);
|
Chris@101
|
157 }
|
Chris@101
|
158
|
Chris@16
|
159 os << SuffixPolicy::apply();
|
Chris@16
|
160 }
|
Chris@16
|
161
|
Chris@101
|
162 template <typename Char, typename Traits>
|
Chris@101
|
163 static inline void apply(std::basic_ostream<Char, Traits>& os,
|
Chris@101
|
164 Range const& range)
|
Chris@101
|
165 {
|
Chris@101
|
166 apply(os, range, false);
|
Chris@101
|
167 }
|
Chris@101
|
168
|
Chris@16
|
169 private:
|
Chris@16
|
170 typedef typename boost::range_value<Range>::type point_type;
|
Chris@16
|
171 };
|
Chris@16
|
172
|
Chris@16
|
173 /*!
|
Chris@16
|
174 \brief Stream sequence of points as WKT-part, e.g. (1 2),(3 4)
|
Chris@16
|
175 \note Used in polygon, all multi-geometries
|
Chris@16
|
176 */
|
Chris@16
|
177 template <typename Range>
|
Chris@16
|
178 struct wkt_sequence
|
Chris@16
|
179 : wkt_range
|
Chris@16
|
180 <
|
Chris@16
|
181 Range,
|
Chris@16
|
182 opening_parenthesis,
|
Chris@16
|
183 closing_parenthesis
|
Chris@16
|
184 >
|
Chris@16
|
185 {};
|
Chris@16
|
186
|
Chris@16
|
187 template <typename Polygon, typename PrefixPolicy>
|
Chris@16
|
188 struct wkt_poly
|
Chris@16
|
189 {
|
Chris@16
|
190 template <typename Char, typename Traits>
|
Chris@16
|
191 static inline void apply(std::basic_ostream<Char, Traits>& os,
|
Chris@16
|
192 Polygon const& poly)
|
Chris@16
|
193 {
|
Chris@16
|
194 typedef typename ring_type<Polygon const>::type ring;
|
Chris@101
|
195 bool const force_closed = true;
|
Chris@16
|
196
|
Chris@16
|
197 os << PrefixPolicy::apply();
|
Chris@16
|
198 // TODO: check EMPTY here
|
Chris@16
|
199 os << "(";
|
Chris@101
|
200 wkt_sequence<ring>::apply(os, exterior_ring(poly), force_closed);
|
Chris@16
|
201
|
Chris@101
|
202 typename interior_return_type<Polygon const>::type
|
Chris@101
|
203 rings = interior_rings(poly);
|
Chris@101
|
204 for (typename detail::interior_iterator<Polygon const>::type
|
Chris@101
|
205 it = boost::begin(rings); it != boost::end(rings); ++it)
|
Chris@16
|
206 {
|
Chris@16
|
207 os << ",";
|
Chris@101
|
208 wkt_sequence<ring>::apply(os, *it, force_closed);
|
Chris@16
|
209 }
|
Chris@16
|
210 os << ")";
|
Chris@16
|
211 }
|
Chris@16
|
212 };
|
Chris@16
|
213
|
Chris@101
|
214 template <typename Multi, typename StreamPolicy, typename PrefixPolicy>
|
Chris@101
|
215 struct wkt_multi
|
Chris@101
|
216 {
|
Chris@101
|
217 template <typename Char, typename Traits>
|
Chris@101
|
218 static inline void apply(std::basic_ostream<Char, Traits>& os,
|
Chris@101
|
219 Multi const& geometry)
|
Chris@101
|
220 {
|
Chris@101
|
221 os << PrefixPolicy::apply();
|
Chris@101
|
222 // TODO: check EMPTY here
|
Chris@101
|
223 os << "(";
|
Chris@101
|
224
|
Chris@101
|
225 for (typename boost::range_iterator<Multi const>::type
|
Chris@101
|
226 it = boost::begin(geometry);
|
Chris@101
|
227 it != boost::end(geometry);
|
Chris@101
|
228 ++it)
|
Chris@101
|
229 {
|
Chris@101
|
230 if (it != boost::begin(geometry))
|
Chris@101
|
231 {
|
Chris@101
|
232 os << ",";
|
Chris@101
|
233 }
|
Chris@101
|
234 StreamPolicy::apply(os, *it);
|
Chris@101
|
235 }
|
Chris@101
|
236
|
Chris@101
|
237 os << ")";
|
Chris@101
|
238 }
|
Chris@101
|
239 };
|
Chris@101
|
240
|
Chris@16
|
241 template <typename Box>
|
Chris@16
|
242 struct wkt_box
|
Chris@16
|
243 {
|
Chris@16
|
244 typedef typename point_type<Box>::type point_type;
|
Chris@16
|
245
|
Chris@16
|
246 template <typename Char, typename Traits>
|
Chris@16
|
247 static inline void apply(std::basic_ostream<Char, Traits>& os,
|
Chris@16
|
248 Box const& box)
|
Chris@16
|
249 {
|
Chris@16
|
250 // Convert to ring, then stream
|
Chris@16
|
251 typedef model::ring<point_type> ring_type;
|
Chris@16
|
252 ring_type ring;
|
Chris@16
|
253 geometry::convert(box, ring);
|
Chris@16
|
254 os << "POLYGON(";
|
Chris@16
|
255 wkt_sequence<ring_type>::apply(os, ring);
|
Chris@16
|
256 os << ")";
|
Chris@16
|
257 }
|
Chris@16
|
258
|
Chris@16
|
259 private:
|
Chris@16
|
260
|
Chris@16
|
261 inline wkt_box()
|
Chris@16
|
262 {
|
Chris@16
|
263 // Only streaming of boxes with two dimensions is support, otherwise it is a polyhedron!
|
Chris@16
|
264 //assert_dimension<B, 2>();
|
Chris@16
|
265 }
|
Chris@16
|
266 };
|
Chris@16
|
267
|
Chris@16
|
268
|
Chris@16
|
269 template <typename Segment>
|
Chris@16
|
270 struct wkt_segment
|
Chris@16
|
271 {
|
Chris@16
|
272 typedef typename point_type<Segment>::type point_type;
|
Chris@16
|
273
|
Chris@16
|
274 template <typename Char, typename Traits>
|
Chris@16
|
275 static inline void apply(std::basic_ostream<Char, Traits>& os,
|
Chris@16
|
276 Segment const& segment)
|
Chris@16
|
277 {
|
Chris@16
|
278 // Convert to two points, then stream
|
Chris@16
|
279 typedef boost::array<point_type, 2> sequence;
|
Chris@16
|
280
|
Chris@16
|
281 sequence points;
|
Chris@16
|
282 geometry::detail::assign_point_from_index<0>(segment, points[0]);
|
Chris@16
|
283 geometry::detail::assign_point_from_index<1>(segment, points[1]);
|
Chris@16
|
284
|
Chris@16
|
285 // In Boost.Geometry a segment is represented
|
Chris@16
|
286 // in WKT-format like (for 2D): LINESTRING(x y,x y)
|
Chris@16
|
287 os << "LINESTRING";
|
Chris@16
|
288 wkt_sequence<sequence>::apply(os, points);
|
Chris@16
|
289 }
|
Chris@16
|
290
|
Chris@16
|
291 private:
|
Chris@16
|
292
|
Chris@16
|
293 inline wkt_segment()
|
Chris@16
|
294 {}
|
Chris@16
|
295 };
|
Chris@16
|
296
|
Chris@16
|
297 }} // namespace detail::wkt
|
Chris@16
|
298 #endif // DOXYGEN_NO_DETAIL
|
Chris@16
|
299
|
Chris@16
|
300 #ifndef DOXYGEN_NO_DISPATCH
|
Chris@16
|
301 namespace dispatch
|
Chris@16
|
302 {
|
Chris@16
|
303
|
Chris@16
|
304 template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
Chris@16
|
305 struct wkt: not_implemented<Tag>
|
Chris@16
|
306 {};
|
Chris@16
|
307
|
Chris@16
|
308 template <typename Point>
|
Chris@16
|
309 struct wkt<Point, point_tag>
|
Chris@16
|
310 : detail::wkt::wkt_point
|
Chris@16
|
311 <
|
Chris@16
|
312 Point,
|
Chris@16
|
313 detail::wkt::prefix_point
|
Chris@16
|
314 >
|
Chris@16
|
315 {};
|
Chris@16
|
316
|
Chris@16
|
317 template <typename Linestring>
|
Chris@16
|
318 struct wkt<Linestring, linestring_tag>
|
Chris@16
|
319 : detail::wkt::wkt_range
|
Chris@16
|
320 <
|
Chris@16
|
321 Linestring,
|
Chris@16
|
322 detail::wkt::prefix_linestring_par,
|
Chris@16
|
323 detail::wkt::closing_parenthesis
|
Chris@16
|
324 >
|
Chris@16
|
325 {};
|
Chris@16
|
326
|
Chris@16
|
327 /*!
|
Chris@16
|
328 \brief Specialization to stream a box as WKT
|
Chris@16
|
329 \details A "box" does not exist in WKT.
|
Chris@16
|
330 It is therefore streamed as a polygon
|
Chris@16
|
331 */
|
Chris@16
|
332 template <typename Box>
|
Chris@16
|
333 struct wkt<Box, box_tag>
|
Chris@16
|
334 : detail::wkt::wkt_box<Box>
|
Chris@16
|
335 {};
|
Chris@16
|
336
|
Chris@16
|
337 template <typename Segment>
|
Chris@16
|
338 struct wkt<Segment, segment_tag>
|
Chris@16
|
339 : detail::wkt::wkt_segment<Segment>
|
Chris@16
|
340 {};
|
Chris@16
|
341
|
Chris@16
|
342 /*!
|
Chris@16
|
343 \brief Specialization to stream a ring as WKT
|
Chris@16
|
344 \details A ring or "linear_ring" does not exist in WKT.
|
Chris@16
|
345 A ring is equivalent to a polygon without inner rings
|
Chris@16
|
346 It is therefore streamed as a polygon
|
Chris@16
|
347 */
|
Chris@16
|
348 template <typename Ring>
|
Chris@16
|
349 struct wkt<Ring, ring_tag>
|
Chris@16
|
350 : detail::wkt::wkt_range
|
Chris@16
|
351 <
|
Chris@16
|
352 Ring,
|
Chris@16
|
353 detail::wkt::prefix_ring_par_par,
|
Chris@16
|
354 detail::wkt::double_closing_parenthesis
|
Chris@16
|
355 >
|
Chris@16
|
356 {};
|
Chris@16
|
357
|
Chris@16
|
358 /*!
|
Chris@16
|
359 \brief Specialization to stream polygon as WKT
|
Chris@16
|
360 */
|
Chris@16
|
361 template <typename Polygon>
|
Chris@16
|
362 struct wkt<Polygon, polygon_tag>
|
Chris@16
|
363 : detail::wkt::wkt_poly
|
Chris@16
|
364 <
|
Chris@16
|
365 Polygon,
|
Chris@16
|
366 detail::wkt::prefix_polygon
|
Chris@16
|
367 >
|
Chris@16
|
368 {};
|
Chris@16
|
369
|
Chris@101
|
370 template <typename Multi>
|
Chris@101
|
371 struct wkt<Multi, multi_point_tag>
|
Chris@101
|
372 : detail::wkt::wkt_multi
|
Chris@101
|
373 <
|
Chris@101
|
374 Multi,
|
Chris@101
|
375 detail::wkt::wkt_point
|
Chris@101
|
376 <
|
Chris@101
|
377 typename boost::range_value<Multi>::type,
|
Chris@101
|
378 detail::wkt::prefix_null
|
Chris@101
|
379 >,
|
Chris@101
|
380 detail::wkt::prefix_multipoint
|
Chris@101
|
381 >
|
Chris@101
|
382 {};
|
Chris@101
|
383
|
Chris@101
|
384 template <typename Multi>
|
Chris@101
|
385 struct wkt<Multi, multi_linestring_tag>
|
Chris@101
|
386 : detail::wkt::wkt_multi
|
Chris@101
|
387 <
|
Chris@101
|
388 Multi,
|
Chris@101
|
389 detail::wkt::wkt_sequence
|
Chris@101
|
390 <
|
Chris@101
|
391 typename boost::range_value<Multi>::type
|
Chris@101
|
392 >,
|
Chris@101
|
393 detail::wkt::prefix_multilinestring
|
Chris@101
|
394 >
|
Chris@101
|
395 {};
|
Chris@101
|
396
|
Chris@101
|
397 template <typename Multi>
|
Chris@101
|
398 struct wkt<Multi, multi_polygon_tag>
|
Chris@101
|
399 : detail::wkt::wkt_multi
|
Chris@101
|
400 <
|
Chris@101
|
401 Multi,
|
Chris@101
|
402 detail::wkt::wkt_poly
|
Chris@101
|
403 <
|
Chris@101
|
404 typename boost::range_value<Multi>::type,
|
Chris@101
|
405 detail::wkt::prefix_null
|
Chris@101
|
406 >,
|
Chris@101
|
407 detail::wkt::prefix_multipolygon
|
Chris@101
|
408 >
|
Chris@101
|
409 {};
|
Chris@101
|
410
|
Chris@16
|
411
|
Chris@16
|
412 template <typename Geometry>
|
Chris@16
|
413 struct devarianted_wkt
|
Chris@16
|
414 {
|
Chris@16
|
415 template <typename OutputStream>
|
Chris@16
|
416 static inline void apply(OutputStream& os, Geometry const& geometry)
|
Chris@16
|
417 {
|
Chris@16
|
418 wkt<Geometry>::apply(os, geometry);
|
Chris@16
|
419 }
|
Chris@16
|
420 };
|
Chris@16
|
421
|
Chris@16
|
422 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
Chris@16
|
423 struct devarianted_wkt<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
Chris@16
|
424 {
|
Chris@16
|
425 template <typename OutputStream>
|
Chris@16
|
426 struct visitor: static_visitor<void>
|
Chris@16
|
427 {
|
Chris@16
|
428 OutputStream& m_os;
|
Chris@16
|
429
|
Chris@16
|
430 visitor(OutputStream& os)
|
Chris@16
|
431 : m_os(os)
|
Chris@16
|
432 {}
|
Chris@16
|
433
|
Chris@16
|
434 template <typename Geometry>
|
Chris@16
|
435 inline void operator()(Geometry const& geometry) const
|
Chris@16
|
436 {
|
Chris@16
|
437 devarianted_wkt<Geometry>::apply(m_os, geometry);
|
Chris@16
|
438 }
|
Chris@16
|
439 };
|
Chris@16
|
440
|
Chris@16
|
441 template <typename OutputStream>
|
Chris@16
|
442 static inline void apply(
|
Chris@16
|
443 OutputStream& os,
|
Chris@16
|
444 variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry
|
Chris@16
|
445 )
|
Chris@16
|
446 {
|
Chris@16
|
447 apply_visitor(visitor<OutputStream>(os), geometry);
|
Chris@16
|
448 }
|
Chris@16
|
449 };
|
Chris@16
|
450
|
Chris@16
|
451
|
Chris@16
|
452 } // namespace dispatch
|
Chris@16
|
453 #endif // DOXYGEN_NO_DISPATCH
|
Chris@16
|
454
|
Chris@16
|
455 /*!
|
Chris@16
|
456 \brief Generic geometry template manipulator class, takes corresponding output class from traits class
|
Chris@16
|
457 \ingroup wkt
|
Chris@16
|
458 \details Stream manipulator, streams geometry classes as \ref WKT streams
|
Chris@16
|
459 \par Example:
|
Chris@16
|
460 Small example showing how to use the wkt class
|
Chris@16
|
461 \dontinclude doxygen_1.cpp
|
Chris@16
|
462 \skip example_as_wkt_point
|
Chris@16
|
463 \line {
|
Chris@16
|
464 \until }
|
Chris@16
|
465 */
|
Chris@16
|
466 template <typename Geometry>
|
Chris@16
|
467 class wkt_manipulator
|
Chris@16
|
468 {
|
Chris@16
|
469 public:
|
Chris@16
|
470
|
Chris@16
|
471 inline wkt_manipulator(Geometry const& g)
|
Chris@16
|
472 : m_geometry(g)
|
Chris@16
|
473 {}
|
Chris@16
|
474
|
Chris@16
|
475 template <typename Char, typename Traits>
|
Chris@16
|
476 inline friend std::basic_ostream<Char, Traits>& operator<<(
|
Chris@16
|
477 std::basic_ostream<Char, Traits>& os,
|
Chris@16
|
478 wkt_manipulator const& m)
|
Chris@16
|
479 {
|
Chris@16
|
480 dispatch::devarianted_wkt<Geometry>::apply(os, m.m_geometry);
|
Chris@16
|
481 os.flush();
|
Chris@16
|
482 return os;
|
Chris@16
|
483 }
|
Chris@16
|
484
|
Chris@16
|
485 private:
|
Chris@16
|
486 Geometry const& m_geometry;
|
Chris@16
|
487 };
|
Chris@16
|
488
|
Chris@16
|
489 /*!
|
Chris@16
|
490 \brief Main WKT-streaming function
|
Chris@101
|
491 \tparam Geometry \tparam_geometry
|
Chris@101
|
492 \param geometry \param_geometry
|
Chris@16
|
493 \ingroup wkt
|
Chris@101
|
494 \qbk{[include reference/io/wkt.qbk]}
|
Chris@16
|
495 */
|
Chris@16
|
496 template <typename Geometry>
|
Chris@16
|
497 inline wkt_manipulator<Geometry> wkt(Geometry const& geometry)
|
Chris@16
|
498 {
|
Chris@16
|
499 concept::check<Geometry const>();
|
Chris@16
|
500
|
Chris@16
|
501 return wkt_manipulator<Geometry>(geometry);
|
Chris@16
|
502 }
|
Chris@16
|
503
|
Chris@16
|
504 #if defined(_MSC_VER)
|
Chris@16
|
505 #pragma warning(pop)
|
Chris@16
|
506 #endif
|
Chris@16
|
507
|
Chris@16
|
508 }} // namespace boost::geometry
|
Chris@16
|
509
|
Chris@16
|
510 #endif // BOOST_GEOMETRY_IO_WKT_WRITE_HPP
|