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