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