Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:07

0001 // This file is part of the actsvg packge.
0002 //
0003 // Copyright (C) 2022 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include <string>
0012 #include <vector>
0013 
0014 #include "actsvg/core.hpp"
0015 #include "actsvg/display/geometry.hpp"
0016 #include "actsvg/proto/surface.hpp"
0017 #include "actsvg/proto/volume.hpp"
0018 #include "actsvg/styles/defaults.hpp"
0019 
0020 namespace actsvg {
0021 
0022 using namespace defaults;
0023 
0024 namespace display {
0025 
0026 /** Helper method to calculate the center
0027  *
0028  * @param vs are the vertices that build up this module
0029  *
0030  * @return the string
0031  **/
0032 template <typename point3_container>
0033 std::string center_string(const point3_container& vs) {
0034     std::string c_str = "center = (";
0035     scalar c_x = 0;
0036     scalar c_y = 0;
0037     scalar c_z = 0;
0038     for (auto& v : vs) {
0039         c_x += v[0];
0040         c_y += v[1];
0041         c_z += v[2];
0042     }
0043     c_x /= vs.size();
0044     c_y /= vs.size();
0045     c_z /= vs.size();
0046     return c_str + std::to_string(c_x) + "," + std::to_string(c_y) + ", " +
0047            std::to_string(c_z) + ")";
0048 }
0049 
0050 /** Helper method to prepare axis for a view point
0051  *
0052  * @param first_ is the first axis
0053  * @param second_ is the second axis
0054  * @param sx_ is the first axis scale
0055  * @param sy_ is the second axis scale
0056  * @param ax_ is the first axis addon
0057  * @param ay_ is the second axis addon
0058  *
0059  * @return the marker size as 1 percent of the range
0060  **/
0061 static inline void prepare_axes(std::array<scalar, 2>& first_,
0062                                 std::array<scalar, 2>& second_, scalar sx_,
0063                                 scalar sy_, scalar ax_ = 0., scalar ay_ = 0.) {
0064     // Add some extra space for the axis
0065     first_[0] *= sx_;
0066     first_[1] *= sx_;
0067     first_[0] -= ax_;
0068     first_[1] += ax_;
0069 
0070     second_[0] *= sy_;
0071     second_[1] *= sy_;
0072     second_[0] -= ay_;
0073     second_[1] += ay_;
0074 }
0075 
0076 /** Helper method to get the contours
0077  *
0078  * @param s_ is the surface
0079  * @param fs_ draw in focus mode
0080  *
0081  * @return a vector of contours;
0082  **/
0083 template <typename surface_type, typename view_type = views::x_y>
0084 views::contour range_contour(const surface_type& s_,
0085                              bool fs_ = false) noexcept(false) {
0086 
0087     view_type view;
0088 
0089     using point3 = typename surface_type::point3_type;
0090 
0091     // Add the surface
0092     views::contour contour;
0093     if (s_._template_object.is_defined()) {
0094         // Use a bounding box trick
0095         // Get the contour from the template as bounding box
0096         point2 bbl = {s_._template_object._x_range[0],
0097                       s_._template_object._y_range[0]};
0098         point2 bbr = {s_._template_object._x_range[1],
0099                       s_._template_object._y_range[1]};
0100         if (not fs_) {
0101             bbl[0] += s_._transform._tr[0];
0102             bbl[1] += s_._transform._tr[1];
0103             bbr[0] += s_._transform._tr[0];
0104             bbr[1] += s_._transform._tr[1];
0105             scalar alpha = s_._transform._rot[0];
0106             if (alpha != 0.) {
0107                 scalar alpha_rad = static_cast<scalar>(alpha / M_PI * 180.);
0108                 bbl = utils::rotate(bbl, alpha_rad);
0109                 bbr = utils::rotate(bbr, alpha_rad);
0110             }
0111         }
0112         contour = {bbl, bbr};
0113     } else if (not s_._vertices.empty()) {
0114         // Plain contours are present
0115         contour = view(s_._vertices);
0116         if (not fs_) {
0117             std::for_each(contour.begin(), contour.end(), [&](auto& v) {
0118                 scalar alpha = s_._transform._rot[0];
0119                 scalar alpha_rad = static_cast<scalar>(alpha / M_PI * 180.);
0120                 v = utils::rotate(v, alpha_rad);
0121                 v[0] += s_._transform._tr[0];
0122                 v[1] += s_._transform._tr[1];
0123             });
0124         }
0125     } else if (s_._radii[1] != 0.) {
0126         // Create a contour
0127         scalar ri = s_._radii[0];
0128         scalar ro = s_._radii[1];
0129         scalar phi_low = s_._opening[0];
0130         scalar phi_high = s_._opening[1];
0131         scalar phi = 0.5 * (phi_low + phi_high);
0132         scalar cos_phi_low = std::cos(phi_low);
0133         scalar sin_phi_low = std::sin(phi_low);
0134         scalar cos_phi_high = std::cos(phi_high);
0135         scalar sin_phi_high = std::cos(phi_high);
0136         /// @todo add transform
0137         point3 A = {ri * cos_phi_low, ri * sin_phi_low, 0.};
0138         point3 B = {ri * std::cos(phi), ri * std::sin(phi), 0.};
0139         point3 C = {ri * cos_phi_high, ri * sin_phi_high, 0.};
0140         point3 D = {ro * cos_phi_high, ro * sin_phi_high, 0.};
0141         point3 E = {ro * std::cos(phi), ro * std::sin(phi), 0.};
0142         point3 F = {ro * cos_phi_low, ro * sin_phi_low, 0.};
0143 
0144         std::vector<point3> vertices_disc = {A, B, C, D, E, F};
0145         contour = view(vertices_disc);
0146     } else {
0147         throw std::invalid_argument(
0148             "surface_sheet_xy(...) - could not estimate range.");
0149     }
0150     return contour;
0151 }
0152 
0153 /** Helper method to scale the axis accordingly
0154  *
0155  * @param cc_ is an iterable container of contours
0156  *
0157  * @return a view range
0158  **/
0159 template <typename contour_container>
0160 static std::array<std::array<scalar, 2>, 2> view_range(
0161     const contour_container& cc_) {
0162 
0163     std::array<scalar, 2> x_range = __e_object._x_range;
0164     std::array<scalar, 2> y_range = __e_object._y_range;
0165 
0166     for (auto& c : cc_) {
0167         for (auto& v : c) {
0168             x_range[0] = std::min(v[0], x_range[0]);
0169             x_range[1] = std::max(v[0], x_range[1]);
0170             y_range[0] = std::min(v[1], y_range[0]);
0171             y_range[1] = std::max(v[1], y_range[1]);
0172         }
0173     }
0174     return {x_range, y_range};
0175 }
0176 
0177 /** Helper method to process the modules, estimate the scale and the axes
0178  *
0179  * @param v_ volume of the detector
0180  * @param view_ the view used for this
0181  * @param sh_ the sheet size
0182  * @param es_ is the equal scale
0183  * @param hl_ switch highlighting on/off
0184  * @param dt_ draw template is available
0185  *
0186  * @returns the modules (per surface batch), a scale transform & the axes
0187  **/
0188 template <typename volume_type, typename view_type>
0189 std::tuple<std::vector<std::vector<svg::object>>, style::transform,
0190            std::array<std::array<scalar, 2>, 2>>
0191 process_modules(const volume_type& v_, const view_type& view_,
0192                 const std::array<scalar, 2>& sh_ = {600., 600.},
0193                 bool es_ = false, bool hl_ = true, bool dt_ = true) {
0194 
0195     using surface_type = typename volume_type::surface_type;
0196 
0197     // Axis range & pre-loop, create contours
0198     std::vector<std::vector<views::contour>> all_contours;
0199     for (const auto& surfaces : v_._surfaces) {
0200         std::vector<views::contour> contours;
0201         contours.reserve(surfaces.size());
0202         for (const auto& s : surfaces) {
0203             surface_type range_surface = s;
0204             if (not dt_) {
0205                 range_surface._template_object = svg::object{};
0206             }
0207             contours.push_back(
0208                 range_contour<surface_type, view_type>(range_surface));
0209         }
0210         all_contours.push_back(contours);
0211     }
0212 
0213     // Concatenate all contours into one for the range display
0214     std::vector<views::contour> flattened_contours;
0215     for (const auto& c : all_contours) {
0216         flattened_contours.insert(flattened_contours.end(), c.begin(), c.end());
0217     }
0218 
0219     // Get the scaling right - same scaling for all potential views
0220     auto axes = display::view_range(flattened_contours);
0221 
0222     scalar s_x = sh_[0] / (axes[0][1] - axes[0][0]);
0223     scalar s_y = sh_[1] / (axes[1][1] - axes[1][0]);
0224 
0225     if (es_) {
0226         // Harmonize the view window with equal scales
0227         s_x = s_x < s_y ? s_x : s_y;
0228         s_y = s_y < s_x ? s_y : s_x;
0229     }
0230 
0231     // Create the scale transform
0232     style::transform scale_transform;
0233     scale_transform._scale = {s_x, s_y};
0234 
0235     // Draw the modules and estimate axis ranges
0236     std::vector<std::vector<svg::object>> all_modules;
0237     for (auto [ics, contours] : utils::enumerate(all_contours)) {
0238         std::vector<svg::object> modules;
0239         modules.reserve(contours.size());
0240         for (auto [ic, c] : utils::enumerate(contours)) {
0241             surface_type draw_surface = v_._surfaces[ics][ic];
0242             draw_surface._transform._scale = {s_x, s_y};
0243             if (not hl_) {
0244                 draw_surface._fill._fc._highlight = {};
0245             }
0246             if (not dt_) {
0247                 draw_surface._template_object = svg::object{};
0248             }
0249 
0250             auto surface_module =
0251                 display::surface(draw_surface._name, draw_surface, view_, true,
0252                                  false, true, false);
0253             modules.push_back(surface_module);
0254         }
0255         all_modules.push_back(modules);
0256     }
0257 
0258     // Prepare the axis for the view range
0259     prepare_axes(axes[0], axes[1], s_x, s_y, 30., 30.);
0260 
0261     return {all_modules, scale_transform, axes};
0262 }
0263 
0264 /** Helper method to connect the surface sheets to the
0265  * surfaces of the layer_sheets
0266  *
0267  * @tparam volume_type the type of volume (templated on point3_container)
0268  *
0269  * @param v_ the input volume
0270  * @param templates_ the given module templtes
0271  * @param o_ the object to which they are attached
0272  *
0273  **/
0274 template <typename volume_type>
0275 void connect_surface_sheets(const volume_type& v_,
0276                             std::vector<std::vector<svg::object>>& templates_,
0277                             svg::object& o_) {
0278     // Now create an item per surface
0279     for (auto [ib, surface_batch] : utils::enumerate(v_._surfaces)) {
0280         for (auto [is, s] : utils::enumerate(surface_batch)) {
0281             std::string sid = s._name;
0282 
0283             svg::object& s_sheet_s = templates_[ib][is];
0284             s_sheet_s._attribute_map["display"] = "none";
0285 
0286             // Object information to appear
0287             svg::object on;
0288             on._tag = "animate";
0289             on._attribute_map["fill"] = "freeze";
0290             on._attribute_map["attributeName"] = "display";
0291             on._attribute_map["from"] = "none";
0292             on._attribute_map["to"] = "block";
0293             on._attribute_map["begin"] = sid + __d + "mouseout";
0294 
0295             svg::object off;
0296 
0297             off._tag = "animate";
0298             off._attribute_map["fill"] = "freeze";
0299             off._attribute_map["attributeName"] = "display";
0300             off._attribute_map["to"] = "none";
0301             off._attribute_map["from"] = "block";
0302             off._attribute_map["begin"] = sid + __d + "mouseover";
0303 
0304             // Store the animation
0305             s_sheet_s._sub_objects.push_back(off);
0306             s_sheet_s._sub_objects.push_back(on);
0307 
0308             o_.add_object(s_sheet_s);
0309         }
0310     }
0311 }
0312 
0313 }  // namespace display
0314 
0315 }  // namespace actsvg