Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-06 09:17:34

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
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   // Position and direction from the query point
0026   const Vector3& position = queryPoint.position;
0027   const Vector3& direction = queryPoint.direction;
0028 
0029   // A container collecting additional candidates from multiple
0030   // valid intersections
0031   std::vector<NavigationTarget> additionalCandidates = {};
0032   for (auto& candidate : m_candidates) {
0033     // Get the surface from the object intersection
0034     const Surface& surface = candidate.surface();
0035     // Intersect the surface
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       // Split them into valid intersections, keep track of potentially
0055       // additional candidates
0056       bool originalCandidateUpdated = false;
0057       for (auto [intersectionIndex, intersection] :
0058            enumerate(multiIntersection)) {
0059         // Skip negative solutions, respecting the on surface tolerance
0060         if (intersection.pathLength() < -onSurfaceTolerance) {
0061           continue;
0062         }
0063         // Valid solution is either on surface or updates the distance
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   // Append the multi intersection candidates
0081   m_candidates.insert(m_candidates.end(), additionalCandidates.begin(),
0082                       additionalCandidates.end());
0083 
0084   // Sort the candidates by path length
0085   std::ranges::sort(m_candidates, NavigationTarget::pathLengthOrder);
0086 
0087   // If we have duplicates, we expect them to be close by in path length, so we
0088   // don't need to re-sort Remove duplicates on basis of the surface pointer
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   // The we find the first invalid candidate
0097   auto firstInvalid = std::ranges::find_if(
0098       m_candidates,
0099       [](const NavigationTarget& a) { return !a.intersection().isValid(); });
0100 
0101   // Set the range and initialize
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   // Loop over the (currently valid) candidates and update
0116   for (; m_currentIndex < m_candidates.size(); ++m_currentIndex) {
0117     // Get the candidate, and resolve the tuple
0118     NavigationTarget& candidate = currentCandidate();
0119     // Get the surface from the object intersection
0120     const Surface& surface = candidate.surface();
0121     // (re-)Intersect the surface
0122     auto multiIntersection =
0123         surface.intersect(gctx, queryPoint.position, queryPoint.direction,
0124                           candidate.boundaryTolerance(), onSurfaceTolerance);
0125     // Split them into valid intersections
0126     for (auto [intersectionIndex, intersection] :
0127          enumerate(multiIntersection)) {
0128       // Skip wrong index solution
0129       if (intersectionIndex != candidate.intersectionIndex()) {
0130         continue;
0131       }
0132       // Valid solution is either on surface or updates the distance
0133       if (intersection.isValid()) {
0134         candidate.intersection() = intersection;
0135         return true;
0136       }
0137     }
0138   }
0139   // No candidate was reachable
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 }  // namespace Acts