Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-07 09:23:07

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/Geometry/GeometryContext.hpp"
0015 #include "Acts/Geometry/Polyhedron.hpp"
0016 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0017 #include "Acts/Surfaces/CylinderBounds.hpp"
0018 #include "Acts/Surfaces/RegularSurface.hpp"
0019 #include "Acts/Surfaces/Surface.hpp"
0020 #include "Acts/Surfaces/SurfaceConcept.hpp"
0021 #include "Acts/Utilities/AxisDefinitions.hpp"
0022 #include "Acts/Utilities/Logger.hpp"
0023 #include "Acts/Utilities/Result.hpp"
0024 #include "Acts/Utilities/detail/RealQuadraticEquation.hpp"
0025 
0026 #include <memory>
0027 #include <numbers>
0028 #include <string>
0029 
0030 namespace Acts {
0031 
0032 /// @class CylinderSurface
0033 ///
0034 /// Class for a CylinderSurface in the TrackingGeometry.
0035 /// It inherits from Surface.
0036 ///
0037 /// The cylinder surface has a special role in the TrackingGeometry,
0038 /// since it builds the surfaces of all TrackingVolumes at container level
0039 /// for a cylindrical tracking geometry.
0040 ///
0041 /// @image html CylinderSurface.png
0042 
0043 class CylinderSurface : public RegularSurface {
0044   friend class Surface;
0045 
0046  protected:
0047   /// Constructor from Transform3 and CylinderBounds
0048   ///
0049   /// @param transform The transform to position the surface
0050   /// @param radius The radius of the cylinder
0051   /// @param halfz The half length in z
0052   /// @param halfphi The half opening angle
0053   /// @param avphi The phi value from which the opening angle spans (both sides)
0054   CylinderSurface(const Transform3& transform, double radius, double halfz,
0055                   double halfphi = std::numbers::pi, double avphi = 0.);
0056 
0057   /// Constructor from Transform3 and CylinderBounds arguments
0058   ///
0059   /// @param transform The transform to position the surface
0060   /// @param cbounds is a shared pointer to a cylindeer bounds object,
0061   /// it must exist (assert test)
0062   CylinderSurface(const Transform3& transform,
0063                   std::shared_ptr<const CylinderBounds> cbounds);
0064 
0065   /// Constructor from SurfacePlacementBase: Element proxy
0066   ///
0067   /// @param cbounds are the provided cylinder bounds (shared)
0068   /// @param placement Reference to the surface placement
0069   /// @note The Surface does not take any ownership over the
0070   ///       `SurfacePlacementBase` it is expected that the user
0071   ///        ensures the life-time of the `SurfacePlacementBase`
0072   ///        and that the `Surface` is actually owned by
0073   ///        the `SurfacePlacementBase` instance
0074   CylinderSurface(std::shared_ptr<const CylinderBounds> cbounds,
0075                   const SurfacePlacementBase& placement);
0076 
0077   /// Copy constructor
0078   ///
0079   /// @param other is the source cylinder for the copy
0080   CylinderSurface(const CylinderSurface& other);
0081 
0082   /// Copy constructor - with shift
0083   ///
0084   /// @param gctx The current geometry context object, e.g. alignment
0085   /// @param other is the source cone surface
0086   /// @param shift is the additional transform applied after copying
0087   CylinderSurface(const GeometryContext& gctx, const CylinderSurface& other,
0088                   const Transform3& shift);
0089 
0090  public:
0091   ~CylinderSurface() override = default;
0092 
0093   /// Assignment operator
0094   ///
0095   /// @param other is the source cylinder for the copy
0096   /// @return Reference to this CylinderSurface after assignment
0097   /// @deprecated Surface copy-assignment will be removed; copy via
0098   ///             `Surface::makeShared<CylinderSurface>(other)` instead.
0099   [[deprecated(
0100       "Surface copy-assignment is deprecated and will be removed; copy via "
0101       "Surface::makeShared<CylinderSurface>(other) instead.")]]
0102   CylinderSurface& operator=(const CylinderSurface& other);
0103 
0104   /// The binning position method - is overloaded for r-type binning
0105   ///
0106   /// @param gctx The current geometry context object, e.g. alignment
0107   /// @param aDir is the axis Direction of global binning to be done
0108   ///
0109   /// @return is the global position to be used for binning
0110   Vector3 referencePosition(const GeometryContext& gctx,
0111                             AxisDirection aDir) const final;
0112 
0113   /// Return the measurement frame - this is needed for alignment, in particular
0114   /// The measurement frame of a cylinder is the tangential plane at a given
0115   /// position
0116   ///
0117   /// @param gctx The current geometry context object, e.g. alignment
0118   /// @param position is the position where the measurement frame is defined
0119   /// @param direction is the momentum direction vector (ignored)
0120   /// @return rotation matrix that defines the measurement frame
0121   RotationMatrix3 referenceFrame(const GeometryContext& gctx,
0122                                  const Vector3& position,
0123                                  const Vector3& direction) const final;
0124 
0125   /// Return the surface type
0126   /// @return Surface type identifier
0127   SurfaceType type() const override;
0128 
0129   /// Return method for surface normal information
0130   /// @note for a Cylinder a local position is always required for the normal
0131   /// vector
0132   ///
0133   /// @param gctx The current geometry context object, e.g. alignment
0134   /// @param lposition is the local position for which the normal vector is
0135   /// requested
0136   ///
0137   /// @return normal vector at the local position by value
0138   Vector3 normal(const GeometryContext& gctx,
0139                  const Vector2& lposition) const final;
0140 
0141   /// Return method for surface normal information
0142   /// @note for a Cylinder a local position is always required for the normal
0143   /// vector
0144   ///
0145   /// @param gctx The current geometry context object, e.g. alignment
0146   /// @param position is the global position for which the normal vector is
0147   /// requested
0148   ///
0149   /// @return normal vector at the global position by value
0150   Vector3 normal(const GeometryContext& gctx,
0151                  const Vector3& position) const final;
0152 
0153   // Use overloads from `RegularSurface`
0154   using RegularSurface::globalToLocal;
0155   using RegularSurface::localToGlobal;
0156   using RegularSurface::normal;
0157 
0158   /// Return method for the rotational symmetry axis
0159   ///
0160   /// @param gctx The current geometry context object, e.g. alignment
0161   ///
0162   /// @return  the z-Axis of transform
0163   virtual Vector3 rotSymmetryAxis(const GeometryContext& gctx) const;
0164 
0165   /// This method returns the CylinderBounds by reference
0166   /// @return Reference to the cylinder bounds
0167   const CylinderBounds& bounds() const final;
0168 
0169   /// This method returns the shared_ptr to the CylinderBounds
0170   /// @return Shared pointer to the cylinder bounds
0171   const std::shared_ptr<const CylinderBounds>& boundsPtr() const;
0172 
0173   /// Overwrite the existing surface bounds with new ones
0174   /// @param newBounds: Pointer to the new bounds
0175   void assignSurfaceBounds(std::shared_ptr<const CylinderBounds> newBounds);
0176 
0177   /// Local to global transformation
0178   ///
0179   /// @param gctx The current geometry context object, e.g. alignment
0180   /// @param lposition is the local position to be transformed
0181   ///
0182   /// @return The global position by value
0183   Vector3 localToGlobal(const GeometryContext& gctx,
0184                         const Vector2& lposition) const final;
0185 
0186   /// Global to local transformation
0187   ///
0188   /// @param gctx The current geometry context object, e.g. alignment
0189   /// @param position is the global position to be transformed
0190   /// @param tolerance optional tolerance within which a point is considered
0191   /// valid on surface
0192   ///
0193   /// @return a Result<Vector2> which can be !ok() if the operation fails
0194   Result<Vector2> globalToLocal(
0195       const GeometryContext& gctx, const Vector3& position,
0196       double tolerance = s_onSurfaceTolerance) const final;
0197 
0198   /// Straight line intersection schema from position/direction
0199   ///
0200   /// @param gctx The current geometry context object, e.g. alignment
0201   /// @param position The position to start from
0202   /// @param direction The direction at start
0203   /// @param boundaryTolerance the Boundary Check Tolerance
0204   /// @param tolerance the tolerance used for the intersection
0205   ///
0206   /// If possible returns both solutions for the cylinder
0207   ///
0208   /// @return SurfaceIntersection object (contains intersection & surface)
0209   MultiIntersection3D intersect(
0210       const GeometryContext& gctx, const Vector3& position,
0211       const Vector3& direction,
0212       const BoundaryTolerance& boundaryTolerance =
0213           BoundaryTolerance::Infinite(),
0214       double tolerance = s_onSurfaceTolerance) const final;
0215 
0216   /// Path correction due to incident of the track
0217   ///
0218   /// @param gctx The current geometry context object, e.g. alignment
0219   /// @param position is the global position as a starting point
0220   /// @param direction is the global momentum direction at the starting point
0221   ///
0222   /// @return is the correction factor due to incident
0223   double pathCorrection(const GeometryContext& gctx, const Vector3& position,
0224                         const Vector3& direction) const final;
0225 
0226   /// Return method for properly formatted output string
0227   /// @return String representation of the class name
0228   std::string name() const override;
0229 
0230   /// Return a Polyhedron for a cylinder
0231   ///
0232   /// This method represents the cylinder as a polyhedron with a given number
0233   /// of segments to represent a quarter of a full circle. The polyedron will
0234   /// consist of the vertices of the cylinder on both sides, and faces between
0235   /// them, both as rectangular faces and as triangular faces.
0236   ///
0237   /// @param gctx The current geometry context object, e.g. alignment
0238   /// @param quarterSegments The number of segments to approximate a quarter of the
0239   /// full circle; it's chosen to be 1, only the extrema points (-pi, -0.5pi,
0240   /// 0., 0.5pi) are inserted to capture the correct extent in the x-y plane
0241   ///
0242   /// @return A list of vertices and a face/facett description of it
0243   Polyhedron polyhedronRepresentation(
0244       const GeometryContext& gctx,
0245       unsigned int quarterSegments = 2u) const override;
0246 
0247   /// Calculate the derivative of path length at the geometry constraint or
0248   /// point-of-closest-approach w.r.t. alignment parameters of the surface (i.e.
0249   /// local frame origin in global 3D Cartesian coordinates and its rotation
0250   /// represented with extrinsic Euler angles)
0251   ///
0252   /// @param gctx The current geometry context object, e.g. alignment
0253   /// @param position global 3D position
0254   /// @param direction global 3D momentum direction
0255   ///
0256   /// @return Derivative of path length w.r.t. the alignment parameters
0257   AlignmentToPathMatrix alignmentToPathDerivative(
0258       const GeometryContext& gctx, const Vector3& position,
0259       const Vector3& direction) const final;
0260 
0261   /// Calculate the derivative of bound track parameters local position w.r.t.
0262   /// position in local 3D Cartesian coordinates
0263   ///
0264   /// @param gctx The current geometry context object, e.g. alignment
0265   /// @param position The position of the parameters in global
0266   ///
0267   /// @return Derivative of bound local position w.r.t. position in local 3D
0268   /// cartesian coordinates
0269   Matrix<2, 3> localCartesianToBoundLocalDerivative(
0270       const GeometryContext& gctx, const Vector3& position) const final;
0271 
0272   /// Merge two cylinder surfaces into a single one.
0273   /// @image html Cylinder_Merging.svg
0274   /// @note The surfaces need to be *compatible*, i.e. have cylinder bounds
0275   ///       that align, and have the same radius
0276   /// @param other The other cylinder surface to merge with
0277   /// @param direction The axis direction: either @c AxisZ or @c AxisRPhi
0278   /// @param externalRotation If true, any phi rotation is done in the transform
0279   /// @param logger The logger to use
0280   /// @return The merged cylinder surface and a boolean indicating if surfaces are reversed
0281   /// @note The returned boolean is `false` if `this` is *left* or
0282   ///       *counter-clockwise* of @p other, and `true` if not.
0283   std::pair<std::shared_ptr<CylinderSurface>, bool> mergedWith(
0284       const CylinderSurface& other, AxisDirection direction,
0285       bool externalRotation, const Logger& logger = getDummyLogger()) const;
0286 
0287   /// @copydoc Surface::assignSurfaceMaterial
0288   void assignSurfaceMaterial(
0289       std::shared_ptr<const ISurfaceMaterial> material) override;
0290 
0291  protected:
0292   std::shared_ptr<const CylinderBounds> m_bounds;  //!< bounds (shared)
0293 
0294   /// @copydoc Surface::localAxes
0295   std::array<AxisDirection, 2> localAxes() const override {
0296     return {AxisDirection::AxisRPhi, AxisDirection::AxisZ};
0297   }
0298 
0299   /// @copydoc Surface::transformSurfaceLocalToMaterialLocal
0300   Vector2 transformSurfaceLocalToMaterialLocal(
0301       const Vector2& surfaceLocal) const override;
0302 
0303  private:
0304   bool m_scaleMaterialAxis = false;
0305 
0306   /// Implementation of the intersection solver
0307   ///
0308   ///  <b>mathematical motivation:</b>
0309   ///
0310   /// The cylinder is given by :
0311   ///   - cylinder center: ccenter (C)
0312   ///   - the direction of the cylinder axis: cdirection (DZ)
0313   ///   - the radius r
0314   /// The line is given by :
0315   ///   - a reference position : lposition (L0)
0316   ///   - the line direction: ldirection (DL)
0317   ///   the parametric form for the line is then : L(t) = L0 + t * DL
0318   ///
0319   /// Any point P on infinite cylinder if :
0320   ///      ((P - C) x DZ)^2 = r^2 * DZ^2
0321   /// We know that DZ is a unit vector:
0322   ///   DZ^2 == 1
0323   /// When expanded with the line equation, this is  :
0324   ///      ((L0 - C) x DZ + t * (DL x DZ))^2 = r^2 * DZ^2
0325   /// which is a quadratic equation in the form (X + t * Y)^2 = d, where :
0326   ///  X = (L0 - C) x DZ
0327   ///  Y = DL x DZ
0328   ///  d = r^2 * (DZ)^2
0329   /// Now, expand the equation :
0330   /// t^2 * (Y . Y) + t * (2 * (X . Y)) + (X . X) - d = 0
0331   /// => second order equation in the form : a*t^2 + b*t + c = 0 where
0332   /// a = (Y . Y)
0333   /// b = 2 * (X . Y)
0334   /// c = (X . X) - d
0335   /// finally solve the second order equation : a*t^2 + b*t + c = 0
0336   /// reinsertion into the line equation.
0337   ///
0338   /// @return the quadratic equation
0339   detail::RealQuadraticEquation intersectionSolver(
0340       const Transform3& transform, const Vector3& position,
0341       const Vector3& direction) const;
0342 };
0343 
0344 static_assert(RegularSurfaceConcept<CylinderSurface>,
0345               "CylinderSurface does not fulfill RegularSurfaceConcept");
0346 
0347 }  // namespace Acts