![]() |
|
|||
File indexing completed on 2025-07-14 08:25:11
0001 // This file is part of the Acts project. 0002 // 0003 // Copyright (C) 2022 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 0011 #include "Acts/Definitions/Algebra.hpp" 0012 #include "Acts/Definitions/Common.hpp" 0013 #include "Acts/Detector/Portal.hpp" 0014 #include "Acts/Navigation/NavigationDelegates.hpp" 0015 #include "Acts/Navigation/NavigationState.hpp" 0016 #include "Acts/Surfaces/Surface.hpp" 0017 #include "Acts/Utilities/BinningType.hpp" 0018 #include "Acts/Utilities/Enumerate.hpp" 0019 #include "Acts/Utilities/GridAccessHelpers.hpp" 0020 #include "Acts/Utilities/IAxis.hpp" 0021 #include "Acts/Utilities/VectorHelpers.hpp" 0022 0023 #include <array> 0024 #include <memory> 0025 0026 namespace Acts::Experimental { 0027 0028 /// Helper method to update the candidates (portals/surfaces), 0029 /// this can be called for initial surface/portal estimation, 0030 /// but also during the navigation to update the current list 0031 /// of candidates. 0032 /// 0033 /// @param gctx is the Geometry context of this call 0034 /// @param nState [in,out] is the navigation state to be updated 0035 /// 0036 /// @todo for surfaces skip the non-reached ones, while keep for portals 0037 inline void intitializeCandidates(const GeometryContext& gctx, 0038 NavigationState& nState) { 0039 const auto& position = nState.position; 0040 const auto& direction = nState.direction; 0041 0042 nState.surfaceCandidateIndex = 0; 0043 0044 NavigationState::SurfaceCandidates confirmedCandidates; 0045 confirmedCandidates.reserve(nState.surfaceCandidates.size()); 0046 0047 for (auto& sc : nState.surfaceCandidates) { 0048 // Get the surface representation: either native surface of portal 0049 const Surface& surface = 0050 sc.surface != nullptr ? *sc.surface : sc.portal->surface(); 0051 // Only allow overstepping if it's not a portal 0052 ActsScalar overstepTolerance = 0053 sc.portal != nullptr ? s_onSurfaceTolerance : nState.overstepTolerance; 0054 // Boundary tolerance is forced to 0 for portals 0055 BoundaryTolerance boundaryTolerance = 0056 sc.portal != nullptr ? BoundaryTolerance::None() : sc.boundaryTolerance; 0057 // Check the surface intersection 0058 auto sIntersection = surface.intersect( 0059 gctx, position, direction, boundaryTolerance, s_onSurfaceTolerance); 0060 for (auto& si : sIntersection.split()) { 0061 if (si.isValid() && si.pathLength() > overstepTolerance) { 0062 confirmedCandidates.emplace_back(NavigationState::SurfaceCandidate{ 0063 si, sc.surface, sc.portal, boundaryTolerance}); 0064 } 0065 } 0066 } 0067 0068 std::sort(confirmedCandidates.begin(), confirmedCandidates.end(), 0069 [&](const auto& a, const auto& b) { 0070 return a.objectIntersection.pathLength() < 0071 b.objectIntersection.pathLength(); 0072 }); 0073 0074 nState.surfaceCandidates = std::move(confirmedCandidates); 0075 nState.surfaceCandidateIndex = 0; 0076 } 0077 0078 /// @brief This sets a single object, e.g. single surface or single volume 0079 /// into the navigation state 0080 /// 0081 /// @tparam navigation_type distinguishes between internal and external navigation 0082 /// @tparam object_type the type of the object to be filled 0083 /// @tparam filler_type is the helper to fill the object into nState 0084 /// 0085 template <typename navigation_type, typename object_type, typename filler_type> 0086 class SingleObjectNavigation : public navigation_type { 0087 public: 0088 /// Convenience constructor 0089 /// @param so the single object 0090 SingleObjectNavigation(const object_type* so) : m_object(so) { 0091 if (so == nullptr) { 0092 throw std::invalid_argument("SingleObjectNavigation: object is nullptr"); 0093 } 0094 } 0095 0096 /// @brief Fill the navigation state with a single object that it holds 0097 /// 0098 /// @param gctx is the Geometry context of this call 0099 /// @param nState the navigation state to which the surfaces are attached 0100 /// 0101 /// @note this is attaching objects without intersecting nor checking 0102 void fill([[maybe_unused]] const GeometryContext& gctx, 0103 NavigationState& nState) const { 0104 filler_type::fill(nState, m_object); 0105 } 0106 0107 /// @brief Update the navigation state with a single object that it holds 0108 /// 0109 /// @note it calls fill and then initializes the candidates (including intersection) 0110 /// 0111 /// @param gctx is the Geometry context of this call 0112 /// @param nState the navigation state to which the surfaces are attached 0113 /// 0114 /// @note this is attaching objects and will perform a check 0115 void update([[maybe_unused]] const GeometryContext& gctx, 0116 NavigationState& nState) const { 0117 fill(gctx, nState); 0118 // If the delegate type is of type IInternalNavigation 0119 if constexpr (std::is_base_of_v<IInternalNavigation, navigation_type>) { 0120 intitializeCandidates(gctx, nState); 0121 } 0122 } 0123 0124 /// Const Access to the object 0125 const object_type* object() const { return m_object; } 0126 0127 private: 0128 // The object to be filled in 0129 const object_type* m_object = nullptr; 0130 }; 0131 0132 /// @brief This uses stateless extractor and fillers to manipulate 0133 /// the navigation state 0134 /// 0135 /// @tparam navigation_type distinguishes between internal and external navigation 0136 /// @tparam extractor_type the helper to extract the objects from 0137 /// @tparam filler_type is the helper to fill the object into nState 0138 /// 0139 template <typename navigation_type, typename extractor_type, 0140 typename filler_type> 0141 class StaticAccessNavigation : public navigation_type { 0142 public: 0143 /// @brief fills the navigation state with extracted objects 0144 /// 0145 /// @param gctx is the Geometry context of this call 0146 /// @param nState the navigation state to which the surfaces are attached 0147 /// 0148 /// @note this is attaching objects without intersecting nor checking 0149 void fill([[maybe_unused]] const GeometryContext& gctx, 0150 NavigationState& nState) const { 0151 auto extracted = extractor_type::extract(gctx, nState); 0152 filler_type::fill(nState, extracted); 0153 } 0154 0155 /// @brief Update the navigation state with extracted objects 0156 /// 0157 /// @note it calls fill and then initializes the candidates (including intersection) 0158 /// 0159 /// @param gctx is the Geometry context of this call 0160 /// @param nState the navigation state to which the surfaces are attached 0161 /// 0162 /// @note this will perform the intersection test 0163 void update([[maybe_unused]] const GeometryContext& gctx, 0164 NavigationState& nState) const { 0165 fill(gctx, nState); 0166 // If the delegate type is of type IInternalNavigation 0167 if constexpr (std::is_base_of_v<IInternalNavigation, navigation_type>) { 0168 intitializeCandidates(gctx, nState); 0169 } 0170 } 0171 }; 0172 0173 /// @brief This is an index grid based navigation state updator, it uses 0174 /// an extractor type and a filler type to handle the navigation state 0175 /// 0176 /// @note a transform is applied `p3l = transform * p3` in order to allow 0177 /// shifted, transformed grids 0178 /// 0179 /// It can be used for volumes, surfaces at convenience 0180 /// 0181 /// @tparam navigation_type distinguishes between internal and external navigation 0182 /// @tparam grid_t is the type of the grid 0183 /// @tparam extractor_type is the helper to extract the object 0184 /// @tparam filler_type is the helper to fill the object into the nState 0185 template <typename navigation_type, typename grid_t, typename extractor_type, 0186 typename filler_type> 0187 class IndexedGridNavigation : public navigation_type { 0188 public: 0189 /// Broadcast the grid type 0190 using grid_type = grid_t; 0191 0192 /// An extractor helper to get the object(s) from the volume 0193 extractor_type extractor; 0194 0195 /// The grid where the indices are stored 0196 grid_type grid; 0197 0198 /// These are the cast parameters - copied from constructor 0199 std::array<BinningValue, grid_type::DIM> casts{}; 0200 0201 /// A transform to be applied to the position 0202 Transform3 transform = Transform3::Identity(); 0203 0204 /// @brief Constructor for a grid based surface attacher 0205 /// @param igrid the grid that is moved into this attacher 0206 /// @param icasts is the cast values array 0207 /// @param itr a transform applied to the global position 0208 IndexedGridNavigation(grid_type&& igrid, 0209 const std::array<BinningValue, grid_type::DIM>& icasts, 0210 const Transform3& itr = Transform3::Identity()) 0211 : grid(std::move(igrid)), casts(icasts), transform(itr) {} 0212 0213 IndexedGridNavigation() = delete; 0214 0215 /// @brief fill the navigation state with objects from the grid entries 0216 /// AFTER applying `p3loc = transform * p3` and casting to subsbpace 0217 /// 0218 /// @param gctx is the Geometry context of this call 0219 /// @param nState the navigation state to which the surfaces are attached 0220 /// 0221 /// @note this will only fill the state without intersecting 0222 void fill(const GeometryContext& gctx, NavigationState& nState) const { 0223 // Extract the index grid entry a 0224 const auto& entry = 0225 grid.atPosition(GridAccessHelpers::castPosition<grid_type>( 0226 transform * nState.position, casts)); 0227 auto extracted = extractor.extract(gctx, nState, entry); 0228 filler_type::fill(nState, extracted); 0229 } 0230 0231 /// @brief Update the navigation state with objects from the entries 0232 /// AFTER applying `p3loc = transform * p3` and casting to subsbpace 0233 /// 0234 /// @note it calls fill and then initializes the candidates (including intersection) 0235 /// 0236 /// @param gctx is the Geometry context of this call 0237 /// @param nState the navigation state to which the surfaces are attached 0238 /// 0239 /// @note this will perform the intersection test for internal navigation paths 0240 void update(const GeometryContext& gctx, NavigationState& nState) const { 0241 fill(gctx, nState); 0242 // If the delegate type is of type IInternalNavigation 0243 if constexpr (std::is_base_of_v<IInternalNavigation, navigation_type>) { 0244 // Update the candidates: initial update 0245 intitializeCandidates(gctx, nState); 0246 } 0247 } 0248 }; 0249 0250 /// This is a chained updated, which can either performed a chained filling, 0251 /// or a chaine update (which included intersection test) 0252 /// 0253 /// @tparam navigation_type distinguishes between internal and external navigation 0254 /// @tparam updators_t the updators that will be called in sequence 0255 /// 0256 template <typename navigation_type, typename... updators_t> 0257 class ChainedNavigation : public navigation_type { 0258 public: 0259 /// The stored updators 0260 std::tuple<updators_t...> updators; 0261 0262 /// Constructor for chained updators in a tuple, this will unroll 0263 /// the tuple and call them in sequence 0264 /// 0265 /// @param upts the updators to be called in chain 0266 ChainedNavigation(const std::tuple<updators_t...>&& upts) 0267 : updators(std::move(upts)) {} 0268 0269 /// A combined navigation state updated to fill the candidates from 0270 /// a sequence of pre-defined updators 0271 /// 0272 /// @param gctx is the Geometry context of this call 0273 /// @param nState the navigation state to which the objects are attached 0274 /// 0275 void fill(const GeometryContext& gctx, NavigationState& nState) const { 0276 // Unfold the tuple and add the attachers 0277 std::apply([&](auto&&... updator) { ((updator.fill(gctx, nState)), ...); }, 0278 updators); 0279 } 0280 0281 /// A combined navigation state to fill & update the candidatesthe candidates 0282 /// 0283 /// @param gctx is the Geometry context of this call 0284 /// @param nState the navigation state to which the objects are attached 0285 /// 0286 /// @note It will call the chained filling and then perform a single update on 0287 /// the candidates to avoid copying and multiple intersection tests 0288 void update(const GeometryContext& gctx, NavigationState& nState) const { 0289 // Unfold the tuple and add the attachers 0290 fill(gctx, nState); 0291 // Update the candidates: initial update 0292 intitializeCandidates(gctx, nState); 0293 } 0294 }; 0295 0296 } // namespace Acts::Experimental
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |