]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/geometry/include/boost/geometry/io/svg/svg_mapper.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / geometry / include / boost / geometry / io / svg / svg_mapper.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2009-2015 Barend Gehrels, Amsterdam, the Netherlands.
4
5 // This file was modified by Oracle on 2015, 2016.
6 // Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
7
8 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
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_MAPPER_HPP
19 #define BOOST_GEOMETRY_IO_SVG_MAPPER_HPP
20
21 #include <cstdio>
22
23 #include <vector>
24
25 #include <boost/config.hpp>
26 #include <boost/mpl/assert.hpp>
27 #include <boost/noncopyable.hpp>
28 #include <boost/scoped_ptr.hpp>
29 #include <boost/type_traits/is_same.hpp>
30 #include <boost/type_traits/remove_const.hpp>
31
32 #include <boost/algorithm/string/split.hpp>
33 #include <boost/algorithm/string/classification.hpp>
34
35
36 #include <boost/geometry/core/tags.hpp>
37 #include <boost/geometry/core/tag_cast.hpp>
38
39 #include <boost/geometry/algorithms/envelope.hpp>
40 #include <boost/geometry/algorithms/expand.hpp>
41 #include <boost/geometry/algorithms/is_empty.hpp>
42 #include <boost/geometry/algorithms/transform.hpp>
43 #include <boost/geometry/strategies/transform/map_transformer.hpp>
44 #include <boost/geometry/views/segment_view.hpp>
45
46 #include <boost/geometry/io/svg/write.hpp>
47
48 // Helper geometries (all points are transformed to svg-points)
49 #include <boost/geometry/geometries/geometries.hpp>
50
51
52 namespace boost { namespace geometry
53 {
54
55
56 #ifndef DOXYGEN_NO_DISPATCH
57 namespace dispatch
58 {
59
60
61 template <typename GeometryTag, typename Geometry, typename SvgPoint>
62 struct svg_map
63 {
64 BOOST_MPL_ASSERT_MSG
65 (
66 false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
67 , (Geometry)
68 );
69 };
70
71
72 template <typename Point, typename SvgPoint>
73 struct svg_map<point_tag, Point, SvgPoint>
74 {
75 template <typename TransformStrategy>
76 static inline void apply(std::ostream& stream,
77 std::string const& style, double size,
78 Point const& point, TransformStrategy const& strategy)
79 {
80 SvgPoint ipoint;
81 geometry::transform(point, ipoint, strategy);
82 stream << geometry::svg(ipoint, style, size) << std::endl;
83 }
84 };
85
86 template <typename BoxSeg1, typename BoxSeg2, typename SvgPoint>
87 struct svg_map_box_seg
88 {
89 template <typename TransformStrategy>
90 static inline void apply(std::ostream& stream,
91 std::string const& style, double size,
92 BoxSeg1 const& box_seg, TransformStrategy const& strategy)
93 {
94 BoxSeg2 ibox_seg;
95
96 // Fix bug in gcc compiler warning for possible uninitialization
97 #if defined(BOOST_GCC)
98 geometry::assign_zero(ibox_seg);
99 #endif
100 geometry::transform(box_seg, ibox_seg, strategy);
101
102 stream << geometry::svg(ibox_seg, style, size) << std::endl;
103 }
104 };
105
106 template <typename Box, typename SvgPoint>
107 struct svg_map<box_tag, Box, SvgPoint>
108 : svg_map_box_seg<Box, model::box<SvgPoint>, SvgPoint>
109 {};
110
111 template <typename Segment, typename SvgPoint>
112 struct svg_map<segment_tag, Segment, SvgPoint>
113 : svg_map_box_seg<Segment, model::segment<SvgPoint>, SvgPoint>
114 {};
115
116
117 template <typename Range1, typename Range2, typename SvgPoint>
118 struct svg_map_range
119 {
120 template <typename TransformStrategy>
121 static inline void apply(std::ostream& stream,
122 std::string const& style, double size,
123 Range1 const& range, TransformStrategy const& strategy)
124 {
125 Range2 irange;
126 geometry::transform(range, irange, strategy);
127 stream << geometry::svg(irange, style, size) << std::endl;
128 }
129 };
130
131 template <typename Ring, typename SvgPoint>
132 struct svg_map<ring_tag, Ring, SvgPoint>
133 : svg_map_range<Ring, model::ring<SvgPoint>, SvgPoint>
134 {};
135
136
137 template <typename Linestring, typename SvgPoint>
138 struct svg_map<linestring_tag, Linestring, SvgPoint>
139 : svg_map_range<Linestring, model::linestring<SvgPoint>, SvgPoint>
140 {};
141
142
143 template <typename Polygon, typename SvgPoint>
144 struct svg_map<polygon_tag, Polygon, SvgPoint>
145 {
146 template <typename TransformStrategy>
147 static inline void apply(std::ostream& stream,
148 std::string const& style, double size,
149 Polygon const& polygon, TransformStrategy const& strategy)
150 {
151 model::polygon<SvgPoint> ipoly;
152 geometry::transform(polygon, ipoly, strategy);
153 stream << geometry::svg(ipoly, style, size) << std::endl;
154 }
155 };
156
157
158 template <typename Multi, typename SvgPoint>
159 struct svg_map<multi_tag, Multi, SvgPoint>
160 {
161 typedef typename single_tag_of
162 <
163 typename geometry::tag<Multi>::type
164 >::type stag;
165
166 template <typename TransformStrategy>
167 static inline void apply(std::ostream& stream,
168 std::string const& style, double size,
169 Multi const& multi, TransformStrategy const& strategy)
170 {
171 for (typename boost::range_iterator<Multi const>::type it
172 = boost::begin(multi);
173 it != boost::end(multi);
174 ++it)
175 {
176 svg_map
177 <
178 stag,
179 typename boost::range_value<Multi>::type,
180 SvgPoint
181 >::apply(stream, style, size, *it, strategy);
182 }
183 }
184 };
185
186
187 template <typename SvgPoint, typename Geometry>
188 struct devarianted_svg_map
189 {
190 template <typename TransformStrategy>
191 static inline void apply(std::ostream& stream,
192 std::string const& style,
193 double size,
194 Geometry const& geometry,
195 TransformStrategy const& strategy)
196 {
197 svg_map
198 <
199 typename tag_cast
200 <
201 typename tag<Geometry>::type,
202 multi_tag
203 >::type,
204 typename boost::remove_const<Geometry>::type,
205 SvgPoint
206 >::apply(stream, style, size, geometry, strategy);
207 }
208 };
209
210 template <typename SvgPoint, BOOST_VARIANT_ENUM_PARAMS(typename T)>
211 struct devarianted_svg_map<SvgPoint, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
212 {
213 template <typename TransformStrategy>
214 struct visitor: static_visitor<void>
215 {
216 std::ostream& m_os;
217 std::string const& m_style;
218 double m_size;
219 TransformStrategy const& m_strategy;
220
221 visitor(std::ostream& os,
222 std::string const& style,
223 double size,
224 TransformStrategy const& strategy)
225 : m_os(os)
226 , m_style(style)
227 , m_size(size)
228 , m_strategy(strategy)
229 {}
230
231 template <typename Geometry>
232 inline void operator()(Geometry const& geometry) const
233 {
234 devarianted_svg_map<SvgPoint, Geometry>::apply(m_os, m_style, m_size, geometry, m_strategy);
235 }
236 };
237
238 template <typename TransformStrategy>
239 static inline void apply(std::ostream& stream,
240 std::string const& style,
241 double size,
242 variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
243 TransformStrategy const& strategy)
244 {
245 boost::apply_visitor(visitor<TransformStrategy>(stream, style, size, strategy), geometry);
246 }
247 };
248
249
250 } // namespace dispatch
251 #endif
252
253
254 template <typename SvgPoint, typename Geometry, typename TransformStrategy>
255 inline void svg_map(std::ostream& stream,
256 std::string const& style, double size,
257 Geometry const& geometry, TransformStrategy const& strategy)
258 {
259 dispatch::devarianted_svg_map<SvgPoint, Geometry>::apply(stream,
260 style, size, geometry, strategy);
261 }
262
263
264 /*!
265 \brief Helper class to create SVG maps
266 \tparam Point Point type, for input geometries.
267 \tparam SameScale Boolean flag indicating if horizontal and vertical scale should
268 be the same. The default value is true
269 \tparam SvgCoordinateType Coordinate type of SVG points. SVG is capable to
270 use floating point coordinates. Therefore the default value is double
271 \ingroup svg
272
273 \qbk{[include reference/io/svg.qbk]}
274 */
275 template
276 <
277 typename Point,
278 bool SameScale = true,
279 typename SvgCoordinateType = double
280 >
281 class svg_mapper : boost::noncopyable
282 {
283 typedef model::point<SvgCoordinateType, 2, cs::cartesian> svg_point_type;
284
285 typedef typename geometry::select_most_precise
286 <
287 typename coordinate_type<Point>::type,
288 double
289 >::type calculation_type;
290
291 typedef strategy::transform::map_transformer
292 <
293 calculation_type,
294 geometry::dimension<Point>::type::value,
295 geometry::dimension<Point>::type::value,
296 true,
297 SameScale
298 > transformer_type;
299
300 model::box<Point> m_bounding_box;
301 boost::scoped_ptr<transformer_type> m_matrix;
302 std::ostream& m_stream;
303 SvgCoordinateType m_width, m_height;
304 std::string m_width_height; // for <svg> tag only, defaults to 2x 100%
305
306 void init_matrix()
307 {
308 if (! m_matrix)
309 {
310 m_matrix.reset(new transformer_type(m_bounding_box,
311 m_width, m_height));
312
313
314 m_stream << "<?xml version=\"1.0\" standalone=\"no\"?>"
315 << std::endl
316 << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\""
317 << std::endl
318 << "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">"
319 << std::endl
320 << "<svg " << m_width_height << " version=\"1.1\""
321 << std::endl
322 << "xmlns=\"http://www.w3.org/2000/svg\""
323 << std::endl
324 << "xmlns:xlink=\"http://www.w3.org/1999/xlink\""
325 << ">"
326 << std::endl;
327 }
328 }
329
330 public :
331
332 /*!
333 \brief Constructor, initializing the SVG map. Opens and initializes the SVG.
334 Should be called explicitly.
335 \param stream Output stream, should be a stream already open
336 \param width Width of the SVG map (in SVG pixels)
337 \param height Height of the SVG map (in SVG pixels)
338 \param width_height Optional information to increase width and/or height
339 */
340 svg_mapper(std::ostream& stream
341 , SvgCoordinateType width
342 , SvgCoordinateType height
343 , std::string const& width_height = "width=\"100%\" height=\"100%\"")
344 : m_stream(stream)
345 , m_width(width)
346 , m_height(height)
347 , m_width_height(width_height)
348 {
349 assign_inverse(m_bounding_box);
350 }
351
352 /*!
353 \brief Destructor, called automatically. Closes the SVG by streaming <\/svg>
354 */
355 virtual ~svg_mapper()
356 {
357 m_stream << "</svg>" << std::endl;
358 }
359
360 /*!
361 \brief Adds a geometry to the transformation matrix. After doing this,
362 the specified geometry can be mapped fully into the SVG map
363 \tparam Geometry \tparam_geometry
364 \param geometry \param_geometry
365 */
366 template <typename Geometry>
367 void add(Geometry const& geometry)
368 {
369 if (! geometry::is_empty(geometry))
370 {
371 expand(m_bounding_box,
372 return_envelope
373 <
374 model::box<Point>
375 >(geometry));
376 }
377 }
378
379 /*!
380 \brief Maps a geometry into the SVG map using the specified style
381 \tparam Geometry \tparam_geometry
382 \param geometry \param_geometry
383 \param style String containing verbatim SVG style information
384 \param size Optional size (used for SVG points) in SVG pixels. For linestrings,
385 specify linewidth in the SVG style information
386 */
387 template <typename Geometry>
388 void map(Geometry const& geometry, std::string const& style,
389 double size = -1.0)
390 {
391 init_matrix();
392 svg_map<svg_point_type>(m_stream, style, size, geometry, *m_matrix);
393 }
394
395 /*!
396 \brief Adds a text to the SVG map
397 \tparam TextPoint \tparam_point
398 \param point Location of the text (in map units)
399 \param s The text itself
400 \param style String containing verbatim SVG style information, of the text
401 \param offset_x Offset in SVG pixels, defaults to 0
402 \param offset_y Offset in SVG pixels, defaults to 0
403 \param lineheight Line height in SVG pixels, in case the text contains \n
404 */
405 template <typename TextPoint>
406 void text(TextPoint const& point, std::string const& s,
407 std::string const& style,
408 double offset_x = 0.0, double offset_y = 0.0,
409 double lineheight = 10.0)
410 {
411 init_matrix();
412 svg_point_type map_point;
413 transform(point, map_point, *m_matrix);
414 m_stream
415 << "<text style=\"" << style << "\""
416 << " x=\"" << get<0>(map_point) + offset_x << "\""
417 << " y=\"" << get<1>(map_point) + offset_y << "\""
418 << ">";
419 if (s.find("\n") == std::string::npos)
420 {
421 m_stream << s;
422 }
423 else
424 {
425 // Multi-line modus
426
427 std::vector<std::string> splitted;
428 boost::split(splitted, s, boost::is_any_of("\n"));
429 for (std::vector<std::string>::const_iterator it
430 = splitted.begin();
431 it != splitted.end();
432 ++it, offset_y += lineheight)
433 {
434 m_stream
435 << "<tspan x=\"" << get<0>(map_point) + offset_x
436 << "\""
437 << " y=\"" << get<1>(map_point) + offset_y
438 << "\""
439 << ">" << *it << "</tspan>";
440 }
441 }
442 m_stream << "</text>" << std::endl;
443 }
444 };
445
446
447 }} // namespace boost::geometry
448
449
450 #endif // BOOST_GEOMETRY_IO_SVG_MAPPER_HPP