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