ECCE @ 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 
10 // CylinderSurface.ipp, Acts project
12 
13 inline const Vector3D CylinderSurface::rotSymmetryAxis(
14  const GeometryContext& gctx) const {
15  // fast access via tranform matrix (and not rotation())
16  return transform(gctx).matrix().block<3, 1>(0, 2);
17 }
18 
19 inline detail::RealQuadraticEquation CylinderSurface::intersectionSolver(
20  const Transform3D& transform, const Vector3D& position,
21  const Vector3D& direction) const {
22  // Solve for radius R
23  double R = bounds().get(CylinderBounds::eR);
24 
25  // Get the transformation matrtix
26  const auto& tMatrix = transform.matrix();
27  Vector3D caxis = tMatrix.block<3, 1>(0, 2).transpose();
28  Vector3D ccenter = tMatrix.block<3, 1>(0, 3).transpose();
29 
30  // Check documentation for explanation
31  Vector3D pc = position - ccenter;
32  Vector3D pcXcd = pc.cross(caxis);
33  Vector3D ldXcd = direction.cross(caxis);
34  double a = ldXcd.dot(ldXcd);
35  double b = 2. * (ldXcd.dot(pcXcd));
36  double c = pcXcd.dot(pcXcd) - (R * R);
37  // And solve the qaudratic equation
38  return detail::RealQuadraticEquation(a, b, c);
39 }
40 
42  const GeometryContext& gctx, const Vector3D& position,
43  const Vector3D& direction, const BoundaryCheck& bcheck) const {
44  const auto& gctxTransform = transform(gctx);
45  // Solve the quadratic equation
46  auto qe = intersectionSolver(gctxTransform, position, direction);
47 
48  // If no valid solution return a non-valid intersection
49  if (qe.solutions == 0) {
50  return Intersection();
51  }
52 
53  // Absolute smallest solution
54  double path =
55  qe.first * qe.first < qe.second * qe.second ? qe.first : qe.second;
56  Vector3D solution = position + path * direction;
57  Intersection::Status status =
59  ? Intersection::Status::onSurface
60  : Intersection::Status::reachable;
61 
62  // Boundary check necessary
63  if (bcheck and not isOnSurface(gctx, solution, direction, bcheck)) {
64  status = Intersection::Status::missed;
65  }
66 
67  // Now return the solution
68  return Intersection(solution, path, status);
69 }
70 
71 inline SurfaceIntersection CylinderSurface::intersect(
72  const GeometryContext& gctx, const Vector3D& position,
73  const Vector3D& direction, const BoundaryCheck& bcheck) const {
74  const auto& gctxTransform = transform(gctx);
75 
76  // Solve the quadratic equation
77  auto qe = intersectionSolver(gctxTransform, position, direction);
78 
79  // If no valid solution return a non-valid surfaceIntersection
80  if (qe.solutions == 0) {
81  return SurfaceIntersection();
82  }
83 
84  // Check the validity of the first solution
85  Vector3D solution1 = position + qe.first * direction;
86  Intersection::Status status1 =
87  qe.first * qe.first < s_onSurfaceTolerance * s_onSurfaceTolerance
88  ? Intersection::Status::onSurface
89  : Intersection::Status::reachable;
90 
91  // Helper method for boundary check
92  auto boundaryCheck =
93  [&](const Vector3D& solution,
95  // No check to be done, return current status
96  if (!bcheck)
97  return status;
98  const auto& cBounds = bounds();
99  if (cBounds.coversFullAzimuth() and
100  bcheck.type() == BoundaryCheck::Type::eAbsolute) {
101  // Project out the current Z value via local z axis
102  // Built-in local to global for speed reasons
103  const auto& tMatrix = gctxTransform.matrix();
104  // Create the reference vector in local
105  const Vector3D vecLocal(solution - tMatrix.block<3, 1>(0, 3));
106  double cZ = vecLocal.dot(tMatrix.block<3, 1>(0, 2));
107  double tolerance = s_onSurfaceTolerance + bcheck.tolerance()[eLOC_Z];
108  double hZ = cBounds.get(CylinderBounds::eHalfLengthZ) + tolerance;
109  return (cZ * cZ < hZ * hZ) ? status : Intersection::Status::missed;
110  }
111  return (isOnSurface(gctx, solution, direction, bcheck)
112  ? status
113  : Intersection::Status::missed);
114  };
115  // Check first solution for boundary compatiblity
116  status1 = boundaryCheck(solution1, status1);
117  // Set the intersection
118  Intersection first(solution1, qe.first, status1);
119  SurfaceIntersection cIntersection(first, this);
120  if (qe.solutions == 1) {
121  return cIntersection;
122  }
123  // Check the validity of the second solution
124  Vector3D solution2 = position + qe.second * direction;
125  Intersection::Status status2 =
126  qe.second * qe.second < s_onSurfaceTolerance * s_onSurfaceTolerance
127  ? Intersection::Status::onSurface
128  : Intersection::Status::reachable;
129  // Check first solution for boundary compatiblity
130  status2 = boundaryCheck(solution2, status2);
131  Intersection second(solution2, qe.second, status2);
132  // Check one if its valid or neither is valid
133  bool check1 = status1 != Intersection::Status::missed or
134  (status1 == Intersection::Status::missed and
135  status2 == Intersection::Status::missed);
136  // Check and (eventually) go with the first solution
137  if ((check1 and qe.first * qe.first < qe.second * qe.second) or
138  status2 == Intersection::Status::missed) {
139  // And add the alternative
140  cIntersection.alternative = second;
141  } else {
142  // And add the alternative
143  cIntersection.alternative = first;
144  cIntersection.intersection = second;
145  }
146  return cIntersection;
147 }