File indexing completed on 2025-07-02 07:50:48
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Direction.hpp"
0012 #include "Acts/Definitions/Units.hpp"
0013 #include "Acts/Geometry/Layer.hpp"
0014 #include "Acts/Geometry/TrackingGeometry.hpp"
0015 #include "Acts/Geometry/TrackingVolume.hpp"
0016 #include "Acts/Propagator/NavigationTarget.hpp"
0017 #include "Acts/Propagator/NavigatorOptions.hpp"
0018 #include "Acts/Propagator/NavigatorStatistics.hpp"
0019 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0020 #include "Acts/Surfaces/Surface.hpp"
0021 #include "Acts/Utilities/Intersection.hpp"
0022 #include "Acts/Utilities/Logger.hpp"
0023 #include "Acts/Utilities/Result.hpp"
0024
0025 #include <limits>
0026 #include <memory>
0027 #include <vector>
0028
0029 namespace Acts {
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 class DirectNavigator {
0040 public:
0041
0042 using SurfaceSequence = std::vector<const Surface*>;
0043
0044
0045 struct Config {};
0046
0047
0048 struct Options : public NavigatorPlainOptions {
0049 explicit Options(const GeometryContext& gctx)
0050 : NavigatorPlainOptions(gctx) {}
0051
0052
0053 SurfaceSequence surfaces;
0054
0055
0056 double surfaceTolerance = s_onSurfaceTolerance;
0057
0058
0059
0060
0061
0062 double nearLimit = -100 * UnitConstants::um;
0063
0064
0065 double farLimit = std::numeric_limits<double>::max();
0066
0067 void setPlainOptions(const NavigatorPlainOptions& options) {
0068 static_cast<NavigatorPlainOptions&>(*this) = options;
0069 }
0070 };
0071
0072
0073
0074
0075
0076
0077 struct State {
0078 explicit State(const Options& options_) : options(options_) {}
0079
0080 Options options;
0081
0082 Direction direction = Direction::Forward();
0083
0084
0085
0086
0087 int surfaceIndex = -1;
0088
0089
0090 const Surface* currentSurface = nullptr;
0091
0092
0093 bool navigationBreak = false;
0094
0095
0096 NavigatorStatistics statistics;
0097
0098 const Surface& navSurface() const {
0099 return *options.surfaces.at(surfaceIndex);
0100 }
0101
0102 void nextSurface() {
0103 if (direction == Direction::Forward()) {
0104 ++surfaceIndex;
0105 } else {
0106 --surfaceIndex;
0107 }
0108 }
0109
0110 bool endOfSurfaces() const {
0111 if (direction == Direction::Forward()) {
0112 return surfaceIndex >= static_cast<int>(options.surfaces.size());
0113 }
0114 return surfaceIndex < 0;
0115 }
0116
0117 int remainingSurfaces() const {
0118 if (direction == Direction::Forward()) {
0119 return options.surfaces.size() - surfaceIndex;
0120 }
0121 return surfaceIndex + 1;
0122 }
0123
0124 void resetSurfaceIndex() {
0125 surfaceIndex = direction == Direction::Forward()
0126 ? -1
0127 : static_cast<int>(options.surfaces.size());
0128 }
0129 };
0130
0131 explicit DirectNavigator(std::unique_ptr<const Logger> _logger =
0132 getDefaultLogger("DirectNavigator",
0133 Logging::INFO))
0134 : m_logger{std::move(_logger)} {}
0135
0136 State makeState(const Options& options) const {
0137 State state(options);
0138 return state;
0139 }
0140
0141 const Surface* currentSurface(const State& state) const {
0142 return state.currentSurface;
0143 }
0144
0145 const TrackingVolume* currentVolume(const State& ) const {
0146 return nullptr;
0147 }
0148
0149 const IVolumeMaterial* currentVolumeMaterial(const State& ) const {
0150 return nullptr;
0151 }
0152
0153 const Surface* startSurface(const State& state) const {
0154 return state.options.startSurface;
0155 }
0156
0157 const Surface* targetSurface(const State& state) const {
0158 return state.options.targetSurface;
0159 }
0160
0161 bool endOfWorldReached(State& ) const { return false; }
0162
0163 bool navigationBreak(const State& state) const {
0164 return state.navigationBreak;
0165 }
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 [[nodiscard]] Result<void> initialize(State& state, const Vector3& position,
0176 const Vector3& direction,
0177 Direction propagationDirection) const {
0178 (void)position;
0179 (void)direction;
0180
0181 ACTS_VERBOSE("Initialize. Surface sequence for navigation:");
0182 for (const Surface* surface : state.options.surfaces) {
0183 ACTS_VERBOSE(surface->geometryId()
0184 << " - "
0185 << surface->center(state.options.geoContext).transpose());
0186 }
0187
0188 state.direction = propagationDirection;
0189 ACTS_VERBOSE("Navigation direction is " << propagationDirection);
0190
0191
0192 state.currentSurface = state.options.startSurface;
0193 if (state.currentSurface != nullptr) {
0194 ACTS_VERBOSE("Current surface set to start surface "
0195 << state.currentSurface->geometryId());
0196 } else {
0197 ACTS_VERBOSE("Current surface set to nullptr");
0198 }
0199
0200
0201 auto found =
0202 std::ranges::find(state.options.surfaces, state.options.startSurface);
0203
0204 if (found != state.options.surfaces.end()) {
0205
0206
0207 state.surfaceIndex = std::distance(state.options.surfaces.begin(), found);
0208 state.surfaceIndex += state.direction == Direction::Backward() ? 1 : -1;
0209 } else {
0210 ACTS_DEBUG(
0211 "Did not find the start surface in the sequence. Assuming it is not "
0212 "part of the sequence. Trusting the correctness of the input "
0213 "sequence. Resetting the surface index.");
0214 state.resetSurfaceIndex();
0215 }
0216
0217 state.navigationBreak = false;
0218
0219 return Result<void>::success();
0220 }
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232 NavigationTarget nextTarget(State& state, const Vector3& position,
0233 const Vector3& direction) const {
0234
0235 state.currentSurface = nullptr;
0236
0237 if (state.navigationBreak) {
0238 return NavigationTarget::None();
0239 }
0240
0241 ACTS_VERBOSE("DirectNavigator::nextTarget");
0242
0243
0244 state.nextSurface();
0245
0246 if (!state.endOfSurfaces()) {
0247 ACTS_VERBOSE("Next surface candidate is "
0248 << state.navSurface().geometryId() << ". "
0249 << state.remainingSurfaces() << " out of "
0250 << state.options.surfaces.size()
0251 << " surfaces remain to try.");
0252 } else {
0253 ACTS_VERBOSE("End of surfaces reached, navigation break.");
0254 state.navigationBreak = true;
0255 return NavigationTarget::None();
0256 }
0257
0258
0259
0260 const Surface& surface = state.navSurface();
0261 const double farLimit = std::numeric_limits<double>::max();
0262 const auto intersection = chooseIntersection(
0263 state.options.geoContext, surface, position, direction,
0264 BoundaryTolerance::Infinite(), state.options.nearLimit, farLimit,
0265 state.options.surfaceTolerance);
0266 return NavigationTarget(surface, intersection.index(),
0267 BoundaryTolerance::Infinite());
0268 }
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280 bool checkTargetValid(const State& state, const Vector3& position,
0281 const Vector3& direction) const {
0282 (void)state;
0283 (void)position;
0284 (void)direction;
0285
0286 return true;
0287 }
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298 void handleSurfaceReached(State& state, const Vector3& position,
0299 const Vector3& direction,
0300 const Surface& surface) const {
0301 (void)position;
0302 (void)direction;
0303 (void)surface;
0304
0305 if (state.navigationBreak) {
0306 return;
0307 }
0308
0309 ACTS_VERBOSE("DirectNavigator::handleSurfaceReached");
0310
0311
0312 state.currentSurface = &state.navSurface();
0313 ACTS_VERBOSE("Current surface set to "
0314 << state.currentSurface->geometryId());
0315 }
0316
0317 private:
0318 ObjectIntersection<Surface> chooseIntersection(
0319 const GeometryContext& gctx, const Surface& surface,
0320 const Vector3& position, const Vector3& direction,
0321 const BoundaryTolerance& boundaryTolerance, double nearLimit,
0322 double farLimit, double tolerance) const {
0323 auto intersections = surface.intersect(gctx, position, direction,
0324 boundaryTolerance, tolerance);
0325
0326 for (auto& intersection : intersections.split()) {
0327 if (detail::checkPathLength(intersection.pathLength(), nearLimit,
0328 farLimit, logger())) {
0329 return intersection;
0330 }
0331 }
0332
0333 return ObjectIntersection<Surface>::invalid();
0334 }
0335
0336 const Logger& logger() const { return *m_logger; }
0337
0338 std::unique_ptr<const Logger> m_logger;
0339 };
0340
0341 }