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