File indexing completed on 2025-12-11 09:40:21
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Geometry/Extent.hpp"
0012 #include "Acts/Geometry/GeometryContext.hpp"
0013 #include "Acts/Geometry/GeometryHierarchyMap.hpp"
0014 #include "Acts/Navigation/InternalNavigation.hpp"
0015 #include "Acts/Navigation/NavigationDelegates.hpp"
0016 #include "Acts/Utilities/Enumerate.hpp"
0017 #include "Acts/Utilities/Grid.hpp"
0018 #include "Acts/Utilities/GridAxisGenerators.hpp"
0019 #include "Acts/Utilities/TypeList.hpp"
0020 #include "ActsPlugins/ActSVG/GridSvgConverter.hpp"
0021 #include "ActsPlugins/ActSVG/SurfaceSvgConverter.hpp"
0022 #include "ActsPlugins/ActSVG/SvgUtils.hpp"
0023 #include <actsvg/core.hpp>
0024 #include <actsvg/meta.hpp>
0025
0026 #include <tuple>
0027 #include <vector>
0028
0029 namespace ActsPlugins::Svg {
0030
0031 using ProtoSurface = actsvg::proto::surface<std::vector<Acts::Vector3>>;
0032 using ProtoSurfaces = std::vector<ProtoSurface>;
0033 using ProtoGrid = actsvg::proto::grid;
0034 using ProtoAssociations = std::vector<std::vector<std::size_t>>;
0035
0036 using ProtoIndexedSurfaceGrid =
0037 std::tuple<ProtoSurfaces, ProtoGrid, ProtoAssociations>;
0038
0039 namespace IndexedSurfacesConverter {
0040
0041 struct Options {
0042
0043 Acts::GeometryHierarchyMap<Style> surfaceStyles;
0044
0045 GridConverter::Options gridOptions;
0046 };
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 template <typename surface_container, typename index_grid>
0059 ProtoIndexedSurfaceGrid convertImpl(const Acts::GeometryContext& gctx,
0060 const surface_container& surfaces,
0061 const index_grid& indexGrid,
0062 const Options& cOptions) {
0063
0064 ProtoSurfaces pSurfaces;
0065 pSurfaces.reserve(surfaces.size());
0066
0067
0068
0069 GridConverter::Options gridOptions = cOptions.gridOptions;
0070 Acts::Extent constrain;
0071
0072
0073
0074
0075 bool estimateR = (index_grid::grid_type::DIM == 1 &&
0076 indexGrid.casts[0u] == Acts::AxisDirection::AxisPhi) ||
0077 (index_grid::grid_type::DIM == 2 &&
0078 (indexGrid.casts[0u] == Acts::AxisDirection::AxisPhi ||
0079 indexGrid.casts[1u] == Acts::AxisDirection::AxisPhi));
0080
0081 for (auto [is, s] : Acts::enumerate(surfaces)) {
0082
0083 SurfaceConverter::Options sOptions;
0084
0085 auto sfIter = cOptions.surfaceStyles.find(s->geometryId());
0086 if (sfIter != cOptions.surfaceStyles.end()) {
0087 sOptions.style = *sfIter;
0088 }
0089 auto pSurface = SurfaceConverter::convert(gctx, *s, sOptions);
0090
0091 if (estimateR) {
0092 auto sExtent = s->polyhedronRepresentation(gctx, 4u).extent();
0093 if constexpr (index_grid::grid_type::DIM == 2u) {
0094 pSurface._radii[0u] =
0095 static_cast<float>(sExtent.medium(Acts::AxisDirection::AxisR));
0096 }
0097 constrain.extend(sExtent, {Acts::AxisDirection::AxisR});
0098 }
0099
0100 std::string centerInfo = " - center = (";
0101 const Acts::Vector3& center = s->center(gctx);
0102 centerInfo +=
0103 std::to_string(Acts::VectorHelpers::cast(center, indexGrid.casts[0u]));
0104 if (indexGrid.casts.size() > 1u) {
0105 centerInfo += ", ";
0106 centerInfo += std::to_string(
0107 Acts::VectorHelpers::cast(center, indexGrid.casts[1u]));
0108 centerInfo += ")";
0109 }
0110 pSurface._aux_info["center"] = {centerInfo};
0111
0112 pSurfaces.push_back(pSurface);
0113 }
0114
0115
0116 if constexpr (index_grid::grid_type::DIM == 1u) {
0117 if (indexGrid.casts[0u] == Acts::AxisDirection::AxisPhi) {
0118 auto estRangeR = constrain.range(Acts::AxisDirection::AxisR);
0119 std::array<double, 2u> rRange = {estRangeR.min(), estRangeR.max()};
0120 gridOptions.optionalBound = {rRange, Acts::AxisDirection::AxisR};
0121 }
0122 }
0123
0124
0125 ProtoGrid pGrid =
0126 GridConverter::convert(indexGrid.grid, indexGrid.casts, gridOptions);
0127
0128 auto axes = indexGrid.grid.axes();
0129
0130
0131 ProtoAssociations highlightIndices;
0132
0133
0134 if constexpr (index_grid::grid_type::DIM == 1u) {
0135 const auto& binEdges = axes[0u]->getBinEdges();
0136 for (unsigned int ib0 = 1u; ib0 <= axes[0u]->getNBins(); ++ib0) {
0137 typename index_grid::grid_type::index_t lbin;
0138 lbin[0u] = ib0;
0139 highlightIndices.push_back(indexGrid.grid.atLocalBins(lbin));
0140
0141 std::string binInfo =
0142 std::string("- bin : [") + std::to_string(ib0) + std::string("]");
0143 double binCenter = 0.5 * (binEdges[ib0] + binEdges[ib0 - 1u]);
0144 binInfo += "\n - center : (" + std::to_string(binCenter) + ")";
0145 pGrid._bin_ids.push_back(binInfo);
0146 }
0147 }
0148
0149 if constexpr (index_grid::grid_type::DIM == 2u) {
0150 const auto& binEdges0 = axes[0u]->getBinEdges();
0151 const auto& binEdges1 = axes[1u]->getBinEdges();
0152 for (unsigned int ib0 = 1u; ib0 <= axes[0u]->getNBins(); ++ib0) {
0153 for (unsigned int ib1 = 1u; ib1 <= axes[1u]->getNBins(); ++ib1) {
0154 typename index_grid::grid_type::index_t lbin;
0155 lbin[0u] = ib0;
0156 lbin[1u] = ib1;
0157 highlightIndices.push_back(indexGrid.grid.atLocalBins(lbin));
0158
0159 std::string binInfo = std::string("- bin : [") + std::to_string(ib0) +
0160 std::string(", ") + std::to_string(ib1) +
0161 std::string("]");
0162 double binCenter0 = 0.5 * (binEdges0[ib0] + binEdges0[ib0 - 1u]);
0163 double binCenter1 = 0.5 * (binEdges1[ib1] + binEdges1[ib1 - 1u]);
0164 binInfo += "\n - center : (" + std::to_string(binCenter0) + ", " +
0165 std::to_string(binCenter1) + ")";
0166 pGrid._bin_ids.push_back(binInfo);
0167 if (estimateR) {
0168 pGrid._reference_r =
0169 static_cast<float>(constrain.medium(Acts::AxisDirection::AxisR));
0170 }
0171 }
0172 }
0173 }
0174 return {pSurfaces, pGrid, highlightIndices};
0175 }
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190 template <typename surface_container, typename instance_type>
0191 void convert(const Acts::GeometryContext& gctx,
0192 const surface_container& surfaces, const Options& cOptions,
0193 ProtoIndexedSurfaceGrid& sgi,
0194 const Acts::Experimental::InternalNavigationDelegate& delegate,
0195 [[maybe_unused]] const instance_type& refInstance) {
0196 using GridType =
0197 typename instance_type::template grid_type<std::vector<std::size_t>>;
0198
0199 using DelegateType = Acts::Experimental::IndexedSurfacesAllPortalsNavigation<
0200 GridType, Acts::Experimental::IndexedSurfacesNavigation>;
0201 using SubDelegateType =
0202 Acts::Experimental::IndexedSurfacesNavigation<GridType>;
0203
0204
0205 const auto* instance = delegate.instance();
0206 auto castedDelegate = dynamic_cast<const DelegateType*>(instance);
0207 if (castedDelegate != nullptr) {
0208
0209 auto indexedSurfaces = std::get<SubDelegateType>(castedDelegate->updators);
0210 auto [pSurfaces, pGrid, pIndices] =
0211 convertImpl(gctx, surfaces, indexedSurfaces, cOptions);
0212 std::get<0u>(sgi) = pSurfaces;
0213 std::get<1u>(sgi) = pGrid;
0214 std::get<2u>(sgi) = pIndices;
0215 }
0216 }
0217
0218
0219
0220
0221 template <typename surface_container, typename... Args>
0222 void unrollConvert(
0223 const Acts::GeometryContext& gctx, const surface_container& surfaces,
0224 const Options& cOptions, ProtoIndexedSurfaceGrid& sgi,
0225 const Acts::Experimental::InternalNavigationDelegate& delegate,
0226 Acts::TypeList<Args...> ) {
0227 (convert(gctx, surfaces, cOptions, sgi, delegate, Args{}), ...);
0228 }
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241 template <typename surface_container>
0242 ProtoIndexedSurfaceGrid convert(
0243 const Acts::GeometryContext& gctx, const surface_container& surfaces,
0244 const Acts::Experimental::InternalNavigationDelegate& delegate,
0245 const Options& cOptions) {
0246
0247 ProtoSurfaces pSurfaces;
0248 ProtoGrid pGrid;
0249 ProtoAssociations indices;
0250 ProtoIndexedSurfaceGrid sgi = {pSurfaces, pGrid, indices};
0251
0252 unrollConvert(gctx, surfaces, cOptions, sgi, delegate,
0253 Acts::GridAxisGenerators::PossibleAxes{});
0254
0255 return sgi;
0256 }
0257
0258 }
0259
0260 namespace View {
0261
0262
0263
0264
0265
0266
0267
0268 static inline actsvg::svg::object xy(const ProtoIndexedSurfaceGrid& pIndexGrid,
0269 const std::string& identification) {
0270 auto [pSurfaces, pGrid, pIndices] = pIndexGrid;
0271
0272
0273 actsvg::svg::object xyIndexedGrid;
0274 xyIndexedGrid._id = identification;
0275 xyIndexedGrid._tag = "g";
0276
0277
0278 std::vector<actsvg::svg::object> sObs;
0279 for (const auto& s : pSurfaces) {
0280 if (pGrid._type == ProtoGrid::e_z_phi) {
0281 sObs.push_back(zrphi(s, s._name));
0282 } else {
0283 sObs.push_back(xy(s, s._name));
0284 }
0285 }
0286
0287
0288 auto gOb =
0289 actsvg::display::grid(identification + std::string("_grid"), pGrid);
0290
0291
0292 actsvg::connectors::connect_action(gOb._sub_objects, sObs, pIndices);
0293
0294
0295 xyIndexedGrid.add_objects(sObs);
0296
0297 auto xmax = xyIndexedGrid._x_range[1u];
0298
0299 for (auto [ig, gTile] : Acts::enumerate(gOb._sub_objects)) {
0300
0301 std::vector<std::string> binText;
0302 binText.push_back("Source:");
0303 binText.push_back(pGrid._bin_ids[ig]);
0304 binText.push_back("Target:");
0305 for (const auto [is, sis] : Acts::enumerate(pIndices[ig])) {
0306 const auto& ps = pSurfaces[sis];
0307 std::string oInfo = std::string("- object: ") + std::to_string(sis);
0308 if (ps._aux_info.contains("center")) {
0309 for (const auto& ci : ps._aux_info.at("center")) {
0310 oInfo += ci;
0311 }
0312 }
0313 binText.push_back(oInfo);
0314 }
0315
0316 std::string cTextId =
0317 identification + std::string("_ct_") + std::to_string(ig);
0318 auto cText = actsvg::draw::connected_text(
0319 cTextId, {static_cast<actsvg::scalar>(1.1 * xmax), 0}, binText,
0320 actsvg::style::font{}, actsvg::style::transform{}, gTile);
0321 xyIndexedGrid.add_object(cText);
0322 }
0323 xyIndexedGrid.add_object(gOb);
0324
0325 return xyIndexedGrid;
0326 }
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337 static inline actsvg::svg::object zphi(
0338 const ProtoIndexedSurfaceGrid& pIndexGrid,
0339 const std::string& identification) {
0340 return xy(pIndexGrid, identification);
0341 }
0342
0343 }
0344 }