|
|
|||
File indexing completed on 2026-11-06 09:25:01
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/Tolerance.hpp" 0012 #include "Acts/Geometry/PortalError.hpp" 0013 #include "Acts/Geometry/PortalLinkBase.hpp" 0014 #include "Acts/Geometry/TrackingVolume.hpp" 0015 #include "Acts/Surfaces/CylinderSurface.hpp" 0016 #include "Acts/Surfaces/DiscSurface.hpp" 0017 #include "Acts/Surfaces/PlaneSurface.hpp" 0018 #include "Acts/Utilities/AxisDefinitions.hpp" 0019 #include "Acts/Utilities/Grid.hpp" 0020 #include "Acts/Utilities/Logger.hpp" 0021 #include "Acts/Utilities/ThrowAssert.hpp" 0022 0023 #include <iosfwd> 0024 0025 namespace Acts { 0026 0027 class IGrid; 0028 class TrivialPortalLink; 0029 0030 template <typename... Axes> 0031 requires(sizeof...(Axes) <= 2) 0032 class GridPortalLinkT; 0033 0034 /// GridPortalLink implements a subdivided surface where the target volume 0035 /// depends on the position on the surface. The link can be in two states: 0036 /// 1. One-dimensional binning with an associated *direction* to determine which 0037 /// local coordinate to use for the lookup 0038 /// 2. Two-dimensional binning 0039 /// @note The grid dimensions and boundaries are **required** (and checked) to be 0040 /// consistent with the surface bounds. 0041 class GridPortalLink : public PortalLinkBase { 0042 protected: 0043 /// Constructor from a surface and a direction, for initialization by derived 0044 /// class 0045 /// @param surface The surface 0046 /// @param direction The binning direction 0047 GridPortalLink(std::shared_ptr<RegularSurface> surface, 0048 AxisDirection direction); 0049 0050 public: 0051 /// Override the destructor so we can get away with forward declaration of 0052 /// `TrivialPortalLink` 0053 ~GridPortalLink() override; 0054 0055 /// Factory function for a one-dimensional grid portal link, which allows 0056 /// using template deduction to figure out the right type 0057 /// @tparam axis_t The axis type 0058 /// @param surface The surface 0059 /// @param direction The binning direction 0060 /// @param axis The axis to use for the binning 0061 /// @note The axis boundaries are checked against the bounds of @p surface. 0062 /// @return A unique pointer to the grid portal link 0063 template <AxisConcept axis_t> 0064 static std::unique_ptr<GridPortalLinkT<axis_t>> make( 0065 const std::shared_ptr<RegularSurface>& surface, AxisDirection direction, 0066 axis_t&& axis) { 0067 using enum AxisDirection; 0068 if (dynamic_cast<const CylinderSurface*>(surface.get()) != nullptr) { 0069 if (direction != AxisZ && direction != AxisRPhi) { 0070 throw std::invalid_argument{"Invalid binning direction"}; 0071 } 0072 } else if (dynamic_cast<const DiscSurface*>(surface.get()) != nullptr && 0073 direction != AxisR && direction != AxisPhi) { 0074 throw std::invalid_argument{"Invalid binning direction"}; 0075 } else if (dynamic_cast<const PlaneSurface*>(surface.get()) != nullptr && 0076 direction != AxisX && direction != AxisY) { 0077 throw std::invalid_argument{"Invalid binning direction"}; 0078 } 0079 0080 return std::make_unique<GridPortalLinkT<axis_t>>( 0081 surface, direction, std::forward<axis_t>(axis)); 0082 } 0083 0084 /// Factory function for a two-dimensional grid portal link, which allows 0085 /// using template deduction to figure out the right type. 0086 /// @tparam axis_1_t The first axis type 0087 /// @tparam axis_2_t The second axis type 0088 /// @param surface The surface 0089 /// @param axis1 The first axis to use for the binning 0090 /// @param axis2 The second axis to use for the binning 0091 /// @note The axis boundaries are checked against the bounds of @p surface. 0092 /// @return A unique pointer to the grid portal link 0093 template <AxisConcept axis_1_t, AxisConcept axis_2_t> 0094 static std::unique_ptr<GridPortalLinkT<axis_1_t, axis_2_t>> make( 0095 const std::shared_ptr<RegularSurface>& surface, axis_1_t axis1, 0096 axis_2_t axis2) { 0097 std::optional<AxisDirection> direction; 0098 if (dynamic_cast<const CylinderSurface*>(surface.get()) != nullptr) { 0099 direction = AxisDirection::AxisRPhi; 0100 } else if (dynamic_cast<const DiscSurface*>(surface.get()) != nullptr) { 0101 direction = AxisDirection::AxisR; 0102 } else if (dynamic_cast<const PlaneSurface*>(surface.get()) != nullptr) { 0103 direction = AxisDirection::AxisX; 0104 } 0105 0106 return std::make_unique<GridPortalLinkT<axis_1_t, axis_2_t>>( 0107 surface, direction.value(), std::move(axis1), std::move(axis2)); 0108 } 0109 0110 /// Factory function for an automatically sized one-dimensional grid. This produces a single-bin grid with boundaries taken from the bounds of @p surface along @p direction. 0111 /// @param surface The surface 0112 /// @param volume The tracking volume 0113 /// @param direction The binning direction 0114 /// @return A unique pointer to the grid portal link 0115 static std::unique_ptr<GridPortalLink> make( 0116 const std::shared_ptr<RegularSurface>& surface, TrackingVolume& volume, 0117 AxisDirection direction); 0118 0119 /// Factory function for a one-dimensional grid portal link from a 0120 /// type-erased axis. Dispatches to the templated overload inside Core, so 0121 /// callers do not instantiate every axis type themselves. 0122 /// @param surface The surface 0123 /// @param direction The binning direction 0124 /// @param axis The axis to use for the binning 0125 /// @return A unique pointer to the grid portal link 0126 static std::unique_ptr<GridPortalLink> make( 0127 const std::shared_ptr<RegularSurface>& surface, AxisDirection direction, 0128 const IAxis& axis); 0129 0130 /// Factory function for a two-dimensional grid portal link from type-erased 0131 /// axes, see the one-dimensional overload. 0132 /// @param surface The surface 0133 /// @param axis0 The first axis to use for the binning 0134 /// @param axis1 The second axis to use for the binning 0135 /// @return A unique pointer to the grid portal link 0136 static std::unique_ptr<GridPortalLink> make( 0137 const std::shared_ptr<RegularSurface>& surface, const IAxis& axis0, 0138 const IAxis& axis1); 0139 0140 /// Merge two grid portal links into a single one. The routine can merge 0141 /// one-dimensional, two-dimensional and mixed links. The merge will try to 0142 /// preserve equidistant binning in case bin widths match. Otherwise, the 0143 /// merge falls back to variable binning. 0144 /// 0145 /// 1D merge scenarios: 0146 /// 0147 /// ``` 0148 /// +----------------------------------------------------------+ 0149 /// |Colinear | 0150 /// | | 0151 /// | +-------+-------+-------+ +-------+-------+-------+ | 0152 /// | | | | | | | | | | 0153 /// | | | | | + | | | | | 0154 /// | | | | | | | | | | 0155 /// | +-------+-------+-------+ +-------+-------+-------+ | 0156 /// | +-------+-------+-------+-------+-------+-------+ | 0157 /// | | | | | | | | | 0158 /// | = | | | | | | | | 0159 /// | | | | | | | | | 0160 /// | +-------+-------+-------+-------+-------+-------+ | 0161 /// | | 0162 /// +----------------------------------------------------------+ 0163 /// ``` 0164 /// 0165 /// Two grid along a shared direction are merged along their shared direction 0166 /// 0167 /// ``` 0168 /// +-------------------------------------------------+ 0169 /// |Parallel | 0170 /// | | 0171 /// | +-------+ +-------+ +-------+-------+ | 0172 /// | | | | | | | | | 0173 /// | | | | | | | | | 0174 /// | | | | | | | | | 0175 /// | +-------+ +-------+ +-------+-------+ | 0176 /// | | | | | | | | | 0177 /// | | | + | | = | | | | 0178 /// | | | | | | | | | 0179 /// | +-------+ +-------+ +-------+-------+ | 0180 /// | | | | | | | | | 0181 /// | | | | | | | | | 0182 /// | | | | | | | | | 0183 /// | +-------+ +-------+ +-------+-------+ | 0184 /// | | 0185 /// +-------------------------------------------------+ 0186 /// ``` 0187 /// 0188 /// Two grids along a shared direction a merged in the direction that is 0189 /// orthogonal to their shared direction. 0190 /// 0191 /// ``` 0192 /// +-------------------------------------------+ 0193 /// |Perpendicular | 0194 /// | | 0195 /// | +-------+ | 0196 /// | | | | 0197 /// | | | | 0198 /// | | | | 0199 /// | +-------+ +-------+-------+-------+ | 0200 /// | | | | | | | | 0201 /// | | | + | | | | | 0202 /// | | | | | | | | 0203 /// | +-------+ +-------+-------+-------+ | 0204 /// | | | | 0205 /// | | | | 0206 /// | | | +-------+-------+-------+ | 0207 /// | +-------+ | | | | | 0208 /// | | | | | | 0209 /// | | | | | | 0210 /// | +-------+-------+-------+ | 0211 /// | | | | | | 0212 /// | = | | | | | 0213 /// | | | | | | 0214 /// | +-------+-------+-------+ | 0215 /// | | | | | | 0216 /// | | | | | | 0217 /// | | | | | | 0218 /// | +-------+-------+-------+ | 0219 /// | | 0220 /// +-------------------------------------------+ 0221 /// ``` 0222 /// 0223 /// Two grids whose directions are not shared are merged (ordering does not 0224 /// matter here). The routine will expand one of the grids to match the 0225 /// other's binning, by subdividing the grid in the as-of-yet unbinned 0226 /// direction, while filling all bins with the original bin contents. 0227 /// Afterwards, a conventional mixed-dimension merge is performed. 0228 /// 0229 /// Mixed merge scenarios 0230 /// The order is normalized by always taking the 2D grid as the left hand 0231 /// side. The 1D grid is expanded to match the binning in the as-of-yet 0232 /// unbinned direction with the binning taken from the 2D grid. 0233 /// 0234 /// ``` 0235 /// +-----------------------------------------+ 0236 /// |2D + 1D | 0237 /// | | 0238 /// | +-------+-------+ +-------+-------+ | 0239 /// | | | | | | | | 0240 /// | | | | | | | | 0241 /// | | | | | | | | 0242 /// | +-------+-------+ +-------+-------+ | 0243 /// | | | | | | | | 0244 /// | | | | | | | | 0245 /// | | | | | | | | 0246 /// | +-------+-------+ = +-------+-------+ | 0247 /// | | | | | | | | 0248 /// | | | | | | | | 0249 /// | | | | | | | | 0250 /// | +-------+-------+ +-------+-------+ | 0251 /// | + | | | | 0252 /// | +-------+-------+ | | | | 0253 /// | | | | | | | | 0254 /// | | | | +-------+-------+ | 0255 /// | | | | | 0256 /// | +-------+-------+ | 0257 /// +-----------------------------------------+ 0258 /// ``` 0259 /// 0260 /// ``` 0261 /// +--------------------------------------------------------------+ 0262 /// |2D + 1D | 0263 /// | | 0264 /// | +-------+-------+ +-------+ +-------+-------+-------+ | 0265 /// | | | | | | | | | | | 0266 /// | | | | | | | | | | | 0267 /// | | | | | | | | | | | 0268 /// | +-------+-------+ +-------+ +-------+-------+-------+ | 0269 /// | | | | | | | | | | | 0270 /// | | | | + | | = | | | | | 0271 /// | | | | | | | | | | | 0272 /// | +-------+-------+ +-------+ +-------+-------+-------+ | 0273 /// | | | | | | | | | | | 0274 /// | | | | | | | | | | | 0275 /// | | | | | | | | | | | 0276 /// | +-------+-------+ +-------+ +-------+-------+-------+ | 0277 /// | | 0278 /// +--------------------------------------------------------------+ 0279 /// ``` 0280 /// 0281 /// 2D merges 0282 /// The grids need to already share a common axis. If that is not the case, 0283 /// the merge routine returns a `nullptr`. This can be handled by composite 0284 /// merging as a fallback if needed. 0285 /// Ordering and direction does not matter here. 0286 /// 0287 /// ``` 0288 /// +-----------------------------------------+ 0289 /// |2D + 2D | 0290 /// | | 0291 /// | +-------+-------+ +-------+-------+ | 0292 /// | | | | | | | | 0293 /// | | | | | | | | 0294 /// | | | | | | | | 0295 /// | +-------+-------+ +-------+-------+ | 0296 /// | | | | | | | | 0297 /// | | | | + | | | | 0298 /// | | | | | | | | 0299 /// | +-------+-------+ +-------+-------+ | 0300 /// | | | | | | | | 0301 /// | | | | | | | | 0302 /// | | | | | | | | 0303 /// | +-------+-------+ +-------+-------+ | 0304 /// | | 0305 /// | +-------+-------+-------+-------+ | 0306 /// | | | | | | | 0307 /// | | | | | | | 0308 /// | | | | | | | 0309 /// | +-------+-------+-------+-------+ | 0310 /// | | | | | | | 0311 /// | = | | | | | | 0312 /// | | | | | | | 0313 /// | +-------+-------+-------+-------+ | 0314 /// | | | | | | | 0315 /// | | | | | | | 0316 /// | | | | | | | 0317 /// | +-------+-------+-------+-------+ | 0318 /// | | 0319 /// +-----------------------------------------+ 0320 /// ``` 0321 /// 0322 /// @param a The first grid portal link 0323 /// @param b The second grid portal link 0324 /// @param direction The merging direction 0325 /// @param logger The logger to use for messages 0326 /// @return The merged grid portal link or nullptr if grid merging did not succeed 0327 /// @note The returned pointer can be nullptr, if the grids 0328 /// given are not mergeable, because their binnings are 0329 /// not compatible. This is not an error case, and needs 0330 /// to be handled by the caller! Invalid input is handled 0331 /// via exceptions. 0332 static std::unique_ptr<PortalLinkBase> merge( 0333 const GridPortalLink& a, const GridPortalLink& b, AxisDirection direction, 0334 const Logger& logger = getDummyLogger()); 0335 0336 /// Return the associated grid in a type-erased form 0337 /// @return The grid 0338 virtual const IGrid& grid() const = 0; 0339 0340 /// Return the associated grid in a type-erased form 0341 /// @return The grid 0342 virtual IGrid& grid() = 0; 0343 0344 /// Set the volume on all grid bins 0345 /// @param volume The volume to set 0346 virtual void setVolume(TrackingVolume* volume) = 0; 0347 0348 /// Get the number of dimensions of the grid 0349 /// @return The number of dimensions 0350 virtual unsigned int dim() const = 0; 0351 0352 /// Expand a 1D grid to a 2D one, by using the provided axis along the 0353 /// *missing* direction. 0354 /// @param other The axis to use for the missing direction, 0355 /// can be null for auto determination 0356 /// @return A unique pointer to the 2D grid portal link 0357 virtual std::unique_ptr<GridPortalLink> extendTo2d( 0358 const IAxis* other) const = 0; 0359 0360 /// The binning direction of the grid 0361 /// @note For 2D grids, this will always be the loc0 0362 /// direction, depending on the surface type. 0363 /// @return The binning direction 0364 AxisDirection direction() const { return m_direction; } 0365 0366 /// Helper function to fill the bin contents after merging. 0367 /// This called by the merging routine, and requires access to the internal 0368 /// grid state. 0369 /// @param a The first grid portal link 0370 /// @param b The second grid portal link 0371 /// @param merged The merged grid portal link 0372 /// @param direction The merging direction 0373 /// @param logger The logger to use for messages 0374 static void fillMergedGrid(const GridPortalLink& a, const GridPortalLink& b, 0375 GridPortalLink& merged, AxisDirection direction, 0376 const Logger& logger); 0377 0378 /// Helper function that prints a textual representation of the grid with the 0379 /// volume names. 0380 /// @param os The output stream 0381 void printContents(std::ostream& os) const; 0382 0383 /// Get the artifact portal links 0384 /// @return Span of artifact portal links 0385 std::span<const TrivialPortalLink> artifactPortalLinks() const; 0386 /// Set the artifact portal links 0387 /// @param links Vector of trivial portal links to set 0388 void setArtifactPortalLinks(std::vector<TrivialPortalLink> links); 0389 0390 protected: 0391 /// Helper function to check consistency for grid on a cylinder surface 0392 /// @param grid the grid to check 0393 /// @param direction The binning direction 0394 /// @param cyl The cylinder surface 0395 static void checkConsistency(const IGrid& grid, AxisDirection direction, 0396 const CylinderSurface& cyl); 0397 0398 /// Helper function to check consistency for grid on a disc surface 0399 /// @param grid the grid to check 0400 /// @param direction The binning direction 0401 /// @param disc The disc surface 0402 static void checkConsistency(const IGrid& grid, AxisDirection direction, 0403 const DiscSurface& disc); 0404 /// Helper function to check consistency for grid on a plane surface 0405 /// @param grid the grid to check 0406 /// @param direction The binning direction 0407 /// @param plane The plane surface 0408 static void checkConsistency(const IGrid& grid, AxisDirection direction, 0409 const PlaneSurface& plane); 0410 /// Expand a 1D grid to a 2D one for a cylinder surface 0411 /// @param surface The cylinder surface 0412 /// @param other The axis to use for the missing direction, 0413 /// can be null for auto determination 0414 /// @return A unique pointer to the 2D grid portal link 0415 std::unique_ptr<GridPortalLink> extendTo2dImpl( 0416 const std::shared_ptr<CylinderSurface>& surface, 0417 const IAxis* other) const; 0418 0419 /// Expand a 1D grid to a 2D one for a disc surface 0420 /// @param surface The disc surface 0421 /// @param other The axis to use for the missing direction, 0422 /// can be null for auto determination 0423 /// @return A unique pointer to the 2D grid portal link 0424 std::unique_ptr<GridPortalLink> extendTo2dImpl( 0425 const std::shared_ptr<DiscSurface>& surface, const IAxis* other) const; 0426 0427 /// Expand a 1D grid to a 2D one for a plane surface 0428 /// @param surface The plane surface 0429 /// @param other The axis to use for the missing direction, 0430 /// can be null for auto determination 0431 /// @return A unique pointer to the 2D grid portal link 0432 std::unique_ptr<GridPortalLink> extendTo2dImpl( 0433 const std::shared_ptr<PlaneSurface>& surface, const IAxis* other) const; 0434 0435 /// Helper enum to declare which local direction to fill 0436 enum class FillDirection { 0437 loc0, 0438 loc1, 0439 }; 0440 0441 /// Helper function to fill a 2D grid from a 1D grid, by extending all 0442 /// bins along the different direction. 0443 /// @param dir The direction to fill 0444 /// @param grid1d The 1D grid 0445 /// @param grid2d The 2D grid 0446 static void fillGrid1dTo2d(FillDirection dir, const GridPortalLink& grid1d, 0447 GridPortalLink& grid2d); 0448 0449 private: 0450 AxisDirection m_direction; 0451 0452 /// Stores the trivial portal links that were used to build this grid portal 0453 /// link, if any 0454 std::vector<TrivialPortalLink> m_artifactPortalLinks; 0455 }; 0456 0457 /// Concrete class deriving from @c GridPortalLink that boxes a concrete grid for lookup. 0458 /// @tparam Axes The axis types of the grid 0459 template <typename... Axes> 0460 requires(sizeof...(Axes) <= 2) 0461 class GridPortalLinkT : public GridPortalLink { 0462 public: 0463 /// The internal grid type 0464 using GridType = Grid<const TrackingVolume*, Axes...>; 0465 0466 /// The dimension of the grid 0467 static constexpr std::size_t DIM = sizeof...(Axes); 0468 0469 /// Constructor from a surface, axes and direction 0470 /// @param surface The surface 0471 /// @param direction The binning direction 0472 /// @param axes The axes for the grid 0473 /// @note The axes are checked for consistency with the bounds of @p surface. 0474 /// @throws std::invalid_argument if an axis has an open boundary type 0475 GridPortalLinkT(std::shared_ptr<RegularSurface> surface, 0476 AxisDirection direction, Axes&&... axes) 0477 : GridPortalLink(std::move(surface), direction), 0478 m_grid(std::tuple{std::move(axes)...}) { 0479 using enum AxisDirection; 0480 0481 // prevent open axis from having a nullptr edge from under/overflow bins 0482 for (const IAxis* axis : m_grid.axes()) { 0483 if (axis->getBoundaryType() == AxisBoundaryType::Open) { 0484 throw std::invalid_argument( 0485 "GridPortalLink: open axis boundary type is not supported"); 0486 } 0487 } 0488 0489 if (const auto* cylinder = 0490 dynamic_cast<const CylinderSurface*>(m_surface.get())) { 0491 checkConsistency(m_grid, direction, *cylinder); 0492 0493 if (direction == AxisRPhi) { 0494 m_projection = &projection<CylinderSurface, AxisRPhi>; 0495 } else if (direction == AxisZ) { 0496 m_projection = &projection<CylinderSurface, AxisZ>; 0497 } else { 0498 throw std::invalid_argument{"Invalid binning direction"}; 0499 } 0500 0501 } else if (const auto* disc = 0502 dynamic_cast<const DiscSurface*>(m_surface.get())) { 0503 checkConsistency(m_grid, direction, *disc); 0504 0505 if (direction == AxisR) { 0506 m_projection = &projection<DiscSurface, AxisR>; 0507 } else if (direction == AxisDirection::AxisPhi) { 0508 m_projection = &projection<DiscSurface, AxisPhi>; 0509 } else { 0510 throw std::invalid_argument{"Invalid binning direction"}; 0511 } 0512 } else if (const auto* plane = 0513 dynamic_cast<const PlaneSurface*>(m_surface.get())) { 0514 checkConsistency(m_grid, direction, *plane); 0515 0516 if (direction == AxisX) { 0517 m_projection = &projection<PlaneSurface, AxisX>; 0518 } else if (direction == AxisDirection::AxisY) { 0519 m_projection = &projection<PlaneSurface, AxisY>; 0520 } else { 0521 throw std::invalid_argument{"Invalid binning direction"}; 0522 } 0523 0524 } else { 0525 throw std::logic_error{"Surface type is not supported"}; 0526 } 0527 } 0528 0529 /// Get the grid 0530 /// @return The grid 0531 const GridType& grid() const override { return m_grid; } 0532 0533 /// Get the grid 0534 /// @return The grid 0535 GridType& grid() override { return m_grid; } 0536 0537 /// Get the number of dimensions of the grid 0538 /// @return The number of dimensions 0539 unsigned int dim() const override { return DIM; } 0540 0541 /// Prints an identification to the output stream 0542 /// @param os The output stream 0543 void toStream(std::ostream& os) const override { 0544 os << "GridPortalLink<dim=" << dim() << ">"; 0545 } 0546 0547 /// Makes a 2D grid from a 1D grid by extending it using an optional axis 0548 /// @param other The axis to use for the missing direction, 0549 /// can be null for auto determination 0550 /// @return A unique pointer to the 2D grid portal link 0551 std::unique_ptr<GridPortalLink> extendTo2d( 0552 const IAxis* other) const override { 0553 if constexpr (DIM == 2) { 0554 return std::make_unique<GridPortalLinkT<Axes...>>(*this); 0555 } else { 0556 if (auto cylinder = 0557 std::dynamic_pointer_cast<CylinderSurface>(m_surface)) { 0558 return extendTo2dImpl(cylinder, other); 0559 } else if (auto disc = 0560 std::dynamic_pointer_cast<DiscSurface>(m_surface)) { 0561 return extendTo2dImpl(disc, other); 0562 } else if (auto plane = 0563 std::dynamic_pointer_cast<PlaneSurface>(m_surface)) { 0564 return extendTo2dImpl(plane, other); 0565 } else { 0566 throw std::logic_error{ 0567 "Surface type is not supported (this should not happen)"}; 0568 } 0569 } 0570 } 0571 0572 /// Set the volume on all grid bins 0573 /// @param volume The volume to set 0574 void setVolume(TrackingVolume* volume) override { 0575 auto loc = m_grid.multiAxis().getNBins(); 0576 if constexpr (GridType::DIM == 1) { 0577 for (std::size_t i = 1; i <= loc[0]; i++) { 0578 m_grid.atLocalBins({i}) = volume; 0579 } 0580 } else { 0581 for (std::size_t i = 1; i <= loc[0]; i++) { 0582 for (std::size_t j = 1; j <= loc[1]; j++) { 0583 m_grid.atLocalBins({i, j}) = volume; 0584 } 0585 } 0586 } 0587 } 0588 0589 /// Lookup the tracking volume at a position on the surface 0590 /// @param gctx The geometry context 0591 /// @param position The local position 0592 /// @param tolerance The tolerance for the lookup 0593 /// @note The position is required to be on the associated surface 0594 /// @return The tracking volume (can be null) 0595 Result<const TrackingVolume*> resolveVolume( 0596 const GeometryContext& gctx, const Vector3& position, 0597 double tolerance = s_onSurfaceTolerance) const override { 0598 auto res = m_surface->globalToLocal(gctx, position, tolerance); 0599 if (!res.ok()) { 0600 return res.error(); 0601 } 0602 0603 const Vector2& local = *res; 0604 return resolveVolume(gctx, local, tolerance); 0605 } 0606 0607 /// Lookup the tracking volume at a position on the surface 0608 /// @param position The local position 0609 /// @param tolerance The tolerance on the surface bounds 0610 /// @note The position is required to be on the associated surface. A position 0611 /// outside the bounds by less than @p tolerance (a portal reached at 0612 /// its edge) is moved onto the bounds before the lookup. 0613 /// @return The tracking volume (can be null), or an error if the position is 0614 /// outside the bounds by more than @p tolerance 0615 Result<const TrackingVolume*> resolveVolume( 0616 const GeometryContext& /*gctx*/, const Vector2& position, 0617 double tolerance = s_onSurfaceTolerance) const override { 0618 if (surface().insideBounds(position, BoundaryTolerance::None())) { 0619 return m_grid.atPosition(m_projection(position)); 0620 } 0621 if (!surface().insideBounds( 0622 position, BoundaryTolerance::AbsoluteEuclidean(tolerance))) { 0623 return Result<const TrackingVolume*>::failure( 0624 PortalError::PositionOutsideLinkBounds); 0625 } 0626 const SurfaceBounds& bounds = surface().bounds(); 0627 const Vector2 onBounds = 0628 bounds.closestPoint(position, bounds.boundToCartesianMetric(position)); 0629 return m_grid.atPosition(m_projection(onBounds)); 0630 } 0631 0632 private: 0633 /// Helper function that's assigned to project from the 2D local position to a 0634 /// possible 1D grid. 0635 template <class surface_t, AxisDirection direction> 0636 static Vector<DIM> projection(const Vector2& position) { 0637 using enum AxisDirection; 0638 if constexpr (DIM == 2) { 0639 return position; 0640 } else { 0641 if constexpr (std::is_same_v<surface_t, CylinderSurface>) { 0642 static_assert(direction == AxisRPhi || direction == AxisZ, 0643 "Invalid binning direction"); 0644 0645 if constexpr (direction == AxisRPhi) { 0646 return Vector<1>{position[0]}; 0647 } else if constexpr (direction == AxisZ) { 0648 return Vector<1>{position[1]}; 0649 } 0650 } else if constexpr (std::is_same_v<surface_t, DiscSurface>) { 0651 static_assert(direction == AxisR || direction == AxisPhi, 0652 "Invalid binning direction"); 0653 0654 if constexpr (direction == AxisR) { 0655 return Vector<1>{position[0]}; 0656 } else if constexpr (direction == AxisPhi) { 0657 return Vector<1>{position[1]}; 0658 } 0659 } else if constexpr (std::is_same_v<surface_t, PlaneSurface>) { 0660 static_assert(direction == AxisX || direction == AxisY, 0661 "Invalid binning direction"); 0662 0663 if constexpr (direction == AxisX) { 0664 return Vector<1>{position[0]}; 0665 } else if constexpr (direction == AxisY) { 0666 return Vector<1>{position[1]}; 0667 } 0668 } 0669 } 0670 } 0671 0672 GridType m_grid; 0673 0674 /// Stores a function pointer that can project from 2D to 1D if needed 0675 Vector<DIM> (*m_projection)(const Vector2& position); 0676 }; 0677 0678 } // 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 |
|