ATLAS Offline Software
CylinderVolumeBounds.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 // CylinderVolumeBounds.cxx, (c) ATLAS Detector software
8 
9 // Trk
12 // TrkSurfaces
15 #include "TrkSurfaces/DiscBounds.h"
19 // Gaudi
20 #include "GaudiKernel/MsgStream.h"
21 #include "GaudiKernel/SystemOfUnits.h"
22 
23 // STD
24 #include <cmath>
25 #include <iostream>
26 
28  10e-2 * Gaudi::Units::mm;
29 
31  : VolumeBounds()
32  , m_innerRadius(0.)
33  , m_outerRadius(0.)
34  , m_halfPhiSector(0.)
35  , m_halfZ(0.)
36  , m_boundaryAccessors()
37 {}
38 
40  : VolumeBounds()
41  , m_innerRadius(0.)
42  , m_outerRadius(std::abs(radius))
43  , m_halfPhiSector(M_PI)
44  , m_halfZ(std::abs(halez))
45  , m_boundaryAccessors()
46 {}
47 
49  double rinner,
50  double router,
51  double halez)
52  : VolumeBounds()
53  , m_innerRadius(std::abs(rinner))
54  , m_outerRadius(std::abs(router))
55  , m_halfPhiSector(M_PI)
56  , m_halfZ(std::abs(halez))
57  , m_boundaryAccessors()
58 {}
59 
61  double rinner,
62  double router,
63  double haphi,
64  double halez)
65  : VolumeBounds()
66  , m_innerRadius(std::abs(rinner))
67  , m_outerRadius(std::abs(router))
68  , m_halfPhiSector(haphi)
69  , m_halfZ(std::abs(halez))
70  , m_boundaryAccessors()
71 {}
72 
74  const Trk::CylinderVolumeBounds& cylbo)
75  : VolumeBounds()
76  , m_innerRadius(cylbo.m_innerRadius)
77  , m_outerRadius(cylbo.m_outerRadius)
78  , m_halfPhiSector(cylbo.m_halfPhiSector)
79  , m_halfZ(cylbo.m_halfZ)
80  , m_boundaryAccessors()
81 {}
82 
84 
87 {
88  if (this != &cylbo) {
89  m_innerRadius = cylbo.m_innerRadius;
90  m_outerRadius = cylbo.m_outerRadius;
91  m_halfPhiSector = cylbo.m_halfPhiSector;
92  m_halfZ = cylbo.m_halfZ;
93  }
94  return *this;
95 }
96 
97 const std::vector<const Trk::Surface*>*
100 {
101  std::vector<const Trk::Surface*>* retsf =
102  new std::vector<const Trk::Surface*>;
103  // memory optimisation --- reserve the maximum
104  retsf->reserve(6);
105 
106  // check if the transform is approximatively the identity
107  bool isConcentric = transform.isApprox(Amg::Transform3D::Identity());
108 
109  Amg::RotationMatrix3D discRot = transform.linear();
110  Amg::Vector3D cylCenter(transform.translation());
111 
112  // bottom Disc (negative z)
113  Amg::RotationMatrix3D bottomDiscRot;
114  bottomDiscRot.col(0) = discRot.col(1);
115  bottomDiscRot.col(1) = discRot.col(0);
116  bottomDiscRot.col(2) = -discRot.col(2);
117  retsf->push_back(new Trk::DiscSurface(
119  transform * Amg::AngleAxis3D(M_PI, Amg::Vector3D(1., 0., 0.)) *
120  Amg::Translation3D(Amg::Vector3D(0., 0., halflengthZ()))),
121  bottomDiscBounds()));
122  // top Disc (positive z)
123  retsf->push_back(new Trk::DiscSurface(
125  topDiscBounds()));
126  // outer Cylinder
127  if (!isConcentric)
128  retsf->push_back(new Trk::CylinderSurface(
129  Amg::Transform3D(transform), outerCylinderBounds()));
130  else
131  retsf->push_back(new Trk::CylinderSurface(outerCylinderBounds()));
132 
133  // innermost Cylinder
134  if (innerRadius() > s_numericalStable) {
135  if (!isConcentric)
136  retsf->push_back(new Trk::CylinderSurface(
137  Amg::Transform3D(transform), innerCylinderBounds()));
138  else
139  retsf->push_back(new Trk::CylinderSurface(innerCylinderBounds()));
140  }
141 
142  if (std::abs(halfPhiSector() - M_PI) > s_numericalStable) {
143  // sectorPlane 1 (negative phi)
144  retsf->push_back(new Trk::PlaneSurface(
146  transform *
147  Amg::AngleAxis3D(-halfPhiSector(), Amg::Vector3D(0., 0., 1.)) *
148  Amg::Translation3D(Amg::Vector3D(mediumRadius(), 0., 0.)) *
149  Amg::AngleAxis3D(M_PI / 2, Amg::Vector3D(1., 0., 0.))),
150  sectorPlaneBounds()));
151  // sectorPlane 2 (positive phi)
152  retsf->push_back(new Trk::PlaneSurface(
154  transform *
155  Amg::AngleAxis3D(halfPhiSector(), Amg::Vector3D(0., 0., 1.)) *
156  Amg::Translation3D(Amg::Vector3D(mediumRadius(), 0., 0.)) *
157  Amg::AngleAxis3D(-M_PI / 2, Amg::Vector3D(1., 0., 0.))),
158  sectorPlaneBounds()));
159  }
160  return retsf;
161 }
162 
165  const Amg::Vector3D& gp,
166  const Amg::Vector3D& dir,
167  bool) const
168 {
169  // the tube case - most likely
170  if (
171  m_innerRadius > s_numericalStable &&
172  std::abs(m_halfPhiSector - M_PI) < s_numericalStable) {
173  // prepare the data
174  double posZ = gp.z();
175  double posR = gp.perp();
176  // difference Vector
177  Amg::Vector3D diff(gp + dir);
178  // differences
179  double deltaZ = diff.z() - posZ;
180  double deltaR = diff.perp() - posR;
181 
182  // the isOnSurface cases + switchers (that change with the cases)
183  bool isOnFace = false;
184  bool intersectionIndicator = (deltaR > 0.);
185  bool choiceIndicator = false;
186 
187  // on surface or look-a-likes
188  // on zMin or slightly outside
189  if (
190  std::abs(posZ + m_halfZ) < s_numericalStable ||
191  (posZ < (-m_halfZ) && deltaZ > 0.)) {
192  isOnFace = true;
193  } else if (
194  std::abs(posZ - m_halfZ) < s_numericalStable ||
195  (posZ > m_halfZ && deltaZ < 0.)) {
196  // on zMax or slighly outside
197  isOnFace = true;
198  } else if (
199  std::abs(posR - m_innerRadius) < s_numericalStable ||
200  (posR < m_innerRadius && deltaR > 0.)) {
201  // on innerRadius or slightly outside
202  isOnFace = true;
203  choiceIndicator =
204  (deltaZ > 0.); // the side choice indicator <========== WRONG ==========
205  } else if (
206  std::abs(posR - m_outerRadius) < s_numericalStable ||
207  (posR > m_outerRadius && deltaR < 0.)) {
208  // on outRadius or slightly outside
209  isOnFace = true;
210  choiceIndicator =
211  (deltaZ > 0.); // the side choice indicator <========== WRONG ==========
212  }
213 
214  // the onSurface case
215  // =================================================================================
216  if (isOnFace) {
217  if (intersectionIndicator) {
218  // intersect the Rmax / with floatint point exception check
219  Trk::CylinderIntersector intersectRmax(
220  posR, posZ, deltaR != 0 ? deltaZ / deltaR : 0, m_outerRadius);
221  double zOfIntersect = intersectRmax.yOfX;
222  // now check if the intersect is inside m_halfZ
223  if (std::abs(zOfIntersect) <= m_halfZ)
224  return {(choiceIndicator || zOfIntersect > 0.)
225  ? m_boundaryAccessors.tubeAccessor(
227  : m_boundaryAccessors.tubeAccessor(
229  // if the intersect is outside
230  return {
231  (choiceIndicator || zOfIntersect > 0.)
232  ? m_boundaryAccessors.tubeAccessor(Trk::TubeZincreaseRincrease)
233  : m_boundaryAccessors.tubeAccessor(
235  }
236  // intersect the Rmin
237  Trk::CylinderIntersector intersectRmin(
238  posR, posZ, deltaR != 0 ? deltaZ / deltaR : 0, m_innerRadius);
239  double zOfIntersect = intersectRmin.yOfX;
240  // now check if the intersect is inside m_halfZ
241  if (std::abs(zOfIntersect) <= m_halfZ)
242  return {
243  (choiceIndicator || zOfIntersect > 0.)
244  ? m_boundaryAccessors.tubeAccessor(Trk::TubeRdecreaseZincrease)
245  : m_boundaryAccessors.tubeAccessor(
247  // if the intersect is outside
248  return {
249  (choiceIndicator || zOfIntersect > 0.)
250  ? m_boundaryAccessors.tubeAccessor(Trk::TubeZincreaseRdecrease)
251  : m_boundaryAccessors.tubeAccessor(Trk::TubeZdecreaseRdecrease)};
252  }
253  // =================================================================================================
254 
255  // ======================= the inside/outside part remains
256  // =========================================
257  // (a) outside cases
258  if (posR < m_innerRadius && deltaR < 0.)
259  return {m_boundaryAccessors.tubeAccessor(Trk::TubeOutsideRminRdecrease)};
260  if (posR > m_outerRadius && deltaR > 0.)
261  return {m_boundaryAccessors.tubeAccessor(Trk::TubeOutsideRmaxRincrease)};
262  if (posZ < -m_halfZ && deltaZ < 0.)
263  return {m_boundaryAccessors.tubeAccessor(Trk::TubeOutsideZminZdecrease)};
264  if (posZ > m_halfZ && deltaZ > 0.)
265  return {m_boundaryAccessors.tubeAccessor(Trk::TubeOutsideZmaxZincrease)};
266  // (b) inside cases
267  // the increase R case
268  if (deltaR > 0.) {
269  // solve the linear equation for the outer Radius - with floating point
270  // exception check
271  Trk::CylinderIntersector intersectRmax(
272  posR, posZ, deltaR != 0 ? deltaZ / deltaR : 0, m_outerRadius);
273  double zOfIntersect = intersectRmax.yOfX;
274 
275  if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect > 0.)
276  return {m_boundaryAccessors.tubeAccessor(Trk::TubeRincreaseZincrease)};
277  if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect < 0.)
278  return {m_boundaryAccessors.tubeAccessor(Trk::TubeRincreaseZdecrease)};
279  if (std::abs(zOfIntersect) > m_halfZ && zOfIntersect < 0.)
280  return {m_boundaryAccessors.tubeAccessor(Trk::TubeZdecreaseRincrease)};
281  if (std::abs(zOfIntersect) > m_halfZ && zOfIntersect > 0.)
282  return {m_boundaryAccessors.tubeAccessor(Trk::TubeZincreaseRincrease)};
283 
284  } else {
285  // solve the linear equation for the inner Radius with floating point
286  // exceptin check
287  Trk::CylinderIntersector intersectRmin(
288  posR, posZ, deltaR != 0 ? deltaZ / deltaR : 0, m_innerRadius);
289  double zOfIntersect = intersectRmin.yOfX;
290 
291  if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect > 0.)
292  return {m_boundaryAccessors.tubeAccessor(Trk::TubeRdecreaseZincrease)};
293  if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect < 0.)
294  return {m_boundaryAccessors.tubeAccessor(Trk::TubeRdecreaseZdecrease)};
295  if (std::abs(zOfIntersect) > m_halfZ && zOfIntersect > 0.)
296  return {m_boundaryAccessors.tubeAccessor(Trk::TubeZincreaseRdecrease)};
297  return {m_boundaryAccessors.tubeAccessor(Trk::TubeZdecreaseRdecrease)};
298  }
299  }
300  // the cylinder case
301  if (
302  m_innerRadius < s_numericalStable &&
303  std::abs(m_halfPhiSector - M_PI) < s_numericalStable) {
304 
305  // ----------------------------- z / r information
306  double posZ = gp.z();
307  double posR = gp.perp();
308 
309  // is on R case
310  bool isOnCylinder = (std::abs(posR - m_outerRadius) < s_numericalStable);
311 
312  // difference Vector
313  Amg::Vector3D diff(gp + dir);
314  // differences
315  double deltaZ = diff.z() - posZ;
316  double deltaR = diff.perp() - posR;
317  // take the sign of the intersect
318  int radiusSign = deltaR > 0. ? 1 : -1;
319 
320  // solve the linear equation for the cylinder Radius / with floating point
321  // exceptin check
322  Trk::CylinderIntersector intersectR(
323  posR,
324  posZ,
325  deltaR != 0 ? deltaZ / deltaR : 0,
326  radiusSign * m_outerRadius);
327 
328  // the intersection point - a little trick for the OnFace cases
329  double zOfIntersect = intersectR.yOfX;
330  // check if intersection exists
331  bool intersectsCylinder =
332  !isOnCylinder ? (zOfIntersect * zOfIntersect <= m_halfZ * m_halfZ)
333  : false;
334 
335  // return the cases for going through the cylinder
336  if (intersectsCylinder && zOfIntersect > 0.)
337  return {m_boundaryAccessors.cylinderAccessor(Trk::CylinderZincrease)};
338  if (intersectsCylinder && zOfIntersect <= 0.)
339  return {m_boundaryAccessors.cylinderAccessor(Trk::CylinderZdecrease)};
340  if (deltaZ > 0.)
341  return {m_boundaryAccessors.cylinderAccessor(Trk::CylinderPositiveFace)};
342  return {m_boundaryAccessors.cylinderAccessor(Trk::CylinderNegativeFace)};
343  }
344  // the sectoral cylinder case
345  if (m_innerRadius != 0. && std::abs(m_halfPhiSector - M_PI) > 10e-3)
346  return {m_boundaryAccessors.sectoralCylinderAccessor(
348  // it remains the sectoral tube case
349  return {m_boundaryAccessors.sectoralTubeAccessor(Trk::StandardSectoralTube)};
350 }
351 
354 {
355  return new Trk::CylinderBounds(m_innerRadius, m_halfPhiSector, m_halfZ);
356 }
357 
360 {
361  return new Trk::CylinderBounds(m_outerRadius, m_halfPhiSector, m_halfZ);
362 }
363 
366 {
367  return new Trk::DiscBounds(m_innerRadius, m_outerRadius, m_halfPhiSector);
368 }
369 
372 {
373  return new Trk::RectangleBounds(
374  0.5 * (m_outerRadius - m_innerRadius), m_halfZ);
375 }
376 
377 // ostream operator overload
378 
379 MsgStream&
381 {
382  std::stringstream temp_sl;
383  temp_sl << std::setiosflags(std::ios::fixed);
384  temp_sl << std::setprecision(2);
385  temp_sl << "Trk::CylinderVolumeBounds: (rMin, rMax, halfPhi, halfZ) = ";
386  temp_sl << m_innerRadius << ", " << m_outerRadius << ", " << m_halfPhiSector
387  << ", " << m_halfZ;
388  sl << temp_sl.str();
389  return sl;
390 }
391 
392 std::ostream&
393 Trk::CylinderVolumeBounds::dump(std::ostream& sl) const
394 {
395  std::stringstream temp_sl;
396  temp_sl << std::setiosflags(std::ios::fixed);
397  temp_sl << std::setprecision(2);
398  temp_sl << "Trk::CylinderVolumeBounds: (rMin, rMax, halfPhi, halfZ) = ";
399  temp_sl << m_innerRadius << ", " << m_outerRadius << ", " << m_halfPhiSector
400  << ", " << m_halfZ;
401  sl << temp_sl.str();
402  return sl;
403 }
404 
Trk::CylinderVolumeBounds::~CylinderVolumeBounds
virtual ~CylinderVolumeBounds()
Destructor.
Trk::TubeRdecreaseZdecrease
@ TubeRdecreaseZdecrease
Accessor type [ 3,0,1,2 ].
Definition: CylinderVolumeBoundaryAccessors.h:33
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
Trk::RectangleBounds
Definition: RectangleBounds.h:38
Trk::TubeOutsideRmaxRincrease
@ TubeOutsideRmaxRincrease
Accessor type [ 2,1,0,3 ] - inverse case.
Definition: CylinderVolumeBoundaryAccessors.h:37
DiscBounds.h
RectangleBounds.h
Trk::TubeZdecreaseRdecrease
@ TubeZdecreaseRdecrease
Accessor type [ 0,3,1,2 ].
Definition: CylinderVolumeBoundaryAccessors.h:35
CylinderIntersector.h
Trk::CylinderVolumeBounds::m_halfZ
double m_halfZ
Definition: CylinderVolumeBounds.h:160
M_PI
#define M_PI
Definition: ActiveFraction.h:11
mc.diff
diff
Definition: mc.SFGenPy8_MuMu_DD.py:14
Trk::DiscSurface
Definition: DiscSurface.h:54
Trk::TubeOutsideZmaxZincrease
@ TubeOutsideZmaxZincrease
Accessor type [ 1,3,2,0 ] - inverse case.
Definition: CylinderVolumeBoundaryAccessors.h:39
Trk::CylinderVolumeBounds::dump
MsgStream & dump(MsgStream &sl) const override final
Output Method for MsgStream.
Definition: CylinderVolumeBounds.cxx:380
Trk::CylinderVolumeBounds::m_halfPhiSector
double m_halfPhiSector
Definition: CylinderVolumeBounds.h:159
Trk::TubeRincreaseZdecrease
@ TubeRincreaseZdecrease
Accessor type [ 2,0,1,3 ].
Definition: CylinderVolumeBoundaryAccessors.h:29
Trk::CylinderVolumeBounds::CylinderVolumeBounds
CylinderVolumeBounds()
Default Constructor.
Definition: CylinderVolumeBounds.cxx:30
Trk::VolumeBounds
Definition: VolumeBounds.h:45
Trk::StandardSectoralCylinder
@ StandardSectoralCylinder
Definition: CylinderVolumeBoundaryAccessors.h:46
CylinderVolumeBounds.h
Trk::CylinderVolumeBounds::m_outerRadius
double m_outerRadius
Definition: CylinderVolumeBounds.h:158
Trk::CylinderVolumeBounds::boundarySurfaceAccessor
ObjectAccessor boundarySurfaceAccessor(const Amg::Vector3D &gp, const Amg::Vector3D &dir, bool forceInside=false) const override final
Provide accessor for BoundarySurfaces.
Definition: CylinderVolumeBounds.cxx:164
Trk::CylinderIntersector
Definition: CylinderIntersector.h:20
beamspotman.posZ
posZ
Definition: beamspotman.py:1624
Trk::CylinderSurface
Definition: CylinderSurface.h:55
Trk::CylinderBounds
Definition: CylinderBounds.h:46
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
CylinderSurface.h
Trk::TubeZdecreaseRincrease
@ TubeZdecreaseRincrease
Accessor type [ 0,2,1,3 ].
Definition: CylinderVolumeBoundaryAccessors.h:31
Trk::CylinderVolumeBounds::bottomDiscBounds
DiscBounds * bottomDiscBounds() const
This method returns the associated DiscBounds for the bottom/top DiscSurface.
Definition: CylinderVolumeBounds.cxx:365
Trk::CylinderZdecrease
@ CylinderZdecrease
Cylinder hit, the neg.
Definition: CylinderVolumeBoundaryAccessors.h:19
Trk::CylinderIntersector::yOfX
double yOfX
the result of x
Definition: CylinderIntersector.h:22
Trk::TubeRdecreaseZincrease
@ TubeRdecreaseZincrease
Accessor type [ 3,1,0,2 ].
Definition: CylinderVolumeBoundaryAccessors.h:32
Trk::CylinderVolumeBounds::m_innerRadius
double m_innerRadius
Definition: CylinderVolumeBounds.h:157
beamspotman.dir
string dir
Definition: beamspotman.py:623
Trk::CylinderNegativeFace
@ CylinderNegativeFace
Neg.
Definition: CylinderVolumeBoundaryAccessors.h:21
Trk::CylinderVolumeBounds
Definition: CylinderVolumeBounds.h:70
Trk::StandardSectoralTube
@ StandardSectoralTube
Definition: CylinderVolumeBoundaryAccessors.h:51
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Trk::TubeRincreaseZincrease
@ TubeRincreaseZincrease
Accessor type [ 2,1,0,3 ].
Definition: CylinderVolumeBoundaryAccessors.h:28
Trk::CylinderVolumeBounds::outerCylinderBounds
CylinderBounds * outerCylinderBounds() const
This method returns the associated CylinderBounds of the outer CylinderSurfaces.
Definition: CylinderVolumeBounds.cxx:359
ParticleGun_SamplingFraction.radius
radius
Definition: ParticleGun_SamplingFraction.py:96
Trk::ObjectAccessor
Definition: ObjectAccessor.h:15
python.SystemOfUnits.mm
int mm
Definition: SystemOfUnits.py:83
CylinderBounds.h
Trk::PlaneSurface
Definition: PlaneSurface.h:64
Amg::RotationMatrix3D
Eigen::Matrix< double, 3, 3 > RotationMatrix3D
Definition: GeoPrimitives.h:49
PlaneSurface.h
Trk::TubeZincreaseRdecrease
@ TubeZincreaseRdecrease
Accessor type [ 1,3,0,2 ].
Definition: CylinderVolumeBoundaryAccessors.h:34
Amg::Translation3D
Eigen::Translation< double, 3 > Translation3D
Definition: GeoPrimitives.h:44
DiscSurface.h
Trk::CylinderVolumeBounds::innerCylinderBounds
CylinderBounds * innerCylinderBounds() const
This method returns the associated CylinderBounds of the inner CylinderSurfaces.
Definition: CylinderVolumeBounds.cxx:353
Trk::CylinderPositiveFace
@ CylinderPositiveFace
Pos.
Definition: CylinderVolumeBoundaryAccessors.h:20
Amg::AngleAxis3D
Eigen::AngleAxisd AngleAxis3D
Definition: GeoPrimitives.h:45
Trk::CylinderZincrease
@ CylinderZincrease
Cylinder hit, then pos.
Definition: CylinderVolumeBoundaryAccessors.h:18
Trk::CylinderVolumeBounds::s_numericalStable
static const double s_numericalStable
numerical stability
Definition: CylinderVolumeBounds.h:168
Trk::CylinderVolumeBounds::sectorPlaneBounds
RectangleBounds * sectorPlaneBounds() const
This method returns the associated PlaneBounds limiting a sectoral CylinderVolume.
Definition: CylinderVolumeBounds.cxx:371
Trk::TubeOutsideRminRdecrease
@ TubeOutsideRminRdecrease
Accessor type [ 3,1,0,2] - inverse case.
Definition: CylinderVolumeBoundaryAccessors.h:36
Trk::CylinderVolumeBounds::decomposeToSurfaces
const std::vector< const Trk::Surface * > * decomposeToSurfaces(const Amg::Transform3D &transform) override final
Method to decompose the Bounds into boundarySurfaces.
Definition: CylinderVolumeBounds.cxx:99
makeComparison.deltaZ
int deltaZ
Definition: makeComparison.py:46
Trk::CylinderVolumeBounds::operator=
CylinderVolumeBounds & operator=(const CylinderVolumeBounds &cylbo)
Assignment operator.
Definition: CylinderVolumeBounds.cxx:86
Trk::TubeOutsideZminZdecrease
@ TubeOutsideZminZdecrease
Accessor type [ 0,3,2,1 ] - inverse case.
Definition: CylinderVolumeBoundaryAccessors.h:38
makeComparison.deltaR
float deltaR
Definition: makeComparison.py:36
Trk::DiscBounds
Definition: DiscBounds.h:44
Trk::TubeZincreaseRincrease
@ TubeZincreaseRincrease
Accessor type [ 1,2,0,3 ].
Definition: CylinderVolumeBoundaryAccessors.h:30