Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:16:59

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 
0014 // Framework include files
0015 #include <DD4hep/Detector.h>
0016 #include <DD4hep/GeoHandler.h>
0017 #include <DD4hep/detail/ObjectsInterna.h>
0018 
0019 // ROOT includes
0020 #include <TGeoManager.h>
0021 #include <TGeoCompositeShape.h>
0022 #include <TGeoBoolNode.h>
0023 #include <TClass.h>
0024 
0025 // C/C++ include files
0026 #include <algorithm>
0027 #include <iostream>
0028 
0029 using namespace dd4hep;
0030 
0031 namespace {
0032 
0033   void collectSolid(detail::GeoHandler::GeometryInfo& geo,
0034                     const std::string& name,
0035                     const std::string& node,
0036                     TGeoShape* shape,
0037                     TGeoMatrix* matrix)
0038   {
0039     if ( 0 == ::strncmp(shape->GetName(), "TGeo", 4) )  {
0040       shape->SetName(name.c_str());
0041     }
0042     if ( shape->IsA() == TGeoCompositeShape::Class() )  {
0043       const TGeoCompositeShape* s = (const TGeoCompositeShape*) shape;
0044       const TGeoBoolNode* boolean = s->GetBoolNode();
0045       collectSolid(geo, name + "_left", name + "_left", boolean->GetLeftShape(), boolean->GetLeftMatrix());
0046       collectSolid(geo, name + "_right", name + "_right", boolean->GetRightShape(), boolean->GetRightMatrix());
0047     }
0048     if(geo.solid_set.emplace(shape).second) {
0049       geo.solids.push_back(shape);
0050     }
0051     geo.trafos.emplace_back(node, matrix);
0052   }
0053 }
0054 
0055 /// Default constructor
0056 detail::GeoHandler::GeoHandler()  {
0057   m_data = new std::map<int, std::vector<const TGeoNode*> >();
0058   m_set_data = new std::map<int, std::set<const TGeoNode*> >();
0059 }
0060 
0061 /// Initializing constructor
0062 detail::GeoHandler::GeoHandler(std::map<int, std::vector<const TGeoNode*> >* ptr,
0063                 std::map<int, std::set<const TGeoNode*> >* ptr_set,
0064         std::map<const TGeoNode*, std::vector<TGeoNode*> >* daus)
0065   : m_data(ptr), m_set_data(ptr_set), m_daughters(daus)
0066 {
0067 }
0068 
0069 /// Default destructor
0070 detail::GeoHandler::~GeoHandler() {
0071   if (m_data)
0072     delete m_data;
0073   if (m_set_data)
0074     delete m_set_data;
0075 
0076   m_data = nullptr;
0077   m_set_data = nullptr;
0078 }
0079 
0080 std::map<int, std::vector<const TGeoNode*> >* detail::GeoHandler::release() {
0081   /// release the std::vector geometry container (preserves order)
0082   std::map<int, std::vector<const TGeoNode*> >* d = m_data;
0083   m_data = nullptr;
0084 
0085   /// the std::set container (for lookup purpose) is not needed anymore, so delete it
0086   /// the container is always present since the call of the constructor
0087   /// we never expect to call release() twice (will release nullptr)
0088   delete m_set_data;
0089   m_set_data = nullptr;
0090 
0091   return d;
0092 }
0093 
0094 /// Propagate regions. Returns the previous value
0095 bool detail::GeoHandler::setPropagateRegions(bool value)   {
0096   bool old = m_propagateRegions;
0097   m_propagateRegions = value;
0098   return old;
0099 }
0100 
0101 detail::GeoHandler& detail::GeoHandler::collect(DetElement element) {
0102   DetElement par = element.parent();
0103   TGeoNode*  par_node = par.isValid() ? par.placement().ptr() : nullptr;
0104   m_data->clear();
0105   m_set_data->clear();
0106   return i_collect(par_node, element.placement().ptr(), 0, Region(), LimitSet());
0107 }
0108 
0109 detail::GeoHandler& detail::GeoHandler::collect(DetElement element, GeometryInfo& info) {
0110   DetElement par = element.parent();
0111   TGeoNode* par_node = par.isValid() ? par.placement().ptr() : nullptr;
0112   m_data->clear();
0113   m_set_data->clear();
0114   i_collect(par_node, element.placement().ptr(), 0, Region(), LimitSet());
0115   for ( auto i = m_data->rbegin(); i != m_data->rend(); ++i ) {
0116     const auto& mapped = (*i).second;
0117     for ( const TGeoNode* n : mapped )  {
0118       TGeoVolume* v = n->GetVolume();
0119       if ( v ) {
0120         Material mat(v->GetMedium());
0121         Volume   vol(v);
0122         // Note : assemblies and the world do not have a real volume nor a material
0123         if ( info.volumeSet.find(vol) == info.volumeSet.end() ) {
0124           info.volumeSet.emplace(vol);
0125           info.volumes.emplace_back(vol);
0126         }
0127         if ( mat.isValid() )
0128           info.materials.emplace(mat);
0129         if (dynamic_cast<Volume::Object*>(v)) {
0130           VisAttr vis = vol.visAttributes();
0131           //Region      reg = vol.region();
0132           //LimitSet    lim = vol.limitSet();
0133           //SensitiveDetector det = vol.sensitiveDetector();
0134 
0135           if (vis.isValid())
0136             info.vis.emplace(vis);
0137           //if ( lim.isValid() ) info.limits[lim.ptr()].emplace(v);
0138           //if ( reg.isValid() ) info.regions[reg.ptr()].emplace(v);
0139           //if ( det.isValid() ) info.sensitives[det.ptr()].emplace(v);
0140         }
0141         collectSolid(info, v->GetName(), n->GetName(), v->GetShape(), n->GetMatrix());
0142       }
0143     }
0144   }
0145   return *this;
0146 }
0147 
0148 detail::GeoHandler& detail::GeoHandler::i_collect(const TGeoNode* /* parent */,
0149                                                   const TGeoNode*    current,
0150                                                   int level, Region rg, LimitSet ls)
0151 {
0152   TGeoVolume* vol    = current->GetVolume();
0153   TObjArray*  nodes  = vol->GetNodes();
0154   Volume      volume = vol;
0155   Region      region = volume.region();
0156   LimitSet    limits = volume.limitSet();
0157 
0158   if ( m_propagateRegions )  {
0159     if ( !region.isValid() && rg.isValid() )   {
0160       region = rg;
0161       volume.setRegion(region);
0162     }
0163     if ( !limits.isValid() && ls.isValid() )  {
0164       limits = ls;
0165       volume.setLimitSet(limits);
0166     }
0167   }
0168   /// Collect the hierarchy of placements
0169   /// perform lookup using std::set::emplace (faster than std::find for very large number of volumes)
0170   if ( (*m_set_data)[level].emplace(current).second ) {
0171     (*m_data)[level].push_back(current);
0172   }
0173   int num = nodes ? nodes->GetEntriesFast() : 0;
0174   for (int i = 0; i < num; ++i)
0175     i_collect(current, (TGeoNode*)nodes->At(i), level + 1, region, limits);
0176   /// Now collect all the daughters of this volume, so that we can reconnect them in the correct order
0177   if ( m_daughters && m_daughters->find(current) == m_daughters->end() )  {
0178     auto [idau,success] = m_daughters->emplace(current, std::vector<TGeoNode*>());
0179     for (int i = 0; i < num; ++i)
0180       idau->second.push_back((TGeoNode*)nodes->At(i));
0181   }
0182   return *this;
0183 }
0184 
0185 /// Initializing constructor
0186 detail::GeoScan::GeoScan(DetElement e)  {
0187   m_data = GeoHandler().collect(e).release();
0188 }
0189 
0190 /// Initializing constructor
0191 detail::GeoScan::GeoScan(DetElement e, bool propagate) {
0192   GeoHandler h;
0193   h.setPropagateRegions(propagate);
0194   m_data = h.collect(e).release();
0195 }
0196 
0197 /// Default destructor
0198 detail::GeoScan::~GeoScan() {
0199   if (m_data)
0200     delete m_data;
0201   m_data = 0;
0202 }
0203 
0204 /// Work callback
0205 detail::GeoScan& detail::GeoScan::operator()() {
0206   return *this;
0207 }
0208