From 1c06875105e2930c7c28873f7cca6a3eef1ef20a Mon Sep 17 00:00:00 2001 From: Barend Gehrels Date: Thu, 12 Nov 2020 14:16:59 +0100 Subject: [PATCH] [svg] Add scale function and examples of it --- doc/html/img/io/svg_mapper_scale.png | Bin 0 -> 8819 bytes doc/imports.qbk | 1 + doc/reference/io/svg.qbk | 4 + doc/src/examples/io/Jamfile | 1 + doc/src/examples/io/svg.cpp | 2 +- doc/src/examples/io/svg_mapper_scale.cpp | 75 +++++++++++++++++++ include/boost/geometry/io/svg/svg_mapper.hpp | 29 +++++++ test/io/svg/svg.cpp | 2 + test/to_svg.hpp | 2 +- 9 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 doc/html/img/io/svg_mapper_scale.png create mode 100644 doc/src/examples/io/svg_mapper_scale.cpp 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 0000000000000000000000000000000000000000..d537408ee4819abc93596192264b59ba6d3d4eb3 GIT binary patch literal 8819 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

dGI?3tm#(}< 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 literal 0 HcmV?d00001 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