Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-08 08:10:03

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 #pragma once
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0013 #include "Acts/Utilities/Logger.hpp"
0014 
0015 #include <algorithm>
0016 #include <array>
0017 #include <cstddef>
0018 #include <cstdint>
0019 #include <limits>
0020 #include <span>
0021 #include <type_traits>
0022 
0023 #include <boost/container/static_vector.hpp>
0024 
0025 namespace Acts {
0026 
0027 /// Status enum
0028 enum class IntersectionStatus : int {
0029   unreachable = 0,
0030   reachable = 1,
0031   onSurface = 2
0032 };
0033 
0034 /// Ostream-operator for the IntersectionStatus enum
0035 inline std::ostream& operator<<(std::ostream& os, IntersectionStatus status) {
0036   constexpr static std::array<const char*, 3> names = {
0037       {"missed/unreachable", "reachable", "onSurface"}};
0038 
0039   os << names[static_cast<std::size_t>(status)];
0040   return os;
0041 }
0042 
0043 ///  @struct Intersection
0044 ///
0045 ///  Intersection struct used for position
0046 template <unsigned int DIM>
0047 class Intersection {
0048  public:
0049   /// Position type
0050   using Position = Eigen::Map<const ActsVector<DIM>>;
0051 
0052   /// Constructor with arguments
0053   ///
0054   /// @param position is the position of the intersection
0055   /// @param pathLength is the path length to the intersection
0056   /// @param status is an enum indicating the status of the intersection
0057   constexpr Intersection(const ActsVector<DIM>& position, double pathLength,
0058                          IntersectionStatus status) noexcept
0059       : Intersection(std::span<const double, DIM>{position.data(), DIM},
0060                      pathLength, status) {}
0061 
0062   constexpr Intersection(const Position& position, double pathLength,
0063                          IntersectionStatus status) noexcept
0064       : Intersection(std::span<const double, DIM>{position.data(), DIM},
0065                      pathLength, status) {}
0066 
0067   constexpr Intersection(std::span<const double, DIM> position,
0068                          double pathLength, IntersectionStatus status) noexcept
0069       : m_pathLength(pathLength), m_status(status) {
0070     std::ranges::copy(position, m_position.begin());
0071   }
0072 
0073   Intersection(const Intersection&) noexcept = default;
0074   Intersection(Intersection&&) noexcept = default;
0075   Intersection& operator=(const Intersection&) noexcept = default;
0076   Intersection& operator=(Intersection&&) noexcept = default;
0077 
0078   /// Returns whether the intersection was successful or not
0079   constexpr bool isValid() const {
0080     return m_status != IntersectionStatus::unreachable;
0081   }
0082 
0083   /// Returns the position of the interseciton
0084   constexpr Position position() const { return Position{m_position.data()}; }
0085 
0086   /// Returns the path length to the interseciton
0087   constexpr double pathLength() const { return m_pathLength; }
0088 
0089   /// Returns the intersection status enum
0090   constexpr IntersectionStatus status() const { return m_status; }
0091 
0092   /// Static factory to creae an invalid instesection
0093   constexpr static Intersection invalid() { return Intersection(); }
0094 
0095   /// Comparison function for path length order i.e. intersection closest to
0096   /// -inf will be first.
0097   constexpr static bool pathLengthOrder(const Intersection& aIntersection,
0098                                         const Intersection& bIntersection) {
0099     auto a = aIntersection.pathLength();
0100     auto b = bIntersection.pathLength();
0101     return a < b;
0102   }
0103 
0104   /// Comparison function for closest order i.e. intersection closest to 0 will
0105   /// be first.
0106   constexpr static bool closestOrder(const Intersection& aIntersection,
0107                                      const Intersection& bIntersection) {
0108     if ((aIntersection.status() == IntersectionStatus::unreachable) &&
0109         (bIntersection.status() != IntersectionStatus::unreachable)) {
0110       return false;
0111     }
0112     if ((aIntersection.status() != IntersectionStatus::unreachable) &&
0113         (bIntersection.status() == IntersectionStatus::unreachable)) {
0114       return true;
0115     }
0116     // both are reachable or onSurface now
0117     auto a = aIntersection.pathLength();
0118     auto b = bIntersection.pathLength();
0119     return std::abs(a) < std::abs(b);
0120   }
0121 
0122   /// Comparison function for closest forward order i.e. intersection closest to
0123   /// 0 with positive path length will be first.
0124   constexpr static bool closestForwardOrder(const Intersection& aIntersection,
0125                                             const Intersection& bIntersection) {
0126     auto a = aIntersection.pathLength();
0127     auto b = bIntersection.pathLength();
0128     return std::signbit(a) == std::signbit(b) ? std::abs(a) < std::abs(b)
0129                                               : a > b;
0130   }
0131 
0132  private:
0133   /// Position of the intersection
0134   std::array<double, DIM> m_position{};
0135   /// Signed path length to the intersection (if valid)
0136   double m_pathLength = std::numeric_limits<double>::infinity();
0137   /// The Status of the intersection
0138   IntersectionStatus m_status = IntersectionStatus::unreachable;
0139 
0140   constexpr Intersection() = default;
0141 };
0142 
0143 using Intersection2D = Intersection<2>;
0144 using Intersection3D = Intersection<3>;
0145 
0146 static_assert(std::is_trivially_move_constructible_v<Intersection2D>);
0147 static_assert(std::is_trivially_copy_constructible_v<Intersection2D>);
0148 static_assert(std::is_trivially_move_assignable_v<Intersection2D>);
0149 
0150 static constexpr std::uint8_t s_maximumNumberOfIntersections = 2;
0151 using MultiIntersection3D =
0152     boost::container::static_vector<Intersection3D,
0153                                     s_maximumNumberOfIntersections>;
0154 
0155 template <typename object_t>
0156 class ObjectIntersection {
0157  public:
0158   /// Object intersection
0159   ///
0160   /// @param intersection is the intersection
0161   /// @param object is the object to be instersected
0162   /// @param index is the intersection index
0163   /// @param boundaryTolerance is the boundary tolerance for the intersection
0164   constexpr ObjectIntersection(
0165       const Intersection3D& intersection, const object_t* object,
0166       std::uint8_t index = 0,
0167       BoundaryTolerance boundaryTolerance = BoundaryTolerance::None()) noexcept
0168       : m_intersection(intersection),
0169         m_object(object),
0170         m_index(index),
0171         m_boundaryTolerance(boundaryTolerance) {}
0172 
0173   ObjectIntersection(const ObjectIntersection&) noexcept = default;
0174   ObjectIntersection(ObjectIntersection&&) noexcept = default;
0175   ObjectIntersection& operator=(const ObjectIntersection&) noexcept = default;
0176   ObjectIntersection& operator=(ObjectIntersection&&) noexcept = default;
0177 
0178   /// Returns whether the intersection was successful or not
0179   constexpr bool isValid() const { return m_intersection.isValid(); }
0180 
0181   /// Returns the intersection
0182   constexpr const Intersection3D& intersection() const {
0183     return m_intersection;
0184   }
0185 
0186   /// Returns the position of the interseciton
0187   Intersection3D::Position position() const {
0188     return m_intersection.position();
0189   }
0190 
0191   /// Returns the path length to the interseciton
0192   constexpr double pathLength() const { return m_intersection.pathLength(); }
0193 
0194   /// Returns the status of the interseciton
0195   constexpr IntersectionStatus status() const {
0196     return m_intersection.status();
0197   }
0198 
0199   /// Returns the object that has been intersected
0200   constexpr const object_t* object() const { return m_object; }
0201 
0202   constexpr std::uint8_t index() const { return m_index; }
0203 
0204   constexpr BoundaryTolerance boundaryTolerance() const {
0205     return m_boundaryTolerance;
0206   }
0207 
0208   constexpr static ObjectIntersection invalid(
0209       const object_t* object = nullptr) {
0210     return ObjectIntersection(Intersection3D::invalid(), object);
0211   }
0212 
0213   constexpr static bool pathLengthOrder(
0214       const ObjectIntersection& aIntersection,
0215       const ObjectIntersection& bIntersection) {
0216     return Intersection3D::pathLengthOrder(aIntersection.intersection(),
0217                                            bIntersection.intersection());
0218   }
0219 
0220   constexpr static bool closestOrder(const ObjectIntersection& aIntersection,
0221                                      const ObjectIntersection& bIntersection) {
0222     return Intersection3D::closestOrder(aIntersection.intersection(),
0223                                         bIntersection.intersection());
0224   }
0225 
0226   constexpr static bool closestForwardOrder(
0227       const ObjectIntersection& aIntersection,
0228       const ObjectIntersection& bIntersection) {
0229     return Intersection3D::closestForwardOrder(aIntersection.intersection(),
0230                                                bIntersection.intersection());
0231   }
0232 
0233  private:
0234   /// The intersection itself
0235   Intersection3D m_intersection = Intersection3D::invalid();
0236   /// The object that was (tried to be) intersected
0237   const object_t* m_object = nullptr;
0238   /// The intersection index
0239   std::uint8_t m_index = 0;
0240   /// The boundary tolerance for the intersection
0241   BoundaryTolerance m_boundaryTolerance = BoundaryTolerance::None();
0242 
0243   constexpr ObjectIntersection() = default;
0244 };
0245 
0246 static_assert(std::is_trivially_move_constructible_v<ObjectIntersection<int>>);
0247 static_assert(std::is_trivially_move_assignable_v<ObjectIntersection<int>>);
0248 
0249 template <typename object_t>
0250 class ObjectMultiIntersection {
0251  public:
0252   using SplitIntersections =
0253       boost::container::static_vector<ObjectIntersection<object_t>,
0254                                       s_maximumNumberOfIntersections>;
0255 
0256   /// Object intersection
0257   ///
0258   /// @param intersections are the intersections
0259   /// @param object is the object to be instersected
0260   /// @param boundaryTolerance is the boundary tolerance for the intersection
0261   constexpr ObjectMultiIntersection(
0262       const MultiIntersection3D& intersections, const object_t* object,
0263       BoundaryTolerance boundaryTolerance = BoundaryTolerance::None())
0264       : m_intersections(intersections),
0265         m_object(object),
0266         m_boundaryTolerance(boundaryTolerance) {}
0267 
0268   constexpr ObjectIntersection<object_t> operator[](std::uint8_t index) const {
0269     return {m_intersections[index], m_object, index, m_boundaryTolerance};
0270   }
0271 
0272   constexpr const MultiIntersection3D& intersections() const {
0273     return m_intersections;
0274   }
0275 
0276   constexpr std::size_t size() const { return m_intersections.size(); }
0277 
0278   constexpr const object_t* object() const { return m_object; }
0279 
0280   constexpr BoundaryTolerance boundaryTolerance() const {
0281     return m_boundaryTolerance;
0282   }
0283 
0284   constexpr SplitIntersections split() const {
0285     SplitIntersections result;
0286     for (std::size_t i = 0; i < size(); ++i) {
0287       result.push_back(operator[](i));
0288     }
0289     return result;
0290   }
0291 
0292   constexpr ObjectIntersection<object_t> closest() const {
0293     auto splitIntersections = split();
0294     return *std::min_element(splitIntersections.begin(),
0295                              splitIntersections.end(),
0296                              ObjectIntersection<object_t>::closestOrder);
0297   }
0298 
0299   constexpr ObjectIntersection<object_t> closestForward() const {
0300     auto splitIntersections = split();
0301     return *std::min_element(splitIntersections.begin(),
0302                              splitIntersections.end(),
0303                              ObjectIntersection<object_t>::closestForwardOrder);
0304   }
0305 
0306  private:
0307   /// The intersections
0308   MultiIntersection3D m_intersections;
0309   /// The object that was (tried to be) intersected
0310   const object_t* m_object = nullptr;
0311   /// The boundary tolerance for the intersection
0312   BoundaryTolerance m_boundaryTolerance = BoundaryTolerance::None();
0313 };
0314 
0315 namespace detail {
0316 
0317 /// This function checks if an intersection path length is valid for the
0318 /// specified near-limit and far-limit
0319 ///
0320 /// @param pathLength The path length of the intersection
0321 /// @param nearLimit The minimum path length for an intersection to be considered
0322 /// @param farLimit The maximum path length for an intersection to be considered
0323 /// @param logger A optionally supplied logger which prints out a lot of infos
0324 ///               at VERBOSE level
0325 bool checkPathLength(double pathLength, double nearLimit, double farLimit,
0326                      const Logger& logger = getDummyLogger());
0327 
0328 }  // namespace detail
0329 
0330 }  // namespace Acts