]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/geometry/include/boost/geometry/io/svg/write.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / geometry / include / boost / geometry / io / svg / write.hpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
3// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
4// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
5
6// This file was modified by Oracle on 2016.
7// Modifications copyright (c) 2016, Oracle and/or its affiliates.
8
9// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10
11// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
12// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
13
14// Use, modification and distribution is subject to the Boost Software License,
15// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
16// http://www.boost.org/LICENSE_1_0.txt)
17
18#ifndef BOOST_GEOMETRY_IO_SVG_WRITE_HPP
19#define BOOST_GEOMETRY_IO_SVG_WRITE_HPP
20
21#include <ostream>
22#include <string>
23
24#include <boost/config.hpp>
25#include <boost/mpl/assert.hpp>
26#include <boost/range.hpp>
27
28#include <boost/variant/apply_visitor.hpp>
29#include <boost/variant/static_visitor.hpp>
30#include <boost/variant/variant_fwd.hpp>
31
32#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
33
34#include <boost/geometry/core/exterior_ring.hpp>
35#include <boost/geometry/core/interior_rings.hpp>
36#include <boost/geometry/core/ring_type.hpp>
37
38#include <boost/geometry/geometries/concepts/check.hpp>
39
40
41namespace boost { namespace geometry
42{
43
44
45#ifndef DOXYGEN_NO_DETAIL
46namespace detail { namespace svg
47{
48
49
50template <typename Point>
51struct svg_point
52{
53 template <typename Char, typename Traits>
54 static inline void apply(std::basic_ostream<Char, Traits>& os,
55 Point const& p, std::string const& style, double size)
56 {
57 os << "<circle cx=\"" << geometry::get<0>(p)
58 << "\" cy=\"" << geometry::get<1>(p)
59 << "\" r=\"" << (size < 0 ? 5 : size)
60 << "\" style=\"" << style << "\"/>";
61 }
62};
63
64
65template <typename Box>
66struct svg_box
67{
68 template <typename Char, typename Traits>
69 static inline void apply(std::basic_ostream<Char, Traits>& os,
70 Box const& box, std::string const& style, double)
71 {
72 // Prevent invisible boxes, making them >=1, using "max"
73 BOOST_USING_STD_MAX();
74
75 typedef typename coordinate_type<Box>::type ct;
76 ct x = geometry::get<geometry::min_corner, 0>(box);
77 ct y = geometry::get<geometry::min_corner, 1>(box);
78 ct width = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),
79 geometry::get<geometry::max_corner, 0>(box) - x);
80 ct height = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),
81 geometry::get<geometry::max_corner, 1>(box) - y);
82
83 os << "<rect x=\"" << x << "\" y=\"" << y
84 << "\" width=\"" << width << "\" height=\"" << height
85 << "\" style=\"" << style << "\"/>";
86 }
87};
88
89template <typename Segment>
90struct svg_segment
91{
92 template <typename Char, typename Traits>
93 static inline void apply(std::basic_ostream<Char, Traits>& os,
94 Segment const& segment, std::string const& style, double)
95 {
96 typedef typename coordinate_type<Segment>::type ct;
97 ct x1 = geometry::get<0, 0>(segment);
98 ct y1 = geometry::get<0, 1>(segment);
99 ct x2 = geometry::get<1, 0>(segment);
100 ct y2 = geometry::get<1, 1>(segment);
101
102 os << "<line x1=\"" << x1 << "\" y1=\"" << y1
103 << "\" x2=\"" << x2 << "\" y2=\"" << y2
104 << "\" style=\"" << style << "\"/>";
105 }
106};
107
108/*!
109\brief Stream ranges as SVG
110\note policy is used to select type (polyline/polygon)
111*/
112template <typename Range, typename Policy>
113struct svg_range
114{
115 template <typename Char, typename Traits>
116 static inline void apply(std::basic_ostream<Char, Traits>& os,
117 Range const& range, std::string const& style, double)
118 {
119 typedef typename boost::range_iterator<Range const>::type iterator;
120
121 bool first = true;
122
123 os << "<" << Policy::prefix() << " points=\"";
124
125 for (iterator it = boost::begin(range);
126 it != boost::end(range);
127 ++it, first = false)
128 {
129 os << (first ? "" : " " )
130 << geometry::get<0>(*it)
131 << ","
132 << geometry::get<1>(*it);
133 }
134 os << "\" style=\"" << style << Policy::style() << "\"/>";
135 }
136};
137
138
139
140template <typename Polygon>
141struct svg_poly
142{
143 template <typename Char, typename Traits>
144 static inline void apply(std::basic_ostream<Char, Traits>& os,
145 Polygon const& polygon, std::string const& style, double)
146 {
147 typedef typename geometry::ring_type<Polygon>::type ring_type;
148 typedef typename boost::range_iterator<ring_type const>::type iterator_type;
149
150 bool first = true;
151 os << "<g fill-rule=\"evenodd\"><path d=\"";
152
153 ring_type const& ring = geometry::exterior_ring(polygon);
154 for (iterator_type it = boost::begin(ring);
155 it != boost::end(ring);
156 ++it, first = false)
157 {
158 os << (first ? "M" : " L") << " "
159 << geometry::get<0>(*it)
160 << ","
161 << geometry::get<1>(*it);
162 }
163
164 // Inner rings:
165 {
166 typename interior_return_type<Polygon const>::type
167 rings = interior_rings(polygon);
168 for (typename detail::interior_iterator<Polygon const>::type
169 rit = boost::begin(rings); rit != boost::end(rings); ++rit)
170 {
171 first = true;
172 for (typename detail::interior_ring_iterator<Polygon const>::type
173 it = boost::begin(*rit); it != boost::end(*rit);
174 ++it, first = false)
175 {
176 os << (first ? "M" : " L") << " "
177 << geometry::get<0>(*it)
178 << ","
179 << geometry::get<1>(*it);
180 }
181 }
182 }
183 os << " z \" style=\"" << style << "\"/></g>";
184
185 }
186};
187
188
189
190struct prefix_linestring
191{
192 static inline const char* prefix() { return "polyline"; }
193 static inline const char* style() { return ";fill:none"; }
194};
195
196
197struct prefix_ring
198{
199 static inline const char* prefix() { return "polygon"; }
200 static inline const char* style() { return ""; }
201};
202
203
204template <typename MultiGeometry, typename Policy>
205struct svg_multi
206{
207 template <typename Char, typename Traits>
208 static inline void apply(std::basic_ostream<Char, Traits>& os,
209 MultiGeometry const& multi, std::string const& style, double size)
210 {
211 for (typename boost::range_iterator<MultiGeometry const>::type
212 it = boost::begin(multi);
213 it != boost::end(multi);
214 ++it)
215 {
216 Policy::apply(os, *it, style, size);
217 }
218
219 }
220
221};
222
223
224}} // namespace detail::svg
225#endif // DOXYGEN_NO_DETAIL
226
227
228#ifndef DOXYGEN_NO_DISPATCH
229namespace dispatch
230{
231
232/*!
233\brief Dispatching base struct for SVG streaming, specialized below per geometry type
234\details Specializations should implement a static method "stream" to stream a geometry
235The static method should have the signature:
236
237template <typename Char, typename Traits>
238static inline void apply(std::basic_ostream<Char, Traits>& os, G const& geometry)
239*/
240template <typename Geometry, typename Tag = typename tag<Geometry>::type>
241struct svg
242{
243 BOOST_MPL_ASSERT_MSG
244 (
245 false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
246 , (Geometry)
247 );
248};
249
250template <typename Point>
251struct svg<Point, point_tag> : detail::svg::svg_point<Point> {};
252
253template <typename Segment>
254struct svg<Segment, segment_tag> : detail::svg::svg_segment<Segment> {};
255
256template <typename Box>
257struct svg<Box, box_tag> : detail::svg::svg_box<Box> {};
258
259template <typename Linestring>
260struct svg<Linestring, linestring_tag>
261 : detail::svg::svg_range<Linestring, detail::svg::prefix_linestring> {};
262
263template <typename Ring>
264struct svg<Ring, ring_tag>
265 : detail::svg::svg_range<Ring, detail::svg::prefix_ring> {};
266
267template <typename Polygon>
268struct svg<Polygon, polygon_tag>
269 : detail::svg::svg_poly<Polygon> {};
270
271template <typename MultiPoint>
272struct svg<MultiPoint, multi_point_tag>
273 : detail::svg::svg_multi
274 <
275 MultiPoint,
276 detail::svg::svg_point
277 <
278 typename boost::range_value<MultiPoint>::type
279 >
280
281 >
282{};
283
284template <typename MultiLinestring>
285struct svg<MultiLinestring, multi_linestring_tag>
286 : detail::svg::svg_multi
287 <
288 MultiLinestring,
289 detail::svg::svg_range
290 <
291 typename boost::range_value<MultiLinestring>::type,
292 detail::svg::prefix_linestring
293 >
294
295 >
296{};
297
298template <typename MultiPolygon>
299struct svg<MultiPolygon, multi_polygon_tag>
300 : detail::svg::svg_multi
301 <
302 MultiPolygon,
303 detail::svg::svg_poly
304 <
305 typename boost::range_value<MultiPolygon>::type
306 >
307
308 >
309{};
310
311
312template <typename Geometry>
313struct devarianted_svg
314{
315 template <typename OutputStream>
316 static inline void apply(OutputStream& os,
317 Geometry const& geometry,
318 std::string const& style,
319 double size)
320 {
321 svg<Geometry>::apply(os, geometry, style, size);
322 }
323};
324
325template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
326struct devarianted_svg<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
327{
328 template <typename OutputStream>
329 struct visitor: static_visitor<void>
330 {
331 OutputStream& m_os;
332 std::string const& m_style;
333 double m_size;
334
335 visitor(OutputStream& os, std::string const& style, double size)
336 : m_os(os)
337 , m_style(style)
338 , m_size(size)
339 {}
340
341 template <typename Geometry>
342 inline void operator()(Geometry const& geometry) const
343 {
344 devarianted_svg<Geometry>::apply(m_os, geometry, m_style, m_size);
345 }
346 };
347
348 template <typename OutputStream>
349 static inline void apply(
350 OutputStream& os,
351 variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
352 std::string const& style,
353 double size
354 )
355 {
356 boost::apply_visitor(visitor<OutputStream>(os, style, size), geometry);
357 }
358};
359
360} // namespace dispatch
361#endif // DOXYGEN_NO_DISPATCH
362
363
364/*!
365\brief Generic geometry template manipulator class, takes corresponding output class from traits class
366\ingroup svg
367\details Stream manipulator, streams geometry classes as SVG (Scalable Vector Graphics)
368*/
369template <typename Geometry>
370class svg_manipulator
371{
372public:
373
374 inline svg_manipulator(Geometry const& g, std::string const& style, double size)
375 : m_geometry(g)
376 , m_style(style)
377 , m_size(size)
378 {}
379
380 template <typename Char, typename Traits>
381 inline friend std::basic_ostream<Char, Traits>& operator<<(
382 std::basic_ostream<Char, Traits>& os, svg_manipulator const& m)
383 {
384 dispatch::devarianted_svg<Geometry>::apply(os,
385 m.m_geometry,
386 m.m_style,
387 m.m_size);
388 os.flush();
389 return os;
390 }
391
392private:
393 Geometry const& m_geometry;
394 std::string const& m_style;
395 double m_size;
396};
397
398/*!
399\brief Manipulator to stream geometries as SVG
400\tparam Geometry \tparam_geometry
401\param geometry \param_geometry
402\param style String containing verbatim SVG style information
403\param size Optional size (used for SVG points) in SVG pixels. For linestrings,
404 specify linewidth in the SVG style information
405\ingroup svg
406*/
407template <typename Geometry>
408inline svg_manipulator<Geometry> svg(Geometry const& geometry,
409 std::string const& style, double size = -1.0)
410{
411 concepts::check<Geometry const>();
412
413 return svg_manipulator<Geometry>(geometry, style, size);
414}
415
416}} // namespace boost::geometry
417
418#endif // BOOST_GEOMETRY_IO_SVG_WRITE_HPP