Back to home page

EIC code displayed by LXR

 
 

    


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

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         typedef typename coordinate_type<Box>::type ct;
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         typedef typename coordinate_type<Segment>::type ct;
0096         ct x1 = geometry::get<0, 0>(segment);
0097         ct y1 = geometry::get<0, 1>(segment);
0098         ct x2 = geometry::get<1, 0>(segment);
0099         ct 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         typedef typename geometry::ring_type<Polygon>::type ring_type;
0143 
0144         bool first = true;
0145         os << "<g fill-rule=\"evenodd\"><path d=\"";
0146 
0147         ring_type const& ring = geometry::exterior_ring(polygon);
0148         for (auto it = boost::begin(ring); it != boost::end(ring); ++it, first = false)
0149         {
0150             os << (first ? "M" : " L") << " "
0151                 << geometry::get<0>(*it)
0152                 << ","
0153                 << geometry::get<1>(*it);
0154         }
0155 
0156         // Inner rings:
0157         {
0158             auto const& rings = interior_rings(polygon);
0159             for (auto rit = boost::begin(rings); rit != boost::end(rings); ++rit)
0160             {
0161                 first = true;
0162                 for (auto it = boost::begin(*rit); it != boost::end(*rit); ++it, first = false)
0163                 {
0164                     os << (first ? "M" : " L") << " "
0165                         << geometry::get<0>(*it)
0166                         << ","
0167                         << geometry::get<1>(*it);
0168                 }
0169             }
0170         }
0171         os << " z \" style=\"" << style << "\"/></g>";
0172 
0173     }
0174 };
0175 
0176 
0177 
0178 struct prefix_linestring
0179 {
0180     static inline const char* prefix() { return "polyline"; }
0181     static inline const char* style() { return ";fill:none"; }
0182 };
0183 
0184 
0185 struct prefix_ring
0186 {
0187     static inline const char* prefix() { return "polygon"; }
0188     static inline const char* style() { return ""; }
0189 };
0190 
0191 
0192 template <typename MultiGeometry, typename Policy>
0193 struct svg_multi
0194 {
0195     template <typename Char, typename Traits>
0196     static inline void apply(std::basic_ostream<Char, Traits>& os,
0197         MultiGeometry const& multi, std::string const& style, double size)
0198     {
0199         for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
0200         {
0201             Policy::apply(os, *it, style, size);
0202         }
0203     }
0204 
0205 };
0206 
0207 
0208 }} // namespace detail::svg
0209 #endif // DOXYGEN_NO_DETAIL
0210 
0211 
0212 #ifndef DOXYGEN_NO_DISPATCH
0213 namespace dispatch
0214 {
0215 
0216 /*!
0217 \brief Dispatching base struct for SVG streaming, specialized below per geometry type
0218 \details Specializations should implement a static method "stream" to stream a geometry
0219 The static method should have the signature:
0220 
0221 template <typename Char, typename Traits>
0222 static inline void apply(std::basic_ostream<Char, Traits>& os, G const& geometry)
0223 */
0224 template <typename Geometry, typename Tag = typename tag<Geometry>::type>
0225 struct svg
0226 {
0227     BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
0228         "Not or not yet implemented for this Geometry type.",
0229         Geometry, Tag);
0230 };
0231 
0232 template <typename Point>
0233 struct svg<Point, point_tag> : detail::svg::svg_point<Point> {};
0234 
0235 template <typename Segment>
0236 struct svg<Segment, segment_tag> : detail::svg::svg_segment<Segment> {};
0237 
0238 template <typename Box>
0239 struct svg<Box, box_tag> : detail::svg::svg_box<Box> {};
0240 
0241 template <typename Linestring>
0242 struct svg<Linestring, linestring_tag>
0243     : detail::svg::svg_range<Linestring, detail::svg::prefix_linestring> {};
0244 
0245 template <typename Ring>
0246 struct svg<Ring, ring_tag>
0247     : detail::svg::svg_range<Ring, detail::svg::prefix_ring> {};
0248 
0249 template <typename Polygon>
0250 struct svg<Polygon, polygon_tag>
0251     : detail::svg::svg_poly<Polygon> {};
0252 
0253 template <typename MultiPoint>
0254 struct svg<MultiPoint, multi_point_tag>
0255     : detail::svg::svg_multi
0256         <
0257             MultiPoint,
0258             detail::svg::svg_point
0259                 <
0260                     typename boost::range_value<MultiPoint>::type
0261                 >
0262 
0263         >
0264 {};
0265 
0266 template <typename MultiLinestring>
0267 struct svg<MultiLinestring, multi_linestring_tag>
0268     : detail::svg::svg_multi
0269         <
0270             MultiLinestring,
0271             detail::svg::svg_range
0272                 <
0273                     typename boost::range_value<MultiLinestring>::type,
0274                     detail::svg::prefix_linestring
0275                 >
0276 
0277         >
0278 {};
0279 
0280 template <typename MultiPolygon>
0281 struct svg<MultiPolygon, multi_polygon_tag>
0282     : detail::svg::svg_multi
0283         <
0284             MultiPolygon,
0285             detail::svg::svg_poly
0286                 <
0287                     typename boost::range_value<MultiPolygon>::type
0288                 >
0289 
0290         >
0291 {};
0292 
0293 
0294 template <typename Geometry>
0295 struct devarianted_svg
0296 {
0297     template <typename OutputStream>
0298     static inline void apply(OutputStream& os,
0299                              Geometry const& geometry,
0300                              std::string const& style,
0301                              double size)
0302     {
0303         svg<Geometry>::apply(os, geometry, style, size);
0304     }
0305 };
0306 
0307 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
0308 struct devarianted_svg<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
0309 {
0310     template <typename OutputStream>
0311     struct visitor: static_visitor<void>
0312     {
0313         OutputStream& m_os;
0314         std::string const& m_style;
0315         double m_size;
0316 
0317         visitor(OutputStream& os, std::string const& style, double size)
0318             : m_os(os)
0319             , m_style(style)
0320             , m_size(size)
0321         {}
0322 
0323         template <typename Geometry>
0324         inline void operator()(Geometry const& geometry) const
0325         {
0326             devarianted_svg<Geometry>::apply(m_os, geometry, m_style, m_size);
0327         }
0328     };
0329 
0330     template <typename OutputStream>
0331     static inline void apply(
0332         OutputStream& os,
0333         variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
0334         std::string const& style,
0335         double size
0336     )
0337     {
0338         boost::apply_visitor(visitor<OutputStream>(os, style, size), geometry);
0339     }
0340 };
0341 
0342 } // namespace dispatch
0343 #endif // DOXYGEN_NO_DISPATCH
0344 
0345 
0346 /*!
0347 \brief Generic geometry template manipulator class, takes corresponding output class from traits class
0348 \ingroup svg
0349 \details Stream manipulator, streams geometry classes as SVG (Scalable Vector Graphics)
0350 */
0351 template <typename Geometry>
0352 class svg_manipulator
0353 {
0354 public:
0355 
0356     inline svg_manipulator(Geometry const& g, std::string const& style, double size)
0357         : m_geometry(g)
0358         , m_style(style)
0359         , m_size(size)
0360     {}
0361 
0362     template <typename Char, typename Traits>
0363     inline friend std::basic_ostream<Char, Traits>& operator<<(
0364                     std::basic_ostream<Char, Traits>& os, svg_manipulator const& m)
0365     {
0366         dispatch::devarianted_svg<Geometry>::apply(os,
0367                                                    m.m_geometry,
0368                                                    m.m_style,
0369                                                    m.m_size);
0370         os.flush();
0371         return os;
0372     }
0373 
0374 private:
0375     Geometry const& m_geometry;
0376     std::string const& m_style;
0377     double m_size;
0378 };
0379 
0380 /*!
0381 \brief Manipulator to stream geometries as SVG
0382 \tparam Geometry \tparam_geometry
0383 \param geometry \param_geometry
0384 \param style String containing verbatim SVG style information
0385 \param size Optional size (used for SVG points) in SVG pixels. For linestrings,
0386     specify linewidth in the SVG style information
0387 \ingroup svg
0388 */
0389 template <typename Geometry>
0390 inline svg_manipulator<Geometry> svg(Geometry const& geometry,
0391             std::string const& style, double size = -1.0)
0392 {
0393     concepts::check<Geometry const>();
0394 
0395     return svg_manipulator<Geometry>(geometry, style, size);
0396 }
0397 
0398 }} // namespace boost::geometry
0399 
0400 #endif // BOOST_GEOMETRY_IO_SVG_WRITE_HPP