![]() |
|
|||
File indexing completed on 2025-06-30 07:51:54
0001 // This file is part of the ACTS project. 0002 // 0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project 0004 // 0005 // This Source Code Form is subject to the terms of the Mozilla Public 0006 // License, v. 2.0. If a copy of the MPL was not distributed with this 0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/. 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/AxisDefinitions.hpp" 0015 #include "Acts/Utilities/Grid.hpp" 0016 #include "Acts/Utilities/IAxis.hpp" 0017 0018 #include <iostream> 0019 #include <type_traits> 0020 #include <vector> 0021 0022 namespace Acts { 0023 0024 using SurfaceVector = std::vector<const Surface*>; 0025 0026 /// @brief Provides Surface binning in N dimensions 0027 /// 0028 /// Uses @c Grid under the hood to implement the storage and lookup 0029 /// Contains a lookup struct which talks to the @c Grid 0030 /// and performs utility actions. This struct needs to be initialised 0031 /// externally and passed to @c SurfaceArray on construction. 0032 class SurfaceArray { 0033 public: 0034 /// @brief Base interface for all surface lookups. 0035 struct ISurfaceGridLookup { 0036 /// @brief Fill provided surfaces into the contained @c Grid. 0037 /// @param gctx The current geometry context object, e.g. alignment 0038 0039 /// @param surfaces Input surface pointers 0040 virtual void fill(const GeometryContext& gctx, 0041 const SurfaceVector& surfaces) = 0; 0042 0043 /// @brief Attempts to fix sub-optimal binning by filling closest 0044 /// Surfaces into empty bin 0045 /// 0046 /// @param gctx The current geometry context object, e.g. alignment 0047 0048 /// @param surfaces The surface pointers to fill 0049 /// @return number of bins that were filled 0050 virtual std::size_t completeBinning(const GeometryContext& gctx, 0051 const SurfaceVector& surfaces) = 0; 0052 0053 /// @brief Performs lookup at @c pos and returns bin content as reference 0054 /// @param position Lookup position 0055 /// @return @c SurfaceVector at given bin 0056 virtual SurfaceVector& lookup(const Vector3& position) = 0; 0057 0058 /// @brief Performs lookup at @c pos and returns bin content as const 0059 /// reference 0060 /// @param position Lookup position 0061 /// @return @c SurfaceVector at given bin 0062 virtual const SurfaceVector& lookup(const Vector3& position) const = 0; 0063 0064 /// @brief Performs lookup at global bin and returns bin content as 0065 /// reference 0066 /// @param bin Global lookup bin 0067 /// @return @c SurfaceVector at given bin 0068 virtual SurfaceVector& lookup(std::size_t bin) = 0; 0069 0070 /// @brief Performs lookup at global bin and returns bin content as const 0071 /// reference 0072 /// @param bin Global lookup bin 0073 /// @return @c SurfaceVector at given bin 0074 virtual const SurfaceVector& lookup(std::size_t bin) const = 0; 0075 0076 /// @brief Performs a lookup at @c pos, but returns neighbors as well 0077 /// 0078 /// @param position Lookup position 0079 /// @return @c SurfaceVector at given bin. Copy of all bins selected 0080 virtual const SurfaceVector& neighbors(const Vector3& position) const = 0; 0081 0082 /// @brief Returns the total size of the grid (including under/overflow 0083 /// bins) 0084 /// @return Size of the grid data structure 0085 virtual std::size_t size() const = 0; 0086 0087 /// @brief Gets the center position of bin @c bin in global coordinates 0088 /// @param bin the global bin index 0089 /// @return The bin center 0090 virtual Vector3 getBinCenter(std::size_t bin) const = 0; 0091 0092 /// @brief Returns copies of the axes used in the grid as @c AnyAxis 0093 /// @return The axes 0094 /// @note This returns copies. Use for introspection and querying. 0095 virtual std::vector<const IAxis*> getAxes() const = 0; 0096 0097 /// @brief Get the number of dimensions of the grid. 0098 /// @return number of dimensions 0099 virtual std::size_t dimensions() const = 0; 0100 0101 /// @brief Checks if global bin is valid 0102 /// @param bin the global bin index 0103 /// @return bool if the bin is valid 0104 /// @note Valid means that the index points to a bin which is not a under 0105 /// or overflow bin or out of range in any axis. 0106 virtual bool isValidBin(std::size_t bin) const = 0; 0107 0108 /// @brief The binning values described by this surface grid lookup 0109 /// They are in order of the axes (optional) and empty for eingle lookups 0110 virtual std::vector<AxisDirection> binningValues() const { return {}; }; 0111 0112 /// Pure virtual destructor 0113 virtual ~ISurfaceGridLookup() = 0; 0114 }; 0115 0116 /// @brief Lookup helper which encapsulates a @c Grid 0117 /// @tparam Axes The axes used for the grid 0118 template <class... Axes> 0119 struct SurfaceGridLookup : ISurfaceGridLookup { 0120 static constexpr std::size_t DIM = sizeof...(Axes); 0121 0122 public: 0123 /// @brief Specifies the local coordinate type. 0124 /// This resolves to @c ActsVector<DIM> for DIM > 1, else @c 0125 /// std::array<double, 1> 0126 using point_t = 0127 std::conditional_t<DIM == 1, std::array<double, 1>, ActsVector<DIM>>; 0128 using Grid_t = Grid<SurfaceVector, Axes...>; 0129 0130 /// @brief Default constructor 0131 /// 0132 /// @param globalToLocal Callable that converts from global to local 0133 /// @param localToGlobal Callable that converts from local to global 0134 /// @param axes The axes to build the grid data structure. 0135 /// @param bValues What the axes represent (optional) 0136 /// @note Signature of localToGlobal and globalToLocal depends on @c DIM. 0137 /// If DIM > 1, local coords are @c ActsVector<DIM> else 0138 /// @c std::array<double, 1>. 0139 SurfaceGridLookup(std::function<point_t(const Vector3&)> globalToLocal, 0140 std::function<Vector3(const point_t&)> localToGlobal, 0141 std::tuple<Axes...> axes, 0142 std::vector<AxisDirection> bValues = {}) 0143 : m_globalToLocal(std::move(globalToLocal)), 0144 m_localToGlobal(std::move(localToGlobal)), 0145 m_grid(std::move(axes)), 0146 m_binValues(std::move(bValues)) { 0147 m_neighborMap.resize(m_grid.size()); 0148 } 0149 0150 /// @brief Fill provided surfaces into the contained @c Grid. 0151 /// 0152 /// This is done by iterating, accessing the referencePosition, lookup 0153 /// and append. 0154 /// Also populates the neighbor map by combining the filled bins of 0155 /// all bins around a given one. 0156 /// 0157 /// @param gctx The current geometry context object, e.g. alignment 0158 /// @param surfaces Input surface pointers 0159 void fill(const GeometryContext& gctx, 0160 const SurfaceVector& surfaces) override { 0161 for (const auto& srf : surfaces) { 0162 Vector3 pos = srf->referencePosition(gctx, AxisDirection::AxisR); 0163 lookup(pos).push_back(srf); 0164 } 0165 0166 populateNeighborCache(); 0167 } 0168 0169 /// @brief Attempts to fix sub-optimal binning by filling closest 0170 /// Surfaces into empty bins 0171 /// @note This does not always do what you want. 0172 /// 0173 /// @param gctx The current geometry context object, e.g. alignment 0174 /// @param surfaces The surface pointers to fill 0175 /// @return number of bins that were filled 0176 std::size_t completeBinning(const GeometryContext& gctx, 0177 const SurfaceVector& surfaces) override { 0178 std::size_t binCompleted = 0; 0179 std::size_t nBins = size(); 0180 double minPath = 0; 0181 double curPath = 0; 0182 const Surface* minSrf = nullptr; 0183 0184 for (std::size_t b = 0; b < nBins; ++b) { 0185 if (!isValidBin(b)) { 0186 continue; 0187 } 0188 std::vector<const Surface*>& binContent = lookup(b); 0189 // only complete if we have an empty bin 0190 if (!binContent.empty()) { 0191 continue; 0192 } 0193 0194 Vector3 binCtr = getBinCenter(b); 0195 minPath = std::numeric_limits<double>::max(); 0196 for (const auto& srf : surfaces) { 0197 curPath = 0198 (binCtr - srf->referencePosition(gctx, AxisDirection::AxisR)) 0199 .norm(); 0200 0201 if (curPath < minPath) { 0202 minPath = curPath; 0203 minSrf = srf; 0204 } 0205 } 0206 0207 binContent.push_back(minSrf); 0208 ++binCompleted; 0209 } 0210 0211 // recreate neighborcache 0212 populateNeighborCache(); 0213 return binCompleted; 0214 } 0215 0216 /// @brief Performs lookup at @c pos and returns bin content as reference 0217 /// @param position Lookup position 0218 /// @return @c SurfaceVector at given bin 0219 SurfaceVector& lookup(const Vector3& position) override { 0220 return m_grid.atPosition(m_globalToLocal(position)); 0221 } 0222 0223 /// @brief Performs lookup at @c pos and returns bin content as const 0224 /// reference 0225 /// @param position Lookup position 0226 /// @return @c SurfaceVector at given bin 0227 const SurfaceVector& lookup(const Vector3& position) const override { 0228 return m_grid.atPosition(m_globalToLocal(position)); 0229 } 0230 0231 /// @brief Performs lookup at global bin and returns bin content as 0232 /// reference 0233 /// @param bin Global lookup bin 0234 /// @return @c SurfaceVector at given bin 0235 SurfaceVector& lookup(std::size_t bin) override { return m_grid.at(bin); } 0236 0237 /// @brief Performs lookup at global bin and returns bin content as const 0238 /// reference 0239 /// @param bin Global lookup bin 0240 /// @return @c SurfaceVector at given bin 0241 const SurfaceVector& lookup(std::size_t bin) const override { 0242 return m_grid.at(bin); 0243 } 0244 0245 /// @brief Performs a lookup at @c pos, but returns neighbors as well 0246 /// 0247 /// @param position Lookup position 0248 /// @return @c SurfaceVector at given bin. Copy of all bins selected 0249 const SurfaceVector& neighbors(const Vector3& position) const override { 0250 auto lposition = m_globalToLocal(position); 0251 return m_neighborMap.at(m_grid.globalBinFromPosition(lposition)); 0252 } 0253 0254 /// @brief Returns the total size of the grid (including under/overflow 0255 /// bins) 0256 /// @return Size of the grid data structure 0257 std::size_t size() const override { return m_grid.size(); } 0258 0259 /// @brief The binning values described by this surface grid lookup 0260 /// They are in order of the axes 0261 std::vector<AxisDirection> binningValues() const override { 0262 return m_binValues; 0263 } 0264 0265 /// @brief Gets the center position of bin @c bin in global coordinates 0266 /// @param bin the global bin index 0267 /// @return The bin center 0268 Vector3 getBinCenter(std::size_t bin) const override { 0269 return getBinCenterImpl(bin); 0270 } 0271 0272 /// @brief Returns copies of the axes used in the grid as @c AnyAxis 0273 /// @return The axes 0274 /// @note This returns copies. Use for introspection and querying. 0275 std::vector<const IAxis*> getAxes() const override { 0276 auto arr = m_grid.axes(); 0277 return std::vector<const IAxis*>(arr.begin(), arr.end()); 0278 } 0279 0280 /// @brief Get the number of dimensions of the grid. 0281 /// @return number of dimensions 0282 std::size_t dimensions() const override { return DIM; } 0283 0284 /// @brief Checks if global bin is valid 0285 /// @param bin the global bin index 0286 /// @return bool if the bin is valid 0287 /// @note Valid means that the index points to a bin which is not a under 0288 /// or overflow bin or out of range in any axis. 0289 bool isValidBin(std::size_t bin) const override { 0290 std::array<std::size_t, DIM> indices = m_grid.localBinsFromGlobalBin(bin); 0291 std::array<std::size_t, DIM> nBins = m_grid.numLocalBins(); 0292 for (std::size_t i = 0; i < indices.size(); ++i) { 0293 std::size_t idx = indices.at(i); 0294 if (idx <= 0 || idx >= nBins.at(i) + 1) { 0295 return false; 0296 } 0297 } 0298 0299 return true; 0300 } 0301 0302 private: 0303 void populateNeighborCache() { 0304 // calculate neighbors for every bin and store in map 0305 for (std::size_t i = 0; i < m_grid.size(); i++) { 0306 if (!isValidBin(i)) { 0307 continue; 0308 } 0309 typename Grid_t::index_t loc = m_grid.localBinsFromGlobalBin(i); 0310 auto neighborIdxs = m_grid.neighborHoodIndices(loc, 1u); 0311 std::vector<const Surface*>& neighbors = m_neighborMap.at(i); 0312 neighbors.clear(); 0313 0314 for (const auto idx : neighborIdxs) { 0315 const std::vector<const Surface*>& binContent = m_grid.at(idx); 0316 std::copy(binContent.begin(), binContent.end(), 0317 std::back_inserter(neighbors)); 0318 } 0319 } 0320 } 0321 0322 /// Internal method. 0323 /// This is here, because apparently Eigen doesn't like Vector1. 0324 /// So SurfaceGridLookup internally uses std::array<double, 1> instead 0325 /// of Vector1 (see the point_t typedef). This needs to be switched here, 0326 /// so as not to 0327 /// attempt an initialization of Vector1 that Eigen will complain about. 0328 /// The SFINAE is hidden in this private method so the public 0329 /// interface stays the same, since we don't care what happens 0330 /// here on the callers end 0331 /// This is the version for DIM>1 0332 Vector3 getBinCenterImpl(std::size_t bin) const 0333 requires(DIM != 1) 0334 { 0335 return m_localToGlobal(ActsVector<DIM>( 0336 m_grid.binCenter(m_grid.localBinsFromGlobalBin(bin)).data())); 0337 } 0338 0339 /// Internal method, see above. 0340 /// This is the version for DIM==1 0341 Vector3 getBinCenterImpl(std::size_t bin) const 0342 requires(DIM == 1) 0343 { 0344 point_t pos = m_grid.binCenter(m_grid.localBinsFromGlobalBin(bin)); 0345 return m_localToGlobal(pos); 0346 } 0347 0348 std::function<point_t(const Vector3&)> m_globalToLocal; 0349 std::function<Vector3(const point_t&)> m_localToGlobal; 0350 Grid_t m_grid; 0351 std::vector<AxisDirection> m_binValues; 0352 std::vector<SurfaceVector> m_neighborMap; 0353 }; 0354 0355 /// @brief Lookup implementation which wraps one element and always returns 0356 /// this element when lookup is called 0357 struct SingleElementLookup : ISurfaceGridLookup { 0358 /// @brief Default constructor. 0359 /// @param element the one and only element. 0360 explicit SingleElementLookup(SurfaceVector::value_type element) 0361 : m_element({element}) {} 0362 0363 /// @brief Default constructor. 0364 /// @param elements the surfaces that are provided through a single lookup 0365 explicit SingleElementLookup(const SurfaceVector& elements) 0366 : m_element(elements) {} 0367 0368 /// @brief Lookup, always returns @c element 0369 /// @return reference to vector containing only @c element 0370 SurfaceVector& lookup(const Vector3& /*position*/) override { 0371 return m_element; 0372 } 0373 0374 /// @brief Lookup, always returns @c element 0375 /// @return reference to vector containing only @c element 0376 const SurfaceVector& lookup(const Vector3& /*position*/) const override { 0377 return m_element; 0378 } 0379 0380 /// @brief Lookup, always returns @c element 0381 /// @return reference to vector containing only @c element 0382 SurfaceVector& lookup(std::size_t /*bin*/) override { return m_element; } 0383 0384 /// @brief Lookup, always returns @c element 0385 /// @return reference to vector containing only @c element 0386 const SurfaceVector& lookup(std::size_t /*bin*/) const override { 0387 return m_element; 0388 } 0389 0390 /// @brief Lookup, always returns @c element 0391 /// @return reference to vector containing only @c element 0392 const SurfaceVector& neighbors(const Vector3& /*position*/) const override { 0393 return m_element; 0394 } 0395 0396 /// @brief returns 1 0397 /// @return 1 0398 std::size_t size() const override { return 1; } 0399 0400 /// @brief Gets the bin center, but always returns (0, 0, 0) 0401 /// @return (0, 0, 0) 0402 Vector3 getBinCenter(std::size_t /*bin*/) const override { 0403 return Vector3(0, 0, 0); 0404 } 0405 0406 /// @brief Returns an empty vector of @c AnyAxis 0407 /// @return empty vector 0408 std::vector<const IAxis*> getAxes() const override { return {}; } 0409 0410 /// @brief Get the number of dimensions 0411 /// @return always 0 0412 std::size_t dimensions() const override { return 0; } 0413 0414 /// @brief Comply with concept and provide fill method 0415 /// @note Does nothing 0416 void fill(const GeometryContext& /*gctx*/, 0417 const SurfaceVector& /*surfaces*/) override {} 0418 0419 /// @brief Comply with concept and provide completeBinning method 0420 /// @note Does nothing 0421 std::size_t completeBinning(const GeometryContext& /*gctx*/, 0422 const SurfaceVector& /*surfaces*/) override { 0423 return 0; 0424 } 0425 0426 /// @brief Returns if the bin is valid (it is) 0427 /// @return always true 0428 bool isValidBin(std::size_t /*bin*/) const override { return true; } 0429 0430 private: 0431 SurfaceVector m_element; 0432 }; 0433 0434 /// @brief Default constructor which takes a @c SurfaceLookup and a vector of 0435 /// surfaces 0436 /// @param gridLookup The grid storage. @c SurfaceArray does not fill it on 0437 /// its own 0438 /// @param surfaces The input vector of surfaces. This is only for 0439 /// bookkeeping, so we can ask 0440 /// @param transform Optional additional transform for this SurfaceArray 0441 explicit SurfaceArray(std::unique_ptr<ISurfaceGridLookup> gridLookup, 0442 std::vector<std::shared_ptr<const Surface>> surfaces, 0443 const Transform3& transform = Transform3::Identity()); 0444 0445 /// @brief Constructor with a single surface 0446 /// @param srf The one and only surface 0447 explicit SurfaceArray(std::shared_ptr<const Surface> srf); 0448 0449 /// @brief Get all surfaces in bin given by position. 0450 /// @param position the lookup position 0451 /// @return reference to @c SurfaceVector contained in bin at that position 0452 SurfaceVector& at(const Vector3& position) { 0453 return p_gridLookup->lookup(position); 0454 } 0455 0456 /// @brief Get all surfaces in bin given by position @p pos. 0457 /// @param position the lookup position 0458 /// @return const reference to @c SurfaceVector contained in bin at that 0459 /// position 0460 const SurfaceVector& at(const Vector3& position) const { 0461 return p_gridLookup->lookup(position); 0462 } 0463 0464 /// @brief Get all surfaces in bin given by global bin index @p bin. 0465 /// @param bin the global bin index 0466 /// @return reference to @c SurfaceVector contained in bin 0467 SurfaceVector& at(std::size_t bin) { return p_gridLookup->lookup(bin); } 0468 0469 /// @brief Get all surfaces in bin given by global bin index. 0470 /// @param bin the global bin index 0471 /// @return const reference to @c SurfaceVector contained in bin 0472 const SurfaceVector& at(std::size_t bin) const { 0473 return p_gridLookup->lookup(bin); 0474 } 0475 0476 /// @brief Get all surfaces in bin at @p pos and its neighbors 0477 /// @param position The position to lookup as nominal 0478 /// @return Merged @c SurfaceVector of neighbors and nominal 0479 /// @note The @c SurfaceVector will be combined. For technical reasons, the 0480 /// different bin content vectors have to be copied, so the resulting 0481 /// vector contains copies. 0482 const SurfaceVector& neighbors(const Vector3& position) const { 0483 return p_gridLookup->neighbors(position); 0484 } 0485 0486 /// @brief Get the size of the underlying grid structure including 0487 /// under/overflow bins 0488 /// @return the size 0489 std::size_t size() const { return p_gridLookup->size(); } 0490 0491 /// @brief Get the center of the bin identified by global bin index @p bin 0492 /// @param bin the global bin index 0493 /// @return Center position of the bin in global coordinates 0494 Vector3 getBinCenter(std::size_t bin) { 0495 return p_gridLookup->getBinCenter(bin); 0496 } 0497 0498 /// @brief Get all surfaces attached to this @c SurfaceArray 0499 /// @return Reference to @c SurfaceVector containing all surfaces 0500 /// @note This does not reflect the actual state of the grid. It only 0501 /// returns what was given in the constructor, without any checks 0502 /// if that is actually what's in the grid. 0503 const SurfaceVector& surfaces() const { return m_surfacesRawPointers; } 0504 0505 /// @brief Get vector of axes spanning the grid as @c AnyAxis 0506 /// @return vector of @c AnyAxis 0507 /// @note The axes in the vector are copies. Only use for introspection and 0508 /// querying. 0509 std::vector<const IAxis*> getAxes() const { return p_gridLookup->getAxes(); } 0510 0511 /// @brief Checks if global bin is valid 0512 /// @param bin the global bin index 0513 /// @return bool if the bin is valid 0514 /// @note Valid means that the index points to a bin which is not a under 0515 /// or overflow bin or out of range in any axis. 0516 bool isValidBin(std::size_t bin) const { 0517 return p_gridLookup->isValidBin(bin); 0518 } 0519 0520 const Transform3& transform() const { return m_transform; } 0521 0522 /// @brief The binning values described by this surface grid lookup 0523 /// They are in order of the axes 0524 std::vector<AxisDirection> binningValues() const { 0525 return p_gridLookup->binningValues(); 0526 }; 0527 0528 /// @brief String representation of this @c SurfaceArray 0529 /// @param gctx The current geometry context object, e.g. alignment 0530 /// @param sl Output stream to write to 0531 /// @return the output stream given as @p sl 0532 std::ostream& toStream(const GeometryContext& gctx, std::ostream& sl) const; 0533 0534 private: 0535 std::unique_ptr<ISurfaceGridLookup> p_gridLookup; 0536 // this vector makes sure we have shared ownership over the surfaces 0537 std::vector<std::shared_ptr<const Surface>> m_surfaces; 0538 // this vector is returned, so that (expensive) copying of the shared_ptr 0539 // vector does not happen by default 0540 SurfaceVector m_surfacesRawPointers; 0541 // this is only used to keep info on transform applied 0542 // by l2g and g2l 0543 Transform3 m_transform; 0544 }; 0545 0546 } // namespace Acts
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |