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