ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Layer.ipp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Layer.ipp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2016-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 <limits>
10 
11 namespace Acts {
12 
13 inline const SurfaceArray* Layer::surfaceArray() const {
14  return m_surfaceArray.get();
15 }
16 
18  return const_cast<SurfaceArray*>(m_surfaceArray.get());
19 }
20 
21 inline double Layer::thickness() const {
22  return m_layerThickness;
23 }
24 
25 inline LayerType Layer::layerType() const {
26  return m_layerType;
27 }
28 
29 inline const TrackingVolume* Layer::trackingVolume() const {
30  return m_trackingVolume;
31 }
32 
33 inline void Layer::encloseTrackingVolume(const TrackingVolume& tvol) {
34  m_trackingVolume = &(tvol);
35 }
36 
38  return m_representingVolume.get();
39 }
40 
41 inline const Layer* Layer::nextLayer(const GeometryContext& /*gctx*/,
42  const Vector3D& position,
43  const Vector3D& direction) const {
44  // no binutility -> no chance to find out the direction
45  if (m_nextLayerUtility == nullptr) {
46  return nullptr;
47  }
48  return (m_nextLayerUtility->nextDirection(position, direction) < 0)
49  ? m_nextLayers.first
50  : m_nextLayers.second;
51 }
52 
53 inline bool Layer::resolve(bool resolveSensitive, bool resolveMaterial,
54  bool resolvePassive) const {
55  if (resolvePassive) {
56  return true;
57  }
58  if (resolveSensitive && m_surfaceArray) {
59  return true;
60  }
61  if (resolveMaterial &&
63  (surfaceRepresentation().surfaceMaterial() != nullptr))) {
64  return true;
65  }
66  return false;
67 }
68 
69 template <typename options_t>
70 std::vector<SurfaceIntersection> Layer::compatibleSurfaces(
71  const GeometryContext& gctx, const Vector3D& position,
72  const Vector3D& direction, const options_t& options) const {
73  // the list of valid intersection
74  std::vector<SurfaceIntersection> sIntersections;
75  // remember the surfaces for duplicate removal
76  std::map<const Surface*, bool> accepted;
77 
78  // fast exit - there is nothing to
79  if (!m_surfaceArray || !m_approachDescriptor || !options.navDir) {
80  return sIntersections;
81  }
82 
83  // reserve a few bins
84  sIntersections.reserve(20);
85 
86  // (0) End surface check
87  // @todo: - we might be able to skip this by use of options.pathLimit
88  // check if you have to stop at the endSurface
89  double pathLimit = options.pathLimit;
90  double overstepLimit = options.overstepLimit;
91  if (options.endObject) {
92  // intersect the end surface
93  // - it is the final one don't use the bounday check at all
94  SurfaceIntersection endInter = options.endObject->intersect(
95  gctx, position, options.navDir * direction, BoundaryCheck(true));
96  // non-valid intersection with the end surface provided at this layer
97  // indicates wrong direction or faulty setup
98  // -> do not return compatible surfaces since they may lead you on a wrong
99  // navigation path
100  if (endInter) {
101  pathLimit = endInter.intersection.pathLength;
102  } else {
103  return sIntersections;
104  }
105  } else {
106  // compatibleSurfaces() should only be called when on the layer,
107  // i.e. the maximum path limit is given by the layer thickness times
108  // path correction, we take a safety factor of 1.5
109  // -> this avoids punch through for cylinders
110  double pCorrection =
111  surfaceRepresentation().pathCorrection(gctx, position, direction);
112  pathLimit = 1.5 * thickness() * pCorrection * options.navDir;
113  }
114 
115  // lemma 0 : accept the surface
116  auto acceptSurface = [&options, &accepted](const Surface& sf,
117  bool sensitive = false) -> bool {
118  // check for duplicates
119  if (accepted.find(&sf) != accepted.end()) {
120  return false;
121  }
122  // surface is sensitive and you're asked to resolve
123  if (sensitive && options.resolveSensitive) {
124  return true;
125  }
126  // next option: it's a material surface and you want to have it
127  if (options.resolveMaterial && sf.surfaceMaterial()) {
128  return true;
129  }
130  // last option: resovle all
131  return options.resolvePassive;
132  };
133 
134  // lemma 1 : check and fill the surface
135  // [&sIntersections, &options, &parameters
136  auto processSurface = [&](const Surface& sf, bool sensitive = false) {
137  // veto if it's start or end surface
138  if (options.startObject == &sf || options.endObject == &sf) {
139  return;
140  }
141  // veto if it doesn't fit the prescription
142  if (!acceptSurface(sf, sensitive)) {
143  return;
144  }
145  // the surface intersection
147  gctx, position, options.navDir * direction, options.boundaryCheck);
148  // check if intersection is valid and pathLimit has not been exceeded
149  double sifPath = sfi.intersection.pathLength;
150  // check the maximum path length
151  if (sfi && sifPath > overstepLimit &&
152  sifPath * sifPath <= pathLimit * pathLimit) {
153  // Now put the right sign on it
154  sfi.intersection.pathLength *= std::copysign(1., options.navDir);
155  sIntersections.push_back(sfi);
156  accepted[&sf] = true;
157  }
158  return;
159  };
160 
161  // (A) approach descriptor section
162  //
163  // the approach surfaces are in principle always testSurfaces
164  // - the surface on approach is excluded via the veto
165  // - the surfaces are only collected if needed
166  if (m_approachDescriptor &&
167  (options.resolveMaterial || options.resolvePassive)) {
168  // the approach surfaces
169  const std::vector<const Surface*>& approachSurfaces =
170  m_approachDescriptor->containedSurfaces();
171  // we loop through and veto
172  // - if the approach surface is the parameter surface
173  // - if the surface is not compatible with the collect
174  for (auto& aSurface : approachSurfaces) {
175  processSurface(*aSurface);
176  }
177  }
178 
179  // (B) sensitive surface section
180  //
181  // check the sensitive surfaces if you have some
182  if (m_surfaceArray && (options.resolveMaterial || options.resolvePassive ||
183  options.resolveSensitive)) {
184  // get the canditates
185  const std::vector<const Surface*>& sensitiveSurfaces =
186  m_surfaceArray->neighbors(position);
187  // loop through and veto
188  // - if the approach surface is the parameter surface
189  // - if the surface is not compatible with the type(s) that are collected
190  for (auto& sSurface : sensitiveSurfaces) {
191  processSurface(*sSurface, true);
192  }
193  }
194 
195  // (C) representing surface section
196  //
197  // the layer surface itself is a testSurface
198  const Surface* layerSurface = &surfaceRepresentation();
199  processSurface(*layerSurface);
200 
201  // sort according to the path length
202  if (options.navDir == forward) {
203  std::sort(sIntersections.begin(), sIntersections.end());
204  } else {
205  std::sort(sIntersections.begin(), sIntersections.end(), std::greater<>());
206  }
207 
208  return sIntersections;
209 }
210 
211 template <typename options_t>
213  const GeometryContext& gctx, const Vector3D& position,
214  const Vector3D& direction, const options_t& options) const {
215  // resolve directive based by options
216  // - options.resolvePassive is on -> always
217  // - options.resolveSensitive is on -> always
218  // - options.resolveMaterial is on
219  // && either sensitive or approach surfaces have material
220  bool resolvePS = options.resolveSensitive || options.resolvePassive;
221  bool resolveMS = options.resolveMaterial &&
224 
225  // The signed direction: solution (except overstepping) is positive
226  auto sDirection = options.navDir * direction;
227 
228  // The Limits: current path & overstepping
229  double pLimit = options.pathLimit;
230  double oLimit = options.overstepLimit;
231 
232  // Helper function to test intersection
233  auto checkIntersection =
234  [&](SurfaceIntersection& sIntersection) -> SurfaceIntersection {
235  // Avoid doing anything if that's a rotten apple already
236  if (!sIntersection) {
237  return sIntersection;
238  }
239  double cLimit = sIntersection.intersection.pathLength;
240  // Check if you are within the limit
241  bool withinLimit =
242  (cLimit > oLimit and
243  cLimit * cLimit <= pLimit * pLimit + s_onSurfaceTolerance);
244  if (withinLimit) {
245  // Set the right sign to the path length
246  sIntersection.intersection.pathLength *=
247  std::copysign(1., options.navDir);
248  return sIntersection;
249  } else if (sIntersection.alternative.status >=
250  Intersection::Status::reachable) {
251  // Test the alternative
252  cLimit = sIntersection.alternative.pathLength;
253  withinLimit = (cLimit > oLimit and
254  cLimit * cLimit <= pLimit * pLimit + s_onSurfaceTolerance);
255  if (sIntersection.alternative and withinLimit) {
256  // Set the right sign for the path length
257  sIntersection.alternative.pathLength *=
258  std::copysign(1., options.navDir);
259  return SurfaceIntersection(sIntersection.alternative,
260  sIntersection.object);
261  }
262  }
263  // Return an invalid one
264  return SurfaceIntersection();
265  };
266 
267  // Approach descriptor present and resolving is necessary
268  if (m_approachDescriptor && (resolvePS || resolveMS)) {
269  SurfaceIntersection aSurface = m_approachDescriptor->approachSurface(
270  gctx, position, sDirection, options.boundaryCheck);
271  return checkIntersection(aSurface);
272  }
273 
274  // Intersect and check the representing surface
275  const Surface& rSurface = surfaceRepresentation();
276  auto sIntersection =
277  rSurface.intersect(gctx, position, sDirection, options.boundaryCheck);
278  return checkIntersection(sIntersection);
279 }
280 
282  const Vector3D& position,
283  const BoundaryCheck& bcheck) const {
284  if (m_representingVolume != nullptr) {
285  return m_representingVolume->inside(position);
286  }
287  return (surfaceRepresentation())
288  .isOnSurface(gctx, position, s_origin, bcheck);
289 }
290 
291 } // namespace Acts