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