EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DiscSurface.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file DiscSurface.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 
18 
19 #include <cmath>
20 #include <system_error>
21 #include <vector>
22 
25 
26 Acts::DiscSurface::DiscSurface(const DiscSurface& other)
27  : GeometryObject(), Surface(other), m_bounds(other.m_bounds) {}
28 
29 Acts::DiscSurface::DiscSurface(const GeometryContext& gctx,
30  const DiscSurface& other,
31  const Transform3D& shift)
32  : GeometryObject(), Surface(gctx, other, shift), m_bounds(other.m_bounds) {}
33 
34 Acts::DiscSurface::DiscSurface(const Transform3D& transform, double rmin,
35  double rmax, double hphisec)
36  : GeometryObject(),
37  Surface(std::move(transform)),
38  m_bounds(std::make_shared<const RadialBounds>(rmin, rmax, hphisec)) {}
39 
40 Acts::DiscSurface::DiscSurface(const Transform3D& transform, double minhalfx,
41  double maxhalfx, double minR, double maxR,
42  double avephi, double stereo)
43  : GeometryObject(),
44  Surface(transform),
45  m_bounds(std::make_shared<const DiscTrapezoidBounds>(
46  minhalfx, maxhalfx, minR, maxR, avephi, stereo)) {}
47 
48 Acts::DiscSurface::DiscSurface(const Transform3D& transform,
49  std::shared_ptr<const DiscBounds> dbounds)
50  : GeometryObject(), Surface(transform), m_bounds(std::move(dbounds)) {}
51 
52 Acts::DiscSurface::DiscSurface(const std::shared_ptr<const DiscBounds>& dbounds,
53  const DetectorElementBase& detelement)
54  : GeometryObject(), Surface(detelement), m_bounds(dbounds) {
55  throw_assert(dbounds, "nullptr as DiscBounds");
56 }
57 
58 Acts::DiscSurface& Acts::DiscSurface::operator=(const DiscSurface& other) {
59  if (this != &other) {
61  m_bounds = other.m_bounds;
62  }
63  return *this;
64 }
65 
66 Acts::Surface::SurfaceType Acts::DiscSurface::type() const {
67  return Surface::Disc;
68 }
69 
70 Acts::Vector3D Acts::DiscSurface::localToGlobal(
71  const GeometryContext& gctx, const Vector2D& lposition,
72  const Vector3D& /*gmom*/) const {
73  // create the position in the local 3d frame
74  Vector3D loc3Dframe(
75  lposition[Acts::eBoundLoc0] * cos(lposition[Acts::eBoundLoc1]),
76  lposition[Acts::eBoundLoc0] * sin(lposition[Acts::eBoundLoc1]), 0.);
77  // transform to globalframe
78  return transform(gctx) * loc3Dframe;
79 }
80 
81 Acts::Result<Acts::Vector2D> Acts::DiscSurface::globalToLocal(
82  const GeometryContext& gctx, const Vector3D& position,
83  const Vector3D& /*gmom*/) const {
84  // transport it to the globalframe
85  Vector3D loc3Dframe = (transform(gctx).inverse()) * position;
86  if (loc3Dframe.z() * loc3Dframe.z() >
88  return Result<Vector2D>::failure(SurfaceError::GlobalPositionNotOnSurface);
89  }
90  return Result<Acts::Vector2D>::success({perp(loc3Dframe), phi(loc3Dframe)});
91 }
92 
93 Acts::Vector2D Acts::DiscSurface::localPolarToLocalCartesian(
94  const Vector2D& locpol) const {
95  const DiscTrapezoidBounds* dtbo =
96  dynamic_cast<const Acts::DiscTrapezoidBounds*>(&(bounds()));
97  if (dtbo != nullptr) {
98  double rMedium = dtbo->rCenter();
99  double phi = dtbo->get(DiscTrapezoidBounds::eAveragePhi);
100 
101  Vector2D polarCenter(rMedium, phi);
102  Vector2D cartCenter = localPolarToCartesian(polarCenter);
103  Vector2D cartPos = localPolarToCartesian(locpol);
104  Vector2D Pos = cartPos - cartCenter;
105 
106  Acts::Vector2D locPos(
107  Pos[Acts::eBoundLoc0] * sin(phi) - Pos[Acts::eBoundLoc1] * cos(phi),
108  Pos[Acts::eBoundLoc1] * sin(phi) + Pos[Acts::eBoundLoc0] * cos(phi));
109  return Vector2D(locPos[Acts::eBoundLoc0], locPos[Acts::eBoundLoc1]);
110  }
111  return Vector2D(locpol[Acts::eBoundLoc0] * cos(locpol[Acts::eBoundLoc1]),
112  locpol[Acts::eBoundLoc0] * sin(locpol[Acts::eBoundLoc1]));
113 }
114 
115 Acts::Vector3D Acts::DiscSurface::localCartesianToGlobal(
116  const GeometryContext& gctx, const Vector2D& lposition) const {
117  Vector3D loc3Dframe(lposition[Acts::eBoundLoc0], lposition[Acts::eBoundLoc1],
118  0.);
119  return Vector3D(transform(gctx) * loc3Dframe);
120 }
121 
122 Acts::Vector2D Acts::DiscSurface::globalToLocalCartesian(
123  const GeometryContext& gctx, const Vector3D& position,
124  double /*unused*/) const {
125  Vector3D loc3Dframe = (transform(gctx).inverse()) * position;
126  return Vector2D(loc3Dframe.x(), loc3Dframe.y());
127 }
128 
129 std::string Acts::DiscSurface::name() const {
130  return "Acts::DiscSurface";
131 }
132 
133 const Acts::SurfaceBounds& Acts::DiscSurface::bounds() const {
134  if (m_bounds) {
135  return (*(m_bounds.get()));
136  }
137  return s_noBounds;
138 }
139 
140 Acts::Polyhedron Acts::DiscSurface::polyhedronRepresentation(
141  const GeometryContext& gctx, size_t lseg) const {
142  // Prepare vertices and faces
143  std::vector<Vector3D> vertices;
144  std::vector<Polyhedron::FaceType> faces;
145  std::vector<Polyhedron::FaceType> triangularMesh;
146 
147  // Understand the disc
148  bool fullDisc = m_bounds->coversFullAzimuth();
149  bool toCenter = m_bounds->rMin() < s_onSurfaceTolerance;
150  // If you have bounds you can create a polyhedron representation
151  bool exactPolyhedron = (m_bounds->type() == SurfaceBounds::eDiscTrapezoid);
152  if (m_bounds) {
153  auto vertices2D = m_bounds->vertices(lseg);
154  vertices.reserve(vertices2D.size() + 1);
155  Vector3D wCenter(0., 0., 0);
156  for (const auto& v2D : vertices2D) {
157  vertices.push_back(transform(gctx) * Vector3D(v2D.x(), v2D.y(), 0.));
158  wCenter += (*vertices.rbegin());
159  }
160  // These are convex shapes, use the helper method
161  // For rings there's a sweet spot when this stops working
162  if (m_bounds->type() == SurfaceBounds::eDiscTrapezoid or toCenter or
163  not fullDisc) {
164  // Transform them into the vertex frame
165  wCenter *= 1. / vertices.size();
166  vertices.push_back(wCenter);
167  auto facesMesh = detail::FacesHelper::convexFaceMesh(vertices, true);
168  faces = facesMesh.first;
169  triangularMesh = facesMesh.second;
170  } else {
171  // Two concentric rings, we use the pure concentric method momentarily,
172  // but that creates too many unneccesarry faces, when only two
173  // are needed to descibe the mesh, @todo investigate merging flag
174  auto facesMesh = detail::FacesHelper::cylindricalFaceMesh(vertices, true);
175  faces = facesMesh.first;
176  triangularMesh = facesMesh.second;
177  }
178  } else {
179  throw std::domain_error(
180  "Polyhedron repr of boundless surface not possible.");
181  }
182  return Polyhedron(vertices, faces, triangularMesh, exactPolyhedron);
183 }