]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/include/boost/geometry/io/dsv/write.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / geometry / include / boost / geometry / io / dsv / write.hpp
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 // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
7
8 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
9 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
10
11 // Use, modification and distribution is subject to the Boost Software License,
12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13 // http://www.boost.org/LICENSE_1_0.txt)
14
15 #ifndef BOOST_GEOMETRY_IO_DSV_WRITE_HPP
16 #define BOOST_GEOMETRY_IO_DSV_WRITE_HPP
17
18 #include <cstddef>
19 #include <ostream>
20 #include <string>
21
22 #include <boost/concept_check.hpp>
23 #include <boost/range.hpp>
24
25 #include <boost/geometry/algorithms/detail/interior_iterator.hpp>
26
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 #include <boost/geometry/core/tag_cast.hpp>
31 #include <boost/geometry/core/tags.hpp>
32
33 #include <boost/geometry/geometries/concepts/check.hpp>
34
35 namespace boost { namespace geometry
36 {
37
38 #ifndef DOXYGEN_NO_DETAIL
39 namespace detail { namespace dsv
40 {
41
42 struct dsv_settings
43 {
44 std::string coordinate_separator;
45 std::string point_open;
46 std::string point_close;
47 std::string point_separator;
48 std::string list_open;
49 std::string list_close;
50 std::string list_separator;
51
52 dsv_settings(std::string const& sep
53 , std::string const& open
54 , std::string const& close
55 , std::string const& psep
56 , std::string const& lopen
57 , std::string const& lclose
58 , std::string const& lsep
59 )
60 : coordinate_separator(sep)
61 , point_open(open)
62 , point_close(close)
63 , point_separator(psep)
64 , list_open(lopen)
65 , list_close(lclose)
66 , list_separator(lsep)
67 {}
68 };
69
70 /*!
71 \brief Stream coordinate of a point as \ref DSV
72 */
73 template <typename Point, std::size_t Dimension, std::size_t Count>
74 struct stream_coordinate
75 {
76 template <typename Char, typename Traits>
77 static inline void apply(std::basic_ostream<Char, Traits>& os,
78 Point const& point,
79 dsv_settings const& settings)
80 {
81 os << (Dimension > 0 ? settings.coordinate_separator : "")
82 << get<Dimension>(point);
83
84 stream_coordinate
85 <
86 Point, Dimension + 1, Count
87 >::apply(os, point, settings);
88 }
89 };
90
91 template <typename Point, std::size_t Count>
92 struct stream_coordinate<Point, Count, Count>
93 {
94 template <typename Char, typename Traits>
95 static inline void apply(std::basic_ostream<Char, Traits>&,
96 Point const&,
97 dsv_settings const& )
98 {
99 }
100 };
101
102 /*!
103 \brief Stream indexed coordinate of a box/segment as \ref DSV
104 */
105 template
106 <
107 typename Geometry,
108 std::size_t Index,
109 std::size_t Dimension,
110 std::size_t Count
111 >
112 struct stream_indexed
113 {
114 template <typename Char, typename Traits>
115 static inline void apply(std::basic_ostream<Char, Traits>& os,
116 Geometry const& geometry,
117 dsv_settings const& settings)
118 {
119 os << (Dimension > 0 ? settings.coordinate_separator : "")
120 << get<Index, Dimension>(geometry);
121 stream_indexed
122 <
123 Geometry, Index, Dimension + 1, Count
124 >::apply(os, geometry, settings);
125 }
126 };
127
128 template <typename Geometry, std::size_t Index, std::size_t Count>
129 struct stream_indexed<Geometry, Index, Count, Count>
130 {
131 template <typename Char, typename Traits>
132 static inline void apply(std::basic_ostream<Char, Traits>&, Geometry const&,
133 dsv_settings const& )
134 {
135 }
136 };
137
138 /*!
139 \brief Stream points as \ref DSV
140 */
141 template <typename Point>
142 struct dsv_point
143 {
144 template <typename Char, typename Traits>
145 static inline void apply(std::basic_ostream<Char, Traits>& os,
146 Point const& p,
147 dsv_settings const& settings)
148 {
149 os << settings.point_open;
150 stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p, settings);
151 os << settings.point_close;
152 }
153 };
154
155 /*!
156 \brief Stream ranges as DSV
157 \note policy is used to stream prefix/postfix, enabling derived classes to override this
158 */
159 template <typename Range>
160 struct dsv_range
161 {
162 template <typename Char, typename Traits>
163 static inline void apply(std::basic_ostream<Char, Traits>& os,
164 Range const& range,
165 dsv_settings const& settings)
166 {
167 typedef typename boost::range_iterator<Range const>::type iterator_type;
168
169 bool first = true;
170
171 os << settings.list_open;
172
173 for (iterator_type it = boost::begin(range);
174 it != boost::end(range);
175 ++it)
176 {
177 os << (first ? "" : settings.point_separator)
178 << settings.point_open;
179
180 stream_coordinate
181 <
182 point_type, 0, dimension<point_type>::type::value
183 >::apply(os, *it, settings);
184 os << settings.point_close;
185
186 first = false;
187 }
188
189 os << settings.list_close;
190 }
191
192 private:
193 typedef typename boost::range_value<Range>::type point_type;
194 };
195
196 /*!
197 \brief Stream sequence of points as DSV-part, e.g. (1 2),(3 4)
198 \note Used in polygon, all multi-geometries
199 */
200
201 template <typename Polygon>
202 struct dsv_poly
203 {
204 template <typename Char, typename Traits>
205 static inline void apply(std::basic_ostream<Char, Traits>& os,
206 Polygon const& poly,
207 dsv_settings const& settings)
208 {
209 typedef typename ring_type<Polygon>::type ring;
210
211 os << settings.list_open;
212
213 dsv_range<ring>::apply(os, exterior_ring(poly), settings);
214
215 typename interior_return_type<Polygon const>::type
216 rings = interior_rings(poly);
217 for (typename detail::interior_iterator<Polygon const>::type
218 it = boost::begin(rings); it != boost::end(rings); ++it)
219 {
220 os << settings.list_separator;
221 dsv_range<ring>::apply(os, *it, settings);
222 }
223 os << settings.list_close;
224 }
225 };
226
227 template <typename Geometry, std::size_t Index>
228 struct dsv_per_index
229 {
230 typedef typename point_type<Geometry>::type point_type;
231
232 template <typename Char, typename Traits>
233 static inline void apply(std::basic_ostream<Char, Traits>& os,
234 Geometry const& geometry,
235 dsv_settings const& settings)
236 {
237 os << settings.point_open;
238 stream_indexed
239 <
240 Geometry, Index, 0, dimension<Geometry>::type::value
241 >::apply(os, geometry, settings);
242 os << settings.point_close;
243 }
244 };
245
246 template <typename Geometry>
247 struct dsv_indexed
248 {
249 typedef typename point_type<Geometry>::type point_type;
250
251 template <typename Char, typename Traits>
252 static inline void apply(std::basic_ostream<Char, Traits>& os,
253 Geometry const& geometry,
254 dsv_settings const& settings)
255 {
256 os << settings.list_open;
257 dsv_per_index<Geometry, 0>::apply(os, geometry, settings);
258 os << settings.point_separator;
259 dsv_per_index<Geometry, 1>::apply(os, geometry, settings);
260 os << settings.list_close;
261 }
262 };
263
264 }} // namespace detail::dsv
265 #endif // DOXYGEN_NO_DETAIL
266
267 #ifndef DOXYGEN_NO_DISPATCH
268 namespace dispatch
269 {
270
271 template <typename Tag, typename Geometry>
272 struct dsv {};
273
274 template <typename Point>
275 struct dsv<point_tag, Point>
276 : detail::dsv::dsv_point<Point>
277 {};
278
279 template <typename Linestring>
280 struct dsv<linestring_tag, Linestring>
281 : detail::dsv::dsv_range<Linestring>
282 {};
283
284 template <typename Box>
285 struct dsv<box_tag, Box>
286 : detail::dsv::dsv_indexed<Box>
287 {};
288
289 template <typename Segment>
290 struct dsv<segment_tag, Segment>
291 : detail::dsv::dsv_indexed<Segment>
292 {};
293
294 template <typename Ring>
295 struct dsv<ring_tag, Ring>
296 : detail::dsv::dsv_range<Ring>
297 {};
298
299 template <typename Polygon>
300 struct dsv<polygon_tag, Polygon>
301 : detail::dsv::dsv_poly<Polygon>
302 {};
303
304 } // namespace dispatch
305 #endif // DOXYGEN_NO_DISPATCH
306
307 #ifndef DOXYGEN_NO_DETAIL
308 namespace detail { namespace dsv
309 {
310
311 // FIXME: This class is not copyable/assignable but it is used as such --mloskot
312 template <typename Geometry>
313 class dsv_manipulator
314 {
315 public:
316
317 inline dsv_manipulator(Geometry const& g,
318 dsv_settings const& settings)
319 : m_geometry(g)
320 , m_settings(settings)
321 {}
322
323 template <typename Char, typename Traits>
324 inline friend std::basic_ostream<Char, Traits>& operator<<(
325 std::basic_ostream<Char, Traits>& os,
326 dsv_manipulator const& m)
327 {
328 dispatch::dsv
329 <
330 typename tag_cast
331 <
332 typename tag<Geometry>::type,
333 multi_tag
334 >::type,
335 Geometry
336 >::apply(os, m.m_geometry, m.m_settings);
337 os.flush();
338 return os;
339 }
340
341 private:
342 Geometry const& m_geometry;
343 dsv_settings m_settings;
344 };
345
346
347 template <typename MultiGeometry>
348 struct dsv_multi
349 {
350 typedef dispatch::dsv
351 <
352 typename single_tag_of
353 <
354 typename tag<MultiGeometry>::type
355 >::type,
356 typename boost::range_value<MultiGeometry>::type
357 > dispatch_one;
358
359 typedef typename boost::range_iterator
360 <
361 MultiGeometry const
362 >::type iterator;
363
364
365 template <typename Char, typename Traits>
366 static inline void apply(std::basic_ostream<Char, Traits>& os,
367 MultiGeometry const& multi,
368 dsv_settings const& settings)
369 {
370 os << settings.list_open;
371
372 bool first = true;
373 for(iterator it = boost::begin(multi);
374 it != boost::end(multi);
375 ++it, first = false)
376 {
377 os << (first ? "" : settings.list_separator);
378 dispatch_one::apply(os, *it, settings);
379 }
380 os << settings.list_close;
381 }
382 };
383
384 }} // namespace detail::dsv
385 #endif // DOXYGEN_NO_DETAIL
386
387 // TODO: The alternative to this could be a forward declaration of dispatch::dsv<>
388 // or braking the code into the interface and implementation part
389 #ifndef DOXYGEN_NO_DISPATCH
390 namespace dispatch
391 {
392
393 template <typename Geometry>
394 struct dsv<multi_tag, Geometry>
395 : detail::dsv::dsv_multi<Geometry>
396 {};
397
398 } // namespace dispatch
399 #endif // DOXYGEN_NO_DISPATCH
400
401 /*!
402 \brief Main DSV-streaming function
403 \details DSV stands for Delimiter Separated Values. Geometries can be streamed
404 as DSV. There are defaults for all separators.
405 \note Useful for examples and testing purposes
406 \note With this function GeoJSON objects can be created, using the right
407 delimiters
408 \ingroup utility
409 */
410 template <typename Geometry>
411 inline detail::dsv::dsv_manipulator<Geometry> dsv(Geometry const& geometry
412 , std::string const& coordinate_separator = ", "
413 , std::string const& point_open = "("
414 , std::string const& point_close = ")"
415 , std::string const& point_separator = ", "
416 , std::string const& list_open = "("
417 , std::string const& list_close = ")"
418 , std::string const& list_separator = ", "
419 )
420 {
421 concepts::check<Geometry const>();
422
423 return detail::dsv::dsv_manipulator<Geometry>(geometry,
424 detail::dsv::dsv_settings(coordinate_separator,
425 point_open, point_close, point_separator,
426 list_open, list_close, list_separator));
427 }
428
429 }} // namespace boost::geometry
430
431 #endif // BOOST_GEOMETRY_IO_DSV_WRITE_HPP