ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ProtoLayer.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ProtoLayer.cpp
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 
9 #include <cmath>
10 
11 #include <algorithm>
18 
21 
22 namespace Acts {
23 
25  const std::vector<const Surface*>& surfaces) {
26  measure(gctx, surfaces);
27 }
28 
30  const GeometryContext& gctx,
31  const std::vector<std::shared_ptr<const Surface>>& surfaces) {
32  measure(gctx, unpack_shared_vector(surfaces));
33 }
34 
36  const Vector3D& pos2) const {
37  Vector2D p1(pos1.x(), pos1.y());
38  Vector2D p2(pos2.x(), pos2.y());
39 
40  Vector2D O(0, 0);
41  Vector2D p1p2 = (p2 - p1);
42  double L = p1p2.norm();
43  Vector2D p1O = (O - p1);
44 
45  // don't do division if L is very small
46  if (L < 1e-7) {
48  }
49  double f = p1p2.dot(p1O) / L;
50 
51  // clamp to [0, |p1p2|]
52  f = std::min(L, std::max(0., f));
53 
54  Vector2D closest = f * p1p2.normalized() + p1;
55  double dist = (closest - O).norm();
56 
57  return dist;
58 }
59 
60 std::ostream& ProtoLayer::toStream(std::ostream& sl) const {
61  sl << "ProtoLayer with dimensions (min/max)" << std::endl;
62  sl << " - r : " << minR << " - " << envR.first << " / " << maxR << " + "
63  << envR.second << std::endl;
64  sl << " - z : " << minZ << " - " << envZ.first << " / " << maxZ << " + "
65  << envZ.second << std::endl;
66  sl << " - phi : " << minPhi << " - " << envPhi.first << " / " << maxPhi
67  << " + " << envPhi.second << std::endl;
68 
69  return sl;
70 }
71 
73  const std::vector<const Surface*>& surfaces) {
75  maxR = std::numeric_limits<double>::lowest();
77  maxX = std::numeric_limits<double>::lowest();
79  maxY = std::numeric_limits<double>::lowest();
81  maxZ = std::numeric_limits<double>::lowest();
83  maxPhi = std::numeric_limits<double>::lowest();
84 
85  for (const auto& sf : surfaces) {
86  // if the associated detector element exists, use
87  // it for thickness
88  double thickness = 0;
89  const DetectorElementBase* element = sf->associatedDetectorElement();
90  if (element != nullptr) {
91  thickness = element->thickness();
92  }
93 
94  // check the shape
95  const PlanarBounds* pBounds =
96  dynamic_cast<const PlanarBounds*>(&(sf->bounds()));
97 
98  const CylinderSurface* cylSurface =
99  dynamic_cast<const CylinderSurface*>(sf);
100 
101  if (pBounds != nullptr) {
102  const auto& sTransform = sf->transform(gctx);
103 
104  // get the vertices
105  std::vector<Vector2D> vertices = pBounds->vertices();
106  size_t nVertices = vertices.size();
107  // loop over the two sides of the module
108  // we only need to run once if no element i.e. no thickness
109  for (int side = 0; side < (element != nullptr ? 2 : 1); ++side) {
110  // loop over the vertex combinations
111  for (size_t iv = 0; iv < nVertices; ++iv) {
112  size_t ivp = iv != 0u ? iv - 1 : nVertices - 1;
113  // thickness
114  double locz = side != 0 ? 0.5 * thickness : -0.5 * thickness;
115  // p1 & p2 vectors
116  Vector3D p2(sTransform *
117  Vector3D(vertices.at(iv).x(), vertices.at(iv).y(), locz));
118  Vector3D p1(sTransform * Vector3D(vertices.at(ivp).x(),
119  vertices.at(ivp).y(), locz));
120 
121  maxX = std::max(maxX, p2.x());
122  minX = std::min(minX, p2.x());
123 
124  maxY = std::max(maxY, p2.y());
125  minY = std::min(minY, p2.y());
126 
127  maxZ = std::max(maxZ, p2.z());
128  minZ = std::min(minZ, p2.z());
129 
130  maxR = std::max(maxR, perp(p2));
131  minR = std::min(minR, radialDistance(p1, p2));
132 
133  maxPhi = std::max(maxPhi, phi(p2));
134  minPhi = std::min(minPhi, phi(p2));
135  }
136  }
137  } else if (cylSurface != nullptr) {
138  // this is an explicit cast and if right now.
139  // It should work with all Polyhedrons
140  // @TODO: Remove the cast and if as soon as ::polyhedronRepresentation()
141  // makes it into the Surface base class
142  // The envelopes might need special treatments though
143 
144  Polyhedron ph = cylSurface->polyhedronRepresentation(gctx, 1);
145  // evaluate at all vertices
146  for (const auto& vtx : ph.vertices) {
147  maxX = std::max(maxX, vtx.x());
148  minX = std::min(minX, vtx.x());
149 
150  maxY = std::max(maxY, vtx.y());
151  minY = std::min(minY, vtx.y());
152 
153  maxZ = std::max(maxZ, vtx.z());
154  minZ = std::min(minZ, vtx.z());
155 
156  maxR = std::max(maxR, perp(vtx));
157 
158  maxPhi = std::max(maxPhi, phi(vtx));
159  minPhi = std::min(minPhi, phi(vtx));
160  }
161 
162  // trace all face connections to possibly catch min-r approach
163  for (const auto& face : ph.faces) {
164  for (size_t i = 0; i < face.size(); i++) {
165  Vector3D p1 = ph.vertices.at(face.at(i));
166  Vector3D p2 = ph.vertices.at(face.at((i + 1) % face.size()));
167  minR = std::min(minR, radialDistance(p1, p2));
168  }
169  }
170 
171  // set envelopes to half radius
172  double cylBoundsR = cylSurface->bounds().get(CylinderBounds::eR);
173  double env = cylBoundsR / 2.;
174  envX = {env, env};
175  envY = {env, env};
176  envZ = {env, env};
177  envR = {env, env};
178 
179  // evaluate impact of r shift on phi
180  double cylPosR = perp(cylSurface->center(gctx));
181  double dPhi = std::atan((cylBoundsR + env) / cylPosR) -
182  std::atan(cylBoundsR / cylPosR);
183 
184  // use this as phi envelope
185  envPhi = {dPhi, dPhi};
186 
187  } else {
188  const CylinderBounds* cBounds =
189  dynamic_cast<const CylinderBounds*>(&(sf->bounds()));
190 
191  const AnnulusBounds* aBounds =
192  dynamic_cast<const AnnulusBounds*>(&(sf->bounds()));
193 
194  if (cBounds != nullptr) {
195  double r = cBounds->get(CylinderBounds::eR);
196  double z = sf->center(gctx).z();
197  double hZ = cBounds->get(CylinderBounds::eHalfLengthZ);
198  double phi = cBounds->get(CylinderBounds::eAveragePhi);
199  double hPhi = cBounds->get(CylinderBounds::eHalfPhiSector);
200 
201  maxX = r;
202  minX = -r;
203 
204  maxY = r;
205  minY = -r;
206 
207  maxZ = z + hZ;
208  minZ = z - hZ;
209 
210  maxR = r;
211  minR = r;
212 
213  maxPhi = phi + hPhi;
214  minPhi = phi - hPhi;
215 
216  } else if (aBounds != nullptr) {
217  minR = aBounds->rMin();
218  maxR = aBounds->rMax();
219  double z = sf->center(gctx).z();
220 
221  maxX = maxR;
222  minX = -maxR;
223 
224  maxY = maxR;
225  minY = -maxR;
226 
227  maxZ = z + 0.5 * thickness;
228  minZ = z - 0.5 * thickness;
229 
230  maxPhi = aBounds->phiMin();
231  minPhi = aBounds->phiMax();
232 
233  } else {
234  throw std::domain_error(
235  "Not implemented yet for the given bounds type.");
236  }
237  }
238  }
239 }
240 
241 } // namespace Acts