ATLAS Offline Software
Loading...
Searching...
No Matches
Trk::VolumeConverter Class Reference

A Simple Helper Class that collects methods for material simplification. More...

#include <VolumeConverter.h>

Inheritance diagram for Trk::VolumeConverter:
Collaboration diagram for Trk::VolumeConverter:

Public Types

using VolumePair
using VolumePairVec = std::vector<VolumePair>

Public Member Functions

 VolumeConverter ()
std::unique_ptr< TrackingVolumetranslate (const GeoVPhysVol *gv, bool simplify, bool blend, double blendMassLimit) const
 translation of GeoVPhysVol to Trk::TrackingVolume
double resolveBooleanVolume (const Volume &trVol, double tolerance) const
std::unique_ptr< VolumeSpanfindVolumeSpan (const VolumeBounds &volBounds, const Amg::Transform3D &transform, double zTol, double phiTol) const
 Estimation of the geometrical volume span.
double calculateVolume (const Volume &vol, bool nonBooleanOnly=false, double precision=1.e-3) const
 Volume calculation : by default return analytical solution only.
double estimateFraction (const VolumePair &sub, double precision) const
 the tricky part of volume calculation
void collectMaterial (const GeoVPhysVol *pv, Trk::MaterialProperties &layMat, double sf) const
 material collection for layers
void collectMaterialContent (const GeoVPhysVol *gv, std::vector< Trk::MaterialComponent > &materialContent) const
 material collection for volumes
bool msgLvl (const MSG::Level lvl) const
 Test the output level.
MsgStream & msg () const
 The standard message stream.
MsgStream & msg (const MSG::Level lvl) const
 The standard message stream.
void setLevel (MSG::Level lvl)
 Change the current logging level.

Static Public Member Functions

static VolumePairVec splitComposedVolume (const Volume &trVol)
 Decomposition of volume into set of non-overlapping subtractions from analytically calculable volume.

Private Member Functions

double leadingVolume (const GeoShape *sh) const
void initMessaging () const
 Initialize our message level and MessageSvc.

Private Attributes

Trk::GeoShapeConverter m_geoShapeConverter
 shape converter
std::string m_nm
 Message source name.
boost::thread_specific_ptr< MsgStream > m_msg_tls
 MsgStream instance (a std::cout like with print-out levels).
std::atomic< IMessageSvc * > m_imsg { nullptr }
 MessageSvc pointer.
std::atomic< MSG::Level > m_lvl { MSG::NIL }
 Current logging level.
std::atomic_flag m_initialized ATLAS_THREAD_SAFE = ATOMIC_FLAG_INIT
 Messaging initialized (initMessaging).

Static Private Attributes

static constexpr double s_precisionInX0

Detailed Description

A Simple Helper Class that collects methods for material simplification.

Author
sarka.nosp@m..tod.nosp@m.orova.nosp@m.@cer.nosp@m.n.ch

Definition at line 60 of file VolumeConverter.h.

Member Typedef Documentation

◆ VolumePair

Initial value:
std::pair<std::shared_ptr<Volume>, std::shared_ptr<Volume>>

Definition at line 69 of file VolumeConverter.h.

◆ VolumePairVec

Definition at line 71 of file VolumeConverter.h.

Constructor & Destructor Documentation

◆ VolumeConverter()

Trk::VolumeConverter::VolumeConverter ( )

Definition at line 44 of file VolumeConverter.cxx.

44: AthMessaging("VolumeConverter") {}
AthMessaging()
Default constructor:

Member Function Documentation

◆ calculateVolume()

double Trk::VolumeConverter::calculateVolume ( const Volume & vol,
bool nonBooleanOnly = false,
double precision = 1.e-3 ) const

Volume calculation : by default return analytical solution only.

Definition at line 947 of file VolumeConverter.cxx.

948 {
949
950 double volume = -1.;
951
952 const CylinderVolumeBounds* cyl = dynamic_cast<const CylinderVolumeBounds*>(&(vol.volumeBounds()));
953 const CuboidVolumeBounds* box = dynamic_cast<const CuboidVolumeBounds*>(&(vol.volumeBounds()));
954 const TrapezoidVolumeBounds* trd = dynamic_cast<const TrapezoidVolumeBounds*>(&(vol.volumeBounds()));
955 const BevelledCylinderVolumeBounds* bcyl =dynamic_cast<const BevelledCylinderVolumeBounds*>(&(vol.volumeBounds()));
956 const PrismVolumeBounds* prism =dynamic_cast<const PrismVolumeBounds*>(&(vol.volumeBounds()));
957 const SimplePolygonBrepVolumeBounds* spb = dynamic_cast<const SimplePolygonBrepVolumeBounds*>(&(vol.volumeBounds()));
958 const CombinedVolumeBounds* comb =dynamic_cast<const CombinedVolumeBounds*>(&(vol.volumeBounds()));
959 const SubtractedVolumeBounds* sub = dynamic_cast<const SubtractedVolumeBounds*>(&(vol.volumeBounds()));
960
961 if (cyl) {
962 return 2 * cyl->halfPhiSector() * cyl->halflengthZ() *
963 (std::pow(cyl->outerRadius(), 2) -
964 std::pow(cyl->innerRadius(), 2));
965 }
966 if (box) {
967 return 8 * box->halflengthX() * box->halflengthY() * box->halflengthZ();
968 }
969 if (trd) {
970 return 4 * (trd->minHalflengthX() + trd->maxHalflengthX()) *
971 trd->halflengthY() * trd->halflengthZ();
972 }
973 if (bcyl) {
974 int type = bcyl->type();
975 if (type < 1)
976 return 2 * bcyl->halfPhiSector() *
977 (std::pow(bcyl->outerRadius(), 2) -
978 std::pow(bcyl->innerRadius(), 2)) *
979 bcyl->halflengthZ();
980 if (type == 1)
981 return 2 * bcyl->halflengthZ() *
982 (bcyl->halfPhiSector() * std::pow(bcyl->outerRadius(), 2) -
983 std::pow(bcyl->innerRadius(), 2) *
984 std::tan(bcyl->halfPhiSector()));
985 if (type == 2)
986 return 2 * bcyl->halflengthZ() *
987 (-bcyl->halfPhiSector() * std::pow(bcyl->innerRadius(), 2) +
988 std::pow(bcyl->outerRadius(), 2) *
989 std::tan(bcyl->halfPhiSector()));
990 if (type == 3)
991 return 2 * bcyl->halflengthZ() * std::tan(bcyl->halfPhiSector()) *
992 (std::pow(bcyl->outerRadius(), 2) -
993 std::pow(bcyl->innerRadius(), 2));
994 }
995 if (prism) {
996
997 std::vector<std::pair<double, double>> v = prism->xyVertices();
998 double vv = v[0].first * (v[1].second - v.back().second);
999 for (unsigned int i = 1; i < v.size() - 1; i++) {
1000 vv += v[i].first * (v[i + 1].second - v[i - 1].second);
1001 }
1002 vv += v.back().first * (v[0].second - v[v.size() - 2].second);
1003 return vv * prism->halflengthZ();
1004 }
1005 if (spb) {
1006 std::vector<std::pair<double, double>> v = spb->xyVertices();
1007 double vv = v[0].first * (v[1].second - v.back().second);
1008 for (unsigned int i = 1; i < v.size() - 1; i++) {
1009 vv += v[i].first * (v[i + 1].second - v[i - 1].second);
1010 }
1011 vv += v.back().first * (v[0].second - v[v.size() - 2].second);
1012 return vv * spb->halflengthZ();
1013 }
1014
1015 if (nonBooleanOnly)
1016 return volume;
1017
1018 if (comb || sub) {
1019 return resolveBooleanVolume(vol, precision);
1020 }
1021 return volume;
1022}
double resolveBooleanVolume(const Volume &trVol, double tolerance) const
@ v
Definition ParamDefs.h:78

◆ collectMaterial()

void Trk::VolumeConverter::collectMaterial ( const GeoVPhysVol * pv,
Trk::MaterialProperties & layMat,
double sf ) const

material collection for layers

Definition at line 1055 of file VolumeConverter.cxx.

1057 {
1058 // sf is the area of the layer collecting the material
1059
1060 // solution relying on GeoModel
1061 // currently involves hit&miss on-fly calculation of boolean volumes
1062 // GeoModelTools::MaterialComponent mat =
1063 // gm_materialHelper.collectMaterial(pv); Material newMP =
1064 // convert(mat.first); double d = mat.second / sf; layMat.addMaterial(newMP,
1065 // d / newMP.x0()); return;
1066
1067 std::vector<MaterialComponent> materialContent;
1068 collectMaterialContent(pv, materialContent);
1069
1070 for (const auto& mat : materialContent) {
1071 if (mat.second < 0)
1072 continue; // protection unsolved booleans
1073 double d = sf > 0 ? mat.second / sf : 0.;
1074 if (d > 0)
1075 layMat.addMaterial(mat.first,
1076 (mat.first.X0 > 0 ? d / mat.first.X0 : 0.));
1077 }
1078}
void addMaterial(const Material &mp, float dInX0)
Material averaging.
void collectMaterialContent(const GeoVPhysVol *gv, std::vector< Trk::MaterialComponent > &materialContent) const
material collection for volumes

◆ collectMaterialContent()

void Trk::VolumeConverter::collectMaterialContent ( const GeoVPhysVol * gv,
std::vector< Trk::MaterialComponent > & materialContent ) const

material collection for volumes

Definition at line 1080 of file VolumeConverter.cxx.

1082 {
1083
1084 // solution relying on GeoModel
1085 // currently involves hit&miss on-fly calculation of boolean volumes
1086 // GeoModelTools::MaterialComponent mat =
1087 // gm_materialHelper.collectMaterial(pv); Material newMP =
1088 // convert(mat.first); materialContent.push_back( MaterialComponent( newMP,
1089 // mat.second) ); return;
1090
1091 const GeoLogVol* lv = gv->getLogVol();
1092 Material mat = Trk::GeoMaterialConverter::convert(lv->getMaterial());
1093
1094 double motherVolume = 0.;
1095
1096 // skip volume calculation for dummy material configuration
1097 if (!Trk::GeoMaterialConverter::dummy_material(lv->getMaterial())) {
1098 const GeoShape* sh = lv->getShape();
1099 while (sh && sh->type() == "Shift") {
1100 const GeoShapeShift* shift = dynamic_cast<const GeoShapeShift*>(sh);
1101 sh = shift ? shift->getOp() : nullptr;
1102 }
1103
1104 bool isBoolean =
1105 sh && (sh->type() == "Subtraction" || sh->type() == "Union" ||
1106 sh->type() == "Intersection");
1107
1108 if (isBoolean) {
1109 Amg::Transform3D transf{Amg::Transform3D::Identity()};
1110 std::unique_ptr<Volume> vol{
1111 m_geoShapeConverter.translateGeoShape(sh, transf)};
1112 motherVolume =
1113 calculateVolume(*vol, false, std::pow(1.e-3 * mat.X0, 3));
1114 if (motherVolume < 0) {
1115 // m_geoShapeConverter.decodeShape(sh);
1116 }
1117 } else
1118 motherVolume = lv->getShape()->volume();
1119 }
1120
1121 double childVol = 0;
1122 std::string cPrevious = " ";
1123 size_t nIdentical = 0;
1124 std::vector<Trk::MaterialComponent> childMat;
1125 std::vector<const GeoVPhysVol*> children = geoGetVolumesNoXform (gv);
1126 for (const GeoVPhysVol* cv : children) {
1127 std::string cname = cv->getLogVol()->getName();
1128 if (cname == cPrevious)
1129 nIdentical++; // assuming identity for identical name and branching
1130 // history
1131 else { // scale and collect material from previous item
1132 for (const auto& cmat : childMat) {
1133 materialContent.emplace_back(cmat.first, nIdentical * cmat.second);
1134 childVol += materialContent.back().second;
1135 }
1136 childMat.clear(); // reset
1137 nIdentical = 1; // current
1138 collectMaterialContent(cv, childMat);
1139 }
1140 }
1141 for (const auto& cmat : childMat) {
1142 materialContent.emplace_back(cmat.first, nIdentical * cmat.second);
1143 childVol += materialContent.back().second;
1144 }
1145 if (motherVolume > 0 && childVol > 0)
1146 motherVolume += -1. * childVol;
1147
1148 ATH_MSG_DEBUG("collected material:" << lv->getName() << ":made of:"
1149 << lv->getMaterial()->getName()
1150 << ":density(g/mm3)" << mat.rho
1151 << ":mass:" << mat.rho * motherVolume);
1152 materialContent.emplace_back(mat, motherVolume);
1153}
#define ATH_MSG_DEBUG(x)
std::vector< const GeoVPhysVol * > geoGetVolumesNoXform(const GeoGraphNode *node, int depthLimit=1, int sizeHint=20)
Return the child volumes.
@ Material
static bool dummy_material(const GeoMaterial *)
hardcoded dummy materials : TODO : find generic criterium ( density ?
static Material convert(const GeoMaterial *gm)
Single conversion , input type GeoMaterial - output type Trk::MaterialProperties.
Trk::GeoShapeConverter m_geoShapeConverter
shape converter
double calculateVolume(const Volume &vol, bool nonBooleanOnly=false, double precision=1.e-3) const
Volume calculation : by default return analytical solution only.
Eigen::Affine3d Transform3D
virtual void shift(size_t pos, ptrdiff_t offs) override
Shift the elements of the container.

◆ estimateFraction()

double Trk::VolumeConverter::estimateFraction ( const VolumePair & sub,
double precision ) const

the tricky part of volume calculation

Definition at line 1024 of file VolumeConverter.cxx.

1025 {
1026
1027 if (!sub.first)
1028 return 0.;
1029
1030 if (sub.first && !sub.second)
1031 return 1.;
1032 double fraction = -1.;
1033
1034 std::pair<bool, std::unique_ptr<Volume>> overlap =
1035 Trk::VolumeIntersection::intersect(*sub.first, *sub.second);
1036
1037 if (overlap.first && !overlap.second)
1038 return fraction = 1.;
1039 else if (overlap.first && overlap.second) {
1040 fraction = 1. - calculateVolume(*overlap.second, true, precision) /
1041 calculateVolume(*sub.first, true, precision);
1042 return fraction;
1043 }
1044 // resolve embedded volumes
1045
1046 // trivial within required precision
1047 double volA = calculateVolume(*sub.first, true, precision);
1048 double volB = calculateVolume(*sub.second, true, precision);
1049 if ((volA > 0 && volA < precision) || (volB > 0 && volB < precision))
1050 return 1.;
1051
1052 return fraction;
1053}
static std::pair< bool, std::unique_ptr< Trk::Volume > > intersect(const Volume &volA, const Volume &volB)

◆ findVolumeSpan()

std::unique_ptr< VolumeSpan > Trk::VolumeConverter::findVolumeSpan ( const VolumeBounds & volBounds,
const Amg::Transform3D & transform,
double zTol,
double phiTol ) const

Estimation of the geometrical volume span.

Definition at line 436 of file VolumeConverter.cxx.

438 {
439 // volume shape
440 const CuboidVolumeBounds* box =
441 dynamic_cast<const CuboidVolumeBounds*>(&volBounds);
442 const TrapezoidVolumeBounds* trd =
443 dynamic_cast<const TrapezoidVolumeBounds*>(&volBounds);
444 const DoubleTrapezoidVolumeBounds* dtrd =
445 dynamic_cast<const DoubleTrapezoidVolumeBounds*>(&volBounds);
446 const BevelledCylinderVolumeBounds* bcyl =
447 dynamic_cast<const BevelledCylinderVolumeBounds*>(&volBounds);
448 const CylinderVolumeBounds* cyl =
449 dynamic_cast<const CylinderVolumeBounds*>(&volBounds);
450 const SubtractedVolumeBounds* sub =
451 dynamic_cast<const SubtractedVolumeBounds*>(&volBounds);
452 const CombinedVolumeBounds* comb =
453 dynamic_cast<const CombinedVolumeBounds*>(&volBounds);
454 const SimplePolygonBrepVolumeBounds* spb =
455 dynamic_cast<const SimplePolygonBrepVolumeBounds*>(&volBounds);
456 const PrismVolumeBounds* prism =
457 dynamic_cast<const PrismVolumeBounds*>(&volBounds);
458
459 double dPhi = 0.;
460
461 if (sub) {
462 return findVolumeSpan(sub->outer()->volumeBounds(),
463 transform * sub->outer()->transform(), zTol,
464 phiTol);
465 }
466
467 if (comb) {
468 std::unique_ptr<VolumeSpan> s1 = findVolumeSpan(
469 comb->first()->volumeBounds(),
470 transform * comb->first()->transform(), zTol, phiTol);
471 std::unique_ptr<VolumeSpan> s2 = findVolumeSpan(
472 comb->second()->volumeBounds(),
473 transform * comb->second()->transform(), zTol, phiTol);
474
475 VolumeSpan scomb;
476 scomb.rMin = std::min((*s1).rMin, (*s2).rMin);
477 scomb.rMax = std::max((*s1).rMax, (*s2).rMax);
478 scomb.xMin = std::min((*s1).xMin, (*s2).xMin);
479 scomb.xMax = std::max((*s1).xMax, (*s2).xMax);
480 scomb.yMin = std::min((*s1).yMin, (*s2).yMin);
481 scomb.yMax = std::max((*s1).yMax, (*s2).yMax);
482 scomb.zMin = std::min((*s1).zMin, (*s2).zMin);
483 scomb.zMax = std::max((*s1).zMax, (*s2).zMax);
484 if ((*s1).phiMin < (*s1).phiMax && (*s2).phiMin < (*s2).phiMax) {
485 scomb.phiMin = std::min((*s1).phiMin, (*s2).phiMin);
486 scomb.phiMax = std::max((*s1).phiMax, (*s2).phiMax);
487 } else if ((*s1).phiMin < (*s1).phiMax && (*s2).phiMin > (*s2).phiMax) {
488 if ((*s1).phiMin > (*s2).phiMax) {
489 scomb.phiMin = std::min((*s1).phiMin, (*s2).phiMin);
490 scomb.phiMax = (*s2).phiMax;
491 } else if ((*s1).phiMax < (*s2).phiMin) {
492 scomb.phiMin = (*s2).phiMin;
493 scomb.phiMax = std::max((*s1).phiMax, (*s2).phiMax);
494 } else {
495 scomb.phiMin = 0.;
496 scomb.phiMax = 2 * M_PI;
497 }
498 } else if ((*s1).phiMin > (*s1).phiMax && (*s2).phiMin < (*s2).phiMax) {
499 if ((*s2).phiMin > (*s1).phiMax) {
500 scomb.phiMin = std::min((*s1).phiMin, (*s2).phiMin);
501 scomb.phiMax = (*s1).phiMax;
502 } else if ((*s2).phiMax < (*s1).phiMin) {
503 scomb.phiMin = (*s1).phiMin;
504 scomb.phiMax = std::max((*s1).phiMax, (*s2).phiMax);
505 } else {
506 scomb.phiMin = 0.;
507 scomb.phiMax = 2 * M_PI;
508 }
509 } else {
510 scomb.phiMin = std::min((*s1).phiMin, (*s2).phiMin);
511 scomb.phiMax = std::max((*s1).phiMax, (*s2).phiMax);
512 }
513 return std::make_unique<VolumeSpan>(scomb);
514 }
515
516 //
517 double minZ{1.e6};
518 double maxZ{-1.e6};
519 double minPhi{2 * M_PI};
520 double maxPhi{0.};
521 double minR{1.e6};
522 double maxR{0.};
523 double minX{1.e6};
524 double maxX{-1.e6};
525 double minY{1.e6};
526 double maxY{-1.e6};
527
528 // defined vertices and edges
529 std::vector<Amg::Vector3D> vtx;
530 std::vector<std::pair<int, int>> edges;
531 VolumeSpan span;
532
533 if (box) {
534 vtx.emplace_back(box->halflengthX(), box->halflengthY(),
535 box->halflengthZ());
536 vtx.emplace_back(-box->halflengthX(), box->halflengthY(),
537 box->halflengthZ());
538 vtx.emplace_back(box->halflengthX(), -box->halflengthY(),
539 box->halflengthZ());
540 vtx.emplace_back(-box->halflengthX(), -box->halflengthY(),
541 box->halflengthZ());
542 vtx.emplace_back(box->halflengthX(), box->halflengthY(),
543 -box->halflengthZ());
544 vtx.emplace_back(-box->halflengthX(), box->halflengthY(),
545 -box->halflengthZ());
546 vtx.emplace_back(box->halflengthX(), -box->halflengthY(),
547 -box->halflengthZ());
548 vtx.emplace_back(-box->halflengthX(), -box->halflengthY(),
549 -box->halflengthZ());
550 edges.emplace_back(0, 1);
551 edges.emplace_back(0, 2);
552 edges.emplace_back(1, 3);
553 edges.emplace_back(2, 3);
554 edges.emplace_back(4, 5);
555 edges.emplace_back(4, 6);
556 edges.emplace_back(5, 7);
557 edges.emplace_back(6, 7);
558 edges.emplace_back(0, 4);
559 edges.emplace_back(1, 5);
560 edges.emplace_back(2, 6);
561 edges.emplace_back(3, 7);
562 }
563 if (trd) {
564 vtx.emplace_back(trd->maxHalflengthX(), trd->halflengthY(),
565 trd->halflengthZ());
566 vtx.emplace_back(-trd->maxHalflengthX(), trd->halflengthY(),
567 trd->halflengthZ());
568 vtx.emplace_back(trd->minHalflengthX(), -trd->halflengthY(),
569 trd->halflengthZ());
570 vtx.emplace_back(-trd->minHalflengthX(), -trd->halflengthY(),
571 trd->halflengthZ());
572 vtx.emplace_back(trd->maxHalflengthX(), trd->halflengthY(),
573 -trd->halflengthZ());
574 vtx.emplace_back(-trd->maxHalflengthX(), trd->halflengthY(),
575 -trd->halflengthZ());
576 vtx.emplace_back(trd->minHalflengthX(), -trd->halflengthY(),
577 -trd->halflengthZ());
578 vtx.emplace_back(-trd->minHalflengthX(), -trd->halflengthY(),
579 -trd->halflengthZ());
580 edges.emplace_back(0, 1);
581 edges.emplace_back(0, 2);
582 edges.emplace_back(1, 3);
583 edges.emplace_back(2, 3);
584 edges.emplace_back(4, 5);
585 edges.emplace_back(4, 6);
586 edges.emplace_back(5, 7);
587 edges.emplace_back(6, 7);
588 edges.emplace_back(0, 4);
589 edges.emplace_back(1, 5);
590 edges.emplace_back(2, 6);
591 edges.emplace_back(3, 7);
592 }
593 if (dtrd) {
594 vtx.emplace_back(dtrd->maxHalflengthX(), 2 * dtrd->halflengthY2(),
595 dtrd->halflengthZ());
596 vtx.emplace_back(-dtrd->maxHalflengthX(), 2 * dtrd->halflengthY2(),
597 dtrd->halflengthZ());
598 vtx.emplace_back(dtrd->medHalflengthX(), 0., dtrd->halflengthZ());
599 vtx.emplace_back(-dtrd->medHalflengthX(), 0., dtrd->halflengthZ());
600 vtx.emplace_back(dtrd->minHalflengthX(), -2 * dtrd->halflengthY1(),
601 dtrd->halflengthZ());
602 vtx.emplace_back(-dtrd->minHalflengthX(), -2 * dtrd->halflengthY1(),
603 dtrd->halflengthZ());
604 vtx.emplace_back(dtrd->maxHalflengthX(), 2 * dtrd->halflengthY2(),
605 -dtrd->halflengthZ());
606 vtx.emplace_back(-dtrd->maxHalflengthX(), 2 * dtrd->halflengthY2(),
607 -dtrd->halflengthZ());
608 vtx.emplace_back(dtrd->medHalflengthX(), 0., -dtrd->halflengthZ());
609 vtx.emplace_back(-dtrd->medHalflengthX(), 0., -dtrd->halflengthZ());
610 vtx.emplace_back(dtrd->minHalflengthX(), -2 * dtrd->halflengthY1(),
611 -dtrd->halflengthZ());
612 vtx.emplace_back(-dtrd->minHalflengthX(), -2 * dtrd->halflengthY1(),
613 -dtrd->halflengthZ());
614 edges.emplace_back(0, 1);
615 edges.emplace_back(0, 2);
616 edges.emplace_back(1, 3);
617 edges.emplace_back(2, 4);
618 edges.emplace_back(3, 5);
619 edges.emplace_back(4, 5);
620 edges.emplace_back(6, 7);
621 edges.emplace_back(6, 8);
622 edges.emplace_back(7, 9);
623 edges.emplace_back(8, 10);
624 edges.emplace_back(9, 11);
625 edges.emplace_back(10, 11);
626 edges.emplace_back(0, 6);
627 edges.emplace_back(1, 7);
628 edges.emplace_back(2, 8);
629 edges.emplace_back(3, 9);
630 edges.emplace_back(4, 10);
631 edges.emplace_back(5, 11);
632 }
633 if (bcyl) {
634 dPhi = bcyl->halfPhiSector();
635 vtx.emplace_back(0., 0., bcyl->halflengthZ());
636 vtx.emplace_back(0., 0., -bcyl->halflengthZ());
637 edges.emplace_back(0, 1);
638 if (dPhi < M_PI) {
639 const double cosDphi = std::cos(dPhi);
640 const double sinDphi = std::sin(dPhi);
641 vtx.emplace_back(bcyl->outerRadius() * cosDphi,
642 bcyl->outerRadius() * sinDphi,
643 bcyl->halflengthZ());
644 vtx.emplace_back(bcyl->innerRadius() * cosDphi,
645 bcyl->innerRadius() * sinDphi,
646 bcyl->halflengthZ());
647 vtx.emplace_back(bcyl->outerRadius() * cosDphi,
648 -bcyl->outerRadius() * sinDphi,
649 bcyl->halflengthZ());
650 vtx.emplace_back(bcyl->innerRadius() * cosDphi,
651 -bcyl->innerRadius() * sinDphi,
652 bcyl->halflengthZ());
653 vtx.emplace_back(bcyl->outerRadius() * cosDphi,
654 bcyl->outerRadius() * sinDphi,
655 -bcyl->halflengthZ());
656 vtx.emplace_back(bcyl->innerRadius() * cosDphi,
657 bcyl->innerRadius() * sinDphi,
658 -bcyl->halflengthZ());
659 vtx.emplace_back(bcyl->outerRadius() * cosDphi,
660 -bcyl->outerRadius() * sinDphi,
661 -bcyl->halflengthZ());
662 vtx.emplace_back(bcyl->innerRadius() * cosDphi,
663 -bcyl->innerRadius() * sinDphi,
664 -bcyl->halflengthZ());
665 vtx.emplace_back(bcyl->outerRadius(), 0.,
666 0.); // to distinguish phi intervals for cylinders
667 // aligned with z axis
668 edges.emplace_back(2, 3);
669 edges.emplace_back(4, 5);
670 edges.emplace_back(6, 7);
671 edges.emplace_back(8, 9);
672 if (bcyl->type() == 1 || bcyl->type() == 3) {
673 edges.emplace_back(3, 5);
674 edges.emplace_back(7, 9);
675 }
676 if (bcyl->type() == 2 || bcyl->type() == 3) {
677 edges.emplace_back(2, 4);
678 edges.emplace_back(6, 8);
679 }
680 }
681 }
682 if (cyl) {
683 dPhi = cyl->halfPhiSector();
684 vtx.emplace_back(0., 0., cyl->halflengthZ());
685 vtx.emplace_back(0., 0., -cyl->halflengthZ());
686 edges.emplace_back(0, 1);
687 if (dPhi < M_PI) {
688 const double cosDphi = std::cos(dPhi);
689 const double sinDphi = std::sin(dPhi);
690 vtx.emplace_back(cyl->outerRadius() * cosDphi,
691 cyl->outerRadius() * sinDphi, cyl->halflengthZ());
692 vtx.emplace_back(cyl->innerRadius() * cosDphi,
693 cyl->innerRadius() * sinDphi, cyl->halflengthZ());
694 vtx.emplace_back(cyl->outerRadius() * cosDphi,
695 -cyl->outerRadius() * sinDphi, cyl->halflengthZ());
696 vtx.emplace_back(cyl->outerRadius() * cosDphi,
697 -cyl->outerRadius() * sinDphi, cyl->halflengthZ());
698 vtx.emplace_back(cyl->outerRadius() * cosDphi,
699 cyl->outerRadius() * sinDphi, -cyl->halflengthZ());
700 vtx.emplace_back(cyl->innerRadius() * cosDphi,
701 cyl->innerRadius() * sinDphi, -cyl->halflengthZ());
702 vtx.emplace_back(cyl->outerRadius() * cosDphi,
703 -cyl->outerRadius() * sinDphi,
704 -cyl->halflengthZ());
705 vtx.emplace_back(cyl->outerRadius() * cosDphi,
706 -cyl->outerRadius() * sinDphi,
707 -cyl->halflengthZ());
708 vtx.emplace_back(cyl->outerRadius(), 0.,
709 0.); // to distinguish phi intervals for cylinders
710 // aligned with z axis
711 edges.emplace_back(2, 3);
712 edges.emplace_back(4, 5);
713 edges.emplace_back(6, 7);
714 edges.emplace_back(8, 9);
715 }
716 }
717
718 if (spb) {
719 const std::vector<std::pair<double, double>> vtcs = spb->xyVertices();
720 for (const auto& vtc : vtcs) {
721 vtx.emplace_back(vtc.first, vtc.second, spb->halflengthZ());
722 vtx.emplace_back(vtc.first, vtc.second, -spb->halflengthZ());
723 edges.emplace_back(vtx.size() - 2, vtx.size() - 1);
724 if (vtx.size() > 2) {
725 edges.emplace_back(
726 vtx.size() - 4, vtx.size() - 2);
727 edges.emplace_back(
728 vtx.size() - 3, vtx.size() - 1);
729 }
730 if (vtx.size() > 4) { // some diagonals
731 edges.emplace_back(vtx.size() - 2, 1);
732 edges.emplace_back(vtx.size() - 1, 0);
733 }
734 }
735 edges.emplace_back(0, vtx.size() - 2);
736 edges.emplace_back(1, vtx.size() - 1);
737 }
738
739 if (prism) {
740 const std::vector<std::pair<double, double>> vtcs = prism->xyVertices();
741 for (const auto& vtc : vtcs) {
742 vtx.emplace_back(vtc.first, vtc.second, prism->halflengthZ());
743 vtx.emplace_back(vtc.first, vtc.second, -prism->halflengthZ());
744 edges.emplace_back(vtx.size() - 2, vtx.size() - 1);
745 if (vtx.size() > 2) {
746 edges.emplace_back(
747 vtx.size() - 4, vtx.size() - 2);
748 edges.emplace_back(
749 vtx.size() - 3, vtx.size() - 1);
750 }
751 }
752 edges.emplace_back(0, vtx.size() - 2);
753 edges.emplace_back(1, vtx.size() - 1);
754 }
755
756 std::vector<Amg::Vector3D> vtxt;
757
758 for (unsigned int ie = 0; ie < vtx.size(); ie++) {
759 Amg::Vector3D gp = transform * vtx[ie];
760 vtxt.push_back(gp);
761
762 double phi = gp.phi() + M_PI;
763 double rad = gp.perp();
764
765 // collect limits from vertices
766 minX = std::min(minX, gp[0]);
767 maxX = std::max(maxX, gp[0]);
768 minY = std::min(minY, gp[1]);
769 maxY = std::max(maxY, gp[1]);
770 minZ = std::min(minZ, gp[2]);
771 maxZ = std::max(maxZ, gp[2]);
772 minR = std::min(minR, rad);
773 maxR = std::max(maxR, rad);
774 maxPhi = std::max(maxPhi, phi);
775 minPhi = std::min(minPhi, phi);
776 }
777
778 if (cyl || bcyl) {
779
780 double ro = cyl ? cyl->outerRadius() : bcyl->outerRadius();
781 double ri = cyl ? cyl->innerRadius() : bcyl->innerRadius();
782 // z span corrected for theta inclination
784 (vtxt[edges[0].first] - vtxt[edges[0].second]).unit();
785 maxZ += ro * sin(dir.theta());
786 minZ += -ro * sin(dir.theta());
787 // azimuthal & radial extent
788 if (ro < minR) { // excentric object, phi span driven by z-R extent
789 // calculate point of closest approach
790 PerigeeSurface peri;
791 Intersection closest = peri.straightLineIntersection(vtxt[1], dir);
792 double le = (vtxt[0] - vtxt[1]).norm();
793 if ((closest.position - vtxt[0]).norm() < le &&
794 (closest.position - vtxt[1]).norm() < le) {
795 if (minR > closest.position.perp() - ro)
796 minR = std::max(0., closest.position.perp() - ro);
797 // use for phi check
798 double phiClosest = closest.position.phi() + M_PI;
799 if (phiClosest < minPhi || phiClosest > maxPhi) {
800 double phiTmp = minPhi;
801 minPhi = maxPhi;
802 maxPhi = phiTmp;
803 }
804 } else
805 minR = std::max(0., minR - ro * std::abs(dir.z()));
806
807 const double aTan = std::atan2(ro, minR);
808 minPhi += -aTan;
809 maxPhi += aTan;
810 if (minPhi < 0)
811 minPhi += 2 * M_PI;
812 if (maxPhi > 2 * M_PI)
813 maxPhi += -2 * M_PI;
814
815 maxR += ro * std::abs(cos(dir.theta()));
816 } else {
817
818 double rAx = std::max(vtxt[0].perp(), vtxt[1].perp());
819 if (rAx < ri)
820 minR = ri - rAx;
821 else
822 minR = std::max(0., minR - ro * std::abs(cos(dir.theta())));
823
824 // loop over edges to check inner radial extent
825 PerigeeSurface peri;
826 for (unsigned int ie = 0; ie < edges.size(); ie++) {
828 (vtxt[edges[ie].first] - vtxt[edges[ie].second]).unit();
829 Intersection closest =
830 peri.straightLineIntersection(vtxt[edges[ie].second], dir);
831 double le =
832 (vtxt[edges[ie].first] - vtxt[edges[ie].second]).norm();
833 if ((closest.position - vtxt[edges[ie].first]).norm() < le &&
834 (closest.position - vtxt[edges[ie].second]).norm() < le)
835 if (minR > closest.position.perp())
836 minR = closest.position.perp();
837 }
838
839 if (vtxt.size() > 10) { // cylindrical section
840 // find spread of phi extent at section (-) boundary : vertices
841 // 4,5,8,9
842 double phiSecLmin = std::min(
843 std::min(vtxt[4].phi() + M_PI, vtxt[5].phi() + M_PI),
844 std::min(vtxt[8].phi() + M_PI, vtxt[9].phi() + M_PI));
845 double phiSecLmax = std::max(
846 std::max(vtxt[4].phi() + M_PI, vtxt[5].phi() + M_PI),
847 std::max(vtxt[8].phi() + M_PI, vtxt[9].phi() + M_PI));
848 // find spread of phi extent at section (+) boundary : vertices
849 // 2,3,6,7
850 double phiSecUmin = std::min(
851 std::min(vtxt[2].phi() + M_PI, vtxt[3].phi() + M_PI),
852 std::min(vtxt[6].phi() + M_PI, vtxt[7].phi() + M_PI));
853 double phiSecUmax = std::max(
854 std::max(vtxt[2].phi() + M_PI, vtxt[3].phi() + M_PI),
855 std::max(vtxt[6].phi() + M_PI, vtxt[7].phi() + M_PI));
856 minPhi = std::min(std::min(phiSecLmin, phiSecLmax),
857 std::min(phiSecUmin, phiSecUmax));
858 maxPhi = std::max(std::max(phiSecLmin, phiSecLmax),
859 std::max(phiSecUmin, phiSecUmax));
860 if (vtxt[10].phi() + M_PI < minPhi ||
861 vtxt[10].phi() + M_PI > maxPhi) {
862 minPhi = 3 * M_PI;
863 maxPhi = 0.;
864 double phiTmp;
865 for (unsigned int iv = 2; iv < vtxt.size(); iv++) {
866 phiTmp = vtxt[iv].phi() + M_PI;
867 if (phiTmp < M_PI)
868 phiTmp += 2 * M_PI;
869 minPhi = phiTmp < minPhi ? phiTmp : minPhi;
870 maxPhi = phiTmp > maxPhi ? phiTmp : maxPhi;
871 }
872 if (minPhi > 2 * M_PI)
873 minPhi += -2 * M_PI;
874 if (maxPhi > 2 * M_PI)
875 maxPhi += -2 * M_PI;
876 }
877 } else {
878 minPhi = 0.;
879 maxPhi = 2 * M_PI;
880 maxR += ro * std::abs(std::cos(dir.theta()));
881 }
882 if (minPhi >= maxPhi && (minPhi - maxPhi) < M_PI) {
883 minPhi = 0.;
884 maxPhi = 2 * M_PI;
885 }
886 }
887 } // end cyl & bcyl
888
889 if (!cyl && !bcyl) {
890 // loop over edges to check inner radial extent
891 PerigeeSurface peri;
892 for (unsigned int ie = 0; ie < edges.size(); ie++) {
894 (vtxt[edges[ie].first] - vtxt[edges[ie].second]).unit();
895 Intersection closest =
896 peri.straightLineIntersection(vtxt[edges[ie].second], dir);
897 double le = (vtxt[edges[ie].first] - vtxt[edges[ie].second]).norm();
898 if ((closest.position - vtxt[edges[ie].first]).norm() < le &&
899 (closest.position - vtxt[edges[ie].second]).norm() < le)
900 if (minR > closest.position.perp())
901 minR = closest.position.perp();
902 } // end loop over edges
903 // verify phi span - may run across step
904 if (std::abs(maxPhi - minPhi) > M_PI) {
905 double phiTmp = minPhi;
906 minPhi = 3 * M_PI;
907 maxPhi = 0.; // redo the search
908 for (unsigned int iv = 0; iv < vtxt.size(); iv++) {
909 phiTmp = vtxt[iv].phi() + M_PI;
910 if (phiTmp < M_PI)
911 phiTmp += 2 * M_PI;
912 minPhi = phiTmp < minPhi ? phiTmp : minPhi;
913 maxPhi = phiTmp > maxPhi ? phiTmp : maxPhi;
914 }
915 if (minPhi > 2 * M_PI)
916 minPhi += -2 * M_PI;
917 if (maxPhi > 2 * M_PI)
918 maxPhi += -2 * M_PI;
919 if (minPhi >= maxPhi && (minPhi - maxPhi) < M_PI) {
920 minPhi = 0.;
921 maxPhi = 2 * M_PI;
922 }
923 }
924 }
925
926 if (cyl || bcyl || box || trd || dtrd || spb || prism) {
927 span.zMin = minZ - zTol;
928 span.zMax = maxZ - +zTol;
929 minPhi = (minPhi - phiTol) < 0 ? minPhi - phiTol + 2 * M_PI
930 : minPhi - phiTol;
931 span.phiMin = minPhi;
932 maxPhi = (maxPhi + phiTol) > 2 * M_PI ? maxPhi + phiTol - 2 * M_PI
933 : maxPhi + phiTol;
934 span.phiMax = maxPhi;
935 span.rMin = std::max(70.001, minR - zTol);
936 span.rMax = maxR + zTol;
937 span.xMin = minX - zTol;
938 span.xMax = maxX - +zTol;
939 span.yMin = minY - zTol;
940 span.yMax = maxY - +zTol;
941 } else {
942 ATH_MSG_WARNING("VolumeConverter::volume shape not recognized ");
943 }
944 return std::make_unique<VolumeSpan>(span);
945}
#define M_PI
Scalar perp() const
perp method - perpendicular length
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
#define ATH_MSG_WARNING(x)
std::unique_ptr< VolumeSpan > findVolumeSpan(const VolumeBounds &volBounds, const Amg::Transform3D &transform, double zTol, double phiTol) const
Estimation of the geometrical volume span.
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Eigen::Matrix< double, 3, 1 > Vector3D
CxxUtils::transform_view_with_at< PackedLinkVector_span, ELSpanConverter > span
bool dPhi(const xAOD::TauJet &tau, const xAOD::CaloVertexedTopoCluster &cluster, float &out)
@ phi
Definition ParamDefs.h:75

◆ initMessaging()

void AthMessaging::initMessaging ( ) const
privateinherited

Initialize our message level and MessageSvc.

This method should only be called once.

Definition at line 39 of file AthMessaging.cxx.

40{
42 // If user did not set an explicit level, set a default
43 if (m_lvl == MSG::NIL) {
44 m_lvl = m_imsg ?
45 static_cast<MSG::Level>( m_imsg.load()->outputLevel(m_nm) ) :
46 MSG::INFO;
47 }
48}
std::string m_nm
Message source name.
std::atomic< IMessageSvc * > m_imsg
MessageSvc pointer.
std::atomic< MSG::Level > m_lvl
Current logging level.
IMessageSvc * getMessageSvc(bool quiet=false)

◆ leadingVolume()

double Trk::VolumeConverter::leadingVolume ( const GeoShape * sh) const
private

Definition at line 1155 of file VolumeConverter.cxx.

1155 {
1156
1157 if (sh->type() == "Subtraction") {
1158 const GeoShapeSubtraction* sub =
1159 dynamic_cast<const GeoShapeSubtraction*>(sh);
1160 if (sub)
1161 return leadingVolume(sub->getOpA());
1162 }
1163 if (sh->type() == "Union") {
1164 const GeoShapeUnion* uni = dynamic_cast<const GeoShapeUnion*>(sh);
1165 if (uni)
1166 return leadingVolume(uni->getOpA()) + leadingVolume(uni->getOpB());
1167 }
1168 if (sh->type() == "Intersection") {
1169 const GeoShapeIntersection* intr =
1170 dynamic_cast<const GeoShapeIntersection*>(sh);
1171 if (intr)
1172 return std::min(leadingVolume(intr->getOpA()),
1173 leadingVolume(intr->getOpB()));
1174 }
1175 if (sh->type() == "Shift") {
1176 const GeoShapeShift* shift = dynamic_cast<const GeoShapeShift*>(sh);
1177 if (shift)
1178 return leadingVolume(shift->getOp());
1179 }
1180
1181 return sh->volume();
1182}
double leadingVolume(const GeoShape *sh) const

◆ msg() [1/2]

MsgStream & AthMessaging::msg ( ) const
inlineinherited

The standard message stream.

Returns a reference to the default message stream May not be invoked before sysInitialize() has been invoked.

Definition at line 167 of file AthMessaging.h.

168{
169 MsgStream* ms = m_msg_tls.get();
170 if (!ms) {
171 if (!m_initialized.test_and_set()) initMessaging();
172 ms = new MsgStream(m_imsg,m_nm);
173 m_msg_tls.reset( ms );
174 }
175
176 ms->setLevel (m_lvl);
177 return *ms;
178}
boost::thread_specific_ptr< MsgStream > m_msg_tls
MsgStream instance (a std::cout like with print-out levels).
void initMessaging() const
Initialize our message level and MessageSvc.

◆ msg() [2/2]

MsgStream & AthMessaging::msg ( const MSG::Level lvl) const
inlineinherited

The standard message stream.

Returns a reference to the default message stream May not be invoked before sysInitialize() has been invoked.

Definition at line 182 of file AthMessaging.h.

183{ return msg() << lvl; }
MsgStream & msg() const
The standard message stream.

◆ msgLvl()

bool AthMessaging::msgLvl ( const MSG::Level lvl) const
inlineinherited

Test the output level.

Parameters
lvlThe message level to test against
Returns
boolean Indicating if messages at given level will be printed
Return values
trueMessages at level "lvl" will be printed

Definition at line 151 of file AthMessaging.h.

152{
153 // If user did not set explicit message level we have to initialize
154 // the messaging and retrieve the default via the MessageSvc.
155 if (m_lvl==MSG::NIL && !m_initialized.test_and_set()) initMessaging();
156
157 if (m_lvl <= lvl) {
158 msg() << lvl;
159 return true;
160 } else {
161 return false;
162 }
163}

◆ resolveBooleanVolume()

double Trk::VolumeConverter::resolveBooleanVolume ( const Volume & trVol,
double tolerance ) const

temporary owner of auxiliary volumes

small components

Definition at line 230 of file VolumeConverter.cxx.

231 {
232
233 VolumePartVec constituents{};
234 VolumePart inputVol{};
235 inputVol.parts.push_back(std::make_unique<Volume>(trVol));
236 constituents.push_back(std::move(inputVol));
237 VolumePartVec::iterator sIter = constituents.begin();
238
240 double volume = 0;
241 while (sIter != constituents.end()) {
242 bool update = false;
243 for (unsigned int ii = 0; ii < (*sIter).parts.size(); ++ii) {
244 const VolumeBounds& bounds{((*sIter).parts[ii]->volumeBounds())};
245 const CombinedVolumeBounds* comb =
246 dynamic_cast<const CombinedVolumeBounds*>(&bounds);
247 const SubtractedVolumeBounds* sub =
248 dynamic_cast<const SubtractedVolumeBounds*>(&bounds);
249 if (comb) {
250 (*sIter).parts[ii].reset(comb->first()->clone());
251 VolumePart vp(*sIter); //copy here
252 constituents.push_back(vp); //insert copy the iter can be invalidated
253 constituents.back().parts[ii].reset(comb->second()->clone()); //modify
254 constituents.push_back(std::move(vp)); //push copy
255 constituents.back().parts.emplace_back(comb->second()->clone());//modify
256 constituents.back().sign = -1. * constituents.back().sign;
257 update = true;
258 break;
259 } else if (sub) {
260 (*sIter).parts[ii].reset(sub->outer()->clone());
262 double volSub = calculateVolume(*sub->inner(), true, tolerance);
263 if (volSub < tolerance) {
264 volume += -1. * (*sIter).sign * volSub;
265 } else {
266 constituents.emplace_back(*sIter);
267 constituents.back().parts.emplace_back(
268 sub->inner()->clone());
269 constituents.back().sign = -1. * constituents.back().sign;
270 }
271 update = true;
272 break;
273 } else {
274 // component small, below tolerance
275 double volSmall = calculateVolume(*(*sIter).parts[ii]);
276 if (volSmall < tolerance) {
277 sIter=constituents.erase(sIter);
278 update = true;
279 break;
280 }
281 }
282 } //
283 if (update)
284 sIter = constituents.begin();
285 else if ((*sIter).parts.size() == 1) {
286 double volSingle = calculateVolume(*(*sIter).parts[0]);
287 volume += (*sIter).sign * volSingle;
288 sIter=constituents.erase(sIter);
289 } else {
290 std::vector<std::shared_ptr<Volume>>::iterator tit =
291 (*sIter).parts.begin();
292 bool noovrlp = false;
293 while (tit + 1 != (*sIter).parts.end()) {
294 std::pair<bool, std::unique_ptr<Volume>> overlap =
295 Trk::VolumeIntersection::intersect(**tit, **(tit + 1));
296 if (overlap.first && !overlap.second) {
297 sIter=constituents.erase(sIter);
298 noovrlp = true;
299 break;
300 } // no intersection
301 else if (overlap.first && overlap.second) {
302 (*sIter).parts.erase(tit, tit + 2);
303 (*sIter).parts.push_back(std::move(overlap.second));
304 tit = (*sIter).parts.begin();
305 } else {
306 if (calculateVolume(**tit) < tolerance) {
307 sIter=constituents.erase(sIter);
308 noovrlp = true;
309 break;
310 }
311 if (calculateVolume(**(tit + 1)) < tolerance) {
312 sIter=constituents.erase(sIter);
313 noovrlp = true;
314 break;
315 }
316 std::pair<bool, std::unique_ptr<Volume>> overlap =
318 **tit, **(tit + 1));
319 if (overlap.first) {
320 if (overlap.second) {
321 (*sIter).parts.erase(tit, tit + 2);
322 (*sIter).parts.push_back(std::move(overlap.second));
323 tit = (*sIter).parts.begin();
324 } else {
325 sIter=constituents.erase(sIter);
326 noovrlp = true;
327 break; // no intersection
328 }
329 } else
330 ++tit;
331 }
332 }
333 if (noovrlp) {
334 } else if ((*sIter).parts.size() == 1) {
335 double volSingle = calculateVolume(*(*sIter).parts[0]);
336 volume += (*sIter).sign * volSingle;
337 sIter=constituents.erase(sIter);
338 } else {
339 ++sIter;
340 }
341 }
342 }
343
344 if (!constituents.empty()) {
345 ATH_MSG_VERBOSE("boolean volume resolved to "
346 << constituents.size() << " items "
347 << ":volume estimate:" << volume);
348 }
349 return volume;
350}
#define ATH_MSG_VERBOSE(x)
static std::pair< bool, std::unique_ptr< Trk::Volume > > intersectApproximative(const Volume &volA, const Volume &volB)
std::vector< VolumePart > VolumePartVec
constexpr double tolerance

◆ setLevel()

void AthMessaging::setLevel ( MSG::Level lvl)
inherited

Change the current logging level.

Use this rather than msg().setLevel() for proper operation with MT.

Definition at line 28 of file AthMessaging.cxx.

29{
30 m_lvl = lvl;
31}

◆ splitComposedVolume()

VolumeConverter::VolumePairVec Trk::VolumeConverter::splitComposedVolume ( const Volume & trVol)
static

Decomposition of volume into set of non-overlapping subtractions from analytically calculable volume.

Check whether the first operand in the iterator is a composite one

Combined one --> Union or Intersecion

Definition at line 352 of file VolumeConverter.cxx.

353 {
354
355 VolumePairVec constituents;
356 constituents.emplace_back(std::make_unique<Volume>(trVol), nullptr);
357 VolumePairVec::iterator sIter = constituents.begin();
358 std::shared_ptr<VolumeBounds> newBounds{};
359 while (sIter != constituents.end()) {
361 const CombinedVolumeBounds* comb =
362 dynamic_cast<const Trk::CombinedVolumeBounds*>(
363 &((*sIter).first->volumeBounds()));
364 const Trk::SubtractedVolumeBounds* sub =
365 dynamic_cast<const Trk::SubtractedVolumeBounds*>(
366 &((*sIter).first->volumeBounds()));
368 if (comb) {
369 std::shared_ptr<Volume> subVol = (*sIter).second;
370 sIter = constituents.erase(sIter);
371 std::shared_ptr<Volume> combFirst{comb->first()->clone()};
372 std::shared_ptr<Volume> combSecond{comb->second()->clone()};
373 if (comb->intersection()) {
374 newBounds = std::make_shared<Trk::SubtractedVolumeBounds>(
375 std::unique_ptr<Trk::Volume>(combFirst->clone()), std::unique_ptr<Trk::Volume>(combSecond->clone()));
376 std::unique_ptr<Trk::Volume> newSubVol =
377 std::make_unique<Volume>(nullptr, std::move(newBounds));
378 if (subVol) {
379 newBounds = std::make_shared<CombinedVolumeBounds>(
380 std::unique_ptr<Trk::Volume>(subVol->clone()), std::move(newSubVol), false);
381 std::shared_ptr<Volume> newCSubVol =
382 std::make_unique<Volume>(nullptr, std::move(newBounds));
383 //insert invalidates iterators
384 constituents.insert(sIter,
385 std::make_pair(combFirst, newCSubVol));
386 } else {
387 //insert invalidates iterators
388 constituents.insert(
389 sIter, std::make_pair(combFirst, std::move(newSubVol)));
390 }
391 } else {
392 //insert invalidates iterators
393 constituents.insert(sIter, std::make_pair(combFirst, subVol));
394 if (subVol) {
395 newBounds = std::make_shared<CombinedVolumeBounds>(
396 std::unique_ptr<Trk::Volume>(subVol->clone()),
397 std::unique_ptr<Trk::Volume>(combFirst->clone()), false);
398 std::unique_ptr<Trk::Volume> newSubVol =
399 std::make_unique<Volume>(nullptr, std::move(newBounds));
400 constituents.insert(
401 sIter,
402 std::make_pair(combSecond, std::move(newSubVol)));
403 } else {
404 //insert invalidates iterators
405 constituents.insert(sIter,
406 std::make_pair(combSecond, combFirst));
407 }
408 }
409 sIter = constituents.begin();
410 } else if (sub) {
411 std::shared_ptr<Volume> subVol = (*sIter).second;
412 sIter = constituents.erase(sIter);
413 std::shared_ptr<Volume> innerVol{sub->inner()->clone()};
414 std::shared_ptr<Volume> outerVol{sub->outer()->clone()};
415 if (subVol) {
416 newBounds = std::make_shared<CombinedVolumeBounds>(
417 std::unique_ptr<Trk::Volume>(subVol->clone()),
418 std::unique_ptr<Trk::Volume>(innerVol->clone()), false);
419 std::unique_ptr<Volume> newSubVol =
420 std::make_unique<Trk::Volume>(nullptr, newBounds);
421 //insert invalidates iterators
422 constituents.insert(
423 sIter, std::make_pair(outerVol, std::move(newSubVol)));
424 } else {
425 //insert invalidates iterators
426 constituents.insert(sIter, std::make_pair(outerVol, innerVol));
427 }
428 sIter = constituents.begin();
429 } else {
430 ++sIter;
431 }
432 }
433 return constituents;
434}
const Volume * inner() const
This method returns the inner Volume.
const Volume * outer() const
This method returns the outer Volume.
std::vector< VolumePair > VolumePairVec
virtual Volume * clone() const
polymorpic deep copy
Definition Volume.cxx:60

◆ translate()

std::unique_ptr< TrackingVolume > Trk::VolumeConverter::translate ( const GeoVPhysVol * gv,
bool simplify,
bool blend,
double blendMassLimit ) const

translation of GeoVPhysVol to Trk::TrackingVolume

Definition at line 46 of file VolumeConverter.cxx.

48 {
49
50 const std::string name = gv->getLogVol()->getName();
51
52 Amg::Transform3D ident{Amg::Transform3D::Identity()};
53 std::unique_ptr<Volume> volGeo{m_geoShapeConverter.translateGeoShape(
54 gv->getLogVol()->getShape(), ident)};
55
56 // resolve volume structure into a set of non-overlapping subtractions from
57 // analytically calculable shapes
58 VolumePairVec constituents = splitComposedVolume(*volGeo);
59
60 // material properties
61 Material mat = Trk::GeoMaterialConverter::convert(gv->getLogVol()->getMaterial());
62
63 // calculate precision of volume estimate taking into account material
64 // properties
65 double precision = s_precisionInX0 * mat.X0; // required precision in mm
66
67 // volume estimate from GeoShape
68 double volumeFromGeoShape =
69 -1; // replace with database info when available
70
71 // volume estimate from resolveBoolean
72 // double volumeBoolean = calculateVolume(volGeo,false,pow(precision,3)); //
73 // TODO : test on inert material
74
75 // volume estimate from Volume
76 double volume = volumeFromGeoShape >= 0 ? volumeFromGeoShape : -1.;
77 if ((simplify || blend) && volumeFromGeoShape < 0) {
78 double fraction = 0.;
79 volume = 0.;
80 for (const VolumePair& cs : constituents) {
81 fraction = estimateFraction(cs, precision);
82 if (fraction < 0) {
83 volume = -1;
84 break;
85 } else
86 volume += fraction * calculateVolume(*cs.first);
87 }
88 }
89
90 // evaluate complexity of shape
91 // simple case
92 if (constituents.size() == 1 && !constituents[0].second) {
93 return std::make_unique<TrackingVolume>(*volGeo, mat, nullptr, nullptr,
94 name);
95 }
96 // build envelope
97 std::unique_ptr<Volume> envelope{};
98 std::string envName = name;
99
100 std::unique_ptr<TrackingVolume> trEnv{};
101
102 bool blended = false;
103
104 if (constituents.size() == 1) {
105
106 envelope = std::make_unique<Volume>(*(constituents.front().first),
107 volGeo->transform());
108 double volEnv = calculateVolume(*constituents.front().first);
109
110 if (blend && volume > 0 && volEnv > 0 &&
111 volume * mat.rho < blendMassLimit)
112 blended = true;
113
114 if ((simplify || blended) && volume > 0 && volEnv > 0) {
115 // simplified material rescales X0, l0 and density
116 double fraction = volume / volEnv;
117 Material matScaled(mat.X0 / fraction, mat.L0 / fraction, mat.A,
118 mat.Z, fraction * mat.rho);
119 if (blend && !blended)
120 envName = envName + "_PERM";
121 trEnv = std::make_unique<TrackingVolume>(*envelope, matScaled,
122 nullptr, nullptr, envName);
123 } else {
124 auto confinedVols =std::make_unique<std::vector<TrackingVolume*>>();
125 confinedVols->push_back(std::make_unique<TrackingVolume>(*volGeo, mat, nullptr, nullptr, name).release());
126 envName = name + "_envelope";
127 trEnv = std::make_unique<TrackingVolume>(*envelope, dummyMaterial, std::move(confinedVols), envName);
128 }
129
130 return trEnv;
131 }
132
133 // composed shapes : derive envelope from span
134 Amg::Transform3D transf = volGeo->transform();
135 std::unique_ptr<VolumeSpan> span =
136 findVolumeSpan(volGeo->volumeBounds(), transf, 0., 0.);
137
138 bool isCyl = false;
139 for (const auto& fv : constituents) {
140 const CylinderVolumeBounds* cyl =
141 dynamic_cast<const CylinderVolumeBounds*>(
142 &(fv.first->volumeBounds()));
143 if (cyl) {
144 isCyl = true;
145 break;
146 }
147 }
148
149 ATH_MSG_DEBUG(__FILE__ << ":" << __LINE__
150 << "envelope estimate: object contains cylinder:"
151 << name << ":" << isCyl);
152 ATH_MSG_DEBUG(__FILE__ << ":" << __LINE__
153 << "complex volume span for envelope:" << name
154 << ":x range:" << (*span).xMin << ","
155 << (*span).xMax);
156 ATH_MSG_DEBUG(__FILE__ << ":" << __LINE__
157 << "complex volume span for envelope:" << name
158 << ":y range:" << (*span).yMin << ","
159 << (*span).yMax);
160 ATH_MSG_DEBUG(__FILE__ << ":" << __LINE__
161 << "complex volume span for envelope:" << name
162 << ":z range:" << (*span).zMin << ","
163 << (*span).zMax);
164 ATH_MSG_DEBUG(__FILE__ << ":" << __LINE__
165 << "complex volume span for envelope:" << name
166 << ":R range:" << (*span).rMin << ","
167 << (*span).rMax);
168 ATH_MSG_DEBUG(__FILE__ << ":" << __LINE__
169 << "complex volume span for envelope:" << name
170 << ":phi range:" << (*span).phiMin << ","
171 << (*span).phiMax);
172
173 if (!isCyl) { // cuboid envelope
174 Amg::Transform3D cylTrf{
175 transf * Amg::Translation3D{0.5 * ((*span).xMin + (*span).xMax),
176 0.5 * ((*span).yMin + (*span).yMax),
177 0.5 * ((*span).zMin + (*span).zMax)}};
178
179 std::shared_ptr<VolumeBounds> bounds =
180 std::make_shared<CuboidVolumeBounds>(
181 0.5 * ((*span).xMax - (*span).xMin),
182 0.5 * ((*span).yMax - (*span).yMin),
183 0.5 * ((*span).zMax - (*span).zMin));
184 envelope = std::make_unique<Volume>(
185 makeTransform(cylTrf), std::move(bounds));
186 } else {
187 double dPhi = (*span).phiMin > (*span).phiMax
188 ? (*span).phiMax - (*span).phiMin + 2 * M_PI
189 : (*span).phiMax - (*span).phiMin;
190 std::shared_ptr<VolumeBounds> cylBounds{};
191 Amg::Transform3D cylTrf{transf};
192 if (dPhi < 2 * M_PI) {
193 double aPhi = 0.5 * ((*span).phiMax + (*span).phiMin);
194 cylBounds = std::make_shared<CylinderVolumeBounds>(
195 (*span).rMin, (*span).rMax, 0.5 * dPhi,
196 0.5 * ((*span).zMax - (*span).zMin));
197 cylTrf = cylTrf * Amg::getRotateZ3D(aPhi);
198 } else {
199 cylBounds = std::make_shared<CylinderVolumeBounds>(
200 (*span).rMin, (*span).rMax,
201 0.5 * ((*span).zMax - (*span).zMin));
202 }
203 envelope = std::make_unique<Volume>(
204 makeTransform(cylTrf), std::move(cylBounds));
205 }
206
207 double volEnv = calculateVolume(*envelope);
208
209 if (blend && volume > 0 && volEnv > 0 && volume * mat.rho < blendMassLimit)
210 blended = true;
211
212 if ((simplify || blended) && volume > 0 && volEnv > 0) {
213 double fraction = volume / volEnv;
214 Material matScaled(mat.X0 / fraction, mat.L0 / fraction, mat.A, mat.Z,
215 fraction * mat.rho);
216 if (blend && !blended)
217 envName = envName + "_PERM";
218 trEnv = std::make_unique<TrackingVolume>(*envelope, mat, nullptr,
219 nullptr, envName);
220 } else {
221 auto confinedVols = std::make_unique<std::vector<TrackingVolume*>>();
222 confinedVols->push_back( std::make_unique<TrackingVolume>(*volGeo, mat, nullptr, nullptr, name).release());
223 envName = envName + "_envelope";
224 trEnv = std::make_unique<TrackingVolume>(*envelope, dummyMaterial, std::move(confinedVols), envName);
225 }
226
227 return trEnv;
228}
static VolumePairVec splitComposedVolume(const Volume &trVol)
Decomposition of volume into set of non-overlapping subtractions from analytically calculable volume.
static constexpr double s_precisionInX0
std::pair< std::shared_ptr< Volume >, std::shared_ptr< Volume > > VolumePair
double estimateFraction(const VolumePair &sub, double precision) const
the tricky part of volume calculation
static std::string release
Definition computils.h:50
Amg::Transform3D getRotateZ3D(double angle)
Rotate the coordinate system by an angle around the z-axis.
Eigen::Translation< double, 3 > Translation3D
std::unique_ptr< Amg::Transform3D > makeTransform(const Amg::Transform3D &trf)
@ ident
Definition HitInfo.h:77

Member Data Documentation

◆ ATLAS_THREAD_SAFE

std::atomic_flag m_initialized AthMessaging::ATLAS_THREAD_SAFE = ATOMIC_FLAG_INIT
mutableprivateinherited

Messaging initialized (initMessaging).

Definition at line 141 of file AthMessaging.h.

◆ m_geoShapeConverter

Trk::GeoShapeConverter Trk::VolumeConverter::m_geoShapeConverter
private

shape converter

Definition at line 102 of file VolumeConverter.h.

◆ m_imsg

std::atomic<IMessageSvc*> AthMessaging::m_imsg { nullptr }
mutableprivateinherited

MessageSvc pointer.

Definition at line 135 of file AthMessaging.h.

135{ nullptr };

◆ m_lvl

std::atomic<MSG::Level> AthMessaging::m_lvl { MSG::NIL }
mutableprivateinherited

Current logging level.

Definition at line 138 of file AthMessaging.h.

138{ MSG::NIL };

◆ m_msg_tls

boost::thread_specific_ptr<MsgStream> AthMessaging::m_msg_tls
mutableprivateinherited

MsgStream instance (a std::cout like with print-out levels).

Definition at line 132 of file AthMessaging.h.

◆ m_nm

std::string AthMessaging::m_nm
privateinherited

Message source name.

Definition at line 129 of file AthMessaging.h.

◆ s_precisionInX0

double Trk::VolumeConverter::s_precisionInX0
staticconstexprprivate
Initial value:
=
1.e-3

Definition at line 104 of file VolumeConverter.h.


The documentation for this class was generated from the following files: