File indexing completed on 2026-08-09 08:18:11
0001
0002
0003
0004
0005
0006
0007
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 #include <span>
0021 #include <type_traits>
0022
0023 namespace Acts {
0024
0025
0026 enum class IntersectionStatus : int {
0027 unreachable = 0,
0028 reachable = 1,
0029 onSurface = 2
0030 };
0031
0032
0033
0034
0035
0036 inline std::ostream& operator<<(std::ostream& os, IntersectionStatus status) {
0037 constexpr static std::array<const char*, 3> names = {
0038 {"missed/unreachable", "reachable", "onSurface"}};
0039
0040 os << names[static_cast<std::size_t>(status)];
0041 return os;
0042 }
0043
0044
0045
0046 template <unsigned int DIM>
0047 class Intersection {
0048 public:
0049
0050 using Position = Eigen::Map<const Vector<DIM>>;
0051
0052
0053
0054
0055
0056
0057 constexpr Intersection(const Vector<DIM>& position, double pathLength,
0058 IntersectionStatus status) noexcept
0059 : Intersection(std::span<const double, DIM>{position.data(), DIM},
0060 pathLength, status) {}
0061
0062
0063
0064
0065
0066 constexpr Intersection(const Position& position, double pathLength,
0067 IntersectionStatus status) noexcept
0068 : Intersection(std::span<const double, DIM>{position.data(), DIM},
0069 pathLength, status) {}
0070
0071
0072
0073
0074
0075 constexpr Intersection(std::span<const double, DIM> position,
0076 double pathLength, IntersectionStatus status) noexcept
0077 : m_pathLength(pathLength), m_status(status) {
0078 std::ranges::copy(position, m_position.begin());
0079 }
0080
0081
0082 constexpr Intersection(const Intersection&) noexcept = default;
0083
0084 constexpr Intersection(Intersection&&) noexcept = default;
0085
0086
0087 constexpr Intersection& operator=(const Intersection&) noexcept = default;
0088
0089
0090 constexpr Intersection& operator=(Intersection&&) noexcept = default;
0091
0092
0093
0094 constexpr bool isValid() const noexcept {
0095 return m_status != IntersectionStatus::unreachable;
0096 }
0097
0098
0099
0100 Position position() const noexcept { return Position{m_position.data()}; }
0101
0102
0103
0104 constexpr double pathLength() const noexcept { return m_pathLength; }
0105
0106
0107
0108 constexpr IntersectionStatus status() const noexcept { return m_status; }
0109
0110
0111
0112 constexpr static Intersection Invalid() noexcept { return Intersection(); }
0113
0114
0115
0116
0117
0118
0119 constexpr static bool pathLengthOrder(
0120 const Intersection& aIntersection,
0121 const Intersection& bIntersection) noexcept {
0122 auto a = aIntersection.pathLength();
0123 auto b = bIntersection.pathLength();
0124 return a < b;
0125 }
0126
0127
0128
0129
0130
0131
0132 constexpr static bool closestOrder(
0133 const Intersection& aIntersection,
0134 const Intersection& bIntersection) noexcept {
0135 using enum IntersectionStatus;
0136
0137 if ((aIntersection.status() == unreachable) &&
0138 (bIntersection.status() != unreachable)) {
0139 return false;
0140 }
0141 if ((aIntersection.status() != unreachable) &&
0142 (bIntersection.status() == unreachable)) {
0143 return true;
0144 }
0145
0146 auto a = aIntersection.pathLength();
0147 auto b = bIntersection.pathLength();
0148 return std::abs(a) < std::abs(b);
0149 }
0150
0151
0152
0153
0154
0155
0156 constexpr static bool closestForwardOrder(
0157 const Intersection& aIntersection,
0158 const Intersection& bIntersection) noexcept {
0159 auto a = aIntersection.pathLength();
0160 auto b = bIntersection.pathLength();
0161 return std::signbit(a) == std::signbit(b) ? std::abs(a) < std::abs(b)
0162 : a > b;
0163 }
0164
0165 private:
0166
0167 std::array<double, DIM> m_position{};
0168
0169 double m_pathLength = std::numeric_limits<double>::infinity();
0170
0171 IntersectionStatus m_status = IntersectionStatus::unreachable;
0172
0173 constexpr Intersection() noexcept = default;
0174 };
0175
0176
0177 using Intersection2D = Intersection<2>;
0178
0179 using Intersection3D = Intersection<3>;
0180
0181 static_assert(std::is_trivially_copy_constructible_v<Intersection2D>);
0182 static_assert(std::is_trivially_move_constructible_v<Intersection2D>);
0183 static_assert(std::is_trivially_move_assignable_v<Intersection2D>);
0184
0185
0186 using IntersectionIndex = std::uint8_t;
0187
0188 static constexpr IntersectionIndex s_maximumNumberOfIntersections = 2;
0189
0190
0191 template <unsigned int DIM>
0192 class MultiIntersection {
0193 public:
0194
0195 using IntersectionType = Intersection<DIM>;
0196
0197 using IndexedIntersection = std::pair<IntersectionType, IntersectionIndex>;
0198
0199
0200 using Container =
0201 std::array<IntersectionType, s_maximumNumberOfIntersections>;
0202
0203
0204 using size_type = IntersectionIndex;
0205
0206
0207
0208 constexpr explicit MultiIntersection(
0209 const IntersectionType& intersection) noexcept
0210 : m_intersections{intersection, IntersectionType::Invalid()}, m_size{1} {}
0211
0212
0213
0214 constexpr MultiIntersection(const IntersectionType& intersection1,
0215 const IntersectionType& intersection2) noexcept
0216 : m_intersections{intersection1, intersection2}, m_size{2} {}
0217
0218
0219 constexpr MultiIntersection(const MultiIntersection&) noexcept = default;
0220
0221 constexpr MultiIntersection(MultiIntersection&&) noexcept = default;
0222
0223
0224 constexpr MultiIntersection& operator=(const MultiIntersection&) noexcept =
0225 default;
0226
0227
0228 constexpr MultiIntersection& operator=(MultiIntersection&&) noexcept =
0229 default;
0230
0231
0232
0233
0234 constexpr const IntersectionType& operator[](IntersectionIndex index) const {
0235 return m_intersections[index];
0236 }
0237
0238
0239
0240
0241 constexpr const IntersectionType& at(IntersectionIndex index) const {
0242 return m_intersections.at(index);
0243 }
0244
0245
0246
0247 constexpr IntersectionIndex size() const noexcept { return m_size; }
0248
0249
0250
0251 constexpr auto begin() const noexcept {
0252 return std::span(m_intersections.data(), m_size).begin();
0253 }
0254
0255
0256 constexpr auto end() const noexcept {
0257 return std::span(m_intersections.data(), m_size).end();
0258 }
0259
0260
0261
0262 constexpr IntersectionType closest() const noexcept {
0263 return closestWithIndex().first;
0264 }
0265
0266
0267 constexpr IndexedIntersection closestWithIndex() const noexcept {
0268 auto min = std::ranges::min_element(m_intersections,
0269 IntersectionType::closestOrder);
0270 return {*min, static_cast<IntersectionIndex>(
0271 std::distance(m_intersections.begin(), min))};
0272 }
0273
0274
0275
0276 constexpr IntersectionType closestForward() const noexcept {
0277 return closestForwardWithIndex().first;
0278 }
0279
0280
0281 constexpr IndexedIntersection closestForwardWithIndex() const noexcept {
0282 auto min = std::ranges::min_element(m_intersections,
0283 IntersectionType::closestForwardOrder);
0284 return {*min, static_cast<IntersectionIndex>(
0285 std::distance(m_intersections.begin(), min))};
0286 }
0287
0288 private:
0289 Container m_intersections{};
0290 IntersectionIndex m_size{};
0291 };
0292
0293
0294 using MultiIntersection2D = MultiIntersection<2>;
0295
0296 using MultiIntersection3D = MultiIntersection<3>;
0297
0298 static_assert(std::is_trivially_copy_constructible_v<MultiIntersection2D>);
0299 static_assert(std::is_trivially_move_constructible_v<MultiIntersection2D>);
0300 static_assert(std::is_trivially_move_assignable_v<MultiIntersection2D>);
0301
0302 namespace detail {
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312 void printCheckPathLength(double pathLength, double nearLimit, double farLimit,
0313 const Logger& logger);
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327 inline bool checkPathLength(double pathLength, double nearLimit,
0328 double farLimit,
0329 const Logger& logger = getDummyLogger()) {
0330 if (logger.doPrint(Logging::VERBOSE)) [[unlikely]] {
0331 printCheckPathLength(pathLength, nearLimit, farLimit, logger);
0332 }
0333
0334
0335 const double tolerance = s_onSurfaceTolerance;
0336 return pathLength > nearLimit && pathLength < farLimit + tolerance;
0337 }
0338
0339 }
0340
0341 }