Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:11:27

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