mirror of
https://github.com/boostorg/geometry.git
synced 2026-02-01 20:42:10 +00:00
[io][svg] Add variant support for SVG writer.
Rename the file write_svg.hpp to write.hpp for consistency with other IOs. Move dispatches for multi geometries to write.hpp. Leave the old files for backward compatibility.
This commit is contained in:
@@ -43,7 +43,7 @@
|
||||
#include <boost/geometry/strategies/transform/map_transformer.hpp>
|
||||
#include <boost/geometry/views/segment_view.hpp>
|
||||
|
||||
#include <boost/geometry/io/svg/write_svg.hpp>
|
||||
#include <boost/geometry/io/svg/write.hpp>
|
||||
|
||||
// Helper geometries (all points are transformed to integer-points)
|
||||
#include <boost/geometry/geometries/geometries.hpp>
|
||||
@@ -191,6 +191,68 @@ struct svg_map<multi_tag, Multi>
|
||||
};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct devarianted_svg_map
|
||||
{
|
||||
template <typename TransformStrategy>
|
||||
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<Geometry>::type,
|
||||
multi_tag
|
||||
>::type,
|
||||
typename boost::remove_const<Geometry>::type
|
||||
>::apply(stream, style, size, geometry, strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct devarianted_svg_map<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename TransformStrategy>
|
||||
struct visitor: static_visitor<void>
|
||||
{
|
||||
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 <typename Geometry>
|
||||
inline void operator()(Geometry const& geometry) const
|
||||
{
|
||||
devarianted_svg_map<Geometry>::apply(m_os, m_style, m_size, geometry, m_strategy);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TransformStrategy>
|
||||
static inline void apply(std::ostream& stream,
|
||||
std::string const& style,
|
||||
int size,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
TransformStrategy const& strategy)
|
||||
{
|
||||
boost::apply_visitor(visitor<TransformStrategy>(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<Geometry>::type,
|
||||
multi_tag
|
||||
>::type,
|
||||
typename boost::remove_const<Geometry>::type
|
||||
>::apply(stream, style, size, geometry, strategy);
|
||||
dispatch::devarianted_svg_map<Geometry>::apply(stream, style, size,
|
||||
geometry, strategy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
417
include/boost/geometry/io/svg/write.hpp
Normal file
417
include/boost/geometry/io/svg/write.hpp
Normal file
@@ -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 <ostream>
|
||||
#include <string>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant_fwd.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace svg
|
||||
{
|
||||
|
||||
|
||||
template <typename Point>
|
||||
struct svg_point
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Point const& p, std::string const& style, int size)
|
||||
{
|
||||
os << "<circle cx=\"" << geometry::get<0>(p)
|
||||
<< "\" cy=\"" << geometry::get<1>(p)
|
||||
<< "\" r=\"" << (size < 0 ? 5 : size)
|
||||
<< "\" style=\"" << style << "\"/>";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct svg_box
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& 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<Box>::type ct;
|
||||
ct x = geometry::get<geometry::min_corner, 0>(box);
|
||||
ct y = geometry::get<geometry::min_corner, 1>(box);
|
||||
ct width = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),
|
||||
geometry::get<geometry::max_corner, 0>(box) - x);
|
||||
ct height = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),
|
||||
geometry::get<geometry::max_corner, 1>(box) - y);
|
||||
|
||||
os << "<rect x=\"" << x << "\" y=\"" << y
|
||||
<< "\" width=\"" << width << "\" height=\"" << height
|
||||
<< "\" style=\"" << style << "\"/>";
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Segment>
|
||||
struct svg_segment
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Segment const& segment, std::string const& style, int)
|
||||
{
|
||||
typedef typename coordinate_type<Segment>::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 << "<line x1=\"" << x1 << "\" y1=\"" << y1
|
||||
<< "\" x2=\"" << x2 << "\" y2=\"" << y2
|
||||
<< "\" style=\"" << style << "\"/>";
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Stream ranges as SVG
|
||||
\note policy is used to select type (polyline/polygon)
|
||||
*/
|
||||
template <typename Range, typename Policy>
|
||||
struct svg_range
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Range const& range, std::string const& style, int )
|
||||
{
|
||||
typedef typename boost::range_iterator<Range const>::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 <typename Polygon>
|
||||
struct svg_poly
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Polygon const& polygon, std::string const& style, int )
|
||||
{
|
||||
typedef typename geometry::ring_type<Polygon>::type ring_type;
|
||||
typedef typename boost::range_iterator<ring_type const>::type iterator_type;
|
||||
|
||||
bool first = true;
|
||||
os << "<g fill-rule=\"evenodd\"><path d=\"";
|
||||
|
||||
ring_type const& ring = geometry::exterior_ring(polygon);
|
||||
for (iterator_type it = boost::begin(ring);
|
||||
it != boost::end(ring);
|
||||
++it, first = false)
|
||||
{
|
||||
os << (first ? "M" : " L") << " "
|
||||
<< geometry::get<0>(*it)
|
||||
<< ","
|
||||
<< geometry::get<1>(*it);
|
||||
}
|
||||
|
||||
// Inner rings:
|
||||
{
|
||||
typename interior_return_type<Polygon const>::type
|
||||
rings = interior_rings(polygon);
|
||||
for (typename detail::interior_iterator<Polygon const>::type
|
||||
rit = boost::begin(rings); rit != boost::end(rings); ++rit)
|
||||
{
|
||||
first = true;
|
||||
for (typename detail::interior_ring_iterator<Polygon const>::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 << "\"/></g>";
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
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 <typename MultiGeometry, typename Policy>
|
||||
struct svg_multi
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
MultiGeometry const& multi, std::string const& style, int size)
|
||||
{
|
||||
for (typename boost::range_iterator<MultiGeometry const>::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 <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os, G const& geometry)
|
||||
*/
|
||||
template <typename Geometry, typename Tag = typename tag<Geometry>::type>
|
||||
struct svg
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG
|
||||
(
|
||||
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
|
||||
, (Geometry)
|
||||
);
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct svg<Point, point_tag> : detail::svg::svg_point<Point> {};
|
||||
|
||||
template <typename Segment>
|
||||
struct svg<Segment, segment_tag> : detail::svg::svg_segment<Segment> {};
|
||||
|
||||
template <typename Box>
|
||||
struct svg<Box, box_tag> : detail::svg::svg_box<Box> {};
|
||||
|
||||
template <typename Linestring>
|
||||
struct svg<Linestring, linestring_tag>
|
||||
: detail::svg::svg_range<Linestring, detail::svg::prefix_linestring> {};
|
||||
|
||||
template <typename Ring>
|
||||
struct svg<Ring, ring_tag>
|
||||
: detail::svg::svg_range<Ring, detail::svg::prefix_ring> {};
|
||||
|
||||
template <typename Polygon>
|
||||
struct svg<Polygon, polygon_tag>
|
||||
: detail::svg::svg_poly<Polygon> {};
|
||||
|
||||
template <typename MultiPoint>
|
||||
struct svg<MultiPoint, multi_point_tag>
|
||||
: detail::svg::svg_multi
|
||||
<
|
||||
MultiPoint,
|
||||
detail::svg::svg_point
|
||||
<
|
||||
typename boost::range_value<MultiPoint>::type
|
||||
>
|
||||
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring>
|
||||
struct svg<MultiLinestring, multi_linestring_tag>
|
||||
: detail::svg::svg_multi
|
||||
<
|
||||
MultiLinestring,
|
||||
detail::svg::svg_range
|
||||
<
|
||||
typename boost::range_value<MultiLinestring>::type,
|
||||
detail::svg::prefix_linestring
|
||||
>
|
||||
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon>
|
||||
struct svg<MultiPolygon, multi_polygon_tag>
|
||||
: detail::svg::svg_multi
|
||||
<
|
||||
MultiPolygon,
|
||||
detail::svg::svg_poly
|
||||
<
|
||||
typename boost::range_value<MultiPolygon>::type
|
||||
>
|
||||
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
template <typename Geometry>
|
||||
struct devarianted_svg
|
||||
{
|
||||
template <typename OutputStream>
|
||||
static inline void apply(OutputStream& os,
|
||||
Geometry const& geometry,
|
||||
std::string const& style,
|
||||
int size)
|
||||
{
|
||||
svg<Geometry>::apply(os, geometry, style, size);
|
||||
}
|
||||
};
|
||||
|
||||
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
|
||||
struct devarianted_svg<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
|
||||
{
|
||||
template <typename OutputStream>
|
||||
struct visitor: static_visitor<void>
|
||||
{
|
||||
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 <typename Geometry>
|
||||
inline void operator()(Geometry const& geometry) const
|
||||
{
|
||||
devarianted_svg<Geometry>::apply(m_os, geometry, m_style, m_size);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename OutputStream>
|
||||
static inline void apply(
|
||||
OutputStream& os,
|
||||
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
|
||||
std::string const& style,
|
||||
int size
|
||||
)
|
||||
{
|
||||
boost::apply_visitor(visitor<OutputStream>(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 <typename Geometry>
|
||||
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 <typename Char, typename Traits>
|
||||
inline friend std::basic_ostream<Char, Traits>& operator<<(
|
||||
std::basic_ostream<Char, Traits>& os, svg_manipulator const& m)
|
||||
{
|
||||
dispatch::devarianted_svg<Geometry>::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 <typename Geometry>
|
||||
inline svg_manipulator<Geometry> svg(Geometry const& geometry, std::string const& style, int size = -1)
|
||||
{
|
||||
concept::check<Geometry const>();
|
||||
|
||||
return svg_manipulator<Geometry>(geometry, style, size);
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_IO_SVG_WRITE_HPP
|
||||
@@ -18,288 +18,11 @@
|
||||
#ifndef BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP
|
||||
#define BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/range.hpp>
|
||||
|
||||
#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
||||
|
||||
#include <boost/geometry/core/exterior_ring.hpp>
|
||||
#include <boost/geometry/core/interior_rings.hpp>
|
||||
#include <boost/geometry/core/ring_type.hpp>
|
||||
|
||||
#include <boost/geometry/geometries/concepts/check.hpp>
|
||||
// THIS FILE WAS LEFT HERE FOR BACKWARD COMPATIBILITY
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
#include <boost/geometry/io/svg/write.hpp>
|
||||
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace svg
|
||||
{
|
||||
|
||||
|
||||
template <typename Point>
|
||||
struct svg_point
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Point const& p, std::string const& style, int size)
|
||||
{
|
||||
os << "<circle cx=\"" << geometry::get<0>(p)
|
||||
<< "\" cy=\"" << geometry::get<1>(p)
|
||||
<< "\" r=\"" << (size < 0 ? 5 : size)
|
||||
<< "\" style=\"" << style << "\"/>";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Box>
|
||||
struct svg_box
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& 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<Box>::type ct;
|
||||
ct x = geometry::get<geometry::min_corner, 0>(box);
|
||||
ct y = geometry::get<geometry::min_corner, 1>(box);
|
||||
ct width = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),
|
||||
geometry::get<geometry::max_corner, 0>(box) - x);
|
||||
ct height = max BOOST_PREVENT_MACRO_SUBSTITUTION (ct(1),
|
||||
geometry::get<geometry::max_corner, 1>(box) - y);
|
||||
|
||||
os << "<rect x=\"" << x << "\" y=\"" << y
|
||||
<< "\" width=\"" << width << "\" height=\"" << height
|
||||
<< "\" style=\"" << style << "\"/>";
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Segment>
|
||||
struct svg_segment
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Segment const& segment, std::string const& style, int)
|
||||
{
|
||||
typedef typename coordinate_type<Segment>::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 << "<line x1=\"" << x1 << "\" y1=\"" << y1
|
||||
<< "\" x2=\"" << x2 << "\" y2=\"" << y2
|
||||
<< "\" style=\"" << style << "\"/>";
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Stream ranges as SVG
|
||||
\note policy is used to select type (polyline/polygon)
|
||||
*/
|
||||
template <typename Range, typename Policy>
|
||||
struct svg_range
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Range const& range, std::string const& style, int )
|
||||
{
|
||||
typedef typename boost::range_iterator<Range const>::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 <typename Polygon>
|
||||
struct svg_poly
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
Polygon const& polygon, std::string const& style, int )
|
||||
{
|
||||
typedef typename geometry::ring_type<Polygon>::type ring_type;
|
||||
typedef typename boost::range_iterator<ring_type const>::type iterator_type;
|
||||
|
||||
bool first = true;
|
||||
os << "<g fill-rule=\"evenodd\"><path d=\"";
|
||||
|
||||
ring_type const& ring = geometry::exterior_ring(polygon);
|
||||
for (iterator_type it = boost::begin(ring);
|
||||
it != boost::end(ring);
|
||||
++it, first = false)
|
||||
{
|
||||
os << (first ? "M" : " L") << " "
|
||||
<< geometry::get<0>(*it)
|
||||
<< ","
|
||||
<< geometry::get<1>(*it);
|
||||
}
|
||||
|
||||
// Inner rings:
|
||||
{
|
||||
typename interior_return_type<Polygon const>::type
|
||||
rings = interior_rings(polygon);
|
||||
for (typename detail::interior_iterator<Polygon const>::type
|
||||
rit = boost::begin(rings); rit != boost::end(rings); ++rit)
|
||||
{
|
||||
first = true;
|
||||
for (typename detail::interior_ring_iterator<Polygon const>::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 << "\"/></g>";
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
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 <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os, G const& geometry)
|
||||
*/
|
||||
template <typename GeometryTag, typename Geometry>
|
||||
struct svg
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG
|
||||
(
|
||||
false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
|
||||
, (Geometry)
|
||||
);
|
||||
};
|
||||
|
||||
template <typename Point>
|
||||
struct svg<point_tag, Point> : detail::svg::svg_point<Point> {};
|
||||
|
||||
template <typename Segment>
|
||||
struct svg<segment_tag, Segment> : detail::svg::svg_segment<Segment> {};
|
||||
|
||||
template <typename Box>
|
||||
struct svg<box_tag, Box> : detail::svg::svg_box<Box> {};
|
||||
|
||||
template <typename Linestring>
|
||||
struct svg<linestring_tag, Linestring>
|
||||
: detail::svg::svg_range<Linestring, detail::svg::prefix_linestring> {};
|
||||
|
||||
template <typename Ring>
|
||||
struct svg<ring_tag, Ring>
|
||||
: detail::svg::svg_range<Ring, detail::svg::prefix_ring> {};
|
||||
|
||||
template <typename Polygon>
|
||||
struct svg<polygon_tag, Polygon>
|
||||
: detail::svg::svg_poly<Polygon> {};
|
||||
|
||||
} // 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 <typename G>
|
||||
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 <typename Char, typename Traits>
|
||||
inline friend std::basic_ostream<Char, Traits>& operator<<(
|
||||
std::basic_ostream<Char, Traits>& os, svg_manipulator const& m)
|
||||
{
|
||||
dispatch::svg
|
||||
<
|
||||
typename tag<G>::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 <typename Geometry>
|
||||
inline svg_manipulator<Geometry> svg(Geometry const& geometry, std::string const& style, int size = -1)
|
||||
{
|
||||
concept::check<Geometry const>();
|
||||
|
||||
return svg_manipulator<Geometry>(geometry, style, size);
|
||||
}
|
||||
|
||||
}} // namespace boost::geometry
|
||||
|
||||
#endif // BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP
|
||||
|
||||
@@ -18,92 +18,10 @@
|
||||
#define BOOST_GEOMETRY_IO_SVG_WRITE_SVG_MULTI_HPP
|
||||
|
||||
|
||||
#include <boost/geometry/io/svg/write_svg.hpp>
|
||||
// THIS FILE WAS LEFT HERE FOR BACKWARD COMPATIBILITY
|
||||
|
||||
|
||||
namespace boost { namespace geometry
|
||||
{
|
||||
|
||||
#ifndef DOXYGEN_NO_DETAIL
|
||||
namespace detail { namespace svg
|
||||
{
|
||||
|
||||
|
||||
template <typename MultiGeometry, typename Policy>
|
||||
struct svg_multi
|
||||
{
|
||||
template <typename Char, typename Traits>
|
||||
static inline void apply(std::basic_ostream<Char, Traits>& os,
|
||||
MultiGeometry const& multi, std::string const& style, int size)
|
||||
{
|
||||
for (typename boost::range_iterator<MultiGeometry const>::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 <typename MultiPoint>
|
||||
struct svg<multi_point_tag, MultiPoint>
|
||||
: detail::svg::svg_multi
|
||||
<
|
||||
MultiPoint,
|
||||
detail::svg::svg_point
|
||||
<
|
||||
typename boost::range_value<MultiPoint>::type
|
||||
>
|
||||
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiLinestring>
|
||||
struct svg<multi_linestring_tag, MultiLinestring>
|
||||
: detail::svg::svg_multi
|
||||
<
|
||||
MultiLinestring,
|
||||
detail::svg::svg_range
|
||||
<
|
||||
typename boost::range_value<MultiLinestring>::type,
|
||||
detail::svg::prefix_linestring
|
||||
>
|
||||
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename MultiPolygon>
|
||||
struct svg<multi_polygon_tag, MultiPolygon>
|
||||
: detail::svg::svg_multi
|
||||
<
|
||||
MultiPolygon,
|
||||
detail::svg::svg_poly
|
||||
<
|
||||
typename boost::range_value<MultiPolygon>::type
|
||||
>
|
||||
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace dispatch
|
||||
#endif // DOXYGEN_NO_DISPATCH
|
||||
|
||||
|
||||
}} // namespace boost::geometry
|
||||
#include <boost/geometry/io/svg/write.hpp>
|
||||
|
||||
|
||||
#endif // BOOST_GEOMETRY_IO_SVG_WRITE_SVG_MULTI_HPP
|
||||
|
||||
Reference in New Issue
Block a user