annotate DEPENDENCIES/generic/include/boost/geometry/io/dsv/write.hpp @ 133:4acb5d8d80b6 tip

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