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