ATLAS Offline Software
Loading...
Searching...
No Matches
BevelledCylinderVolumeBounds.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
6// BevelledCylinderVolumeBounds.cxx, (c) ATLAS Detector software
8
9// Trk
11// TrkSurfaces
15//#include "TrkGeometrySurfaces/BevelledCylinderBounds.h"
24// Gaudi
25#include "GaudiKernel/MsgStream.h"
26#include "GaudiKernel/SystemOfUnits.h"
27// STD
28#include <cmath>
29#include <iostream>
30
32 10e-2 * Gaudi::Units::millimeter;
33
46
48 double rinner,
49 double router,
50 double haphi,
51 double halez,
52 int type)
53 : VolumeBounds()
54 , m_innerRadius(std::abs(rinner))
55 , m_outerRadius(std::abs(router))
56 , m_halfPhiSector(haphi)
57 , m_halfZ(std::abs(halez))
58 , m_thetaMinus(0.)
59 , m_thetaPlus(0.)
60 , m_type(type)
62 , m_subtractedVolume(nullptr)
63{}
64
78
80
84{
85 if (this != &cylbo) {
89 m_halfZ = cylbo.m_halfZ;
92 m_type = cylbo.m_type;
93 m_subtractedVolume.store(nullptr);
94 }
95 return *this;
96}
97
98std::vector<std::unique_ptr<Trk::Surface>>
100 (const Amg::Transform3D& transform)
101{
102 auto retsf = std::vector<std::unique_ptr<Trk::Surface>>();
103 // memory optimisation (reserve a save number of 20)
104 retsf.reserve(6);
105
106 Amg::RotationMatrix3D discRot(transform.rotation());
107 Amg::Vector3D cylCenter(transform.translation());
108
109 // Lazy init m_m_subtractedVolume
110 if (m_type > -1 && !m_subtractedVolume) {
111 m_subtractedVolume.set(std::unique_ptr<Trk::Volume>(subtractedVolume()));
112 }
113
114 // bottom Ellipse/Disc (negative z)
115 if (m_type < 0)
116 retsf.push_back(std::make_unique<Trk::PlaneSurface>(
118 (discRot *
121 cylCenter - (halflengthZ() - m_outerRadius * tan(m_thetaMinus)) *
122 discRot.col(2))),
124 else {
125 if (m_subtractedVolume) {
126 auto subtrVol = std::make_unique<Trk::Volume>(*m_subtractedVolume);
127 Trk::DiscSurface bottomDisc(
129 transform * Amg::AngleAxis3D(M_PI, Amg::Vector3D(1., 0., 0.)) *
131 discBounds());
132 retsf.push_back(std::make_unique<Trk::SubtractedDiscSurface>(
133 bottomDisc, std::make_shared<Trk::VolumeExcluder>(std::move(subtrVol)), false));
134 } else
135 retsf.push_back(std::make_unique<Trk::DiscSurface>(
137 transform * Amg::AngleAxis3D(M_PI, Amg::Vector3D(1., 0., 0.)) *
139 discBounds()));
140 }
141
142 // top Ellipse/Disc (positive z)
143 if (m_type < 0)
144 retsf.push_back(std::make_unique<Trk::PlaneSurface>(
146 discRot * Amg::AngleAxis3D(m_thetaPlus, Amg::Vector3D(0., 1., 0.)) *
148 cylCenter +
149 (halflengthZ() - m_outerRadius * tan(m_thetaPlus)) * discRot.col(2))),
151 else {
152 if (m_subtractedVolume) {
153 auto subtrVol = std::make_unique<Trk::Volume>(*m_subtractedVolume);
154 Trk::DiscSurface topDisc(
156 transform * Amg::Translation3D(Amg::Vector3D(0., 0., halflengthZ()))),
157 discBounds());
158 retsf.push_back(std::make_unique<Trk::SubtractedDiscSurface>(
159 topDisc, std::make_shared<Trk::VolumeExcluder>(std::move(subtrVol)), false));
160 } else
161 retsf.push_back(std::make_unique<Trk::DiscSurface>(
163 transform * Amg::Translation3D(Amg::Vector3D(0., 0., halflengthZ()))),
164 discBounds()));
165 }
166
167 // outer BevelledCylinder/Plane
168 if (m_type < 0)
169 retsf.push_back(std::make_unique<Trk::CylinderSurface>(
171 else if (m_type < 2)
172 retsf.push_back(std::make_unique<Trk::CylinderSurface>(
174 else
175 retsf.push_back(std::make_unique<Trk::PlaneSurface>(
177 transform *
179 Amg::AngleAxis3D(-90 * Gaudi::Units::deg, Amg::Vector3D(0., 0., 1.)) *
180 Amg::AngleAxis3D(-90. * Gaudi::Units::deg, Amg::Vector3D(1., 0., 0.))),
182
183 // inner BevelledCylinder/Plane
185 if (m_type < 1)
186 retsf.push_back(std::make_unique<Trk::CylinderSurface>(
188 else if (m_type == 2)
189 retsf.push_back(std::make_unique<Trk::CylinderSurface>(
191 else
192 retsf.push_back(std::make_unique<Trk::PlaneSurface>(
194 transform *
196 Amg::AngleAxis3D(+90 * Gaudi::Units::deg, Amg::Vector3D(0., 0., 1.)) *
198 -90. * Gaudi::Units::deg, Amg::Vector3D(1., 0., 0.))),
200 }
201
202 if (std::abs(halfPhiSector() - M_PI) > s_numericalStable) {
203 if (m_type < 0) {
204 // sectorPlane 1 (negative phi)
205 retsf.push_back(std::make_unique<Trk::PlaneSurface>(
207 transform *
210 Amg::AngleAxis3D(M_PI / 2, Amg::Vector3D(1., 0., 0.))),
211 sectorTrdBounds()));
212 // sectorPlane 2 (positive phi)
213 retsf.push_back(std::make_unique<Trk::PlaneSurface>(
215 transform *
218 Amg::AngleAxis3D(-M_PI / 2, Amg::Vector3D(1., 0., 0.))),
219 sectorTrdBounds()));
220 } else {
221 // sectorPlane 1 (negative phi)
222 double ri = innerRadius();
223 double ro = outerRadius();
224 if (m_type == 1 || m_type == 3)
225 ri *= 1. / cos(halfPhiSector());
226 if (m_type > 1)
227 ro *= 1. / cos(halfPhiSector());
228 retsf.push_back(std::make_unique<Trk::PlaneSurface>(
230 transform *
232 Amg::Translation3D(Amg::Vector3D(0.5 * (ri + ro), 0., 0.)) *
233 Amg::AngleAxis3D(M_PI / 2, Amg::Vector3D(1., 0., 0.))),
235 // sectorPlane 2 (positive phi)
236 retsf.push_back(std::make_unique<Trk::PlaneSurface>(
238 transform *
240 Amg::Translation3D(Amg::Vector3D(0.5 * (ri + ro), 0., 0.)) *
241 Amg::AngleAxis3D(-M_PI / 2, Amg::Vector3D(1., 0., 0.))),
243 }
244 }
245 return retsf;
246}
247
250 const Amg::Vector3D& gp,
251 const Amg::Vector3D& dir,
252 bool) const
253{
254 // the tube case - most likely
255 if (m_innerRadius != 0. && std::abs(m_halfPhiSector - M_PI) < s_numericalStable) {
256 // prepare the data
257 double posZ = gp.z();
258 double posR = gp.perp();
259 // difference Vector
260 Amg::Vector3D diff(gp + dir);
261 // differences
262 double deltaZ = diff.z() - posZ;
263 double deltaR = diff.perp() - posR;
264
265 // the isOnSurface cases + switchers (that change with the cases)
266 bool isOnFace = false;
267 bool intersectionIndicator = (deltaR > 0.);
268 bool choiceIndicator = false;
269
270 // on surface or look-a-likes
271 // on zMin or slightly outside
272 if (
273 std::abs(posZ + m_halfZ) < s_numericalStable ||
274 (posZ < (-m_halfZ) && deltaZ > 0.)) {
275 isOnFace = true;
276 } else if (
277 std::abs(posZ - m_halfZ) < s_numericalStable ||
278 (posZ > m_halfZ && deltaZ < 0.)) {
279 // on zMax or slighly outside
280 isOnFace = true;
281 } else if (
282 std::abs(posR - m_innerRadius) < s_numericalStable ||
283 (posR < m_innerRadius && deltaR > 0.)) {
284 // on innerRadius or slightly outside
285 isOnFace = true;
286 choiceIndicator =
287 (deltaZ > 0.); // the side choice indicator <========== WRONG ==========
288 } else if (
289 std::abs(posR - m_outerRadius) < s_numericalStable ||
290 (posR > m_outerRadius && deltaR < 0.)) {
291 // on outRadius or slightly outside
292 isOnFace = true;
293 choiceIndicator =
294 (deltaZ > 0.); // the side choice indicator <========== WRONG ==========
295 }
296
297 // the onSurface case
298 // =================================================================================
299 if (isOnFace) {
300 if (intersectionIndicator) {
301 // intersect the Rmax
303 posR, posZ, deltaZ / deltaR, m_outerRadius);
304 double zOfIntersect = intersectRmax.yOfX;
305 // now check if the intersect is inside m_halfZ
306 if (std::abs(zOfIntersect) <= m_halfZ)
307 return {(choiceIndicator || zOfIntersect > 0.)
308 ? m_boundaryAccessors.bevelledtubeAccessor(
310 : m_boundaryAccessors.bevelledtubeAccessor(
312 // if the intersect is outside
313 return {(choiceIndicator || zOfIntersect > 0.)
314 ? m_boundaryAccessors.bevelledtubeAccessor(
316 : m_boundaryAccessors.bevelledtubeAccessor(
318 }
319 // intersect the Rmin
321 posR, posZ, deltaZ / deltaR, m_innerRadius);
322 double zOfIntersect = intersectRmin.yOfX;
323 // now check if the intersect is inside m_halfZ
324 if (std::abs(zOfIntersect) <= m_halfZ)
325 return {(choiceIndicator || zOfIntersect > 0.)
326 ? m_boundaryAccessors.bevelledtubeAccessor(
328 : m_boundaryAccessors.bevelledtubeAccessor(
330 // if the intersect is outside
331 return {(choiceIndicator || zOfIntersect > 0.)
332 ? m_boundaryAccessors.bevelledtubeAccessor(
334 : m_boundaryAccessors.bevelledtubeAccessor(
336 }
337 // =================================================================================================
338
339 // ======================= the inside/outside part remains
340 // =========================================
341 // (a) outside cases
342 if (posR < m_innerRadius && deltaR < 0.)
343 return {m_boundaryAccessors.bevelledtubeAccessor(
345 if (posR > m_outerRadius && deltaR > 0.)
346 return {m_boundaryAccessors.bevelledtubeAccessor(
348 if (posZ < -m_halfZ && deltaZ < 0.)
349 return {m_boundaryAccessors.bevelledtubeAccessor(
351 if (posZ > m_halfZ && deltaZ > 0.)
352 return {m_boundaryAccessors.bevelledtubeAccessor(
354 // (b) inside cases
355 // the increase R case
356 if (deltaR > 0.) {
357 // solve the linear equation for the outer Radius
359 posR, posZ, deltaZ / deltaR, m_outerRadius);
360 double zOfIntersect = intersectRmax.yOfX;
361
362 if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect > 0.)
363 return {m_boundaryAccessors.bevelledtubeAccessor(
365 if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect < 0.)
366 return {m_boundaryAccessors.bevelledtubeAccessor(
368 if (std::abs(zOfIntersect) > m_halfZ && zOfIntersect < 0.)
369 return {m_boundaryAccessors.bevelledtubeAccessor(
371 if (std::abs(zOfIntersect) > m_halfZ && zOfIntersect > 0.)
372 return {m_boundaryAccessors.bevelledtubeAccessor(
374
375 } else {
376 // solve the linear equation for the inner Radius
378 posR, posZ, deltaZ / deltaR, m_innerRadius);
379 double zOfIntersect = intersectRmin.yOfX;
380
381 if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect > 0.)
382 return {m_boundaryAccessors.bevelledtubeAccessor(
384 if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect < 0.)
385 return {m_boundaryAccessors.bevelledtubeAccessor(
387 if (std::abs(zOfIntersect) > m_halfZ && zOfIntersect > 0.)
388 return {m_boundaryAccessors.bevelledtubeAccessor(
390 return {m_boundaryAccessors.bevelledtubeAccessor(
392 }
393 }
394 // the cylinder case
395 if (m_innerRadius == 0. && std::abs(m_halfPhiSector - M_PI) < 10e-3) {
396
397 double posZ = gp.z();
398 double posR = gp.perp();
399 // difference Vector
400 Amg::Vector3D diff(gp + dir);
401 // differences
402 double deltaZ = diff.z() - posZ;
403 double deltaR = diff.perp() - posR;
404
405 // solve the linear equation for the cylinder Radius
407 posR, posZ, deltaZ / deltaR, m_outerRadius);
408 // the intersection point
409 double zOfIntersect = intersectR.yOfX;
410
411 if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect > 0.)
412 return {m_boundaryAccessors.bevelledcylinderAccessor(
414 if (std::abs(zOfIntersect) <= m_halfZ && zOfIntersect < 0.)
415 return {m_boundaryAccessors.bevelledcylinderAccessor(
417 if (std::abs(zOfIntersect) > m_halfZ && zOfIntersect > 0.)
418 return {m_boundaryAccessors.bevelledcylinderAccessor(
420 return {m_boundaryAccessors.bevelledcylinderAccessor(
422 }
423 // the sectoral cylinder case
424 if (m_innerRadius != 0. && std::abs(m_halfPhiSector - M_PI) > 10e-3)
425 return {m_boundaryAccessors.sectoralBevelledCylinderAccessor(
427 // it remains the sectoral tube case
428 return {m_boundaryAccessors.sectoralBevelledTubeAccessor(
430}
431
432std::shared_ptr<Trk::CylinderBounds>
434{
435 return std::make_shared<Trk::CylinderBounds>(m_innerRadius, m_halfPhiSector, m_halfZ);
436}
437
438std::shared_ptr<Trk::CylinderBounds>
440{
441 return std::make_shared<Trk::CylinderBounds>(m_outerRadius, m_halfPhiSector, m_halfZ);
442}
443
444std::shared_ptr<Trk::RectangleBounds>
446{
447 return std::make_shared<Trk::RectangleBounds>(m_outerRadius * tan(m_halfPhiSector), m_halfZ);
448}
449
450std::shared_ptr<Trk::RectangleBounds>
452{
453 return std::make_shared<Trk::RectangleBounds>(m_innerRadius * tan(m_halfPhiSector), m_halfZ);
454}
455
456std::shared_ptr<Trk::EllipseBounds>
458{
459 return std::make_shared<Trk::EllipseBounds>(
465}
466
467std::shared_ptr<Trk::EllipseBounds>
469{
470 return std::make_shared<Trk::EllipseBounds>(
476}
477
478std::shared_ptr<Trk::CylinderBounds>
480{
481 return std::make_shared<Trk::CylinderBounds>(m_innerRadius, m_halfPhiSector, m_halfZ);
482}
483
484std::shared_ptr<Trk::CylinderBounds>
486{
487 return std::make_shared<Trk::CylinderBounds>(m_outerRadius, m_halfPhiSector, m_halfZ);
488}
489
490std::shared_ptr<Trk::DiscBounds>
492{
493 // adjust radius to make sure all surface covered
494 double outerRadius =
496 return std::make_shared<Trk::DiscBounds>(m_innerRadius, outerRadius, m_halfPhiSector);
497}
498
499std::shared_ptr<Trk::TrapezoidBounds>
501{
502 return std::make_shared<Trk::TrapezoidBounds>(
505}
506
507std::shared_ptr<Trk::RectangleBounds>
509{
510 double ri = innerRadius();
511 double ro = outerRadius();
512 if (m_type == 1 || m_type == 3)
513 ri *= 1. / cos(halfPhiSector());
514 if (m_type > 1)
515 ro *= 1. / cos(halfPhiSector());
516 return std::make_shared<Trk::RectangleBounds>(0.5 * (ro - ri), m_halfZ);
517}
518
521{
522 if (m_type < 1)
523 return nullptr;
524
525 double tp = tan(m_halfPhiSector);
526 std::unique_ptr<Trk::Volume> volIn;
527 std::unique_ptr<Trk::Volume> volOut;
528 if (m_type == 1 || m_type == 3) { // cut inner cylinder
529 volIn = std::make_unique<Trk::Volume>(
530 nullptr,
531 std::make_shared<Trk::CuboidVolumeBounds>(m_innerRadius, m_innerRadius * tp + 0.1, m_halfZ + 0.1));
532 }
533 if (m_type > 1) {
534 double hz = m_outerRadius * (1. / cos(m_halfPhiSector) - 1.);
535 volOut = std::make_unique<Trk::Volume>(
536 std::make_unique<Amg::Transform3D>(Amg::Translation3D(Amg::Vector3D(m_outerRadius + hz, 0., 0.))),
537 std::make_shared<Trk::CuboidVolumeBounds>(hz, m_outerRadius * tp + 0.1, m_halfZ + 0.1));
538 }
539
540 if (!volIn){
541 return volOut.release();
542 }
543 else if (!volOut){
544 return volIn.release();
545 }
546 return new Trk::Volume(
547 nullptr, std::make_shared<Trk::CombinedVolumeBounds>(std::move(volIn), std::move(volOut), false));
548}
549
550// ostream operator overload
551
552MsgStream&
554{
555 std::stringstream sl_temp;
556 sl_temp << std::setiosflags(std::ios::fixed);
557 sl_temp << std::setprecision(7);
558 sl_temp << "Trk::BevelledCylinderVolumeBounds: (innerR, outerR, "
559 "halfPhiSector, halflengthInZ, thetaMinus, thetaPlus) = ";
560 sl_temp << "(" << m_innerRadius << ", " << m_outerRadius << ", "
561 << m_halfPhiSector << ", " << m_halfZ << ", " << m_thetaMinus << ", "
562 << m_thetaPlus << ")";
563 sl << sl_temp.str();
564 return sl;
565}
566
567std::ostream&
569{
570 std::stringstream sl_temp;
571 sl_temp << std::setiosflags(std::ios::fixed);
572 sl_temp << std::setprecision(7);
573 sl_temp << "Trk::BevelledCylinderVolumeBounds: (innerR, outerR, "
574 "halfPhiSector, halflengthInZ, thetaMinus, thetaPlus) = ";
575 sl_temp << "(" << m_innerRadius << ", " << m_outerRadius << ", "
576 << m_halfPhiSector << ", " << m_halfZ << m_thetaMinus << ", "
577 << m_thetaPlus << ")";
578 sl << sl_temp.str();
579 return sl;
580}
581
#define M_PI
Scalar deltaR(const MatrixBase< Derived > &vec) const
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
Bounds for a cylindrical Volume, the decomposeToSurfaces method creates a vector of up to 6 surfaces:
std::shared_ptr< RectangleBounds > outerBevelledPlaneBounds() const
This method returns the associated BevelledCylinderBounds of the outer BevelledCylinderSurfaces.
std::shared_ptr< DiscBounds > discBounds() const
This method returns the associated DiscBounds for the bottom/top DiscSurface.
virtual std::vector< std::unique_ptr< Trk::Surface > > decomposeToSurfaces(const Amg::Transform3D &transform) override
Method to decompose the Bounds into boundarySurfaces.
std::shared_ptr< EllipseBounds > bottomEllipseBounds() const
This method returns the associated EllipseBounds for the bottom/top EllipseSurface.
virtual ~BevelledCylinderVolumeBounds()
Destructor.
Volume * subtractedVolume() const
This method returns the bevelled area volume.
int type() const
This method returns the type.
ObjectAccessor boundarySurfaceAccessor(const Amg::Vector3D &gp, const Amg::Vector3D &dir, bool forceInside=false) const override
Provide accessor for BoundarySurfaces.
std::shared_ptr< RectangleBounds > innerBevelledPlaneBounds() const
This method returns the associated plane surface bounds of the inner bevelled surface.
static const double s_numericalStable
numerical stability
CxxUtils::CachedUniquePtr< Trk::Volume > m_subtractedVolume
double halflengthZ() const
This method returns the halflengthZ.
double mediumRadius() const
This method returns the medium radius.
MsgStream & dump(MsgStream &sl) const override
Output Method for MsgStream.
double innerRadius() const
This method returns the inner radius.
std::shared_ptr< TrapezoidBounds > sectorTrdBounds() const
This method returns the associated PlaneBounds limiting a sectoral BevelledCylinderVolume.
BevelledCylinderVolumeBounds & operator=(const BevelledCylinderVolumeBounds &cylbo)
Assignment operator.
std::shared_ptr< CylinderBounds > outerBevelledCylinderBounds() const
This method returns the associated BevelledCylinderBounds of the outer BevelledCylinderSurfaces.
std::shared_ptr< CylinderBounds > outerCylinderBounds() const
This method returns the associated CylinderBounds of the outer CylinderSurfaces.
std::shared_ptr< RectangleBounds > sectorPlaneBounds() const
double outerRadius() const
This method returns the outer radius.
std::shared_ptr< EllipseBounds > topEllipseBounds() const
This method returns the associated EllipseBounds for the bottom/top EllipseSurface.
double halfPhiSector() const
This method returns the halfPhiSector angle.
std::shared_ptr< CylinderBounds > innerBevelledCylinderBounds() const
This method returns the associated BevelledCylinderBounds of the inner BevelledCylinderSurfaces.
BevelledCylinderVolumeBoundaryAccessors m_boundaryAccessors
Accessors for Boundary surface access - static is not possible due to mismatched delete() / free () w...
std::shared_ptr< CylinderBounds > innerCylinderBounds() const
This method returns the associated CylinderBounds of the inner CylinderSurfaces.
Class for a DiscSurface in the ATLAS detector.
Definition DiscSurface.h:54
VolumeBounds()
Default Constructor.
Base class for all volumes inside the tracking realm, it defines the interface for inherited Volume c...
Definition Volume.h:36
Eigen::AngleAxisd AngleAxis3D
Eigen::Matrix< double, 3, 3 > RotationMatrix3D
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Eigen::Translation< double, 3 > Translation3D
@ BevelledCylinderZincrease
Cylinder hit, then pos.
@ BevelledCylinderZdecrease
Cylinder hit, the neg.
@ BevelledTubeOutsideRminRdecrease
Accessor type [ 3,1,0,2] - inverse case.
@ BevelledTubeOutsideZmaxZincrease
Accessor type [ 1,3,2,0 ] - inverse case.
@ BevelledTubeRincreaseZincrease
Accessor type [ 2,1,0,3 ].
@ BevelledTubeZincreaseRdecrease
Accessor type [ 1,3,0,2 ].
@ BevelledTubeRdecreaseZincrease
Accessor type [ 3,1,0,2 ].
@ BevelledTubeZdecreaseRdecrease
Accessor type [ 0,3,1,2 ].
@ BevelledTubeRdecreaseZdecrease
Accessor type [ 3,0,1,2 ].
@ BevelledTubeRincreaseZdecrease
Accessor type [ 2,0,1,3 ].
@ BevelledTubeZincreaseRincrease
Accessor type [ 1,2,0,3 ].
@ BevelledTubeOutsideZminZdecrease
Accessor type [ 0,3,2,1 ] - inverse case.
@ BevelledTubeZdecreaseRincrease
Accessor type [ 0,2,1,3 ].
@ BevelledTubeOutsideRmaxRincrease
Accessor type [ 2,1,0,3 ] - inverse case.
STL namespace.