File indexing completed on 2026-04-20 07:46:27
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Geometry/GeometryContext.hpp"
0012 #include "Acts/Navigation/NavigationDelegate.hpp"
0013 #include "Acts/Navigation/NavigationStream.hpp"
0014 #include "Acts/Utilities/Any.hpp"
0015
0016 #include <type_traits>
0017
0018 namespace Acts {
0019
0020 class TrackingVolume;
0021 class INavigationPolicy;
0022 class Surface;
0023 class Navigator;
0024
0025 class NavigationPolicyStateManager;
0026
0027
0028
0029
0030
0031 class NavigationPolicyState {
0032 public:
0033
0034
0035
0036 template <typename T>
0037 T& as() {
0038 return std::any_cast<T&>(payload());
0039 }
0040
0041
0042
0043
0044 template <typename T>
0045 const T& as() const {
0046 return std::any_cast<T&>(payload());
0047 }
0048
0049 NavigationPolicyState() = default;
0050
0051
0052
0053 bool empty() const { return m_manager == nullptr; }
0054
0055 private:
0056 NavigationPolicyState(NavigationPolicyStateManager& manager,
0057 std::size_t index)
0058 : m_manager(&manager), m_index(index) {}
0059
0060 std::any& payload();
0061 const std::any& payload() const;
0062
0063 NavigationPolicyStateManager* m_manager = nullptr;
0064 std::size_t m_index = 0;
0065
0066 friend class NavigationPolicyStateManager;
0067 };
0068
0069
0070
0071
0072
0073 class NavigationPolicyStateManager {
0074 public:
0075
0076
0077
0078
0079
0080 template <typename T, typename... Args>
0081 T& pushState(Args&&... args) {
0082 std::any& state = m_stateStack.emplace_back();
0083 return state.emplace<T>(std::forward<Args>(args)...);
0084 }
0085
0086 friend class Navigator;
0087
0088
0089
0090 NavigationPolicyState currentState() {
0091 if (m_stateStack.empty()) {
0092 return {};
0093 }
0094 return NavigationPolicyState{*this, m_stateStack.size() - 1};
0095 }
0096
0097
0098
0099 void popState() {
0100 if (m_stateStack.empty()) {
0101 throw std::runtime_error(
0102 "NavigationPolicyStateManager: Attempt to pop from empty stack");
0103 }
0104 m_stateStack.pop_back();
0105 }
0106
0107
0108 void reset() { m_stateStack.clear(); }
0109
0110 private:
0111 friend class NavigationPolicyState;
0112
0113
0114 std::vector<std::any> m_stateStack;
0115 };
0116
0117 inline std::any& NavigationPolicyState::payload() {
0118 if (m_manager == nullptr) {
0119 throw std::runtime_error(
0120 "NavigationPolicyState: Attempt to access empty payload");
0121 }
0122 return m_manager->m_stateStack.at(m_index);
0123 }
0124
0125 inline const std::any& NavigationPolicyState::payload() const {
0126 if (m_manager == nullptr) {
0127 throw std::runtime_error(
0128 "NavigationPolicyState: Attempt to access empty payload");
0129 }
0130 return m_manager->m_stateStack.at(m_index);
0131 }
0132
0133 namespace detail {
0134 template <typename T>
0135 concept HasOldInitializeCandidates = requires {
0136 requires requires(T policy, const GeometryContext& gctx,
0137 const NavigationArguments& args,
0138 AppendOnlyNavigationStream& stream, const Logger& logger) {
0139 policy.initializeCandidates(gctx, args, stream, logger);
0140 };
0141 };
0142
0143 template <typename T>
0144 concept HasNewInitializeCandidates = requires {
0145 requires requires(T policy, const GeometryContext& gctx,
0146 const NavigationArguments& args,
0147 NavigationPolicyState& state,
0148 AppendOnlyNavigationStream& stream, const Logger& logger) {
0149 policy.initializeCandidates(gctx, args, state, stream, logger);
0150 };
0151 };
0152
0153 template <detail::HasOldInitializeCandidates T>
0154 void oldToNewSignatureAdapter(const void* instance, const GeometryContext& gctx,
0155 const NavigationArguments& args,
0156 NavigationPolicyState& ,
0157 AppendOnlyNavigationStream& stream,
0158 const Logger& logger) {
0159 const auto* policy = static_cast<const T*>(instance);
0160 policy->initializeCandidates(gctx, args, stream, logger);
0161 }
0162 }
0163
0164
0165
0166
0167 template <typename T>
0168 concept NavigationPolicyConcept = requires {
0169 requires std::is_base_of_v<INavigationPolicy, T>;
0170
0171
0172 requires(detail::HasOldInitializeCandidates<T> ||
0173 detail::HasNewInitializeCandidates<T>);
0174 };
0175
0176
0177
0178
0179
0180
0181 class INavigationPolicy {
0182 public:
0183
0184
0185 static void noopInitializeCandidates(
0186 const GeometryContext& , const NavigationArguments& ,
0187 NavigationPolicyState& ,
0188 const AppendOnlyNavigationStream& , const Logger& ) {
0189
0190 }
0191
0192
0193 virtual ~INavigationPolicy() = default;
0194
0195
0196
0197
0198
0199 virtual void connect(NavigationDelegate& delegate) const = 0;
0200
0201
0202
0203
0204
0205 virtual void visit(
0206 const std::function<void(const INavigationPolicy&)>& visitor) const {
0207 visitor(*this);
0208 }
0209
0210
0211
0212
0213
0214
0215
0216 virtual bool isValid([[maybe_unused]] const GeometryContext& gctx,
0217 [[maybe_unused]] const NavigationArguments& args,
0218 [[maybe_unused]] NavigationPolicyState& state,
0219 const Logger& logger) const {
0220 ACTS_VERBOSE("Default navigation policy isValid check. (always true)");
0221 return true;
0222 }
0223
0224 struct EmptyState {};
0225
0226
0227
0228
0229
0230
0231 virtual void createState([[maybe_unused]] const GeometryContext& gctx,
0232 [[maybe_unused]] const NavigationArguments& args,
0233 NavigationPolicyStateManager& stateManager,
0234 const Logger& logger) const {
0235 ACTS_VERBOSE(
0236 "Default navigation policy state initialization. (empty state)");
0237 stateManager.pushState<EmptyState>();
0238 }
0239
0240
0241
0242
0243 virtual void popState(NavigationPolicyStateManager& stateManager,
0244 const Logger& logger) const {
0245
0246 ACTS_VERBOSE("Default navigation policy pop state. (pops empty state)");
0247 stateManager.popState();
0248
0249
0250 }
0251
0252 protected:
0253
0254
0255
0256
0257
0258 template <NavigationPolicyConcept T>
0259 void connectDefault(NavigationDelegate& delegate) const {
0260
0261 const auto* self = static_cast<const T*>(this);
0262
0263 if constexpr (detail::HasNewInitializeCandidates<T>) {
0264 delegate.template connect<&T::initializeCandidates>(self);
0265 } else {
0266
0267 delegate.connect(&detail::oldToNewSignatureAdapter<T>, self);
0268 }
0269 }
0270 };
0271
0272 }