File indexing completed on 2025-12-15 09:42:15
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/Layer.hpp"
0013 #include "Acts/Geometry/TrackingGeometry.hpp"
0014 #include "Acts/Geometry/TrackingVolume.hpp"
0015 #include "Acts/Propagator/NavigationTarget.hpp"
0016 #include "Acts/Propagator/NavigatorOptions.hpp"
0017 #include "Acts/Propagator/NavigatorStatistics.hpp"
0018 #include "Acts/Propagator/detail/NavigationHelpers.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/StringHelpers.hpp"
0025
0026 #include <algorithm>
0027 #include <cstdint>
0028 #include <limits>
0029 #include <memory>
0030 #include <vector>
0031
0032 namespace Acts {
0033
0034
0035
0036
0037
0038
0039 class TryAllNavigatorBase {
0040 public:
0041
0042 struct Config {
0043
0044 std::shared_ptr<const TrackingGeometry> trackingGeometry;
0045
0046
0047 bool resolveSensitive = true;
0048
0049 bool resolveMaterial = true;
0050
0051 bool resolvePassive = false;
0052
0053
0054 BoundaryTolerance boundaryToleranceSurfaceApproach =
0055 BoundaryTolerance::None();
0056 };
0057
0058
0059 struct Options : public NavigatorPlainOptions {
0060
0061
0062 explicit Options(const GeometryContext& gctx)
0063 : NavigatorPlainOptions(gctx) {}
0064
0065
0066 double surfaceTolerance = s_onSurfaceTolerance;
0067
0068
0069 double nearLimit = s_onSurfaceTolerance;
0070
0071
0072 double farLimit = std::numeric_limits<double>::max();
0073
0074
0075
0076 void setPlainOptions(const NavigatorPlainOptions& options) {
0077 static_cast<NavigatorPlainOptions&>(*this) = options;
0078 }
0079 };
0080
0081
0082
0083
0084
0085 struct State {
0086
0087
0088 explicit State(const Options& options_) : options(options_) {}
0089
0090
0091 Options options;
0092
0093
0094
0095
0096
0097 const Surface* startSurface = nullptr;
0098
0099
0100
0101
0102
0103 const Surface* targetSurface = nullptr;
0104
0105
0106
0107
0108 const Surface* currentSurface = nullptr;
0109
0110 const TrackingVolume* currentVolume = nullptr;
0111
0112
0113 std::vector<detail::NavigationObjectCandidate> navigationCandidates;
0114
0115
0116 bool navigationBreak = false;
0117
0118
0119 NavigatorStatistics statistics;
0120 };
0121
0122
0123
0124
0125
0126 TryAllNavigatorBase(Config cfg, std::unique_ptr<const Logger> logger)
0127 : m_cfg(std::move(cfg)), m_logger{std::move(logger)} {}
0128
0129
0130
0131
0132 const Surface* currentSurface(const State& state) const {
0133 return state.currentSurface;
0134 }
0135
0136
0137
0138
0139 const TrackingVolume* currentVolume(const State& state) const {
0140 return state.currentVolume;
0141 }
0142
0143
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
0154
0155
0156 const Surface* startSurface(const State& state) const {
0157 return state.startSurface;
0158 }
0159
0160
0161
0162
0163 const Surface* targetSurface(const State& state) const {
0164 return state.targetSurface;
0165 }
0166
0167
0168
0169
0170 bool endOfWorldReached(State& state) const {
0171 return state.currentVolume == nullptr;
0172 }
0173
0174
0175
0176
0177 bool navigationBreak(const State& state) const {
0178 return state.navigationBreak;
0179 }
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 [[nodiscard]] Result<void> initialize(State& state, const Vector3& position,
0192 const Vector3& direction,
0193 Direction propagationDirection) const {
0194 (void)propagationDirection;
0195
0196 ACTS_VERBOSE("initialize");
0197
0198 state.startSurface = state.options.startSurface;
0199 state.targetSurface = state.options.targetSurface;
0200
0201 const TrackingVolume* startVolume = nullptr;
0202
0203 if (state.startSurface != nullptr &&
0204 state.startSurface->associatedLayer() != nullptr) {
0205 ACTS_VERBOSE(
0206 "Fast start initialization through association from Surface.");
0207 const auto* startLayer = state.startSurface->associatedLayer();
0208 startVolume = startLayer->trackingVolume();
0209 } else {
0210 ACTS_VERBOSE("Slow start initialization through search.");
0211 ACTS_VERBOSE("Starting from position " << toString(position)
0212 << " and direction "
0213 << toString(direction));
0214 startVolume = m_cfg.trackingGeometry->lowestTrackingVolume(
0215 state.options.geoContext, position);
0216 }
0217
0218
0219 {
0220 state.currentVolume = startVolume;
0221 if (state.currentVolume != nullptr) {
0222 ACTS_VERBOSE(volInfo(state) << "Start volume resolved.");
0223 } else {
0224 ACTS_ERROR("Start volume not resolved.");
0225 }
0226
0227 state.currentSurface = state.startSurface;
0228 if (state.currentSurface != nullptr) {
0229 ACTS_VERBOSE(volInfo(state) << "Current surface set to start surface "
0230 << state.currentSurface->geometryId());
0231 } else {
0232 ACTS_VERBOSE(volInfo(state) << "No start surface set.");
0233 }
0234 }
0235
0236 return Result<void>::success();
0237 }
0238
0239 protected:
0240
0241
0242 void initializeVolumeCandidates(State& state) const {
0243 const TrackingVolume* volume = state.currentVolume;
0244 ACTS_VERBOSE(volInfo(state) << "Initialize volume");
0245
0246 if (volume == nullptr) {
0247 state.navigationBreak = true;
0248 ACTS_VERBOSE(volInfo(state) << "No volume set. Good luck.");
0249 return;
0250 }
0251
0252 emplaceAllVolumeCandidates(
0253 state.navigationCandidates, *volume, m_cfg.resolveSensitive,
0254 m_cfg.resolveMaterial, m_cfg.resolvePassive,
0255 m_cfg.boundaryToleranceSurfaceApproach, logger());
0256 }
0257
0258
0259
0260
0261 std::string volInfo(const State& state) const {
0262 return (state.currentVolume != nullptr ? state.currentVolume->volumeName()
0263 : "No Volume") +
0264 " | ";
0265 }
0266
0267
0268
0269 const Logger& logger() const { return *m_logger; }
0270
0271
0272 Config m_cfg;
0273
0274
0275 std::unique_ptr<const Logger> m_logger;
0276 };
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287 class TryAllNavigator : public TryAllNavigatorBase {
0288 public:
0289
0290 using Config = TryAllNavigatorBase::Config;
0291
0292 using Options = TryAllNavigatorBase::Options;
0293
0294
0295 struct State : public TryAllNavigatorBase::State {
0296
0297
0298 explicit State(const Options& options_)
0299 : TryAllNavigatorBase::State(options_) {}
0300
0301
0302 std::vector<NavigationTarget> currentTargets;
0303 };
0304
0305
0306
0307
0308
0309 explicit TryAllNavigator(Config cfg, std::unique_ptr<const Logger> logger =
0310 getDefaultLogger("TryAllNavigator",
0311 Logging::INFO))
0312 : TryAllNavigatorBase(std::move(cfg), std::move(logger)) {}
0313
0314
0315
0316
0317 State makeState(const Options& options) const {
0318 State state(options);
0319 return state;
0320 }
0321
0322 using TryAllNavigatorBase::currentSurface;
0323 using TryAllNavigatorBase::currentVolume;
0324 using TryAllNavigatorBase::currentVolumeMaterial;
0325 using TryAllNavigatorBase::endOfWorldReached;
0326 using TryAllNavigatorBase::navigationBreak;
0327 using TryAllNavigatorBase::startSurface;
0328 using TryAllNavigatorBase::targetSurface;
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340 [[nodiscard]] Result<void> initialize(State& state, const Vector3& position,
0341 const Vector3& direction,
0342 Direction propagationDirection) const {
0343 auto baseRes = TryAllNavigatorBase::initialize(state, position, direction,
0344 propagationDirection);
0345 if (!baseRes.ok()) {
0346 return baseRes.error();
0347 }
0348
0349
0350 reinitializeCandidates(state);
0351
0352 return Result<void>::success();
0353 }
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366 NavigationTarget nextTarget(State& state, const Vector3& position,
0367 const Vector3& direction) const {
0368
0369 state.currentSurface = nullptr;
0370
0371
0372 if (state.navigationBreak) {
0373 return NavigationTarget::None();
0374 }
0375
0376 ACTS_VERBOSE(volInfo(state) << "nextTarget");
0377
0378 double nearLimit = state.options.nearLimit;
0379 double farLimit = state.options.farLimit;
0380
0381
0382 if (!state.currentTargets.empty()) {
0383 const NavigationTarget& previousTarget = state.currentTargets.front();
0384
0385 const Surface& surface = previousTarget.surface();
0386 IntersectionIndex index = previousTarget.intersectionIndex();
0387 BoundaryTolerance boundaryTolerance = previousTarget.boundaryTolerance();
0388
0389 auto intersection =
0390 surface
0391 .intersect(state.options.geoContext, position, direction,
0392 boundaryTolerance, state.options.surfaceTolerance)
0393 .at(index);
0394
0395 if (intersection.pathLength() < 0) {
0396 nearLimit = std::min(nearLimit, intersection.pathLength() -
0397 state.options.surfaceTolerance);
0398 farLimit = -state.options.surfaceTolerance;
0399
0400 ACTS_VERBOSE(volInfo(state)
0401 << "handle overstepping with nearLimit " << nearLimit
0402 << " and farLimit " << farLimit);
0403 }
0404 }
0405
0406 std::vector<NavigationTarget> nextTargets;
0407
0408
0409 for (const auto& candidate : state.navigationCandidates) {
0410 auto intersections =
0411 candidate.intersect(state.options.geoContext, position, direction,
0412 state.options.surfaceTolerance);
0413 for (auto [intersectionIndex, intersection] :
0414 Acts::enumerate(intersections)) {
0415
0416 if (!intersection.isValid() ||
0417 !detail::checkPathLength(intersection.pathLength(), nearLimit,
0418 farLimit)) {
0419 continue;
0420 }
0421
0422 nextTargets.emplace_back(
0423 candidate.target(intersection, intersectionIndex));
0424 }
0425 }
0426
0427 std::ranges::sort(nextTargets, NavigationTarget::pathLengthOrder);
0428
0429 ACTS_VERBOSE(volInfo(state)
0430 << "found " << nextTargets.size() << " intersections");
0431
0432 NavigationTarget nextTarget = NavigationTarget::None();
0433 state.currentTargets.clear();
0434
0435 for (const auto& target : nextTargets) {
0436 const Intersection3D& intersection = target.intersection();
0437
0438 if (intersection.status() == IntersectionStatus::onSurface) {
0439 ACTS_ERROR(volInfo(state)
0440 << "We are on surface " << target.surface().geometryId()
0441 << " before trying to reach it. This should not happen. "
0442 "Good luck.");
0443 continue;
0444 }
0445
0446 if (intersection.status() == IntersectionStatus::reachable) {
0447 nextTarget = target;
0448 break;
0449 }
0450 }
0451
0452 state.currentTargets = std::move(nextTargets);
0453
0454 if (nextTarget.isNone()) {
0455 ACTS_VERBOSE(volInfo(state) << "no target found");
0456 } else {
0457 ACTS_VERBOSE(volInfo(state)
0458 << "next target is " << nextTarget.surface().geometryId());
0459 }
0460
0461 return nextTarget;
0462 }
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477 bool checkTargetValid(const State& state, const Vector3& position,
0478 const Vector3& direction) const {
0479 (void)state;
0480 (void)position;
0481 (void)direction;
0482
0483 return false;
0484 }
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494 void handleSurfaceReached(State& state, const Vector3& position,
0495 const Vector3& direction,
0496 const Surface& ) const {
0497
0498 if (state.navigationBreak) {
0499 return;
0500 }
0501
0502 ACTS_VERBOSE(volInfo(state) << "handleSurfaceReached");
0503
0504 if (state.currentTargets.empty()) {
0505 ACTS_VERBOSE(volInfo(state) << "No current target set.");
0506 return;
0507 }
0508
0509 assert(state.currentSurface == nullptr && "Current surface must be reset.");
0510
0511
0512
0513 std::vector<NavigationTarget> hitTargets;
0514
0515 for (const auto& target : state.currentTargets) {
0516 std::uint8_t index = target.intersectionIndex();
0517 const Surface& surface = target.surface();
0518 BoundaryTolerance boundaryTolerance = BoundaryTolerance::None();
0519
0520 Intersection3D intersection =
0521 surface
0522 .intersect(state.options.geoContext, position, direction,
0523 boundaryTolerance, state.options.surfaceTolerance)
0524 .at(index);
0525
0526 if (intersection.status() == IntersectionStatus::onSurface) {
0527 hitTargets.emplace_back(target);
0528 }
0529 }
0530
0531 state.currentTargets.clear();
0532
0533 ACTS_VERBOSE(volInfo(state)
0534 << "Found " << hitTargets.size()
0535 << " intersections on surface with bounds check.");
0536
0537 if (hitTargets.empty()) {
0538 ACTS_VERBOSE(volInfo(state) << "No hit targets found.");
0539 return;
0540 }
0541
0542 if (hitTargets.size() > 1) {
0543 ACTS_VERBOSE(volInfo(state)
0544 << "Only using first intersection within bounds.");
0545 }
0546
0547
0548 const auto target = hitTargets.front();
0549 const Surface& surface = target.surface();
0550
0551 ACTS_VERBOSE(volInfo(state) << "Surface " << surface.geometryId()
0552 << " successfully hit, storing it.");
0553 state.currentSurface = &surface;
0554
0555 if (target.isSurfaceTarget()) {
0556 ACTS_VERBOSE(volInfo(state) << "This is a surface");
0557 } else if (target.isLayerTarget()) {
0558 ACTS_VERBOSE(volInfo(state) << "This is a layer");
0559 } else if (target.isPortalTarget()) {
0560 ACTS_VERBOSE(volInfo(state)
0561 << "This is a boundary. Reinitialize navigation");
0562
0563 const BoundarySurface& boundary = target.boundarySurface();
0564
0565 state.currentVolume = boundary.attachedVolume(state.options.geoContext,
0566 position, direction);
0567
0568 ACTS_VERBOSE(volInfo(state) << "Switched volume");
0569
0570 reinitializeCandidates(state);
0571 } else {
0572 ACTS_ERROR(volInfo(state) << "Unknown intersection type");
0573 }
0574 }
0575
0576 private:
0577
0578 void reinitializeCandidates(State& state) const {
0579 state.navigationCandidates.clear();
0580 state.currentTargets.clear();
0581
0582 initializeVolumeCandidates(state);
0583 }
0584 };
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600 class TryAllOverstepNavigator : public TryAllNavigatorBase {
0601 public:
0602
0603 using Config = TryAllNavigatorBase::Config;
0604
0605
0606 using Options = TryAllNavigatorBase::Options;
0607
0608
0609
0610
0611
0612 struct State : public TryAllNavigatorBase::State {
0613
0614
0615 explicit State(const Options& options_)
0616 : TryAllNavigatorBase::State(options_) {}
0617
0618
0619 std::vector<NavigationTarget> activeTargets;
0620
0621 int activeTargetIndex = -1;
0622
0623
0624 std::optional<Vector3> lastPosition;
0625
0626
0627
0628 const NavigationTarget& activeTarget() const {
0629 return activeTargets.at(activeTargetIndex);
0630 }
0631
0632
0633
0634 bool endOfTargets() const {
0635 return activeTargetIndex >= static_cast<int>(activeTargets.size());
0636 }
0637 };
0638
0639
0640
0641
0642
0643 explicit TryAllOverstepNavigator(
0644 Config cfg, std::unique_ptr<const Logger> logger = getDefaultLogger(
0645 "TryAllOverstepNavigator", Logging::INFO))
0646 : TryAllNavigatorBase(std::move(cfg), std::move(logger)) {}
0647
0648
0649
0650
0651 State makeState(const Options& options) const {
0652 State state(options);
0653 return state;
0654 }
0655
0656 using TryAllNavigatorBase::currentSurface;
0657 using TryAllNavigatorBase::currentVolume;
0658 using TryAllNavigatorBase::currentVolumeMaterial;
0659 using TryAllNavigatorBase::endOfWorldReached;
0660 using TryAllNavigatorBase::navigationBreak;
0661 using TryAllNavigatorBase::startSurface;
0662 using TryAllNavigatorBase::targetSurface;
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674 [[nodiscard]] Result<void> initialize(State& state, const Vector3& position,
0675 const Vector3& direction,
0676 Direction propagationDirection) const {
0677 auto baseRes = TryAllNavigatorBase::initialize(state, position, direction,
0678 propagationDirection);
0679 if (!baseRes.ok()) {
0680 return baseRes.error();
0681 }
0682
0683
0684 reinitializeCandidates(state);
0685
0686 state.lastPosition.reset();
0687
0688 return Result<void>::success();
0689 }
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702 NavigationTarget nextTarget(State& state, const Vector3& position,
0703 const Vector3& direction) const {
0704 (void)direction;
0705
0706
0707 state.currentSurface = nullptr;
0708
0709
0710 if (state.navigationBreak) {
0711 return NavigationTarget::None();
0712 }
0713
0714 ACTS_VERBOSE(volInfo(state) << "nextTarget");
0715
0716
0717 if (!state.lastPosition.has_value() && state.endOfTargets()) {
0718 ACTS_VERBOSE(
0719 volInfo(state)
0720 << "Initial position, nothing to do, blindly stepping forward.");
0721 state.lastPosition = position;
0722 return NavigationTarget::None();
0723 }
0724
0725 if (state.endOfTargets()) {
0726 ACTS_VERBOSE(volInfo(state) << "evaluate blind step");
0727
0728 Vector3 stepStart = state.lastPosition.value();
0729 Vector3 stepEnd = position;
0730 Vector3 step = stepEnd - stepStart;
0731 double stepDistance = step.norm();
0732 if (stepDistance < std::numeric_limits<double>::epsilon()) {
0733 ACTS_ERROR(volInfo(state) << "Step distance is zero. " << stepDistance);
0734 }
0735 Vector3 stepDirection = step.normalized();
0736
0737 double nearLimit = -stepDistance + state.options.surfaceTolerance;
0738 double farLimit = 0;
0739
0740 state.lastPosition.reset();
0741 state.activeTargets.clear();
0742 state.activeTargetIndex = -1;
0743
0744
0745 for (const auto& candidate : state.navigationCandidates) {
0746 auto intersections =
0747 candidate.intersect(state.options.geoContext, stepEnd,
0748 stepDirection, state.options.surfaceTolerance);
0749 for (auto [intersectionIndex, intersection] :
0750 Acts::enumerate(intersections)) {
0751
0752 if (!intersection.isValid() ||
0753 !detail::checkPathLength(intersection.pathLength(), nearLimit,
0754 farLimit)) {
0755 continue;
0756 }
0757
0758 state.activeTargets.emplace_back(
0759 candidate.target(intersection, intersectionIndex));
0760 }
0761 }
0762
0763 std::ranges::sort(state.activeTargets, NavigationTarget::pathLengthOrder);
0764
0765 ACTS_VERBOSE(volInfo(state) << "Found " << state.activeTargets.size()
0766 << " intersections");
0767
0768 for (const auto& target : state.activeTargets) {
0769 ACTS_VERBOSE("found target " << target.surface().geometryId());
0770 }
0771 }
0772
0773 ++state.activeTargetIndex;
0774
0775 if (state.endOfTargets()) {
0776 ACTS_VERBOSE(volInfo(state)
0777 << "No target found, blindly stepping forward.");
0778 state.lastPosition = position;
0779 return NavigationTarget::None();
0780 }
0781
0782 ACTS_VERBOSE(volInfo(state) << "handle active candidates");
0783
0784 ACTS_VERBOSE(volInfo(state)
0785 << (state.activeTargets.size() - state.activeTargetIndex)
0786 << " out of " << state.activeTargets.size()
0787 << " surfaces remain to try.");
0788
0789 const auto& target = state.activeTarget();
0790
0791 ACTS_VERBOSE(volInfo(state) << "Next surface candidate will be "
0792 << target.surface().geometryId());
0793
0794 return target;
0795 }
0796
0797
0798
0799
0800
0801
0802
0803
0804
0805
0806
0807 bool checkTargetValid(const State& state, const Vector3& position,
0808 const Vector3& direction) const {
0809 (void)state;
0810 (void)position;
0811 (void)direction;
0812
0813 return true;
0814 }
0815
0816
0817
0818
0819
0820
0821
0822
0823
0824 void handleSurfaceReached(State& state, const Vector3& position,
0825 const Vector3& direction,
0826 const Surface& ) const {
0827 if (state.navigationBreak) {
0828 return;
0829 }
0830
0831 ACTS_VERBOSE(volInfo(state) << "handleSurfaceReached");
0832
0833 assert(state.currentSurface == nullptr && "Current surface must be reset.");
0834
0835 if (state.endOfTargets()) {
0836 ACTS_VERBOSE(volInfo(state) << "No active candidate set.");
0837 return;
0838 }
0839
0840 std::vector<NavigationTarget> hitTargets;
0841
0842 while (!state.endOfTargets()) {
0843 const auto& candidate = state.activeTarget();
0844 IntersectionIndex index = candidate.intersectionIndex();
0845 const Surface& surface = candidate.surface();
0846 BoundaryTolerance boundaryTolerance = candidate.boundaryTolerance();
0847
0848
0849 IntersectionStatus surfaceStatus =
0850 surface
0851 .intersect(state.options.geoContext, position, direction,
0852 boundaryTolerance, state.options.surfaceTolerance)
0853 .at(index)
0854 .status();
0855
0856 if (surfaceStatus != IntersectionStatus::onSurface) {
0857 break;
0858 }
0859
0860
0861 boundaryTolerance = BoundaryTolerance::None();
0862 surfaceStatus =
0863 surface
0864 .intersect(state.options.geoContext, position, direction,
0865 boundaryTolerance, state.options.surfaceTolerance)
0866 .at(index)
0867 .status();
0868
0869 if (surfaceStatus == IntersectionStatus::onSurface) {
0870 hitTargets.emplace_back(candidate);
0871 }
0872
0873 ++state.activeTargetIndex;
0874 ACTS_VERBOSE("skip target " << surface.geometryId());
0875 }
0876
0877
0878 --state.activeTargetIndex;
0879
0880 ACTS_VERBOSE(volInfo(state)
0881 << "Found " << hitTargets.size()
0882 << " intersections on surface with bounds check.");
0883
0884 if (hitTargets.empty()) {
0885 ACTS_VERBOSE(volInfo(state)
0886 << "Surface successfully hit, but outside bounds.");
0887 return;
0888 }
0889
0890 if (hitTargets.size() > 1) {
0891 ACTS_VERBOSE(volInfo(state)
0892 << "Only using first intersection within bounds.");
0893 }
0894
0895
0896 const auto& candidate = hitTargets.front();
0897 const Surface& surface = candidate.surface();
0898
0899 ACTS_VERBOSE(volInfo(state) << "Surface successfully hit, storing it.");
0900 state.currentSurface = &surface;
0901
0902 if (state.currentSurface != nullptr) {
0903 ACTS_VERBOSE(volInfo(state) << "Current surface set to surface "
0904 << surface.geometryId());
0905 }
0906
0907 if (candidate.isSurfaceTarget()) {
0908 ACTS_VERBOSE(volInfo(state) << "This is a surface");
0909 } else if (candidate.isLayerTarget()) {
0910 ACTS_VERBOSE(volInfo(state) << "This is a layer");
0911 } else if (candidate.isPortalTarget()) {
0912 ACTS_VERBOSE(volInfo(state)
0913 << "This is a portal. Reinitialize navigation");
0914
0915 const BoundarySurface& boundary = candidate.boundarySurface();
0916
0917 state.currentVolume = boundary.attachedVolume(state.options.geoContext,
0918 position, direction);
0919
0920 ACTS_VERBOSE(volInfo(state) << "Switched volume");
0921
0922 reinitializeCandidates(state);
0923 } else {
0924 ACTS_ERROR(volInfo(state) << "Unknown intersection type");
0925 }
0926 }
0927
0928 private:
0929
0930 void reinitializeCandidates(State& state) const {
0931 state.navigationCandidates.clear();
0932 state.activeTargets.clear();
0933 state.activeTargetIndex = -1;
0934
0935 initializeVolumeCandidates(state);
0936 }
0937 };
0938
0939 }