Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-14 09:39:43

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/Alignment.hpp"
0013 #include "Acts/Definitions/Tolerance.hpp"
0014 #include "Acts/Definitions/TrackParametrization.hpp"
0015 #include "Acts/Geometry/DetectorElementBase.hpp"
0016 #include "Acts/Geometry/GeometryContext.hpp"
0017 #include "Acts/Geometry/GeometryObject.hpp"
0018 #include "Acts/Geometry/Polyhedron.hpp"
0019 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0020 #include "Acts/Surfaces/SurfaceBounds.hpp"
0021 #include "Acts/Utilities/Intersection.hpp"
0022 #include "Acts/Utilities/Result.hpp"
0023 #include "Acts/Visualization/ViewConfig.hpp"
0024 
0025 #include <array>
0026 #include <memory>
0027 #include <ostream>
0028 #include <string>
0029 #include <string_view>
0030 #include <utility>
0031 
0032 namespace Acts {
0033 
0034 class DetectorElementBase;
0035 class SurfaceBounds;
0036 class ISurfaceMaterial;
0037 class Layer;
0038 class TrackingVolume;
0039 class IVisualization3D;
0040 class Surface;
0041 
0042 /// @class Surface
0043 ///
0044 /// @brief Abstract Base Class for tracking surfaces
0045 ///
0046 /// The Surface class builds the core of the Acts Tracking Geometry.
0047 /// All other geometrical objects are either extending the surface or
0048 /// are built from it.
0049 ///
0050 /// Surfaces are either owned by Detector elements or the Tracking Geometry,
0051 /// in which case they are not copied within the data model objects.
0052 ///
0053 class Surface : public virtual GeometryObject,
0054                 public std::enable_shared_from_this<Surface> {
0055  public:
0056   friend struct GeometryContextOstreamWrapper<Surface>;
0057 
0058   /// @enum SurfaceType
0059   ///
0060   /// This enumerator simplifies the persistency & calculations,
0061   /// by saving a dynamic_cast, e.g. for persistency
0062   enum SurfaceType {
0063     Cone = 0,
0064     Cylinder = 1,
0065     Disc = 2,
0066     Perigee = 3,
0067     Plane = 4,
0068     Straw = 5,
0069     Curvilinear = 6,
0070     Other = 7
0071   };
0072 
0073   /// Helper strings for screen output
0074   static constexpr std::array<std::string_view, Surface::SurfaceType::Other + 1>
0075       s_surfaceTypeNames = {"Cone",  "Cylinder", "Disc",        "Perigee",
0076                             "Plane", "Straw",    "Curvilinear", "Other"};
0077 
0078   friend std::ostream& operator<<(std::ostream& os, SurfaceType type);
0079 
0080  protected:
0081   /// Constructor with Transform3 as a shared object
0082   ///
0083   /// @param transform Transform3 positions the surface in 3D global space
0084   /// @note also acts as default constructor
0085   explicit Surface(const Transform3& transform = Transform3::Identity());
0086 
0087   /// Copy constructor
0088   ///
0089   /// @note copy construction invalidates the association
0090   /// to detector element and layer
0091   ///
0092   /// @param other Source surface for copy.
0093   Surface(const Surface& other);
0094 
0095   /// Constructor from DetectorElementBase: Element proxy
0096   ///
0097   /// @param detelement Detector element which is represented by this surface
0098   explicit Surface(const DetectorElementBase& detelement);
0099 
0100   /// Copy constructor with optional shift
0101   ///
0102   /// @note copy construction invalidates the association
0103   /// to detector element and layer
0104   ///
0105   /// @param gctx The current geometry context object, e.g. alignment
0106   /// @param other Source surface for copy
0107   /// @param shift Additional transform applied as: shift * transform
0108   Surface(const GeometryContext& gctx, const Surface& other,
0109           const Transform3& shift);
0110 
0111  public:
0112   ~Surface() noexcept override;
0113 
0114   /// Factory for producing memory managed instances of Surface.
0115   /// Will forward all parameters and will attempt to find a suitable
0116   /// constructor.
0117   /// @param args Constructor arguments to forward to surface creation
0118   /// @return Shared pointer to the created surface instance
0119   template <class T, typename... Args>
0120   static std::shared_ptr<T> makeShared(Args&&... args) {
0121     return std::shared_ptr<T>(new T(std::forward<Args>(args)...));
0122   }
0123 
0124   /// Retrieve a @c std::shared_ptr for this surface (non-const version)
0125   ///
0126   /// @note Will error if this was not created through the @c makeShared factory
0127   ///       since it needs access to the original reference. In C++14 this is
0128   ///       undefined behavior (but most likely implemented as a @c bad_weak_ptr
0129   ///       exception), in C++17 it is defined as that exception.
0130   /// @note Only call this if you need shared ownership of this object.
0131   ///
0132   /// @return The shared pointer
0133   std::shared_ptr<Surface> getSharedPtr();
0134 
0135   /// Retrieve a @c std::shared_ptr for this surface (const version)
0136   ///
0137   /// @note Will error if this was not created through the @c makeShared factory
0138   ///       since it needs access to the original reference. In C++14 this is
0139   ///       undefined behavior, but most likely implemented as a @c bad_weak_ptr
0140   ///       exception, in C++17 it is defined as that exception.
0141   /// @note Only call this if you need shared ownership of this object.
0142   ///
0143   /// @return The shared pointer
0144   std::shared_ptr<const Surface> getSharedPtr() const;
0145 
0146   /// Assignment operator
0147   /// @note copy construction invalidates the association
0148   /// to detector element and layer
0149   ///
0150   /// @param other Source surface for the assignment
0151   /// @return Reference to this surface after assignment
0152   Surface& operator=(const Surface& other);
0153 
0154   /// Comparison (equality) operator
0155   /// The strategy for comparison is
0156   /// (a) first pointer comparison
0157   /// (b) then type comparison
0158   /// (c) then bounds comparison
0159   /// (d) then transform comparison
0160   ///
0161   /// @param other source surface for the comparison
0162   /// @return True if surfaces are equal, false otherwise
0163   bool operator==(const Surface& other) const;
0164 
0165  public:
0166   /// Return method for the Surface type to avoid dynamic casts
0167   /// @return The surface type enumeration value
0168   virtual SurfaceType type() const = 0;
0169 
0170   /// Return method for the surface Transform3 by reference
0171   /// In case a detector element is associated the surface transform
0172   /// is just forwarded to the detector element in order to keep the
0173   /// (mis-)alignment cache cetrally handled
0174   ///
0175   /// @param gctx The current geometry context object, e.g. alignment
0176   ///
0177   /// @return the contextual transform
0178   virtual const Transform3& transform(const GeometryContext& gctx) const;
0179 
0180   /// Return method for the surface center
0181   /// @note the center is always recalculated in order to not keep a cache
0182   ///
0183   /// @param gctx The current geometry context object, e.g. alignment
0184   ///
0185   /// @return center position by value
0186   virtual Vector3 center(const GeometryContext& gctx) const;
0187 
0188   /// Return the surface normal at a given @p position and @p direction.
0189   /// This method is fully generic, and valid for all surface types.
0190   /// @note For some surface types, the @p direction is ignored, but
0191   ///       it is **not safe** to pass in a zero vector!
0192   /// @param gctx The current geometry context object, e.g. alignment
0193   /// @param pos The position at which to calculate the normal
0194   /// @param direction The direction at which to calculate the normal
0195   /// @return The normal vector at the given position and direction
0196   virtual Vector3 normal(const GeometryContext& gctx, const Vector3& pos,
0197                          const Vector3& direction) const = 0;
0198 
0199   /// Return method for SurfaceBounds
0200   /// @return SurfaceBounds by reference
0201   virtual const SurfaceBounds& bounds() const = 0;
0202 
0203   /// Return method for the associated Detector Element
0204   /// @return plain pointer to the DetectorElement, can be nullptr
0205   const DetectorElementBase* associatedDetectorElement() const;
0206 
0207   /// Return method for the associated Layer in which the surface is embedded
0208   /// @return Layer by plain pointer, can be nullptr
0209   const Layer* associatedLayer() const;
0210 
0211   /// Set Associated Layer
0212   /// Many surfaces can be associated to a Layer, but it might not be known yet
0213   /// during construction of the layer, this can be set afterwards
0214   ///
0215   /// @param lay the assignment Layer by reference
0216   void associateLayer(const Layer& lay);
0217 
0218   /// Return method for the associated Material to this surface
0219   /// @return SurfaceMaterial as plain pointer, can be nullptr
0220   const ISurfaceMaterial* surfaceMaterial() const;
0221 
0222   /// Return method for the shared pointer to the associated Material
0223   /// @return SurfaceMaterial as shared_pointer, can be nullptr
0224   const std::shared_ptr<const ISurfaceMaterial>& surfaceMaterialSharedPtr()
0225       const;
0226 
0227   /// Assign a detector element
0228   ///
0229   /// @param detelement Detector element which is represented by this surface
0230   void assignDetectorElement(const DetectorElementBase& detelement);
0231 
0232   /// Assign the surface material description
0233   ///
0234   /// The material is usually derived in a complicated way and loaded from
0235   /// a framework given source. As various surfaces may share the same source
0236   /// this is provided by a shared pointer
0237   ///
0238   /// @param material Material description associated to this surface
0239   void assignSurfaceMaterial(std::shared_ptr<const ISurfaceMaterial> material);
0240 
0241   /// The geometric onSurface method
0242   ///
0243   /// Geometrical check whether position is on Surface
0244   ///
0245   /// @param gctx The current geometry context object, e.g. alignment
0246   /// @param position global position to be evaludated
0247   /// @param direction global momentum direction (required for line-type surfaces)
0248   /// @param boundaryTolerance BoundaryTolerance directive for this onSurface check
0249   /// @param tolerance optional tolerance within which a point is considered on surface
0250   ///
0251   /// @return boolean indication if operation was successful
0252   bool isOnSurface(
0253       const GeometryContext& gctx, const Vector3& position,
0254       const Vector3& direction,
0255       const BoundaryTolerance& boundaryTolerance = BoundaryTolerance::None(),
0256       double tolerance = s_onSurfaceTolerance) const;
0257 
0258   /// Calculates the closest point on the boundary of the surface to a given
0259   /// point in local coordinates.
0260   /// @param lposition The local position to check
0261   /// @param metric The metric to use for the calculation
0262   /// @return The closest point on the boundary of the surface
0263   virtual Vector2 closestPointOnBoundary(const Vector2& lposition,
0264                                          const SquareMatrix2& metric) const;
0265 
0266   /// Calculates the distance to the boundary of the surface from a given point
0267   /// in local coordinates.
0268   /// @param lposition The local position to check
0269   /// @return The distance to the boundary of the surface
0270   virtual double distanceToBoundary(const Vector2& lposition) const;
0271 
0272   /// The insideBounds method for local positions
0273   ///
0274   /// @param lposition The local position to check
0275   /// @param boundaryTolerance BoundaryTolerance directive for this onSurface check
0276   /// @return boolean indication if operation was successful
0277   virtual bool insideBounds(const Vector2& lposition,
0278                             const BoundaryTolerance& boundaryTolerance =
0279                                 BoundaryTolerance::None()) const;
0280 
0281   /// Local to global transformation
0282   /// Generalized local to global transformation for the surface types. Since
0283   /// some surface types need the global momentum/direction to resolve sign
0284   /// ambiguity this is also provided
0285   ///
0286   /// @param gctx The current geometry context object, e.g. alignment
0287   /// @param lposition local 2D position in specialized surface frame
0288   /// @param direction global 3D momentum direction
0289   ///
0290   /// @return The global position by value
0291   virtual Vector3 localToGlobal(const GeometryContext& gctx,
0292                                 const Vector2& lposition,
0293                                 const Vector3& direction) const = 0;
0294 
0295   /// Global to local transformation
0296   /// Generalized global to local transformation for the surface types. Since
0297   /// some surface types need the global momentum/direction to resolve sign
0298   /// ambiguity this is also provided
0299   ///
0300   /// @param gctx The current geometry context object, e.g. alignment
0301   /// @param position global 3D position - considered to be on surface but not
0302   /// inside bounds (check is done)
0303   /// @param direction global 3D momentum direction
0304   /// @param tolerance optional tolerance within which a point is considered
0305   /// valid on surface
0306   ///
0307   /// @return a Result<Vector2> which can be !ok() if the operation fails
0308   virtual Result<Vector2> globalToLocal(
0309       const GeometryContext& gctx, const Vector3& position,
0310       const Vector3& direction,
0311       double tolerance = s_onSurfaceTolerance) const = 0;
0312 
0313   /// Return method for the reference frame
0314   /// This is the frame in which the covariance matrix is defined (specialized
0315   /// by all surfaces)
0316   ///
0317   /// @param gctx The current geometry context object, e.g. alignment
0318   /// @param position global 3D position - considered to be on surface but not
0319   /// inside bounds (check is done)
0320   /// @param direction global 3D momentum direction (optionally ignored)
0321   ///
0322   /// @return RotationMatrix3 which defines the three axes of the measurement
0323   /// frame
0324   virtual Acts::RotationMatrix3 referenceFrame(const GeometryContext& gctx,
0325                                                const Vector3& position,
0326                                                const Vector3& direction) const;
0327 
0328   /// Calculate the jacobian from local to global which the surface knows best,
0329   /// hence the calculation is done here.
0330   ///
0331   /// @note In principle, the input could also be a free parameters
0332   /// vector as it could be transformed to a bound parameters. But the transform
0333   /// might fail in case the parameters is not on surface. To avoid the check
0334   /// inside this function, it takes directly the bound parameters as input
0335   /// (then the check might be done where this function is called).
0336   ///
0337   /// @todo this mixes track parameterisation and geometry
0338   /// should move to :
0339   /// "Acts/EventData/detail/coordinate_transformations.hpp"
0340   ///
0341   /// @param gctx The current geometry context object, e.g. alignment
0342   /// @param position global 3D position
0343   /// @param direction global 3D momentum direction
0344   ///
0345   /// @return Jacobian from local to global
0346   virtual BoundToFreeMatrix boundToFreeJacobian(const GeometryContext& gctx,
0347                                                 const Vector3& position,
0348                                                 const Vector3& direction) const;
0349 
0350   /// Calculate the jacobian from global to local which the surface knows best,
0351   /// hence the calculation is done here.
0352   ///
0353   /// @note It assumes the input free parameters is on surface, hence no
0354   /// onSurface check is done inside this function.
0355   ///
0356   /// @todo this mixes track parameterisation and geometry
0357   /// should move to :
0358   /// "Acts/EventData/detail/coordinate_transformations.hpp"
0359   ///
0360   /// @param gctx The current geometry context object, e.g. alignment
0361   /// @param position global 3D position
0362   /// @param direction global 3D momentum direction
0363   ///
0364   /// @return Jacobian from global to local
0365   virtual FreeToBoundMatrix freeToBoundJacobian(const GeometryContext& gctx,
0366                                                 const Vector3& position,
0367                                                 const Vector3& direction) const;
0368 
0369   /// Calculate the derivative of path length at the geometry constraint or
0370   /// point-of-closest-approach w.r.t. free parameters. The calculation is
0371   /// identical for all surfaces where the reference frame does not depend on
0372   /// the direction
0373   ///
0374   /// @todo this mixes track parameterisation and geometry
0375   /// should move to :
0376   /// "Acts/EventData/detail/coordinate_transformations.hpp"
0377   ///
0378   /// @param gctx The current geometry context object, e.g. alignment
0379   /// @param position global 3D position
0380   /// @param direction global 3D momentum direction
0381   ///
0382   /// @return Derivative of path length w.r.t. free parameters
0383   virtual FreeToPathMatrix freeToPathDerivative(const GeometryContext& gctx,
0384                                                 const Vector3& position,
0385                                                 const Vector3& direction) const;
0386 
0387   /// Calucation of the path correction for incident
0388   ///
0389   /// @param gctx The current geometry context object, e.g. alignment
0390   /// @param position global 3D position
0391   /// @note The @p position is either ignored, or it is coerced to be on the surface,
0392   ///       depending on the surface type.
0393   /// @param direction global 3D momentum direction
0394   ///
0395   /// @return Path correction with respect to the nominal incident.
0396   virtual double pathCorrection(const GeometryContext& gctx,
0397                                 const Vector3& position,
0398                                 const Vector3& direction) const = 0;
0399 
0400   /// Straight line intersection schema from position/direction
0401   ///
0402   /// @param gctx The current geometry context object, e.g. alignment
0403   /// @param position The position to start from
0404   /// @param direction The direction at start
0405   /// @param boundaryTolerance the BoundaryTolerance
0406   /// @param tolerance the tolerance used for the intersection
0407   ///
0408   /// @return @c MultiIntersection3D intersection object
0409   virtual MultiIntersection3D intersect(
0410       const GeometryContext& gctx, const Vector3& position,
0411       const Vector3& direction,
0412       const BoundaryTolerance& boundaryTolerance =
0413           BoundaryTolerance::Infinite(),
0414       double tolerance = s_onSurfaceTolerance) const = 0;
0415 
0416   /// Helper method for printing: the returned object captures the
0417   /// surface and the geometry context and will print the surface
0418   /// @param gctx The current geometry context object, e.g. alignment
0419   /// @return The wrapper object for printing
0420   GeometryContextOstreamWrapper<Surface> toStream(
0421       const GeometryContext& gctx) const {
0422     return {*this, gctx};
0423   }
0424 
0425   /// Output into a std::string
0426   ///
0427   /// @param gctx The current geometry context object, e.g. alignment
0428   /// @return String representation of the surface
0429   std::string toString(const GeometryContext& gctx) const;
0430 
0431   /// Return properly formatted class name
0432   /// @return The surface class name as a string
0433   virtual std::string name() const = 0;
0434 
0435   /// Return a Polyhedron for surface objects
0436   ///
0437   /// @param gctx The current geometry context object, e.g. alignment
0438   /// @param quarterSegments The number of segemtns to approximate a 0.5*pi sector,
0439   /// which represents a quarter of the full circle
0440   ///
0441   /// @note In order to symmetrize the code between sectoral and closed cylinders
0442   /// in case of closed cylinders, both (-pi, pi) are given as separate vertices
0443   ///
0444   /// @note An internal surface transform can invalidate the extrema
0445   /// in the transformed space
0446   ///
0447   /// @return A list of vertices and a face/facett description of it
0448   virtual Polyhedron polyhedronRepresentation(
0449       const GeometryContext& gctx, unsigned int quarterSegments = 2u) const = 0;
0450 
0451   /// The derivative of bound track parameters w.r.t. alignment
0452   /// parameters of its reference surface (i.e. local frame origin in
0453   /// global 3D Cartesian coordinates and its rotation represented with
0454   /// extrinsic Euler angles)
0455   ///
0456   /// @param gctx The current geometry context object, e.g. alignment
0457   /// change of alignment parameters
0458   /// @param position global 3D position
0459   /// @param direction global 3D momentum direction
0460   /// @param pathDerivative is the derivative of free parameters w.r.t. path
0461   /// length
0462   ///
0463   /// @return Derivative of bound track parameters w.r.t. local frame
0464   /// alignment parameters
0465   AlignmentToBoundMatrix alignmentToBoundDerivative(
0466       const GeometryContext& gctx, const Vector3& position,
0467       const Vector3& direction, const FreeVector& pathDerivative) const;
0468 
0469   /// Calculate the derivative of path length at the geometry constraint or
0470   /// point-of-closest-approach w.r.t. alignment parameters of the surface (i.e.
0471   /// local frame origin in global 3D Cartesian coordinates and its rotation
0472   /// represented with extrinsic Euler angles)
0473   ///
0474   /// @note Re-implementation is needed for surface whose intersection with
0475   /// track is not its local xy plane, e.g. LineSurface, CylinderSurface and
0476   /// ConeSurface
0477   ///
0478   /// @param gctx The current geometry context object, e.g. alignment
0479   /// @param position global 3D position
0480   /// @param direction global 3D momentum direction
0481   ///
0482   /// @return Derivative of path length w.r.t. the alignment parameters
0483   virtual AlignmentToPathMatrix alignmentToPathDerivative(
0484       const GeometryContext& gctx, const Vector3& position,
0485       const Vector3& direction) const;
0486 
0487   /// Calculate the derivative of bound track parameters local position w.r.t.
0488   /// position in local 3D Cartesian coordinates
0489   ///
0490   /// @param gctx The current geometry context object, e.g. alignment
0491   /// @param position The position of the parameters in global
0492   ///
0493   /// @return Derivative of bound local position w.r.t. position in local 3D
0494   /// cartesian coordinates
0495   virtual ActsMatrix<2, 3> localCartesianToBoundLocalDerivative(
0496       const GeometryContext& gctx, const Vector3& position) const = 0;
0497 
0498   /// Visualize the surface for debugging and inspection
0499   /// @param helper Visualization helper for 3D rendering
0500   /// @param gctx Geometry context for coordinate transformations
0501   /// @param viewConfig Visual configuration (color, style, etc.)
0502   void visualize(IVisualization3D& helper, const GeometryContext& gctx,
0503                  const ViewConfig& viewConfig = s_viewSurface) const;
0504 
0505  protected:
0506   /// Output Method for std::ostream, to be overloaded by child classes
0507   ///
0508   /// @param gctx The current geometry context object, e.g. alignment
0509   /// @param sl is the ostream to be dumped into
0510   /// @return Reference to the output stream for chaining
0511   virtual std::ostream& toStreamImpl(const GeometryContext& gctx,
0512                                      std::ostream& sl) const;
0513 
0514   /// Transform3 definition that positions
0515   /// (translation, rotation) the surface in global space
0516   std::unique_ptr<const Transform3> m_transform{};
0517 
0518   /// Pointer to the a DetectorElementBase
0519   const DetectorElementBase* m_associatedDetElement{nullptr};
0520 
0521   /// The associated layer Layer - layer in which the Surface is be embedded,
0522   /// nullptr if not associated
0523   const Layer* m_associatedLayer{nullptr};
0524 
0525   /// The associated TrackingVolume - tracking volume in case the surface is a
0526   /// boundary surface, nullptr if not associated
0527   const TrackingVolume* m_associatedTrackingVolume{nullptr};
0528 
0529   /// Possibility to attach a material description
0530   std::shared_ptr<const ISurfaceMaterial> m_surfaceMaterial;
0531 
0532  private:
0533   /// Calculate the derivative of bound track parameters w.r.t.
0534   /// alignment parameters of its reference surface (i.e. origin in global 3D
0535   /// Cartesian coordinates and its rotation represented with extrinsic Euler
0536   /// angles) without any path correction
0537   ///
0538   /// @note This function should be used together with alignment to path
0539   /// derivative to get the full alignment to bound derivatives
0540   ///
0541   /// @param gctx The current geometry context object, e.g. alignment
0542   /// @param position global 3D position
0543   /// @param direction global 3D momentum direction
0544   ///
0545   /// @return Derivative of bound track parameters w.r.t. local frame alignment
0546   /// parameters without path correction
0547   AlignmentToBoundMatrix alignmentToBoundDerivativeWithoutCorrection(
0548       const GeometryContext& gctx, const Vector3& position,
0549       const Vector3& direction) const;
0550 };
0551 
0552 }  // namespace Acts