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