File indexing completed on 2025-07-08 08:10:03
0001
0002
0003
0004
0005
0006
0007
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
0028 enum class IntersectionStatus : int {
0029 unreachable = 0,
0030 reachable = 1,
0031 onSurface = 2
0032 };
0033
0034
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
0044
0045
0046 template <unsigned int DIM>
0047 class Intersection {
0048 public:
0049
0050 using Position = Eigen::Map<const ActsVector<DIM>>;
0051
0052
0053
0054
0055
0056
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
0079 constexpr bool isValid() const {
0080 return m_status != IntersectionStatus::unreachable;
0081 }
0082
0083
0084 constexpr Position position() const { return Position{m_position.data()}; }
0085
0086
0087 constexpr double pathLength() const { return m_pathLength; }
0088
0089
0090 constexpr IntersectionStatus status() const { return m_status; }
0091
0092
0093 constexpr static Intersection invalid() { return Intersection(); }
0094
0095
0096
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
0105
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
0117 auto a = aIntersection.pathLength();
0118 auto b = bIntersection.pathLength();
0119 return std::abs(a) < std::abs(b);
0120 }
0121
0122
0123
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
0134 std::array<double, DIM> m_position{};
0135
0136 double m_pathLength = std::numeric_limits<double>::infinity();
0137
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
0159
0160
0161
0162
0163
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
0179 constexpr bool isValid() const { return m_intersection.isValid(); }
0180
0181
0182 constexpr const Intersection3D& intersection() const {
0183 return m_intersection;
0184 }
0185
0186
0187 Intersection3D::Position position() const {
0188 return m_intersection.position();
0189 }
0190
0191
0192 constexpr double pathLength() const { return m_intersection.pathLength(); }
0193
0194
0195 constexpr IntersectionStatus status() const {
0196 return m_intersection.status();
0197 }
0198
0199
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
0235 Intersection3D m_intersection = Intersection3D::invalid();
0236
0237 const object_t* m_object = nullptr;
0238
0239 std::uint8_t m_index = 0;
0240
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
0257
0258
0259
0260
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
0308 MultiIntersection3D m_intersections;
0309
0310 const object_t* m_object = nullptr;
0311
0312 BoundaryTolerance m_boundaryTolerance = BoundaryTolerance::None();
0313 };
0314
0315 namespace detail {
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325 bool checkPathLength(double pathLength, double nearLimit, double farLimit,
0326 const Logger& logger = getDummyLogger());
0327
0328 }
0329
0330 }