File indexing completed on 2025-08-05 08:09:34
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Detector/Portal.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Navigation/NavigationState.hpp"
0013 #include "Acts/Surfaces/Surface.hpp"
0014 #include "Acts/Utilities/Delegate.hpp"
0015 #include "Acts/Utilities/ThrowAssert.hpp"
0016
0017 #include <cstddef>
0018 #include <stdexcept>
0019 #include <utility>
0020
0021 namespace Acts::Experimental {
0022
0023 Portal::Portal(std::shared_ptr<RegularSurface> surface)
0024 : m_surface(std::move(surface)) {
0025 throw_assert(m_surface, "Portal surface is nullptr");
0026 }
0027
0028 const Acts::RegularSurface& Portal::surface() const {
0029 return *m_surface.get();
0030 }
0031
0032 Acts::RegularSurface& Portal::surface() {
0033 return *m_surface.get();
0034 }
0035
0036 const Portal::DetectorVolumeUpdaters& Portal::detectorVolumeUpdaters() const {
0037 return m_volumeUpdaters;
0038 }
0039
0040 Portal::AttachedDetectorVolumes& Portal::attachedDetectorVolumes() {
0041 return m_attachedVolumes;
0042 }
0043
0044 void Portal::assignGeometryId(const GeometryIdentifier& geometryId) {
0045 m_surface->assignGeometryId(geometryId);
0046 }
0047
0048 std::shared_ptr<Portal> Portal::fuse(std::shared_ptr<Portal>& aPortal,
0049 std::shared_ptr<Portal>& bPortal) {
0050 if (aPortal == bPortal) {
0051 return aPortal;
0052 }
0053
0054 auto bothConnected = [](const auto& p) {
0055 return p.m_volumeUpdaters[0u].connected() &&
0056 p.m_volumeUpdaters[1u].connected();
0057 };
0058
0059 auto noneConnected = [](const auto& p) {
0060 return !p.m_volumeUpdaters[0u].connected() &&
0061 !p.m_volumeUpdaters[1u].connected();
0062 };
0063
0064 if (bothConnected(*aPortal) || bothConnected(*bPortal)) {
0065 throw std::invalid_argument(
0066 "Portal: trying to fuse two portals where at least one has links on "
0067 "both sides.");
0068 }
0069
0070 if (noneConnected(*aPortal) || noneConnected(*bPortal)) {
0071 throw std::invalid_argument(
0072 "Portal: trying to fuse two portals where at least one has no links.");
0073 }
0074
0075
0076
0077 std::shared_ptr<Portal> fused = std::make_shared<Portal>(aPortal->m_surface);
0078
0079
0080 Direction getA = (aPortal->m_volumeUpdaters[0].connected())
0081 ? Direction::fromIndex(0)
0082 : Direction::fromIndex(1);
0083 Direction getB = (bPortal->m_volumeUpdaters[0].connected())
0084 ? Direction::fromIndex(0)
0085 : Direction::fromIndex(1);
0086
0087
0088 Direction setA = getA;
0089 Direction setB = setA.invert();
0090
0091
0092 const auto& aSurface = aPortal->surface();
0093 const auto& bSurface = bPortal->surface();
0094
0095 if (aSurface.surfaceMaterial() != nullptr &&
0096 bSurface.surfaceMaterial() != nullptr) {
0097 throw std::runtime_error(
0098 "Portal: both surfaces have surface material, fusing will lead to "
0099 "information loss.");
0100 } else if (aSurface.surfaceMaterial() != nullptr) {
0101
0102 fused->m_surface = aPortal->m_surface;
0103 } else if (bSurface.surfaceMaterial() != nullptr) {
0104 fused->m_surface = bPortal->m_surface;
0105
0106 setB = getB;
0107 setA = setB.invert();
0108 }
0109
0110 fused->m_volumeUpdaters[setA.index()] =
0111 std::move(aPortal->m_volumeUpdaters[getA.index()]);
0112 fused->m_attachedVolumes[setA.index()] =
0113 std::move(aPortal->m_attachedVolumes[getA.index()]);
0114
0115 fused->m_volumeUpdaters[setB.index()] =
0116 std::move(bPortal->m_volumeUpdaters[getB.index()]);
0117 fused->m_attachedVolumes[setB.index()] =
0118 std::move(bPortal->m_attachedVolumes[getB.index()]);
0119
0120 return fused;
0121 }
0122
0123 void Portal::assignDetectorVolumeUpdater(
0124 Direction dir, DetectorVolumeUpdater dVolumeUpdater,
0125 std::vector<std::shared_ptr<DetectorVolume>> attachedVolumes) {
0126 auto idx = dir.index();
0127 m_volumeUpdaters[idx] = std::move(dVolumeUpdater);
0128 m_attachedVolumes[idx] = std::move(attachedVolumes);
0129 }
0130
0131 void Portal::assignDetectorVolumeUpdater(
0132 DetectorVolumeUpdater dVolumeUpdater,
0133 std::vector<std::shared_ptr<DetectorVolume>> attachedVolumes) {
0134
0135 if (!m_volumeUpdaters[0u].connected() && !m_volumeUpdaters[1u].connected()) {
0136 throw std::runtime_error("Portal: portal has no link on either side.");
0137 }
0138 if (m_volumeUpdaters[0u].connected() && m_volumeUpdaters[1u].connected()) {
0139 throw std::runtime_error("Portal: portal already has links on both sides.");
0140 }
0141 std::size_t idx = m_volumeUpdaters[0u].connected() ? 1u : 0u;
0142 m_volumeUpdaters[idx] = std::move(dVolumeUpdater);
0143 m_attachedVolumes[idx] = std::move(attachedVolumes);
0144 }
0145
0146 void Portal::updateDetectorVolume(const GeometryContext& gctx,
0147 NavigationState& nState) const {
0148 const auto& position = nState.position;
0149 const auto& direction = nState.direction;
0150 const Vector3 normal = surface().normal(gctx, position);
0151 Direction dir = Direction::fromScalar(normal.dot(direction));
0152 const auto& vUpdater = m_volumeUpdaters[dir.index()];
0153 if (vUpdater.connected()) {
0154 vUpdater(gctx, nState);
0155 } else {
0156 nState.currentVolume = nullptr;
0157 }
0158 }
0159
0160 }