]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/geometry/io/svg/write.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / geometry / io / svg / write.hpp
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
41 namespace boost { namespace geometry
42 {
43
44
45 #ifndef DOXYGEN_NO_DETAIL
46 namespace detail { namespace svg
47 {
48
49
50 template <typename Point>
51 struct 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
65 template <typename Box>
66 struct 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
89 template <typename Segment>
90 struct 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 */
112 template <typename Range, typename Policy>
113 struct 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
140 template <typename Polygon>
141 struct 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
190 struct prefix_linestring
191 {
192 static inline const char* prefix() { return "polyline"; }
193 static inline const char* style() { return ";fill:none"; }
194 };
195
196
197 struct prefix_ring
198 {
199 static inline const char* prefix() { return "polygon"; }
200 static inline const char* style() { return ""; }
201 };
202
203
204 template <typename MultiGeometry, typename Policy>
205 struct 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
229 namespace 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
235 The static method should have the signature:
236
237 template <typename Char, typename Traits>
238 static inline void apply(std::basic_ostream<Char, Traits>& os, G const& geometry)
239 */
240 template <typename Geometry, typename Tag = typename tag<Geometry>::type>
241 struct svg
242 {
243 BOOST_MPL_ASSERT_MSG
244 (
245 false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
246 , (Geometry)
247 );
248 };
249
250 template <typename Point>
251 struct svg<Point, point_tag> : detail::svg::svg_point<Point> {};
252
253 template <typename Segment>
254 struct svg<Segment, segment_tag> : detail::svg::svg_segment<Segment> {};
255
256 template <typename Box>
257 struct svg<Box, box_tag> : detail::svg::svg_box<Box> {};
258
259 template <typename Linestring>
260 struct svg<Linestring, linestring_tag>
261 : detail::svg::svg_range<Linestring, detail::svg::prefix_linestring> {};
262
263 template <typename Ring>
264 struct svg<Ring, ring_tag>
265 : detail::svg::svg_range<Ring, detail::svg::prefix_ring> {};
266
267 template <typename Polygon>
268 struct svg<Polygon, polygon_tag>
269 : detail::svg::svg_poly<Polygon> {};
270
271 template <typename MultiPoint>
272 struct 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
284 template <typename MultiLinestring>
285 struct 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
298 template <typename MultiPolygon>
299 struct 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
312 template <typename Geometry>
313 struct 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
325 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
326 struct 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 */
369 template <typename Geometry>
370 class svg_manipulator
371 {
372 public:
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
392 private:
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 */
407 template <typename Geometry>
408 inline 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