DD4hep  1.30.0
Detector Description Toolkit for High Energy Physics
Volumes.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : M.Frank
11 //
12 //==========================================================================
13 
14 // Framework include files
15 #include <DD4hep/Detector.h>
16 #include <DD4hep/Printout.h>
17 #include <DD4hep/InstanceCount.h>
18 #include <DD4hep/MatrixHelpers.h>
20 
21 // ROOT include files
22 #include <TROOT.h>
23 #include <TClass.h>
24 #include <TColor.h>
25 #include <TGeoShape.h>
26 #include <TGeoVolume.h>
27 #include <TGeoNode.h>
28 #include <TGeoMatrix.h>
29 #include <TGeoMedium.h>
30 
31 #include <TGeoVoxelFinder.h>
32 #include <TGeoShapeAssembly.h>
33 #include <TGeoScaledShape.h>
34 #include <TMap.h>
35 
36 // C/C++ include files
37 #include <climits>
38 #include <iostream>
39 #include <stdexcept>
40 #include <sstream>
41 #include <iomanip>
42 
43 using namespace dd4hep;
44 
45 /*
46  * The section below uses the new ROOT features using user extensions to volumes
47  * and placements. Once this is common, the above mechanism should be thrown away....
48  *
49  * M.Frank
50  */
51 
52 typedef TGeoNode geo_node_t;
53 typedef TGeoVolume geo_volume_t;
54 typedef TGeoVolumeAssembly geo_assembly_t;
55 
60 
61 namespace {
62 
63  static constexpr double s_rotation_test_limit = 1e-12;
64  static bool s_verifyCopyNumbers = true;
65 
66  template <typename T> typename T::Object* _userExtension(const T& v) {
67  typedef typename T::Object O;
68  O* o = (O*)(v.ptr()->GetUserExtension());
69  return o;
70  }
71 
72  TGeoVolume* _createTGeoVolume(const std::string& name, TGeoShape* s, TGeoMedium* m) {
73  geo_volume_t* e = new geo_volume_t(name.c_str(),s,m);
74  e->SetUserExtension(new Volume::Object());
75  return e;
76  }
77  TGeoVolume* _createTGeoVolumeAssembly(const std::string& name) {
78  geo_assembly_t* e = new geo_assembly_t(name.c_str()); // It is important to use the correct constructor!!
79  e->SetUserExtension(new Assembly::Object());
80  return e;
81  }
82  TGeoVolumeMulti* _createTGeoVolumeMulti(const std::string& name, TGeoMedium* medium) {
83  TGeoVolumeMulti* e = new TGeoVolumeMulti(name.c_str(), medium);
84  e->SetUserExtension(new VolumeMulti::Object());
85  return e;
86  }
87  PlacedVolume::Object* _data(const PlacedVolume& v) {
88  PlacedVolume::Object* o = _userExtension(v);
89  if (o) return o;
90  throw std::runtime_error("dd4hep: Attempt to access invalid handle of type: PlacedVolume");
91  }
93  Volume::Object* _data(const Volume& v, bool throw_exception = true) {
94  //if ( v.ptr() && v.ptr()->IsA() == TGeoVolume::Class() ) return v.data<Volume::Object>();
95  Volume::Object* o = _userExtension(v);
96  if (o)
97  return o;
98  else if (!throw_exception)
99  return nullptr;
100  throw std::runtime_error("dd4hep: Attempt to access invalid handle of type: PlacedVolume");
101  }
102 
103  class VolumeImport {
104  public:
105  void setShapeTitle(TGeoVolume* vol) {
106  if ( vol ) {
107  TGeoShape* sh = vol->GetShape();
108  std::string tag = get_shape_tag(sh);
109  sh->SetTitle(tag.c_str());
110  }
111  }
112 
113  public:
115  void operator()(TGeoVolume* v) {
116  TClass* c = v->IsA();
117  if ( !v->GetUserExtension() ) {
118  if ( c == geo_volume_t::Class() )
119  v->SetUserExtension(new Volume::Object());
120  else if ( c == geo_assembly_t::Class() )
121  v->SetUserExtension(new Assembly::Object());
122  else if ( c == TGeoVolumeMulti::Class() )
123  v->SetUserExtension(new VolumeMulti::Object());
124  else
125  except("dd4hep","VolumeImport: Unknown TGeoVolume sub-class: %s",v->IsA()->GetName());
126  }
127  if ( c == TGeoVolumeMulti::Class() ) {
128  TGeoVolumeMulti* mv = (TGeoVolumeMulti*)v;
129  for( int i=0, n=mv->GetNvolumes(); i<n; ++i ) {
130  TGeoVolume* vol = mv->GetVolume(i);
131  this->setShapeTitle(vol);
132  (*this)(vol);
133  }
134  }
135  for( Int_t i=0; i<v->GetNdaughters(); ++i ) {
136  geo_node_t* pv = v->GetNode(i);
137  if ( !pv->GetUserExtension() )
138  pv->geo_node_t::SetUserExtension(new PlacedVolume::Object());
139  (*this)(pv->GetVolume());
140  }
141  }
143  void operator()(TGeoVolume* new_v, TGeoVolume* old_v, SensitiveDetector sd, int set_bit) {
144  if ( !new_v || !old_v ) {
145  except("dd4hep","VolumeImport: ERROR: The refected volume is INVALID!");
146  }
147  else if ( !old_v->GetUserExtension() ) {
148  except("dd4hep","VolumeImport: ERROR: Reflection of non-dd4hep volume %s",new_v->IsA()->GetName());
149  }
150  else if ( !new_v->GetUserExtension() ) {
151  TClass* c = new_v->IsA();
152  Volume old_vol(old_v);
153  Volume new_vol(new_v);
154  if ( sd.isValid() && old_vol.isSensitive() ) {
155  new_vol.setSensitiveDetector(sd);
156  }
157  if ( c == geo_volume_t::Class() ) {
158  Volume::Object *new_e, *old_e = (Volume::Object*)_data(old_vol);
159  old_e->reflected = new_v;
160  new_v->SetUserExtension(new_e = new Volume::Object(*old_e));
161  new_e->reflected = old_v;
162  }
163  else if ( c == geo_assembly_t::Class() ) {
164  Assembly::Object *new_e, *old_e = (Assembly::Object*)_data(old_vol);
165  old_e->reflected = new_v;
166  new_v->SetUserExtension(new_e = new Assembly::Object(*old_e));
167  new_e->reflected = old_v;
168  }
169  else if ( c == TGeoVolumeMulti::Class() ) {
170  VolumeMulti::Object *new_e, *old_e = (VolumeMulti::Object*)_data(old_vol);
171  TGeoVolumeMulti* new_mv = (TGeoVolumeMulti*)new_v;
172  TGeoVolumeMulti* old_mv = (TGeoVolumeMulti*)old_v;
173  new_v->SetUserExtension(new_e = new VolumeMulti::Object(*old_e));
174  old_e->reflected = new_v;
175  new_e->reflected = old_v;
176  for(int i=0, n=new_mv->GetNvolumes(); i<n; ++i) {
177  TGeoVolume* vol = new_mv->GetVolume(i);
178  this->setShapeTitle(vol);
179  (*this)(vol, old_mv->GetVolume(i), sd, set_bit);
180  }
181  }
182  else
183  except("dd4hep","VolumeImport: Unknown TGeoVolume sub-class: %s",new_v->IsA()->GetName());
184 
185  new_vol.setSensitiveDetector(old_vol.sensitiveDetector());
186  new_vol.setVisAttributes(old_vol.visAttributes());
187  new_vol.setLimitSet(old_vol.limitSet());
188  new_vol.setRegion(old_vol.region());
189 
190  if ( set_bit >= 0 ) new_vol.setFlagBit(set_bit);
191  for(Int_t i=0; i<new_v->GetNdaughters(); ++i) {
192  geo_node_t* pv = new_v->GetNode(i);
193  geo_node_t* ov = old_v->GetNode(i);
194  if ( !pv->GetUserExtension() ) {
195  auto* e = (PlacedVolume::Object*)ov->geo_node_t::GetUserExtension();
196  pv->geo_node_t::SetUserExtension(new PlacedVolume::Object(*e));
197  }
198  (*this)(pv->GetVolume(), ov->GetVolume(), sd, set_bit);
199  }
200  }
201  }
202  };
203 
204  TGeoVolume* MakeReflection(TGeoVolume* v, const char* newname=0) {
205  static TMap map(100);
206  TGeoVolume* vol = (TGeoVolume*)map.GetValue(v);
207  if ( vol ) {
208  if (newname && newname[0]) v->SetName(newname);
209  return vol;
210  }
211  vol = v->CloneVolume();
212  if (!vol) {
213  printout(ERROR,"MakeReflection", "Cannot clone volume %s\n", v->GetName());
214  return nullptr;
215  }
216  map.Add(v, vol);
217  std::string nam;
218  if (newname && newname[0]) {
219  nam = newname;
220  vol->SetName(newname);
221  }
222  else {
223  nam = v->GetName();
224  vol->SetName((nam+"_refl").c_str());
225  }
226  delete vol->GetNodes();
227  vol->SetNodes(nullptr);
228  vol->SetBit(TGeoVolume::kVolumeImportNodes, kFALSE);
229  v->CloneNodesAndConnect(vol);
230  // The volume is now properly cloned, but with the same shape.
231  // Reflect the shape (if any) and connect it.
232  if (v->GetShape()) {
233  TGeoScale* scale = new TGeoScale( 1., 1.,-1.);
234  TGeoShape* reflected_shape =
235  TGeoScaledShape::MakeScaledShape((nam+"_shape_refl").c_str(), v->GetShape(), scale);
236  vol->SetShape(reflected_shape);
237  //vol->SetShape(v->GetShape());
238  }
239  // Reflect the daughters.
240  Int_t nd = vol->GetNdaughters();
241  if ( !nd ) return vol;
242  TGeoVolume *new_vol;
243  if ( !vol->GetFinder() ) {
244  for (Int_t i=0; i < nd; i++) {
245  TGeoNodeMatrix* node = (TGeoNodeMatrix*)vol->GetNode(i);
246  TGeoMatrix* local = node->GetMatrix();
247  // printf("%s before\n", node->GetName());
248  // local->Print();
249  Bool_t reflected = local->IsReflection();
250  TGeoMatrix* local_cloned = new TGeoCombiTrans(*local);
251  local_cloned->RegisterYourself();
252  node->SetMatrix(local_cloned);
253  if (!reflected) {
254  // We need to reflect only the translation and propagate to daughters.
255  // H' = Sz * H * Sz
256  local_cloned->ReflectZ(kTRUE);
257  local_cloned->ReflectZ(kFALSE);
258  // printf("%s after\n", node->GetName());
259  // node->GetMatrix()->Print();
260  new_vol = MakeReflection(node->GetVolume());
261  node->SetVolume(new_vol);
262  continue;
263  }
264  // The next daughter is already reflected, so reflect on Z everything and stop
265  local_cloned->ReflectZ(kTRUE); // rot + tr
266  // printf("%s already reflected... After:\n", node->GetName());
267  // node->GetMatrix()->Print();
268  }
269  if ( vol->GetVoxels() ) vol->GetVoxels()->Voxelize();
270  return vol;
271  }
272  // Volume is divided, so we have to reflect the division.
273  // printf(" ... divided %s\n", fFinder->ClassName());
274  TGeoPatternFinder *new_finder = v->GetFinder()->MakeCopy(kTRUE);
275  if (!new_finder) {
276  printout(ERROR,"MakeReflection", "Could not copy finder for volume %s", v->GetName());
277  return nullptr;
278  }
279  new_finder->SetVolume(vol);
280  vol->SetFinder(new_finder);
281  TGeoNodeOffset *nodeoff;
282  new_vol = 0;
283  for (Int_t i=0; i<nd; i++) {
284  nodeoff = (TGeoNodeOffset*)vol->GetNode(i);
285  nodeoff->SetFinder(new_finder);
286  new_vol = MakeReflection(nodeoff->GetVolume());
287  nodeoff->SetVolume(new_vol);
288  }
289  return vol;
290  }
291 
292  int get_copy_number(TGeoVolume* par) {
293  TObjArray* a = par ? par->GetNodes() : 0;
294  int copy_nr = (a ? a->GetEntries() : 0);
295  return copy_nr;
296  }
297 
298 }
299 
300 
302 void ReflectionBuilder::execute() const {
303  TGeoIterator next(detector.manager().GetTopVolume());
304  bool print_active = isActivePrintLevel(DEBUG);
305  TGeoNode *node;
306  while ( (node=next()) ) {
307  TGeoMatrix* matrix = node->GetMatrix();
308  if (matrix->IsReflection()) {
309  if ( print_active ) {
310  printout(INFO,"ReflectionBuilder","Reflection matrix:");
311  matrix->Print();
312  }
313  Volume vol(node->GetVolume());
314  TGeoMatrix* mclone = new TGeoCombiTrans(*matrix);
315  mclone->RegisterYourself();
316  // Reflect just the rotation component
317  //mclone->ReflectZ(kFALSE, kTRUE);
318  if ( print_active ) {
319  printout(INFO,"ReflectionBuilder","CLONE matrix:");
320  mclone->Print();
321  }
322  TGeoNodeMatrix* nodematrix = (TGeoNodeMatrix*)node;
323  nodematrix->SetMatrix(mclone);
324  if ( print_active ) {
325  printout(INFO,"ReflectionBuilder","Reflected volume: %s ", vol.name());
326  }
327  Volume refl = vol.reflect(vol.sensitiveDetector());
328  node->SetVolume(refl.ptr());
329  }
330  }
331 }
332 
335 }
336 
339 }
340 
343  ++refCount;
344  return this;
345 }
348  --refCount;
349  if ( 0 == refCount ) delete this;
350 }
351 
354  : TGeoExtension(), volIDs()
355 {
356  magic = magic_word();
358 }
359 
362  : TGeoExtension(c), magic(std::move(c.magic)), refCount(0), volIDs(std::move(c.volIDs)) {
364 }
365 
368  : TGeoExtension(), magic(c.magic), refCount(0), volIDs() {
370  volIDs = c.volIDs;
371 }
372 
375  if ( this->params ) this->params->release();
377 }
378 
381  ++this->refCount;
382 #ifdef ___print_vols
383  else cout << "Placement grabbed....." << endl;
384 #endif
385  return this;
386 }
387 
390  PlacedVolumeExtension* ext = const_cast<PlacedVolumeExtension*>(this);
391  --ext->refCount;
392  if ( 0 == ext->refCount ) delete ext;
393 }
394 
396 std::vector<PlacedVolumeExtension::VolID>::const_iterator
397 PlacedVolumeExtension::VolIDs::find(const std::string& name) const {
398  for (Base::const_iterator i = this->Base::begin(); i != this->Base::end(); ++i)
399  if (name == (*i).first)
400  return i;
401  return this->end();
402 }
403 
405 std::pair<std::vector<PlacedVolumeExtension::VolID>::iterator, bool>
406 PlacedVolumeExtension::VolIDs::insert(const std::string& name, int value) {
407  Base::iterator i = this->Base::begin();
408  for (; i != this->Base::end(); ++i)
409  if (name == (*i).first)
410  break;
411  //
412  if (i != this->Base::end()) {
413  return make_pair(i, false);
414  }
415  i = this->Base::emplace(this->Base::end(), name, value);
416  return make_pair(i, true);
417 }
418 
421  std::stringstream str;
422  str << std::hex;
423  for(const auto& i : *this ) {
424  str << i.first << "=" << std::setw(4) << std::right
425  << std::setfill('0') << i.second << std::setfill(' ') << " ";
426  }
427  return str.str();
428 }
429 
432  PlacedVolume::Object* o = _userExtension(*this);
433  return o;
434 }
435 
437 const char* PlacedVolume::type() const {
438  return m_element ? m_element->IsA()->GetName() : "UNKNOWN-PlacedVolume";
439 }
440 
443  return m_element ? m_element->GetNumber() : -1;
444 }
445 
448  return Material(m_element ? m_element->GetMedium() : 0);
449 }
450 
453  return Volume(m_element ? m_element->GetVolume() : 0);
454 }
455 
458  return Volume(m_element ? m_element->GetMotherVolume() : 0);
459 }
460 
462 std::size_t PlacedVolume::num_daughters() const {
463  return m_element ? m_element->GetNdaughters() : 0;
464 }
465 
467 PlacedVolume PlacedVolume::daughter(std::size_t which) const {
468  if ( m_element ) {
469  if ( which < (std::size_t)m_element->GetNdaughters() ) {
470  return m_element->GetDaughter(which);
471  }
472  except("Volume","+++ Access daughter %ld of %s [Has only %d daughters]",
473  which, m_element->GetName(), m_element->GetNdaughters());
474  }
475  except("Volume","+++ Cannot access daughters of a non-existing volume!");
476  return nullptr;
477 }
478 
481  return _data(*this)->volIDs;
482 }
483 
485 PlacedVolume& PlacedVolume::addPhysVolID(const std::string& nam, int value) {
486  auto* o = _data(*this);
487  if ( !o->params ) {
488  o->volIDs.emplace_back(nam, value);
489  return *this;
490  }
491  if ( value > 0 ) {
492  except("PlacedVolume",
493  "+++ addPhysVolID(%s): parameterised volumes only accept '0' is volID."
494  "These automatically get overwritten with the copy number!",
495  ptr()->GetName());
496  }
497  if ( !o->volIDs.empty() ) {
498  except("PlacedVolume",
499  "+++ addPhysVolID(%s): parameterised volumes can only host 1 physical volume ID."
500  " vol id '%s' is already defined!", ptr()->GetName(), o->volIDs[0].first.c_str());
501  }
502  for(PlacedVolume pv : o->params->placements) {
503  auto* p = _data(pv);
504  p->volIDs.emplace_back(nam, pv->GetNumber());
505  }
506  return *this;
507 }
508 
510 const TGeoMatrix& PlacedVolume::matrix() const {
511  if ( !isValid() ) {
512  except("PlacedVolume","+++ matrix: Failed to access invalid PlacedVolume! [Invalid handle]");
513  }
514  return *(m_element->GetMatrix());
515 }
516 
519  const double* ptr = matrix().GetTranslation();
520  return Position(ptr[0],ptr[1],ptr[2]);
521 }
522 
524 std::string PlacedVolume::toString() const {
525  std::stringstream str;
526  Object* obj = _data(*this);
527  str << m_element->GetName() << ": vol='" << m_element->GetVolume()->GetName()
528  << "' mat:'" << m_element->GetMatrix()->GetName()
529  << "' volID[" << obj->volIDs.size() << "] ";
530  for (VolIDs::const_iterator i = obj->volIDs.begin(); i != obj->volIDs.end(); ++i)
531  str << (*i).first << "=" << (*i).second << " ";
532  str << std::ends;
533  return str.str();
534 }
535 
538 : TGeoExtension(), region(), limits(), vis(), sens_det() {
540 }
541 
544  detail::deletePtr(properties);
545  region.clear();
546  limits.clear();
547  vis.clear();
548  sens_det.clear();
550 }
551 
554  this->copy(c);
555 }
556 
559  this->copy(c);
560  return *this;
561 }
562 
565  if ( this != &c ) {
566  magic = c.magic;
567  region = c.region;
568  limits = c.limits;
569  vis = c.vis;
570  sens_det = c.sens_det;
572  detail::deletePtr(properties);
573  if ( c.properties ) {
574  properties = new TList();
575  properties->SetOwner();
576  TIter next(properties);
577  TNamed *property;
578  while ((property = (TNamed*)next())) properties->Add(new TNamed(*property));
579  }
580  }
581 }
582 
585  VolumeExtension* ext = const_cast<VolumeExtension*>(this);
586  ++ext->refCount;
587 #ifdef ___print_vols
588  if ( ext->sens_det.isValid() )
589  cout << "Volume grabbed with valid sensitive detector....." << endl;
590  else
591  cout << "Volume grabbed....." << endl;
592 #endif
593  return ext;
594 }
595 
598  VolumeExtension* ext = const_cast<VolumeExtension*>(this);
599  --ext->refCount;
600  if ( 0 == ext->refCount ) {
601 #ifdef ___print_vols
602  cout << "Volume deleted....." << endl;
603 #endif
604  delete ext;
605  }
606  else {
607 #ifdef ___print_vols
608  cout << "VolumeExtension::Release::refCount:" << ext->refCount << endl;
609 #endif
610  }
611 }
612 
614 Volume::Volume(const std::string& nam) {
615  m_element = _createTGeoVolume(nam,0,0);
616 }
617 
619 Volume::Volume(const std::string& nam, const std::string& title) {
620  m_element = _createTGeoVolume(nam,0,0);
621  m_element->SetTitle(title.c_str());
622 }
623 
625 Volume::Volume(const std::string& nam, const Solid& sol, const Material& mat) {
626  m_element = _createTGeoVolume(nam, sol.ptr(), mat.ptr());
627 }
628 
630 Volume::Volume(const std::string& nam, const std::string& title, const Solid& sol, const Material& mat) {
631  m_element = _createTGeoVolume(nam, sol.ptr(), mat.ptr());
632  m_element->SetTitle(title.c_str());
633 }
634 
637  s_verifyCopyNumbers = value;
638 }
639 
642  Volume::Object* o = _userExtension(*this);
643  return o;
644 }
645 
647 const char* Volume::type() const {
648  return m_element ? m_element->IsA()->GetName() : "UNKNOWN-Volume";
649 }
650 
653  return this->reflect(this->sensitiveDetector());
654 }
655 
658  if ( m_element ) {
659  VolumeImport imp;
660  Object* o = data();
661  if ( !o->reflected.isValid() ) {
662  TGeoVolume* vol = MakeReflection(m_element);
663  imp(vol, m_element, sd, Volume::REFLECTED);
664  o->reflected = vol;
665  }
666  return o->reflected;
667  }
668  except("dd4hep","Volume: Attempt to reflect an invalid Volume handle.");
669  return *this;
670 }
671 
674  if ( m_element ) {
675  VolumeImport imp;
676  imp(m_element);
677  return *this;
678  }
679  except("dd4hep","Volume: Attempt to import an invalid Volume handle.");
680  return *this;
681 }
682 
684 void Volume::setFlagBit(unsigned int bit) {
685  if ( bit <= 31 ) {
686  data()->flags |= 1<<bit;
687  return;
688  }
689  except("Volume","+++ Volume flag bit outsize range [0...31]: %d",bit);
690 }
691 
693 bool Volume::testFlagBit(unsigned int bit) const {
694  if ( bit <= 31 ) {
695  return (data()->flags & 1<<bit) != 0;
696  }
697  except("Volume","+++ Volume flag bit outsize range [0...31]: %d",bit);
698  return false; // Anyhow never called. Only to satisfy the compiler.
699 }
700 
702 bool Volume::isReflected() const {
703  return testFlagBit(REFLECTED);
704 }
705 
707 bool Volume::isAssembly() const {
708  return m_element ? m_element->IsAssembly() : false;
709 }
710 
712 Volume Volume::divide(const std::string& divname, int iaxis, int ndiv,
713  double start, double step, int numed, const char* option) {
714  TGeoVolume* p = m_element;
715  if ( p ) {
716  TGeoVolume* mvp = p->Divide(divname.c_str(), iaxis, ndiv, start, step, numed, option);
717  if ( mvp ) {
718  VolumeImport imp;
719  imp(mvp);
720  return VolumeMulti(mvp);
721  }
722  except("dd4hep","Volume: Failed to divide volume %s -> %s [Invalid result]",
723  p->GetName(), divname.c_str());
724  }
725  except("dd4hep","Volume: Attempt to divide an invalid logical volume.");
726  return nullptr;
727 }
728 
729 PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, int id, TGeoMatrix* transform) {
730  TGeoVolume* parent = par;
731  if ( !parent ) {
732  except("dd4hep","Volume: Attempt to assign daughters to an invalid physical parent volume.");
733  }
734  else if ( !daughter ) {
735  except("dd4hep","Volume: Attempt to assign an invalid physical daughter volume.");
736  }
737  else if ( !transform ) {
738  except("dd4hep","Volume: Attempt to place volume without placement matrix.");
739  }
740  if ( transform != detail::matrix::_identity() ) {
741  std::string nam = std::string(daughter->GetName()) + "_placement";
742  transform->SetName(nam.c_str());
743  }
744  TGeoShape* shape = daughter->GetShape();
745  // Need to fix the daughter's BBox of assemblies, if the BBox was not calculated....
746  if ( shape->IsA() == TGeoShapeAssembly::Class() ) {
747  TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
748  as->NeedsBBoxRecompute();
749  as->ComputeBBox();
750  }
751  const Double_t* r = transform->GetRotationMatrix();
752  if ( r ) {
753  Double_t test_rot = r[0] + r[4] + r[8] - 3.0;
754  if ( TMath::Abs(test_rot) < s_rotation_test_limit )
755  transform->ResetBit(TGeoMatrix::kGeoRotation);
756  else
757  transform->SetBit(TGeoMatrix::kGeoRotation);
758 
759  if ( transform->IsRotation() ) {
760  Double_t det =
761  r[0]*r[4]*r[8] + r[3]*r[7]*r[2] + r[6]*r[1]*r[5] -
762  r[2]*r[4]*r[6] - r[5]*r[7]*r[0] - r[8]*r[1]*r[3];
764  if ( det < 0e0 ) {
765  transform->SetBit(TGeoMatrix::kGeoReflection);
766  printout(DEBUG, "PlacedVolume",
767  "REFLECTION: (x.Cross(y)).Dot(z): %8.3g Parent: %s [%s] Daughter: %s [%s]",
768  det, par->GetName(), par->IsA()->GetName(),
769  daughter->GetName(), daughter->IsA()->GetName());
770  }
771  }
772  }
773  geo_node_t* n {nullptr};
774  TString nam_id = TString::Format("%s_%d", daughter->GetName(), id);
775  if ( s_verifyCopyNumbers ) {
776  n = static_cast<geo_node_t*>(parent->GetNode(nam_id));
777  if ( n != 0 ) {
778  printout(ERROR,"PlacedVolume","++ Attempt to place already exiting node %s",(const char*)nam_id);
779  }
780  }
781  /* n = */ parent->AddNode(daughter, id, transform);
782  //n = static_cast<geo_node_t*>(parent->GetNode(nam_id));
783  n = static_cast<geo_node_t*>(parent->GetNodes()->Last());
784  if ( nam_id != n->GetName() ) {
785  printout(ERROR,"PlacedVolume","++ FAILED to place node %s",(const char*)nam_id);
786  }
787  PlacedVolume::Object* extension = new PlacedVolume::Object();
788  n->geo_node_t::SetUserExtension(extension);
789  return PlacedVolume(n);
790 }
791 
792 PlacedVolume _addNode(TGeoVolume* par, Volume daughter, int copy_nr, const Rotation3D& rot3D) {
793  TGeoRotation r;
794  double elements[9];
795  rot3D.GetComponents(elements);
796  r.SetMatrix(elements);
797  auto matrix = std::make_unique<TGeoCombiTrans>(TGeoTranslation(0,0,0),r);
798  return _addNode(par, daughter, copy_nr, matrix.release());
799 }
800 
801 PlacedVolume _addNode(TGeoVolume* par, Volume daughter, int copy_nr, const Transform3D& tr) {
802  TGeoRotation r;
803  double elements[9];
804  Position pos3D;
805  Rotation3D rot3D;
806  tr.GetRotation(rot3D);
807  tr.GetTranslation(pos3D);
808  rot3D.GetComponents(elements);
809  r.SetMatrix(elements);
810  auto matrix = std::make_unique<TGeoCombiTrans>(TGeoTranslation(pos3D.x(), pos3D.y(), pos3D.z()),r);
811  return _addNode(par, daughter, copy_nr, matrix.release());
812 }
813 
815 PlacedVolume Volume::placeVolume(const Volume& volume, TGeoMatrix* tr) const {
816  return _addNode(m_element, volume, get_copy_number(m_element), tr);
817 }
818 
820 PlacedVolume Volume::placeVolume(const Volume& volume, int copy_nr, TGeoMatrix* tr) const {
821  return _addNode(m_element, volume, copy_nr, tr);
822 }
823 
825 PlacedVolume Volume::placeVolume(const Volume& volume, const Transform3D& trans) const {
826  return _addNode(m_element, volume, get_copy_number(m_element), trans);
827 }
828 
831  return _addNode(m_element, volume, get_copy_number(m_element), detail::matrix::_identity());
832 }
833 
835 PlacedVolume Volume::placeVolume(const Volume& volume, const Position& pos) const {
836  return _addNode(m_element, volume, get_copy_number(m_element), detail::matrix::_translation(pos));
837 }
838 
840 PlacedVolume Volume::placeVolume(const Volume& volume, const RotationZYX& rot) const {
841  return _addNode(m_element, volume, get_copy_number(m_element), detail::matrix::_rotationZYX(rot));
842 }
843 
845 PlacedVolume Volume::placeVolume(const Volume& volume, const Rotation3D& rot) const {
846  return _addNode(m_element, volume, get_copy_number(m_element), rot);
847 }
848 
850 PlacedVolume Volume::placeVolume(const Volume& volume, int copy_no, const Transform3D& trans) const {
851  return _addNode(m_element, volume, copy_no, trans);
852 }
853 
855 PlacedVolume Volume::placeVolume(const Volume& volume, int copy_no) const {
856  return _addNode(m_element, volume, copy_no, detail::matrix::_identity());
857 }
858 
860 PlacedVolume Volume::placeVolume(const Volume& volume, int copy_no, const Position& pos) const {
861  return _addNode(m_element, volume, copy_no, detail::matrix::_translation(pos));
862 }
863 
865 PlacedVolume Volume::placeVolume(const Volume& volume, int copy_no, const RotationZYX& rot) const {
866  return _addNode(m_element, volume, copy_no, detail::matrix::_rotationZYX(rot));
867 }
868 
870 PlacedVolume Volume::placeVolume(const Volume& volume, int copy_no, const Rotation3D& rot) const {
871  return _addNode(m_element, volume, copy_no, rot);
872 }
873 
876  size_t count, double inc, double start)
877 {
878  Transform3D offset(1e0, 0e0, 0e0, axis == X_axis ? start : 0e0,
879  0e0, 1e0, 0e0, axis == Y_axis ? start : 0e0,
880  0e0, 0e0, 1e0, axis == Z_axis ? start : 0e0);
881  Transform3D tr(1e0, 0e0, 0e0, axis == X_axis ? inc : 0e0,
882  0e0, 1e0, 0e0, axis == Y_axis ? inc : 0e0,
883  0e0, 0e0, 1e0, axis == Z_axis ? inc : 0e0);
884  PlacedVolume pv = paramVolume1D(offset, entity, count, tr);
885  auto* data = pv.data();
886  data->params->flags = axis | REPLICATED;
887  return pv;
888 }
889 
891 PlacedVolume Volume::paramVolume1D(Volume entity, size_t count, const Position& inc) {
892  return paramVolume1D(Transform3D(), entity, count, Transform3D(inc));
893 }
894 
896 PlacedVolume Volume::paramVolume1D(Volume entity, size_t count, const RotationZYX& inc) {
897  return paramVolume1D(Transform3D(), entity, count, Transform3D(inc));
898 }
899 
901 PlacedVolume Volume::paramVolume1D(Volume entity, size_t count, const Transform3D& inc) {
902  return paramVolume1D(Transform3D(), entity, count, inc);
903 }
904 
907  Volume entity,
908  size_t count,
909  const Transform3D& trafo)
910 {
911  Transform3D tr(start);
912  PlacedVolume pv =
913  _addNode(m_element, entity, get_copy_number(m_element), detail::matrix::_transform(tr));
914  auto* data = pv.data();
915  if ( pv->GetNdaughters() > 1 ) {
916  except("Volume","paramVolume1D: Mother %s has too many daughters: %ld "
917  "Parameterized volumes may only have one single daughter!",
918  ptr()->GetName(), pv.volume()->GetNdaughters());
919  }
921  data->params->addref();
922  data->params->flags = PARAMETERIZED;
923  data->params->start = start;
924  data->params->trafo1D.first = trafo;
925  data->params->trafo1D.second = count;
926  data->params->trafo2D.second = 0;
927  data->params->trafo3D.second = 0;
928  data->params->placements.emplace_back(pv);
929  for(size_t i=1; i < count; ++i) {
930  tr *= trafo;
931  PlacedVolume ppv =
932  _addNode(m_element, entity, get_copy_number(m_element), detail::matrix::_transform(tr));
933  data->params->placements.emplace_back(ppv);
934  ppv.data()->params = data->params->addref();
935  }
936  return pv;
937 }
938 
941  size_t count_1,
942  const Transform3D& trafo_1,
943  size_t count_2,
944  const Transform3D& trafo_2)
945 {
946  return paramVolume2D(Transform3D(), entity, count_1, trafo_1, count_2, trafo_2);
947 }
948 
951  Volume entity,
952  size_t count_1,
953  const Position& pos_1,
954  size_t count_2,
955  const Position& pos_2)
956 {
957  return paramVolume2D(start, entity, count_1, Transform3D(pos_1), count_2, Transform3D(pos_2));
958 }
959 
962  size_t count_1,
963  const Position& pos_1,
964  size_t count_2,
965  const Position& pos_2)
966 {
967  return paramVolume2D(Transform3D(), entity, count_1, Transform3D(pos_1), count_2, Transform3D(pos_2));
968 }
969 
972  Volume entity,
973  size_t count_1,
974  const Transform3D& trafo_1,
975  size_t count_2,
976  const Transform3D& trafo_2)
977 {
978  PlacedVolume pv =
979  _addNode(m_element, entity, get_copy_number(m_element), detail::matrix::_transform(start));
980  auto* data = pv.data();
981  if ( pv->GetNdaughters() > 1 ) {
982  except("Volume","paramVolume1D: Mother %s has too many daughters: %ld "
983  "Parameterized volumes may only have one single daughter!",
984  ptr()->GetName(), pv.volume()->GetNdaughters());
985  }
987  data->params->addref();
988  data->params->flags = PARAMETERIZED;
989  data->params->start = start;
990  data->params->trafo1D.first = trafo_1;
991  data->params->trafo1D.second = count_1;
992  data->params->trafo2D.first = trafo_2;
993  data->params->trafo2D.second = count_2;
994  data->params->trafo3D.second = 0;
995  data->params->placements.emplace_back(pv);
996  Transform3D tr2(start);
997  for(size_t j=0; j < count_2; ++j) {
998  Transform3D tr1 = tr2;
999  for(size_t i = 0; i < count_1; ++i) {
1000  if ( !( i == 0 && j == 0 ) ) {
1001  PlacedVolume ppv =
1002  _addNode(m_element, entity, get_copy_number(m_element), detail::matrix::_transform(tr1));
1003  data->params->placements.emplace_back(ppv);
1004  ppv.data()->params = data->params->addref();
1005  }
1006  tr1 *= trafo_1;
1007  }
1008  tr2 *= trafo_2;
1009  }
1010  return pv;
1011 }
1012 
1015  Volume entity,
1016  size_t count_1,
1017  const Position& pos_1,
1018  size_t count_2,
1019  const Position& pos_2,
1020  size_t count_3,
1021  const Position& pos_3)
1022 {
1023  return paramVolume3D(start, entity,
1024  count_1, Transform3D(pos_1),
1025  count_2, Transform3D(pos_2),
1026  count_3, Transform3D(pos_3));
1027 }
1028 
1031  size_t count_1,
1032  const Position& pos_1,
1033  size_t count_2,
1034  const Position& pos_2,
1035  size_t count_3,
1036  const Position& pos_3)
1037 {
1038  return paramVolume3D(Transform3D(), entity,
1039  count_1, Transform3D(pos_1),
1040  count_2, Transform3D(pos_2),
1041  count_3, Transform3D(pos_3));
1042 }
1043 
1046  Volume entity,
1047  size_t count_1,
1048  const Transform3D& trafo_1,
1049  size_t count_2,
1050  const Transform3D& trafo_2,
1051  size_t count_3,
1052  const Transform3D& trafo_3)
1053 {
1054  PlacedVolume pv =
1055  _addNode(m_element, entity, get_copy_number(m_element), detail::matrix::_transform(start));
1056  auto* data = pv.data();
1057  if ( pv->GetNdaughters() > 1 ) {
1058  except("Volume","paramVolume1D: Mother %s has too many daughters: %ld "
1059  "Parameterized volumes may only have one single daughter!",
1060  ptr()->GetName(), pv.volume()->GetNdaughters());
1061  }
1063  data->params->addref();
1064  data->params->flags = PARAMETERIZED;
1065  data->params->start = start;
1066  data->params->trafo1D.first = trafo_1;
1067  data->params->trafo1D.second = count_1;
1068  data->params->trafo2D.first = trafo_2;
1069  data->params->trafo2D.second = count_2;
1070  data->params->trafo3D.first = trafo_3;
1071  data->params->trafo3D.second = count_3;
1072  data->params->placements.emplace_back(pv);
1073  Transform3D tr3(start);
1074  for(size_t k=0; k < count_3; ++k) {
1075  Transform3D tr2 = tr3;
1076  for(size_t j=0; j < count_2; ++j) {
1077  Transform3D tr1 = tr2;
1078  for(size_t i = 0; i < count_1; ++i) {
1079  if ( !( i == 0 && j == 0 && k == 0 ) ) {
1080  PlacedVolume ppv =
1081  _addNode(m_element, entity, get_copy_number(m_element), detail::matrix::_transform(tr1));
1082  data->params->placements.emplace_back(ppv);
1083  ppv.data()->params = data->params->addref();
1084  }
1085  tr1 *= trafo_1;
1086  }
1087  tr2 *= trafo_2;
1088  }
1089  tr3 *= trafo_3;
1090  }
1091  return pv;
1092 }
1093 
1095 const Volume& Volume::setOption(const std::string& opt) const {
1096  if ( isValid() ) {
1097  m_element->SetOption(opt.c_str());
1098  return *this;
1099  }
1100  throw std::runtime_error("dd4hep: Attempt to access invalid handle of type: PlacedVolume");
1101 }
1102 
1104 std::string Volume::option() const {
1105  return m_element->GetOption();
1106 }
1107 
1109 const Volume& Volume::setMaterial(const Material& mat) const {
1110  if (mat.isValid()) {
1111  TGeoMedium* medium = mat._ptr<TGeoMedium>();
1112  if (medium) {
1113  m_element->SetMedium(medium);
1114  return *this;
1115  }
1116  throw std::runtime_error("dd4hep: Volume: Medium " + std::string(mat.name()) + " is not registered with geometry manager.");
1117  }
1118  throw std::runtime_error("dd4hep: Volume: Attempt to assign invalid material.");
1119 }
1120 
1123  return Material(m_element->GetMedium());
1124 }
1125 
1127 const Volume& Volume::setVisAttributes(const VisAttr& attr) const {
1128  if ( attr.isValid() ) {
1129  VisAttr::Object* vis = attr.data<VisAttr::Object>();
1130  TColor* col = vis->color;
1131  if ( col ) {
1132  int draw_style = vis->drawingStyle;
1133  int line_style = vis->lineStyle;
1134  int col_num = col->GetNumber();
1135  int col_tr_num = vis->colortr->GetNumber();
1136  m_element->SetVisibility(vis->visible ? kTRUE : kFALSE);
1137  m_element->SetVisContainers(kTRUE);
1138  m_element->SetVisDaughters(vis->showDaughters ? kTRUE : kFALSE);
1139  printout(DEBUG,"setVisAttributes",
1140  "Set color %3d transparent(alpha:%.3f): %3d [%02X,%02X,%02X] DrawingStyle:%9s LineStyle:%6s for volume %s",
1141  col_num, vis->alpha, col_tr_num,
1142  int(255*col->GetRed()),
1143  int(255*col->GetGreen()),
1144  int(255*col->GetBlue()),
1145  draw_style == VisAttr::SOLID ? "Solid" : "Wireframe",
1146  line_style == VisAttr::SOLID ? "Solid" : "Dashed",
1147  name()
1148  );
1149  m_element->SetLineWidth(10);
1150  m_element->SetLineColor(col_num);
1151  m_element->SetFillColor(col_tr_num);
1152  if (draw_style == VisAttr::SOLID) {
1153  m_element->SetFillStyle(1001); // Root: solid
1154 
1155 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,29,0)
1156  // Set directly transparency to the volume, NOT to the material as for ROOT < 6.29
1157  m_element->ResetTransparency(Char_t((1.0-vis->alpha)*100));
1158 #else
1159  // As suggested by Valentin Volkl https://sft.its.cern.ch/jira/browse/DDFORHEP-20
1160  //
1161  // According to https://root.cern.ch/phpBB3/viewtopic.php?t=2309#p66013
1162  // a transparency>50 will make a volume invisible in the normal pad.
1163  // Hence: possibly restrict transparency to a maximum of 50.
1164  // but let's see first how this behaves.
1165  m_element->SetTransparency(Char_t((1.0-vis->alpha)*100));
1166 #endif
1167  }
1168  else {
1169  printout(DEBUG,"setVisAttributes","Set to wireframe vis:%s",name());
1170  m_element->SetLineColor(kBlack);
1171  m_element->SetFillColor(0);
1172  m_element->SetFillStyle(0); // Root: hollow
1173  }
1174  if (line_style == VisAttr::SOLID) // Root line style: 1=solid, 2=dash, 3=dot, 4=dash-dot.
1175  m_element->SetLineStyle(1);
1176  else if (line_style == VisAttr::DASHED)
1177  m_element->SetLineStyle(2);
1178  else
1179  m_element->SetLineStyle(line_style);
1180  }
1181  else {
1182  except("Volume","setVisAttributes: encountered valid, but badly initialized visattr: %s",attr.name());
1183  }
1184  }
1185  Volume::Object* o = _userExtension(*this);
1186  if ( o ) o->vis = attr;
1187  return *this;
1188 }
1189 
1191 const Volume& Volume::setVisAttributes(const Detector& description, const std::string& nam) const {
1192  if (!nam.empty()) {
1193  VisAttr attr = description.visAttributes(nam);
1194  setVisAttributes(attr);
1195  }
1196  return *this;
1197 }
1198 
1200 const Volume& Volume::setAttributes(const Detector& description, const std::string& rg, const std::string& ls, const std::string& vis) const {
1201  if (!rg.empty())
1202  setRegion(description.region(rg));
1203  if (!ls.empty())
1204  setLimitSet(description.limitSet(ls));
1205  setVisAttributes(description, vis);
1206  return *this;
1207 }
1208 
1211  Object* o = _data(*this, false);
1212  if (o) return o->vis;
1213  return VisAttr();
1214 }
1215 
1217 const Volume& Volume::setSolid(const Solid& sol) const {
1218  m_element->SetShape(sol);
1219  return *this;
1220 }
1221 
1224  return Solid((*this)->GetShape());
1225 }
1226 
1229  Box box = this->solid();
1230  if ( box.isValid() ) {
1231  return box;
1232  }
1233  else if ( !isValid() ) {
1234  except("dd4hep","Volume: Cannot access the bounding box of an invalid volume [Invalid Handle]!");
1235  }
1236  except("dd4hep","Volume: Cannot access the bounding box an object of type: %s shape: %s",
1237  this->ptr()->IsA()->GetName(), this->ptr()->GetShape()->IsA()->GetName());
1238  return box;
1239 }
1240 
1242 const Volume& Volume::setRegion(const Detector& description, const std::string& nam) const {
1243  if (!nam.empty()) {
1244  return setRegion(description.region(nam));
1245  }
1246  return *this;
1247 }
1248 
1250 const Volume& Volume::setRegion(const Region& obj) const {
1251  _data(*this)->region = obj;
1252  return *this;
1253 }
1254 
1257  return _data(*this)->region;
1258 }
1259 
1261 const Volume& Volume::setLimitSet(const Detector& description, const std::string& nam) const {
1262  if (!nam.empty()) {
1263  return setLimitSet(description.limitSet(nam));
1264  }
1265  return *this;
1266 }
1267 
1269 const Volume& Volume::setLimitSet(const LimitSet& obj) const {
1270  _data(*this)->limits = obj;
1271  return *this;
1272 }
1273 
1276  return _data(*this)->limits;
1277 }
1278 
1281  //cout << "Setting sensitive detector '" << obj.name() << "' to volume:" << ptr() << " " << name() << endl;
1282  _data(*this)->sens_det = obj;
1283  return *this;
1284 }
1285 
1288  const Object* o = _data(*this);
1289  return o->sens_det;
1290 }
1291 
1293 bool Volume::isSensitive() const {
1294  return _data(*this)->sens_det.isValid();
1295 }
1296 
1299  return _data(*this)->properties != nullptr;
1300 }
1301 
1303 void Volume::addProperty(const std::string& nam, const std::string& val) const {
1304  auto* o = _data(*this);
1305  if ( !o->properties ) {
1306  o->properties = new TList();
1307  o->properties->SetOwner();
1308  }
1309  TNamed *prop = (TNamed*)o->properties->FindObject(nam.c_str());
1310  if ( !prop ) {
1311  o->properties->Add(new TNamed(nam.c_str(), val.c_str()));
1312  return;
1313  }
1314  except("Volume::addProperty", "Volume: '%s' Property '%s' is already set!",
1315  ptr()->GetName(), nam.c_str());
1316 }
1317 
1319 std::string Volume::getProperty(const std::string& nam, const std::string& default_val) const {
1320  const auto* o = _data(*this);
1321  if ( !o->properties ) {
1322  return default_val;
1323  }
1324  TNamed *prop = (TNamed*)o->properties->FindObject(nam.c_str());
1325  if ( prop ) return prop->GetTitle();
1326  return default_val;
1327 }
1328 
1330 Assembly::Assembly(const std::string& nam) {
1331  m_element = _createTGeoVolumeAssembly(nam);
1332 }
1333 
1335 VolumeMulti::VolumeMulti(const std::string& nam, Material mat) {
1336  m_element = _createTGeoVolumeMulti(nam, mat.ptr());
1337 }
1338 
1341  if ( m_element ) {
1342  // This will lead to an exception if the type is not TGeoVolumeMulti
1343  TGeoVolumeMulti* multi = detail::safe_cast<TGeoVolumeMulti>::cast(m_element);
1344  if ( multi ) {
1345  import();
1346  return;
1347  }
1348  // Force a bad cast exception
1350  if ( handle.isValid() ) {}
1351  }
1352 }
1353 
1355 std::string dd4hep::toStringMesh(PlacedVolume place, int prec) {
1356  Volume vol = place->GetVolume();
1357  TGeoMatrix* mat = place->GetMatrix();
1358  Solid sol = vol.solid();
1359  std::stringstream os;
1360  struct _numbering {
1361  double adjust(double value) const {
1362  if ( std::abs(value) < TGeoShape::Tolerance() )
1363  return 0.0;
1364  return value/dd4hep::cm;
1365  }
1366  } _vertex;
1367 
1368  if ( vol->IsA() == TGeoVolumeAssembly::Class() ) {
1369  for(int i=0; i<vol->GetNdaughters(); ++i) {
1370  os << toStringMesh(vol->GetNode(i), prec) << std::endl;
1371  }
1372  return os.str();
1373  }
1374 
1375  // Prints shape parameters
1376  int nvert = 0, nsegs = 0, npols = 0;
1377  sol->GetMeshNumbers(nvert, nsegs, npols);
1378  Double_t* points = new Double_t[3*nvert];
1379  sol->SetPoints(points);
1380 
1381  os << std::setw(16) << std::left << sol->IsA()->GetName()
1382  << " " << nvert << " Mesh-points:" << std::endl;
1383  os << std::setw(16) << std::left << sol->IsA()->GetName() << " " << sol->GetName()
1384  << " N(mesh)=" << sol->GetNmeshVertices()
1385  << " N(vert)=" << nvert << " N(seg)=" << nsegs << " N(pols)=" << npols << std::endl;
1386 
1387  for(int i=0; i<nvert; ++i) {
1388  Double_t* p = points + 3*i;
1389  Double_t global[3], local[3] = {p[0], p[1], p[2]};
1390  mat->LocalToMaster(local, global);
1391  os << std::setw(16) << std::left << sol->IsA()->GetName() << " " << std::setw(3) << std::left << i
1392  << " Local (" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(local[0])
1393  << ", " << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(local[1])
1394  << ", " << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(local[2])
1395  << ") Global (" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(global[0])
1396  << ", " << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(global[1])
1397  << ", " << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(global[2])
1398  << ")" << std::endl;
1399  }
1400  Box box = sol;
1401  const Double_t* org = box->GetOrigin();
1402  os << std::setw(16) << std::left << sol->IsA()->GetName()
1403  << " Bounding box: "
1404  << " dx=" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(box->GetDX())
1405  << " dy=" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(box->GetDY())
1406  << " dz=" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(box->GetDZ())
1407  << " Origin: x=" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(org[0])
1408  << " y=" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(org[1])
1409  << " z=" << std::setw(7) << std::setprecision(prec) << std::fixed << std::right << _vertex.adjust(org[2])
1410  << std::endl;
1411 
1413  delete [] points;
1414  return os.str();
1415 }
1416 
dd4hep::detail::matrix::_translation
TGeoTranslation * _translation(const Position &pos)
Convert a Position object to a TGeoTranslation.
Definition: MatrixHelpers.cpp:55
dd4hep::Detector::manager
virtual TGeoManager & manager() const =0
Access the geometry manager of this instance.
dd4hep::VolumeMulti
Implementation class extending the ROOT mulit-volumes (TGeoVolumeMulti)
Definition: Volumes.h:728
dd4hep::Volume::Z_axis
@ Z_axis
Definition: Volumes.h:394
dd4hep::VolumeExtension::Release
virtual void Release() const override
TGeoExtension overload: Method called always when the pointer to the extension is not needed anymore.
Definition: Volumes.cpp:597
dd4hep::Volume::setLimitSet
const Volume & setLimitSet(const Detector &description, const std::string &name) const
Set the limits to the volume. Note: If the name string is empty, the action is ignored.
Definition: Volumes.cpp:1261
dd4hep::Volume::isAssembly
bool isAssembly() const
Test if this volume is an assembly structure.
Definition: Volumes.cpp:707
dd4hep::VolumeExtension
Implementation class extending the ROOT volume (TGeoVolume)
Definition: Volumes.h:310
dd4hep::VisAttrObject::colortr
TColor * colortr
Definition: ObjectsInterna.h:92
dd4hep::Volume::enableCopyNumberCheck
static void enableCopyNumberCheck(bool value)
Set flag to enable copy number checks when inserting new nodes.
Definition: Volumes.cpp:636
dd4hep::Volume::hasProperties
bool hasProperties() const
Check for existence of properties.
Definition: Volumes.cpp:1298
dd4hep::Assembly::Assembly
Assembly()=default
Default constructor.
dd4hep::Volume::ReplicationAxis
ReplicationAxis
Definition: Volumes.h:388
dd4hep::VolumeExtension::region
Region region
Region reference.
Definition: Volumes.h:321
v
View * v
Definition: MultiView.cpp:28
dd4hep::SensitiveDetector
Handle class to hold the information of a sensitive detector.
Definition: DetElement.h:44
dd4hep::detail::matrix::_rotationZYX
TGeoRotation * _rotationZYX(const RotationZYX &rot)
Convert a RotationZYX object to a newly created TGeoRotation.
Definition: MatrixHelpers.cpp:59
MatrixHelpers.h
Detector.h
dd4hep::PlacedVolumeExtension
Implementation class extending the ROOT placed volume.
Definition: Volumes.h:79
dd4hep::PlacedVolumeExtension::~PlacedVolumeExtension
virtual ~PlacedVolumeExtension()
Default destructor.
Definition: Volumes.cpp:374
dd4hep::VolumeMulti::VolumeMulti
VolumeMulti()=default
Default constructor.
dd4hep::PlacedVolumeExtension::Release
virtual void Release() const override
TGeoExtension overload: Method called always when the pointer to the extension is not needed anymore.
Definition: Volumes.cpp:389
dd4hep::VolumeExtension::reflected
Handle< TGeoVolume > reflected
Reference to the reflected volume (or to the original volume for reflections)
Definition: Volumes.h:329
dd4hep::PlacedVolume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:173
dd4hep::VisAttr
Handle class describing visualization attributes.
Definition: Objects.h:324
dd4hep::Volume::paramVolume2D
PlacedVolume paramVolume2D(Volume entity, size_t count_1, const Transform3D &inc_1, size_t count_2, const Transform3D &inc_2)
2D Parameterised volume implementation
Definition: Volumes.cpp:940
geo_volume_t
TGeoVolume geo_volume_t
Definition: Volumes.cpp:53
dd4hep::NamedObject::GetName
const char * GetName() const
Access name.
Definition: NamedObject.h:58
dd4hep::LimitSet::limits
const std::set< Limit > & limits() const
Accessor to limits container.
Definition: Objects.cpp:464
dd4hep::PlacedVolume::addPhysVolID
PlacedVolume & addPhysVolID(const std::string &name, int value)
Add identifier.
Definition: Volumes.cpp:485
dd4hep::detail::matrix::_identity
TGeoIdentity * _identity()
Access the TGeo identity transformation.
Definition: MatrixHelpers.cpp:27
dd4hep::Volume::setOption
const Volume & setOption(const std::string &opt) const
Set the volume's option value.
Definition: Volumes.cpp:1095
dd4hep::Volume::solid
Solid solid() const
Access to Solid (Shape)
Definition: Volumes.cpp:1223
dd4hep::Handle::isValid
bool isValid() const
Check the validity of the object held by the handle.
Definition: Handle.h:128
dd4hep::Handle< NamedObject >
dd4hep::Detector::region
virtual Region region(const std::string &name) const =0
Retrieve a region object by its name from the detector description.
dd4hep::detail::matrix::_transform
TGeoHMatrix * _transform(const Transform3D &trans)
Convert a Transform3D object to a newly created TGeoHMatrix.
Definition: MatrixHelpers.cpp:140
dd4hep::Volume::setRegion
const Volume & setRegion(const Detector &description, const std::string &name) const
Set the regional attributes to the volume. Note: If the name string is empty, the action is ignored.
Definition: Volumes.cpp:1242
dd4hep::PlacedVolume::Object
PlacedVolumeExtension Object
Definition: Volumes.h:175
dd4hep::Rotation3D
ROOT::Math::Rotation3D Rotation3D
Definition: Objects.h:113
dd4hep::PlacedVolumeExtension::volIDs
VolIDs volIDs
ID container.
Definition: Volumes.h:127
dd4hep::magic_word
unsigned long long int magic_word()
Access to the magic word, which is protecting some objects against memory corruptions.
Definition: Handle.h:53
dd4hep::Solid_type< TGeoShape >
dd4hep::Volume::paramVolume1D
PlacedVolume paramVolume1D(const Transform3D &start, Volume entity, size_t count, const Transform3D &inc)
1D Parameterised volume implementation
Definition: Volumes.cpp:906
dd4hep::Volume::isSensitive
bool isSensitive() const
Accessor if volume is sensitive (ie. is attached to a sensitive detector)
Definition: Volumes.cpp:1293
dd4hep::VolumeExtension::magic
unsigned long magic
Magic word to detect memory corruptions.
Definition: Volumes.h:313
dd4hep::Handle::name
const char * name() const
Access the object name (or "" if not supported by the object)
dd4hep::VolumeExtension::vis
VisAttr vis
Reference to visualization attributes.
Definition: Volumes.h:325
dd4hep::Volume::placeVolume
PlacedVolume placeVolume(const Volume &volume) const
Place daughter volume. The position and rotation are the identity.
Definition: Volumes.cpp:830
dd4hep::PlacedVolumeExtension::Parameterisation::addref
Parameterisation * addref()
Increase ref count.
Definition: Volumes.cpp:342
dd4hep::Handle::clear
Handle< T > & clear()
Release the object held by the handle.
Definition: Handle.h:136
dd4hep::VolumeExtension::refCount
long refCount
Reference count on object (used to implement Grab/Release)
Definition: Volumes.h:315
dd4hep::Volume::material
Material material() const
Access to the Volume material.
Definition: Volumes.cpp:1122
dd4hep::PlacedVolumeExtension::Parameterisation::release
void release()
Decrease ref count.
Definition: Volumes.cpp:347
dd4hep::Material
Handle class describing a material.
Definition: Objects.h:272
dd4hep::Volume::REFLECTED
@ REFLECTED
Definition: Volumes.h:386
dd4hep::Volume::option
std::string option() const
Access the volume's option value.
Definition: Volumes.cpp:1104
dd4hep::PlacedVolume::daughter
PlacedVolume daughter(std::size_t which) const
Access the daughter by index.
Definition: Volumes.cpp:467
dd4hep::Volume::PARAMETERIZED
@ PARAMETERIZED
Definition: Volumes.h:390
dd4hep::PlacedVolume::Processor::Processor
Processor()
Default constructor.
dd4hep::PlacedVolumeExtension::VolIDs
Volume ID container.
Definition: Volumes.h:88
dd4hep::Utilities::GetName
const char * GetName(T *p)
Definition: Utilities.h:45
dd4hep::Volume::REPLICATED
@ REPLICATED
Definition: Volumes.h:389
dd4hep::Volume
Handle class holding a placed volume (also called physical volume)
Definition: Volumes.h:378
dd4hep::Volume::Y_axis
@ Y_axis
Definition: Volumes.h:393
dd4hep::VisAttrObject::showDaughters
unsigned char showDaughters
Definition: ObjectsInterna.h:96
dd4hep::Volume::setSensitiveDetector
const Volume & setSensitiveDetector(const SensitiveDetector &obj) const
Assign the sensitive detector structure.
Definition: Volumes.cpp:1280
dd4hep::VisAttrObject::lineStyle
unsigned char lineStyle
Definition: ObjectsInterna.h:95
dd4hep::Volume::setSolid
const Volume & setSolid(const Solid &s) const
Set the volume's solid shape.
Definition: Volumes.cpp:1217
dd4hep::VolumeExtension::copy
void copy(const VolumeExtension &c)
Copy the object.
Definition: Volumes.cpp:564
dd4hep::Handle::data
Q * data() const
Access to an unrelated object type.
Definition: Handle.h:161
dd4hep::LimitSet
Handle class describing a set of limits as they are used for simulation.
Definition: Objects.h:425
dd4hep::PlacedVolume::material
Material material() const
Volume material.
Definition: Volumes.cpp:447
dd4hep::Volume::limitSet
LimitSet limitSet() const
Access to the limit set.
Definition: Volumes.cpp:1275
dd4hep::Volume::replicate
PlacedVolume replicate(const Volume entity, ReplicationAxis axis, size_t count, double inc, double start=0e0)
1D volume replication implementation
Definition: Volumes.cpp:875
dd4hep::VisAttr::DASHED
@ DASHED
Definition: Objects.h:327
dd4hep::Volume::region
Region region() const
Access to the handle to the region structure.
Definition: Volumes.cpp:1256
dd4hep::VolumeExtension::sens_det
Handle< NamedObject > sens_det
Reference to the sensitive detector.
Definition: Volumes.h:327
_addNode
PlacedVolume _addNode(TGeoVolume *par, TGeoVolume *daughter, int id, TGeoMatrix *transform)
Definition: Volumes.cpp:729
dd4hep::VisAttrObject::color
TColor * color
Definition: ObjectsInterna.h:91
dd4hep::VolumeExtension::flags
int flags
Bit field to determine the usage. Bit 0...15 reserverd for system usage. 16...31 user space.
Definition: Volumes.h:319
dd4hep::Volume::addProperty
void addProperty(const std::string &nam, const std::string &val) const
Add Volume property (name-value pair)
Definition: Volumes.cpp:1303
dd4hep::Volume::setMaterial
const Volume & setMaterial(const Material &m) const
Set the volume's material.
Definition: Volumes.cpp:1109
dd4hep::VisAttrObject::drawingStyle
unsigned char drawingStyle
Definition: ObjectsInterna.h:94
TNamed
Class of the ROOT toolkit. See http://root.cern.ch/root/htmldoc/ClassIndex.html.
Definition: ROOTClasses.h:37
dd4hep::Volume::paramVolume3D
PlacedVolume paramVolume3D(Volume entity, size_t count_1, const Transform3D &inc_1, size_t count_2, const Transform3D &inc_2, size_t count_3, const Transform3D &inc_3)
3D Parameterised volume implementation
dd4hep::Volume::testFlagBit
bool testFlagBit(unsigned int bit) const
Test the user flag bit.
Definition: Volumes.cpp:693
geo_assembly_t
TGeoVolumeAssembly geo_assembly_t
Definition: Volumes.cpp:54
dd4hep::Region
Handle class describing a region as used in simulation.
Definition: Objects.h:462
dd4hep::Handle< TGeoVolume >::m_element
TGeoVolume * m_element
Single and only data member: Reference to the actual element.
Definition: Handle.h:93
dd4hep::Handle::_ptr
Q * _ptr() const
Access to an unrelated object type.
Definition: Handle.h:157
dd4hep::Detector::limitSet
virtual LimitSet limitSet(const std::string &name) const =0
Retrieve a limitset by its name from the detector description.
dd4hep::PlacedVolume::matrix
const TGeoMatrix & matrix() const
Access the full transformation matrix to the parent volume.
Definition: Volumes.cpp:510
dd4hep::VolumeExtension::Grab
virtual TGeoExtension * Grab() override
TGeoExtension overload: Method called whenever requiring a pointer to the extension.
Definition: Volumes.cpp:584
dd4hep::ReflectionBuilder::execute
void execute() const
Perform scan.
dd4hep::PlacedVolume::motherVol
Volume motherVol() const
Parent volume (envelope)
Definition: Volumes.cpp:457
dd4hep::PlacedVolume::toString
std::string toString() const
String dump.
Definition: Volumes.cpp:524
dd4hep::PlacedVolumeExtension::PlacedVolumeExtension
PlacedVolumeExtension()
Default constructor.
Definition: Volumes.cpp:353
dd4hep::Volume::Volume
Volume()=default
Default constructor.
dd4hep::Detector::visAttributes
virtual const HandleMap & visAttributes() const =0
Accessor to the map of visualisation attributes.
dd4hep::Transform3D
ROOT::Math::Transform3D Transform3D
Definition: Objects.h:117
dd4hep::PlacedVolume::num_daughters
std::size_t num_daughters() const
Number of daughters placed in this volume.
Definition: Volumes.cpp:462
DECREMENT_COUNTER
#define DECREMENT_COUNTER
Definition: config.h:39
dd4hep::Volume::divide
Volume divide(const std::string &divname, int iaxis, int ndiv, double start, double step, int numed=0, const char *option="")
Divide volume into subsections (See the ROOT manuloa for details)
Definition: Volumes.cpp:712
dd4hep::Position
ROOT::Math::XYZVector Position
Definition: Objects.h:81
dd4hep::VolumeExtension::VolumeExtension
VolumeExtension()
Default constructor.
Definition: Volumes.cpp:537
dd4hep::PlacedVolumeExtension::magic
unsigned long magic
Magic word to detect memory corruptions.
Definition: Volumes.h:121
dd4hep::Volume::isReflected
bool isReflected() const
Test if this volume was reflected.
Definition: Volumes.cpp:702
dd4hep::PlacedVolume::type
const char * type() const
Access the object type from the class information.
Definition: Volumes.cpp:437
dd4hep::Box
Class describing a box shape.
Definition: Shapes.h:294
std
Definition: Plugins.h:30
dd4hep::VisAttr::SOLID
@ SOLID
Definition: Objects.h:327
dd4hep::PlacedVolumeExtension::Grab
virtual TGeoExtension * Grab() override
TGeoExtension overload: Method called whenever requiring a pointer to the extension.
Definition: Volumes.cpp:380
dd4hep::Handle::ptr
T * ptr() const
Access to the held object.
Definition: Handle.h:153
ObjectsInterna.h
dd4hep::Volume::type
const char * type() const
Access the object type from the class information.
Definition: Volumes.cpp:647
dd4hep::ReflectionBuilder::detector
Detector & detector
Definition: Volumes.h:60
dd4hep::Volume::boundingBox
Box boundingBox() const
Access the bounding box of the volume (if available)
Definition: Volumes.cpp:1228
dd4hep::VolumeExtension::operator=
VolumeExtension & operator=(VolumeExtension &&copy)=delete
No move assignment.
geo_node_t
TGeoNode geo_node_t
Definition: Volumes.cpp:52
dd4hep::VolumeMulti::verifyVolumeMulti
void verifyVolumeMulti()
Import volume from pointer as a result of Solid->Divide()
Definition: Volumes.cpp:1340
dd4hep::Volume::setVisAttributes
const Volume & setVisAttributes(const VisAttr &obj) const
Set Visualization attributes to the volume.
Definition: Volumes.cpp:1127
dd4hep
Namespace for the AIDA detector description toolkit.
Definition: AlignmentsCalib.h:28
dd4hep::PlacedVolumeExtension::VolIDs::str
std::string str() const
String representation for debugging.
Definition: Volumes.cpp:420
dd4hep::Solid
Solid_type< TGeoShape > Solid
Definition: Shapes.h:197
det
DetElement::Object * det
Definition: AlignmentsCalculator.cpp:66
dd4hep::PlacedVolume::copyNumber
int copyNumber() const
Access the copy number of this placement within its mother.
Definition: Volumes.cpp:442
dd4hep::PlacedVolume::Processor::~Processor
virtual ~Processor()
Default destructor.
Definition: Volumes.cpp:338
dd4hep::PlacedVolume::volume
Volume volume() const
Logical volume of this placement.
Definition: Volumes.cpp:452
dd4hep::PlacedVolumeExtension::VolIDs::insert
std::pair< std::vector< VolID >::iterator, bool > insert(const std::string &name, int value)
Insert new entry.
Definition: Volumes.cpp:406
dd4hep::PlacedVolume::data
Object * data() const
Check if placement is properly instrumented.
Definition: Volumes.cpp:431
dd4hep::Detector
The main interface to the dd4hep detector description package.
Definition: Detector.h:90
dd4hep::Volume::getProperty
std::string getProperty(const std::string &nam, const std::string &default_val="") const
Access property value. Returns default_value if the property is not present.
Definition: Volumes.cpp:1319
INCREMENT_COUNTER
#define INCREMENT_COUNTER
Definition: config.h:38
dd4hep::Volume::reflect
Volume reflect() const
Create a reflected volume tree. The reflected volume has left-handed coordinates.
Definition: Volumes.cpp:652
dd4hep::VolumeExtension::~VolumeExtension
virtual ~VolumeExtension()
Default destructor.
Definition: Volumes.cpp:543
dd4hep::Volume::setFlagBit
void setFlagBit(unsigned int bit)
Set user flags in bit-field.
Definition: Volumes.cpp:684
TGeoExtension
Class of the ROOT toolkit. See http://root.cern.ch/root/htmldoc/ClassIndex.html.
Definition: ROOTClasses.h:25
dd4hep::PlacedVolumeExtension::refCount
long refCount
Reference count on object (used to implement Grab/Release)
Definition: Volumes.h:123
dd4hep::PlacedVolume::volIDs
const PlacedVolumeExtension::VolIDs & volIDs() const
Access to the volume IDs.
Definition: Volumes.cpp:480
dd4hep::RotationZYX
ROOT::Math::RotationZYX RotationZYX
Definition: Objects.h:105
InstanceCount.h
dd4hep::Volume::setAttributes
const Volume & setAttributes(const Detector &description, const std::string &region, const std::string &limits, const std::string &vis) const
Attach attributes to the volume.
Definition: Volumes.cpp:1200
dd4hep::VolumeExtension::properties
TList * properties
Reference to properties.
Definition: Volumes.h:331
dd4hep::VisAttrObject::alpha
float alpha
Definition: ObjectsInterna.h:93
dd4hep::Volume::visAttributes
VisAttr visAttributes() const
Access the visualisation attributes.
Definition: Volumes.cpp:1210
dd4hep::Volume::Object
VolumeExtension Object
Definition: Volumes.h:380
ClassImp
ClassImp(VolumeExtension) ClassImp(PlacedVolumeExtension) ClassImp(PlacedVolumeExtension
Enable ROOT persistency.
Definition: Volumes.cpp:57
dd4hep::PlacedVolumeExtension::params
Parameterisation * params
Reference to the parameterised transformation.
Definition: Volumes.h:125
dd4hep::PlacedVolume::position
Position position() const
Access the translation vector to the parent volume.
Definition: Volumes.cpp:518
dd4hep::get_shape_tag
std::string get_shape_tag(const TGeoShape *shape)
Retrieve tag name from shape type.
Definition: ShapeUtilities.cpp:185
Printout.h
dd4hep::Volume::X_axis
@ X_axis
Definition: Volumes.h:392
dd4hep::PlacedVolumeExtension::Parameterisation
Optional parameters to implement special features such as parametrization.
Definition: Volumes.h:256
dd4hep::Volume::import
Volume & import()
If we import volumes from external sources, we have to attach the extensions to the tree.
Definition: Volumes.cpp:673
dd4hep::PlacedVolumeExtension::VolIDs::find
std::vector< VolID >::const_iterator find(const std::string &name) const
Find entry.
Definition: Volumes.cpp:397
dd4hep::toStringMesh
std::string toStringMesh(const TGeoShape *shape, int precision=2)
Output mesh vertices to string.
Definition: ShapeUtilities.cpp:1295
handle
void handle(const O *o, const C &c, F pmf)
Definition: LCDDConverter.cpp:1105
dd4hep::VolumeExtension::referenced
int referenced
Definition: Volumes.h:317
dd4hep::Volume::data
Object * data() const
Check if placement is properly instrumented.
Definition: Volumes.cpp:641
dd4hep::Volume::sensitiveDetector
Handle< NamedObject > sensitiveDetector() const
Access to the handle to the sensitive detector.
Definition: Volumes.cpp:1287
dd4hep::VolumeExtension::limits
LimitSet limits
Limit sets used for simulation.
Definition: Volumes.h:323
dd4hep::VisAttrObject::visible
unsigned char visible
Definition: ObjectsInterna.h:97
dd4hep::VisAttrObject
Concrete object implementation of the VisAttr Handle.
Definition: ObjectsInterna.h:88