File indexing completed on 2024-11-15 09:01:55
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
0021 #include <boost/container/static_vector.hpp>
0022
0023 namespace Acts {
0024
0025
0026 enum class IntersectionStatus : int {
0027 missed = 0,
0028 unreachable = 0,
0029 reachable = 1,
0030 onSurface = 2
0031 };
0032
0033
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
0043
0044
0045 template <unsigned int DIM>
0046 class Intersection {
0047 public:
0048
0049 using Position = ActsVector<DIM>;
0050
0051 using Status = IntersectionStatus;
0052
0053
0054
0055
0056
0057
0058 constexpr Intersection(const Position& position, double pathLength,
0059 Status status)
0060 : m_position(position), m_pathLength(pathLength), m_status(status) {}
0061
0062
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
0076
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
0085
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
0097 auto a = aIntersection.pathLength();
0098 auto b = bIntersection.pathLength();
0099 return std::abs(a) < std::abs(b);
0100 }
0101
0102
0103
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
0114 Position m_position = Position::Zero();
0115
0116 ActsScalar m_pathLength = std::numeric_limits<double>::infinity();
0117
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
0135
0136
0137
0138
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
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
0192 Intersection3D m_intersection = Intersection3D::invalid();
0193
0194 const object_t* m_object = nullptr;
0195
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
0209
0210
0211
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
0248 MultiIntersection3D m_intersections;
0249
0250 const object_t* m_object = nullptr;
0251 };
0252
0253 namespace detail {
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
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
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 }
0301
0302 }