|
||||
Warning, file /include/Acts/Surfaces/SurfaceArray.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 // This file is part of the Acts project. 0002 // 0003 // Copyright (C) 2017-2020 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 http://mozilla.org/MPL/2.0/. 0008 0009 #pragma once 0010 #include "Acts/Definitions/Algebra.hpp" 0011 #include "Acts/Geometry/GeometryContext.hpp" 0012 #include "Acts/Surfaces/Surface.hpp" 0013 #include "Acts/Utilities/BinningType.hpp" 0014 #include "Acts/Utilities/Grid.hpp" 0015 #include "Acts/Utilities/IAxis.hpp" 0016 #include "Acts/Utilities/detail/Axis.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<BinningValue> 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<BinningValue> 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 binningPosition, 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->binningPosition(gctx, binR); 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 = (binCtr - srf->binningPosition(gctx, binR)).norm(); 0198 0199 if (curPath < minPath) { 0200 minPath = curPath; 0201 minSrf = srf; 0202 } 0203 } 0204 0205 binContent.push_back(minSrf); 0206 ++binCompleted; 0207 } 0208 0209 // recreate neighborcache 0210 populateNeighborCache(); 0211 return binCompleted; 0212 } 0213 0214 /// @brief Performs lookup at @c pos and returns bin content as reference 0215 /// @param position Lookup position 0216 /// @return @c SurfaceVector at given bin 0217 SurfaceVector& lookup(const Vector3& position) override { 0218 return m_grid.atPosition(m_globalToLocal(position)); 0219 } 0220 0221 /// @brief Performs lookup at @c pos and returns bin content as const 0222 /// reference 0223 /// @param position Lookup position 0224 /// @return @c SurfaceVector at given bin 0225 const SurfaceVector& lookup(const Vector3& position) const override { 0226 return m_grid.atPosition(m_globalToLocal(position)); 0227 } 0228 0229 /// @brief Performs lookup at global bin and returns bin content as 0230 /// reference 0231 /// @param bin Global lookup bin 0232 /// @return @c SurfaceVector at given bin 0233 SurfaceVector& lookup(std::size_t bin) override { return m_grid.at(bin); } 0234 0235 /// @brief Performs lookup at global bin and returns bin content as const 0236 /// reference 0237 /// @param bin Global lookup bin 0238 /// @return @c SurfaceVector at given bin 0239 const SurfaceVector& lookup(std::size_t bin) const override { 0240 return m_grid.at(bin); 0241 } 0242 0243 /// @brief Performs a lookup at @c pos, but returns neighbors as well 0244 /// 0245 /// @param position Lookup position 0246 /// @return @c SurfaceVector at given bin. Copy of all bins selected 0247 const SurfaceVector& neighbors(const Vector3& position) const override { 0248 auto lposition = m_globalToLocal(position); 0249 return m_neighborMap.at(m_grid.globalBinFromPosition(lposition)); 0250 } 0251 0252 /// @brief Returns the total size of the grid (including under/overflow 0253 /// bins) 0254 /// @return Size of the grid data structure 0255 std::size_t size() const override { return m_grid.size(); } 0256 0257 /// @brief The binning values described by this surface grid lookup 0258 /// They are in order of the axes 0259 std::vector<BinningValue> binningValues() const override { 0260 return m_binValues; 0261 } 0262 0263 /// @brief Gets the center position of bin @c bin in global coordinates 0264 /// @param bin the global bin index 0265 /// @return The bin center 0266 Vector3 getBinCenter(std::size_t bin) const override { 0267 return getBinCenterImpl(bin); 0268 } 0269 0270 /// @brief Returns copies of the axes used in the grid as @c AnyAxis 0271 /// @return The axes 0272 /// @note This returns copies. Use for introspection and querying. 0273 std::vector<const IAxis*> getAxes() const override { 0274 auto arr = m_grid.axes(); 0275 return std::vector<const IAxis*>(arr.begin(), arr.end()); 0276 } 0277 0278 /// @brief Get the number of dimensions of the grid. 0279 /// @return number of dimensions 0280 std::size_t dimensions() const override { return DIM; } 0281 0282 /// @brief Checks if global bin is valid 0283 /// @param bin the global bin index 0284 /// @return bool if the bin is valid 0285 /// @note Valid means that the index points to a bin which is not a under 0286 /// or overflow bin or out of range in any axis. 0287 bool isValidBin(std::size_t bin) const override { 0288 std::array<std::size_t, DIM> indices = m_grid.localBinsFromGlobalBin(bin); 0289 std::array<std::size_t, DIM> nBins = m_grid.numLocalBins(); 0290 for (std::size_t i = 0; i < indices.size(); ++i) { 0291 std::size_t idx = indices.at(i); 0292 if (idx <= 0 || idx >= nBins.at(i) + 1) { 0293 return false; 0294 } 0295 } 0296 0297 return true; 0298 } 0299 0300 private: 0301 void populateNeighborCache() { 0302 // calculate neighbors for every bin and store in map 0303 for (std::size_t i = 0; i < m_grid.size(); i++) { 0304 if (!isValidBin(i)) { 0305 continue; 0306 } 0307 typename Grid_t::index_t loc = m_grid.localBinsFromGlobalBin(i); 0308 auto neighborIdxs = m_grid.neighborHoodIndices(loc, 1u); 0309 std::vector<const Surface*>& neighbors = m_neighborMap.at(i); 0310 neighbors.clear(); 0311 0312 for (const auto idx : neighborIdxs) { 0313 const std::vector<const Surface*>& binContent = m_grid.at(idx); 0314 std::copy(binContent.begin(), binContent.end(), 0315 std::back_inserter(neighbors)); 0316 } 0317 } 0318 } 0319 0320 /// Internal method. 0321 /// This is here, because apparently Eigen doesn't like Vector1. 0322 /// So SurfaceGridLookup internally uses std::array<double, 1> instead 0323 /// of Vector1 (see the point_t typedef). This needs to be switched here, 0324 /// so as not to 0325 /// attempt an initialization of Vector1 that Eigen will complain about. 0326 /// The SFINAE is hidden in this private method so the public 0327 /// interface stays the same, since we don't care what happens 0328 /// here on the callers end 0329 /// This is the version for DIM>1 0330 template <std::size_t D = DIM, std::enable_if_t<D != 1, int> = 0> 0331 Vector3 getBinCenterImpl(std::size_t bin) const { 0332 return m_localToGlobal(ActsVector<DIM>( 0333 m_grid.binCenter(m_grid.localBinsFromGlobalBin(bin)).data())); 0334 } 0335 0336 /// Internal method, see above. 0337 /// This is the version for DIM==1 0338 template <std::size_t D = DIM, std::enable_if_t<D == 1, int> = 0> 0339 Vector3 getBinCenterImpl(std::size_t bin) const { 0340 point_t pos = m_grid.binCenter(m_grid.localBinsFromGlobalBin(bin)); 0341 return m_localToGlobal(pos); 0342 } 0343 0344 std::function<point_t(const Vector3&)> m_globalToLocal; 0345 std::function<Vector3(const point_t&)> m_localToGlobal; 0346 Grid_t m_grid; 0347 std::vector<BinningValue> m_binValues; 0348 std::vector<SurfaceVector> m_neighborMap; 0349 }; 0350 0351 /// @brief Lookup implementation which wraps one element and always returns 0352 /// this element when lookup is called 0353 struct SingleElementLookup : ISurfaceGridLookup { 0354 /// @brief Default constructor. 0355 /// @param element the one and only element. 0356 SingleElementLookup(SurfaceVector::value_type element) 0357 : m_element({element}) {} 0358 0359 /// @brief Default constructor. 0360 /// @param elements the surfaces that are provided through a single lookup 0361 SingleElementLookup(const SurfaceVector& elements) : m_element(elements) {} 0362 0363 /// @brief Lookup, always returns @c element 0364 /// @return reference to vector containing only @c element 0365 SurfaceVector& lookup(const Vector3& /*position*/) override { 0366 return m_element; 0367 } 0368 0369 /// @brief Lookup, always returns @c element 0370 /// @return reference to vector containing only @c element 0371 const SurfaceVector& lookup(const Vector3& /*position*/) const override { 0372 return m_element; 0373 } 0374 0375 /// @brief Lookup, always returns @c element 0376 /// @return reference to vector containing only @c element 0377 SurfaceVector& lookup(std::size_t /*bin*/) override { return m_element; } 0378 0379 /// @brief Lookup, always returns @c element 0380 /// @return reference to vector containing only @c element 0381 const SurfaceVector& lookup(std::size_t /*bin*/) const override { 0382 return m_element; 0383 } 0384 0385 /// @brief Lookup, always returns @c element 0386 /// @return reference to vector containing only @c element 0387 const SurfaceVector& neighbors(const Vector3& /*position*/) const override { 0388 return m_element; 0389 } 0390 0391 /// @brief returns 1 0392 /// @return 1 0393 std::size_t size() const override { return 1; } 0394 0395 /// @brief Gets the bin center, but always returns (0, 0, 0) 0396 /// @return (0, 0, 0) 0397 Vector3 getBinCenter(std::size_t /*bin*/) const override { 0398 return Vector3(0, 0, 0); 0399 } 0400 0401 /// @brief Returns an empty vector of @c AnyAxis 0402 /// @return empty vector 0403 std::vector<const IAxis*> getAxes() const override { return {}; } 0404 0405 /// @brief Get the number of dimensions 0406 /// @return always 0 0407 std::size_t dimensions() const override { return 0; } 0408 0409 /// @brief Comply with concept and provide fill method 0410 /// @note Does nothing 0411 void fill(const GeometryContext& /*gctx*/, 0412 const SurfaceVector& /*surfaces*/) override {} 0413 0414 /// @brief Comply with concept and provide completeBinning method 0415 /// @note Does nothing 0416 std::size_t completeBinning(const GeometryContext& /*gctx*/, 0417 const SurfaceVector& /*surfaces*/) override { 0418 return 0; 0419 } 0420 0421 /// @brief Returns if the bin is valid (it is) 0422 /// @return always true 0423 bool isValidBin(std::size_t /*bin*/) const override { return true; } 0424 0425 private: 0426 SurfaceVector m_element; 0427 }; 0428 0429 /// @brief Default constructor which takes a @c SurfaceLookup and a vector of 0430 /// surfaces 0431 /// @param gridLookup The grid storage. @c SurfaceArray does not fill it on 0432 /// its own 0433 /// @param surfaces The input vector of surfaces. This is only for 0434 /// bookkeeping, so we can ask 0435 /// @param transform Optional additional transform for this SurfaceArray 0436 SurfaceArray(std::unique_ptr<ISurfaceGridLookup> gridLookup, 0437 std::vector<std::shared_ptr<const Surface>> surfaces, 0438 const Transform3& transform = Transform3::Identity()); 0439 0440 /// @brief Constructor with a single surface 0441 /// @param srf The one and only surface 0442 SurfaceArray(std::shared_ptr<const Surface> srf); 0443 0444 /// @brief Get all surfaces in bin given by position. 0445 /// @param position the lookup position 0446 /// @return reference to @c SurfaceVector contained in bin at that position 0447 SurfaceVector& at(const Vector3& position) { 0448 return p_gridLookup->lookup(position); 0449 } 0450 0451 /// @brief Get all surfaces in bin given by position @p pos. 0452 /// @param position the lookup position 0453 /// @return const reference to @c SurfaceVector contained in bin at that 0454 /// position 0455 const SurfaceVector& at(const Vector3& position) const { 0456 return p_gridLookup->lookup(position); 0457 } 0458 0459 /// @brief Get all surfaces in bin given by global bin index @p bin. 0460 /// @param bin the global bin index 0461 /// @return reference to @c SurfaceVector contained in bin 0462 SurfaceVector& at(std::size_t bin) { return p_gridLookup->lookup(bin); } 0463 0464 /// @brief Get all surfaces in bin given by global bin index. 0465 /// @param bin the global bin index 0466 /// @return const reference to @c SurfaceVector contained in bin 0467 const SurfaceVector& at(std::size_t bin) const { 0468 return p_gridLookup->lookup(bin); 0469 } 0470 0471 /// @brief Get all surfaces in bin at @p pos and its neighbors 0472 /// @param position The position to lookup as nominal 0473 /// @return Merged @c SurfaceVector of neighbors and nominal 0474 /// @note The @c SurfaceVector will be combined. For technical reasons, the 0475 /// different bin content vectors have to be copied, so the resulting 0476 /// vector contains copies. 0477 const SurfaceVector& neighbors(const Vector3& position) const { 0478 return p_gridLookup->neighbors(position); 0479 } 0480 0481 /// @brief Get the size of the underlying grid structure including 0482 /// under/overflow bins 0483 /// @return the size 0484 std::size_t size() const { return p_gridLookup->size(); } 0485 0486 /// @brief Get the center of the bin identified by global bin index @p bin 0487 /// @param bin the global bin index 0488 /// @return Center position of the bin in global coordinates 0489 Vector3 getBinCenter(std::size_t bin) { 0490 return p_gridLookup->getBinCenter(bin); 0491 } 0492 0493 /// @brief Get all surfaces attached to this @c SurfaceArray 0494 /// @return Reference to @c SurfaceVector containing all surfaces 0495 /// @note This does not reflect the actual state of the grid. It only 0496 /// returns what was given in the constructor, without any checks 0497 /// if that is actually what's in the grid. 0498 const SurfaceVector& surfaces() const { return m_surfacesRawPointers; } 0499 0500 /// @brief Get vector of axes spanning the grid as @c AnyAxis 0501 /// @return vector of @c AnyAxis 0502 /// @note The axes in the vector are copies. Only use for introspection and 0503 /// querying. 0504 std::vector<const IAxis*> getAxes() const { return p_gridLookup->getAxes(); } 0505 0506 /// @brief Checks if global bin is valid 0507 /// @param bin the global bin index 0508 /// @return bool if the bin is valid 0509 /// @note Valid means that the index points to a bin which is not a under 0510 /// or overflow bin or out of range in any axis. 0511 bool isValidBin(std::size_t bin) const { 0512 return p_gridLookup->isValidBin(bin); 0513 } 0514 0515 const Transform3& transform() const { return m_transform; } 0516 0517 /// @brief The binning values described by this surface grid lookup 0518 /// They are in order of the axes 0519 std::vector<BinningValue> binningValues() const { 0520 return p_gridLookup->binningValues(); 0521 }; 0522 0523 /// @brief String representation of this @c SurfaceArray 0524 /// @param gctx The current geometry context object, e.g. alignment 0525 /// @param sl Output stream to write to 0526 /// @return the output stream given as @p sl 0527 std::ostream& toStream(const GeometryContext& gctx, std::ostream& sl) const; 0528 0529 private: 0530 std::unique_ptr<ISurfaceGridLookup> p_gridLookup; 0531 // this vector makes sure we have shared ownership over the surfaces 0532 std::vector<std::shared_ptr<const Surface>> m_surfaces; 0533 // this vector is returned, so that (expensive) copying of the shared_ptr 0534 // vector does not happen by default 0535 SurfaceVector m_surfacesRawPointers; 0536 // this is only used to keep info on transform applied 0537 // by l2g and g2l 0538 Transform3 m_transform; 0539 }; 0540 0541 } // 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 |