From 81c890a89227a0498546589372524a698ac1ef4c Mon Sep 17 00:00:00 2001 From: Andreas Salzburger Date: Tue, 24 Sep 2024 11:04:47 +0200 Subject: [PATCH] allow for a custom view box setting --- core/include/actsvg/core/svg.hpp | 14 +++++++ core/src/core/svg.cpp | 69 ++++++++++++++++++-------------- tests/core/barrel.cpp | 13 ++---- tests/core/endcap.cpp | 19 +++------ tests/core/svg.cpp | 9 +++++ tests/meta/barrel_sheet.cpp | 5 +-- tests/meta/detector.cpp | 11 +++++ 7 files changed, 84 insertions(+), 56 deletions(-) diff --git a/core/include/actsvg/core/svg.hpp b/core/include/actsvg/core/svg.hpp index 7a0b46b..32a977f 100644 --- a/core/include/actsvg/core/svg.hpp +++ b/core/include/actsvg/core/svg.hpp @@ -182,6 +182,13 @@ struct file { scalar _height = 800; scalar _border = 10; + std::array _x_range = {std::numeric_limits::max(), + std::numeric_limits::min()}; + std::array _y_range = {std::numeric_limits::max(), + std::numeric_limits::min()}; + + std::optional> _view_box = std::nullopt; + std::vector _objects = {}; /** Add an object and respect the min/max range @@ -196,6 +203,13 @@ struct file { **/ void add_objects(const std::vector &os_); + /** Get the view box from the x-y range */ + std::array view_box() const; + + /** Set a view box, this will overwrite the auto-determined one */ + void set_view_box(const std::array &vb_); + + /** Write to ostream */ friend std::ostream &operator<<(std::ostream &os_, const file &f_); }; diff --git a/core/src/core/svg.cpp b/core/src/core/svg.cpp index cfba969..cd79616 100644 --- a/core/src/core/svg.cpp +++ b/core/src/core/svg.cpp @@ -122,57 +122,64 @@ std::ostream &operator<<(std::ostream &os_, const object &o_) { } void file::add_object(const svg::object &o_) { - // Add the object - if (o_._active) { - _objects.push_back(o_); - } + add_objects({o_}); } void file::add_objects(const std::vector &os_) { // Add the objects one by one - for (const auto &o_ : os_) - if (o_._active) { - _objects.push_back(o_); + for (const auto &o : os_) { + if (o._active) { + _objects.push_back(o); + // Adjust range + _x_range[0] = std::min(_x_range[0], o._x_range[0]); + _x_range[1] = std::max(_x_range[1], o._x_range[1]); + _y_range[0] = std::min(_y_range[0], o._y_range[0]); + _y_range[1] = std::max(_y_range[1], o._y_range[1]); } + } } -std::ostream &operator<<(std::ostream &os_, const file &f_) { - // Do the viewBox adjustment - std::array x_range = {std::numeric_limits::max(), - std::numeric_limits::min()}; - std::array y_range = {std::numeric_limits::max(), - std::numeric_limits::min()}; +std::array file::view_box() const { - std::array viewBox = {-800, -800, 1600, 1600}; + std::array vbox = {-800, -800, 1600, 1600}; - std::map definitions; + // Enlarge the view box by 10 percent + vbox[2] = 1.2_scalar * (_x_range[1] - _x_range[0]); + vbox[3] = 1.2_scalar * (_y_range[1] - _y_range[0]); + + // Include a fixed size border + vbox[0] = (_x_range[0] - 0.1_scalar * vbox[2]) - _border; + vbox[1] = (_y_range[0] - 0.1_scalar * vbox[3]) - _border; + vbox[2] += _border; + vbox[3] += _border; + + return vbox; +} +void file::set_view_box(const std::array &vbox_) { + _view_box = vbox_; +} + +std::ostream &operator<<(std::ostream &os_, const file &f_) { + + std::map definitions; for (const auto &o : f_._objects) { - x_range[0] = std::min(x_range[0], o._x_range[0]); - x_range[1] = std::max(x_range[1], o._x_range[1]); - y_range[0] = std::min(y_range[0], o._y_range[0]); - y_range[1] = std::max(y_range[1], o._y_range[1]); - for (const auto &d : o._definitions) { - definitions[d._id] = d; + if (o._active) { + for (const auto &d : o._definitions) { + definitions[d._id] = d; + } } } - // Enlarge the view box by 10 percent - viewBox[2] = 1.2_scalar * (x_range[1] - x_range[0]); - viewBox[3] = 1.2_scalar * (y_range[1] - y_range[0]); - // Include a fixed size border - viewBox[0] = (x_range[0] - 0.1_scalar * viewBox[2]) - f_._border; - viewBox[1] = (y_range[0] - 0.1_scalar * viewBox[3]) - f_._border; - viewBox[2] += f_._border; - viewBox[3] += f_._border; + std::array vbox = f_._view_box.value_or(f_.view_box()); if (f_._add_html) { os_ << f_._html_head; } os_ << f_._svg_head; os_ << " width=\"" << f_._width << "\" height=\"" << f_._height << "\""; - os_ << " viewBox=\"" << viewBox[0] << " " << viewBox[1] << " " << viewBox[2] - << " " << viewBox[3] << "\""; + os_ << " viewBox=\"" << vbox[0] << " " << vbox[1] << " " << vbox[2] << " " + << vbox[3] << "\""; os_ << f_._svg_def_end; // Write the definitions first if (not definitions.empty()) { diff --git a/tests/core/barrel.cpp b/tests/core/barrel.cpp index 9ecba72..7146adb 100644 --- a/tests/core/barrel.cpp +++ b/tests/core/barrel.cpp @@ -43,8 +43,7 @@ TEST(barrel, x_y_view) { } // Add the surfaces - barrel_file._objects.insert(barrel_file._objects.end(), modules.begin(), - modules.end()); + barrel_file.add_objects(modules); // File output std::ofstream barrel_stream; @@ -80,8 +79,7 @@ TEST(barrel, z_phi_view) { } // Add the surfaces - barrel_file._objects.insert(barrel_file._objects.end(), modules.begin(), - modules.end()); + barrel_file.add_objects(modules); // File output std::ofstream barrel_stream; @@ -160,12 +158,9 @@ TEST(barrel, z_phi_view_grid) { grid_color, grid_stroke, scale); // Add the surfaces - barrel_file._objects.insert(barrel_file._objects.end(), modules.begin(), - modules.end()); + barrel_file.add_objects(modules); // Add the grid tiles - barrel_file._objects.insert(barrel_file._objects.end(), - grid._sub_objects.begin(), - grid._sub_objects.end()); + barrel_file.add_objects(grid._sub_objects); // File output std::ofstream barrel_stream; diff --git a/tests/core/endcap.cpp b/tests/core/endcap.cpp index c0b0dc4..f2d51e6 100644 --- a/tests/core/endcap.cpp +++ b/tests/core/endcap.cpp @@ -44,8 +44,7 @@ TEST(endcap, z_r_view) { } // Add the surfaces - ec_file._objects.insert(ec_file._objects.end(), modules.begin(), - modules.end()); + ec_file.add_objects(modules); // File output std::ofstream ec_stream; @@ -93,10 +92,8 @@ TEST(endcap, x_y_view) { } // Add the surfaces - ec_file._objects.insert(ec_file._objects.end(), modules.begin(), - modules.end()); - ec_file._objects.insert(ec_file._objects.end(), labels.begin(), - labels.end()); + ec_file.add_objects(modules); + ec_file.add_objects(labels); // File output std::ofstream ec_stream; @@ -176,16 +173,12 @@ TEST(endcap, x_y_view_grid) { // Build the connectors auto c_objects = connectors::connect_action(grid_sectors._sub_objects, modules, associations); - ec_file._objects.insert(ec_file._objects.end(), c_objects.begin(), - c_objects.end()); + ec_file.add_objects(c_objects); // Add the surfaces - ec_file._objects.insert(ec_file._objects.end(), modules.begin(), - modules.end()); + ec_file.add_objects(modules); // Add the grid sectors - ec_file._objects.insert(ec_file._objects.end(), - grid_sectors._sub_objects.begin(), - grid_sectors._sub_objects.end()); + ec_file.add_objects(grid_sectors._sub_objects); // File output std::ofstream ec_stream; diff --git a/tests/core/svg.cpp b/tests/core/svg.cpp index a0a0318..998874c 100644 --- a/tests/core/svg.cpp +++ b/tests/core/svg.cpp @@ -21,3 +21,12 @@ TEST(svg, empty_object) { svg::object empty{"empty"}; std::stringstream ss; } + +TEST(svg, file_set_view_box) { + svg::file file; + file.set_view_box({0, 0, 100, 100}); + std::stringstream ss; + ss << file; + std::string svg = ss.str(); + ASSERT_TRUE(svg.find("viewBox=\"0 0 100 100\"") != std::string::npos); +} \ No newline at end of file diff --git a/tests/meta/barrel_sheet.cpp b/tests/meta/barrel_sheet.cpp index ed0acc4..0cafa62 100644 --- a/tests/meta/barrel_sheet.cpp +++ b/tests/meta/barrel_sheet.cpp @@ -231,12 +231,11 @@ TEST(display, barrel_x_y_view) { } } // Add the surfaces - barrel_file._objects.insert(barrel_file._objects.end(), modules.begin(), - modules.end()); + barrel_file.add_objects(modules); // Write out the file std::ofstream eout; - eout.open("barrel_xy_view.svg"); + eout.open("sheet_barrel_xy_view.svg"); eout << barrel_file; eout.close(); } diff --git a/tests/meta/detector.cpp b/tests/meta/detector.cpp index 70157a9..14875fa 100644 --- a/tests/meta/detector.cpp +++ b/tests/meta/detector.cpp @@ -251,4 +251,15 @@ TEST(proto, cylindrical_detector) { rstream.open("test_meta_cylinder_detector_zr.svg"); rstream << rfile_zr; rstream.close(); + + // Let's adjust the view box as a test + std::array view_box = rfile_zr.view_box(); + view_box[0] = -10; + view_box[2] *= 0.5; + view_box[2] += 100.; + rfile_zr.set_view_box(view_box); + + rstream.open("test_meta_cylinder_detector_zr_half.svg"); + rstream << rfile_zr; + rstream.close(); }