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