File indexing completed on 2025-08-06 08:10:06
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Geometry/BoundarySurfaceT.hpp"
0012 #include "Acts/Geometry/Layer.hpp"
0013 #include "Acts/Geometry/TrackingGeometry.hpp"
0014 #include "Acts/Geometry/TrackingVolume.hpp"
0015 #include "Acts/Propagator/Propagator.hpp"
0016 #include "Acts/Surfaces/Surface.hpp"
0017 #include "Acts/Utilities/Intersection.hpp"
0018
0019 #include <algorithm>
0020 #include <iterator>
0021 #include <limits>
0022 #include <memory>
0023 #include <vector>
0024
0025 namespace Acts {
0026
0027
0028
0029
0030
0031
0032 class DirectNavigator {
0033 public:
0034
0035 using SurfaceSequence = std::vector<const Surface*>;
0036 using SurfaceIter = std::vector<const Surface*>::iterator;
0037
0038 DirectNavigator(std::unique_ptr<const Logger> _logger =
0039 getDefaultLogger("DirectNavigator", Logging::INFO))
0040 : m_logger{std::move(_logger)} {}
0041
0042
0043
0044
0045 struct Initializer {
0046
0047 SurfaceSequence navSurfaces = {};
0048
0049
0050 struct this_result {
0051 bool initialized = false;
0052 };
0053
0054 using result_type = this_result;
0055
0056
0057 Initializer() = default;
0058
0059
0060
0061
0062
0063
0064
0065
0066 template <typename propagator_state_t, typename stepper_t,
0067 typename navigator_t>
0068 void operator()(propagator_state_t& state, const stepper_t& ,
0069 const navigator_t& , result_type& r,
0070 const Logger& ) const {
0071
0072 if (!r.initialized) {
0073
0074 state.navigation.navSurfaces = navSurfaces;
0075 state.navigation.navSurfaceIter = state.navigation.navSurfaces.begin();
0076
0077
0078
0079
0080 if (state.navigation.startSurface) {
0081 auto surfaceIter = std::find(state.navigation.navSurfaces.begin(),
0082 state.navigation.navSurfaces.end(),
0083 state.navigation.startSurface);
0084
0085 if (surfaceIter != state.navigation.navSurfaces.end()) {
0086 state.navigation.navSurfaceIter = ++surfaceIter;
0087 }
0088 }
0089
0090 r.initialized = true;
0091 }
0092 }
0093 };
0094
0095
0096
0097
0098
0099
0100 struct State {
0101
0102 SurfaceSequence navSurfaces = {};
0103
0104
0105 SurfaceIter navSurfaceIter = navSurfaces.begin();
0106
0107
0108 const Surface* startSurface = nullptr;
0109
0110 const Surface* currentSurface = nullptr;
0111
0112 const Surface* targetSurface = nullptr;
0113
0114 const Layer* startLayer = nullptr;
0115
0116 const Layer* targetLayer = nullptr;
0117
0118 const TrackingVolume* startVolume = nullptr;
0119
0120 const TrackingVolume* currentVolume = nullptr;
0121
0122 const TrackingVolume* targetVolume = nullptr;
0123
0124
0125 bool targetReached = false;
0126
0127 bool navigationBreak = false;
0128 };
0129
0130 State makeState(const Surface* startSurface,
0131 const Surface* targetSurface) const {
0132 State result;
0133 result.startSurface = startSurface;
0134 result.targetSurface = targetSurface;
0135 return result;
0136 }
0137
0138 const Surface* currentSurface(const State& state) const {
0139 return state.currentSurface;
0140 }
0141
0142 const TrackingVolume* currentVolume(const State& state) const {
0143 return state.currentVolume;
0144 }
0145
0146 const IVolumeMaterial* currentVolumeMaterial(const State& state) const {
0147 if (state.currentVolume == nullptr) {
0148 return nullptr;
0149 }
0150 return state.currentVolume->volumeMaterial();
0151 }
0152
0153 const Surface* startSurface(const State& state) const {
0154 return state.startSurface;
0155 }
0156
0157 const Surface* targetSurface(const State& state) const {
0158 return state.targetSurface;
0159 }
0160
0161 bool targetReached(const State& state) const { return state.targetReached; }
0162
0163 bool endOfWorldReached(State& state) const {
0164 return state.currentVolume == nullptr;
0165 }
0166
0167 bool navigationBreak(const State& state) const {
0168 return state.navigationBreak;
0169 }
0170
0171 void currentSurface(State& state, const Surface* surface) const {
0172 state.currentSurface = surface;
0173 }
0174
0175 void targetReached(State& state, bool targetReached) const {
0176 state.targetReached = targetReached;
0177 }
0178
0179 void navigationBreak(State& state, bool navigationBreak) const {
0180 state.navigationBreak = navigationBreak;
0181 }
0182
0183
0184
0185
0186
0187
0188
0189 template <typename propagator_state_t, typename stepper_t>
0190 void initialize(propagator_state_t& state,
0191 const stepper_t& ) const {
0192 ACTS_VERBOSE(volInfo(state) << "initialize");
0193
0194
0195 state.navigation.currentSurface = state.navigation.startSurface;
0196 if (state.navigation.currentSurface) {
0197 ACTS_VERBOSE(volInfo(state)
0198 << "Current surface set to start surface "
0199 << state.navigation.currentSurface->geometryId());
0200 }
0201 }
0202
0203
0204
0205
0206
0207
0208
0209
0210 template <typename propagator_state_t, typename stepper_t>
0211 void preStep(propagator_state_t& state, const stepper_t& stepper) const {
0212 ACTS_VERBOSE(volInfo(state) << "pre step");
0213
0214
0215 state.navigation.currentSurface = nullptr;
0216
0217 ACTS_VERBOSE(std::distance(state.navigation.navSurfaceIter,
0218 state.navigation.navSurfaces.end())
0219 << " out of " << state.navigation.navSurfaces.size()
0220 << " surfaces remain to try.");
0221
0222 if (state.navigation.navSurfaceIter != state.navigation.navSurfaces.end()) {
0223
0224
0225 const auto& surface = **state.navigation.navSurfaceIter;
0226 const double farLimit = std::numeric_limits<double>::max();
0227 const auto index =
0228 chooseIntersection(
0229 state.geoContext, surface, stepper.position(state.stepping),
0230 state.options.direction * stepper.direction(state.stepping),
0231 BoundaryCheck(false), m_nearLimit, farLimit,
0232 state.options.surfaceTolerance)
0233 .index();
0234 auto surfaceStatus = stepper.updateSurfaceStatus(
0235 state.stepping, surface, index, state.options.direction,
0236 BoundaryCheck(false), state.options.surfaceTolerance, *m_logger);
0237 if (surfaceStatus == Intersection3D::Status::unreachable) {
0238 ACTS_VERBOSE(
0239 "Surface not reachable anymore, switching to next one in "
0240 "sequence");
0241
0242 ++state.navigation.navSurfaceIter;
0243 } else {
0244 ACTS_VERBOSE("Navigation stepSize set to "
0245 << stepper.outputStepSize(state.stepping));
0246 }
0247 } else {
0248
0249 state.navigation.navigationBreak = true;
0250
0251 if (state.navigation.targetSurface == nullptr) {
0252 state.navigation.targetReached = true;
0253
0254 ACTS_VERBOSE("No target Surface, job done.");
0255 }
0256 }
0257 }
0258
0259
0260
0261
0262
0263
0264
0265
0266 template <typename propagator_state_t, typename stepper_t>
0267 void postStep(propagator_state_t& state, const stepper_t& stepper) const {
0268 ACTS_VERBOSE(volInfo(state) << "post step");
0269
0270
0271 state.navigation.currentSurface = nullptr;
0272
0273 ACTS_VERBOSE(std::distance(state.navigation.navSurfaceIter,
0274 state.navigation.navSurfaces.end())
0275 << " out of " << state.navigation.navSurfaces.size()
0276 << " surfaces remain to try.");
0277
0278
0279 if (state.navigation.navSurfaceIter != state.navigation.navSurfaces.end()) {
0280
0281
0282 const auto& surface = **state.navigation.navSurfaceIter;
0283 const double farLimit = std::numeric_limits<double>::max();
0284 const auto index =
0285 chooseIntersection(
0286 state.geoContext, surface, stepper.position(state.stepping),
0287 state.options.direction * stepper.direction(state.stepping),
0288 BoundaryCheck(false), m_nearLimit, farLimit,
0289 state.options.surfaceTolerance)
0290 .index();
0291 auto surfaceStatus = stepper.updateSurfaceStatus(
0292 state.stepping, surface, index, state.options.direction,
0293 BoundaryCheck(false), state.options.surfaceTolerance, *m_logger);
0294 if (surfaceStatus == Intersection3D::Status::onSurface) {
0295
0296 state.navigation.currentSurface = *state.navigation.navSurfaceIter;
0297 ACTS_VERBOSE("Current surface set to "
0298 << state.navigation.currentSurface->geometryId())
0299
0300 ++state.navigation.navSurfaceIter;
0301 if (state.navigation.navSurfaceIter !=
0302 state.navigation.navSurfaces.end()) {
0303 ACTS_VERBOSE("Next surface candidate is "
0304 << (*state.navigation.navSurfaceIter)->geometryId());
0305 }
0306 } else if (surfaceStatus == Intersection3D::Status::reachable) {
0307 ACTS_VERBOSE("Next surface reachable at distance "
0308 << stepper.outputStepSize(state.stepping));
0309 }
0310 }
0311 }
0312
0313 private:
0314 template <typename propagator_state_t>
0315 std::string volInfo(const propagator_state_t& state) const {
0316 return (state.navigation.currentVolume != nullptr
0317 ? state.navigation.currentVolume->volumeName()
0318 : "No Volume") +
0319 " | ";
0320 }
0321
0322 ObjectIntersection<Surface> chooseIntersection(
0323 const GeometryContext& gctx, const Surface& surface,
0324 const Vector3& position, const Vector3& direction,
0325 const BoundaryCheck& bcheck, double nearLimit, double farLimit,
0326 double tolerance) const {
0327 auto intersections =
0328 surface.intersect(gctx, position, direction, bcheck, tolerance);
0329
0330 for (auto& intersection : intersections.split()) {
0331 if (detail::checkIntersection(intersection, nearLimit, farLimit,
0332 logger())) {
0333 return intersection;
0334 }
0335 }
0336
0337 return ObjectIntersection<Surface>::invalid();
0338 }
0339
0340 const Logger& logger() const { return *m_logger; }
0341
0342 std::unique_ptr<const Logger> m_logger;
0343
0344
0345
0346
0347
0348 double m_nearLimit = -100 * UnitConstants::um;
0349 };
0350
0351 }