Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:01:55

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