File indexing completed on 2026-05-29 07:46:32
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/ReferenceGenerators.hpp"
0013 #include "Acts/Surfaces/Surface.hpp"
0014 #include "Acts/Utilities/AxisDefinitions.hpp"
0015 #include "Acts/Utilities/KDTree.hpp"
0016
0017 #include <array>
0018 #include <ranges>
0019 #include <stdexcept>
0020 #include <tuple>
0021 #include <vector>
0022
0023 namespace Acts {
0024
0025
0026
0027
0028
0029
0030 template <std::size_t kDIM = 2u, std::size_t bSize = 100u>
0031 class KdtSurfaces {
0032 public:
0033
0034 using KDTS =
0035 KDTree<kDIM, std::shared_ptr<Surface>, double, std::array, bSize>;
0036
0037
0038 using Query = std::array<double, kDIM>;
0039
0040
0041 using Entry = std::pair<Query, std::shared_ptr<Surface>>;
0042
0043
0044
0045
0046
0047
0048
0049 KdtSurfaces(const GeometryContext& gctx,
0050 const std::vector<std::shared_ptr<Surface>>& surfaces,
0051 const std::array<AxisDirection, kDIM>& casts,
0052 const std::shared_ptr<IReferenceGenerator>& rgen =
0053 std::make_shared<PolyhedronReferenceGenerator>())
0054 : m_kdt(nullptr), m_casts(casts), m_rGenerator(rgen) {
0055
0056 if (kDIM == 0u) {
0057 throw std::invalid_argument(
0058 "KdtSurfaces: dimension and/or cast rules are incorrect.");
0059 }
0060
0061 std::vector<Entry> kdtEntries;
0062 kdtEntries.reserve(surfaces.size());
0063 for (auto& s : surfaces) {
0064
0065 const auto references = m_rGenerator->references(gctx, *s);
0066 std::vector<Query> castedReferences;
0067 castedReferences.reserve(references.size());
0068 for (const auto& r : references) {
0069
0070 Query rc = {};
0071 fillCasts(r, rc, std::make_integer_sequence<std::size_t, kDIM>{});
0072 castedReferences.push_back(rc);
0073 }
0074
0075 kdtEntries.push_back({cog(castedReferences), s});
0076 }
0077
0078 m_kdt = std::make_unique<KDTS>(std::move(kdtEntries));
0079 }
0080
0081
0082
0083
0084
0085
0086 std::vector<std::shared_ptr<Surface>> surfaces(
0087 const RangeXD<kDIM, double>& range) const {
0088
0089 std::vector<std::shared_ptr<Surface>> surfacePtrs;
0090 auto surfaceQuery = m_kdt->rangeSearchWithKey(range);
0091 std::ranges::for_each(
0092 surfaceQuery, [&](auto& surf) { surfacePtrs.push_back(surf.second); });
0093 return surfacePtrs;
0094 }
0095
0096
0097
0098
0099
0100
0101 std::vector<std::shared_ptr<Surface>> surfaces(const Extent& extent) const {
0102 RangeXD<kDIM, double> qRange;
0103 for (auto [ibv, v] : enumerate(m_casts)) {
0104 qRange[ibv] = extent.range(v);
0105 }
0106 return surfaces(qRange);
0107 }
0108
0109 private:
0110
0111 std::unique_ptr<KDTS> m_kdt = nullptr;
0112
0113
0114 std::array<AxisDirection, kDIM> m_casts = {};
0115
0116
0117 std::shared_ptr<IReferenceGenerator> m_rGenerator{nullptr};
0118
0119
0120
0121
0122 template <typename Array, std::size_t... idx>
0123 void fillCasts(const Vector3& position, Array& a,
0124 std::index_sequence<idx...> ) const {
0125 ((a[idx] = VectorHelpers::cast(position, m_casts[idx])), ...);
0126 }
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139 Query cog(const std::vector<Query>& cQueries) const {
0140
0141 if (cQueries.size() == 1) {
0142 return cQueries.front();
0143 }
0144
0145 Query c{};
0146 float weight = 1. / cQueries.size();
0147 for (auto& q : cQueries) {
0148 std::transform(c.begin(), c.end(), q.begin(), c.begin(),
0149 std::plus<double>());
0150 }
0151 std::ranges::for_each(c, [&](auto& v) { v *= weight; });
0152 return c;
0153 }
0154 };
0155
0156 }