File indexing completed on 2025-09-13 08:35:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #ifndef BOOST_GEOMETRY_IO_DSV_WRITE_HPP
0020 #define BOOST_GEOMETRY_IO_DSV_WRITE_HPP
0021
0022 #include <cstddef>
0023 #include <ostream>
0024 #include <string>
0025
0026 #include <boost/concept_check.hpp>
0027 #include <boost/range/begin.hpp>
0028 #include <boost/range/end.hpp>
0029 #include <boost/range/value_type.hpp>
0030 #include <boost/range/size.hpp>
0031
0032 #include <boost/geometry/core/exterior_ring.hpp>
0033 #include <boost/geometry/core/interior_rings.hpp>
0034 #include <boost/geometry/core/ring_type.hpp>
0035 #include <boost/geometry/core/tag_cast.hpp>
0036 #include <boost/geometry/core/tags.hpp>
0037
0038 #include <boost/geometry/geometries/concepts/check.hpp>
0039
0040 #include <boost/geometry/util/condition.hpp>
0041
0042 namespace boost { namespace geometry
0043 {
0044
0045 #ifndef DOXYGEN_NO_DETAIL
0046 namespace detail { namespace dsv
0047 {
0048
0049 struct dsv_settings
0050 {
0051 std::string coordinate_separator;
0052 std::string point_open;
0053 std::string point_close;
0054 std::string point_separator;
0055 std::string list_open;
0056 std::string list_close;
0057 std::string list_separator;
0058 bool close_rings{false};
0059
0060 dsv_settings(std::string const& sep
0061 , std::string const& open
0062 , std::string const& close
0063 , std::string const& psep
0064 , std::string const& lopen
0065 , std::string const& lclose
0066 , std::string const& lsep
0067 , bool cr = false
0068 )
0069 : coordinate_separator(sep)
0070 , point_open(open)
0071 , point_close(close)
0072 , point_separator(psep)
0073 , list_open(lopen)
0074 , list_close(lclose)
0075 , list_separator(lsep)
0076 , close_rings(cr)
0077 {}
0078 };
0079
0080
0081
0082
0083 template <typename Point, std::size_t Dimension, std::size_t Count>
0084 struct stream_coordinate
0085 {
0086 template <typename Char, typename Traits>
0087 static inline void apply(std::basic_ostream<Char, Traits>& os,
0088 Point const& point,
0089 dsv_settings const& settings)
0090 {
0091 os << (Dimension > 0 ? settings.coordinate_separator : "")
0092 << get<Dimension>(point);
0093
0094 stream_coordinate
0095 <
0096 Point, Dimension + 1, Count
0097 >::apply(os, point, settings);
0098 }
0099 };
0100
0101 template <typename Point, std::size_t Count>
0102 struct stream_coordinate<Point, Count, Count>
0103 {
0104 template <typename Char, typename Traits>
0105 static inline void apply(std::basic_ostream<Char, Traits>&,
0106 Point const&,
0107 dsv_settings const& )
0108 {
0109 }
0110 };
0111
0112
0113
0114
0115 template
0116 <
0117 typename Geometry,
0118 std::size_t Index,
0119 std::size_t Dimension,
0120 std::size_t Count
0121 >
0122 struct stream_indexed
0123 {
0124 template <typename Char, typename Traits>
0125 static inline void apply(std::basic_ostream<Char, Traits>& os,
0126 Geometry const& geometry,
0127 dsv_settings const& settings)
0128 {
0129 os << (Dimension > 0 ? settings.coordinate_separator : "")
0130 << get<Index, Dimension>(geometry);
0131 stream_indexed
0132 <
0133 Geometry, Index, Dimension + 1, Count
0134 >::apply(os, geometry, settings);
0135 }
0136 };
0137
0138 template <typename Geometry, std::size_t Index, std::size_t Count>
0139 struct stream_indexed<Geometry, Index, Count, Count>
0140 {
0141 template <typename Char, typename Traits>
0142 static inline void apply(std::basic_ostream<Char, Traits>&, Geometry const&,
0143 dsv_settings const& )
0144 {
0145 }
0146 };
0147
0148
0149
0150
0151 template <typename Point>
0152 struct dsv_point
0153 {
0154 template <typename Char, typename Traits>
0155 static inline void apply(std::basic_ostream<Char, Traits>& os,
0156 Point const& p,
0157 dsv_settings const& settings)
0158 {
0159 os << settings.point_open;
0160 stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p, settings);
0161 os << settings.point_close;
0162 }
0163 };
0164
0165
0166
0167
0168
0169 template <typename Range, bool Areal>
0170 struct dsv_range
0171 {
0172 template <typename Char, typename Traits>
0173 static inline void apply(std::basic_ostream<Char, Traits>& os,
0174 Range const& range,
0175 dsv_settings const& settings)
0176 {
0177 bool first = true;
0178
0179 os << settings.list_open;
0180
0181 auto stream_point = [&os, &settings](std::string const& sep, auto const& point)
0182 {
0183 os << sep << settings.point_open;
0184 stream_coordinate
0185 <
0186 point_type, 0, dimension<point_type>::type::value
0187 >::apply(os, point, settings);
0188 os << settings.point_close;
0189 };
0190
0191 for (auto it = boost::begin(range); it != boost::end(range); ++it)
0192 {
0193 stream_point(first ? "" : settings.point_separator, *it);
0194 first = false;
0195 }
0196
0197 if (BOOST_GEOMETRY_CONDITION(Areal))
0198 {
0199 if (settings.close_rings && boost::size(range) > 0)
0200 {
0201
0202 stream_point(settings.point_separator, *boost::begin(range));
0203 }
0204 }
0205
0206 os << settings.list_close;
0207 }
0208
0209 private:
0210 typedef typename boost::range_value<Range>::type point_type;
0211 };
0212
0213
0214
0215
0216
0217
0218 template <typename Polygon>
0219 struct dsv_poly
0220 {
0221 template <typename Char, typename Traits>
0222 static inline void apply(std::basic_ostream<Char, Traits>& os,
0223 Polygon const& poly,
0224 dsv_settings const& settings)
0225 {
0226 using ring_t = ring_type_t<Polygon>;
0227
0228 os << settings.list_open;
0229
0230 dsv_range<ring_t, true>::apply(os, exterior_ring(poly), settings);
0231
0232 auto const& rings = interior_rings(poly);
0233 for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
0234 {
0235 os << settings.list_separator;
0236 dsv_range<ring_t, true>::apply(os, *it, settings);
0237 }
0238 os << settings.list_close;
0239 }
0240 };
0241
0242 template <typename Geometry, std::size_t Index>
0243 struct dsv_per_index
0244 {
0245 using type = point_type_t<Geometry>;
0246
0247 template <typename Char, typename Traits>
0248 static inline void apply(std::basic_ostream<Char, Traits>& os,
0249 Geometry const& geometry,
0250 dsv_settings const& settings)
0251 {
0252 os << settings.point_open;
0253 stream_indexed
0254 <
0255 Geometry, Index, 0, dimension<Geometry>::type::value
0256 >::apply(os, geometry, settings);
0257 os << settings.point_close;
0258 }
0259 };
0260
0261 template <typename Geometry>
0262 struct dsv_indexed
0263 {
0264 using type = point_type_t<Geometry>;
0265
0266 template <typename Char, typename Traits>
0267 static inline void apply(std::basic_ostream<Char, Traits>& os,
0268 Geometry const& geometry,
0269 dsv_settings const& settings)
0270 {
0271 os << settings.list_open;
0272 dsv_per_index<Geometry, 0>::apply(os, geometry, settings);
0273 os << settings.point_separator;
0274 dsv_per_index<Geometry, 1>::apply(os, geometry, settings);
0275 os << settings.list_close;
0276 }
0277 };
0278
0279 }}
0280 #endif
0281
0282 #ifndef DOXYGEN_NO_DISPATCH
0283 namespace dispatch
0284 {
0285
0286 template <typename Tag, typename Geometry>
0287 struct dsv {};
0288
0289 template <typename Point>
0290 struct dsv<point_tag, Point>
0291 : detail::dsv::dsv_point<Point>
0292 {};
0293
0294 template <typename Linestring>
0295 struct dsv<linestring_tag, Linestring>
0296 : detail::dsv::dsv_range<Linestring, false>
0297 {};
0298
0299 template <typename Box>
0300 struct dsv<box_tag, Box>
0301 : detail::dsv::dsv_indexed<Box>
0302 {};
0303
0304 template <typename Segment>
0305 struct dsv<segment_tag, Segment>
0306 : detail::dsv::dsv_indexed<Segment>
0307 {};
0308
0309 template <typename Ring>
0310 struct dsv<ring_tag, Ring>
0311 : detail::dsv::dsv_range<Ring, true>
0312 {};
0313
0314 template <typename Polygon>
0315 struct dsv<polygon_tag, Polygon>
0316 : detail::dsv::dsv_poly<Polygon>
0317 {};
0318
0319 }
0320 #endif
0321
0322 #ifndef DOXYGEN_NO_DETAIL
0323 namespace detail { namespace dsv
0324 {
0325
0326
0327 template <typename Geometry>
0328 class dsv_manipulator
0329 {
0330 public:
0331
0332 inline dsv_manipulator(Geometry const& g,
0333 dsv_settings const& settings)
0334 : m_geometry(g)
0335 , m_settings(settings)
0336 {}
0337
0338 template <typename Char, typename Traits>
0339 inline friend std::basic_ostream<Char, Traits>& operator<<(
0340 std::basic_ostream<Char, Traits>& os,
0341 dsv_manipulator const& m)
0342 {
0343 dispatch::dsv
0344 <
0345 tag_cast_t
0346 <
0347 tag_t<Geometry>,
0348 multi_tag
0349 >,
0350 Geometry
0351 >::apply(os, m.m_geometry, m.m_settings);
0352 os.flush();
0353 return os;
0354 }
0355
0356 private:
0357 Geometry const& m_geometry;
0358 dsv_settings m_settings;
0359 };
0360
0361
0362 template <typename MultiGeometry>
0363 struct dsv_multi
0364 {
0365 typedef dispatch::dsv
0366 <
0367 typename single_tag_of<tag_t<MultiGeometry>>::type,
0368 typename boost::range_value<MultiGeometry>::type
0369 > dispatch_one;
0370
0371 template <typename Char, typename Traits>
0372 static inline void apply(std::basic_ostream<Char, Traits>& os,
0373 MultiGeometry const& multi,
0374 dsv_settings const& settings)
0375 {
0376 os << settings.list_open;
0377
0378 bool first = true;
0379 for(auto it = boost::begin(multi); it != boost::end(multi); ++it, first = false)
0380 {
0381 os << (first ? "" : settings.list_separator);
0382 dispatch_one::apply(os, *it, settings);
0383 }
0384 os << settings.list_close;
0385 }
0386 };
0387
0388 }}
0389 #endif
0390
0391
0392
0393 #ifndef DOXYGEN_NO_DISPATCH
0394 namespace dispatch
0395 {
0396
0397 template <typename Geometry>
0398 struct dsv<multi_tag, Geometry>
0399 : detail::dsv::dsv_multi<Geometry>
0400 {};
0401
0402 }
0403 #endif
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414 template <typename Geometry>
0415 inline detail::dsv::dsv_manipulator<Geometry> dsv(Geometry const& geometry
0416 , std::string const& coordinate_separator = ", "
0417 , std::string const& point_open = "("
0418 , std::string const& point_close = ")"
0419 , std::string const& point_separator = ", "
0420 , std::string const& list_open = "("
0421 , std::string const& list_close = ")"
0422 , std::string const& list_separator = ", "
0423 , bool close_rings = false
0424 )
0425 {
0426 concepts::check<Geometry const>();
0427
0428 return detail::dsv::dsv_manipulator<Geometry>(geometry,
0429 detail::dsv::dsv_settings(coordinate_separator,
0430 point_open, point_close, point_separator,
0431 list_open, list_close, list_separator, close_rings));
0432 }
0433
0434 }}
0435
0436 #endif