Chris@16: // Boost.Geometry (aka GGL, Generic Geometry Library) Chris@16: Chris@16: // Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. Chris@101: // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. Chris@16: Chris@16: // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library Chris@16: // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. Chris@16: Chris@16: // Use, modification and distribution is subject to the Boost Software License, Chris@16: // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP Chris@16: #define BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@101: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: Chris@16: namespace boost { namespace geometry Chris@16: { Chris@16: Chris@16: Chris@16: #ifndef DOXYGEN_NO_DETAIL Chris@16: namespace detail { namespace svg Chris@16: { Chris@16: Chris@16: Chris@16: template Chris@16: struct svg_point Chris@16: { Chris@16: template Chris@16: static inline void apply(std::basic_ostream& os, Chris@16: Point const& p, std::string const& style, int size) Chris@16: { Chris@16: os << "(p) Chris@16: << "\" cy=\"" << geometry::get<1>(p) Chris@16: << "\" r=\"" << (size < 0 ? 5 : size) Chris@16: << "\" style=\"" << style << "\"/>"; Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: struct svg_box Chris@16: { Chris@16: template Chris@16: static inline void apply(std::basic_ostream& os, Chris@16: Box const& box, std::string const& style, int ) Chris@16: { Chris@16: // Prevent invisible boxes, making them >=1, using "max" Chris@16: BOOST_USING_STD_MAX(); Chris@16: Chris@16: typedef typename coordinate_type::type ct; Chris@16: ct x = geometry::get(box); Chris@16: ct y = geometry::get(box); Chris@16: ct width = max BOOST_PREVENT_MACRO_SUBSTITUTION(1, Chris@16: geometry::get(box) - x); Chris@16: ct height = max BOOST_PREVENT_MACRO_SUBSTITUTION (1, Chris@16: geometry::get(box) - y); Chris@16: Chris@16: os << ""; Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: /*! Chris@16: \brief Stream ranges as SVG Chris@16: \note policy is used to select type (polyline/polygon) Chris@16: */ Chris@16: template Chris@16: struct svg_range Chris@16: { Chris@16: template Chris@16: static inline void apply(std::basic_ostream& os, Chris@16: Range const& range, std::string const& style, int ) Chris@16: { Chris@16: typedef typename boost::range_iterator::type iterator; Chris@16: Chris@16: bool first = true; Chris@16: Chris@16: os << "<" << Policy::prefix() << " points=\""; Chris@16: Chris@16: for (iterator it = boost::begin(range); Chris@16: it != boost::end(range); Chris@16: ++it, first = false) Chris@16: { Chris@16: os << (first ? "" : " " ) Chris@16: << geometry::get<0>(*it) Chris@16: << "," Chris@16: << geometry::get<1>(*it); Chris@16: } Chris@16: os << "\" style=\"" << style << Policy::style() << "\"/>"; Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: Chris@16: template Chris@16: struct svg_poly Chris@16: { Chris@16: template Chris@16: static inline void apply(std::basic_ostream& os, Chris@16: Polygon const& polygon, std::string const& style, int ) Chris@16: { Chris@16: typedef typename geometry::ring_type::type ring_type; Chris@16: typedef typename boost::range_iterator::type iterator_type; Chris@16: Chris@16: bool first = true; Chris@16: os << "(*it) Chris@16: << "," Chris@16: << geometry::get<1>(*it); Chris@16: } Chris@16: Chris@16: // Inner rings: Chris@16: { Chris@101: typename interior_return_type::type Chris@101: rings = interior_rings(polygon); Chris@101: for (typename detail::interior_iterator::type Chris@101: rit = boost::begin(rings); rit != boost::end(rings); ++rit) Chris@16: { Chris@16: first = true; Chris@101: for (typename detail::interior_ring_iterator::type Chris@101: it = boost::begin(*rit); it != boost::end(*rit); Chris@16: ++it, first = false) Chris@16: { Chris@16: os << (first ? "M" : " L") << " " Chris@16: << geometry::get<0>(*it) Chris@16: << "," Chris@16: << geometry::get<1>(*it); Chris@16: } Chris@16: } Chris@16: } Chris@16: os << " z \" style=\"" << style << "\"/>"; Chris@16: Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: Chris@16: struct prefix_linestring Chris@16: { Chris@16: static inline const char* prefix() { return "polyline"; } Chris@16: static inline const char* style() { return ";fill:none"; } Chris@16: }; Chris@16: Chris@16: Chris@16: struct prefix_ring Chris@16: { Chris@16: static inline const char* prefix() { return "polygon"; } Chris@16: static inline const char* style() { return ""; } Chris@16: }; Chris@16: Chris@16: Chris@16: Chris@16: }} // namespace detail::svg Chris@16: #endif // DOXYGEN_NO_DETAIL Chris@16: Chris@16: Chris@16: #ifndef DOXYGEN_NO_DISPATCH Chris@16: namespace dispatch Chris@16: { Chris@16: Chris@16: /*! Chris@16: \brief Dispatching base struct for SVG streaming, specialized below per geometry type Chris@16: \details Specializations should implement a static method "stream" to stream a geometry Chris@16: The static method should have the signature: Chris@16: Chris@16: template Chris@16: static inline void apply(std::basic_ostream& os, G const& geometry) Chris@16: */ Chris@16: template Chris@16: struct svg Chris@16: { Chris@16: BOOST_MPL_ASSERT_MSG Chris@16: ( Chris@16: false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE Chris@16: , (Geometry) Chris@16: ); Chris@16: }; Chris@16: Chris@16: template Chris@16: struct svg : detail::svg::svg_point {}; Chris@16: Chris@16: template Chris@16: struct svg : detail::svg::svg_box {}; Chris@16: Chris@16: template Chris@16: struct svg Chris@16: : detail::svg::svg_range {}; Chris@16: Chris@16: template Chris@16: struct svg Chris@16: : detail::svg::svg_range {}; Chris@16: Chris@16: template Chris@16: struct svg Chris@16: : detail::svg::svg_poly {}; Chris@16: Chris@16: } // namespace dispatch Chris@16: #endif // DOXYGEN_NO_DISPATCH Chris@16: Chris@16: Chris@16: /*! Chris@16: \brief Generic geometry template manipulator class, takes corresponding output class from traits class Chris@16: \ingroup svg Chris@16: \details Stream manipulator, streams geometry classes as SVG (Scalable Vector Graphics) Chris@16: */ Chris@16: template Chris@16: class svg_manipulator Chris@16: { Chris@16: public: Chris@16: Chris@16: inline svg_manipulator(G const& g, std::string const& style, int size) Chris@16: : m_geometry(g) Chris@16: , m_style(style) Chris@16: , m_size(size) Chris@16: {} Chris@16: Chris@16: template Chris@16: inline friend std::basic_ostream& operator<<( Chris@16: std::basic_ostream& os, svg_manipulator const& m) Chris@16: { Chris@16: dispatch::svg Chris@16: < Chris@16: typename tag::type, G Chris@16: >::apply(os, m.m_geometry, m.m_style, m.m_size); Chris@16: os.flush(); Chris@16: return os; Chris@16: } Chris@16: Chris@16: private: Chris@16: G const& m_geometry; Chris@16: std::string const& m_style; Chris@16: int m_size; Chris@16: }; Chris@16: Chris@16: /*! Chris@16: \brief Manipulator to stream geometries as SVG Chris@16: \tparam Geometry \tparam_geometry Chris@16: \param geometry \param_geometry Chris@16: \param style String containing verbatim SVG style information Chris@16: \param size Optional size (used for SVG points) in SVG pixels. For linestrings, Chris@16: specify linewidth in the SVG style information Chris@16: \ingroup svg Chris@16: */ Chris@16: template Chris@16: inline svg_manipulator svg(Geometry const& geometry, std::string const& style, int size = -1) Chris@16: { Chris@16: concept::check(); Chris@16: Chris@16: return svg_manipulator(geometry, style, size); Chris@16: } Chris@16: Chris@16: }} // namespace boost::geometry Chris@16: Chris@16: #endif // BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP