annotate DEPENDENCIES/generic/include/boost/geometry/io/svg/svg_mapper.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Boost.Geometry (aka GGL, Generic Geometry Library)
Chris@16 2
Chris@16 3 // Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
Chris@16 4
Chris@16 5 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
Chris@16 6 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
Chris@16 7
Chris@16 8 // Use, modification and distribution is subject to the Boost Software License,
Chris@16 9 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 10 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 11
Chris@16 12 #ifndef BOOST_GEOMETRY_IO_SVG_MAPPER_HPP
Chris@16 13 #define BOOST_GEOMETRY_IO_SVG_MAPPER_HPP
Chris@16 14
Chris@16 15 #include <cstdio>
Chris@16 16
Chris@16 17 #include <vector>
Chris@16 18
Chris@16 19 #include <boost/mpl/assert.hpp>
Chris@16 20 #include <boost/noncopyable.hpp>
Chris@16 21 #include <boost/scoped_ptr.hpp>
Chris@16 22 #include <boost/type_traits/is_same.hpp>
Chris@16 23 #include <boost/type_traits/remove_const.hpp>
Chris@16 24
Chris@16 25 #include <boost/algorithm/string/split.hpp>
Chris@16 26 #include <boost/algorithm/string/classification.hpp>
Chris@16 27
Chris@16 28
Chris@16 29 #include <boost/geometry/core/tags.hpp>
Chris@16 30 #include <boost/geometry/core/tag_cast.hpp>
Chris@16 31
Chris@16 32 #include <boost/geometry/algorithms/envelope.hpp>
Chris@16 33 #include <boost/geometry/algorithms/expand.hpp>
Chris@16 34 #include <boost/geometry/algorithms/transform.hpp>
Chris@16 35 #include <boost/geometry/algorithms/num_points.hpp>
Chris@16 36 #include <boost/geometry/strategies/transform.hpp>
Chris@16 37 #include <boost/geometry/strategies/transform/map_transformer.hpp>
Chris@16 38 #include <boost/geometry/views/segment_view.hpp>
Chris@16 39
Chris@16 40 #include <boost/geometry/multi/algorithms/envelope.hpp>
Chris@16 41 #include <boost/geometry/multi/algorithms/num_points.hpp>
Chris@16 42
Chris@16 43 #include <boost/geometry/io/svg/write_svg.hpp>
Chris@16 44
Chris@16 45 // Helper geometries (all points are transformed to integer-points)
Chris@16 46 #include <boost/geometry/geometries/geometries.hpp>
Chris@16 47
Chris@16 48
Chris@16 49 namespace boost { namespace geometry
Chris@16 50 {
Chris@16 51
Chris@16 52 #ifndef DOXYGEN_NO_DETAIL
Chris@16 53 namespace detail { namespace svg
Chris@16 54 {
Chris@16 55 typedef model::point<int, 2, cs::cartesian> svg_point_type;
Chris@16 56 }}
Chris@16 57 #endif
Chris@16 58
Chris@16 59
Chris@16 60 #ifndef DOXYGEN_NO_DISPATCH
Chris@16 61 namespace dispatch
Chris@16 62 {
Chris@16 63
Chris@16 64
Chris@16 65
Chris@16 66 template <typename GeometryTag, typename Geometry>
Chris@16 67 struct svg_map
Chris@16 68 {
Chris@16 69 BOOST_MPL_ASSERT_MSG
Chris@16 70 (
Chris@16 71 false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
Chris@16 72 , (Geometry)
Chris@16 73 );
Chris@16 74 };
Chris@16 75
Chris@16 76
Chris@16 77 template <typename Point>
Chris@16 78 struct svg_map<point_tag, Point>
Chris@16 79 {
Chris@16 80 template <typename TransformStrategy>
Chris@16 81 static inline void apply(std::ostream& stream,
Chris@16 82 std::string const& style, int size,
Chris@16 83 Point const& point, TransformStrategy const& strategy)
Chris@16 84 {
Chris@16 85 detail::svg::svg_point_type ipoint;
Chris@16 86 geometry::transform(point, ipoint, strategy);
Chris@16 87 stream << geometry::svg(ipoint, style, size) << std::endl;
Chris@16 88 }
Chris@16 89 };
Chris@16 90
Chris@16 91 template <typename Box>
Chris@16 92 struct svg_map<box_tag, Box>
Chris@16 93 {
Chris@16 94 template <typename TransformStrategy>
Chris@16 95 static inline void apply(std::ostream& stream,
Chris@16 96 std::string const& style, int size,
Chris@16 97 Box const& box, TransformStrategy const& strategy)
Chris@16 98 {
Chris@16 99 model::box<detail::svg::svg_point_type> ibox;
Chris@16 100 geometry::transform(box, ibox, strategy);
Chris@16 101
Chris@16 102 stream << geometry::svg(ibox, style, size) << std::endl;
Chris@16 103 }
Chris@16 104 };
Chris@16 105
Chris@16 106
Chris@16 107 template <typename Range1, typename Range2>
Chris@16 108 struct svg_map_range
Chris@16 109 {
Chris@16 110 template <typename TransformStrategy>
Chris@16 111 static inline void apply(std::ostream& stream,
Chris@16 112 std::string const& style, int size,
Chris@16 113 Range1 const& range, TransformStrategy const& strategy)
Chris@16 114 {
Chris@16 115 Range2 irange;
Chris@16 116 geometry::transform(range, irange, strategy);
Chris@16 117 stream << geometry::svg(irange, style, size) << std::endl;
Chris@16 118 }
Chris@16 119 };
Chris@16 120
Chris@16 121 template <typename Segment>
Chris@16 122 struct svg_map<segment_tag, Segment>
Chris@16 123 {
Chris@16 124 template <typename TransformStrategy>
Chris@16 125 static inline void apply(std::ostream& stream,
Chris@16 126 std::string const& style, int size,
Chris@16 127 Segment const& segment, TransformStrategy const& strategy)
Chris@16 128 {
Chris@16 129 typedef segment_view<Segment> view_type;
Chris@16 130 view_type range(segment);
Chris@16 131 svg_map_range
Chris@16 132 <
Chris@16 133 view_type,
Chris@16 134 model::linestring<detail::svg::svg_point_type>
Chris@16 135 >::apply(stream, style, size, range, strategy);
Chris@16 136 }
Chris@16 137 };
Chris@16 138
Chris@16 139
Chris@16 140 template <typename Ring>
Chris@16 141 struct svg_map<ring_tag, Ring>
Chris@16 142 : svg_map_range<Ring, model::ring<detail::svg::svg_point_type> >
Chris@16 143 {};
Chris@16 144
Chris@16 145
Chris@16 146 template <typename Linestring>
Chris@16 147 struct svg_map<linestring_tag, Linestring>
Chris@16 148 : svg_map_range<Linestring, model::linestring<detail::svg::svg_point_type> >
Chris@16 149 {};
Chris@16 150
Chris@16 151
Chris@16 152 template <typename Polygon>
Chris@16 153 struct svg_map<polygon_tag, Polygon>
Chris@16 154 {
Chris@16 155 template <typename TransformStrategy>
Chris@16 156 static inline void apply(std::ostream& stream,
Chris@16 157 std::string const& style, int size,
Chris@16 158 Polygon const& polygon, TransformStrategy const& strategy)
Chris@16 159 {
Chris@16 160 model::polygon<detail::svg::svg_point_type> ipoly;
Chris@16 161 geometry::transform(polygon, ipoly, strategy);
Chris@16 162 stream << geometry::svg(ipoly, style, size) << std::endl;
Chris@16 163 }
Chris@16 164 };
Chris@16 165
Chris@16 166
Chris@16 167 template <typename Multi>
Chris@16 168 struct svg_map<multi_tag, Multi>
Chris@16 169 {
Chris@16 170 typedef typename single_tag_of
Chris@16 171 <
Chris@16 172 typename geometry::tag<Multi>::type
Chris@16 173 >::type stag;
Chris@16 174
Chris@16 175 template <typename TransformStrategy>
Chris@16 176 static inline void apply(std::ostream& stream,
Chris@16 177 std::string const& style, int size,
Chris@16 178 Multi const& multi, TransformStrategy const& strategy)
Chris@16 179 {
Chris@16 180 for (typename boost::range_iterator<Multi const>::type it
Chris@16 181 = boost::begin(multi);
Chris@16 182 it != boost::end(multi);
Chris@16 183 ++it)
Chris@16 184 {
Chris@16 185 svg_map
Chris@16 186 <
Chris@16 187 stag,
Chris@16 188 typename boost::range_value<Multi>::type
Chris@16 189 >::apply(stream, style, size, *it, strategy);
Chris@16 190 }
Chris@16 191 }
Chris@16 192 };
Chris@16 193
Chris@16 194
Chris@16 195 } // namespace dispatch
Chris@16 196 #endif
Chris@16 197
Chris@16 198
Chris@16 199 template <typename Geometry, typename TransformStrategy>
Chris@16 200 inline void svg_map(std::ostream& stream,
Chris@16 201 std::string const& style, int size,
Chris@16 202 Geometry const& geometry, TransformStrategy const& strategy)
Chris@16 203 {
Chris@16 204 dispatch::svg_map
Chris@16 205 <
Chris@16 206 typename tag_cast
Chris@16 207 <
Chris@16 208 typename tag<Geometry>::type,
Chris@16 209 multi_tag
Chris@16 210 >::type,
Chris@16 211 typename boost::remove_const<Geometry>::type
Chris@16 212 >::apply(stream, style, size, geometry, strategy);
Chris@16 213 }
Chris@16 214
Chris@16 215
Chris@16 216 /*!
Chris@16 217 \brief Helper class to create SVG maps
Chris@16 218 \tparam Point Point type, for input geometries.
Chris@16 219 \tparam SameScale Boolean flag indicating if horizontal and vertical scale should
Chris@16 220 be the same. The default value is true
Chris@16 221 \ingroup svg
Chris@16 222
Chris@16 223 \qbk{[include reference/io/svg.qbk]}
Chris@16 224 */
Chris@16 225 template <typename Point, bool SameScale = true>
Chris@16 226 class svg_mapper : boost::noncopyable
Chris@16 227 {
Chris@16 228 typedef typename geometry::select_most_precise
Chris@16 229 <
Chris@16 230 typename coordinate_type<Point>::type,
Chris@16 231 double
Chris@16 232 >::type calculation_type;
Chris@16 233
Chris@16 234 typedef strategy::transform::map_transformer
Chris@16 235 <
Chris@16 236 calculation_type,
Chris@16 237 geometry::dimension<Point>::type::value,
Chris@16 238 geometry::dimension<Point>::type::value,
Chris@16 239 true,
Chris@16 240 SameScale
Chris@16 241 > transformer_type;
Chris@16 242
Chris@16 243 model::box<Point> m_bounding_box;
Chris@16 244 boost::scoped_ptr<transformer_type> m_matrix;
Chris@16 245 std::ostream& m_stream;
Chris@16 246 int m_width, m_height;
Chris@16 247 std::string m_width_height; // for <svg> tag only, defaults to 2x 100%
Chris@16 248
Chris@16 249 void init_matrix()
Chris@16 250 {
Chris@16 251 if (! m_matrix)
Chris@16 252 {
Chris@16 253 m_matrix.reset(new transformer_type(m_bounding_box,
Chris@16 254 m_width, m_height));
Chris@16 255
Chris@16 256
Chris@16 257 m_stream << "<?xml version=\"1.0\" standalone=\"no\"?>"
Chris@16 258 << std::endl
Chris@16 259 << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\""
Chris@16 260 << std::endl
Chris@16 261 << "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">"
Chris@16 262 << std::endl
Chris@16 263 << "<svg " << m_width_height << " version=\"1.1\""
Chris@16 264 << std::endl
Chris@16 265 << "xmlns=\"http://www.w3.org/2000/svg\""
Chris@16 266 << std::endl
Chris@16 267 << "xmlns:xlink=\"http://www.w3.org/1999/xlink\""
Chris@16 268 << ">"
Chris@16 269 << std::endl;
Chris@16 270 }
Chris@16 271 }
Chris@16 272
Chris@16 273 public :
Chris@16 274
Chris@16 275 /*!
Chris@16 276 \brief Constructor, initializing the SVG map. Opens and initializes the SVG.
Chris@16 277 Should be called explicitly.
Chris@16 278 \param stream Output stream, should be a stream already open
Chris@16 279 \param width Width of the SVG map (in SVG pixels)
Chris@16 280 \param height Height of the SVG map (in SVG pixels)
Chris@16 281 \param width_height Optional information to increase width and/or height
Chris@16 282 */
Chris@16 283 explicit svg_mapper(std::ostream& stream, int width, int height
Chris@16 284 , std::string const& width_height = "width=\"100%\" height=\"100%\"")
Chris@16 285 : m_stream(stream)
Chris@16 286 , m_width(width)
Chris@16 287 , m_height(height)
Chris@16 288 , m_width_height(width_height)
Chris@16 289 {
Chris@16 290 assign_inverse(m_bounding_box);
Chris@16 291 }
Chris@16 292
Chris@16 293 /*!
Chris@16 294 \brief Destructor, called automatically. Closes the SVG by streaming <\/svg>
Chris@16 295 */
Chris@16 296 virtual ~svg_mapper()
Chris@16 297 {
Chris@16 298 m_stream << "</svg>" << std::endl;
Chris@16 299 }
Chris@16 300
Chris@16 301 /*!
Chris@16 302 \brief Adds a geometry to the transformation matrix. After doing this,
Chris@16 303 the specified geometry can be mapped fully into the SVG map
Chris@16 304 \tparam Geometry \tparam_geometry
Chris@16 305 \param geometry \param_geometry
Chris@16 306 */
Chris@16 307 template <typename Geometry>
Chris@16 308 void add(Geometry const& geometry)
Chris@16 309 {
Chris@16 310 if (num_points(geometry) > 0)
Chris@16 311 {
Chris@16 312 expand(m_bounding_box,
Chris@16 313 return_envelope
Chris@16 314 <
Chris@16 315 model::box<Point>
Chris@16 316 >(geometry));
Chris@16 317 }
Chris@16 318 }
Chris@16 319
Chris@16 320 /*!
Chris@16 321 \brief Maps a geometry into the SVG map using the specified style
Chris@16 322 \tparam Geometry \tparam_geometry
Chris@16 323 \param geometry \param_geometry
Chris@16 324 \param style String containing verbatim SVG style information
Chris@16 325 \param size Optional size (used for SVG points) in SVG pixels. For linestrings,
Chris@16 326 specify linewidth in the SVG style information
Chris@16 327 */
Chris@16 328 template <typename Geometry>
Chris@16 329 void map(Geometry const& geometry, std::string const& style,
Chris@16 330 int size = -1)
Chris@16 331 {
Chris@16 332 init_matrix();
Chris@16 333 svg_map(m_stream, style, size, geometry, *m_matrix);
Chris@16 334 }
Chris@16 335
Chris@16 336 /*!
Chris@16 337 \brief Adds a text to the SVG map
Chris@16 338 \tparam TextPoint \tparam_point
Chris@16 339 \param point Location of the text (in map units)
Chris@16 340 \param s The text itself
Chris@16 341 \param style String containing verbatim SVG style information, of the text
Chris@16 342 \param offset_x Offset in SVG pixels, defaults to 0
Chris@16 343 \param offset_y Offset in SVG pixels, defaults to 0
Chris@16 344 \param lineheight Line height in SVG pixels, in case the text contains \n
Chris@16 345 */
Chris@16 346 template <typename TextPoint>
Chris@16 347 void text(TextPoint const& point, std::string const& s,
Chris@16 348 std::string const& style,
Chris@16 349 int offset_x = 0, int offset_y = 0, int lineheight = 10)
Chris@16 350 {
Chris@16 351 init_matrix();
Chris@16 352 detail::svg::svg_point_type map_point;
Chris@16 353 transform(point, map_point, *m_matrix);
Chris@16 354 m_stream
Chris@16 355 << "<text style=\"" << style << "\""
Chris@16 356 << " x=\"" << get<0>(map_point) + offset_x << "\""
Chris@16 357 << " y=\"" << get<1>(map_point) + offset_y << "\""
Chris@16 358 << ">";
Chris@16 359 if (s.find("\n") == std::string::npos)
Chris@16 360 {
Chris@16 361 m_stream << s;
Chris@16 362 }
Chris@16 363 else
Chris@16 364 {
Chris@16 365 // Multi-line modus
Chris@16 366
Chris@16 367 std::vector<std::string> splitted;
Chris@16 368 boost::split(splitted, s, boost::is_any_of("\n"));
Chris@16 369 for (std::vector<std::string>::const_iterator it
Chris@16 370 = splitted.begin();
Chris@16 371 it != splitted.end();
Chris@16 372 ++it, offset_y += lineheight)
Chris@16 373 {
Chris@16 374 m_stream
Chris@16 375 << "<tspan x=\"" << get<0>(map_point) + offset_x
Chris@16 376 << "\""
Chris@16 377 << " y=\"" << get<1>(map_point) + offset_y
Chris@16 378 << "\""
Chris@16 379 << ">" << *it << "</tspan>";
Chris@16 380 }
Chris@16 381 }
Chris@16 382 m_stream << "</text>" << std::endl;
Chris@16 383 }
Chris@16 384 };
Chris@16 385
Chris@16 386
Chris@16 387 }} // namespace boost::geometry
Chris@16 388
Chris@16 389
Chris@16 390 #endif // BOOST_GEOMETRY_IO_SVG_MAPPER_HPP