Chris@16: // Boost.Geometry (aka GGL, Generic Geometry Library) Chris@16: Chris@16: // Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. 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_MAPPER_HPP Chris@16: #define BOOST_GEOMETRY_IO_SVG_MAPPER_HPP Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: // Helper geometries (all points are transformed to integer-points) Chris@16: #include Chris@16: Chris@16: Chris@16: namespace boost { namespace geometry Chris@16: { Chris@16: Chris@16: #ifndef DOXYGEN_NO_DETAIL Chris@16: namespace detail { namespace svg Chris@16: { Chris@16: typedef model::point svg_point_type; Chris@16: }} Chris@16: #endif Chris@16: Chris@16: Chris@16: #ifndef DOXYGEN_NO_DISPATCH Chris@16: namespace dispatch Chris@16: { Chris@16: Chris@16: Chris@16: Chris@16: template Chris@16: struct svg_map 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: Chris@16: template Chris@16: struct svg_map Chris@16: { Chris@16: template Chris@16: static inline void apply(std::ostream& stream, Chris@16: std::string const& style, int size, Chris@16: Point const& point, TransformStrategy const& strategy) Chris@16: { Chris@16: detail::svg::svg_point_type ipoint; Chris@16: geometry::transform(point, ipoint, strategy); Chris@16: stream << geometry::svg(ipoint, style, size) << std::endl; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct svg_map Chris@16: { Chris@16: template Chris@16: static inline void apply(std::ostream& stream, Chris@16: std::string const& style, int size, Chris@16: Box const& box, TransformStrategy const& strategy) Chris@16: { Chris@16: model::box ibox; Chris@16: geometry::transform(box, ibox, strategy); Chris@16: Chris@16: stream << geometry::svg(ibox, style, size) << std::endl; Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: struct svg_map_range Chris@16: { Chris@16: template Chris@16: static inline void apply(std::ostream& stream, Chris@16: std::string const& style, int size, Chris@16: Range1 const& range, TransformStrategy const& strategy) Chris@16: { Chris@16: Range2 irange; Chris@16: geometry::transform(range, irange, strategy); Chris@16: stream << geometry::svg(irange, style, size) << std::endl; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct svg_map Chris@16: { Chris@16: template Chris@16: static inline void apply(std::ostream& stream, Chris@16: std::string const& style, int size, Chris@16: Segment const& segment, TransformStrategy const& strategy) Chris@16: { Chris@16: typedef segment_view view_type; Chris@16: view_type range(segment); Chris@16: svg_map_range Chris@16: < Chris@16: view_type, Chris@16: model::linestring Chris@16: >::apply(stream, style, size, range, strategy); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: struct svg_map Chris@16: : svg_map_range > Chris@16: {}; Chris@16: Chris@16: Chris@16: template Chris@16: struct svg_map Chris@16: : svg_map_range > Chris@16: {}; Chris@16: Chris@16: Chris@16: template Chris@16: struct svg_map Chris@16: { Chris@16: template Chris@16: static inline void apply(std::ostream& stream, Chris@16: std::string const& style, int size, Chris@16: Polygon const& polygon, TransformStrategy const& strategy) Chris@16: { Chris@16: model::polygon ipoly; Chris@16: geometry::transform(polygon, ipoly, strategy); Chris@16: stream << geometry::svg(ipoly, style, size) << std::endl; Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: template Chris@16: struct svg_map Chris@16: { Chris@16: typedef typename single_tag_of Chris@16: < Chris@16: typename geometry::tag::type Chris@16: >::type stag; Chris@16: Chris@16: template Chris@16: static inline void apply(std::ostream& stream, Chris@16: std::string const& style, int size, Chris@16: Multi const& multi, TransformStrategy const& strategy) Chris@16: { Chris@16: for (typename boost::range_iterator::type it Chris@16: = boost::begin(multi); Chris@16: it != boost::end(multi); Chris@16: ++it) Chris@16: { Chris@16: svg_map Chris@16: < Chris@16: stag, Chris@16: typename boost::range_value::type Chris@16: >::apply(stream, style, size, *it, strategy); Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: } // namespace dispatch Chris@16: #endif Chris@16: Chris@16: Chris@16: template Chris@16: inline void svg_map(std::ostream& stream, Chris@16: std::string const& style, int size, Chris@16: Geometry const& geometry, TransformStrategy const& strategy) Chris@16: { Chris@16: dispatch::svg_map Chris@16: < Chris@16: typename tag_cast Chris@16: < Chris@16: typename tag::type, Chris@16: multi_tag Chris@16: >::type, Chris@16: typename boost::remove_const::type Chris@16: >::apply(stream, style, size, geometry, strategy); Chris@16: } Chris@16: Chris@16: Chris@16: /*! Chris@16: \brief Helper class to create SVG maps Chris@16: \tparam Point Point type, for input geometries. Chris@16: \tparam SameScale Boolean flag indicating if horizontal and vertical scale should Chris@16: be the same. The default value is true Chris@16: \ingroup svg Chris@16: Chris@16: \qbk{[include reference/io/svg.qbk]} Chris@16: */ Chris@16: template Chris@16: class svg_mapper : boost::noncopyable Chris@16: { Chris@16: typedef typename geometry::select_most_precise Chris@16: < Chris@16: typename coordinate_type::type, Chris@16: double Chris@16: >::type calculation_type; Chris@16: Chris@16: typedef strategy::transform::map_transformer Chris@16: < Chris@16: calculation_type, Chris@16: geometry::dimension::type::value, Chris@16: geometry::dimension::type::value, Chris@16: true, Chris@16: SameScale Chris@16: > transformer_type; Chris@16: Chris@16: model::box m_bounding_box; Chris@16: boost::scoped_ptr m_matrix; Chris@16: std::ostream& m_stream; Chris@16: int m_width, m_height; Chris@16: std::string m_width_height; // for tag only, defaults to 2x 100% Chris@16: Chris@16: void init_matrix() Chris@16: { Chris@16: if (! m_matrix) Chris@16: { Chris@16: m_matrix.reset(new transformer_type(m_bounding_box, Chris@16: m_width, m_height)); Chris@16: Chris@16: Chris@16: m_stream << "" Chris@16: << std::endl Chris@16: << "" Chris@16: << std::endl Chris@16: << "" Chris@16: << std::endl; Chris@16: } Chris@16: } Chris@16: Chris@16: public : Chris@16: Chris@16: /*! Chris@16: \brief Constructor, initializing the SVG map. Opens and initializes the SVG. Chris@16: Should be called explicitly. Chris@16: \param stream Output stream, should be a stream already open Chris@16: \param width Width of the SVG map (in SVG pixels) Chris@16: \param height Height of the SVG map (in SVG pixels) Chris@16: \param width_height Optional information to increase width and/or height Chris@16: */ Chris@16: explicit svg_mapper(std::ostream& stream, int width, int height Chris@16: , std::string const& width_height = "width=\"100%\" height=\"100%\"") Chris@16: : m_stream(stream) Chris@16: , m_width(width) Chris@16: , m_height(height) Chris@16: , m_width_height(width_height) Chris@16: { Chris@16: assign_inverse(m_bounding_box); Chris@16: } Chris@16: Chris@16: /*! Chris@16: \brief Destructor, called automatically. Closes the SVG by streaming <\/svg> Chris@16: */ Chris@16: virtual ~svg_mapper() Chris@16: { Chris@16: m_stream << "" << std::endl; Chris@16: } Chris@16: Chris@16: /*! Chris@16: \brief Adds a geometry to the transformation matrix. After doing this, Chris@16: the specified geometry can be mapped fully into the SVG map Chris@16: \tparam Geometry \tparam_geometry Chris@16: \param geometry \param_geometry Chris@16: */ Chris@16: template Chris@16: void add(Geometry const& geometry) Chris@16: { Chris@16: if (num_points(geometry) > 0) Chris@16: { Chris@16: expand(m_bounding_box, Chris@16: return_envelope Chris@16: < Chris@16: model::box Chris@16: >(geometry)); Chris@16: } Chris@16: } Chris@16: Chris@16: /*! Chris@16: \brief Maps a geometry into the SVG map using the specified style 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: */ Chris@16: template Chris@16: void map(Geometry const& geometry, std::string const& style, Chris@16: int size = -1) Chris@16: { Chris@16: init_matrix(); Chris@16: svg_map(m_stream, style, size, geometry, *m_matrix); Chris@16: } Chris@16: Chris@16: /*! Chris@16: \brief Adds a text to the SVG map Chris@16: \tparam TextPoint \tparam_point Chris@16: \param point Location of the text (in map units) Chris@16: \param s The text itself Chris@16: \param style String containing verbatim SVG style information, of the text Chris@16: \param offset_x Offset in SVG pixels, defaults to 0 Chris@16: \param offset_y Offset in SVG pixels, defaults to 0 Chris@16: \param lineheight Line height in SVG pixels, in case the text contains \n Chris@16: */ Chris@16: template Chris@16: void text(TextPoint const& point, std::string const& s, Chris@16: std::string const& style, Chris@16: int offset_x = 0, int offset_y = 0, int lineheight = 10) Chris@16: { Chris@16: init_matrix(); Chris@16: detail::svg::svg_point_type map_point; Chris@16: transform(point, map_point, *m_matrix); Chris@16: m_stream Chris@16: << "(map_point) + offset_x << "\"" Chris@16: << " y=\"" << get<1>(map_point) + offset_y << "\"" Chris@16: << ">"; Chris@16: if (s.find("\n") == std::string::npos) Chris@16: { Chris@16: m_stream << s; Chris@16: } Chris@16: else Chris@16: { Chris@16: // Multi-line modus Chris@16: Chris@16: std::vector splitted; Chris@16: boost::split(splitted, s, boost::is_any_of("\n")); Chris@16: for (std::vector::const_iterator it Chris@16: = splitted.begin(); Chris@16: it != splitted.end(); Chris@16: ++it, offset_y += lineheight) Chris@16: { Chris@16: m_stream Chris@16: << "(map_point) + offset_x Chris@16: << "\"" Chris@16: << " y=\"" << get<1>(map_point) + offset_y Chris@16: << "\"" Chris@16: << ">" << *it << ""; Chris@16: } Chris@16: } Chris@16: m_stream << "" << std::endl; Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: }} // namespace boost::geometry Chris@16: Chris@16: Chris@16: #endif // BOOST_GEOMETRY_IO_SVG_MAPPER_HPP