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