Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:11:33

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/Surfaces/BoundaryTolerance.hpp"
0013 #include "Acts/Surfaces/Surface.hpp"
0014 
0015 #include <algorithm>
0016 
0017 namespace Acts {
0018 
0019 bool NavigationStream::initialize(const GeometryContext& gctx,
0020                                   const QueryPoint& queryPoint,
0021                                   const BoundaryTolerance& cTolerance,
0022                                   double onSurfaceTolerance) {
0023   // Position and direction from the query point
0024   const Vector3& position = queryPoint.position;
0025   const Vector3& direction = queryPoint.direction;
0026 
0027   // A container collecting additional candidates from multiple
0028   // valid interseciton
0029   std::vector<Candidate> additionalCandidates = {};
0030   for (auto& [sIntersection, gen2Portal, portal, bTolerance] : m_candidates) {
0031     // Get the surface from the object intersection
0032     const Surface* surface = sIntersection.object();
0033     // Intersect the surface
0034     auto multiIntersection = surface->intersect(gctx, position, direction,
0035                                                 cTolerance, onSurfaceTolerance);
0036 
0037     bool firstValid = multiIntersection[0].isValid();
0038     bool secondValid = multiIntersection[1].isValid();
0039     if (firstValid && !secondValid) {
0040       if (multiIntersection[0].pathLength() < -onSurfaceTolerance) {
0041         continue;
0042       }
0043       sIntersection = multiIntersection[0];
0044     } else if (!firstValid && secondValid) {
0045       if (multiIntersection[1].pathLength() < -onSurfaceTolerance) {
0046         continue;
0047       }
0048       sIntersection = multiIntersection[1];
0049     } else {
0050       // Split them into valid intersections, keep track of potentially
0051       // additional candidates
0052       bool originalCandidateUpdated = false;
0053       for (const auto& rsIntersection : multiIntersection.split()) {
0054         // Skip negative solutions, respecting the on surface tolerance
0055         if (rsIntersection.pathLength() < -onSurfaceTolerance) {
0056           continue;
0057         }
0058         // Valid solution is either on surface or updates the distance
0059         if (rsIntersection.isValid()) {
0060           if (!originalCandidateUpdated) {
0061             sIntersection = rsIntersection;
0062             originalCandidateUpdated = true;
0063           } else {
0064             additionalCandidates.emplace_back(rsIntersection, gen2Portal,
0065                                               portal, bTolerance);
0066           }
0067         }
0068       }
0069     }
0070   }
0071 
0072   // Append the multi intersection candidates
0073   m_candidates.insert(m_candidates.end(), additionalCandidates.begin(),
0074                       additionalCandidates.end());
0075 
0076   // Sort the candidates by path length
0077   std::ranges::sort(m_candidates, Candidate::pathLengthOrder);
0078 
0079   // If we have duplicates, we expect them to be close by in path length, so we
0080   // don't need to re-sort Remove duplicates on basis of the surface pointer
0081   m_candidates.erase(std::unique(m_candidates.begin(), m_candidates.end(),
0082                                  [](const Candidate& a, const Candidate& b) {
0083                                    return (&a.surface()) == (&b.surface());
0084                                  }),
0085                      m_candidates.end());
0086 
0087   // The we find the first invalid candidate
0088   auto firstInvalid =
0089       std::ranges::find_if(m_candidates, [](const Candidate& a) {
0090         const auto& [aIntersection, aGen2Portal, aPortal, aTolerance] = a;
0091         return !aIntersection.isValid();
0092       });
0093 
0094   // Set the range and initialize
0095   m_candidates.resize(std::distance(m_candidates.begin(), firstInvalid));
0096 
0097   m_currentIndex = 0;
0098   if (m_candidates.empty()) {
0099     return false;
0100   }
0101   return true;
0102 }
0103 
0104 bool NavigationStream::update(const GeometryContext& gctx,
0105                               const QueryPoint& queryPoint,
0106                               double onSurfaceTolerance) {
0107   // Loop over the (currently valid) candidates and update
0108   for (; m_currentIndex < m_candidates.size(); ++m_currentIndex) {
0109     // Get the candidate, and resolve the tuple
0110     Candidate& candidate = currentCandidate();
0111     // Get the surface from the object intersection
0112     const Surface* surface = candidate.intersection.object();
0113     // (re-)Intersect the surface
0114     auto multiIntersection =
0115         surface->intersect(gctx, queryPoint.position, queryPoint.direction,
0116                            candidate.bTolerance, onSurfaceTolerance);
0117     // Split them into valid intersections
0118     for (const auto& rsIntersection : multiIntersection.split()) {
0119       // Skip wrong index solution
0120       if (rsIntersection.index() != candidate.intersection.index()) {
0121         continue;
0122       }
0123       // Valid solution is either on surface or updates the distance
0124       if (rsIntersection.isValid()) {
0125         candidate.intersection = rsIntersection;
0126         return true;
0127       }
0128     }
0129   }
0130   // No candidate was reachable
0131   return false;
0132 }
0133 
0134 void NavigationStream::reset() {
0135   m_candidates.clear();
0136   m_currentIndex = 0;
0137 }
0138 
0139 void NavigationStream::addSurfaceCandidate(
0140     const Surface& surface, const BoundaryTolerance& bTolerance) {
0141   m_candidates.emplace_back(ObjectIntersection<Surface>::invalid(&surface),
0142                             nullptr, nullptr, bTolerance);
0143 }
0144 
0145 void NavigationStream::addSurfaceCandidates(
0146     std::span<const Surface*> surfaces, const BoundaryTolerance& bTolerance) {
0147   m_candidates.reserve(m_candidates.size() + surfaces.size());
0148   std::ranges::for_each(surfaces, [&](const auto* surface) {
0149     m_candidates.emplace_back(ObjectIntersection<Surface>::invalid(surface),
0150                               nullptr, nullptr, bTolerance);
0151   });
0152 }
0153 
0154 void NavigationStream::addPortalCandidate(const Experimental::Portal& portal) {
0155   m_candidates.emplace_back(
0156       ObjectIntersection<Surface>::invalid(&portal.surface()), &portal, nullptr,
0157       BoundaryTolerance::None());
0158 }
0159 
0160 void NavigationStream::addPortalCandidate(const Portal& portal) {
0161   m_candidates.emplace_back(
0162       ObjectIntersection<Surface>::invalid(&portal.surface()), nullptr, &portal,
0163       BoundaryTolerance::None());
0164 }
0165 
0166 void NavigationStream::addPortalCandidates(
0167     std::span<const Experimental::Portal*> portals) {
0168   m_candidates.reserve(m_candidates.size() + portals.size());
0169   std::ranges::for_each(portals, [&](const auto& portal) {
0170     m_candidates.emplace_back(
0171         ObjectIntersection<Surface>::invalid(&(portal->surface())), portal,
0172         nullptr, BoundaryTolerance::None());
0173   });
0174 }
0175 
0176 AppendOnlyNavigationStream::AppendOnlyNavigationStream(NavigationStream& stream)
0177     : m_stream{&stream} {}
0178 
0179 void AppendOnlyNavigationStream::addPortalCandidate(const Portal& portal) {
0180   m_stream->addPortalCandidate(portal);
0181 }
0182 
0183 void AppendOnlyNavigationStream::addSurfaceCandidate(
0184     const Surface& surface, const BoundaryTolerance& bTolerance) {
0185   m_stream->addSurfaceCandidate(surface, bTolerance);
0186 }
0187 
0188 }  // namespace Acts