Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:12:21

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