Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:35:34

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 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 \brief Stream coordinate of a point as \ref DSV
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 \brief Stream indexed coordinate of a box/segment as \ref DSV
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 \brief Stream points as \ref DSV
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 \brief Stream ranges as DSV
0162 \note policy is used to stream prefix/postfix, enabling derived classes to override this
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 \brief Stream sequence of points as DSV-part, e.g. (1 2),(3 4)
0199 \note Used in polygon, all multi-geometries
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 }} // namespace detail::dsv
0264 #endif // DOXYGEN_NO_DETAIL
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 } // namespace dispatch
0304 #endif // DOXYGEN_NO_DISPATCH
0305 
0306 #ifndef DOXYGEN_NO_DETAIL
0307 namespace detail { namespace dsv
0308 {
0309 
0310 // FIXME: This class is not copyable/assignable but it is used as such --mloskot
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 }} // namespace detail::dsv
0376 #endif // DOXYGEN_NO_DETAIL
0377 
0378 // TODO: The alternative to this could be a forward declaration of dispatch::dsv<>
0379 //       or braking the code into the interface and implementation part
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 } // namespace dispatch
0390 #endif // DOXYGEN_NO_DISPATCH
0391 
0392 /*!
0393 \brief Main DSV-streaming function
0394 \details DSV stands for Delimiter Separated Values. Geometries can be streamed
0395     as DSV. There are defaults for all separators.
0396 \note Useful for examples and testing purposes
0397 \note With this function GeoJSON objects can be created, using the right
0398     delimiters
0399 \ingroup dsv
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 }} // namespace boost::geometry
0421 
0422 #endif // BOOST_GEOMETRY_IO_DSV_WRITE_HPP