diff --git a/doc/html/img/io/svg_mapper_scale.png b/doc/html/img/io/svg_mapper_scale.png
new file mode 100644
index 000000000..d537408ee
Binary files /dev/null and b/doc/html/img/io/svg_mapper_scale.png differ
diff --git a/doc/imports.qbk b/doc/imports.qbk
index a184f1513..8bee56818 100644
--- a/doc/imports.qbk
+++ b/doc/imports.qbk
@@ -151,6 +151,7 @@
[import src/examples/geometries/register/multi_polygon.cpp]
[import src/examples/io/svg.cpp]
+[import src/examples/io/svg_mapper_scale.cpp]
[import src/examples/io/wkt.cpp]
[import src/examples/io/read_wkt.cpp]
diff --git a/doc/reference/io/svg.qbk b/doc/reference/io/svg.qbk
index be76303d3..e298dbbad 100644
--- a/doc/reference/io/svg.qbk
+++ b/doc/reference/io/svg.qbk
@@ -12,5 +12,9 @@
[svg_mapper]
[svg_mapper_output]
+[heading Example with arrows and groups]
+[svg_mapper_scale]
+[svg_mapper_scale_output]
+
[heading See also]
* [link geometry.reference.io.svg.svg The SVG manipulator]
diff --git a/doc/src/examples/io/Jamfile b/doc/src/examples/io/Jamfile
index 489fa6a77..1b8620e6a 100644
--- a/doc/src/examples/io/Jamfile
+++ b/doc/src/examples/io/Jamfile
@@ -15,5 +15,6 @@ project boost-geometry-doc-example-io
;
exe svg : svg.cpp ;
+exe svg_mapper_scale : svg_mapper_scale.cpp ;
exe wkt : wkt.cpp ;
exe read_wkt : read_wkt.cpp ;
diff --git a/doc/src/examples/io/svg.cpp b/doc/src/examples/io/svg.cpp
index 37fb171cc..5c7ca91b3 100644
--- a/doc/src/examples/io/svg.cpp
+++ b/doc/src/examples/io/svg.cpp
@@ -37,7 +37,7 @@ int main()
std::ofstream svg("my_map.svg");
boost::geometry::svg_mapper mapper(svg, 400, 400);
- // Add geometries such that all these geometries fit on the map
+ // Add geometries such that all these geometries fit exactly on the map
mapper.add(a);
mapper.add(b);
mapper.add(c);
diff --git a/doc/src/examples/io/svg_mapper_scale.cpp b/doc/src/examples/io/svg_mapper_scale.cpp
new file mode 100644
index 000000000..97eaf8c24
--- /dev/null
+++ b/doc/src/examples/io/svg_mapper_scale.cpp
@@ -0,0 +1,75 @@
+// Boost.Geometry
+// QuickBook Example
+
+// Copyright (c) 2020 Barend Gehrels, 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)
+
+//[svg_mapper_scale
+//` Shows the usage of svg_mapper with the scale function
+
+#include
+#include
+
+#include
+#include
+
+int main()
+{
+ // Specify the basic type
+ using point_type = boost::geometry::model::d2::point_xy;
+
+ // Declare linestrings and set their values
+ boost::geometry::model::linestring a, b, c;
+ a.push_back({1, 0});
+ a.push_back({3, 3});
+
+ b.push_back({5, 0});
+ b.push_back({3, 2});
+
+ c.push_back({4, 5});
+ c.push_back({3, 4});
+
+ // Declare a stream and an SVG mapper
+ std::ofstream svg("my_map.svg");
+ boost::geometry::svg_mapper mapper(svg, 400, 400);
+
+ // Add geometries such that all these geometries fit exactly on the map
+ mapper.add(a);
+ mapper.add(b);
+ mapper.add(c);
+
+ // Zoom out 5% to have a bit margin around the geometries
+ // This also forces writing the SVG header.
+ mapper.scale(0.95);
+
+ // Write a marker definition.
+ svg << "";
+ svg << ""
+ " ";
+ svg << "";
+
+ // Group the first two geometries
+ svg << "";
+ mapper.map(a, "opacity:0.5;stroke-width:1;stroke:gray;marker-end:url(#arrowhead)");
+ mapper.map(b, "opacity:0.5;stroke-width:3;stroke:gray;marker-end:url(#arrowhead)");
+ svg << "";
+
+ mapper.map(c, "opacity:0.5;stroke-width:5;stroke:red;marker-end:url(#arrowhead)");
+
+ return 0;
+}
+
+//]
+
+
+//[svg_mapper_scale_output
+/*`
+Output:
+
+[$img/io/svg_mapper_scale.png]
+*/
+//]
diff --git a/include/boost/geometry/io/svg/svg_mapper.hpp b/include/boost/geometry/io/svg/svg_mapper.hpp
index 6722518c4..8292e12d2 100644
--- a/include/boost/geometry/io/svg/svg_mapper.hpp
+++ b/include/boost/geometry/io/svg/svg_mapper.hpp
@@ -368,6 +368,35 @@ public :
}
}
+ /*!
+ \brief Optional step, zoom in or zoom out, and forces writing the header. After writing the
+ transformation, geometries should not be added, and mapping can begin. After writing the
+ header, other SVG elements can be streamed (for example defs) which can later be used
+ in styles.
+ Call this function after add and before map or text.
+ \param scale A value larger than 1.0 zooms in, a value smaller than 1.0 zooms out.
+ A scale of 1.0 doesn't change any scaling, but still writes the SVG header.
+ */
+ void scale(double scale = 1.0)
+ {
+ if (scale != 1.0 && scale > 0)
+ {
+ // Zoom out (scale < 1) or zoom in (scale > 1).
+ // Typically, users might specify 0.95, to have a small margin around their geometries.
+ auto& b = m_bounding_box;
+ auto const w = geometry::get<1, 0>(b) - geometry::get<0, 0>(b);
+ auto const h = geometry::get<1, 1>(b) - geometry::get<0, 1>(b);
+
+ auto const& m = std::max(w, h) * (1.0 - scale);
+ geometry::set<0, 0>(b, geometry::get<0, 0>(b) - m);
+ geometry::set<0, 1>(b, geometry::get<0, 1>(b) - m);
+ geometry::set<1, 0>(b, geometry::get<1, 0>(b) + m);
+ geometry::set<1, 1>(b, geometry::get<1, 1>(b) + m);
+ }
+
+ init_matrix();
+ }
+
/*!
\brief Maps a geometry into the SVG map using the specified style
\tparam Geometry \tparam_geometry
diff --git a/test/io/svg/svg.cpp b/test/io/svg/svg.cpp
index d7f6fa825..4ac59e7c9 100644
--- a/test/io/svg/svg.cpp
+++ b/test/io/svg/svg.cpp
@@ -131,6 +131,8 @@ void test_all()
mapper.add(m_po);
mapper.add(var);
+ mapper.scale(0.95);
+
mapper.map(pt, style);
mapper.map(b, style);
mapper.map(s, style);
diff --git a/test/to_svg.hpp b/test/to_svg.hpp
index ad62e217a..10c13f800 100644
--- a/test/to_svg.hpp
+++ b/test/to_svg.hpp
@@ -259,11 +259,11 @@ inline void geom_to_svg(std::string const& wkt1, std::string const& wkt2, std::s
}
struct to_svg_assign_policy
- : boost::geometry::detail::overlay::assign_null_policy
{
static bool const include_no_turn = false;
static bool const include_degenerate = false;
static bool const include_opposite = false;
+ static bool const include_start_turn = false;
};
template