ECCE @ 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 #include <cassert>
11 #include <cmath>
12 #include <iomanip>
13 #include <iostream>
14 #include <utility>
15 
19 
22 
24  : GeometryObject(), Surface(other), m_bounds(other.m_bounds) {}
25 
27  const CylinderSurface& other,
28  const Transform3D& transf)
29  : GeometryObject(),
30  Surface(gctx, other, transf),
31  m_bounds(other.m_bounds) {}
32 
34  std::shared_ptr<const Transform3D> htrans, double radius, double halfz,
35  double halfphi, double avphi)
36  : Surface(std::move(htrans)),
37  m_bounds(std::make_shared<const CylinderBounds>(radius, halfz, halfphi,
38  avphi)) {}
39 
41  std::shared_ptr<const CylinderBounds> cbounds,
42  const Acts::DetectorElementBase& detelement)
43  : Surface(detelement), m_bounds(std::move(cbounds)) {
45  assert(cbounds);
46 }
47 
49  std::shared_ptr<const Transform3D> htrans,
50  const std::shared_ptr<const CylinderBounds>& cbounds)
51  : Surface(std::move(htrans)), m_bounds(cbounds) {
52  throw_assert(cbounds, "CylinderBounds must not be nullptr");
53 }
54 
56  const CylinderSurface& other) {
57  if (this != &other) {
58  Surface::operator=(other);
59  m_bounds = other.m_bounds;
60  }
61  return *this;
62 }
63 
64 // return the binning position for ordering in the BinnedArray
66  const GeometryContext& gctx, BinningValue bValue) const {
67  const Acts::Vector3D& sfCenter = center(gctx);
68  // special binning type for R-type methods
69  if (bValue == Acts::binR || bValue == Acts::binRPhi) {
70  double R = bounds().get(CylinderBounds::eR);
71  double phi = bounds().get(CylinderBounds::eAveragePhi);
72  return Vector3D(sfCenter.x() + R * cos(phi), sfCenter.y() + R * sin(phi),
73  sfCenter.z());
74  }
75  // give the center as default for all of these binning types
76  // binX, binY, binZ, binR, binPhi, binRPhi, binH, binEta
77  return sfCenter;
78 }
79 
80 // return the measurement frame: it's the tangential plane
82  const GeometryContext& gctx, const Vector3D& position,
83  const Vector3D& /*unused*/) const {
84  RotationMatrix3D mFrame;
85  // construct the measurement frame
86  // measured Y is the z axis
87  Vector3D measY = rotSymmetryAxis(gctx);
88  // measured z is the position normalized transverse (in local)
89  Vector3D measDepth = normal(gctx, position);
90  // measured X is what comoes out of it
91  Vector3D measX(measY.cross(measDepth).normalized());
92  // assign the columnes
93  mFrame.col(0) = measX;
94  mFrame.col(1) = measY;
95  mFrame.col(2) = measDepth;
96  // return the rotation matrix
97  return mFrame;
98 }
99 
101  return Surface::Cylinder;
102 }
103 
105  const Vector2D& lposition,
106  const Vector3D& /*unused*/,
107  Vector3D& position) const {
108  // create the position in the local 3d frame
109  double r = bounds().get(CylinderBounds::eR);
110  double phi = lposition[Acts::eLOC_RPHI] / r;
111  position = Vector3D(r * cos(phi), r * sin(phi), lposition[Acts::eLOC_Z]);
112  position = transform(gctx) * position;
113 }
114 
116  const Vector3D& position,
117  const Vector3D& /*unused*/,
118  Vector2D& lposition) const {
119  // get the transform & transform global position into cylinder frame
120  // @todo clean up intolerance parameters
121  // transform it to the globalframe: CylinderSurfaces are allowed to have 0
122  // pointer transform
123  double radius = 0.;
124  double inttol = bounds().get(CylinderBounds::eR) * 0.0001;
125  if (inttol < 0.01) {
126  inttol = 0.01;
127  }
128 
129  const Transform3D& sfTransform = transform(gctx);
130  Transform3D inverseTrans(sfTransform.inverse());
131  Vector3D loc3Dframe(inverseTrans * position);
132  lposition = Vector2D(bounds().get(CylinderBounds::eR) * phi(loc3Dframe),
133  loc3Dframe.z());
134  radius = perp(loc3Dframe);
135  // return true or false
136  return ((std::abs(radius - bounds().get(CylinderBounds::eR)) > inttol)
137  ? false
138  : true);
139 }
140 
141 std::string Acts::CylinderSurface::name() const {
142  return "Acts::CylinderSurface";
143 }
144 
146  const GeometryContext& gctx, const Acts::Vector2D& lposition) const {
147  double phi = lposition[Acts::eLOC_RPHI] / m_bounds->get(CylinderBounds::eR);
148  Vector3D localNormal(cos(phi), sin(phi), 0.);
149  return Vector3D(transform(gctx).matrix().block<3, 3>(0, 0) * localNormal);
150 }
151 
153  const GeometryContext& gctx, const Acts::Vector3D& position) const {
154  const Transform3D& sfTransform = transform(gctx);
155  // get it into the cylinder frame
156  Vector3D pos3D = sfTransform.inverse() * position;
157  // set the z coordinate to 0
158  pos3D.z() = 0.;
159  // normalize and rotate back into global if needed
160  return sfTransform.linear() * pos3D.normalized();
161 }
162 
165  const Acts::Vector3D& direction) const {
166  Vector3D normalT = normal(gctx, position);
167  double cosAlpha = normalT.dot(direction);
168  return std::fabs(1. / cosAlpha);
169 }
170 
172  return (*m_bounds.get());
173 }
174 
176  const GeometryContext& gctx, size_t lseg) const {
177  // Prepare vertices and faces
178  std::vector<Vector3D> vertices;
179  std::vector<Polyhedron::FaceType> faces;
180  std::vector<Polyhedron::FaceType> triangularMesh;
181 
182  auto ctrans = transform(gctx);
183  bool fullCylinder = bounds().coversFullAzimuth();
184 
185  double avgPhi = bounds().get(CylinderBounds::eAveragePhi);
186  double halfPhi = bounds().get(CylinderBounds::eHalfPhiSector);
187 
188  // Get the phi segments from the helper - ensures extra points
189  auto phiSegs = fullCylinder
192  avgPhi - halfPhi, avgPhi + halfPhi, {avgPhi});
193 
194  // Write the two bows/circles on either side
195  std::vector<int> sides = {-1, 1};
196  for (auto& side : sides) {
197  for (size_t iseg = 0; iseg < phiSegs.size() - 1; ++iseg) {
198  int addon = (iseg == phiSegs.size() - 2 and not fullCylinder) ? 1 : 0;
201  vertices,
202  {bounds().get(CylinderBounds::eR), bounds().get(CylinderBounds::eR)},
203  phiSegs[iseg], phiSegs[iseg + 1], lseg, addon,
204  Vector3D(0., 0., side * bounds().get(CylinderBounds::eHalfLengthZ)),
205  ctrans);
206  }
207  }
208  auto facesMesh =
209  detail::FacesHelper::cylindricalFaceMesh(vertices, fullCylinder);
210  return Polyhedron(vertices, facesMesh.first, facesMesh.second);
211 }