Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-06 07:54:19

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