File indexing completed on 2026-07-22 08:22:29
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Navigation/NavigationStream.hpp"
0010
0011 #include "Acts/Propagator/NavigationTarget.hpp"
0012 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0013 #include "Acts/Surfaces/Surface.hpp"
0014 #include "Acts/Utilities/Enumerate.hpp"
0015
0016 #include <algorithm>
0017
0018 namespace Acts {
0019
0020 bool NavigationStream::initialize(const GeometryContext& gctx,
0021 const QueryPoint& queryPoint,
0022 const BoundaryTolerance& cTolerance,
0023 const double onSurfaceTolerance) {
0024
0025 const Vector3& position = queryPoint.position;
0026 const Vector3& direction = queryPoint.direction;
0027
0028
0029
0030 std::ranges::stable_sort(
0031 m_candidates, [](const NavigationTarget& a, const NavigationTarget& b) {
0032 return &a.surface() < &b.surface();
0033 });
0034 auto initialDuplicates = std::ranges::unique(
0035 m_candidates.begin(), m_candidates.end(),
0036 [](const NavigationTarget& a, const NavigationTarget& b) {
0037 return &a.surface() == &b.surface();
0038 });
0039 m_candidates.erase(initialDuplicates.begin(), initialDuplicates.end());
0040
0041
0042 std::vector<NavigationTarget> additionalCandidates = {};
0043 for (auto& candidate : m_candidates) {
0044
0045 const Surface& surface = candidate.surface();
0046
0047 auto multiIntersection = surface.intersect(gctx, position, direction,
0048 cTolerance, onSurfaceTolerance);
0049
0050 bool firstValid = multiIntersection.at(0).isValid();
0051 bool secondValid = multiIntersection.at(1).isValid();
0052 if (firstValid && !secondValid) {
0053 if (multiIntersection.at(0).pathLength() < -onSurfaceTolerance) {
0054 continue;
0055 }
0056 candidate.intersection() = multiIntersection.at(0);
0057 candidate.intersectionIndex() = 0;
0058 } else if (!firstValid && secondValid) {
0059 if (multiIntersection.at(1).pathLength() < -onSurfaceTolerance) {
0060 continue;
0061 }
0062 candidate.intersection() = multiIntersection.at(1);
0063 candidate.intersectionIndex() = 1;
0064 } else {
0065
0066
0067 bool originalCandidateUpdated = false;
0068 for (auto [intersectionIndex, intersection] :
0069 enumerate(multiIntersection)) {
0070
0071 if (intersection.pathLength() < -onSurfaceTolerance) {
0072 continue;
0073 }
0074
0075 if (intersection.isValid()) {
0076 if (!originalCandidateUpdated) {
0077 candidate.intersection() = intersection;
0078 candidate.intersectionIndex() = intersectionIndex;
0079 originalCandidateUpdated = true;
0080 } else {
0081 NavigationTarget additionalCandidate = candidate;
0082 additionalCandidate.intersection() = intersection;
0083 additionalCandidate.intersectionIndex() = intersectionIndex;
0084 additionalCandidates.emplace_back(additionalCandidate);
0085 }
0086 }
0087 }
0088 }
0089 }
0090
0091
0092 m_candidates.insert(m_candidates.end(), additionalCandidates.begin(),
0093 additionalCandidates.end());
0094
0095
0096 std::ranges::sort(m_candidates, NavigationTarget::pathLengthOrder);
0097
0098
0099
0100
0101
0102 auto nonUniqueRange = std::ranges::unique(
0103 m_candidates.begin(), m_candidates.end(),
0104 [](const NavigationTarget& a, const NavigationTarget& b) {
0105 return &a.surface() == &b.surface();
0106 });
0107 m_candidates.erase(nonUniqueRange.begin(), nonUniqueRange.end());
0108
0109
0110 auto firstInvalid = std::ranges::find_if(
0111 m_candidates,
0112 [](const NavigationTarget& a) { return !a.intersection().isValid(); });
0113
0114
0115 m_candidates.resize(std::distance(m_candidates.begin(), firstInvalid),
0116 NavigationTarget::None());
0117
0118 m_currentIndex = 0;
0119 if (m_candidates.empty()) {
0120 return false;
0121 }
0122 return true;
0123 }
0124
0125 bool NavigationStream::update(const GeometryContext& gctx,
0126 const QueryPoint& queryPoint,
0127 double onSurfaceTolerance) {
0128
0129 for (; m_currentIndex < m_candidates.size(); ++m_currentIndex) {
0130
0131 NavigationTarget& candidate = currentCandidate();
0132
0133 const Surface& surface = candidate.surface();
0134
0135 auto multiIntersection =
0136 surface.intersect(gctx, queryPoint.position, queryPoint.direction,
0137 candidate.boundaryTolerance(), onSurfaceTolerance);
0138
0139 for (auto [intersectionIndex, intersection] :
0140 enumerate(multiIntersection)) {
0141
0142 if (intersectionIndex != candidate.intersectionIndex()) {
0143 continue;
0144 }
0145
0146 if (intersection.isValid()) {
0147 candidate.intersection() = intersection;
0148 return true;
0149 }
0150 }
0151 }
0152
0153 return false;
0154 }
0155
0156 void NavigationStream::reset() {
0157 m_candidates.clear();
0158 m_currentIndex = 0;
0159 }
0160
0161 void NavigationStream::addSurfaceCandidate(
0162 const Surface& surface, const BoundaryTolerance& bTolerance) {
0163 m_candidates.emplace_back(Intersection3D::Invalid(), 0, surface, bTolerance);
0164 }
0165
0166 void NavigationStream::addSurfaceCandidates(
0167 std::span<const Surface*> surfaces, const BoundaryTolerance& bTolerance) {
0168 m_candidates.reserve(m_candidates.size() + surfaces.size());
0169 std::ranges::for_each(surfaces, [&](const Surface* surface) {
0170 m_candidates.emplace_back(Intersection3D::Invalid(), 0, *surface,
0171 bTolerance);
0172 });
0173 }
0174
0175 void NavigationStream::addPortalCandidate(const Portal& portal) {
0176 m_candidates.emplace_back(Intersection3D::Invalid(), 0, portal,
0177 BoundaryTolerance::None());
0178 }
0179
0180 AppendOnlyNavigationStream::AppendOnlyNavigationStream(NavigationStream& stream)
0181 : m_stream{&stream} {}
0182
0183 void AppendOnlyNavigationStream::addPortalCandidate(const Portal& portal) {
0184 m_stream->addPortalCandidate(portal);
0185 }
0186
0187 void AppendOnlyNavigationStream::addSurfaceCandidate(
0188 const Surface& surface, const BoundaryTolerance& bTolerance) {
0189 m_stream->addSurfaceCandidate(surface, bTolerance);
0190 }
0191
0192 }