Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:34:36

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
0004 // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
0005 
0006 // This file was modified by Oracle on 2016-2020.
0007 // Modifications copyright (c) 2016-2020, Oracle and/or its affiliates.
0008 
0009 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0010 
0011 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
0012 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
0013 
0014 // Use, modification and distribution is subject to the Boost Software License,
0015 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0016 // http://www.boost.org/LICENSE_1_0.txt)
0017 
0018 #ifndef BOOST_GEOMETRY_IO_SVG_WRITE_HPP
0019 #define BOOST_GEOMETRY_IO_SVG_WRITE_HPP
0020 
0021 #include <ostream>
0022 #include <string>
0023 
0024 #include <boost/config.hpp>
0025 #include <boost/range/begin.hpp>
0026 #include <boost/range/end.hpp>
0027 #include <boost/range/value_type.hpp>
0028 #include <boost/variant/apply_visitor.hpp>
0029 #include <boost/variant/static_visitor.hpp>
0030 #include <boost/variant/variant_fwd.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/static_assert.hpp>
0036 
0037 #include <boost/geometry/geometries/concepts/check.hpp>
0038 
0039 
0040 namespace boost { namespace geometry
0041 {
0042 
0043 
0044 #ifndef DOXYGEN_NO_DETAIL
0045 namespace detail { namespace svg
0046 {
0047 
0048 
0049 template <typename Point>
0050 struct svg_point
0051 {
0052     template <typename Char, typename Traits>
0053     static inline void apply(std::basic_ostream<Char, Traits>& os,
0054                 Point const& p, std::string const& style, double size)
0055     {
0056         os << "<circle cx=\"" << geometry::get<0>(p)
0057             << "\" cy=\"" << geometry::get<1>(p)
0058             << "\" r=\"" << (size < 0 ? 5 : size)
0059             << "\" style=\"" << style << "\"/>";
0060     }
0061 };
0062 
0063 
0064 template <typename Box>
0065 struct svg_box
0066 {
0067     template <typename Char, typename Traits>
0068     static inline void apply(std::basic_ostream<Char, Traits>& os,
0069                 Box const& box, std::string const& style, double)
0070     {
0071         // Prevent invisible boxes, making them >=1, using "max"
0072         BOOST_USING_STD_MAX();
0073 
0074         using ct = coordinate_type_t<Box>;
0075         ct x = geometry::get<geometry::min_corner, 0>(box);
0076         ct y = geometry::get<geometry::min_corner, 1>(box);
0077         ct width = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),
0078                     geometry::get<geometry::max_corner, 0>(box) - x);
0079         ct height = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),
0080                     geometry::get<geometry::max_corner, 1>(box) - y);
0081 
0082         os << "<rect x=\"" << x << "\" y=\"" << y
0083            << "\" width=\"" << width << "\" height=\"" << height
0084            << "\" style=\"" << style << "\"/>";
0085     }
0086 };
0087 
0088 template <typename Segment>
0089 struct svg_segment
0090 {
0091     template <typename Char, typename Traits>
0092     static inline void apply(std::basic_ostream<Char, Traits>& os,
0093         Segment const& segment, std::string const& style, double)
0094     {
0095         using ct = coordinate_type_t<Segment>;
0096         ct const x1 = geometry::get<0, 0>(segment);
0097         ct const y1 = geometry::get<0, 1>(segment);
0098         ct const x2 = geometry::get<1, 0>(segment);
0099         ct const y2 = geometry::get<1, 1>(segment);
0100 
0101         os << "<line x1=\"" << x1 << "\" y1=\"" << y1
0102             << "\" x2=\"" << x2 << "\" y2=\"" << y2
0103             << "\" style=\"" << style << "\"/>";
0104     }
0105 };
0106 
0107 /*!
0108 \brief Stream ranges as SVG
0109 \note policy is used to select type (polyline/polygon)
0110 */
0111 template <typename Range, typename Policy>
0112 struct svg_range
0113 {
0114     template <typename Char, typename Traits>
0115     static inline void apply(std::basic_ostream<Char, Traits>& os,
0116         Range const& range, std::string const& style, double)
0117     {
0118         bool first = true;
0119 
0120         os << "<" << Policy::prefix() << " points=\"";
0121 
0122         for (auto it = boost::begin(range); it != boost::end(range); ++it, first = false)
0123         {
0124             os << (first ? "" : " " )
0125                 << geometry::get<0>(*it)
0126                 << ","
0127                 << geometry::get<1>(*it);
0128         }
0129         os << "\" style=\"" << style << Policy::style() << "\"/>";
0130     }
0131 };
0132 
0133 
0134 
0135 template <typename Polygon>
0136 struct svg_poly
0137 {
0138     template <typename Char, typename Traits>
0139     static inline void apply(std::basic_ostream<Char, Traits>& os,
0140         Polygon const& polygon, std::string const& style, double)
0141     {
0142         bool first = true;
0143         os << "<g fill-rule=\"evenodd\"><path d=\"";
0144 
0145         auto const& ring = geometry::exterior_ring(polygon);
0146         for (auto it = boost::begin(ring); it != boost::end(ring); ++it, first = false)
0147         {
0148             os << (first ? "M" : " L") << " "
0149                 << geometry::get<0>(*it)
0150                 << ","
0151                 << geometry::get<1>(*it);
0152         }
0153 
0154         // Inner rings:
0155         {
0156             auto const& rings = interior_rings(polygon);
0157             for (auto rit = boost::begin(rings); rit != boost::end(rings); ++rit)
0158             {
0159                 first = true;
0160                 for (auto it = boost::begin(*rit); it != boost::end(*rit); ++it, first = false)
0161                 {
0162                     os << (first ? "M" : " L") << " "
0163                         << geometry::get<0>(*it)
0164                         << ","
0165                         << geometry::get<1>(*it);
0166                 }
0167             }
0168         }
0169         os << " z \" style=\"" << style << "\"/></g>";
0170 
0171     }
0172 };
0173 
0174 
0175 
0176 struct prefix_linestring
0177 {
0178     static inline const char* prefix() { return "polyline"; }
0179     static inline const char* style() { return ";fill:none"; }
0180 };
0181 
0182 
0183 struct prefix_ring
0184 {
0185     static inline const char* prefix() { return "polygon"; }
0186     static inline const char* style() { return ""; }
0187 };
0188 
0189 
0190 template <typename MultiGeometry, typename Policy>
0191 struct svg_multi
0192 {
0193     template <typename Char, typename Traits>
0194     static inline void apply(std::basic_ostream<Char, Traits>& os,
0195         MultiGeometry const& multi, std::string const& style, double size)
0196     {
0197         for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
0198         {
0199             Policy::apply(os, *it, style, size);
0200         }
0201     }
0202 
0203 };
0204 
0205 
0206 }} // namespace detail::svg
0207 #endif // DOXYGEN_NO_DETAIL
0208 
0209 
0210 #ifndef DOXYGEN_NO_DISPATCH
0211 namespace dispatch
0212 {
0213 
0214 /*!
0215 \brief Dispatching base struct for SVG streaming, specialized below per geometry type
0216 \details Specializations should implement a static method "stream" to stream a geometry
0217 The static method should have the signature:
0218 
0219 template <typename Char, typename Traits>
0220 static inline void apply(std::basic_ostream<Char, Traits>& os, G const& geometry)
0221 */
0222 template <typename Geometry, typename Tag = tag_t<Geometry>>
0223 struct svg
0224 {
0225     BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
0226         "Not or not yet implemented for this Geometry type.",
0227         Geometry, Tag);
0228 };
0229 
0230 template <typename Point>
0231 struct svg<Point, point_tag> : detail::svg::svg_point<Point> {};
0232 
0233 template <typename Segment>
0234 struct svg<Segment, segment_tag> : detail::svg::svg_segment<Segment> {};
0235 
0236 template <typename Box>
0237 struct svg<Box, box_tag> : detail::svg::svg_box<Box> {};
0238 
0239 template <typename Linestring>
0240 struct svg<Linestring, linestring_tag>
0241     : detail::svg::svg_range<Linestring, detail::svg::prefix_linestring> {};
0242 
0243 template <typename Ring>
0244 struct svg<Ring, ring_tag>
0245     : detail::svg::svg_range<Ring, detail::svg::prefix_ring> {};
0246 
0247 template <typename Polygon>
0248 struct svg<Polygon, polygon_tag>
0249     : detail::svg::svg_poly<Polygon> {};
0250 
0251 template <typename MultiPoint>
0252 struct svg<MultiPoint, multi_point_tag>
0253     : detail::svg::svg_multi
0254         <
0255             MultiPoint,
0256             detail::svg::svg_point
0257                 <
0258                     typename boost::range_value<MultiPoint>::type
0259                 >
0260 
0261         >
0262 {};
0263 
0264 template <typename MultiLinestring>
0265 struct svg<MultiLinestring, multi_linestring_tag>
0266     : detail::svg::svg_multi
0267         <
0268             MultiLinestring,
0269             detail::svg::svg_range
0270                 <
0271                     typename boost::range_value<MultiLinestring>::type,
0272                     detail::svg::prefix_linestring
0273                 >
0274 
0275         >
0276 {};
0277 
0278 template <typename MultiPolygon>
0279 struct svg<MultiPolygon, multi_polygon_tag>
0280     : detail::svg::svg_multi
0281         <
0282             MultiPolygon,
0283             detail::svg::svg_poly
0284                 <
0285                     typename boost::range_value<MultiPolygon>::type
0286                 >
0287 
0288         >
0289 {};
0290 
0291 
0292 template <typename Geometry>
0293 struct devarianted_svg
0294 {
0295     template <typename OutputStream>
0296     static inline void apply(OutputStream& os,
0297                              Geometry const& geometry,
0298                              std::string const& style,
0299                              double size)
0300     {
0301         svg<Geometry>::apply(os, geometry, style, size);
0302     }
0303 };
0304 
0305 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
0306 struct devarianted_svg<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
0307 {
0308     template <typename OutputStream>
0309     struct visitor: static_visitor<void>
0310     {
0311         OutputStream& m_os;
0312         std::string const& m_style;
0313         double m_size;
0314 
0315         visitor(OutputStream& os, std::string const& style, double size)
0316             : m_os(os)
0317             , m_style(style)
0318             , m_size(size)
0319         {}
0320 
0321         template <typename Geometry>
0322         inline void operator()(Geometry const& geometry) const
0323         {
0324             devarianted_svg<Geometry>::apply(m_os, geometry, m_style, m_size);
0325         }
0326     };
0327 
0328     template <typename OutputStream>
0329     static inline void apply(
0330         OutputStream& os,
0331         variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
0332         std::string const& style,
0333         double size
0334     )
0335     {
0336         boost::apply_visitor(visitor<OutputStream>(os, style, size), geometry);
0337     }
0338 };
0339 
0340 } // namespace dispatch
0341 #endif // DOXYGEN_NO_DISPATCH
0342 
0343 
0344 /*!
0345 \brief Generic geometry template manipulator class, takes corresponding output class from traits class
0346 \ingroup svg
0347 \details Stream manipulator, streams geometry classes as SVG (Scalable Vector Graphics)
0348 */
0349 template <typename Geometry>
0350 class svg_manipulator
0351 {
0352 public:
0353 
0354     inline svg_manipulator(Geometry const& g, std::string const& style, double size)
0355         : m_geometry(g)
0356         , m_style(style)
0357         , m_size(size)
0358     {}
0359 
0360     template <typename Char, typename Traits>
0361     inline friend std::basic_ostream<Char, Traits>& operator<<(
0362                     std::basic_ostream<Char, Traits>& os, svg_manipulator const& m)
0363     {
0364         dispatch::devarianted_svg<Geometry>::apply(os,
0365                                                    m.m_geometry,
0366                                                    m.m_style,
0367                                                    m.m_size);
0368         os.flush();
0369         return os;
0370     }
0371 
0372 private:
0373     Geometry const& m_geometry;
0374     std::string const& m_style;
0375     double m_size;
0376 };
0377 
0378 /*!
0379 \brief Manipulator to stream geometries as SVG
0380 \tparam Geometry \tparam_geometry
0381 \param geometry \param_geometry
0382 \param style String containing verbatim SVG style information
0383 \param size Optional size (used for SVG points) in SVG pixels. For linestrings,
0384     specify linewidth in the SVG style information
0385 \ingroup svg
0386 */
0387 template <typename Geometry>
0388 inline svg_manipulator<Geometry> svg(Geometry const& geometry,
0389             std::string const& style, double size = -1.0)
0390 {
0391     concepts::check<Geometry const>();
0392 
0393     return svg_manipulator<Geometry>(geometry, style, size);
0394 }
0395 
0396 }} // namespace boost::geometry
0397 
0398 #endif // BOOST_GEOMETRY_IO_SVG_WRITE_HPP