File indexing completed on 2025-01-18 09:35:35
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef BOOST_GEOMETRY_IO_SVG_WRITE_HPP
0019 #define BOOST_GEOMETRY_IO_SVG_WRITE_HPP
0020
0021 #include <ostream>
0022 #include <string>
0023
0024 #include <boost/config.hpp>
0025 #include <boost/range/begin.hpp>
0026 #include <boost/range/end.hpp>
0027 #include <boost/range/value_type.hpp>
0028 #include <boost/variant/apply_visitor.hpp>
0029 #include <boost/variant/static_visitor.hpp>
0030 #include <boost/variant/variant_fwd.hpp>
0031
0032 #include <boost/geometry/core/exterior_ring.hpp>
0033 #include <boost/geometry/core/interior_rings.hpp>
0034 #include <boost/geometry/core/ring_type.hpp>
0035 #include <boost/geometry/core/static_assert.hpp>
0036
0037 #include <boost/geometry/geometries/concepts/check.hpp>
0038
0039
0040 namespace boost { namespace geometry
0041 {
0042
0043
0044 #ifndef DOXYGEN_NO_DETAIL
0045 namespace detail { namespace svg
0046 {
0047
0048
0049 template <typename Point>
0050 struct svg_point
0051 {
0052 template <typename Char, typename Traits>
0053 static inline void apply(std::basic_ostream<Char, Traits>& os,
0054 Point const& p, std::string const& style, double size)
0055 {
0056 os << "<circle cx=\"" << geometry::get<0>(p)
0057 << "\" cy=\"" << geometry::get<1>(p)
0058 << "\" r=\"" << (size < 0 ? 5 : size)
0059 << "\" style=\"" << style << "\"/>";
0060 }
0061 };
0062
0063
0064 template <typename Box>
0065 struct svg_box
0066 {
0067 template <typename Char, typename Traits>
0068 static inline void apply(std::basic_ostream<Char, Traits>& os,
0069 Box const& box, std::string const& style, double)
0070 {
0071
0072 BOOST_USING_STD_MAX();
0073
0074 typedef typename coordinate_type<Box>::type ct;
0075 ct x = geometry::get<geometry::min_corner, 0>(box);
0076 ct y = geometry::get<geometry::min_corner, 1>(box);
0077 ct width = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),
0078 geometry::get<geometry::max_corner, 0>(box) - x);
0079 ct height = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),
0080 geometry::get<geometry::max_corner, 1>(box) - y);
0081
0082 os << "<rect x=\"" << x << "\" y=\"" << y
0083 << "\" width=\"" << width << "\" height=\"" << height
0084 << "\" style=\"" << style << "\"/>";
0085 }
0086 };
0087
0088 template <typename Segment>
0089 struct svg_segment
0090 {
0091 template <typename Char, typename Traits>
0092 static inline void apply(std::basic_ostream<Char, Traits>& os,
0093 Segment const& segment, std::string const& style, double)
0094 {
0095 typedef typename coordinate_type<Segment>::type ct;
0096 ct x1 = geometry::get<0, 0>(segment);
0097 ct y1 = geometry::get<0, 1>(segment);
0098 ct x2 = geometry::get<1, 0>(segment);
0099 ct y2 = geometry::get<1, 1>(segment);
0100
0101 os << "<line x1=\"" << x1 << "\" y1=\"" << y1
0102 << "\" x2=\"" << x2 << "\" y2=\"" << y2
0103 << "\" style=\"" << style << "\"/>";
0104 }
0105 };
0106
0107
0108
0109
0110
0111 template <typename Range, typename Policy>
0112 struct svg_range
0113 {
0114 template <typename Char, typename Traits>
0115 static inline void apply(std::basic_ostream<Char, Traits>& os,
0116 Range const& range, std::string const& style, double)
0117 {
0118 bool first = true;
0119
0120 os << "<" << Policy::prefix() << " points=\"";
0121
0122 for (auto it = boost::begin(range); it != boost::end(range); ++it, first = false)
0123 {
0124 os << (first ? "" : " " )
0125 << geometry::get<0>(*it)
0126 << ","
0127 << geometry::get<1>(*it);
0128 }
0129 os << "\" style=\"" << style << Policy::style() << "\"/>";
0130 }
0131 };
0132
0133
0134
0135 template <typename Polygon>
0136 struct svg_poly
0137 {
0138 template <typename Char, typename Traits>
0139 static inline void apply(std::basic_ostream<Char, Traits>& os,
0140 Polygon const& polygon, std::string const& style, double)
0141 {
0142 typedef typename geometry::ring_type<Polygon>::type ring_type;
0143
0144 bool first = true;
0145 os << "<g fill-rule=\"evenodd\"><path d=\"";
0146
0147 ring_type const& ring = geometry::exterior_ring(polygon);
0148 for (auto it = boost::begin(ring); it != boost::end(ring); ++it, first = false)
0149 {
0150 os << (first ? "M" : " L") << " "
0151 << geometry::get<0>(*it)
0152 << ","
0153 << geometry::get<1>(*it);
0154 }
0155
0156
0157 {
0158 auto const& rings = interior_rings(polygon);
0159 for (auto rit = boost::begin(rings); rit != boost::end(rings); ++rit)
0160 {
0161 first = true;
0162 for (auto it = boost::begin(*rit); it != boost::end(*rit); ++it, first = false)
0163 {
0164 os << (first ? "M" : " L") << " "
0165 << geometry::get<0>(*it)
0166 << ","
0167 << geometry::get<1>(*it);
0168 }
0169 }
0170 }
0171 os << " z \" style=\"" << style << "\"/></g>";
0172
0173 }
0174 };
0175
0176
0177
0178 struct prefix_linestring
0179 {
0180 static inline const char* prefix() { return "polyline"; }
0181 static inline const char* style() { return ";fill:none"; }
0182 };
0183
0184
0185 struct prefix_ring
0186 {
0187 static inline const char* prefix() { return "polygon"; }
0188 static inline const char* style() { return ""; }
0189 };
0190
0191
0192 template <typename MultiGeometry, typename Policy>
0193 struct svg_multi
0194 {
0195 template <typename Char, typename Traits>
0196 static inline void apply(std::basic_ostream<Char, Traits>& os,
0197 MultiGeometry const& multi, std::string const& style, double size)
0198 {
0199 for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
0200 {
0201 Policy::apply(os, *it, style, size);
0202 }
0203 }
0204
0205 };
0206
0207
0208 }}
0209 #endif
0210
0211
0212 #ifndef DOXYGEN_NO_DISPATCH
0213 namespace dispatch
0214 {
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224 template <typename Geometry, typename Tag = typename tag<Geometry>::type>
0225 struct svg
0226 {
0227 BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
0228 "Not or not yet implemented for this Geometry type.",
0229 Geometry, Tag);
0230 };
0231
0232 template <typename Point>
0233 struct svg<Point, point_tag> : detail::svg::svg_point<Point> {};
0234
0235 template <typename Segment>
0236 struct svg<Segment, segment_tag> : detail::svg::svg_segment<Segment> {};
0237
0238 template <typename Box>
0239 struct svg<Box, box_tag> : detail::svg::svg_box<Box> {};
0240
0241 template <typename Linestring>
0242 struct svg<Linestring, linestring_tag>
0243 : detail::svg::svg_range<Linestring, detail::svg::prefix_linestring> {};
0244
0245 template <typename Ring>
0246 struct svg<Ring, ring_tag>
0247 : detail::svg::svg_range<Ring, detail::svg::prefix_ring> {};
0248
0249 template <typename Polygon>
0250 struct svg<Polygon, polygon_tag>
0251 : detail::svg::svg_poly<Polygon> {};
0252
0253 template <typename MultiPoint>
0254 struct svg<MultiPoint, multi_point_tag>
0255 : detail::svg::svg_multi
0256 <
0257 MultiPoint,
0258 detail::svg::svg_point
0259 <
0260 typename boost::range_value<MultiPoint>::type
0261 >
0262
0263 >
0264 {};
0265
0266 template <typename MultiLinestring>
0267 struct svg<MultiLinestring, multi_linestring_tag>
0268 : detail::svg::svg_multi
0269 <
0270 MultiLinestring,
0271 detail::svg::svg_range
0272 <
0273 typename boost::range_value<MultiLinestring>::type,
0274 detail::svg::prefix_linestring
0275 >
0276
0277 >
0278 {};
0279
0280 template <typename MultiPolygon>
0281 struct svg<MultiPolygon, multi_polygon_tag>
0282 : detail::svg::svg_multi
0283 <
0284 MultiPolygon,
0285 detail::svg::svg_poly
0286 <
0287 typename boost::range_value<MultiPolygon>::type
0288 >
0289
0290 >
0291 {};
0292
0293
0294 template <typename Geometry>
0295 struct devarianted_svg
0296 {
0297 template <typename OutputStream>
0298 static inline void apply(OutputStream& os,
0299 Geometry const& geometry,
0300 std::string const& style,
0301 double size)
0302 {
0303 svg<Geometry>::apply(os, geometry, style, size);
0304 }
0305 };
0306
0307 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
0308 struct devarianted_svg<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
0309 {
0310 template <typename OutputStream>
0311 struct visitor: static_visitor<void>
0312 {
0313 OutputStream& m_os;
0314 std::string const& m_style;
0315 double m_size;
0316
0317 visitor(OutputStream& os, std::string const& style, double size)
0318 : m_os(os)
0319 , m_style(style)
0320 , m_size(size)
0321 {}
0322
0323 template <typename Geometry>
0324 inline void operator()(Geometry const& geometry) const
0325 {
0326 devarianted_svg<Geometry>::apply(m_os, geometry, m_style, m_size);
0327 }
0328 };
0329
0330 template <typename OutputStream>
0331 static inline void apply(
0332 OutputStream& os,
0333 variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
0334 std::string const& style,
0335 double size
0336 )
0337 {
0338 boost::apply_visitor(visitor<OutputStream>(os, style, size), geometry);
0339 }
0340 };
0341
0342 }
0343 #endif
0344
0345
0346
0347
0348
0349
0350
0351 template <typename Geometry>
0352 class svg_manipulator
0353 {
0354 public:
0355
0356 inline svg_manipulator(Geometry const& g, std::string const& style, double size)
0357 : m_geometry(g)
0358 , m_style(style)
0359 , m_size(size)
0360 {}
0361
0362 template <typename Char, typename Traits>
0363 inline friend std::basic_ostream<Char, Traits>& operator<<(
0364 std::basic_ostream<Char, Traits>& os, svg_manipulator const& m)
0365 {
0366 dispatch::devarianted_svg<Geometry>::apply(os,
0367 m.m_geometry,
0368 m.m_style,
0369 m.m_size);
0370 os.flush();
0371 return os;
0372 }
0373
0374 private:
0375 Geometry const& m_geometry;
0376 std::string const& m_style;
0377 double m_size;
0378 };
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389 template <typename Geometry>
0390 inline svg_manipulator<Geometry> svg(Geometry const& geometry,
0391 std::string const& style, double size = -1.0)
0392 {
0393 concepts::check<Geometry const>();
0394
0395 return svg_manipulator<Geometry>(geometry, style, size);
0396 }
0397
0398 }}
0399
0400 #endif