diff --git a/DDCore/include/DD4hep/Shapes.h b/DDCore/include/DD4hep/Shapes.h index 6817e766a7b9e491ed46ddedc3ecd8d710c81300..54a8acc8fe230d4ea71a2a9f81e005151c6e3fae 100644 --- a/DDCore/include/DD4hep/Shapes.h +++ b/DDCore/include/DD4hep/Shapes.h @@ -50,6 +50,7 @@ /// Namespace for the AIDA detector description toolkit namespace dd4hep { + class Volume; /** Utitlity functions */ /// Pretty print of solid attributes @@ -63,6 +64,18 @@ namespace dd4hep { /** * Generic handle holding an object of base TGeoShape. * + * One note about divisions: + * ========================= + * Since dd4hep requires Volumes (aka TGeoVolume) and PlacedVolumes (aka TGeoNode) + * to be enhaced with the user extension mechanism shape divisions MUST be + * done using the division mechanism of the dd4hep shape or volume wrapper. + * Otherwise the enhancements are not added and you shall get exception + * when dd4hep is closing the geometry. + * The same argument holds when a division is made from a Volume. + * Unfortunately there is no reasonable way to intercept this call to the + * TGeo objects - except to sub-class each of them, which is not really + * acceptable either. + * * For any further documentation please see the following ROOT documentation: * \see http://root.cern.ch/root/html/TGeoShape.html * @@ -112,6 +125,9 @@ namespace dd4hep { std::string toString(int precision=2) const { return toStringSolid(this->m_element,precision); } + /// Divide volume into subsections (See the ROOT manuloa for details) + TGeoVolume* divide(const Volume& voldiv, const std::string& divname, + int iaxis, int ndiv, double start, double step) const; }; typedef Solid_type<TGeoShape> Solid; diff --git a/DDCore/include/DD4hep/Volumes.h b/DDCore/include/DD4hep/Volumes.h index f0bbe256ade3d91d8e14538b3e49e30548fabbd2..9132209628a757fb75fe430bdfe1f6fe6f2c07be 100644 --- a/DDCore/include/DD4hep/Volumes.h +++ b/DDCore/include/DD4hep/Volumes.h @@ -246,6 +246,18 @@ namespace dd4hep { /** * Handle describing a Volume * + * One note about divisions: + * ========================= + * Since dd4hep requires Volumes (aka TGeoVolume) and PlacedVolumes (aka TGeoNode) + * to be enhaced with the user extension mechanism shape divisions MUST be + * done using the division mechanism of the dd4hep shape or volume wrapper. + * Otherwise the enhancements are not added and you shall get exception + * when dd4hep is closing the geometry. + * The same argument holds when a division is made from a Volume. + * Unfortunately there is no reasonable way to intercept this call to the + * TGeo objects - except to sub-class each of them, which is not really + * acceptable either. + * * For any further documentation please see the following ROOT documentation: * \see http://root.cern.ch/root/html/TGeoVolume.html * @@ -286,7 +298,9 @@ namespace dd4hep { /// If we import volumes from external sources, we have to attach the extensions to the tree Volume& import(); - + + /// Divide volume into subsections (See the ROOT manuloa for details) + Volume divide(const std::string& divname, int iaxis, int ndiv, double start, double step, int numed = 0, const char* option = ""); /** Daughter placements with auto-generated copy number for the daughter volume */ /// Place daughter volume. The position and rotation are the identity PlacedVolume placeVolume(const Volume& vol) const; @@ -310,6 +324,35 @@ namespace dd4hep { PlacedVolume placeVolume(const Volume& vol, int copy_no, const RotationZYX& rot) const; /// Place rotated daughter volume. The position is automatically the identity position PlacedVolume placeVolume(const Volume& vol, int copy_no, const Rotation3D& rot) const; + /// Parametrized volume implementation + /** Embedding parametrized daughter placements in a mother volume + * @param start start transormation for the first placement + * @param count Number of entities to be placed + * @param entity Daughter volume to be placed + * @param inc Transformation increment for each iteration + */ + void paramVolume1D(const Transform3D& start, size_t count, Volume entity, const Transform3D& inc); + /// Parametrized volume implementation + /** Embedding parametrized daughter placements in a mother volume + * @param count Number of entities to be placed + * @param entity Daughter volume to be placed + * @param inc Transformation increment for each iteration + */ + void paramVolume1D(size_t count, Volume entity, const Transform3D& trafo); + /// Parametrized volume implementation + /** Embedding parametrized daughter placements in a mother volume + * @param count Number of entities to be placed + * @param entity Daughter volume to be placed + * @param inc Transformation increment for each iteration + */ + void paramVolume1D(size_t count, Volume entity, const Position& inc); + /// Parametrized volume implementation + /** Embedding parametrized daughter placements in a mother volume + * @param count Number of entities to be placed + * @param entity Daughter volume to be placed + * @param inc Transformation increment for each iteration + */ + void paramVolume1D(size_t count, Volume entity, const RotationZYX& inc); /// Set user flags in bit-field void setFlagBit(unsigned int bit); @@ -364,7 +407,39 @@ namespace dd4hep { } }; - /// Implementation class extending the ROOT assembly volumes (TGeoVolumeAsembly) + /// Implementation class extending the ROOT mulit-volumes (TGeoVolumeMulti) + /** + * Handle describing a multi volume. + * + * For any further documentation please see the following ROOT documentation: + * \see http://root.cern.ch/root/html/TGeoVolumeMulti.html + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_CORE + */ + class VolumeMulti : public Volume { + void verifyVolumeMulti(); + public: + /// Default constructor + VolumeMulti() = default; + /// Copy from handle + VolumeMulti(const VolumeMulti& v) = default; + /// Copy from pointer as a result of Solid->Divide() + VolumeMulti(TGeoVolume* v) : Volume(v) { + verifyVolumeMulti(); + } + /// Copy from arbitrary Element + template <typename T> VolumeMulti(const Handle<T>& v) : Volume(v) { + verifyVolumeMulti(); + } + /// Constructor to be used when creating a new multi-volume object + VolumeMulti(const std::string& name, Material material); + /// Assignment operator (must match copy constructor) + VolumeMulti& operator=(const VolumeMulti& a) = default; + }; + + /// Implementation class extending the ROOT assembly volumes (TGeoVolumeAssembly) /** * Handle describing a volume assembly. * @@ -383,7 +458,7 @@ namespace dd4hep { Assembly(const Assembly& v) = default; /// Copy from arbitrary Element template <typename T> Assembly(const Handle<T>& v) : Volume(v) { } - /// Constructor to be used when creating a new geometry tree. + /// Constructor to be used when creating a new assembly object Assembly(const std::string& name); /// Assignment operator (must match copy constructor) Assembly& operator=(const Assembly& a) = default; diff --git a/DDCore/include/XML/VolumeBuilder.h b/DDCore/include/XML/VolumeBuilder.h index 82a0a41d92ae1c96453e2f158345fd40332a1571..ccf468386923f439bab3a0cfb8fe0253dc487e1a 100644 --- a/DDCore/include/XML/VolumeBuilder.h +++ b/DDCore/include/XML/VolumeBuilder.h @@ -21,6 +21,7 @@ // C/C++ include files #include <set> #include <map> +#include <memory> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -144,6 +145,7 @@ namespace dd4hep { typedef std::map<std::string,std::pair<Handle_t,Volume> > Volumes; typedef std::map<std::string,Material> Materials; typedef std::map<std::string,std::pair<Handle_t,Transform3D> > Transformations; + std::map<std::string, std::unique_ptr<xml::DocumentHolder> > included_docs; Detector& description; xml_det_h x_det; int id = -1; @@ -201,6 +203,8 @@ namespace dd4hep { size_t buildVolumes(Handle_t handle); /// Build all <transformation/> identifiers in the passed parent xml element size_t buildTransformations(Handle_t handle); + /// Load include tags contained in the passed XML handle + size_t load(Handle_t element, const std::string& tag); /// Build all <physvol/> identifiers as PlaceVolume daughters. Ignores structure VolumeBuilder& placeDaughters(Volume vol, Handle_t handle); /// Build all <physvol/> identifiers as PlaceVolume daughters. Also handles structure diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp index b3769d26719c6448bb447b983a0015c90d719e54..5b937cc6dd27d47a6a86c94a6dc8e5ae52ba2ad4 100644 --- a/DDCore/src/Handle.cpp +++ b/DDCore/src/Handle.cpp @@ -373,6 +373,7 @@ DD4HEP_INSTANTIATE_HANDLE(TGeoNodeOffset); #include "TGeoCompositeShape.h" #include "TGeoShapeAssembly.h" DD4HEP_INSTANTIATE_HANDLE(TGeoVolumeAssembly,TGeoVolume,TGeoAtt); +DD4HEP_INSTANTIATE_HANDLE(TGeoVolumeMulti,TGeoVolume,TGeoAtt); DD4HEP_INSTANTIATE_HANDLE(TGeoVolume,TGeoAtt,TAttLine,TAtt3D); DD4HEP_INSTANTIATE_HANDLE(TGeoShape); DD4HEP_INSTANTIATE_HANDLE(TGeoBBox,TGeoShape); diff --git a/DDCore/src/Shapes.cpp b/DDCore/src/Shapes.cpp index 0b784fc37afd51436fabca5d7e72e4be0b1467a8..26b3aecd756e4656714cf95dfeb778cb2377f994 100644 --- a/DDCore/src/Shapes.cpp +++ b/DDCore/src/Shapes.cpp @@ -265,6 +265,19 @@ template <typename T> const char* Solid_type<T>::type() const { return ""; } +/// Divide volume into subsections (See the ROOT manuloa for details) +template <typename T> TGeoVolume* +Solid_type<T>::divide(const Volume& voldiv, const std::string& divname, + int iaxis, int ndiv, double start, double step) const { + T* p = this->ptr(); + if ( p ) { + VolumeMulti mv(p->Divide(voldiv.ptr(), divname.c_str(), iaxis, ndiv, start, step)); + return mv.ptr(); + } + except("dd4hep","Volume: Attempt to divide an invalid logical volume."); + return 0; +} + /// Constructor to create an anonymous new box object (retrieves name from volume) ShapelessSolid::ShapelessSolid(const string& nam) { _assign(new TGeoShapeAssembly(), nam, "assembly", true); diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp index 039be1bf55b92312bf1ff0c4dbf25068aba95dab..736b5b355565feee555c064f5eff9f938ec05f4e 100644 --- a/DDCore/src/Volumes.cpp +++ b/DDCore/src/Volumes.cpp @@ -304,17 +304,30 @@ namespace { e->SetUserExtension(new Assembly::Object()); return e; } + TGeoVolumeMulti* _createTGeoVolumeMulti(const string& name, TGeoMedium* medium) { + TGeoVolumeMulti* e = new TGeoVolumeMulti(name.c_str(), medium); + e->SetUserExtension(new VolumeMulti::Object()); + return e; + } class VolumeImport { public: void operator()(TGeoVolume* v) { + TClass* c = v->IsA(); if ( !v->GetUserExtension() ) { - if ( v->IsA() == geo_volume_t::Class() ) + if ( c == geo_volume_t::Class() ) v->SetUserExtension(new Volume::Object()); - else if ( v->IsA() == geo_assembly_t::Class() ) + else if ( c == geo_assembly_t::Class() ) v->SetUserExtension(new Assembly::Object()); + else if ( c == TGeoVolumeMulti::Class() ) + v->SetUserExtension(new VolumeMulti::Object()); else except("dd4hep","VolumeImport: Unknown TGeoVolume sub-class: %s",v->IsA()->GetName()); } + if ( c == TGeoVolumeMulti::Class() ) { + TGeoVolumeMulti* mv = (TGeoVolumeMulti*)v; + for(int i=0, n=mv->GetNvolumes(); i<n; ++i) + (*this)(mv->GetVolume(i)); + } for(Int_t i=0; i<v->GetNdaughters(); ++i) { geo_node_t* pv = v->GetNode(i); if ( !pv->GetUserExtension() ) @@ -547,8 +560,8 @@ Volume::Object* Volume::data() const { /// If we import volumes from external sources, we have to attach the extensions to the tree Volume& Volume::import() { if ( m_element ) { - VolumeImport import; - import(m_element); + VolumeImport imp; + imp(m_element); return *this; } except("dd4hep","Volume: Attempt to import invalid Volume handle."); @@ -573,6 +586,20 @@ bool Volume::testFlagBit(unsigned int bit) const { return false; // Anyhow never called. Only to satisfy the compiler. } +/// Divide volume into subsections (See the ROOT manuloa for details) +Volume Volume::divide(const std::string& divname, int iaxis, int ndiv, + double start, double step, int numed, const char* option) { + TGeoVolume* p = m_element; + if ( p ) { + VolumeImport imp; + TGeoVolume* mvp = p->Divide(divname.c_str(), iaxis, ndiv, start, step, numed, option); + imp(mvp); + return mvp; + } + except("dd4hep","Volume: Attempt to divide an invalid logical volume."); + return 0; +} + static PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, int id, TGeoMatrix* transform) { TGeoVolume* parent = par; if ( !parent ) { @@ -665,6 +692,34 @@ PlacedVolume Volume::placeVolume(const Volume& volume, int copy_no, const Rotati return _addNode(m_element, volume, copy_no, detail::matrix::_rotation3D(rot)); } +/// Constructor to be used when creating a new parametrized volume object +void Volume::paramVolume1D(size_t count, Volume entity, const Position& inc) { + paramVolume1D(Transform3D(), count, entity, Transform3D(inc)); +} + +/// Constructor to be used when creating a new parametrized volume object +void Volume::paramVolume1D(size_t count, Volume entity, const RotationZYX& inc) { + paramVolume1D(Transform3D(), count, entity, Transform3D(inc)); +} + +/// Constructor to be used when creating a new parametrized volume object +void Volume::paramVolume1D(size_t count, Volume entity, const Transform3D& inc) { + paramVolume1D(Transform3D(), count, entity, inc); +} + +/// Constructor to be used when creating a new parametrized volume object +void Volume::paramVolume1D(const Transform3D& start, + size_t count, + Volume entity, + const Transform3D& trafo) +{ + Transform3D transformation(start); + for(size_t i=0; i<count; ++i) { + _addNode(m_element, entity, detail::matrix::_transform(transformation)); + transformation *= trafo; + } +} + /// Set the volume's material const Volume& Volume::setMaterial(const Material& m) const { if (m.isValid()) { @@ -874,11 +929,30 @@ bool Volume::isSensitive() const { return _data(*this)->sens_det.isValid(); } -/// Constructor to be used when creating a new geometry tree. +/// Constructor to be used when creating a new assembly object Assembly::Assembly(const string& nam) { m_element = _createTGeoVolumeAssembly(nam); } +/// Constructor to be used when creating a new multi-volume object +VolumeMulti::VolumeMulti(const string& nam, Material mat) { + m_element = _createTGeoVolumeMulti(nam, mat.ptr()); +} + +/// Copy from pointer as a result of Solid->Divide() +void VolumeMulti::verifyVolumeMulti() { + if ( m_element ) { + // This will lead to an exception if the type is not TGeoVolumeMulti + TGeoVolumeMulti* m = detail::safe_cast<TGeoVolumeMulti>::cast(m_element); + if ( m ) { + import(); + return; + } + // Force a bad cast exception + Handle<TGeoVolumeMulti> h(m_element); + if ( h.isValid() ) {} + } +} /// Output mesh vertices to string std::string dd4hep::toStringMesh(PlacedVolume place, int prec) { diff --git a/DDCore/src/XML/VolumeBuilder.cpp b/DDCore/src/XML/VolumeBuilder.cpp index 3169d1860b90f103d5db9a33dbfd95fdcca13b42..838529ea7f68b36d665cec5ebeb0f7165160609d 100644 --- a/DDCore/src/XML/VolumeBuilder.cpp +++ b/DDCore/src/XML/VolumeBuilder.cpp @@ -21,7 +21,8 @@ #include "DD4hep/DetFactoryHelper.h" #include "Math/Polar2D.h" -class TObject; +#include "TClass.h" + using namespace std; using namespace dd4hep; @@ -38,7 +39,6 @@ VolumeBuilder::VolumeBuilder(Detector& dsc, xml_h x_parent, SensitiveDetector sd detector = DetElement(name, id); } buildType = description.buildType(); - debug = true; } /// Collect a set of materials from the leafs of an xml tag @@ -153,7 +153,7 @@ Solid VolumeBuilder::makeShape(xml_h handle) { solid.setName(nam); shapes.insert(make_pair(nam,make_pair(handle,solid))); } - printout(debug ? ALWAYS : INFO, "VolumeBuilder", + printout(debug ? ALWAYS : DEBUG, "VolumeBuilder", "+++ Created shape of type: %s name: %s",type.c_str(), nam.c_str()); return solid; } @@ -183,9 +183,9 @@ size_t VolumeBuilder::buildShapes(xml_h handle) { except("VolumeBuilder","+++ Failed to create shape %s of type: %s", nam.c_str(), type.c_str()); } - if ( debug ) { - printout(ALWAYS,"VolumeBuilder","+++ Building shape from XML: %s",nam.c_str()); - } + printout(debug ? ALWAYS : DEBUG,"VolumeBuilder", + "+++ Building shape from XML: %s of type: %s", + nam.c_str(), solid->IsA()->GetName()); shapes.insert(make_pair(nam,make_pair(c,solid))); continue; } @@ -223,9 +223,10 @@ size_t VolumeBuilder::buildVolumes(xml_h handle) { if ( c.attr_nothrow(_U(sensitive)) ) { vol.setSensitiveDetector(sensitive); } - if ( debug ) { - printout(ALWAYS,"VolumeBuilder","+++ Building volume from XML: %s",nam.c_str()); - } + solid = vol.solid(); + printout(debug ? ALWAYS : DEBUG,"VolumeBuilder", + "+++ Building volume from XML: %-20s shape:%-24s vis:%s", + nam.c_str(), solid->IsA()->GetName(), x.visStr().c_str()); buildVolumes(c); continue; } @@ -251,9 +252,9 @@ size_t VolumeBuilder::buildVolumes(xml_h handle) { if ( c.attr_nothrow(_U(sensitive)) ) { vol.setSensitiveDetector(sensitive); } - if ( debug ) { - printout(ALWAYS,"VolumeBuilder","+++ Building volume from XML: %s",nam.c_str()); - } + printout(debug ? ALWAYS : DEBUG,"VolumeBuilder", + "+++ Building volume from XML: %-20s shape:%-24s vis:%s", + nam.c_str(), solid->IsA()->GetName(), x.visStr().c_str()); buildVolumes(c); continue; } @@ -265,6 +266,9 @@ size_t VolumeBuilder::buildVolumes(xml_h handle) { placeDaughters(detector, vol, x); vol.setAttributes(description,x.regionStr(),x.limitsStr(),x.visStr()); volumes.insert(make_pair(nam,make_pair(c,vol))); + printout(debug ? ALWAYS : DEBUG,"VolumeBuilder", + "+++ Building assembly from XML: %-20s shape:%-24s vis:%s", + nam.c_str(), vol->GetShape()->IsA()->GetName(), x.visStr().c_str()); buildVolumes(c); continue; } @@ -415,6 +419,23 @@ void VolumeBuilder::_placeParamVolumes(DetElement parent, Volume vol, xml_h c) } } +/// Load include tags contained in the passed XML handle +size_t VolumeBuilder::load(xml_h element, const string& tag) { + size_t count = 0; + for( xml_coll_t c(element,Unicode(tag)); c; ++c ) { + string ref = c.attr<string>(_U(ref)); + unique_ptr<xml::DocumentHolder> doc(new xml::DocumentHolder(xml::DocumentHandler().load(element, c.attr_value(_U(ref))))); + xml_h vols = doc->root(); + printout(debug ? ALWAYS : DEBUG, "VolumeBuilder", + "++ Processing xml document %s.", doc->uri().c_str()); + included_docs[ref] = unique_ptr<xml::DocumentHolder>(doc.release()); + buildShapes(vols); + buildVolumes(vols); + ++count; + } + return count; +} + /// Build all <physvol/> identifiers as PlaceVolume daughters. Ignores structure VolumeBuilder& VolumeBuilder::placeDaughters(Volume vol, xml_h handle) { DetElement null_de; diff --git a/DDCore/src/plugins/ShapePlugins.cpp b/DDCore/src/plugins/ShapePlugins.cpp index 2b64a6de624ced6ed8f01d8cd432ca45aa73a486..899805e39a7729778a3b97f58bed1ed1e2a91418 100644 --- a/DDCore/src/plugins/ShapePlugins.cpp +++ b/DDCore/src/plugins/ShapePlugins.cpp @@ -149,10 +149,17 @@ DECLARE_XML_SHAPE(Cone__shape_constructor,create_Cone) static Handle<TObject> create_Trap(Detector&, xml_h element) { xml_dim_t e(element); Solid solid; - if ( e.hasAttr(_U(dz)) ) + if ( e.hasAttr(_U(dz)) ) { solid = Trap(e.dz(),e.dy(),e.dx(),_toDouble(_Unicode(pLTX))); - else - solid = Trap(e.z(0.0),e.theta(0),e.phi(0),e.y1(),e.x1(),e.x2(),e.alpha1(0),e.y2(),e.x3(),e.x4(),e.alpha2(0)); + } + else { + xml_attr_t attr = 0; + double x1 = e.x1(); + double x2 = e.x2(); + double x3 = (attr=element.attr_nothrow(_U(x3))) ? element.attr<double>(attr) : x1; + double x4 = (attr=element.attr_nothrow(_U(x4))) ? element.attr<double>(attr) : x2; + solid = Trap(e.z(0.0),e.theta(0),e.phi(0),e.y1(),x1,x2,e.alpha1(0),e.y2(),x3,x4,e.alpha2(0)); + } if ( e.hasAttr(_U(name)) ) solid->SetName(e.attr<string>(_U(name)).c_str()); return solid; } @@ -378,6 +385,7 @@ static Handle<TObject> create_BooleanMulti(Detector& description, xml_h element) xml_attr_t attr = 0; std::string op = e.attr<std::string>(_U(operation)) ; std::transform( op.begin(), op.end(), op.begin(), ::tolower); + //printout(ALWAYS,"","Boolean shape ---> %s",op.c_str()); for (xml_coll_t i(e ,_U(star)); i; ++i ) { xml_comp_t x_elt = i; string tag = x_elt.tag(); diff --git a/DDDetectors/src/VolumeAssembly_geo.cpp b/DDDetectors/src/VolumeAssembly_geo.cpp index 37b0254c2c2cbc1bc72bd6cf45ae084d0691e8e1..4f2c2a59e8558d46df139334c1b2c5ae660c7c3d 100644 --- a/DDDetectors/src/VolumeAssembly_geo.cpp +++ b/DDDetectors/src/VolumeAssembly_geo.cpp @@ -36,18 +36,7 @@ static Ref_t create_element(Detector& description, xml_h e, SensitiveDetector se xml::tools::VolumeBuilder builder(description, e, sens); builder.debug = x_dbg != 0 || true; - - // Need to keep these alive as long as the volumebuilder lives - map<string, unique_ptr<xml::DocumentHolder> > docs; - for( xml_coll_t c(x_det,_U(include)); c; ++c ) { - string ref = c.attr<string>(_U(ref)); - docs[ref] = unique_ptr<xml::DocumentHolder>(new xml::DocumentHolder(xml::DocumentHandler().load(e, c.attr_value(_U(ref))))); - xml_h vols = docs[ref]->root(); - printout(builder.debug ? ALWAYS : DEBUG, "VolumeAssembly","++ Processing xml document %s.", - docs[ref]->uri().c_str()); - builder.buildShapes(vols); - builder.buildVolumes(vols); - } + builder.load(x_det, "include"); builder.buildShapes(x_det); builder.buildShapes(x_env); builder.buildVolumes(x_det); @@ -66,21 +55,23 @@ static Ref_t create_element(Detector& description, xml_h e, SensitiveDetector se /// Set generic associations assembly.setAttributes(description,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); /// If specified more direct: use these ones. - if ( x_env.hasAttr(_U(vis)) ) { + if ( x_env.hasAttr(_U(vis)) ) assembly.setVisAttributes(description, x_env.visStr()); - } - if ( x_env.hasAttr(_U(region)) ) { + + if ( x_env.hasAttr(_U(region)) ) assembly.setRegion(description, x_env.regionStr()); - } - if ( x_env.hasAttr(_U(limits)) ) { + + if ( x_env.hasAttr(_U(limits)) ) assembly.setLimitSet(description, x_env.limitsStr()); - } - if ( x_det.hasAttr(_U(sensitive)) ) { + + if ( x_det.hasAttr(_U(sensitive)) ) sens.setType(x_det.attr<string>(_U(sensitive))); - } - if ( x_env.hasAttr(_U(name)) ) { + else + builder.detector.setType("compound"); + + if ( x_env.hasAttr(_U(name)) ) assembly->SetName(x_env.nameStr().c_str()); - } + builder.placeDaughters(builder.detector, assembly, x_env); builder.placeDaughters(builder.detector, assembly, x_det); x_pos = x_env.child(_U(position),false); diff --git a/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp b/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp index cf122dc68790587bb1c3fb3055b67e66e8ff9d1d..82eb1f5b42048fe317201fb75f385ad6dfde9e9e 100644 --- a/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp +++ b/DDG4/plugins/Geant4DetectorGeometryConstruction.cpp @@ -81,9 +81,9 @@ namespace dd4hep { // Geant4 include files #include "G4PVPlacement.hh" -#ifdef GEANT4_HAS_GDML +//#ifdef GEANT4_HAS_GDML #include "G4GDMLParser.hh" -#endif +//#endif using namespace std; using namespace dd4hep; @@ -137,16 +137,19 @@ void Geant4DetectorGeometryConstruction::constructGeo(Geant4DetectorConstruction Geant4HierarchyDump dmp(ctxt->description); dmp.dump("",w); } -#ifdef GEANT4_HAS_GDML - const char* gdml_dmp = ::getenv("DUMP_GDML"); - if ( !m_dumpGDML.empty() || ) { + //#ifdef GEANT4_HAS_GDML + if ( !m_dumpGDML.empty() ) { G4GDMLParser parser; - if ( !m_dumpGDML.empty() ) - parser.Write(m_dumpGDML.c_str(), w); - else if ( gdml_dmp ) + parser.Write(m_dumpGDML.c_str(), w); + } + else { + const char* gdml_dmp = ::getenv("DUMP_GDML"); + if ( gdml_dmp ) { + G4GDMLParser parser; parser.Write(gdml_dmp, w); + } } -#endif + //#endif ctxt->world = w; } diff --git a/examples/ClientTests/compact/VolumeMultiTester.xml b/examples/ClientTests/compact/VolumeMultiTester.xml new file mode 100644 index 0000000000000000000000000000000000000000..f5a5a1eb51ff99fe3a6f02be136afaa0dd8a3471 --- /dev/null +++ b/examples/ClientTests/compact/VolumeMultiTester.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lccdd> + <define> + <constant name="world_size" value="30*m"/> + <constant name="world_x" value="world_size"/> + <constant name="world_y" value="world_size"/> + <constant name="world_z" value="world_size"/> + </define> + <includes> + <gdmlFile ref="${DD4hepINSTALL}/DDDetectors/compact/elements.xml"/> + <gdmlFile ref="${DD4hepINSTALL}/DDDetectors/compact/materials.xml"/> + </includes> + <detectors> + <detector id="1" name="VolumeMultiTester" type="VolumeMultiTester"/> + </detectors> +</lccdd> diff --git a/examples/ClientTests/src/VolumeMultiTester_geo.cpp b/examples/ClientTests/src/VolumeMultiTester_geo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5832a61a3a2f474871ce471884473399bbf3f5c8 --- /dev/null +++ b/examples/ClientTests/src/VolumeMultiTester_geo.cpp @@ -0,0 +1,49 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== + +// Framework include files +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/Printout.h" + +// ROOT include file +#include "TClass.h" + +using namespace std; +using namespace dd4hep; +using namespace dd4hep::detail; + +static Ref_t create_element(Detector& description, xml_h xml_det, SensitiveDetector /* sens */) { + xml_det_t x_det = xml_det; + string det_name = x_det.nameStr(); + Box box(100, 100, 100); + Volume vol(det_name+"_vol", box, description.air()); + DetElement det(det_name,x_det.typeStr(), x_det.id()); + VolumeMulti mv; + + mv = box.divide(vol.ptr(), "Div", 1, 3, -100, 10); + printout(ALWAYS,"VolumeMultiTester","+++ VolumeMulti %p",mv.ptr()); + printout(ALWAYS,"VolumeMultiTester","+++ VolumeMulti %s",mv.name()); + printout(ALWAYS,"VolumeMultiTester","+++ VolumeMulti %s",mv->IsA()->GetName()); + + mv = box.divide(vol.ptr(), "Div2", 1, 3, 0, 50); + printout(ALWAYS,"VolumeMultiTester","+++ VolumeMulti %p",mv.ptr()); + printout(ALWAYS,"VolumeMultiTester","+++ VolumeMulti %s",mv.name()); + printout(ALWAYS,"VolumeMultiTester","+++ VolumeMulti %s",mv->IsA()->GetName()); + + PlacedVolume pv = description.pickMotherVolume(det).placeVolume(vol); + pv.addPhysVolID("system",x_det.id()); + det.setPlacement(pv); + return det; +} + +DECLARE_DETELEMENT(VolumeMultiTester,create_element)