Mercurial > hg > vamp-build-and-test
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 |