diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp index 10cbed8939a2af0a5a4aaf9a617283c0d9700d65..ff00e8a716d05e59b9d5098e21e74d85f2623f3b 100644 --- a/DDCore/src/LCDDImp.cpp +++ b/DDCore/src/LCDDImp.cpp @@ -85,6 +85,10 @@ LCDDImp::LCDDImp() LCDDImp::~LCDDImp() { if ( m_properties ) delete m_properties; m_properties = 0; + if ( m_volManager.isValid() ) { + delete m_volManager.ptr(); + m_volManager = VolumeManager(); + } } Volume LCDDImp::pickMotherVolume(const DetElement&) const { // throw if not existing @@ -131,14 +135,18 @@ Handle<TObject> LCDDImp::getRefChild(const HandleMap& e, const string& name, boo } return 0; } + namespace { struct ShapePatcher : public GeoScan { - ShapePatcher(DetElement e) : GeoScan(e) {} - GeoScan& operator()() { + VolumeManager m_volManager; + DetElement m_world; + ShapePatcher(VolumeManager m, DetElement e) : GeoScan(e), m_volManager(m), m_world(e) {} + void patchShapes() { GeoHandler::Data& data = *m_data; string nam; cout << "++ Patching names of anonymous shapes...." << endl; for(GeoHandler::Data::const_reverse_iterator i=data.rbegin(); i != data.rend(); ++i) { + int level = (*i).first; const GeoHandler::Data::mapped_type& v = (*i).second; for(GeoHandler::Data::mapped_type::const_iterator j=v.begin(); j != v.end(); ++j) { const TGeoNode* n = *j; @@ -182,9 +190,144 @@ namespace { } } } + } + + typedef DetElement::Children _C; + DetElement findElt(DetElement e, PlacedVolume pv) { + const _C& children = e.children(); + if ( e.placement().ptr() == pv.ptr() ) return e; + for(_C::const_iterator i=children.begin(); i!=children.end(); ++i) { + DetElement de = (*i).second; + if ( de.placement().ptr() == pv.ptr() ) return de; + } + for(_C::const_iterator i=children.begin(); i!=children.end(); ++i) { + DetElement de = findElt((*i).second,pv); + if ( de.isValid() ) return de; + } + return DetElement(); + } + + unsigned long long int encode_cell(Readout ro, const PlacedVolume::VolIDs& ids) { + unsigned long long value = ~0x0ull; + const IDDescriptor& en = ro.idSpec(); + for(PlacedVolume::VolIDs::const_iterator i=ids.begin(); i!=ids.end(); ++i) { + const PlacedVolume::VolID& id = (*i); + value &= en.field(id.first).encode(id.second); + } + return value; + } + + typedef void (::ShapePatcher::*Func_t)(DetElement parent, DetElement e,const TGeoNode* n, + const PlacedVolume::VolIDs& ids, + const vector<const TGeoNode*>& nodes, + const vector<const TGeoNode*>& elt_nodes); + + void scanNode(Func_t func, + DetElement parent, DetElement e, PlacedVolume pv, + const PlacedVolume::VolIDs& vol_ids, + vector<const TGeoNode*>& nodes, + vector<const TGeoNode*>& elt_nodes) + { + const TGeoNode* node = dynamic_cast<const TGeoNode*>(pv.ptr()); + if ( node ) { + Int_t ndau = node->GetNdaughters(); + PlacedVolume::VolIDs ids(vol_ids); + const PlacedVolume::VolIDs& ids_node = pv.volIDs(); + + nodes.push_back(node); + elt_nodes.push_back(node); + ids.PlacedVolume::VolIDs::Base::insert(ids.end(),ids_node.begin(),ids_node.end()); + (this->*func)(parent, e, node, ids, nodes, elt_nodes); + for(Int_t idau=0; idau<ndau; ++idau) { + TGeoNode* daughter = node->GetDaughter(idau); + if ( dynamic_cast<const PlacedVolume::Object*>(daughter) ) { + PlacedVolume pv_dau = Ref_t(daughter); + DetElement de_dau = findElt(e,daughter); + if ( de_dau.isValid() ) { + vector<const TGeoNode*> dau_nodes; + scanNode(func, parent, de_dau, pv_dau, ids, nodes, dau_nodes); + } + else { + scanNode(func, parent, e, pv_dau, ids, nodes, elt_nodes); + } + } + } + elt_nodes.pop_back(); + nodes.pop_back(); + } + } + void scanVolumes(Func_t func) { + const _C& children = m_world.children(); + for(_C::const_iterator i=children.begin(); i!=children.end(); ++i) { + DetElement de = (*i).second; + PlacedVolume pv = de.placement(); + if ( pv.isValid() ) { + PlacedVolume::VolIDs ids; + vector<const TGeoNode*> nodes, elt_nodes; + scanNode(func, de, de, pv, ids, nodes, elt_nodes); + continue; + } + cout << "++ Detector element " << de.name() << " has no placement." << endl; + } + } + + void print_node(DetElement parent, DetElement e,const TGeoNode* n, + const PlacedVolume::VolIDs& ids, + const vector<const TGeoNode*>& nodes, + const vector<const TGeoNode*>& elt_nodes); + + GeoScan& printVolumes() { + scanVolumes(&ShapePatcher::print_node); return *this; } }; + + void ShapePatcher::print_node(DetElement parent, + DetElement e, + const TGeoNode* n, + const PlacedVolume::VolIDs& ids, + const vector<const TGeoNode*>& nodes, + const vector<const TGeoNode*>& elt_nodes) + { + static int s_count = 0; + Readout ro = parent.readout(); + const IDDescriptor& en = ro.idSpec(); + IDDescriptor::VolumeID volume_id = encode_cell(ro,ids); + PlacedVolume pv = Ref_t(n); + bool sensitive = pv.volume().isSensitive(); + + if ( !sensitive ) return; + ++s_count; + cout << s_count << ": " << e.name() << " de:" << e.ptr() << " ro:" << ro.ptr() + << " pv:" << n->GetName() << " id:" << (void*)volume_id << " : "; + for(PlacedVolume::VolIDs::const_iterator i=ids.begin(); i!=ids.end(); ++i) { + const PlacedVolume::VolID& id = (*i); + IDDescriptor::Field f = ro.idSpec().field(id.first); + int value = en.field(id.first).decode(volume_id); + cout << id.first << "=" << id.second << "," << value + << " [" << f.first << "," << f.second << "] "; + } + cout << " Sensitive:" << (sensitive ? "YES" : "NO"); + if ( sensitive ) { + VolumeManager section = m_volManager.subdetector(volume_id); + VolumeManager::Context* ctxt = section.lookupContext(volume_id|0xDEAD); + if ( ctxt->placement.ptr() != pv.ptr() ) { + cout << " !!!!! No Volume found!" << endl; + } + cout << " Pv:" << pv.ptr() << " <> " << ctxt->placement.ptr(); + } + cout << endl; +#if 0 + cout << s_count << ": " << e.name() << " Detector GeoNodes:"; + for(vector<const TGeoNode*>::const_iterator j=nodes.begin(); j!=nodes.end();++j) + cout << (void*)(*j) << " "; + cout << endl; + cout << s_count << ": " << e.name() << " Element GeoNodes:"; + for(vector<const TGeoNode*>::const_iterator j=elt_nodes.begin(); j!=elt_nodes.end();++j) + cout << (void*)(*j) << " "; + cout << endl; +#endif + } } void LCDDImp::endDocument() { @@ -219,8 +362,10 @@ void LCDDImp::endDocument() { //gGeoManager->SetTopVolume(m_worldVol); mgr->CloseGeometry(); m_world.setPlacement(PlacedVolume(mgr->GetTopNode())); - ShapePatcher patcher(m_world); - patcher(); + m_volManager = VolumeManager("World", m_world); + ShapePatcher patcher(m_volManager,m_world); + patcher.patchShapes(); + //patcher.printVolumes(); } }