1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
6 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
7 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
9 // Use, modification and distribution is subject to the Boost Software License,
10 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
13 #ifndef BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP
14 #define BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP
19 #include <boost/config.hpp>
20 #include <boost/mpl/assert.hpp>
21 #include <boost/range.hpp>
23 #include <boost/geometry/algorithms/detail/interior_iterator.hpp>
25 #include <boost/geometry/core/exterior_ring.hpp>
26 #include <boost/geometry/core/interior_rings.hpp>
27 #include <boost/geometry/core/ring_type.hpp>
29 #include <boost/geometry/geometries/concepts/check.hpp>
32 namespace boost { namespace geometry
36 #ifndef DOXYGEN_NO_DETAIL
37 namespace detail { namespace svg
41 template <typename Point>
44 template <typename Char, typename Traits>
45 static inline void apply(std::basic_ostream<Char, Traits>& os,
46 Point const& p, std::string const& style, int size)
48 os << "<circle cx=\"" << geometry::get<0>(p)
49 << "\" cy=\"" << geometry::get<1>(p)
50 << "\" r=\"" << (size < 0 ? 5 : size)
51 << "\" style=\"" << style << "\"/>";
56 template <typename Box>
59 template <typename Char, typename Traits>
60 static inline void apply(std::basic_ostream<Char, Traits>& os,
61 Box const& box, std::string const& style, int )
63 // Prevent invisible boxes, making them >=1, using "max"
64 BOOST_USING_STD_MAX();
66 typedef typename coordinate_type<Box>::type ct;
67 ct x = geometry::get<geometry::min_corner, 0>(box);
68 ct y = geometry::get<geometry::min_corner, 1>(box);
69 ct width = max BOOST_PREVENT_MACRO_SUBSTITUTION(1,
70 geometry::get<geometry::max_corner, 0>(box) - x);
71 ct height = max BOOST_PREVENT_MACRO_SUBSTITUTION (1,
72 geometry::get<geometry::max_corner, 1>(box) - y);
74 os << "<rect x=\"" << x << "\" y=\"" << y
75 << "\" width=\"" << width << "\" height=\"" << height
76 << "\" style=\"" << style << "\"/>";
82 \brief Stream ranges as SVG
83 \note policy is used to select type (polyline/polygon)
85 template <typename Range, typename Policy>
88 template <typename Char, typename Traits>
89 static inline void apply(std::basic_ostream<Char, Traits>& os,
90 Range const& range, std::string const& style, int )
92 typedef typename boost::range_iterator<Range const>::type iterator;
96 os << "<" << Policy::prefix() << " points=\"";
98 for (iterator it = boost::begin(range);
99 it != boost::end(range);
102 os << (first ? "" : " " )
103 << geometry::get<0>(*it)
105 << geometry::get<1>(*it);
107 os << "\" style=\"" << style << Policy::style() << "\"/>";
113 template <typename Polygon>
116 template <typename Char, typename Traits>
117 static inline void apply(std::basic_ostream<Char, Traits>& os,
118 Polygon const& polygon, std::string const& style, int )
120 typedef typename geometry::ring_type<Polygon>::type ring_type;
121 typedef typename boost::range_iterator<ring_type const>::type iterator_type;
124 os << "<g fill-rule=\"evenodd\"><path d=\"";
126 ring_type const& ring = geometry::exterior_ring(polygon);
127 for (iterator_type it = boost::begin(ring);
128 it != boost::end(ring);
131 os << (first ? "M" : " L") << " "
132 << geometry::get<0>(*it)
134 << geometry::get<1>(*it);
139 typename interior_return_type<Polygon const>::type
140 rings = interior_rings(polygon);
141 for (typename detail::interior_iterator<Polygon const>::type
142 rit = boost::begin(rings); rit != boost::end(rings); ++rit)
145 for (typename detail::interior_ring_iterator<Polygon const>::type
146 it = boost::begin(*rit); it != boost::end(*rit);
149 os << (first ? "M" : " L") << " "
150 << geometry::get<0>(*it)
152 << geometry::get<1>(*it);
156 os << " z \" style=\"" << style << "\"/></g>";
163 struct prefix_linestring
165 static inline const char* prefix() { return "polyline"; }
166 static inline const char* style() { return ";fill:none"; }
172 static inline const char* prefix() { return "polygon"; }
173 static inline const char* style() { return ""; }
178 }} // namespace detail::svg
179 #endif // DOXYGEN_NO_DETAIL
182 #ifndef DOXYGEN_NO_DISPATCH
187 \brief Dispatching base struct for SVG streaming, specialized below per geometry type
188 \details Specializations should implement a static method "stream" to stream a geometry
189 The static method should have the signature:
191 template <typename Char, typename Traits>
192 static inline void apply(std::basic_ostream<Char, Traits>& os, G const& geometry)
194 template <typename GeometryTag, typename Geometry>
199 false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
204 template <typename Point>
205 struct svg<point_tag, Point> : detail::svg::svg_point<Point> {};
207 template <typename Box>
208 struct svg<box_tag, Box> : detail::svg::svg_box<Box> {};
210 template <typename Linestring>
211 struct svg<linestring_tag, Linestring>
212 : detail::svg::svg_range<Linestring, detail::svg::prefix_linestring> {};
214 template <typename Ring>
215 struct svg<ring_tag, Ring>
216 : detail::svg::svg_range<Ring, detail::svg::prefix_ring> {};
218 template <typename Polygon>
219 struct svg<polygon_tag, Polygon>
220 : detail::svg::svg_poly<Polygon> {};
222 } // namespace dispatch
223 #endif // DOXYGEN_NO_DISPATCH
227 \brief Generic geometry template manipulator class, takes corresponding output class from traits class
229 \details Stream manipulator, streams geometry classes as SVG (Scalable Vector Graphics)
231 template <typename G>
232 class svg_manipulator
236 inline svg_manipulator(G const& g, std::string const& style, int size)
242 template <typename Char, typename Traits>
243 inline friend std::basic_ostream<Char, Traits>& operator<<(
244 std::basic_ostream<Char, Traits>& os, svg_manipulator const& m)
248 typename tag<G>::type, G
249 >::apply(os, m.m_geometry, m.m_style, m.m_size);
256 std::string const& m_style;
261 \brief Manipulator to stream geometries as SVG
262 \tparam Geometry \tparam_geometry
263 \param geometry \param_geometry
264 \param style String containing verbatim SVG style information
265 \param size Optional size (used for SVG points) in SVG pixels. For linestrings,
266 specify linewidth in the SVG style information
269 template <typename Geometry>
270 inline svg_manipulator<Geometry> svg(Geometry const& geometry, std::string const& style, int size = -1)
272 concept::check<Geometry const>();
274 return svg_manipulator<Geometry>(geometry, style, size);
277 }} // namespace boost::geometry
279 #endif // BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP