Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UnitVectors.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file UnitVectors.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
12 
13 #include <cmath>
14 #include <limits>
15 #include <utility>
16 
17 namespace Acts {
18 
28 template <typename T>
29 inline Eigen::Matrix<T, 3, 1> makeDirectionFromPhiEta(T phi, T eta) {
30  const auto coshEtaInv = 1 / std::cosh(eta);
31  return {
32  std::cos(phi) * coshEtaInv,
33  std::sin(phi) * coshEtaInv,
34  std::tanh(eta),
35  };
36 }
37 
47 template <typename T>
48 inline Eigen::Matrix<T, 3, 1> makeDirectionFromPhiTheta(T phi, T theta) {
49  const auto cosTheta = std::cos(theta);
50  const auto sinTheta = std::sin(theta);
51  return {
52  std::cos(phi) * sinTheta,
53  std::sin(phi) * sinTheta,
54  cosTheta,
55  };
56 }
57 
62 template <typename T>
63 inline Eigen::Matrix<T, 2, 1> makePhiThetaFromDirection(
64  Eigen::Matrix<T, 3, 1> unitDir) {
65  unitDir.normalize();
66  T phi = std::atan2(unitDir[1], unitDir[0]);
67  T theta = std::acos(unitDir[2]);
68  return {
69  phi,
70  theta,
71  };
72 }
73 
81 template <typename InputVector>
83  const Eigen::MatrixBase<InputVector>& direction) {
84  EIGEN_STATIC_ASSERT_FIXED_SIZE(InputVector);
85  EIGEN_STATIC_ASSERT_VECTOR_ONLY(InputVector);
86  static_assert(3 <= InputVector::RowsAtCompileTime,
87  "Direction vector must be at least three-dimensional.");
88 
89  using OutputVector = typename InputVector::PlainObject;
90  using OutputScalar = typename InputVector::Scalar;
91 
92  OutputVector unitU = OutputVector::Zero();
93  // explicit version of U = Z x T
94  unitU[0] = -direction[1];
95  unitU[1] = direction[0];
96  const auto scale = unitU.template head<2>().norm();
97  // if the absolute scale is tiny, the initial direction vector is aligned with
98  // the z-axis. the ZxT product is ill-defined since any vector in the x-y
99  // plane would be orthogonal to the direction. fix the U unit vector along the
100  // x-axis to avoid this numerical instability.
101  if (scale < (16 * std::numeric_limits<OutputScalar>::epsilon())) {
102  unitU[0] = 1;
103  unitU[1] = 0;
104  } else {
105  unitU.template head<2>() /= scale;
106  }
107  return unitU;
108 }
109 
123 template <typename InputVector>
125  const Eigen::MatrixBase<InputVector>& direction) {
126  EIGEN_STATIC_ASSERT_FIXED_SIZE(InputVector);
127  EIGEN_STATIC_ASSERT_VECTOR_ONLY(InputVector);
128  static_assert(3 <= InputVector::RowsAtCompileTime,
129  "Direction vector must be at least three-dimensional.");
130 
131  using OutputVector = typename InputVector::PlainObject;
132 
133  std::pair<OutputVector, OutputVector> unitVectors;
134  unitVectors.first = makeCurvilinearUnitU(direction);
135  unitVectors.second = direction.cross(unitVectors.first);
136  unitVectors.second.normalize();
137  return unitVectors;
138 }
139 
140 } // namespace Acts