comparison DEPENDENCIES/generic/include/boost/geometry/io/wkt/write.hpp @ 16:2665513ce2d3

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