ATLAS Offline Software
CylinderVolumeBounds.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 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.rotation());
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  discRot * Amg::Translation3D(cylCenter + halflengthZ() * discRot.col(2))),
126  topDiscBounds()));
127  // outer Cylinder
128  if (!isConcentric)
129  retsf->push_back(new Trk::CylinderSurface(
130  Amg::Transform3D(transform), outerCylinderBounds()));
131  else
132  retsf->push_back(new Trk::CylinderSurface(outerCylinderBounds()));
133 
134  // innermost Cylinder
135  if (innerRadius() > s_numericalStable) {
136  if (!isConcentric)
137  retsf->push_back(new Trk::CylinderSurface(
138  Amg::Transform3D(transform), innerCylinderBounds()));
139  else
140  retsf->push_back(new Trk::CylinderSurface(innerCylinderBounds()));
141  }
142 
143  if (std::abs(halfPhiSector() - M_PI) > s_numericalStable) {
144  // sectorPlane 1 (negative phi)
145  retsf->push_back(new Trk::PlaneSurface(
147  transform *
148  Amg::AngleAxis3D(-halfPhiSector(), Amg::Vector3D(0., 0., 1.)) *
149  Amg::Translation3D(Amg::Vector3D(mediumRadius(), 0., 0.)) *
150  Amg::AngleAxis3D(M_PI / 2, Amg::Vector3D(1., 0., 0.))),
151  sectorPlaneBounds()));
152  // sectorPlane 2 (positive phi)
153  retsf->push_back(new Trk::PlaneSurface(
155  transform *
156  Amg::AngleAxis3D(halfPhiSector(), Amg::Vector3D(0., 0., 1.)) *
157  Amg::Translation3D(Amg::Vector3D(mediumRadius(), 0., 0.)) *
158  Amg::AngleAxis3D(-M_PI / 2, Amg::Vector3D(1., 0., 0.))),
159  sectorPlaneBounds()));
160  }
161  return retsf;
162 }
163 
166  const Amg::Vector3D& gp,
167  const Amg::Vector3D& dir,
168  bool) const
169 {
170  // the tube case - most likely
171  if (
172  m_innerRadius > s_numericalStable &&
173  std::abs(m_halfPhiSector - M_PI) < s_numericalStable) {
174  // prepare the data
175  double posZ = gp.z();
176  double posR = gp.perp();
177  // difference Vector
178  Amg::Vector3D diff(gp + dir);
179  // differences
180  double deltaZ = diff.z() - posZ;
181  double deltaR = diff.perp() - posR;
182 
183  // the isOnSurface cases + switchers (that change with the cases)
184  bool isOnFace = false;
185  bool intersectionIndicator = (deltaR > 0.);
186  bool choiceIndicator = false;
187 
188  // on surface or look-a-likes
189  // on zMin or slightly outside
190  if (
191  std::abs(posZ + m_halfZ) < s_numericalStable ||
192  (posZ < (-m_halfZ) && deltaZ > 0.)) {
193  isOnFace = true;
194  } else if (
195  std::abs(posZ - m_halfZ) < s_numericalStable ||
196  (posZ > m_halfZ && deltaZ < 0.)) {
197  // on zMax or slighly outside
198  isOnFace = true;
199  } else if (
200  std::abs(posR - m_innerRadius) < s_numericalStable ||
201  (posR < m_innerRadius && deltaR > 0.)) {
202  // on innerRadius or slightly outside
203  isOnFace = true;
204  choiceIndicator =
205  (deltaZ > 0.); // the side choice indicator <========== WRONG ==========
206  } else if (
207  std::abs(posR - m_outerRadius) < s_numericalStable ||
208  (posR > m_outerRadius && deltaR < 0.)) {
209  // on outRadius or slightly outside
210  isOnFace = true;
211  choiceIndicator =
212  (deltaZ > 0.); // the side choice indicator <========== WRONG ==========
213  }
214 
215  // the onSurface case
216  // =================================================================================
217  if (isOnFace) {
218  if (intersectionIndicator) {
219  // intersect the Rmax / with floatint point exception check
220  Trk::CylinderIntersector intersectRmax(
221  posR, posZ, deltaR != 0 ? deltaZ / deltaR : 0, m_outerRadius);
222  double zOfIntersect = intersectRmax.yOfX;
223  // now check if the intersect is inside m_halfZ
224  if (std::abs(zOfIntersect) <= m_halfZ)
225  return {(choiceIndicator || zOfIntersect > 0.)
226  ? m_boundaryAccessors.tubeAccessor(
228  : m_boundaryAccessors.tubeAccessor(
230  // if the intersect is outside
231  return {
232  (choiceIndicator || zOfIntersect > 0.)
233  ? m_boundaryAccessors.tubeAccessor(Trk::TubeZincreaseRincrease)
234  : m_boundaryAccessors.tubeAccessor(
236  }
237  // intersect the Rmin
238  Trk::CylinderIntersector intersectRmin(
239  posR, posZ, deltaR != 0 ? deltaZ / deltaR : 0, m_innerRadius);
240  double zOfIntersect = intersectRmin.yOfX;
241  // now check if the intersect is inside m_halfZ
242  if (std::abs(zOfIntersect) <= m_halfZ)
243  return {
244  (choiceIndicator || zOfIntersect > 0.)
245  ? m_boundaryAccessors.tubeAccessor(Trk::TubeRdecreaseZincrease)
246  : m_boundaryAccessors.tubeAccessor(
248  // if the intersect is outside
249  return {
250  (choiceIndicator || zOfIntersect > 0.)
251  ? m_boundaryAccessors.tubeAccessor(Trk::TubeZincreaseRdecrease)
252  : m_boundaryAccessors.tubeAccessor(Trk::TubeZdecreaseRdecrease)};
253  }
254  // =================================================================================================
255 
256  // ======================= the inside/outside part remains
257  // =========================================
258  // (a) outside cases
259  if (posR < m_innerRadius && deltaR < 0.)
260  return {m_boundaryAccessors.tubeAccessor(Trk::TubeOutsideRminRdecrease)};
261  if (posR > m_outerRadius && deltaR > 0.)
262  return {m_boundaryAccessors.tubeAccessor(Trk::TubeOutsideRmaxRincrease)};
263  if (posZ < -m_halfZ && deltaZ < 0.)
264  return {m_boundaryAccessors.tubeAccessor(Trk::TubeOutsideZminZdecrease)};
265  if (posZ > m_halfZ && deltaZ > 0.)
266  return {m_boundaryAccessors.tubeAccessor(Trk::TubeOutsideZmaxZincrease)};
267  // (b) inside cases
268  // the increase R case
269  if (deltaR > 0.) {
270  // solve the linear equation for the outer Radius - with floating point
271  // exception check
272  Trk::CylinderIntersector intersectRmax(
273  posR, posZ, deltaR != 0 ? deltaZ / deltaR : 0, m_outerRadius);
274  double zOfIntersect = intersectRmax.yOfX;
275 
276  if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect > 0.)
277  return {m_boundaryAccessors.tubeAccessor(Trk::TubeRincreaseZincrease)};
278  if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect < 0.)
279  return {m_boundaryAccessors.tubeAccessor(Trk::TubeRincreaseZdecrease)};
280  if (std::abs(zOfIntersect) > m_halfZ && zOfIntersect < 0.)
281  return {m_boundaryAccessors.tubeAccessor(Trk::TubeZdecreaseRincrease)};
282  if (std::abs(zOfIntersect) > m_halfZ && zOfIntersect > 0.)
283  return {m_boundaryAccessors.tubeAccessor(Trk::TubeZincreaseRincrease)};
284 
285  } else {
286  // solve the linear equation for the inner Radius with floating point
287  // exceptin check
288  Trk::CylinderIntersector intersectRmin(
289  posR, posZ, deltaR != 0 ? deltaZ / deltaR : 0, m_innerRadius);
290  double zOfIntersect = intersectRmin.yOfX;
291 
292  if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect > 0.)
293  return {m_boundaryAccessors.tubeAccessor(Trk::TubeRdecreaseZincrease)};
294  if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect < 0.)
295  return {m_boundaryAccessors.tubeAccessor(Trk::TubeRdecreaseZdecrease)};
296  if (std::abs(zOfIntersect) > m_halfZ && zOfIntersect > 0.)
297  return {m_boundaryAccessors.tubeAccessor(Trk::TubeZincreaseRdecrease)};
298  return {m_boundaryAccessors.tubeAccessor(Trk::TubeZdecreaseRdecrease)};
299  }
300  }
301  // the cylinder case
302  if (
303  m_innerRadius < s_numericalStable &&
304  std::abs(m_halfPhiSector - M_PI) < s_numericalStable) {
305 
306  // ----------------------------- z / r information
307  double posZ = gp.z();
308  double posR = gp.perp();
309 
310  // is on R case
311  bool isOnCylinder = (std::abs(posR - m_outerRadius) < s_numericalStable);
312 
313  // difference Vector
314  Amg::Vector3D diff(gp + dir);
315  // differences
316  double deltaZ = diff.z() - posZ;
317  double deltaR = diff.perp() - posR;
318  // take the sign of the intersect
319  int radiusSign = deltaR > 0. ? 1 : -1;
320 
321  // solve the linear equation for the cylinder Radius / with floating point
322  // exceptin check
323  Trk::CylinderIntersector intersectR(
324  posR,
325  posZ,
326  deltaR != 0 ? deltaZ / deltaR : 0,
327  radiusSign * m_outerRadius);
328 
329  // the intersection point - a little trick for the OnFace cases
330  double zOfIntersect = intersectR.yOfX;
331  // check if intersection exists
332  bool intersectsCylinder =
333  !isOnCylinder ? (zOfIntersect * zOfIntersect <= m_halfZ * m_halfZ)
334  : false;
335 
336  // return the cases for going through the cylinder
337  if (intersectsCylinder && zOfIntersect > 0.)
338  return {m_boundaryAccessors.cylinderAccessor(Trk::CylinderZincrease)};
339  if (intersectsCylinder && zOfIntersect <= 0.)
340  return {m_boundaryAccessors.cylinderAccessor(Trk::CylinderZdecrease)};
341  if (deltaZ > 0.)
342  return {m_boundaryAccessors.cylinderAccessor(Trk::CylinderPositiveFace)};
343  return {m_boundaryAccessors.cylinderAccessor(Trk::CylinderNegativeFace)};
344  }
345  // the sectoral cylinder case
346  if (m_innerRadius != 0. && std::abs(m_halfPhiSector - M_PI) > 10e-3)
347  return {m_boundaryAccessors.sectoralCylinderAccessor(
349  // it remains the sectoral tube case
350  return {m_boundaryAccessors.sectoralTubeAccessor(Trk::StandardSectoralTube)};
351 }
352 
355 {
356  return new Trk::CylinderBounds(m_innerRadius, m_halfPhiSector, m_halfZ);
357 }
358 
361 {
362  return new Trk::CylinderBounds(m_outerRadius, m_halfPhiSector, m_halfZ);
363 }
364 
367 {
368  return new Trk::DiscBounds(m_innerRadius, m_outerRadius, m_halfPhiSector);
369 }
370 
373 {
374  return new Trk::RectangleBounds(
375  0.5 * (m_outerRadius - m_innerRadius), m_halfZ);
376 }
377 
378 // ostream operator overload
379 
380 MsgStream&
382 {
383  std::stringstream temp_sl;
384  temp_sl << std::setiosflags(std::ios::fixed);
385  temp_sl << std::setprecision(2);
386  temp_sl << "Trk::CylinderVolumeBounds: (rMin, rMax, halfPhi, halfZ) = ";
387  temp_sl << m_innerRadius << ", " << m_outerRadius << ", " << m_halfPhiSector
388  << ", " << m_halfZ;
389  sl << temp_sl.str();
390  return sl;
391 }
392 
393 std::ostream&
394 Trk::CylinderVolumeBounds::dump(std::ostream& sl) const
395 {
396  std::stringstream temp_sl;
397  temp_sl << std::setiosflags(std::ios::fixed);
398  temp_sl << std::setprecision(2);
399  temp_sl << "Trk::CylinderVolumeBounds: (rMin, rMax, halfPhi, halfZ) = ";
400  temp_sl << m_innerRadius << ", " << m_outerRadius << ", " << m_halfPhiSector
401  << ", " << m_halfZ;
402  sl << temp_sl.str();
403  return sl;
404 }
405 
Trk::CylinderVolumeBounds::~CylinderVolumeBounds
virtual ~CylinderVolumeBounds()
Destructor.
Trk::TubeRdecreaseZdecrease
@ TubeRdecreaseZdecrease
Accessor type [ 3,0,1,2 ].
Definition: CylinderVolumeBoundaryAccessors.h:33
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:381
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:165
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:366
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:360
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
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
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:354
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:372
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