File indexing completed on 2025-09-17 08:03:26
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Plugins/ActSVG/SurfaceArraySvgConverter.hpp"
0010
0011 #include "Acts/Plugins/ActSVG/SurfaceSvgConverter.hpp"
0012 #include "Acts/Surfaces/Surface.hpp"
0013 #include "Acts/Surfaces/SurfaceArray.hpp"
0014 #include "Acts/Surfaces/SurfaceBounds.hpp"
0015
0016 #include <algorithm>
0017 #include <numbers>
0018
0019 Acts::Svg::ProtoIndexedSurfaceGrid Acts::Svg::SurfaceArrayConverter::convert(
0020 const GeometryContext& gctx, const SurfaceArray& surfaceArray,
0021 const SurfaceArrayConverter::Options& cOptions) {
0022
0023 ProtoSurfaces pSurfaces;
0024 ProtoGrid pGrid;
0025 ProtoAssociations pAssociations;
0026
0027 const auto& surfaces = surfaceArray.surfaces();
0028
0029
0030 auto binning = surfaceArray.binningValues();
0031 auto axes = surfaceArray.getAxes();
0032
0033 enum class ViewType { cylinder, polar, planar, none };
0034 using enum ViewType;
0035 ViewType vType = none;
0036
0037 if (!binning.empty() && binning.size() == 2 && axes.size() == 2) {
0038
0039 std::vector<double> edges0;
0040 std::vector<double> edges1;
0041
0042 auto convertGridEdges = [](const std::vector<double>& actsEdges) {
0043 std::vector<actsvg::scalar> svgEdges;
0044 svgEdges.reserve(actsEdges.size());
0045 for (const auto ae : actsEdges) {
0046 svgEdges.push_back(static_cast<actsvg::scalar>(ae));
0047 }
0048 return svgEdges;
0049 };
0050
0051
0052 if (binning[0] == AxisDirection::AxisPhi &&
0053 binning[1] == AxisDirection::AxisZ) {
0054 vType = cylinder;
0055
0056 edges1 = axes[0]->getBinEdges();
0057 edges0 = axes[1]->getBinEdges();
0058 pGrid._type = actsvg::proto::grid::e_z_phi;
0059 } else if (binning[0] == AxisDirection::AxisPhi &&
0060 binning[1] == AxisDirection::AxisR) {
0061 vType = polar;
0062
0063 edges1 = axes[0]->getBinEdges();
0064 edges0 = axes[1]->getBinEdges();
0065 pGrid._type = actsvg::proto::grid::e_r_phi;
0066 } else if (binning[0] == AxisDirection::AxisZ &&
0067 binning[1] == AxisDirection::AxisPhi) {
0068
0069 vType = cylinder;
0070 edges0 = axes[0]->getBinEdges();
0071 edges1 = axes[1]->getBinEdges();
0072 pGrid._type = actsvg::proto::grid::e_z_phi;
0073 } else if (binning[0] == AxisDirection::AxisR &&
0074 binning[1] == AxisDirection::AxisPhi) {
0075
0076 vType = polar;
0077 edges0 = axes[0]->getBinEdges();
0078 edges1 = axes[1]->getBinEdges();
0079 pGrid._type = actsvg::proto::grid::e_r_phi;
0080 }
0081
0082 pGrid._edges_0 = convertGridEdges(edges0);
0083 pGrid._edges_1 = convertGridEdges(edges1);
0084 }
0085
0086 auto [fill, stroke] = cOptions.gridOptions.style.fillAndStroke();
0087 pGrid._fill = fill;
0088 pGrid._stroke = stroke;
0089
0090
0091 std::vector<actsvg::svg::object> templateObjects;
0092 std::vector<const SurfaceBounds*> templateBounds;
0093
0094
0095 double radius = 0.;
0096 for (const auto& sf : surfaces) {
0097
0098 const SurfaceBounds& sBounds = sf->bounds();
0099 radius += Acts::VectorHelpers::perp(sf->center(gctx));
0100
0101
0102 auto sameBounds = [&](const SurfaceBounds* test) {
0103 return ((*test) == sBounds);
0104 };
0105
0106
0107 if (std::ranges::none_of(templateBounds, sameBounds)) {
0108
0109 SurfaceConverter::Options sOptions;
0110 sOptions.templateSurface = true;
0111
0112 auto sfStyle = cOptions.surfaceStyles.find(sf->geometryId());
0113 if (sfStyle != cOptions.surfaceStyles.end()) {
0114 sOptions.style = *sfStyle;
0115 }
0116
0117
0118 auto referenceSurface = SurfaceConverter::convert(gctx, *sf, sOptions);
0119 auto referenceObject =
0120 View::xy(referenceSurface,
0121 "Template_" + std::to_string(templateObjects.size()));
0122 templateBounds.push_back(&sBounds);
0123 templateObjects.push_back(referenceObject);
0124 }
0125 }
0126 radius /= static_cast<double>(surfaces.size());
0127
0128
0129 if (pGrid._type == actsvg::proto::grid::e_z_phi) {
0130 pGrid._reference_r = static_cast<float>(radius);
0131 }
0132
0133
0134 for (const auto& sf : surfaces) {
0135
0136 SurfaceConverter::Options sOptions;
0137 sOptions.templateSurface = vType != cylinder;
0138
0139 auto sfStyle = cOptions.surfaceStyles.find(sf->geometryId());
0140 if (sfStyle != cOptions.surfaceStyles.end()) {
0141 sOptions.style = *sfStyle;
0142 }
0143
0144 auto cSurface = Acts::Svg::SurfaceConverter::convert(gctx, *sf, sOptions);
0145 cSurface._name = "Module_n_" + std::to_string(pSurfaces.size());
0146
0147 cSurface._aux_info["grid_info"] = {
0148 "* module " + std::to_string(pSurfaces.size()) +
0149 ", surface = " + std::to_string(sf->geometryId().sensitive())};
0150
0151 if (vType == planar || vType == polar) {
0152
0153
0154 const auto& sTransform = sf->transform(gctx);
0155 Vector3 localA = sTransform.rotation().col(0);
0156 Vector3 localZ = sTransform.rotation().col(2);
0157
0158 double projZ = localZ.dot(Vector3(0., 0., 1.));
0159 double alpha = std::atan2(localA[1], localA[0]) / std::numbers::pi * 180.;
0160 if (projZ < 0.) {
0161 alpha += 180.;
0162 }
0163 auto surfaceCenter = sf->center(gctx);
0164
0165 cSurface._transform._tr = {static_cast<actsvg::scalar>(surfaceCenter[0]),
0166 static_cast<actsvg::scalar>(surfaceCenter[1])};
0167 cSurface._transform._rot = {static_cast<actsvg::scalar>(alpha), 0., 0.};
0168 }
0169 cSurface._radii[0u] = static_cast<float>(radius);
0170 pSurfaces.push_back(cSurface);
0171 }
0172
0173
0174 for (unsigned int il0 = 1; il0 < pGrid._edges_0.size(); ++il0) {
0175 double p0 = 0.5 * (pGrid._edges_0[il0] + pGrid._edges_0[il0 - 1]);
0176 for (unsigned int il1 = 1; il1 < pGrid._edges_1.size(); ++il1) {
0177 double p1 = 0.5 * (pGrid._edges_1[il1] + pGrid._edges_1[il1 - 1]);
0178
0179 Vector3 bCenter;
0180 if (vType == polar) {
0181 bCenter = Vector3(p0 * std::cos(p1), p0 * std::sin(p1), 0.);
0182 } else if (vType == cylinder) {
0183 bCenter = Vector3(radius * std::cos(p1), radius * std::sin(p1), p0);
0184 }
0185
0186 auto bSurfaces = surfaceArray.neighbors(bCenter);
0187 std::vector<std::size_t> binnAssoc;
0188 for (const auto& bs : bSurfaces) {
0189 auto candidate = std::ranges::find(surfaces, bs);
0190 if (candidate != surfaces.end()) {
0191 binnAssoc.push_back(std::distance(surfaces.begin(), candidate));
0192 }
0193 }
0194 pAssociations.push_back(binnAssoc);
0195
0196 std::string binInfo = std::string("- bin : [") + std::to_string(il0) +
0197 std::string(", ") + std::to_string(il1) +
0198 std::string("]") + '\n';
0199 binInfo += " - center : (" + std::to_string(p0) + ", " +
0200 std::to_string(p1) + ")";
0201
0202 pGrid._bin_ids.push_back(binInfo);
0203 }
0204 }
0205
0206 return {pSurfaces, pGrid, pAssociations};
0207 }