EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CylinderSurface.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CylinderSurface.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2016-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 
10 
15 
16 #include <cassert>
17 #include <cmath>
18 #include <system_error>
19 
22 
24  : GeometryObject(), Surface(other), m_bounds(other.m_bounds) {}
25 
27  const CylinderSurface& other,
28  const Transform3D& shift)
29  : GeometryObject(), Surface(gctx, other, shift), m_bounds(other.m_bounds) {}
30 
32  double radius, double halfz,
33  double halfphi, double avphi)
34  : Surface(transform),
35  m_bounds(std::make_shared<const CylinderBounds>(radius, halfz, halfphi,
36  avphi)) {}
37 
39  std::shared_ptr<const CylinderBounds> cbounds,
40  const Acts::DetectorElementBase& detelement)
41  : Surface(detelement), m_bounds(std::move(cbounds)) {
43  assert(cbounds);
44 }
45 
47  const Transform3D& transform,
48  const std::shared_ptr<const CylinderBounds>& cbounds)
49  : Surface(transform), m_bounds(cbounds) {
50  throw_assert(cbounds, "CylinderBounds must not be nullptr");
51 }
52 
54  const CylinderSurface& other) {
55  if (this != &other) {
56  Surface::operator=(other);
57  m_bounds = other.m_bounds;
58  }
59  return *this;
60 }
61 
62 // return the binning position for ordering in the BinnedArray
64  const GeometryContext& gctx, BinningValue bValue) const {
65  const Acts::Vector3D& sfCenter = center(gctx);
66  // special binning type for R-type methods
67  if (bValue == Acts::binR || bValue == Acts::binRPhi) {
68  double R = bounds().get(CylinderBounds::eR);
69  double phi = bounds().get(CylinderBounds::eAveragePhi);
70  return Vector3D(sfCenter.x() + R * cos(phi), sfCenter.y() + R * sin(phi),
71  sfCenter.z());
72  }
73  // give the center as default for all of these binning types
74  // binX, binY, binZ, binR, binPhi, binRPhi, binH, binEta
75  return sfCenter;
76 }
77 
78 // return the measurement frame: it's the tangential plane
80  const GeometryContext& gctx, const Vector3D& position,
81  const Vector3D& /*unused*/) const {
82  RotationMatrix3D mFrame;
83  // construct the measurement frame
84  // measured Y is the z axis
85  Vector3D measY = rotSymmetryAxis(gctx);
86  // measured z is the position normalized transverse (in local)
87  Vector3D measDepth = normal(gctx, position);
88  // measured X is what comoes out of it
89  Vector3D measX(measY.cross(measDepth).normalized());
90  // assign the columnes
91  mFrame.col(0) = measX;
92  mFrame.col(1) = measY;
93  mFrame.col(2) = measDepth;
94  // return the rotation matrix
95  return mFrame;
96 }
97 
99  return Surface::Cylinder;
100 }
101 
103  const GeometryContext& gctx, const Vector2D& lposition,
104  const Vector3D& /*unused*/) const {
105  // create the position in the local 3d frame
106  double r = bounds().get(CylinderBounds::eR);
107  double phi = lposition[Acts::eBoundLoc0] / r;
108  Vector3D position(r * cos(phi), r * sin(phi), lposition[Acts::eBoundLoc1]);
109  return transform(gctx) * position;
110 }
111 
113  const GeometryContext& gctx, const Vector3D& position,
114  const Vector3D& /*unused*/) const {
115  // @todo check if s_onSurfaceTolerance would do here
116  double inttol = bounds().get(CylinderBounds::eR) * 0.0001;
117  if (inttol < 0.01) {
118  inttol = 0.01;
119  }
120  const Transform3D& sfTransform = transform(gctx);
121  Transform3D inverseTrans(sfTransform.inverse());
122  Vector3D loc3Dframe(inverseTrans * position);
123  if (std::abs(perp(loc3Dframe) - bounds().get(CylinderBounds::eR)) > inttol) {
124  return Result<Vector2D>::failure(SurfaceError::GlobalPositionNotOnSurface);
125  }
127  {bounds().get(CylinderBounds::eR) * phi(loc3Dframe), loc3Dframe.z()});
128 }
129 
130 std::string Acts::CylinderSurface::name() const {
131  return "Acts::CylinderSurface";
132 }
133 
135  const GeometryContext& gctx, const Acts::Vector2D& lposition) const {
136  double phi = lposition[Acts::eBoundLoc0] / m_bounds->get(CylinderBounds::eR);
137  Vector3D localNormal(cos(phi), sin(phi), 0.);
138  return Vector3D(transform(gctx).matrix().block<3, 3>(0, 0) * localNormal);
139 }
140 
142  const GeometryContext& gctx, const Acts::Vector3D& position) const {
143  const Transform3D& sfTransform = transform(gctx);
144  // get it into the cylinder frame
145  Vector3D pos3D = sfTransform.inverse() * position;
146  // set the z coordinate to 0
147  pos3D.z() = 0.;
148  // normalize and rotate back into global if needed
149  return sfTransform.linear() * pos3D.normalized();
150 }
151 
154  const Acts::Vector3D& direction) const {
155  Vector3D normalT = normal(gctx, position);
156  double cosAlpha = normalT.dot(direction);
157  return std::fabs(1. / cosAlpha);
158 }
159 
161  return (*m_bounds.get());
162 }
163 
165  const GeometryContext& gctx, size_t lseg) const {
166  // Prepare vertices and faces
167  std::vector<Vector3D> vertices;
168  std::vector<Polyhedron::FaceType> faces;
169  std::vector<Polyhedron::FaceType> triangularMesh;
170 
171  auto ctrans = transform(gctx);
172  bool fullCylinder = bounds().coversFullAzimuth();
173 
174  double avgPhi = bounds().get(CylinderBounds::eAveragePhi);
175  double halfPhi = bounds().get(CylinderBounds::eHalfPhiSector);
176 
177  // Get the phi segments from the helper - ensures extra points
178  auto phiSegs = fullCylinder
181  avgPhi - halfPhi, avgPhi + halfPhi, {avgPhi});
182 
183  // Write the two bows/circles on either side
184  std::vector<int> sides = {-1, 1};
185  for (auto& side : sides) {
186  for (size_t iseg = 0; iseg < phiSegs.size() - 1; ++iseg) {
187  int addon = (iseg == phiSegs.size() - 2 and not fullCylinder) ? 1 : 0;
190  vertices,
191  {bounds().get(CylinderBounds::eR), bounds().get(CylinderBounds::eR)},
192  phiSegs[iseg], phiSegs[iseg + 1], lseg, addon,
193  Vector3D(0., 0., side * bounds().get(CylinderBounds::eHalfLengthZ)),
194  ctrans);
195  }
196  }
197  auto facesMesh =
198  detail::FacesHelper::cylindricalFaceMesh(vertices, fullCylinder);
199  return Polyhedron(vertices, facesMesh.first, facesMesh.second, false);
200 }