diff --git a/include/boost/geometry/io/svg/svg_mapper.hpp b/include/boost/geometry/io/svg/svg_mapper.hpp index e06f2acc2..f492f07cb 100644 --- a/include/boost/geometry/io/svg/svg_mapper.hpp +++ b/include/boost/geometry/io/svg/svg_mapper.hpp @@ -43,7 +43,7 @@ #include #include -#include +#include // Helper geometries (all points are transformed to integer-points) #include @@ -191,6 +191,68 @@ struct svg_map }; +template +struct devarianted_svg_map +{ + template + static inline void apply(std::ostream& stream, + std::string const& style, + int size, + Geometry const& geometry, + TransformStrategy const& strategy) + { + svg_map + < + typename tag_cast + < + typename tag::type, + multi_tag + >::type, + typename boost::remove_const::type + >::apply(stream, style, size, geometry, strategy); + } +}; + +template +struct devarianted_svg_map > +{ + template + struct visitor: static_visitor + { + std::ostream& m_os; + std::string const& m_style; + int m_size; + TransformStrategy const& m_strategy; + + visitor(std::ostream& os, + std::string const& style, + int size, + TransformStrategy const& strategy) + : m_os(os) + , m_style(style) + , m_size(size) + , m_strategy(strategy) + {} + + template + inline void operator()(Geometry const& geometry) const + { + devarianted_svg_map::apply(m_os, m_style, m_size, geometry, m_strategy); + } + }; + + template + static inline void apply(std::ostream& stream, + std::string const& style, + int size, + variant const& geometry, + TransformStrategy const& strategy) + { + boost::apply_visitor(visitor(stream, style, size, strategy), geometry); + } +}; + + } // namespace dispatch #endif @@ -200,15 +262,8 @@ inline void svg_map(std::ostream& stream, std::string const& style, int size, Geometry const& geometry, TransformStrategy const& strategy) { - dispatch::svg_map - < - typename tag_cast - < - typename tag::type, - multi_tag - >::type, - typename boost::remove_const::type - >::apply(stream, style, size, geometry, strategy); + dispatch::devarianted_svg_map::apply(stream, style, size, + geometry, strategy); } diff --git a/include/boost/geometry/io/svg/write.hpp b/include/boost/geometry/io/svg/write.hpp new file mode 100644 index 000000000..57db0b1ad --- /dev/null +++ b/include/boost/geometry/io/svg/write.hpp @@ -0,0 +1,417 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland. + +// This file was modified by Oracle on 2016. +// Modifications copyright (c) 2016, Oracle and/or its affiliates. + +// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle + +// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library +// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_IO_SVG_WRITE_HPP +#define BOOST_GEOMETRY_IO_SVG_WRITE_HPP + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace svg +{ + + +template +struct svg_point +{ + template + static inline void apply(std::basic_ostream& os, + Point const& p, std::string const& style, int size) + { + os << "(p) + << "\" cy=\"" << geometry::get<1>(p) + << "\" r=\"" << (size < 0 ? 5 : size) + << "\" style=\"" << style << "\"/>"; + } +}; + + +template +struct svg_box +{ + template + static inline void apply(std::basic_ostream& os, + Box const& box, std::string const& style, int ) + { + // Prevent invisible boxes, making them >=1, using "max" + BOOST_USING_STD_MAX(); + + typedef typename coordinate_type::type ct; + ct x = geometry::get(box); + ct y = geometry::get(box); + ct width = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1), + geometry::get(box) - x); + ct height = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1), + geometry::get(box) - y); + + os << ""; + } +}; + +template +struct svg_segment +{ + template + static inline void apply(std::basic_ostream& os, + Segment const& segment, std::string const& style, int) + { + typedef typename coordinate_type::type ct; + ct x1 = geometry::get<0, 0>(segment); + ct y1 = geometry::get<0, 1>(segment); + ct x2 = geometry::get<1, 0>(segment); + ct y2 = geometry::get<1, 1>(segment); + + os << ""; + } +}; + +/*! +\brief Stream ranges as SVG +\note policy is used to select type (polyline/polygon) +*/ +template +struct svg_range +{ + template + static inline void apply(std::basic_ostream& os, + Range const& range, std::string const& style, int ) + { + typedef typename boost::range_iterator::type iterator; + + bool first = true; + + os << "<" << Policy::prefix() << " points=\""; + + for (iterator it = boost::begin(range); + it != boost::end(range); + ++it, first = false) + { + os << (first ? "" : " " ) + << geometry::get<0>(*it) + << "," + << geometry::get<1>(*it); + } + os << "\" style=\"" << style << Policy::style() << "\"/>"; + } +}; + + + +template +struct svg_poly +{ + template + static inline void apply(std::basic_ostream& os, + Polygon const& polygon, std::string const& style, int ) + { + typedef typename geometry::ring_type::type ring_type; + typedef typename boost::range_iterator::type iterator_type; + + bool first = true; + os << "(*it) + << "," + << geometry::get<1>(*it); + } + + // Inner rings: + { + typename interior_return_type::type + rings = interior_rings(polygon); + for (typename detail::interior_iterator::type + rit = boost::begin(rings); rit != boost::end(rings); ++rit) + { + first = true; + for (typename detail::interior_ring_iterator::type + it = boost::begin(*rit); it != boost::end(*rit); + ++it, first = false) + { + os << (first ? "M" : " L") << " " + << geometry::get<0>(*it) + << "," + << geometry::get<1>(*it); + } + } + } + os << " z \" style=\"" << style << "\"/>"; + + } +}; + + + +struct prefix_linestring +{ + static inline const char* prefix() { return "polyline"; } + static inline const char* style() { return ";fill:none"; } +}; + + +struct prefix_ring +{ + static inline const char* prefix() { return "polygon"; } + static inline const char* style() { return ""; } +}; + + +template +struct svg_multi +{ + template + static inline void apply(std::basic_ostream& os, + MultiGeometry const& multi, std::string const& style, int size) + { + for (typename boost::range_iterator::type + it = boost::begin(multi); + it != boost::end(multi); + ++it) + { + Policy::apply(os, *it, style, size); + } + + } + +}; + + +}} // namespace detail::svg +#endif // DOXYGEN_NO_DETAIL + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +/*! +\brief Dispatching base struct for SVG streaming, specialized below per geometry type +\details Specializations should implement a static method "stream" to stream a geometry +The static method should have the signature: + +template +static inline void apply(std::basic_ostream& os, G const& geometry) +*/ +template ::type> +struct svg +{ + BOOST_MPL_ASSERT_MSG + ( + false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE + , (Geometry) + ); +}; + +template +struct svg : detail::svg::svg_point {}; + +template +struct svg : detail::svg::svg_segment {}; + +template +struct svg : detail::svg::svg_box {}; + +template +struct svg + : detail::svg::svg_range {}; + +template +struct svg + : detail::svg::svg_range {}; + +template +struct svg + : detail::svg::svg_poly {}; + +template +struct svg + : detail::svg::svg_multi + < + MultiPoint, + detail::svg::svg_point + < + typename boost::range_value::type + > + + > +{}; + +template +struct svg + : detail::svg::svg_multi + < + MultiLinestring, + detail::svg::svg_range + < + typename boost::range_value::type, + detail::svg::prefix_linestring + > + + > +{}; + +template +struct svg + : detail::svg::svg_multi + < + MultiPolygon, + detail::svg::svg_poly + < + typename boost::range_value::type + > + + > +{}; + + +template +struct devarianted_svg +{ + template + static inline void apply(OutputStream& os, + Geometry const& geometry, + std::string const& style, + int size) + { + svg::apply(os, geometry, style, size); + } +}; + +template +struct devarianted_svg > +{ + template + struct visitor: static_visitor + { + OutputStream& m_os; + std::string const& m_style; + int m_size; + + visitor(OutputStream& os, std::string const& style, int size) + : m_os(os) + , m_style(style) + , m_size(size) + {} + + template + inline void operator()(Geometry const& geometry) const + { + devarianted_svg::apply(m_os, geometry, m_style, m_size); + } + }; + + template + static inline void apply( + OutputStream& os, + variant const& geometry, + std::string const& style, + int size + ) + { + boost::apply_visitor(visitor(os, style, size), geometry); + } +}; + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +/*! +\brief Generic geometry template manipulator class, takes corresponding output class from traits class +\ingroup svg +\details Stream manipulator, streams geometry classes as SVG (Scalable Vector Graphics) +*/ +template +class svg_manipulator +{ +public: + + inline svg_manipulator(Geometry const& g, std::string const& style, int size) + : m_geometry(g) + , m_style(style) + , m_size(size) + {} + + template + inline friend std::basic_ostream& operator<<( + std::basic_ostream& os, svg_manipulator const& m) + { + dispatch::devarianted_svg::apply(os, + m.m_geometry, + m.m_style, + m.m_size); + os.flush(); + return os; + } + +private: + Geometry const& m_geometry; + std::string const& m_style; + int m_size; +}; + +/*! +\brief Manipulator to stream geometries as SVG +\tparam Geometry \tparam_geometry +\param geometry \param_geometry +\param style String containing verbatim SVG style information +\param size Optional size (used for SVG points) in SVG pixels. For linestrings, + specify linewidth in the SVG style information +\ingroup svg +*/ +template +inline svg_manipulator svg(Geometry const& geometry, std::string const& style, int size = -1) +{ + concept::check(); + + return svg_manipulator(geometry, style, size); +} + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_IO_SVG_WRITE_HPP diff --git a/include/boost/geometry/io/svg/write_svg.hpp b/include/boost/geometry/io/svg/write_svg.hpp index 4a518a081..371a80bc6 100644 --- a/include/boost/geometry/io/svg/write_svg.hpp +++ b/include/boost/geometry/io/svg/write_svg.hpp @@ -18,288 +18,11 @@ #ifndef BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP #define BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include +// THIS FILE WAS LEFT HERE FOR BACKWARD COMPATIBILITY -namespace boost { namespace geometry -{ +#include -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace svg -{ - - -template -struct svg_point -{ - template - static inline void apply(std::basic_ostream& os, - Point const& p, std::string const& style, int size) - { - os << "(p) - << "\" cy=\"" << geometry::get<1>(p) - << "\" r=\"" << (size < 0 ? 5 : size) - << "\" style=\"" << style << "\"/>"; - } -}; - - -template -struct svg_box -{ - template - static inline void apply(std::basic_ostream& os, - Box const& box, std::string const& style, int ) - { - // Prevent invisible boxes, making them >=1, using "max" - BOOST_USING_STD_MAX(); - - typedef typename coordinate_type::type ct; - ct x = geometry::get(box); - ct y = geometry::get(box); - ct width = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1), - geometry::get(box) - x); - ct height = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1), - geometry::get(box) - y); - - os << ""; - } -}; - -template -struct svg_segment -{ - template - static inline void apply(std::basic_ostream& os, - Segment const& segment, std::string const& style, int) - { - typedef typename coordinate_type::type ct; - ct x1 = geometry::get<0, 0>(segment); - ct y1 = geometry::get<0, 1>(segment); - ct x2 = geometry::get<1, 0>(segment); - ct y2 = geometry::get<1, 1>(segment); - - os << ""; - } -}; - -/*! -\brief Stream ranges as SVG -\note policy is used to select type (polyline/polygon) -*/ -template -struct svg_range -{ - template - static inline void apply(std::basic_ostream& os, - Range const& range, std::string const& style, int ) - { - typedef typename boost::range_iterator::type iterator; - - bool first = true; - - os << "<" << Policy::prefix() << " points=\""; - - for (iterator it = boost::begin(range); - it != boost::end(range); - ++it, first = false) - { - os << (first ? "" : " " ) - << geometry::get<0>(*it) - << "," - << geometry::get<1>(*it); - } - os << "\" style=\"" << style << Policy::style() << "\"/>"; - } -}; - - - -template -struct svg_poly -{ - template - static inline void apply(std::basic_ostream& os, - Polygon const& polygon, std::string const& style, int ) - { - typedef typename geometry::ring_type::type ring_type; - typedef typename boost::range_iterator::type iterator_type; - - bool first = true; - os << "(*it) - << "," - << geometry::get<1>(*it); - } - - // Inner rings: - { - typename interior_return_type::type - rings = interior_rings(polygon); - for (typename detail::interior_iterator::type - rit = boost::begin(rings); rit != boost::end(rings); ++rit) - { - first = true; - for (typename detail::interior_ring_iterator::type - it = boost::begin(*rit); it != boost::end(*rit); - ++it, first = false) - { - os << (first ? "M" : " L") << " " - << geometry::get<0>(*it) - << "," - << geometry::get<1>(*it); - } - } - } - os << " z \" style=\"" << style << "\"/>"; - - } -}; - - - -struct prefix_linestring -{ - static inline const char* prefix() { return "polyline"; } - static inline const char* style() { return ";fill:none"; } -}; - - -struct prefix_ring -{ - static inline const char* prefix() { return "polygon"; } - static inline const char* style() { return ""; } -}; - - - -}} // namespace detail::svg -#endif // DOXYGEN_NO_DETAIL - - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - -/*! -\brief Dispatching base struct for SVG streaming, specialized below per geometry type -\details Specializations should implement a static method "stream" to stream a geometry -The static method should have the signature: - -template -static inline void apply(std::basic_ostream& os, G const& geometry) -*/ -template -struct svg -{ - BOOST_MPL_ASSERT_MSG - ( - false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE - , (Geometry) - ); -}; - -template -struct svg : detail::svg::svg_point {}; - -template -struct svg : detail::svg::svg_segment {}; - -template -struct svg : detail::svg::svg_box {}; - -template -struct svg - : detail::svg::svg_range {}; - -template -struct svg - : detail::svg::svg_range {}; - -template -struct svg - : detail::svg::svg_poly {}; - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - - -/*! -\brief Generic geometry template manipulator class, takes corresponding output class from traits class -\ingroup svg -\details Stream manipulator, streams geometry classes as SVG (Scalable Vector Graphics) -*/ -template -class svg_manipulator -{ -public: - - inline svg_manipulator(G const& g, std::string const& style, int size) - : m_geometry(g) - , m_style(style) - , m_size(size) - {} - - template - inline friend std::basic_ostream& operator<<( - std::basic_ostream& os, svg_manipulator const& m) - { - dispatch::svg - < - typename tag::type, G - >::apply(os, m.m_geometry, m.m_style, m.m_size); - os.flush(); - return os; - } - -private: - G const& m_geometry; - std::string const& m_style; - int m_size; -}; - -/*! -\brief Manipulator to stream geometries as SVG -\tparam Geometry \tparam_geometry -\param geometry \param_geometry -\param style String containing verbatim SVG style information -\param size Optional size (used for SVG points) in SVG pixels. For linestrings, - specify linewidth in the SVG style information -\ingroup svg -*/ -template -inline svg_manipulator svg(Geometry const& geometry, std::string const& style, int size = -1) -{ - concept::check(); - - return svg_manipulator(geometry, style, size); -} - -}} // namespace boost::geometry - #endif // BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP diff --git a/include/boost/geometry/io/svg/write_svg_multi.hpp b/include/boost/geometry/io/svg/write_svg_multi.hpp index ff349ebd7..d07a2c204 100644 --- a/include/boost/geometry/io/svg/write_svg_multi.hpp +++ b/include/boost/geometry/io/svg/write_svg_multi.hpp @@ -18,92 +18,10 @@ #define BOOST_GEOMETRY_IO_SVG_WRITE_SVG_MULTI_HPP -#include +// THIS FILE WAS LEFT HERE FOR BACKWARD COMPATIBILITY -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace svg -{ - - -template -struct svg_multi -{ - template - static inline void apply(std::basic_ostream& os, - MultiGeometry const& multi, std::string const& style, int size) - { - for (typename boost::range_iterator::type - it = boost::begin(multi); - it != boost::end(multi); - ++it) - { - Policy::apply(os, *it, style, size); - } - - } - -}; - - - -}} // namespace detail::svg -#endif // DOXYGEN_NO_DETAIL - - -#ifndef DOXYGEN_NO_DISPATCH -namespace dispatch -{ - -template -struct svg - : detail::svg::svg_multi - < - MultiPoint, - detail::svg::svg_point - < - typename boost::range_value::type - > - - > -{}; - -template -struct svg - : detail::svg::svg_multi - < - MultiLinestring, - detail::svg::svg_range - < - typename boost::range_value::type, - detail::svg::prefix_linestring - > - - > -{}; - -template -struct svg - : detail::svg::svg_multi - < - MultiPolygon, - detail::svg::svg_poly - < - typename boost::range_value::type - > - - > -{}; - - -} // namespace dispatch -#endif // DOXYGEN_NO_DISPATCH - - -}} // namespace boost::geometry +#include #endif // BOOST_GEOMETRY_IO_SVG_WRITE_SVG_MULTI_HPP