1 // Boost.Geometry (aka GGL, Generic Geometry Library)
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.
8 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
9 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
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)
15 #ifndef BOOST_GEOMETRY_IO_DSV_WRITE_HPP
16 #define BOOST_GEOMETRY_IO_DSV_WRITE_HPP
22 #include <boost/concept_check.hpp>
23 #include <boost/range.hpp>
25 #include <boost/geometry/algorithms/detail/interior_iterator.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 #include <boost/geometry/core/tag_cast.hpp>
31 #include <boost/geometry/core/tags.hpp>
33 #include <boost/geometry/geometries/concepts/check.hpp>
35 namespace boost { namespace geometry
38 #ifndef DOXYGEN_NO_DETAIL
39 namespace detail { namespace dsv
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;
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
60 : coordinate_separator(sep)
63 , point_separator(psep)
66 , list_separator(lsep)
71 \brief Stream coordinate of a point as \ref DSV
73 template <typename Point, std::size_t Dimension, std::size_t Count>
74 struct stream_coordinate
76 template <typename Char, typename Traits>
77 static inline void apply(std::basic_ostream<Char, Traits>& os,
79 dsv_settings const& settings)
81 os << (Dimension > 0 ? settings.coordinate_separator : "")
82 << get<Dimension>(point);
86 Point, Dimension + 1, Count
87 >::apply(os, point, settings);
91 template <typename Point, std::size_t Count>
92 struct stream_coordinate<Point, Count, Count>
94 template <typename Char, typename Traits>
95 static inline void apply(std::basic_ostream<Char, Traits>&,
103 \brief Stream indexed coordinate of a box/segment as \ref DSV
109 std::size_t Dimension,
112 struct stream_indexed
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)
119 os << (Dimension > 0 ? settings.coordinate_separator : "")
120 << get<Index, Dimension>(geometry);
123 Geometry, Index, Dimension + 1, Count
124 >::apply(os, geometry, settings);
128 template <typename Geometry, std::size_t Index, std::size_t Count>
129 struct stream_indexed<Geometry, Index, Count, Count>
131 template <typename Char, typename Traits>
132 static inline void apply(std::basic_ostream<Char, Traits>&, Geometry const&,
133 dsv_settings const& )
139 \brief Stream points as \ref DSV
141 template <typename Point>
144 template <typename Char, typename Traits>
145 static inline void apply(std::basic_ostream<Char, Traits>& os,
147 dsv_settings const& settings)
149 os << settings.point_open;
150 stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p, settings);
151 os << settings.point_close;
156 \brief Stream ranges as DSV
157 \note policy is used to stream prefix/postfix, enabling derived classes to override this
159 template <typename Range>
162 template <typename Char, typename Traits>
163 static inline void apply(std::basic_ostream<Char, Traits>& os,
165 dsv_settings const& settings)
167 typedef typename boost::range_iterator<Range const>::type iterator_type;
171 os << settings.list_open;
173 for (iterator_type it = boost::begin(range);
174 it != boost::end(range);
177 os << (first ? "" : settings.point_separator)
178 << settings.point_open;
182 point_type, 0, dimension<point_type>::type::value
183 >::apply(os, *it, settings);
184 os << settings.point_close;
189 os << settings.list_close;
193 typedef typename boost::range_value<Range>::type point_type;
197 \brief Stream sequence of points as DSV-part, e.g. (1 2),(3 4)
198 \note Used in polygon, all multi-geometries
201 template <typename Polygon>
204 template <typename Char, typename Traits>
205 static inline void apply(std::basic_ostream<Char, Traits>& os,
207 dsv_settings const& settings)
209 typedef typename ring_type<Polygon>::type ring;
211 os << settings.list_open;
213 dsv_range<ring>::apply(os, exterior_ring(poly), settings);
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)
220 os << settings.list_separator;
221 dsv_range<ring>::apply(os, *it, settings);
223 os << settings.list_close;
227 template <typename Geometry, std::size_t Index>
230 typedef typename point_type<Geometry>::type point_type;
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)
237 os << settings.point_open;
240 Geometry, Index, 0, dimension<Geometry>::type::value
241 >::apply(os, geometry, settings);
242 os << settings.point_close;
246 template <typename Geometry>
249 typedef typename point_type<Geometry>::type point_type;
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)
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;
264 }} // namespace detail::dsv
265 #endif // DOXYGEN_NO_DETAIL
267 #ifndef DOXYGEN_NO_DISPATCH
271 template <typename Tag, typename Geometry>
274 template <typename Point>
275 struct dsv<point_tag, Point>
276 : detail::dsv::dsv_point<Point>
279 template <typename Linestring>
280 struct dsv<linestring_tag, Linestring>
281 : detail::dsv::dsv_range<Linestring>
284 template <typename Box>
285 struct dsv<box_tag, Box>
286 : detail::dsv::dsv_indexed<Box>
289 template <typename Segment>
290 struct dsv<segment_tag, Segment>
291 : detail::dsv::dsv_indexed<Segment>
294 template <typename Ring>
295 struct dsv<ring_tag, Ring>
296 : detail::dsv::dsv_range<Ring>
299 template <typename Polygon>
300 struct dsv<polygon_tag, Polygon>
301 : detail::dsv::dsv_poly<Polygon>
304 } // namespace dispatch
305 #endif // DOXYGEN_NO_DISPATCH
307 #ifndef DOXYGEN_NO_DETAIL
308 namespace detail { namespace dsv
311 // FIXME: This class is not copyable/assignable but it is used as such --mloskot
312 template <typename Geometry>
313 class dsv_manipulator
317 inline dsv_manipulator(Geometry const& g,
318 dsv_settings const& settings)
320 , m_settings(settings)
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)
332 typename tag<Geometry>::type,
336 >::apply(os, m.m_geometry, m.m_settings);
342 Geometry const& m_geometry;
343 dsv_settings m_settings;
347 template <typename MultiGeometry>
350 typedef dispatch::dsv
352 typename single_tag_of
354 typename tag<MultiGeometry>::type
356 typename boost::range_value<MultiGeometry>::type
359 typedef typename boost::range_iterator
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)
370 os << settings.list_open;
373 for(iterator it = boost::begin(multi);
374 it != boost::end(multi);
377 os << (first ? "" : settings.list_separator);
378 dispatch_one::apply(os, *it, settings);
380 os << settings.list_close;
384 }} // namespace detail::dsv
385 #endif // DOXYGEN_NO_DETAIL
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
393 template <typename Geometry>
394 struct dsv<multi_tag, Geometry>
395 : detail::dsv::dsv_multi<Geometry>
398 } // namespace dispatch
399 #endif // DOXYGEN_NO_DISPATCH
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
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 = ", "
421 concepts::check<Geometry const>();
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));
429 }} // namespace boost::geometry
431 #endif // BOOST_GEOMETRY_IO_DSV_WRITE_HPP