EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CylinderSurface.ipp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CylinderSurface.ipp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2018 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 inline Vector3D CylinderSurface::rotSymmetryAxis(
10  const GeometryContext& gctx) const {
11  // fast access via tranform matrix (and not rotation())
12  return transform(gctx).matrix().block<3, 1>(0, 2);
13 }
14 
15 inline detail::RealQuadraticEquation CylinderSurface::intersectionSolver(
16  const Transform3D& transform, const Vector3D& position,
17  const Vector3D& direction) const {
18  // Solve for radius R
19  double R = bounds().get(CylinderBounds::eR);
20 
21  // Get the transformation matrtix
22  const auto& tMatrix = transform.matrix();
23  Vector3D caxis = tMatrix.block<3, 1>(0, 2).transpose();
24  Vector3D ccenter = tMatrix.block<3, 1>(0, 3).transpose();
25 
26  // Check documentation for explanation
27  Vector3D pc = position - ccenter;
28  Vector3D pcXcd = pc.cross(caxis);
29  Vector3D ldXcd = direction.cross(caxis);
30  double a = ldXcd.dot(ldXcd);
31  double b = 2. * (ldXcd.dot(pcXcd));
32  double c = pcXcd.dot(pcXcd) - (R * R);
33  // And solve the qaudratic equation
34  return detail::RealQuadraticEquation(a, b, c);
35 }
36 
38  const GeometryContext& gctx, const Vector3D& position,
39  const Vector3D& direction, const BoundaryCheck& bcheck) const {
40  const auto& gctxTransform = transform(gctx);
41 
42  // Solve the quadratic equation
43  auto qe = intersectionSolver(gctxTransform, position, direction);
44 
45  // If no valid solution return a non-valid surfaceIntersection
46  if (qe.solutions == 0) {
47  return SurfaceIntersection();
48  }
49 
50  // Check the validity of the first solution
51  Vector3D solution1 = position + qe.first * direction;
52  Intersection3D::Status status1 =
53  qe.first * qe.first < s_onSurfaceTolerance * s_onSurfaceTolerance
54  ? Intersection3D::Status::onSurface
55  : Intersection3D::Status::reachable;
56 
57  // Helper method for boundary check
58  auto boundaryCheck =
59  [&](const Vector3D& solution,
61  // No check to be done, return current status
62  if (!bcheck)
63  return status;
64  const auto& cBounds = bounds();
65  if (cBounds.coversFullAzimuth() and
66  bcheck.type() == BoundaryCheck::Type::eAbsolute) {
67  // Project out the current Z value via local z axis
68  // Built-in local to global for speed reasons
69  const auto& tMatrix = gctxTransform.matrix();
70  // Create the reference vector in local
71  const Vector3D vecLocal(solution - tMatrix.block<3, 1>(0, 3));
72  double cZ = vecLocal.dot(tMatrix.block<3, 1>(0, 2));
74  double hZ = cBounds.get(CylinderBounds::eHalfLengthZ) + tolerance;
75  return (cZ * cZ < hZ * hZ) ? status : Intersection3D::Status::missed;
76  }
77  return (isOnSurface(gctx, solution, direction, bcheck)
78  ? status
79  : Intersection3D::Status::missed);
80  };
81  // Check first solution for boundary compatiblity
82  status1 = boundaryCheck(solution1, status1);
83  // Set the intersection
84  Intersection3D first(solution1, qe.first, status1);
85  SurfaceIntersection cIntersection(first, this);
86  if (qe.solutions == 1) {
87  return cIntersection;
88  }
89  // Check the validity of the second solution
90  Vector3D solution2 = position + qe.second * direction;
91  Intersection3D::Status status2 =
92  qe.second * qe.second < s_onSurfaceTolerance * s_onSurfaceTolerance
93  ? Intersection3D::Status::onSurface
94  : Intersection3D::Status::reachable;
95  // Check first solution for boundary compatiblity
96  status2 = boundaryCheck(solution2, status2);
97  Intersection3D second(solution2, qe.second, status2);
98  // Check one if its valid or neither is valid
99  bool check1 = status1 != Intersection3D::Status::missed or
100  (status1 == Intersection3D::Status::missed and
101  status2 == Intersection3D::Status::missed);
102  // Check and (eventually) go with the first solution
103  if ((check1 and qe.first * qe.first < qe.second * qe.second) or
104  status2 == Intersection3D::Status::missed) {
105  // And add the alternative
106  cIntersection.alternative = second;
107  } else {
108  // And add the alternative
109  cIntersection.alternative = first;
110  cIntersection.intersection = second;
111  }
112  return cIntersection;
113 }
114 
116 CylinderSurface::localCartesianToBoundLocalDerivative(
117  const GeometryContext& gctx, const Vector3D& position) const {
118  using VectorHelpers::perp;
119  using VectorHelpers::phi;
120  // The local frame transform
121  const auto& sTransform = transform(gctx);
122  // calculate the transformation to local coorinates
123  const Vector3D localPos = sTransform.inverse() * position;
124  const double lr = perp(localPos);
125  const double lphi = phi(localPos);
126  const double lcphi = std::cos(lphi);
127  const double lsphi = std::sin(lphi);
128  // Solve for radius R
129  double R = bounds().get(CylinderBounds::eR);
130  LocalCartesianToBoundLocalMatrix loc3DToLocBound =
131  LocalCartesianToBoundLocalMatrix::Zero();
132  loc3DToLocBound << -R * lsphi / lr, R * lcphi / lr, 0, 0, 0, 1;
133 
134  return loc3DToLocBound;
135 }