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