Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-02 09:19: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 
0013 #include <cmath>
0014 #include <limits>
0015 #include <utility>
0016 
0017 namespace Acts {
0018 
0019 /// Construct a normalized direction vector from phi angle and pseudorapidity.
0020 ///
0021 /// @param phi is the direction angle in the x-y plane.
0022 /// @param eta is the pseudorapidity towards the z-axis.
0023 /// @return A normalized 3D direction vector constructed from phi and eta
0024 ///
0025 /// @note The input arguments intentionally use the same template type so that
0026 ///       a compile error occurs if inconsistent input types are used. Avoids
0027 ///       unexpected implicit type conversions and forces the user to
0028 ///       explicitly cast mismatched input types.
0029 template <typename T>
0030 inline Eigen::Matrix<T, 3, 1> makeDirectionFromPhiEta(T phi, T eta) {
0031   const auto coshEtaInv = 1 / std::cosh(eta);
0032   return {
0033       std::cos(phi) * coshEtaInv,
0034       std::sin(phi) * coshEtaInv,
0035       std::tanh(eta),
0036   };
0037 }
0038 
0039 /// Construct a normalized direction vector from phi and theta angle.
0040 ///
0041 /// @param phi is the direction angle in radian in the x-y plane.
0042 /// @param theta is the polar angle in radian towards the z-axis.
0043 /// @return A normalized 3D direction vector constructed from phi and theta
0044 ///
0045 /// @note The input arguments intentionally use the same template type so that
0046 ///       a compile error occurs if inconsistent input types are used. Avoids
0047 ///       unexpected implicit type conversions and forces the user to
0048 ///       explicitly cast mismatched input types.
0049 template <typename T>
0050 inline Eigen::Matrix<T, 3, 1> makeDirectionFromPhiTheta(T phi, T theta) {
0051   const T sinTheta{std::sin(theta)};
0052   return {
0053       std::cos(phi) * sinTheta,
0054       std::sin(phi) * sinTheta,
0055       std::cos(theta),
0056   };
0057 }
0058 /// @brief Construct a normalized direction vector from the tangents of the
0059 ///        x-axis to the z-axis and of the y-axis to the z-axis
0060 ///
0061 /// @param tanAlpha Tangent of the x-axis to the z-axis
0062 /// @param tanBeta Tangent of the y-axis to the z-axis
0063 /// @return A normalized 3D direction vector constructed from the axis tangents
0064 template <typename T>
0065 inline Eigen::Matrix<T, 3, 1> makeDirectionFromAxisTangents(T tanAlpha,
0066                                                             T tanBeta) {
0067   return Eigen::Matrix<T, 3, 1>{tanAlpha, tanBeta, 1}.normalized();
0068 }
0069 
0070 /// Construct a phi and theta angle from a direction vector.
0071 ///
0072 /// @param unitDir 3D vector indicating a direction
0073 /// @return A 2D vector containing phi and theta angles [phi, theta]
0074 ///
0075 template <typename T>
0076 inline Eigen::Matrix<T, 2, 1> makePhiThetaFromDirection(
0077     const Eigen::Matrix<T, 3, 1>& unitDir) {
0078   T phi = std::atan2(unitDir[1], unitDir[0]);
0079   T theta = std::acos(unitDir[2]);
0080   return {
0081       phi,
0082       theta,
0083   };
0084 }
0085 
0086 /// Construct the first curvilinear unit vector `U` for the given direction.
0087 ///
0088 /// @param direction is the input direction vector
0089 /// @returns a normalized vector in the x-y plane orthogonal to the direction.
0090 ///
0091 /// The special case of the direction vector pointing along the z-axis is
0092 /// handled by forcing the unit vector to along the x-axis.
0093 template <typename InputVector>
0094 inline auto createCurvilinearUnitU(
0095     const Eigen::MatrixBase<InputVector>& direction) {
0096   EIGEN_STATIC_ASSERT_FIXED_SIZE(InputVector);
0097   EIGEN_STATIC_ASSERT_VECTOR_ONLY(InputVector);
0098   static_assert(3 <= InputVector::RowsAtCompileTime,
0099                 "Direction vector must be at least three-dimensional.");
0100 
0101   using OutputVector = typename InputVector::PlainObject;
0102   using OutputScalar = typename InputVector::Scalar;
0103 
0104   OutputVector unitU = OutputVector::Zero();
0105   // explicit version of U = Z x T
0106   unitU[0] = -direction[1];
0107   unitU[1] = direction[0];
0108   const auto scale = unitU.template head<2>().norm();
0109   // if the absolute scale is tiny, the initial direction vector is aligned with
0110   // the z-axis. the ZxT product is ill-defined since any vector in the x-y
0111   // plane would be orthogonal to the direction. fix the U unit vector along the
0112   // x-axis to avoid this numerical instability.
0113   if (scale < (16 * std::numeric_limits<OutputScalar>::epsilon())) {
0114     unitU[0] = 1;
0115     unitU[1] = 0;
0116   } else {
0117     unitU.template head<2>() /= scale;
0118   }
0119   return unitU;
0120 }
0121 
0122 /// Construct the curvilinear unit vectors `U` and `V` for the given direction.
0123 ///
0124 /// @param direction is the input direction vector
0125 /// @returns normalized unit vectors `U` and `V` orthogonal to the direction.
0126 ///
0127 /// With `T` the normalized input direction, the three vectors `U`, `V`, and
0128 /// `T` form an orthonormal basis set, i.e. they satisfy
0129 ///
0130 ///     U x V = T
0131 ///     V x T = U
0132 ///     T x U = V
0133 ///
0134 /// with the additional condition that `U` is located in the global x-y plane.
0135 template <typename InputVector>
0136 inline auto createCurvilinearUnitVectors(
0137     const Eigen::MatrixBase<InputVector>& direction) {
0138   EIGEN_STATIC_ASSERT_FIXED_SIZE(InputVector);
0139   EIGEN_STATIC_ASSERT_VECTOR_ONLY(InputVector);
0140   static_assert(3 <= InputVector::RowsAtCompileTime,
0141                 "Direction vector must be at least three-dimensional.");
0142 
0143   using OutputVector = typename InputVector::PlainObject;
0144 
0145   std::pair<OutputVector, OutputVector> unitVectors;
0146   unitVectors.first = createCurvilinearUnitU(direction);
0147   unitVectors.second = direction.cross(unitVectors.first);
0148   unitVectors.second.normalize();
0149   return unitVectors;
0150 }
0151 
0152 }  // namespace Acts