File indexing completed on 2026-01-04 09:10:53
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <algorithm>
0012 #include <exception>
0013 #include <limits>
0014 #include <string>
0015 #include <vector>
0016
0017 #include "actsvg/core.hpp"
0018 #include "actsvg/display/geometry.hpp"
0019 #include "actsvg/display/helpers.hpp"
0020 #include "actsvg/display/tools.hpp"
0021 #include "actsvg/proto/cluster.hpp"
0022 #include "actsvg/proto/surface.hpp"
0023 #include "actsvg/proto/volume.hpp"
0024
0025 namespace actsvg {
0026
0027 using namespace defaults;
0028
0029 namespace display {
0030
0031 enum layer_type { e_endcap = 0, e_barrel = 1 };
0032
0033 enum sheet_type { e_module_info = 0, e_grid_info = 1 };
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 template <typename point3_container>
0047 svg::object surface_sheet_xy(const std::string& id_,
0048 const proto::surface<point3_container>& s_,
0049 const std::array<scalar, 2>& sh_ = {400., 400.},
0050 bool fs_ = false) noexcept(false) {
0051 svg::object so = svg::object::create_group(id_);
0052
0053 views::x_y x_y_view;
0054
0055 std::vector<views::contour> contours = {range_contour(s_, fs_)};
0056 auto [x_axis, y_axis] = display::view_range(contours);
0057
0058
0059 bool full = (s_._type == proto::surface<point3_container>::type::e_disc and
0060 s_._opening == std::array<scalar, 2>({-pi, pi}));
0061
0062 bool draw_axes = true;
0063 if (s_._type == proto::surface<point3_container>::type::e_disc or
0064 s_._type == proto::surface<point3_container>::type::e_annulus) {
0065 draw_axes = not fs_;
0066 }
0067
0068 scalar s_x = sh_[0] / (x_axis[1] - x_axis[0]);
0069 scalar s_y = sh_[1] / (y_axis[1] - y_axis[0]);
0070
0071
0072 s_x = s_x < s_y ? s_x : s_y;
0073 s_y = s_y < s_x ? s_y : s_x;
0074
0075
0076 style::transform scale_transform;
0077 scale_transform._scale = {s_x, s_y};
0078
0079
0080 so._summary._scale = scale_transform._scale;
0081
0082
0083 proto::surface<point3_container> draw_surface = s_;
0084 draw_surface._transform._scale = {s_x, s_y};
0085
0086 if (draw_surface._type == decltype(draw_surface)::type::e_disc) {
0087 draw_surface._vertices.clear();
0088 }
0089
0090
0091 auto surface = display::surface(s_._name + "_in_sheet", draw_surface,
0092 x_y_view, {true, true, true, true});
0093 so.add_object(surface);
0094
0095
0096 if (draw_axes) {
0097 display::prepare_axes(x_axis, y_axis, s_x, s_y, 30., 30.);
0098 auto axis_font = __a_font;
0099 axis_font._size = static_cast<unsigned int>(0.035 * sh_[0]);
0100
0101 so.add_object(draw::x_y_axes(id_ + "_axes_xy", x_axis, y_axis,
0102 __a_stroke, "x", "y", axis_font));
0103 }
0104
0105
0106 style::font m_font = __m_font;
0107 m_font._size = static_cast<unsigned int>(0.035 * sh_[0]);
0108 style::marker m_marker = __m_marker;
0109 m_marker._size = static_cast<scalar>(0.015 * sh_[0]);
0110
0111
0112 if (s_._type == proto::surface<point3_container>::type::e_trapez and
0113 s_._measures.size() == 3u) {
0114
0115 scalar hlx_min = s_._measures[0] * s_x;
0116 scalar hlx_max = s_._measures[1] * s_x;
0117 scalar hly = s_._measures[2] * s_y;
0118 scalar ms = 2._scalar * m_marker._size;
0119
0120 std::string h_x_min = "h_x_min";
0121 std::string h_x_max = "h_x_max";
0122 std::string h_y = "h_y";
0123
0124 scalar hly_x = hlx_max + 2 * m_marker._size;
0125
0126 auto measure_hlx_min = draw::measure(
0127 id_ + "_hlx_min", {0, -hly - ms}, {hlx_min, -hly - ms}, __m_stroke,
0128 m_marker, m_marker, m_font,
0129 h_x_min + " = " + utils::to_string(s_._measures[0]),
0130 {static_cast<scalar>(0.5 * hlx_min),
0131 static_cast<scalar>((-hly - ms - 2.2 * m_font._size))});
0132 auto measure_hlx_max = draw::measure(
0133 id_ + "_hlx_max", {0, hly + ms}, {hlx_max, hly + ms}, __m_stroke,
0134 m_marker, m_marker, m_font,
0135 h_x_max + " = " + utils::to_string(s_._measures[1]),
0136 {static_cast<scalar>(0.5 * hlx_max),
0137 static_cast<scalar>(1.2 * m_font._size + (hly + ms))});
0138 auto measure_hly = draw::measure(
0139 id_ + "_hly", {hly_x, 0}, {hly_x, hly}, __m_stroke, m_marker,
0140 m_marker, m_font, h_y + " = " + utils::to_string(s_._measures[2]),
0141 {static_cast<scalar>(m_font._size + hly_x),
0142 static_cast<scalar>(0.5 * hly)});
0143 so.add_object(measure_hlx_min);
0144 so.add_object(measure_hlx_max);
0145 so.add_object(measure_hly);
0146 } else if (s_._type ==
0147 proto::surface<point3_container>::type::e_rectangle and
0148 s_._measures.size() == 2u) {
0149
0150 scalar hlx = s_._measures[0] * s_x;
0151 scalar hly = s_._measures[1] * s_y;
0152 scalar ms = 2._scalar * m_marker._size;
0153
0154 std::string h_x = "h_x";
0155 std::string h_y = "h_y";
0156
0157 auto measure_hlx = draw::measure(
0158 id_ + "_hlx", {0, hly + ms}, {hlx, hly + ms}, __m_stroke, m_marker,
0159 m_marker, m_font, h_x + " = " + utils::to_string(s_._measures[0]),
0160 {static_cast<scalar>(0.5 * hlx),
0161 static_cast<scalar>((hly + ms + 1.2 * m_font._size))});
0162 auto measure_hly = draw::measure(
0163 id_ + "_hly", {hlx + ms, 0}, {hlx + ms, hly}, __m_stroke, m_marker,
0164 m_marker, m_font, h_y + " = " + utils::to_string(s_._measures[1]),
0165 {static_cast<scalar>(hlx + 1.2 * m_font._size),
0166 static_cast<scalar>(0.5 * hly)});
0167 so.add_object(measure_hlx);
0168 so.add_object(measure_hly);
0169 } else if (s_._type == proto::surface<point3_container>::type::e_diamond and
0170 s_._measures.size() == 5u) {
0171
0172 scalar hlx_ymin = s_._measures[0] * s_x;
0173 scalar hlx_y0 = s_._measures[1] * s_x;
0174 scalar hlx_ymax = s_._measures[2] * s_x;
0175 scalar hly_xmin = s_._measures[3] * s_y;
0176 scalar hly_xmax = s_._measures[4] * s_y;
0177 scalar ms = 2._scalar * m_marker._size;
0178
0179
0180 std::string h_x_n = "h_x_ny";
0181 std::string h_x_0 = "h_x_0y";
0182 std::string h_x_p = "h_x_py";
0183 std::string h_y_n = "h_y_nx";
0184 std::string h_y_p = "h_y_px";
0185
0186 auto measure_hlx_ny = draw::measure(
0187 id_ + "_hlx_ny", {0, -hly_xmin - ms}, {hlx_ymin, -hly_xmin - ms},
0188 __m_stroke, m_marker, m_marker, m_font,
0189 h_x_n + " = " + utils::to_string(s_._measures[0]),
0190 {static_cast<scalar>(0.5 * hlx_ymin),
0191 static_cast<scalar>((-hly_xmin - ms - 1.2 * m_font._size))});
0192
0193 auto measure_hlx_0y = draw::measure(
0194 id_ + "_hlx_ny", {0., 0.}, {hlx_y0, 0.}, __m_stroke, m_marker,
0195 m_marker, m_font, h_x_0 + " = " + utils::to_string(s_._measures[1]),
0196 {static_cast<scalar>(0.5 * hlx_y0),
0197 static_cast<scalar>((-ms - 1.2 * m_font._size))});
0198
0199 auto measure_hlx_py = draw::measure(
0200 id_ + "_hlx_py", {0, hly_xmax + ms}, {hlx_ymax, hly_xmax + ms},
0201 __m_stroke, m_marker, m_marker, m_font,
0202 h_x_p + " = " + utils::to_string(s_._measures[2]),
0203 {static_cast<scalar>(0.5 * hlx_ymax),
0204 static_cast<scalar>((hly_xmax + ms + 1.2 * m_font._size))});
0205
0206 auto measure_hly_nx = draw::measure(
0207 id_ + "_hly_nx", {static_cast<scalar>(-0.5 * hlx_ymin), -hly_xmin},
0208 {static_cast<scalar>(-0.5 * hlx_ymin), 0.}, __m_stroke, m_marker,
0209 m_marker, m_font, h_y_n + " = " + utils::to_string(s_._measures[3]),
0210 {static_cast<scalar>(-0.5 * hlx_ymin + ms),
0211 static_cast<scalar>(-0.5 * hly_xmin)});
0212
0213 auto measure_hly_px = draw::measure(
0214 id_ + "_hly_px", {static_cast<scalar>(-0.5 * hlx_ymax), 0.},
0215 {static_cast<scalar>(-0.5 * hlx_ymax), hly_xmax}, __m_stroke,
0216 m_marker, m_marker, m_font,
0217 h_y_p + " = " + utils::to_string(s_._measures[4]),
0218 {static_cast<scalar>(-0.5 * hlx_ymax + ms),
0219 static_cast<scalar>(0.5 * hly_xmax)});
0220
0221 so.add_object(measure_hlx_ny);
0222 so.add_object(measure_hlx_0y);
0223 so.add_object(measure_hlx_py);
0224 so.add_object(measure_hly_nx);
0225 so.add_object(measure_hly_px);
0226
0227 } else if (s_._type == proto::surface<point3_container>::type::e_polygon and
0228 s_._measures.size() == 2 * s_._vertices.size()) {
0229
0230 point2 gcenter = {0., 0.};
0231
0232 for (unsigned int iv = 0; iv < s_._vertices.size(); ++iv) {
0233 auto v = draw::marker(
0234 id_ + "_vertex_" + std::to_string(iv),
0235 {static_cast<scalar>(s_x * s_._measures[2 * iv]),
0236 static_cast<scalar>(s_y * s_._measures[2 * iv + 1u])},
0237 style::marker({"o"}));
0238
0239 gcenter[0] += s_x * s_._measures[2 * iv];
0240 gcenter[1] += s_y * s_._measures[2 * iv + 1u];
0241
0242 so.add_object(v);
0243 }
0244
0245 gcenter[0] /= s_._vertices.size();
0246 gcenter[1] /= s_._vertices.size();
0247
0248 for (unsigned int iv = 0; iv < s_._vertices.size(); ++iv) {
0249 scalar x = s_x * s_._measures[2 * iv];
0250 scalar y = s_x * s_._measures[2 * iv + 1];
0251
0252 scalar dx = x - gcenter[0];
0253 scalar dy = y - gcenter[1];
0254
0255 scalar dnorm = std::sqrt(dx * dx + dy * dy);
0256 dx /= dnorm;
0257 dy /= dnorm;
0258
0259 std::string label_v = "v" + std::to_string(iv) + " = ";
0260 label_v += utils::to_string(std::array<scalar, 2>{
0261 s_._measures[2 * iv], s_._measures[2 * iv + 1]});
0262
0263 scalar offx = dx > 0
0264 ? 2._scalar * m_font._size * dx
0265 : 0.5_scalar * label_v.size() * m_font._size * dx;
0266 scalar offy = 2 * m_font._size * dy;
0267
0268 so.add_object(draw::text(id_ + "_label_v" + std::to_string(iv),
0269 {x + offx, y + offy}, {label_v}));
0270 }
0271
0272 } else if (s_._type == proto::surface<point3_container>::type::e_disc and
0273 not s_._measures.empty()) {
0274
0275 std::string dphi = "h_phi";
0276 std::string aphi = "avg_phi";
0277
0278
0279 std::vector<scalar> r_label;
0280 scalar phi_span = 2 * pi;
0281
0282 if (full) {
0283 r_label = {pi * 0.25, -pi * 0.25};
0284 } else {
0285 phi_span = s_._opening[1] - s_._opening[0];
0286 r_label = {static_cast<scalar>(s_._opening[0] - 0.1),
0287 static_cast<scalar>(s_._opening[1] + 0.1)};
0288 }
0289
0290 scalar r_min = std::numeric_limits<scalar>::max();
0291 scalar r_max = 0.;
0292 for (auto [ir, r] : utils::enumerate(s_._measures)) {
0293
0294 std::array<scalar, 2> xs = {
0295 static_cast<scalar>(s_x * r * std::cos(r_label[0])),
0296 static_cast<scalar>(s_x * r * std::cos(r_label[1]))};
0297 std::array<scalar, 2> ys = {
0298 static_cast<scalar>(s_y * r * std::sin(r_label[0])),
0299 static_cast<scalar>(s_y * r * std::sin(r_label[1]))};
0300
0301
0302 if (ir < 2 and
0303 std::abs(r) > std::numeric_limits<scalar>::epsilon()) {
0304
0305 if (not full) {
0306 auto helper_r = draw::arc(id_ + "_arc_helper", s_x * r,
0307 {xs[0], ys[0]}, {xs[1], ys[1]},
0308 style::fill(), __m_stroke_guide);
0309 so.add_object(helper_r);
0310 }
0311
0312
0313 r_max = r > r_max ? r : r_max;
0314 r_min = r < r_min ? r : r_min;
0315 std::string r_o = ir == 0 ? "r" : "R";
0316
0317 scalar rfs =
0318 (fs_ and not full) ? s_x * 0.85_scalar * r_min : 0._scalar;
0319 scalar rfs_phi = std::atan2(ys[ir], xs[ir]);
0320
0321 point2 rstart = {static_cast<scalar>(rfs * std::cos(rfs_phi)),
0322 static_cast<scalar>(rfs * std::sin(rfs_phi))};
0323
0324 auto measure_r =
0325 draw::measure(id_ + "_r", rstart, {xs[ir], ys[ir]},
0326 __m_stroke, style::marker(), m_marker, m_font,
0327 r_o + " = " + utils::to_string(r),
0328 {static_cast<scalar>(m_font._size + xs[ir]),
0329 static_cast<scalar>(m_font._size + ys[ir])});
0330 so.add_object(measure_r);
0331 }
0332
0333 if (ir == 2 and not full) {
0334
0335
0336 scalar rfs =
0337 (fs_ and not full) ? s_x * 0.85_scalar * r_min : 0._scalar;
0338
0339
0340 scalar lr = s_x * r_max + 2._scalar * m_marker._size;
0341
0342 point2 start = {
0343 static_cast<scalar>(lr * std::cos(s_._opening[0])),
0344 static_cast<scalar>(lr * std::sin(s_._opening[0]))};
0345
0346
0347 scalar mphi = 0.5_scalar * (s_._opening[0] + s_._opening[1]);
0348 point2 end = {static_cast<scalar>(lr * std::cos(mphi)),
0349 static_cast<scalar>(lr * std::sin(mphi))};
0350
0351 scalar mmphi = 0.5_scalar * (s_._opening[0] + mphi);
0352 point2 mend = {
0353 static_cast<scalar>(m_font._size + lr * std::cos(mmphi)),
0354 static_cast<scalar>(m_font._size + lr * std::sin(mmphi))};
0355
0356 auto maesure_arc = draw::arc_measure(
0357 id_ + "_arc", lr, start, end, __m_stroke, m_marker,
0358 m_marker, m_font, dphi + " = " + utils::to_string(phi_span),
0359 mend);
0360
0361 so.add_object(maesure_arc);
0362
0363 point2 mstart = {static_cast<scalar>(rfs * std::cos(mphi)),
0364 static_cast<scalar>(rfs * std::sin(mphi))};
0365
0366 auto medium_phi_line = draw::line(id_ + "medium_phi", mstart,
0367 end, __m_stroke_guide);
0368 so.add_object(medium_phi_line);
0369
0370
0371 scalar r_avg_phi = 0.2_scalar * s_x * r_max;
0372 std::array<scalar, 2> r_avg_start = {r_avg_phi, 0.};
0373 std::array<scalar, 2> r_avg_end = {
0374 static_cast<scalar>(r_avg_phi * std::cos(mphi)),
0375 static_cast<scalar>(r_avg_phi * std::sin(mphi))};
0376
0377 std::array<scalar, 2> r_avg_mend = {
0378 static_cast<scalar>(m_font._size +
0379 r_avg_phi * std::cos(0.5 * mphi)),
0380 static_cast<scalar>(m_font._size +
0381 r_avg_phi * std::sin(0.5 * mphi))};
0382
0383 if (std::abs(mphi) >
0384 5 * std::numeric_limits<scalar>::epsilon()) {
0385 auto measure_avg_phi = draw::arc_measure(
0386 id_ + "_avg_phi", r_avg_phi, r_avg_start, r_avg_end,
0387 __m_stroke, style::marker(), m_marker, m_font,
0388 aphi + " = " + utils::to_string(mphi), r_avg_mend);
0389 so.add_object(measure_avg_phi);
0390 }
0391 }
0392 }
0393 } else if (s_._type == proto::surface<point3_container>::type::e_annulus and
0394 not s_._measures.empty()) {
0395
0396 if (s_._measures.size() != 7u) {
0397 throw std::invalid_argument(
0398 "surface_sheet_xy(...) - incorrect length of <measures> for "
0399 "annulus shape.");
0400 }
0401
0402
0403 scalar min_r = s_x * s_._measures[0];
0404 scalar max_r = s_x * s_._measures[1];
0405 scalar min_phi_rel = s_._measures[2];
0406 scalar max_phi_rel = s_._measures[3];
0407
0408 scalar origin_x = s_x * s_._measures[5];
0409 scalar origin_y = s_x * s_._measures[6];
0410
0411 point2 cart_origin = {origin_x, origin_y};
0412
0413 auto out_left_s_xy =
0414 annulusCircleIx(origin_x, origin_y, max_r, max_phi_rel);
0415 auto in_left_s_xy =
0416 annulusCircleIx(origin_x, origin_y, min_r, max_phi_rel);
0417 auto out_right_s_xy =
0418 annulusCircleIx(origin_x, origin_y, max_r, min_phi_rel);
0419 auto in_right_s_xy =
0420 annulusCircleIx(origin_x, origin_y, min_r, min_phi_rel);
0421
0422 std::vector<point2> corners = {in_right_s_xy, in_left_s_xy,
0423 out_right_s_xy, out_left_s_xy};
0424
0425 so.add_object(draw::line(id_ + "_phi_line_l", {0, 0}, in_left_s_xy,
0426 __m_stroke_guide));
0427
0428 so.add_object(draw::line(id_ + "_phi_line_r", {0, 0}, in_right_s_xy,
0429 __m_stroke_guide));
0430
0431 std::vector<std::string> phi_labels = {"phi_min_rel", "phi_max_rel"};
0432
0433 for (unsigned int ic = 0; ic < 2; ++ic) {
0434
0435 const auto& corner = corners[ic];
0436 scalar in_phi = static_cast<scalar>(atan2(corner[1], corner[0]));
0437
0438 scalar in_r =
0439 (0.2_scalar + ic * 0.2_scalar) * utils::perp(corners[ic]);
0440 std::array<scalar, 2> in_start = {in_r, 0.};
0441 std::array<scalar, 2> in_end = {
0442 static_cast<scalar>(in_r * std::cos(in_phi)),
0443 static_cast<scalar>(in_r * std::sin(in_phi))};
0444
0445 std::array<scalar, 2> in_mend = {
0446 static_cast<scalar>(m_font._size +
0447 in_r * std::cos(0.5 * in_phi)),
0448 static_cast<scalar>(m_font._size +
0449 in_r * std::sin(0.5 * in_phi))};
0450
0451 auto in_phi_arc = draw::arc_measure(
0452 id_ + "_in_phi_" + std::to_string(ic), in_r, in_start, in_end,
0453 __m_stroke, style::marker(), m_marker, m_font,
0454 phi_labels[ic] + " = " + utils::to_string(in_phi), in_mend);
0455 so.add_object(in_phi_arc);
0456 }
0457
0458 style::marker cart_origin_marker = style::marker({"o"});
0459 cart_origin_marker._fill = style::fill(style::color{{255, 0, 0}});
0460
0461 style::font cart_font = m_font;
0462 cart_font._fc = style::color{{255, 0, 0}};
0463
0464 style::stroke cart_stroke = __m_stroke;
0465 cart_stroke._sc = style::color{{255, 0, 0}};
0466
0467 style::marker cart_marker = m_marker;
0468 cart_marker._fill = style::fill(style::color{{255, 0, 0}});
0469 cart_marker._stroke = cart_stroke;
0470
0471
0472 so.add_object(draw::marker(id_ + "_origin_cart", {origin_x, origin_y},
0473 cart_origin_marker));
0474
0475 so.add_object(draw::text(
0476 id_ + "_origin_label",
0477 {origin_x - 2 * cart_font._size, origin_y - 2 * cart_font._size},
0478 {"cart_origin = " + utils::to_string(std::array<scalar, 2>{
0479 s_._measures[5], s_._measures[6]})},
0480 cart_font));
0481
0482 style::stroke cart_guide = __m_stroke_guide;
0483 cart_guide._sc = style::color{{255, 0, 0}};
0484
0485 std::vector<std::string> rs = {"r", "R"};
0486
0487 for (unsigned int idc = 0; idc < 2; ++idc) {
0488
0489 const auto& c0 = corners[2 * idc];
0490 const auto& c1 = corners[2 * idc + 1];
0491
0492 point2 cart_c0 = point2{c0[0] - origin_x, c0[1] - origin_y};
0493 point2 cart_c1 = point2{c1[0] - origin_x, c1[1] - origin_y};
0494 scalar cart_r = utils::perp(cart_c0);
0495
0496 scalar cart_phi0 =
0497 static_cast<scalar>(atan2(cart_c0[1], cart_c0[0])) - 0.2_scalar;
0498 scalar cart_phi1 =
0499 static_cast<scalar>(atan2(cart_c1[1], cart_c1[0])) +
0500 0.25_scalar;
0501 scalar cart_phir =
0502 cart_phi1 - (2_scalar * idc + 1_scalar) * 0.05_scalar;
0503
0504 point2 start_arc = {
0505 static_cast<scalar>(origin_x + cart_r * std::cos(cart_phi0)),
0506 static_cast<scalar>(origin_y + cart_r * std::sin(cart_phi0))};
0507 point2 end_arc = {
0508 static_cast<scalar>(origin_x + cart_r * std::cos(cart_phi1)),
0509 static_cast<scalar>(origin_y + cart_r * std::sin(cart_phi1))};
0510
0511 point2 end_r = {
0512 static_cast<scalar>(origin_x + cart_r * std::cos(cart_phir)),
0513 static_cast<scalar>(origin_y + cart_r * std::sin(cart_phir))};
0514
0515 auto helper_r =
0516 draw::arc(id_ + "_arc_helper_" + std::to_string(idc), cart_r,
0517 start_arc, end_arc, style::fill(), cart_guide);
0518 so.add_object(helper_r);
0519
0520 auto measure_r = draw::measure(
0521 id_ + "_measure_r_" + std::to_string(idc), cart_origin, end_r,
0522 cart_stroke, style::marker(), cart_marker, cart_font,
0523 rs[idc] + " = " +
0524 utils::to_string(static_cast<scalar>(cart_r / s_x)),
0525 {static_cast<scalar>(m_font._size + end_r[0]),
0526 static_cast<scalar>(m_font._size + end_r[1])});
0527 so.add_object(measure_r);
0528 }
0529 }
0530 return so;
0531 }
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544 template <typename point3_container, typename view_type, layer_type lT>
0545 svg::object sheet(const std::string& id_,
0546 const proto::volume<point3_container>& v_,
0547 const std::array<scalar, 2>& sh_ = {600., 600.},
0548 sheet_type t_ = e_module_info,
0549 const std::array<scalar, 2>& s_sh_ = {600., 600.}) {
0550
0551 svg::object o_sheet = svg::object::create_group(id_);
0552
0553 view_type view;
0554
0555 scalar sub_offset = 0.25;
0556
0557
0558 auto [modules, scale_transform, axes] = process_modules(
0559 v_, view, sh_, lT == e_endcap, t_ == e_module_info, lT == e_endcap);
0560 auto x_axis = axes[0];
0561 auto y_axis = axes[1];
0562
0563
0564 o_sheet._summary._scale = scale_transform._scale;
0565
0566
0567 for (auto [ib, surface_batch] : utils::enumerate(v_._surfaces)) {
0568 for (auto [is, s] : utils::enumerate(surface_batch)) {
0569 auto& m = modules[ib][is];
0570 if (t_ == e_module_info and
0571 s._aux_info.find("module_info") != s._aux_info.end()) {
0572 m._aux_info = s._aux_info.find("module_info")->second;
0573 } else if (t_ == e_grid_info and
0574 s._aux_info.find("grid_info") != s._aux_info.end()) {
0575 m._aux_info = s._aux_info.find("grid_info")->second;
0576 }
0577 }
0578 }
0579
0580
0581 std::vector<svg::object> extra_objects;
0582
0583 std::vector<std::vector<svg::object>> all_s_sheets;
0584
0585
0586 if (t_ == e_module_info) {
0587
0588 for (auto [ib, surface_batch] : utils::enumerate(v_._surfaces)) {
0589 std::vector<svg::object> s_sheets;
0590 for (auto s : surface_batch) {
0591
0592 style::fill s_fill;
0593 s_fill._fc._rgb = s._fill._fc._hl_rgb;
0594 s_fill._fc._opacity = s._fill._fc._opacity;
0595 s._fill = s_fill;
0596
0597 svg::object s_sheet =
0598 svg::object::create_group(s._name + "_surface_sheet");
0599
0600 auto bg_panel =
0601 draw::rectangle(s._name + "_surface_sheet_bg", {0, 0},
0602 static_cast<scalar>(0.7 * s_sh_[0]),
0603 static_cast<scalar>(0.7 * s_sh_[1]),
0604 __bg_fill, __bg_stroke);
0605 s_sheet.add_object(bg_panel);
0606 s_sheet.add_object(display::surface_sheet_xy(
0607 s._name + "_surface_sheet_display", s, s_sh_,
0608 lT == e_endcap));
0609
0610 style::transform(
0611 {{static_cast<scalar>((ib + 1) *
0612 (sh_[0] + sub_offset * s_sh_[0])),
0613 0., 0.}})
0614 .attach_attributes(s_sheet);
0615 s_sheets.push_back(s_sheet);
0616 }
0617 all_s_sheets.push_back(s_sheets);
0618 }
0619 } else if (t_ == e_grid_info and not v_._surface_grid._edges_0.empty() and
0620 not v_._surface_grid._edges_1.empty()) {
0621
0622 svg::object sub_sheet;
0623
0624 if (lT == e_endcap) {
0625 extra_objects =
0626 draw::tiled_polar_grid(id_, v_._surface_grid._edges_0,
0627 v_._surface_grid._edges_1, __g_fill,
0628 __g_stroke, scale_transform)
0629 ._sub_objects;
0630 } else if (lT == e_barrel) {
0631 extra_objects =
0632 draw::tiled_cartesian_grid(id_, v_._surface_grid._edges_0,
0633 v_._surface_grid._edges_1, __g_fill,
0634 __g_stroke, scale_transform)
0635 ._sub_objects;
0636 }
0637
0638
0639 for (auto [ib, module_batch] : utils::enumerate(modules)) {
0640
0641 style::font info_font;
0642 info_font._size = static_cast<unsigned int>(0.03 * s_sh_[0]);
0643 auto c_objects = connectors::connect_action(
0644 extra_objects, module_batch, v_._grid_associations[ib],
0645 ib == 0u, {"mouseover", "mouseout"},
0646 {connectors::e_highlight, connectors::e_associate_info},
0647 info_font);
0648 scalar offsx =
0649 static_cast<scalar>((ib * (1 + sub_offset) + 0.7) * sh_[0]);
0650 scalar offsy = std::abs(0.1_scalar * y_axis[1]);
0651
0652 std::for_each(
0653 c_objects.begin(), c_objects.end(), [&](svg::object& o_) {
0654 o_._attribute_map["x"] = utils::to_string(offsx);
0655 o_._attribute_map["y"] = utils::to_string(offsy);
0656 o_._x_range = {static_cast<scalar>(offsx - 100.), offsy};
0657 });
0658 o_sheet.add_objects(c_objects);
0659 }
0660 }
0661
0662
0663 for (auto [ib, module_batch] : utils::enumerate(modules)) {
0664
0665 svg::object sub_sheet =
0666 svg::object::create_group(id_ + "_sub_sheet" + std::to_string(ib));
0667 sub_sheet.add_objects(module_batch);
0668
0669 auto axis_font = __a_font;
0670 axis_font._size = static_cast<unsigned int>(0.035 * s_sh_[0]);
0671 sub_sheet.add_object(draw::x_y_axes(id_ + "_xy", x_axis, y_axis,
0672 __a_stroke, view._axis_names[0],
0673 view._axis_names[1], axis_font));
0674
0675 style::transform(
0676 {{static_cast<scalar>(ib * (sh_[0] + sub_offset * s_sh_[0])), 0.,
0677 0.}})
0678 .attach_attributes(sub_sheet);
0679
0680 o_sheet.add_object(sub_sheet);
0681 }
0682
0683
0684 if (not all_s_sheets.empty()) {
0685
0686 connect_surface_sheets(v_, all_s_sheets, o_sheet);
0687 }
0688
0689
0690 if (not extra_objects.empty()) {
0691 o_sheet.add_objects(extra_objects);
0692 }
0693
0694
0695 auto title_font = __t_font;
0696 title_font._size = static_cast<unsigned int>(0.05 * sh_[0]);
0697 auto title = draw::text(id_ + "sheet_title",
0698 {static_cast<scalar>(-0.55 * sh_[0]),
0699 static_cast<scalar>(0.6 * sh_[1])},
0700 {v_._name}, title_font);
0701 o_sheet.add_object(title);
0702
0703 return o_sheet;
0704 }
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716 template <typename point3_container>
0717 svg::object endcap_sheet(const std::string& id_,
0718 const proto::volume<point3_container>& v_,
0719 const std::array<scalar, 2>& sh_ = {600., 600.},
0720 sheet_type t_ = e_module_info,
0721 const std::array<scalar, 2>& s_sh_ = {600., 600.}) {
0722
0723 return sheet<point3_container, views::x_y, e_endcap>(id_, v_, sh_, t_,
0724 s_sh_);
0725 }
0726
0727
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737 template <typename point3_container>
0738 svg::object barrel_sheet(const std::string& id_,
0739 const proto::volume<point3_container>& v_,
0740 const std::array<scalar, 2>& sh_ = {600., 600.},
0741 sheet_type t_ = e_module_info,
0742 const std::array<scalar, 2>& s_sh_ = {600., 600.}) {
0743
0744 return sheet<point3_container, views::z_phi, e_barrel>(id_, v_, sh_, t_,
0745 s_sh_);
0746 }
0747
0748 }
0749 }