Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:10:52

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/Direction.hpp"
0013 #include "Acts/Utilities/AxisDefinitions.hpp"
0014 #include "Acts/Utilities/Logger.hpp"
0015 #include "Acts/Utilities/Result.hpp"
0016 
0017 #include <memory>
0018 
0019 namespace Acts {
0020 
0021 class RegularSurface;
0022 class GeometryContext;
0023 class TrackingVolume;
0024 class CylinderSurface;
0025 class PlaneSurface;
0026 class DiscSurface;
0027 class Surface;
0028 
0029 class PortalLinkBase;
0030 
0031 /// Exception thrown when portals cannot be merged
0032 class PortalMergingException : public std::exception {
0033   const char* what() const noexcept override;
0034 };
0035 
0036 /// Exception thrown when portals cannot be fused
0037 class PortalFusingException : public std::exception {
0038   const char* what() const noexcept override;
0039 };
0040 
0041 /// A portal connects two or more neighboring volumes. Each volume has a set of
0042 /// portals that describes which volumes lie behind the portal in that
0043 /// direction. Portals use associated portal links to perform lookups of target
0044 /// volumes.
0045 /// Each portal has two links, and a corresponding surface. One link is
0046 /// associated with the direction along the surface's normal vector, and one
0047 /// with the opposite direction.
0048 class Portal {
0049  public:
0050   /// Constructor for a portal from a single link
0051   /// @param direction The direction of the link
0052   /// @param link The portal link
0053   Portal(Direction direction, std::unique_ptr<PortalLinkBase> link);
0054 
0055   /// Constructor for a portal from a surface and volume, where a trivial portal
0056   /// link is automatically constructed.
0057   /// @param direction The direction of the link
0058   /// @param surface The surface from which to create the portal link
0059   /// @param volume The volume this portal connects to in the @p direction
0060   ///               relative to the normal of @p surface.
0061   Portal(Direction direction, std::shared_ptr<RegularSurface> surface,
0062          TrackingVolume& volume);
0063 
0064   /// Constructor for a portal from two links. One of the links can be
0065   /// `nullptr`, but at least one of them needs to be set. If both are set, they
0066   /// need to be valid compatible links that can be fused.
0067   /// @param gctx The geometry context
0068   /// @param alongNormal The link along the normal of the surface
0069   /// @param oppositeNormal The link opposite to the normal of the
0070   Portal(const GeometryContext& gctx,
0071          std::unique_ptr<PortalLinkBase> alongNormal,
0072          std::unique_ptr<PortalLinkBase> oppositeNormal);
0073 
0074   /// Helper struct for the arguments to the portal constructor below using
0075   /// designated initializers.
0076   struct Arguments {
0077     /// Aggregate over a surface and a volume with optional semantics
0078     struct Link {
0079       Link() = default;
0080       /// Constructor from a surface and a volume
0081       Link(std::shared_ptr<RegularSurface> surfaceIn, TrackingVolume& volumeIn)
0082           : surface(std::move(surfaceIn)), volume(&volumeIn) {}
0083 
0084       /// The associated surface
0085       std::shared_ptr<RegularSurface> surface = nullptr;
0086       /// The associated volume
0087       TrackingVolume* volume = nullptr;
0088     };
0089 
0090     /// Entry for the link along normal
0091     /// Entry for the link opposite normal
0092     Link alongNormal{};
0093     Link oppositeNormal{};
0094   };
0095 
0096   /// Constructor that takes a geometry context and an rvalue reference to a
0097   /// helper struct from above. This pattern allows you to use designated
0098   /// initializers to construct this object like:
0099   /// ```cpp
0100   /// Portal{gctx, {.oppositeNormal = {cyl1, *vol1}}};
0101   /// Portal{gctx, {.alongNormal = {cyl2, *vol2}}};
0102   /// ```
0103   /// @param gctx The geometry context
0104   /// @param args The struct containing the arguments
0105   Portal(const GeometryContext& gctx, Arguments&& args);
0106 
0107   /// Fuse two portals together. Fusing is the combination of two portal links
0108   /// on the same logical surfaces. The actual surface instances can be
0109   /// different, as long as they are geometrically equivalent (within numerical
0110   /// precision). The resulting portal will have one portal along the shared
0111   /// surface's normal vector, and one opposite that vector.
0112   ///
0113   /// ```
0114   ///    portal1   portal2
0115   ///      +---+   +---+
0116   ///      |   |   |   |
0117   ///      |   |   |   |
0118   /// <----+   | + |   +---->
0119   ///      |   |   |   |
0120   ///      |   |   |   |
0121   ///      +---+   +---+
0122   /// ```
0123   ///
0124   /// @note The input portals need to have compatible link loadaout, e.g. one
0125   ///       portal needs to have the *along normal* slot filled, and the
0126   ///       otherone one needs to have the *opposite normal* slot filled. If
0127   ///       portals share a filled slot, the function throws an exception.
0128   /// @note This is a destructive operation on the portals involved
0129   /// @param gctx The geometry context
0130   /// @param aPortal The first portal
0131   /// @param bPortal The second portal
0132   /// @param logger The logger to push output to
0133   static Portal fuse(const GeometryContext& gctx, Portal& aPortal,
0134                      Portal& bPortal, const Logger& logger = getDummyLogger());
0135 
0136   /// Merge two adjacent portals with each other to produce a new portal that
0137   /// encompasses both inputs. It is the complementary operation to the fusing
0138   /// of portals. To be able to merge portals, the surfaces of their associated
0139   /// links need to be *mergeable*, and the portal links need to be compatible.
0140   /// This means that both portals need to have a link along the portal surface
0141   /// normal, opposite the normal, or both. If the equipped links are opposite
0142   /// relative to one another (e.g. one along one opposite), the function will
0143   /// throw an exception.
0144   ///
0145   /// ```
0146   ///         ^                     ^
0147   ///         |                     |
0148   ///  portal1|              portal2|
0149   /// +-------+-------+     +-------+-------+
0150   /// |               |  +  |               |
0151   /// +-------+-------+     +-------+-------+
0152   ///         |                     |
0153   ///         |                     |
0154   ///         v                     v
0155   /// ```
0156   ///
0157   /// @note This is a destructive operation on both portals, their
0158   ///       links will be moved to produce merged links, which can fail
0159   ///       if the portal links are not compatible
0160   /// @param gctx The geometry context
0161   /// @param aPortal The first portal
0162   /// @param bPortal The second portal
0163   /// @param direction The direction of the merge (e.g. along z)
0164   /// @param logger The logger to push output to
0165   static Portal merge(const GeometryContext& gctx, Portal& aPortal,
0166                       Portal& bPortal, AxisDirection direction,
0167                       const Logger& logger = getDummyLogger());
0168 
0169   /// Resolve the volume for a 3D position and a direction
0170   /// The @p direction is used to select the right portal link, if it is set.
0171   /// In case no link is found in the specified direction, a `nullptr` is
0172   /// returned.
0173   /// @param gctx The geometry context
0174   /// @param position The 3D position
0175   /// @param direction The direction
0176   /// @return The target volume (can be `nullptr`)
0177   Result<const TrackingVolume*> resolveVolume(const GeometryContext& gctx,
0178                                               const Vector3& position,
0179                                               const Vector3& direction) const;
0180 
0181   /// Set a link on the portal into the slot specified by the direction.
0182   /// @note The surface associated with @p link must be logically equivalent
0183   ///       to the one of the link that's already set on the portal.
0184   /// @param gctx The geometry context
0185   /// @param direction The direction
0186   /// @param link The link to set
0187   void setLink(const GeometryContext& gctx, Direction direction,
0188                std::unique_ptr<PortalLinkBase> link);
0189 
0190   /// Helper function create a trivial portal link based on a surface.
0191   /// @param gctx The geometry context
0192   /// @param direction The direction of the link to create
0193   /// @param surface The surface
0194   /// @note The @p surface must be logically equivalent
0195   ///       to the one of the link that's already set on the portal.
0196   /// @param volume The target volume
0197   void setLink(const GeometryContext& gctx, Direction direction,
0198                std::shared_ptr<RegularSurface> surface, TrackingVolume& volume);
0199 
0200   /// Get the link associated with the @p direction. Can be null if the associated link is unset.
0201   /// @param direction The direction
0202   /// @return The link (can be null)
0203   const PortalLinkBase* getLink(Direction direction) const;
0204 
0205   /// Returns true if the portal is valid, that means it has at least one
0206   /// non-null link associated.Portals can be in an invalid state after they get
0207   /// merged or fused with other portals.
0208   /// @return True if the portal is valid
0209   bool isValid() const;
0210 
0211   /// Create and attach a trivial portal link to the empty slot of this portal
0212   /// @param volume The target volume to connect to
0213   void fill(TrackingVolume& volume);
0214 
0215   /// Access the portal surface that is shared between the two links
0216   /// @return The portal surface
0217   const RegularSurface& surface() const;
0218 
0219   /// Access the portal surface that is shared between the two links
0220   /// @return The portal surface
0221   RegularSurface& surface();
0222 
0223  private:
0224   /// Helper to check surface equivalence without checking material status. This
0225   /// is needed because we allow fusing portals with surfaces that are
0226   /// equivalent but one of them has material while the other does not. The
0227   /// normal surface comparison would determine these surfaces as not
0228   /// equivalent.
0229   /// @param gctx The geometry context
0230   /// @param a The first surface
0231   /// @param b The second surface
0232   /// @return True if the surfaces are equivalent
0233   static bool isSameSurface(const GeometryContext& gctx, const Surface& a,
0234                             const Surface& b);
0235 
0236   std::shared_ptr<RegularSurface> m_surface;
0237 
0238   std::unique_ptr<PortalLinkBase> m_alongNormal;
0239   std::unique_ptr<PortalLinkBase> m_oppositeNormal;
0240 };
0241 
0242 }  // namespace Acts