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