Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-13 08:35:19

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
0004 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
0005 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
0006 // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
0007 
0008 // This file was modified by Oracle on 2018-2020.
0009 // Modifications copyright (c) 2018-2020, Oracle and/or its affiliates.
0010 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0011 
0012 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
0013 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
0014 
0015 // Use, modification and distribution is subject to the Boost Software License,
0016 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0017 // http://www.boost.org/LICENSE_1_0.txt)
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 \brief Stream coordinate of a point as \ref DSV
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 \brief Stream indexed coordinate of a box/segment as \ref DSV
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 \brief Stream points as \ref DSV
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 \brief Stream ranges as DSV
0167 \note policy is used to stream prefix/postfix, enabling derived classes to override this
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                 // Close it explicitly
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 \brief Stream sequence of points as DSV-part, e.g. (1 2),(3 4)
0215 \note Used in polygon, all multi-geometries
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 }} // namespace detail::dsv
0280 #endif // DOXYGEN_NO_DETAIL
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 } // namespace dispatch
0320 #endif // DOXYGEN_NO_DISPATCH
0321 
0322 #ifndef DOXYGEN_NO_DETAIL
0323 namespace detail { namespace dsv
0324 {
0325 
0326 // FIXME: This class is not copyable/assignable but it is used as such --mloskot
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 }} // namespace detail::dsv
0389 #endif // DOXYGEN_NO_DETAIL
0390 
0391 // TODO: The alternative to this could be a forward declaration of dispatch::dsv<>
0392 //       or braking the code into the interface and implementation part
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 } // namespace dispatch
0403 #endif // DOXYGEN_NO_DISPATCH
0404 
0405 /*!
0406 \brief Main DSV-streaming function
0407 \details DSV stands for Delimiter Separated Values. Geometries can be streamed
0408     as DSV. There are defaults for all separators.
0409 \note Useful for examples and testing purposes
0410 \note With this function GeoJSON objects can be created, using the right
0411     delimiters
0412 \ingroup dsv
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 }} // namespace boost::geometry
0435 
0436 #endif // BOOST_GEOMETRY_IO_DSV_WRITE_HPP