File indexing completed on 2025-01-18 09:11:19
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 std::array<Acts::Experimental::ExternalNavigationDelegate, 2u>&
0037 Portal::portalNavigation() const {
0038 return m_portalNavigation;
0039 }
0040
0041 Portal::AttachedDetectorVolumes& Portal::attachedDetectorVolumes() {
0042 return m_attachedVolumes;
0043 }
0044
0045 void Portal::assignGeometryId(const GeometryIdentifier& geometryId) {
0046 m_surface->assignGeometryId(geometryId);
0047 }
0048
0049 std::shared_ptr<Portal> Portal::fuse(std::shared_ptr<Portal>& aPortal,
0050 std::shared_ptr<Portal>& bPortal) {
0051 if (aPortal == bPortal) {
0052 return aPortal;
0053 }
0054
0055 auto bothConnected = [](const auto& p) {
0056 return p.m_portalNavigation[0u].connected() &&
0057 p.m_portalNavigation[1u].connected();
0058 };
0059
0060 auto noneConnected = [](const auto& p) {
0061 return !p.m_portalNavigation[0u].connected() &&
0062 !p.m_portalNavigation[1u].connected();
0063 };
0064
0065 if (bothConnected(*aPortal) || bothConnected(*bPortal)) {
0066 throw std::invalid_argument(
0067 "Portal: trying to fuse two portals where at least one has links on "
0068 "both sides.");
0069 }
0070
0071 if (noneConnected(*aPortal) || noneConnected(*bPortal)) {
0072 throw std::invalid_argument(
0073 "Portal: trying to fuse two portals where at least one has no links.");
0074 }
0075
0076
0077
0078 std::shared_ptr<Portal> fused = std::make_shared<Portal>(aPortal->m_surface);
0079
0080
0081 Direction getA = (aPortal->m_portalNavigation[0].connected())
0082 ? Direction::fromIndex(0)
0083 : Direction::fromIndex(1);
0084 Direction getB = (bPortal->m_portalNavigation[0].connected())
0085 ? Direction::fromIndex(0)
0086 : Direction::fromIndex(1);
0087
0088
0089 Direction setA = getA;
0090 Direction setB = setA.invert();
0091
0092
0093 const auto& aSurface = aPortal->surface();
0094 const auto& bSurface = bPortal->surface();
0095
0096 if (aSurface.surfaceMaterial() != nullptr &&
0097 bSurface.surfaceMaterial() != nullptr) {
0098 throw std::runtime_error(
0099 "Portal: both surfaces have surface material, fusing will lead to "
0100 "information loss.");
0101 } else if (aSurface.surfaceMaterial() != nullptr) {
0102
0103 fused->m_surface = aPortal->m_surface;
0104 } else if (bSurface.surfaceMaterial() != nullptr) {
0105 fused->m_surface = bPortal->m_surface;
0106
0107 setB = getB;
0108 setA = setB.invert();
0109 }
0110
0111 fused->m_portalNavigation[setA.index()] =
0112 std::move(aPortal->m_portalNavigation[getA.index()]);
0113 fused->m_attachedVolumes[setA.index()] =
0114 std::move(aPortal->m_attachedVolumes[getA.index()]);
0115
0116 fused->m_portalNavigation[setB.index()] =
0117 std::move(bPortal->m_portalNavigation[getB.index()]);
0118 fused->m_attachedVolumes[setB.index()] =
0119 std::move(bPortal->m_attachedVolumes[getB.index()]);
0120
0121 return fused;
0122 }
0123
0124 void Portal::assignPortalNavigation(
0125 Direction dir, ExternalNavigationDelegate portalNavigation,
0126 std::vector<std::shared_ptr<DetectorVolume>> attachedVolumes) {
0127 auto idx = dir.index();
0128 m_portalNavigation[idx] = std::move(portalNavigation);
0129 m_attachedVolumes[idx] = std::move(attachedVolumes);
0130 }
0131
0132 void Portal::assignPortalNavigation(
0133 ExternalNavigationDelegate portalNavigation,
0134 std::vector<std::shared_ptr<DetectorVolume>> attachedVolumes) {
0135
0136 if (!m_portalNavigation[0u].connected() &&
0137 !m_portalNavigation[1u].connected()) {
0138 throw std::runtime_error("Portal: portal has no link on either side.");
0139 }
0140 if (m_portalNavigation[0u].connected() &&
0141 m_portalNavigation[1u].connected()) {
0142 throw std::runtime_error("Portal: portal already has links on both sides.");
0143 }
0144 std::size_t idx = m_portalNavigation[0u].connected() ? 1u : 0u;
0145 m_portalNavigation[idx] = std::move(portalNavigation);
0146 m_attachedVolumes[idx] = std::move(attachedVolumes);
0147 }
0148
0149 void Portal::updateDetectorVolume(const GeometryContext& gctx,
0150 NavigationState& nState) const {
0151 const auto& position = nState.position;
0152 const auto& direction = nState.direction;
0153 const Vector3 normal = surface().normal(gctx, position);
0154 Direction dir = Direction::fromScalar(normal.dot(direction));
0155 const auto& vUpdater = m_portalNavigation[dir.index()];
0156 if (vUpdater.connected()) {
0157 vUpdater(gctx, nState);
0158 } else {
0159 nState.currentVolume = nullptr;
0160 }
0161 }
0162
0163 }