File indexing completed on 2025-12-14 09:20:35
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Common.hpp"
0013 #include "Acts/Geometry/GeometryContext.hpp"
0014 #include "Acts/Geometry/Polyhedron.hpp"
0015 #include "Acts/Utilities/Enumerate.hpp"
0016 #include "Acts/Utilities/GridAccessHelpers.hpp"
0017 #include "Acts/Utilities/Helpers.hpp"
0018 #include "Acts/Utilities/IAxis.hpp"
0019 #include "Acts/Utilities/Logger.hpp"
0020
0021 #include <algorithm>
0022 #include <array>
0023 #include <set>
0024 #include <string>
0025 #include <vector>
0026
0027 namespace Acts {
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 std::vector<std::size_t> binSequence(std::array<std::size_t, 2u> minMaxBins,
0041 std::size_t expand, std::size_t nBins,
0042 Acts::AxisBoundaryType type);
0043
0044
0045
0046
0047
0048
0049
0050 template <typename queries_type, typename expansion_type, std::size_t kDIM>
0051 void expand(queries_type& gridQueries,
0052 const expansion_type& referenceExpansion) {
0053 queries_type copiedQueries = gridQueries;
0054
0055 std::ranges::sort(copiedQueries, [](const auto& a, const auto& b) {
0056 return a[kDIM] < b[kDIM];
0057 });
0058
0059 auto midPoint =
0060 0.5 * (copiedQueries.front()[kDIM] + copiedQueries.back()[kDIM]);
0061
0062 for (auto& pq : gridQueries) {
0063 if (pq[kDIM] < midPoint) {
0064 pq[kDIM] -= referenceExpansion[kDIM];
0065 } else {
0066 pq[kDIM] += referenceExpansion[kDIM];
0067 }
0068 }
0069 }
0070
0071
0072
0073
0074
0075 template <typename grid_type>
0076 void applyReferenceExpansion(
0077 std::vector<typename grid_type::point_t>& gridQueries,
0078 const std::vector<double>& referenceExpansion) {
0079 if (referenceExpansion.empty()) {
0080 return;
0081 }
0082 if (referenceExpansion.size() != grid_type::DIM) {
0083 throw std::runtime_error(
0084 "IndexedSurfaceGridFiller: wrong dimension of reference expansion "
0085 "given.");
0086 }
0087 expand<decltype(gridQueries), decltype(referenceExpansion), 0u>(
0088 gridQueries, referenceExpansion);
0089 if constexpr (grid_type::DIM >= 2u) {
0090 expand<decltype(gridQueries), decltype(referenceExpansion), 1u>(
0091 gridQueries, referenceExpansion);
0092 }
0093 if constexpr (grid_type::DIM == 3u) {
0094 expand<decltype(gridQueries), decltype(referenceExpansion), 2u>(
0095 gridQueries, referenceExpansion);
0096 }
0097 }
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111 template <typename grid_type>
0112 std::set<typename grid_type::index_t> localIndices(
0113 const grid_type& grid,
0114 const std::vector<typename grid_type::point_t>& queries,
0115 const std::vector<std::size_t>& expansion = {}) {
0116
0117 std::set<typename grid_type::index_t> lIndices;
0118
0119 if (queries.empty()) {
0120 throw std::runtime_error("IndexedSurfaceGridFiller: no query point given.");
0121 }
0122
0123 if (!expansion.empty() && expansion.size() != grid_type::DIM) {
0124 throw std::runtime_error(
0125 "IndexedSurfaceGridFiller: wrong dimension of bin expansion given.");
0126 }
0127
0128
0129 std::array<Acts::AxisBoundaryType, grid_type::DIM> axisTypes{};
0130 std::array<std::size_t, grid_type::DIM> axisBins{};
0131
0132 for (auto [ia, a] : enumerate(grid.axes())) {
0133 axisTypes[ia] = a->getBoundaryType();
0134 axisBins[ia] = a->getNBins();
0135 }
0136
0137
0138 std::array<std::array<std::size_t, 2u>, grid_type::DIM> binRanges = {};
0139 for (auto& br : binRanges) {
0140 br[0u] = std::numeric_limits<std::size_t>::max();
0141 br[1u] = 0u;
0142 }
0143
0144 for (const auto& q : queries) {
0145 auto qbin = grid.localBinsFromPosition(q);
0146 for (std::size_t ib = 0; ib < grid_type::DIM; ++ib) {
0147 auto iqb = qbin[ib];
0148 binRanges[ib][0u] = std::min(iqb, binRanges[ib][0u]);
0149 binRanges[ib][1u] = std::max(iqb, binRanges[ib][1u]);
0150 }
0151 }
0152
0153 if constexpr (grid_type::DIM == 1u) {
0154
0155 std::size_t expand = expansion.empty() ? 0u : expansion[0u];
0156 auto localBins0 =
0157 binSequence(binRanges[0u], expand, axisBins[0u], axisTypes[0u]);
0158 for (auto l0 : localBins0) {
0159 typename grid_type::index_t b;
0160 b[0u] = l0;
0161 lIndices.insert(b);
0162 }
0163 }
0164
0165 if constexpr (grid_type::DIM == 2u) {
0166
0167 std::size_t expand = expansion.empty() ? 0u : expansion[0u];
0168 auto localBins0 =
0169 binSequence(binRanges[0u], expand, axisBins[0u], axisTypes[0u]);
0170 expand = expansion.empty() ? 0u : expansion[1u];
0171 auto localBins1 =
0172 binSequence(binRanges[1u], expand, axisBins[1u], axisTypes[1u]);
0173 for (auto l0 : localBins0) {
0174 for (auto l1 : localBins1) {
0175 typename grid_type::index_t b;
0176 b[0u] = l0;
0177 b[1u] = l1;
0178 lIndices.insert(b);
0179 }
0180 }
0181 }
0182 return lIndices;
0183 }
0184
0185
0186
0187
0188
0189
0190
0191
0192 template <typename local_bin>
0193 std::string outputIndices(const std::set<local_bin>& lbins) {
0194 std::string rString;
0195 for (auto [ilb, lb] : Acts::enumerate(lbins)) {
0196 if (ilb == 0) {
0197 rString = "bins: [";
0198 } else {
0199 rString += ", [";
0200 }
0201 for (auto [ib, b] : Acts::enumerate(lb)) {
0202 if (ib != 0u) {
0203 rString += ", ";
0204 }
0205 rString += std::to_string(b);
0206 }
0207 rString += "]";
0208 }
0209 return rString;
0210 }
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224 template <typename grid_t>
0225 class IndexGrid {
0226 public:
0227
0228 using grid_type = grid_t;
0229
0230
0231 grid_type grid;
0232
0233
0234 std::array<AxisDirection, grid_type::DIM> casts{};
0235
0236
0237 Transform3 transform = Transform3::Identity();
0238
0239
0240
0241
0242
0243 IndexGrid(grid_type&& igrid,
0244 const std::array<AxisDirection, grid_type::DIM>& icasts,
0245 const Transform3& itr = Transform3::Identity())
0246 : grid(std::move(igrid)), casts(icasts), transform(itr) {}
0247
0248 IndexGrid() = delete;
0249 };
0250
0251
0252 struct IndexGridFiller {
0253
0254 std::vector<std::size_t> binExpansion = {};
0255
0256
0257 std::vector<double> referenceExpansion = {};
0258
0259
0260 std::unique_ptr<const Logger> oLogger =
0261 getDefaultLogger("IndexGridFiller", Logging::INFO);
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282 template <typename index_grid, typename indexed_objects,
0283 typename reference_generator>
0284 void fill(
0285 const GeometryContext& gctx, index_grid& iGrid,
0286 const indexed_objects& iObjects, const reference_generator& rGenerator,
0287 const typename index_grid::grid_type::value_type& aToAll = {}) const {
0288
0289 for (auto [io, o] : enumerate(iObjects)) {
0290
0291 if (rangeContainsValue(aToAll, io)) {
0292 continue;
0293 }
0294
0295 auto refs = rGenerator.references(gctx, *o);
0296 std::vector<typename index_grid::grid_type::point_t> gridQueries;
0297 gridQueries.reserve(refs.size());
0298 for (const auto& ref : refs) {
0299
0300 gridQueries.push_back(
0301 GridAccessHelpers::castPosition<decltype(iGrid.grid)>(
0302 iGrid.transform * ref, iGrid.casts));
0303 }
0304 ACTS_DEBUG(gridQueries.size() << " reference points generated.");
0305
0306 if (!referenceExpansion.empty()) {
0307 ACTS_DEBUG("Applying reference expansion.");
0308 applyReferenceExpansion<decltype(iGrid.grid)>(gridQueries,
0309 referenceExpansion);
0310 }
0311
0312 auto lIndices = localIndices<decltype(iGrid.grid)>(
0313 iGrid.grid, gridQueries, binExpansion);
0314 ACTS_DEBUG(lIndices.size() << " indices assigned.");
0315 if (oLogger->level() <= Logging::VERBOSE) {
0316 ACTS_VERBOSE("- list of indices: " << outputIndices(lIndices));
0317 }
0318
0319 for (const auto& li : lIndices) {
0320 auto& bContent = iGrid.grid.atLocalBins(li);
0321 if (!rangeContainsValue(bContent, io)) {
0322 bContent.push_back(io);
0323 }
0324 }
0325 }
0326
0327
0328 if (!aToAll.empty()) {
0329 assignToAll(iGrid, aToAll);
0330 }
0331 }
0332
0333
0334
0335
0336
0337
0338 template <typename index_grid, typename indices>
0339 void assignToAll(index_grid& iGrid, const indices& idcs) const {
0340 for (std::size_t gi = 0; gi < iGrid.grid.size(true); ++gi) {
0341 auto& bContent = iGrid.grid.at(gi);
0342 for (const auto& io : idcs) {
0343 if (!rangeContainsValue(bContent, io)) {
0344 bContent.push_back(io);
0345 }
0346 }
0347 }
0348 }
0349
0350
0351
0352
0353 const Logger& logger() const { return (*oLogger); }
0354 };
0355
0356 }