File indexing completed on 2025-09-17 08:01:53
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/GeometryContext.hpp"
0013 #include "Acts/Surfaces/Surface.hpp"
0014 #include "Acts/Utilities/AnyGridView.hpp"
0015 #include "Acts/Utilities/AxisDefinitions.hpp"
0016 #include "Acts/Utilities/Grid.hpp"
0017 #include "Acts/Utilities/IAxis.hpp"
0018
0019 #include <iostream>
0020 #include <type_traits>
0021 #include <vector>
0022
0023 namespace Acts {
0024
0025 using SurfaceVector = std::vector<const Surface*>;
0026
0027
0028
0029
0030
0031
0032
0033 class SurfaceArray {
0034 public:
0035
0036 struct ISurfaceGridLookup {
0037
0038
0039
0040
0041 virtual void fill(const GeometryContext& gctx,
0042 const SurfaceVector& surfaces) = 0;
0043
0044
0045
0046
0047
0048
0049
0050
0051 virtual std::size_t completeBinning(const GeometryContext& gctx,
0052 const SurfaceVector& surfaces) = 0;
0053
0054
0055
0056
0057 virtual SurfaceVector& lookup(const Vector3& position) = 0;
0058
0059
0060
0061
0062
0063 virtual const SurfaceVector& lookup(const Vector3& position) const = 0;
0064
0065
0066
0067
0068
0069 virtual SurfaceVector& lookup(std::size_t bin) = 0;
0070
0071
0072
0073
0074
0075 virtual const SurfaceVector& lookup(std::size_t bin) const = 0;
0076
0077
0078
0079
0080
0081 virtual const SurfaceVector& neighbors(const Vector3& position) const = 0;
0082
0083
0084
0085
0086 virtual std::size_t size() const = 0;
0087
0088
0089
0090
0091 virtual Vector3 getBinCenter(std::size_t bin) const = 0;
0092
0093
0094
0095
0096 virtual std::vector<const IAxis*> getAxes() const = 0;
0097
0098 virtual std::optional<AnyGridConstView<SurfaceVector>> getGridView()
0099 const = 0;
0100
0101 virtual const Transform3& getTransform() const = 0;
0102
0103 virtual Surface::SurfaceType surfaceType() const = 0;
0104
0105
0106
0107 virtual std::size_t dimensions() const = 0;
0108
0109
0110
0111
0112
0113
0114 virtual bool isValidBin(std::size_t bin) const = 0;
0115
0116
0117
0118 virtual std::vector<AxisDirection> binningValues() const { return {}; };
0119
0120
0121 virtual ~ISurfaceGridLookup() = 0;
0122 };
0123
0124
0125
0126 template <class... Axes>
0127 struct SurfaceGridLookup : ISurfaceGridLookup {
0128 static constexpr std::size_t DIM = sizeof...(Axes);
0129
0130 public:
0131
0132
0133
0134 using point_t =
0135 std::conditional_t<DIM == 1, std::array<double, 1>, ActsVector<DIM>>;
0136 using Grid_t = Grid<SurfaceVector, Axes...>;
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149 SurfaceGridLookup(Surface::SurfaceType type, const Transform3& transform,
0150 double R, double Z, std::tuple<Axes...> axes,
0151 std::vector<AxisDirection> bValues = {})
0152 : m_type(type),
0153 m_transform(transform),
0154 m_itransform(transform.inverse()),
0155 m_grid(std::move(axes)),
0156 m_binValues(std::move(bValues)) {
0157 m_neighborMap.resize(m_grid.size());
0158
0159 using namespace VectorHelpers;
0160
0161 switch (type) {
0162 using enum Surface::SurfaceType;
0163 case Cylinder:
0164 m_globalToLocal = [](const Vector3& pos) {
0165 return Vector2(phi(pos), pos.z());
0166 };
0167 m_localToGlobal = [R](const Vector2& loc) {
0168
0169 return Vector3(R * std::cos(loc[0]), R * std::sin(loc[0]), loc[1]);
0170 };
0171 break;
0172 case Disc:
0173 m_globalToLocal = [](const Vector3& pos) {
0174 return Vector2(perp(pos), phi(pos));
0175 };
0176 m_localToGlobal = [Z](const Vector2& loc) {
0177
0178 return Vector3(loc[0] * std::cos(loc[1]), loc[0] * std::sin(loc[1]),
0179 Z);
0180 };
0181 break;
0182 case Plane:
0183 m_globalToLocal = [](const Vector3& pos) {
0184 return Vector2(perp(pos), phi(pos));
0185 };
0186 m_localToGlobal = [](const Vector2& loc) {
0187 return Vector3(loc.x(), loc.y(), 0.);
0188 };
0189 break;
0190 default:
0191 throw std::invalid_argument("Surface type not supported");
0192 }
0193 }
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204 void fill(const GeometryContext& gctx,
0205 const SurfaceVector& surfaces) override {
0206 for (const auto& srf : surfaces) {
0207 Vector3 pos = srf->referencePosition(gctx, AxisDirection::AxisR);
0208 lookup(pos).push_back(srf);
0209 }
0210
0211 populateNeighborCache();
0212 }
0213
0214
0215
0216
0217
0218
0219
0220
0221 std::size_t completeBinning(const GeometryContext& gctx,
0222 const SurfaceVector& surfaces) override {
0223 std::size_t binCompleted = 0;
0224 std::size_t nBins = size();
0225 double minPath = 0;
0226 double curPath = 0;
0227 const Surface* minSrf = nullptr;
0228
0229 for (std::size_t b = 0; b < nBins; ++b) {
0230 if (!isValidBin(b)) {
0231 continue;
0232 }
0233 std::vector<const Surface*>& binContent = lookup(b);
0234
0235 if (!binContent.empty()) {
0236 continue;
0237 }
0238
0239 Vector3 binCtr = getBinCenter(b);
0240 minPath = std::numeric_limits<double>::max();
0241 for (const auto& srf : surfaces) {
0242 curPath =
0243 (binCtr - srf->referencePosition(gctx, AxisDirection::AxisR))
0244 .norm();
0245
0246 if (curPath < minPath) {
0247 minPath = curPath;
0248 minSrf = srf;
0249 }
0250 }
0251
0252 binContent.push_back(minSrf);
0253 ++binCompleted;
0254 }
0255
0256
0257 populateNeighborCache();
0258 return binCompleted;
0259 }
0260
0261
0262
0263
0264 SurfaceVector& lookup(const Vector3& position) override {
0265 return m_grid.atPosition(m_globalToLocal(m_transform * position));
0266 }
0267
0268
0269
0270
0271
0272 const SurfaceVector& lookup(const Vector3& position) const override {
0273 return m_grid.atPosition(m_globalToLocal(m_transform * position));
0274 }
0275
0276
0277
0278
0279
0280 SurfaceVector& lookup(std::size_t bin) override { return m_grid.at(bin); }
0281
0282
0283
0284
0285
0286 const SurfaceVector& lookup(std::size_t bin) const override {
0287 return m_grid.at(bin);
0288 }
0289
0290
0291
0292
0293
0294 const SurfaceVector& neighbors(const Vector3& position) const override {
0295 auto lposition = m_globalToLocal(m_transform * position);
0296 return m_neighborMap.at(m_grid.globalBinFromPosition(lposition));
0297 }
0298
0299
0300
0301
0302 std::size_t size() const override { return m_grid.size(); }
0303
0304
0305
0306 std::vector<AxisDirection> binningValues() const override {
0307 return m_binValues;
0308 }
0309
0310
0311
0312
0313 Vector3 getBinCenter(std::size_t bin) const override {
0314 return getBinCenterImpl(bin);
0315 }
0316
0317
0318
0319
0320 std::vector<const IAxis*> getAxes() const override {
0321 auto arr = m_grid.axes();
0322 return std::vector<const IAxis*>(arr.begin(), arr.end());
0323 }
0324
0325 std::optional<AnyGridConstView<SurfaceVector>> getGridView()
0326 const override {
0327 return AnyGridConstView<SurfaceVector>{m_grid};
0328 }
0329
0330 const Transform3& getTransform() const override { return m_transform; }
0331
0332 Surface::SurfaceType surfaceType() const override { return m_type; }
0333
0334
0335
0336 std::size_t dimensions() const override { return DIM; }
0337
0338
0339
0340
0341
0342
0343 bool isValidBin(std::size_t bin) const override {
0344 std::array<std::size_t, DIM> indices = m_grid.localBinsFromGlobalBin(bin);
0345 std::array<std::size_t, DIM> nBins = m_grid.numLocalBins();
0346 for (std::size_t i = 0; i < indices.size(); ++i) {
0347 std::size_t idx = indices.at(i);
0348 if (idx <= 0 || idx >= nBins.at(i) + 1) {
0349 return false;
0350 }
0351 }
0352
0353 return true;
0354 }
0355
0356 private:
0357 void populateNeighborCache() {
0358
0359 for (std::size_t i = 0; i < m_grid.size(); i++) {
0360 if (!isValidBin(i)) {
0361 continue;
0362 }
0363 typename Grid_t::index_t loc = m_grid.localBinsFromGlobalBin(i);
0364 auto neighborIdxs = m_grid.neighborHoodIndices(loc, 1u);
0365 std::vector<const Surface*>& neighbors = m_neighborMap.at(i);
0366 neighbors.clear();
0367
0368 for (const auto idx : neighborIdxs) {
0369 const std::vector<const Surface*>& binContent = m_grid.at(idx);
0370 std::copy(binContent.begin(), binContent.end(),
0371 std::back_inserter(neighbors));
0372 }
0373 }
0374 }
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386 Vector3 getBinCenterImpl(std::size_t bin) const
0387 requires(DIM != 1)
0388 {
0389 return m_itransform *
0390 m_localToGlobal(ActsVector<DIM>(
0391 m_grid.binCenter(m_grid.localBinsFromGlobalBin(bin)).data()));
0392 }
0393
0394
0395
0396 Vector3 getBinCenterImpl(std::size_t bin) const
0397 requires(DIM == 1)
0398 {
0399 point_t pos = m_grid.binCenter(m_grid.localBinsFromGlobalBin(bin));
0400 return m_itransform * m_localToGlobal(pos);
0401 }
0402
0403 Surface::SurfaceType m_type;
0404 Transform3 m_transform;
0405 Transform3 m_itransform;
0406 std::function<point_t(const Vector3&)> m_globalToLocal;
0407 std::function<Vector3(const point_t&)> m_localToGlobal;
0408 Grid_t m_grid;
0409 std::vector<AxisDirection> m_binValues;
0410 std::vector<SurfaceVector> m_neighborMap;
0411 };
0412
0413
0414
0415 struct SingleElementLookup : ISurfaceGridLookup {
0416
0417
0418 explicit SingleElementLookup(SurfaceVector::value_type element)
0419 : m_element({element}) {}
0420
0421
0422
0423 explicit SingleElementLookup(const SurfaceVector& elements)
0424 : m_element(elements) {}
0425
0426
0427
0428 SurfaceVector& lookup(const Vector3& ) override {
0429 return m_element;
0430 }
0431
0432
0433
0434 const SurfaceVector& lookup(const Vector3& ) const override {
0435 return m_element;
0436 }
0437
0438
0439
0440 SurfaceVector& lookup(std::size_t ) override { return m_element; }
0441
0442
0443
0444 const SurfaceVector& lookup(std::size_t ) const override {
0445 return m_element;
0446 }
0447
0448
0449
0450 const SurfaceVector& neighbors(const Vector3& ) const override {
0451 return m_element;
0452 }
0453
0454
0455
0456 std::size_t size() const override { return 1; }
0457
0458
0459
0460 Vector3 getBinCenter(std::size_t ) const override {
0461 return Vector3(0, 0, 0);
0462 }
0463
0464
0465
0466 std::vector<const IAxis*> getAxes() const override { return {}; }
0467
0468 std::optional<AnyGridConstView<SurfaceVector>> getGridView()
0469 const override {
0470 return std::nullopt;
0471 }
0472
0473 const Transform3& getTransform() const override {
0474 static const Transform3 identityTransform = Transform3::Identity();
0475 return identityTransform;
0476 }
0477
0478 Surface::SurfaceType surfaceType() const override {
0479 return Surface::SurfaceType::Other;
0480 }
0481
0482
0483
0484 std::size_t dimensions() const override { return 0; }
0485
0486
0487
0488 void fill(const GeometryContext& ,
0489 const SurfaceVector& ) override {}
0490
0491
0492
0493 std::size_t completeBinning(const GeometryContext& ,
0494 const SurfaceVector& ) override {
0495 return 0;
0496 }
0497
0498
0499
0500 bool isValidBin(std::size_t ) const override { return true; }
0501
0502 private:
0503 SurfaceVector m_element;
0504 };
0505
0506
0507
0508
0509
0510
0511
0512
0513 explicit SurfaceArray(std::unique_ptr<ISurfaceGridLookup> gridLookup,
0514 std::vector<std::shared_ptr<const Surface>> surfaces,
0515 const Transform3& transform = Transform3::Identity());
0516
0517
0518
0519 explicit SurfaceArray(std::shared_ptr<const Surface> srf);
0520
0521
0522
0523
0524 SurfaceVector& at(const Vector3& position) {
0525 return p_gridLookup->lookup(position);
0526 }
0527
0528
0529
0530
0531
0532 const SurfaceVector& at(const Vector3& position) const {
0533 return p_gridLookup->lookup(position);
0534 }
0535
0536
0537
0538
0539 SurfaceVector& at(std::size_t bin) { return p_gridLookup->lookup(bin); }
0540
0541
0542
0543
0544 const SurfaceVector& at(std::size_t bin) const {
0545 return p_gridLookup->lookup(bin);
0546 }
0547
0548
0549
0550
0551
0552
0553
0554 const SurfaceVector& neighbors(const Vector3& position) const {
0555 return p_gridLookup->neighbors(position);
0556 }
0557
0558
0559
0560
0561 std::size_t size() const { return p_gridLookup->size(); }
0562
0563
0564
0565
0566 Vector3 getBinCenter(std::size_t bin) const {
0567 return p_gridLookup->getBinCenter(bin);
0568 }
0569
0570
0571
0572
0573
0574
0575 const SurfaceVector& surfaces() const { return m_surfacesRawPointers; }
0576
0577
0578
0579
0580
0581 std::vector<const IAxis*> getAxes() const { return p_gridLookup->getAxes(); }
0582
0583
0584
0585
0586
0587
0588 bool isValidBin(std::size_t bin) const {
0589 return p_gridLookup->isValidBin(bin);
0590 }
0591
0592 const Transform3& transform() const { return m_transform; }
0593
0594
0595
0596 std::vector<AxisDirection> binningValues() const {
0597 return p_gridLookup->binningValues();
0598 };
0599
0600
0601
0602
0603
0604 std::ostream& toStream(const GeometryContext& gctx, std::ostream& sl) const;
0605
0606
0607 const ISurfaceGridLookup& gridLookup() const { return *p_gridLookup; }
0608
0609 private:
0610 std::unique_ptr<ISurfaceGridLookup> p_gridLookup;
0611
0612 std::vector<std::shared_ptr<const Surface>> m_surfaces;
0613
0614
0615 SurfaceVector m_surfacesRawPointers;
0616
0617
0618 Transform3 m_transform;
0619 };
0620
0621 }