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.
7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
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)
14 #ifndef BOOST_GEOMETRY_IO_DSV_WRITE_HPP
15 #define BOOST_GEOMETRY_IO_DSV_WRITE_HPP
21 #include <boost/concept_check.hpp>
22 #include <boost/range.hpp>
23 #include <boost/typeof/typeof.hpp>
25 #include <boost/geometry/core/exterior_ring.hpp>
26 #include <boost/geometry/core/interior_rings.hpp>
27 #include <boost/geometry/core/ring_type.hpp>
28 #include <boost/geometry/core/tag_cast.hpp>
30 #include <boost/geometry/geometries/concepts/check.hpp>
32 namespace boost { namespace geometry
35 #ifndef DOXYGEN_NO_DETAIL
36 namespace detail { namespace dsv
41 std::string coordinate_separator;
42 std::string point_open;
43 std::string point_close;
44 std::string point_separator;
45 std::string list_open;
46 std::string list_close;
47 std::string list_separator;
49 dsv_settings(std::string const& sep
50 , std::string const& open
51 , std::string const& close
52 , std::string const& psep
53 , std::string const& lopen
54 , std::string const& lclose
55 , std::string const& lsep
57 : coordinate_separator(sep)
60 , point_separator(psep)
63 , list_separator(lsep)
68 \brief Stream coordinate of a point as \ref DSV
70 template <typename Point, std::size_t Dimension, std::size_t Count>
71 struct stream_coordinate
73 template <typename Char, typename Traits>
74 static inline void apply(std::basic_ostream<Char, Traits>& os,
76 dsv_settings const& settings)
78 os << (Dimension > 0 ? settings.coordinate_separator : "")
79 << get<Dimension>(point);
83 Point, Dimension + 1, Count
84 >::apply(os, point, settings);
88 template <typename Point, std::size_t Count>
89 struct stream_coordinate<Point, Count, Count>
91 template <typename Char, typename Traits>
92 static inline void apply(std::basic_ostream<Char, Traits>&,
100 \brief Stream indexed coordinate of a box/segment as \ref DSV
106 std::size_t Dimension,
109 struct stream_indexed
111 template <typename Char, typename Traits>
112 static inline void apply(std::basic_ostream<Char, Traits>& os,
113 Geometry const& geometry,
114 dsv_settings const& settings)
116 os << (Dimension > 0 ? settings.coordinate_separator : "")
117 << get<Index, Dimension>(geometry);
120 Geometry, Index, Dimension + 1, Count
121 >::apply(os, geometry, settings);
125 template <typename Geometry, std::size_t Index, std::size_t Count>
126 struct stream_indexed<Geometry, Index, Count, Count>
128 template <typename Char, typename Traits>
129 static inline void apply(std::basic_ostream<Char, Traits>&, Geometry const&,
130 dsv_settings const& )
136 \brief Stream points as \ref DSV
138 template <typename Point>
141 template <typename Char, typename Traits>
142 static inline void apply(std::basic_ostream<Char, Traits>& os,
144 dsv_settings const& settings)
146 os << settings.point_open;
147 stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p, settings);
148 os << settings.point_close;
153 \brief Stream ranges as DSV
154 \note policy is used to stream prefix/postfix, enabling derived classes to override this
156 template <typename Range>
159 template <typename Char, typename Traits>
160 static inline void apply(std::basic_ostream<Char, Traits>& os,
162 dsv_settings const& settings)
164 typedef typename boost::range_iterator<Range const>::type iterator_type;
168 os << settings.list_open;
170 for (iterator_type it = boost::begin(range);
171 it != boost::end(range);
174 os << (first ? "" : settings.point_separator)
175 << settings.point_open;
179 point_type, 0, dimension<point_type>::type::value
180 >::apply(os, *it, settings);
181 os << settings.point_close;
186 os << settings.list_close;
190 typedef typename boost::range_value<Range>::type point_type;
194 \brief Stream sequence of points as DSV-part, e.g. (1 2),(3 4)
195 \note Used in polygon, all multi-geometries
198 template <typename Polygon>
201 template <typename Char, typename Traits>
202 static inline void apply(std::basic_ostream<Char, Traits>& os,
204 dsv_settings const& settings)
206 typedef typename ring_type<Polygon>::type ring;
208 os << settings.list_open;
210 dsv_range<ring>::apply(os, exterior_ring(poly), settings);
212 typename interior_return_type<Polygon const>::type rings
213 = interior_rings(poly);
214 for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
216 os << settings.list_separator;
217 dsv_range<ring>::apply(os, *it, settings);
219 os << settings.list_close;
223 template <typename Geometry, std::size_t Index>
226 typedef typename point_type<Geometry>::type point_type;
228 template <typename Char, typename Traits>
229 static inline void apply(std::basic_ostream<Char, Traits>& os,
230 Geometry const& geometry,
231 dsv_settings const& settings)
233 os << settings.point_open;
236 Geometry, Index, 0, dimension<Geometry>::type::value
237 >::apply(os, geometry, settings);
238 os << settings.point_close;
242 template <typename Geometry>
245 typedef typename point_type<Geometry>::type point_type;
247 template <typename Char, typename Traits>
248 static inline void apply(std::basic_ostream<Char, Traits>& os,
249 Geometry const& geometry,
250 dsv_settings const& settings)
252 os << settings.list_open;
253 dsv_per_index<Geometry, 0>::apply(os, geometry, settings);
254 os << settings.point_separator;
255 dsv_per_index<Geometry, 1>::apply(os, geometry, settings);
256 os << settings.list_close;
260 }} // namespace detail::dsv
261 #endif // DOXYGEN_NO_DETAIL
263 #ifndef DOXYGEN_NO_DISPATCH
267 template <typename Tag, typename Geometry>
270 template <typename Point>
271 struct dsv<point_tag, Point>
272 : detail::dsv::dsv_point<Point>
275 template <typename Linestring>
276 struct dsv<linestring_tag, Linestring>
277 : detail::dsv::dsv_range<Linestring>
280 template <typename Box>
281 struct dsv<box_tag, Box>
282 : detail::dsv::dsv_indexed<Box>
285 template <typename Segment>
286 struct dsv<segment_tag, Segment>
287 : detail::dsv::dsv_indexed<Segment>
290 template <typename Ring>
291 struct dsv<ring_tag, Ring>
292 : detail::dsv::dsv_range<Ring>
295 template <typename Polygon>
296 struct dsv<polygon_tag, Polygon>
297 : detail::dsv::dsv_poly<Polygon>
300 } // namespace dispatch
301 #endif // DOXYGEN_NO_DISPATCH
303 #ifndef DOXYGEN_NO_DETAIL
304 namespace detail { namespace dsv
307 // FIXME: This class is not copyable/assignable but it is used as such --mloskot
308 template <typename Geometry>
309 class dsv_manipulator
313 inline dsv_manipulator(Geometry const& g,
314 dsv_settings const& settings)
316 , m_settings(settings)
319 template <typename Char, typename Traits>
320 inline friend std::basic_ostream<Char, Traits>& operator<<(
321 std::basic_ostream<Char, Traits>& os,
322 dsv_manipulator const& m)
328 typename tag<Geometry>::type,
332 >::apply(os, m.m_geometry, m.m_settings);
338 Geometry const& m_geometry;
339 dsv_settings m_settings;
342 }} // namespace detail::dsv
343 #endif // DOXYGEN_NO_DETAIL
346 \brief Main DSV-streaming function
347 \details DSV stands for Delimiter Separated Values. Geometries can be streamed
348 as DSV. There are defaults for all separators.
349 \note Useful for examples and testing purposes
350 \note With this function GeoJSON objects can be created, using the right
354 template <typename Geometry>
355 inline detail::dsv::dsv_manipulator<Geometry> dsv(Geometry const& geometry
356 , std::string const& coordinate_separator = ", "
357 , std::string const& point_open = "("
358 , std::string const& point_close = ")"
359 , std::string const& point_separator = ", "
360 , std::string const& list_open = "("
361 , std::string const& list_close = ")"
362 , std::string const& list_separator = ", "
365 concept::check<Geometry const>();
367 return detail::dsv::dsv_manipulator<Geometry>(geometry,
368 detail::dsv::dsv_settings(coordinate_separator,
369 point_open, point_close, point_separator,
370 list_open, list_close, list_separator));
373 }} // namespace boost::geometry
375 #endif // BOOST_GEOMETRY_IO_DSV_WRITE_HPP