File indexing completed on 2025-08-05 08:10:14
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Plugins/ActSVG/PortalSvgConverter.hpp"
0010
0011 #include "Acts/Detector/Portal.hpp"
0012 #include "Acts/Navigation/DetectorVolumeUpdaters.hpp"
0013 #include "Acts/Surfaces/RegularSurface.hpp"
0014
0015 namespace {
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 Acts::Svg::ProtoLink makeProtoLink(
0026 const Acts::Svg::PortalConverter::Options& portalOptions,
0027 const Acts::Vector3& position, const Acts::Vector3& direction,
0028 const Acts::Experimental::DetectorVolume* dVolume) {
0029 Acts::Svg::ProtoLink pLink;
0030 Acts::Vector3 end3 = position + portalOptions.linkLength * direction;
0031 pLink._start = {position.x(), position.y(), position.z()};
0032 pLink._end = {end3.x(), end3.y(), end3.z()};
0033 auto linkIndexCandidate = portalOptions.volumeIndices.find(dVolume);
0034 if (linkIndexCandidate != portalOptions.volumeIndices.end()) {
0035 pLink._link_index = linkIndexCandidate->second;
0036 }
0037 return pLink;
0038 }
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 std::vector<Acts::Svg::ProtoLink> convertMultiLink(
0051 const Acts::GeometryContext& gctx,
0052 const Acts::Experimental::BoundVolumesGrid1Impl& multiLink,
0053 const Acts::Surface& surface, const Acts::Vector3& refPosition,
0054 const Acts::Svg::PortalConverter::Options& portalOptions,
0055 int sign) noexcept(false) {
0056 const auto* regSurface = dynamic_cast<const Acts::RegularSurface*>(&surface);
0057 if (regSurface == nullptr) {
0058 throw std::invalid_argument(
0059 "convertMultiLink: surface is not RegularSurface.");
0060 }
0061
0062 std::vector<Acts::Svg::ProtoLink> pLinks;
0063 const auto& volumes = multiLink.indexedUpdater.extractor.dVolumes;
0064 const auto& casts = multiLink.indexedUpdater.casts;
0065
0066
0067 for (auto [il, v] : Acts::enumerate(volumes)) {
0068 Acts::Vector3 position = refPosition;
0069 if constexpr (decltype(multiLink.indexedUpdater)::grid_type::DIM == 1u) {
0070
0071 Acts::BinningValue bValue = casts[0u];
0072
0073 const auto& boundaries =
0074 multiLink.indexedUpdater.grid.axes()[0u]->getBinEdges();
0075
0076 Acts::ActsScalar refC = 0.5 * (boundaries[il + 1u] + boundaries[il]);
0077
0078 if (bValue == Acts::binR) {
0079 Acts::ActsScalar phi = Acts::VectorHelpers::phi(refPosition);
0080 position = Acts::Vector3(refC * std::cos(phi), refC * std::sin(phi),
0081 refPosition.z());
0082 } else if (bValue == Acts::binZ) {
0083 position[2] = refC;
0084
0085 refC += surface.transform(gctx).translation().z();
0086 } else if (bValue == Acts::binPhi) {
0087 Acts::ActsScalar r = Acts::VectorHelpers::perp(refPosition);
0088 position = Acts::Vector3(r * std::cos(refC), r * std::sin(refC),
0089 refPosition.z());
0090 } else {
0091 throw std::invalid_argument("convertMultiLink: incorrect binning.");
0092 }
0093 Acts::Vector3 direction = regSurface->normal(gctx, position);
0094 pLinks.push_back(makeProtoLink(portalOptions, position,
0095 Acts::Vector3(sign * direction), v));
0096 }
0097 }
0098 return pLinks;
0099 }
0100
0101 }
0102
0103 Acts::Svg::ProtoPortal Acts::Svg::PortalConverter::convert(
0104 const GeometryContext& gctx, const Experimental::Portal& portal,
0105 const PortalConverter::Options& portalOptions) {
0106 ProtoPortal pPortal;
0107
0108 pPortal._surface = SurfaceConverter::convert(gctx, portal.surface(),
0109 portalOptions.surfaceOptions);
0110
0111
0112 Vector3 rPos(0., 0., 0);
0113 Vector3 rDir(0., 0., 1);
0114 const auto& surface = portal.surface();
0115 const auto surfaceTransform = portal.surface().transform(gctx);
0116 const auto surfaceTranslation = surfaceTransform.translation().eval();
0117 const auto surfaceType = surface.bounds().type();
0118 const auto& boundValues = surface.bounds().values();
0119 switch (surfaceType) {
0120 case SurfaceBounds::eCylinder: {
0121
0122 ActsScalar r = boundValues[0u];
0123 ActsScalar aphi = boundValues[3u];
0124 rPos = Vector3(r * std::cos(aphi), r * std::sin(aphi),
0125 surfaceTranslation.z());
0126 } break;
0127 case SurfaceBounds::eDisc: {
0128
0129 ActsScalar r = 0.5 * (boundValues[0u] + boundValues[1u]);
0130 ActsScalar aphi = boundValues[3u];
0131 rPos = Vector3(r * std::cos(aphi), r * std::sin(aphi),
0132 surfaceTranslation.z());
0133 } break;
0134 default: {
0135 rPos = surfaceTranslation;
0136 } break;
0137 }
0138 rDir = surface.normal(gctx, rPos);
0139
0140
0141 const auto& updators = portal.detectorVolumeUpdaters();
0142
0143 int sign = -1;
0144 for (const auto& dvu : updators) {
0145
0146 const auto* instance = dvu.instance();
0147 auto singleLink =
0148 dynamic_cast<const Experimental::SingleDetectorVolumeImpl*>(instance);
0149 if (singleLink != nullptr) {
0150 pPortal._volume_links.push_back(makeProtoLink(
0151 portalOptions, rPos, Vector3(sign * rDir), singleLink->dVolume));
0152 }
0153 auto multiLink =
0154 dynamic_cast<const Experimental::BoundVolumesGrid1Impl*>(instance);
0155 if (multiLink != nullptr) {
0156 auto pLinks = convertMultiLink(gctx, *multiLink, surface, rPos,
0157 portalOptions, sign);
0158
0159 pPortal._volume_links.insert(pPortal._volume_links.end(), pLinks.begin(),
0160 pLinks.end());
0161 }
0162
0163 sign += 2;
0164 }
0165
0166
0167 return pPortal;
0168 }