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