ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ConeSurface.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ConeSurface.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 
9 #include <cassert>
10 #include <cmath>
11 #include <iomanip>
12 #include <iostream>
13 #include <utility>
14 
20 
23 
25  : GeometryObject(), Surface(other), m_bounds(other.m_bounds) {}
26 
28  const ConeSurface& other,
29  const Transform3D& transf)
30  : GeometryObject(),
31  Surface(gctx, other, transf),
32  m_bounds(other.m_bounds) {}
33 
34 Acts::ConeSurface::ConeSurface(std::shared_ptr<const Transform3D> htrans,
35  double alpha, bool symmetric)
36  : GeometryObject(),
37  Surface(std::move(htrans)),
38  m_bounds(std::make_shared<const ConeBounds>(alpha, symmetric)) {}
39 
40 Acts::ConeSurface::ConeSurface(std::shared_ptr<const Transform3D> htrans,
41  double alpha, double zmin, double zmax,
42  double halfPhi)
43  : GeometryObject(),
44  Surface(std::move(htrans)),
45  m_bounds(std::make_shared<const ConeBounds>(alpha, zmin, zmax, halfPhi)) {
46 }
47 
48 Acts::ConeSurface::ConeSurface(std::shared_ptr<const Transform3D> htrans,
49  const std::shared_ptr<const ConeBounds>& cbounds)
50  : GeometryObject(), Surface(std::move(htrans)), m_bounds(cbounds) {
51  throw_assert(cbounds, "ConeBounds must not be nullptr");
52 }
53 
55  const GeometryContext& gctx, Acts::BinningValue bValue) const {
56  const Vector3D& sfCenter = center(gctx);
57 
58  // special binning type for R-type methods
59  if (bValue == Acts::binR || bValue == Acts::binRPhi) {
60  return Vector3D(sfCenter.x() + bounds().r(sfCenter.z()), sfCenter.y(),
61  sfCenter.z());
62  }
63  // give the center as default for all of these binning types
64  // binX, binY, binZ, binR, binPhi, binRPhi, binH, binEta
65  return sfCenter;
66 }
67 
69  return Surface::Cone;
70 }
71 
73  if (this != &other) {
74  Surface::operator=(other);
75  m_bounds = other.m_bounds;
76  }
77  return *this;
78 }
79 
81  const GeometryContext& gctx) const {
82  return std::move(transform(gctx).matrix().block<3, 1>(0, 2));
83 }
84 
86  const GeometryContext& gctx, const Vector3D& position,
87  const Vector3D& /*unused*/) const {
88  RotationMatrix3D mFrame;
89  // construct the measurement frame
90  // measured Y is the local z axis
91  Vector3D measY = rotSymmetryAxis(gctx);
92  // measured z is the position transverse normalized
93  Vector3D measDepth = Vector3D(position.x(), position.y(), 0.).normalized();
94  // measured X is what comoes out of it
95  Acts::Vector3D measX(measY.cross(measDepth).normalized());
96  // the columnes
97  mFrame.col(0) = measX;
98  mFrame.col(1) = measY;
99  mFrame.col(2) = measDepth;
100  // return the rotation matrix
102  // return it
103  return mFrame;
104 }
105 
107  const Vector2D& lposition,
108  const Vector3D& /*unused*/,
109  Vector3D& position) const {
110  // create the position in the local 3d frame
111  double r = lposition[Acts::eLOC_Z] * bounds().tanAlpha();
112  double phi = lposition[Acts::eLOC_RPHI] / r;
113  Vector3D loc3Dframe(r * cos(phi), r * sin(phi), lposition[Acts::eLOC_Z]);
114  // transport it to the globalframe
115  if (m_transform) {
116  position = transform(gctx) * loc3Dframe;
117  }
118 }
119 
121  const Vector3D& position,
122  const Vector3D& /*unused*/,
123  Vector2D& lposition) const {
124  Vector3D loc3Dframe =
125  m_transform ? (transform(gctx).inverse() * position) : position;
126  double r = loc3Dframe.z() * bounds().tanAlpha();
127  lposition =
128  Vector2D(r * atan2(loc3Dframe.y(), loc3Dframe.x()), loc3Dframe.z());
129  // now decide on the quility of the transformation
130  double inttol = r * 0.0001;
131  inttol = (inttol < 0.01) ? 0.01 : 0.01; // ?
132  return ((std::abs(perp(loc3Dframe) - r) > inttol) ? false : true);
133 }
134 
136  const Vector3D& position,
137  const Vector3D& direction) const {
138  // (cos phi cos alpha, sin phi cos alpha, sgn z sin alpha)
139  Vector3D posLocal =
140  m_transform ? transform(gctx).inverse() * position : position;
141  double phi = VectorHelpers::phi(posLocal);
142  double sgn = posLocal.z() > 0. ? -1. : +1.;
143  double cosAlpha = std::cos(bounds().get(ConeBounds::eAlpha));
144  double sinAlpha = std::sin(bounds().get(ConeBounds::eAlpha));
145  Vector3D normalC(cos(phi) * cosAlpha, sin(phi) * cosAlpha, sgn * sinAlpha);
146  if (m_transform) {
147  normalC = transform(gctx) * normalC;
148  }
149  // Back to the global frame
150  double cAlpha = normalC.dot(direction);
151  return std::abs(1. / cAlpha);
152 }
153 
154 std::string Acts::ConeSurface::name() const {
155  return "Acts::ConeSurface";
156 }
157 
159  const GeometryContext& gctx, const Acts::Vector2D& lposition) const {
160  // (cos phi cos alpha, sin phi cos alpha, sgn z sin alpha)
161  double phi =
162  lposition[Acts::eLOC_RPHI] / (bounds().r(lposition[Acts::eLOC_Z])),
163  sgn = lposition[Acts::eLOC_Z] > 0 ? -1. : +1.;
164  double cosAlpha = std::cos(bounds().get(ConeBounds::eAlpha));
165  double sinAlpha = std::sin(bounds().get(ConeBounds::eAlpha));
166  Vector3D localNormal(cos(phi) * cosAlpha, sin(phi) * cosAlpha,
167  sgn * sinAlpha);
168  return m_transform ? Vector3D(transform(gctx).linear() * localNormal)
169  : localNormal;
170 }
171 
173  const GeometryContext& gctx, const Acts::Vector3D& position) const {
174  // get it into the cylinder frame if needed
175  // @todo respect opening angle
176  Vector3D pos3D = position;
177  if (m_transform || (m_associatedDetElement != nullptr)) {
178  pos3D = transform(gctx).inverse() * position;
179  pos3D.z() = 0;
180  }
181  return pos3D.normalized();
182 }
183 
185  // is safe because no constructor w/o bounds exists
186  return (*m_bounds.get());
187 }
188 
190  const GeometryContext& gctx, size_t lseg) const {
191  // Prepare vertices and faces
192  std::vector<Vector3D> vertices;
193  std::vector<Polyhedron::FaceType> faces;
194  std::vector<Polyhedron::FaceType> triangularMesh;
195 
196  double minZ = bounds().get(ConeBounds::eMinZ);
197  double maxZ = bounds().get(ConeBounds::eMaxZ);
198 
199  if (minZ == -std::numeric_limits<double>::infinity() or
200  maxZ == std::numeric_limits<double>::infinity()) {
201  throw std::domain_error(
202  "Polyhedron repr of boundless surface not possible");
203  }
204 
205  auto ctransform = transform(gctx);
206 
207  // The tip - created only once and only, if the it's not a cut-off cone
208  bool tipExists = false;
209  if (minZ * maxZ <= s_onSurfaceTolerance) {
210  vertices.push_back(ctransform * Vector3D(0., 0., 0.));
211  tipExists = true;
212  }
213 
214  // Cone parameters
215  double hPhiSec = bounds().get(ConeBounds::eHalfPhiSector);
216  double avgPhi = bounds().get(ConeBounds::eAveragePhi);
217  bool fullCone = (hPhiSec == M_PI);
218 
219  // Get the phi segments from the helper
220  auto phiSegs = fullCone ? detail::VerticesHelper::phiSegments()
222  avgPhi - hPhiSec, avgPhi + hPhiSec, {avgPhi});
223 
224  // Negative cone if exists
225  std::vector<double> coneSides;
226  if (std::abs(minZ) > s_onSurfaceTolerance) {
227  coneSides.push_back(minZ);
228  }
229  if (std::abs(maxZ) > s_onSurfaceTolerance) {
230  coneSides.push_back(maxZ);
231  }
232  for (auto& z : coneSides) {
233  // Remember the first vertex
234  size_t firstIv = vertices.size();
235  // Radius and z offset
236  double r = std::abs(z) * bounds().tanAlpha();
237  Vector3D zoffset(0., 0., z);
238  for (unsigned int iseg = 0; iseg < phiSegs.size() - 1; ++iseg) {
239  int addon = (iseg == phiSegs.size() - 2 and not fullCone) ? 1 : 0;
240  detail::VerticesHelper::createSegment(vertices, {r, r}, phiSegs[iseg],
241  phiSegs[iseg + 1], lseg, addon,
242  zoffset, ctransform);
243  }
244  // Create the faces
245  if (tipExists) {
246  for (size_t iv = firstIv + 2; iv < vertices.size() + 1; ++iv) {
247  size_t one = 0, two = iv - 1, three = iv - 2;
248  if (z < 0.) {
249  std::swap(two, three);
250  }
251  faces.push_back({one, two, three});
252  }
253  // Complete cone if necessary
254  if (fullCone) {
255  if (z > 0.) {
256  faces.push_back({0, firstIv, vertices.size() - 1});
257  } else {
258  faces.push_back({0, vertices.size() - 1, firstIv});
259  }
260  }
261  }
262  }
263  // if no tip exists, connect the two bows
264  if (tipExists) {
265  triangularMesh = faces;
266  } else {
267  auto facesMesh =
268  detail::FacesHelper::cylindricalFaceMesh(vertices, fullCone);
269  faces = facesMesh.first;
270  triangularMesh = facesMesh.second;
271  }
272  return Polyhedron(vertices, faces, triangularMesh);
273 }