Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-03-08 03:04:10

0001 // -*- C++ -*-
0002 //
0003 // Package:     Geometry
0004 // Class  :     TGeoMgrFromDdd
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:
0010 //         Created:  Fri Jul  2 16:11:42 CEST 2010
0011 //
0012 
0013 #include "FWCore/Framework/interface/ESProducer.h"
0014 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0015 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
0016 #include "FWCore/Framework/interface/EventSetup.h"
0017 #include "FWCore/Framework/interface/ESTransientHandle.h"
0018 #include "FWCore/Framework/interface/ModuleFactory.h"
0019 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0020 
0021 #include "DetectorDescription/Core/interface/DDCompactView.h"
0022 #include "DetectorDescription/Core/interface/DDSolid.h"
0023 #include "DetectorDescription/Core/interface/DDMaterial.h"
0024 
0025 #include "Geometry/Records/interface/IdealGeometryRecord.h"
0026 
0027 #include "Fireworks/Geometry/interface/DisplayGeomRecord.h"
0028 
0029 #include "TGeoManager.h"
0030 #include "TGeoMatrix.h"
0031 #include "TGeoCompositeShape.h"
0032 #include "TGeoPcon.h"
0033 #include "TGeoPgon.h"
0034 #include "TGeoCone.h"
0035 #include "TGeoBoolNode.h"
0036 #include "TGeoTube.h"
0037 #include "TGeoArb8.h"
0038 #include "TGeoTrd2.h"
0039 #include "TGeoTorus.h"
0040 #include "TGeoEltu.h"
0041 #include "TGeoXtru.h"
0042 
0043 #include "Math/GenVector/RotationX.h"
0044 #include "Math/GenVector/RotationZ.h"
0045 
0046 #include <CLHEP/Units/SystemOfUnits.h>
0047 #include <cmath>
0048 #include <sstream>
0049 
0050 using CLHEP::cm;
0051 using CLHEP::deg;
0052 
0053 class TGeoMgrFromDdd : public edm::ESProducer {
0054 public:
0055   TGeoMgrFromDdd(const edm::ParameterSet&);
0056   TGeoMgrFromDdd(const TGeoMgrFromDdd&) = delete;
0057   const TGeoMgrFromDdd& operator=(const TGeoMgrFromDdd&) = delete;
0058 
0059   using ReturnType = std::unique_ptr<TGeoManager>;
0060 
0061   // ---------- const member functions ---------------------
0062 
0063   // ---------- static member functions --------------------
0064 
0065   // ---------- member functions ---------------------------
0066 
0067   ReturnType produce(const DisplayGeomRecord&);
0068 
0069   static void fillDescriptions(edm::ConfigurationDescriptions&);
0070 
0071 private:
0072   TGeoManager* createManager(int level);
0073 
0074   TGeoShape* createShape(const std::string& iName, const DDSolid& iSolid);
0075   TGeoVolume* createVolume(const std::string& iName, const DDSolid& iSolid, const DDMaterial& iMaterial);
0076   TGeoMaterial* createMaterial(const DDMaterial& iMaterial);
0077 
0078   // ---------- member data --------------------------------
0079 
0080   const int m_level;
0081   const bool m_verbose;
0082   const bool m_fullname;
0083   std::string m_TGeoName;
0084   std::string m_TGeoTitle;
0085 
0086   std::map<std::string, TGeoShape*> nameToShape_;
0087   std::map<std::string, TGeoVolume*> nameToVolume_;
0088   std::map<std::string, TGeoMaterial*> nameToMaterial_;
0089   std::map<std::string, TGeoMedium*> nameToMedium_;
0090 
0091   const edm::ESGetToken<DDCompactView, IdealGeometryRecord> viewToken_;
0092 };
0093 
0094 TGeoMgrFromDdd::TGeoMgrFromDdd(const edm::ParameterSet& pset)
0095     : m_level(pset.getUntrackedParameter<int>("level")),
0096       m_verbose(pset.getUntrackedParameter<bool>("verbose")),
0097       m_fullname(pset.getUntrackedParameter<bool>("fullName")),
0098       viewToken_(setWhatProduced(this).consumes()) {}
0099 
0100 void TGeoMgrFromDdd::fillDescriptions(edm::ConfigurationDescriptions& conf) {
0101   edm::ParameterSetDescription desc;
0102   desc.addUntracked<int>("level", 10)->setComment("How deep into the geometry hierarchy should the conversion go.");
0103   desc.addUntracked<bool>("verbose", false);
0104   desc.addUntracked<bool>("fullName", true)->setComment("use fillname() instead of name() when generating node names");
0105 
0106   conf.add("TGeoMgrFromDdd", desc);
0107 }
0108 
0109 //==============================================================================
0110 // Local helpers
0111 //==============================================================================
0112 
0113 namespace {
0114   TGeoCombiTrans* createPlacement(const DDRotationMatrix& iRot, const DDTranslation& iTrans) {
0115     double elements[9];
0116     iRot.GetComponents(elements);
0117     TGeoRotation r;
0118     r.SetMatrix(elements);
0119 
0120     TGeoTranslation t(iTrans.x() / cm, iTrans.y() / cm, iTrans.z() / cm);
0121 
0122     return new TGeoCombiTrans(t, r);
0123   }
0124 }  // namespace
0125 
0126 //==============================================================================
0127 // public member functions
0128 //==============================================================================
0129 
0130 TGeoMgrFromDdd::ReturnType TGeoMgrFromDdd::produce(const DisplayGeomRecord& iRecord) {
0131   using namespace edm;
0132 
0133   ESTransientHandle<DDCompactView> viewH = iRecord.getTransientHandle(viewToken_);
0134 
0135   if (!viewH.isValid()) {
0136     return std::unique_ptr<TGeoManager>();
0137   }
0138 
0139   TGeoManager* geo_mgr = new TGeoManager("cmsGeo", "CMS Detector");
0140   // NOTE: the default constructor does not create the identity matrix
0141   if (gGeoIdentity == nullptr) {
0142     gGeoIdentity = new TGeoIdentity("Identity");
0143   }
0144 
0145   edm::LogVerbatim("TGeoMgrFromDdd") << "about to initialize the DDCompactView walker with a root node "
0146                                      << viewH->root() << std::endl;
0147 
0148   auto walker = viewH->walker();
0149   auto info = walker.current();
0150 
0151   // The top most item is actually the volume holding both the
0152   // geometry AND the magnetic field volumes!
0153   walker.firstChild();
0154   if (!walker.firstChild()) {
0155     return std::unique_ptr<TGeoManager>();
0156   }
0157 
0158   TGeoVolume* top = (m_fullname ? createVolume(info.first.name().fullname(), info.first.solid(), info.first.material())
0159                                 : createVolume(info.first.name().name(), info.first.solid(), info.first.material()));
0160 
0161   if (top == nullptr) {
0162     return std::unique_ptr<TGeoManager>();
0163   }
0164 
0165   geo_mgr->SetTopVolume(top);
0166   // ROOT chokes unless colors are assigned
0167   top->SetVisibility(kFALSE);
0168   top->SetLineColor(kBlue);
0169 
0170   std::vector<TGeoVolume*> parentStack;
0171   parentStack.push_back(top);
0172 
0173   do {
0174     auto info = walker.current();
0175 
0176     if (m_verbose) {
0177       edm::LogVerbatim("TGeoMgrFromDdd") << "parentStack of size " << parentStack.size() << " info " << &info
0178                                          << " first " << &(info.first) << " second " << info.second << " Name "
0179                                          << info.first.name();
0180       auto num = (info.second != nullptr) ? info.second->copyno() : 0;
0181       edm::LogVerbatim("TGeoMgrFromDdd") << info.first.name() << " " << num << " "
0182                                          << DDSolidShapesName::name(info.first.solid().shape());
0183     }
0184 
0185     std::string name = m_fullname ? info.first.name().fullname() : info.first.name().name();
0186     bool childAlreadyExists = (nullptr != nameToVolume_[name]);
0187     TGeoVolume* child = createVolume(name, info.first.solid(), info.first.material());
0188     if (nullptr != child && info.second != nullptr) {
0189       parentStack.back()->AddNode(
0190           child, info.second->copyno(), createPlacement(info.second->rotation(), info.second->translation()));
0191       child->SetLineColor(kBlue);
0192     } else {
0193       if (info.second == nullptr) {
0194         break;
0195       }
0196     }
0197     if (nullptr == child || childAlreadyExists || m_level == int(parentStack.size())) {
0198       if (nullptr != child) {
0199         child->SetLineColor(kRed);
0200       }
0201       //stop descending
0202       if (!walker.nextSibling()) {
0203         while (walker.parent()) {
0204           parentStack.pop_back();
0205           if (walker.nextSibling()) {
0206             break;
0207           }
0208         }
0209       }
0210     } else {
0211       if (walker.firstChild()) {
0212         parentStack.push_back(child);
0213       } else {
0214         if (!walker.nextSibling()) {
0215           while (walker.parent()) {
0216             parentStack.pop_back();
0217             if (walker.nextSibling()) {
0218               break;
0219             }
0220           }
0221         }
0222       }
0223     }
0224   } while (!parentStack.empty());
0225 
0226   geo_mgr->CloseGeometry();
0227 
0228   geo_mgr->DefaultColors();
0229 
0230   nameToShape_.clear();
0231   nameToVolume_.clear();
0232   nameToMaterial_.clear();
0233   nameToMedium_.clear();
0234 
0235   return std::unique_ptr<TGeoManager>(geo_mgr);
0236 }
0237 
0238 //==============================================================================
0239 // private member functions
0240 //==============================================================================
0241 
0242 TGeoShape* TGeoMgrFromDdd::createShape(const std::string& iName, const DDSolid& iSolid) {
0243   if (m_verbose)
0244     edm::LogVerbatim("TGeoMgrFromDdd") << "createShape with name: " << iName
0245                                        << " and solid: " << iSolid.name().fullname();
0246 
0247   DDBase<DDName, DDI::Solid*>::def_type defined(iSolid.isDefined());
0248   if (!defined.first)
0249     throw cms::Exception("TGeoMgrFromDdd::createShape * solid " + iName + " is not declared * ");
0250   if (!defined.second)
0251     throw cms::Exception("TGeoMgrFromDdd::createShape * solid " + defined.first->name() + " is not defined *");
0252 
0253   TGeoShape* rSolid = nameToShape_[iName];
0254   if (rSolid == nullptr) {
0255     const std::vector<double>& params = iSolid.parameters();
0256     if (m_verbose) {
0257       std::ostringstream st1;
0258       for (const double& par : params)
0259         st1 << " : " << par;
0260       edm::LogVerbatim("TGeoMgrFromDdd") << params.size() << " Parameters" << st1.str();
0261     }
0262     switch (iSolid.shape()) {
0263       case DDSolidShape::ddbox:
0264         rSolid = new TGeoBBox(iName.c_str(), params[0] / cm, params[1] / cm, params[2] / cm);
0265         break;
0266       case DDSolidShape::ddcons:
0267         rSolid = new TGeoConeSeg(iName.c_str(),
0268                                  params[0] / cm,
0269                                  params[1] / cm,
0270                                  params[2] / cm,
0271                                  params[3] / cm,
0272                                  params[4] / cm,
0273                                  params[5] / deg,
0274                                  params[6] / deg + params[5] / deg);
0275         break;
0276       case DDSolidShape::ddtubs:
0277         //Order in params is  zhalf,rIn,rOut,startPhi,deltaPhi
0278         rSolid = new TGeoTubeSeg(iName.c_str(),
0279                                  params[1] / cm,
0280                                  params[2] / cm,
0281                                  params[0] / cm,
0282                                  params[3] / deg,
0283                                  params[3] / deg + params[4] / deg);
0284         break;
0285       case DDSolidShape::ddcuttubs:
0286         //Order in params is  zhalf,rIn,rOut,startPhi,deltaPhi,lx,ly,lz,tx,ty,tz
0287         rSolid = new TGeoCtub(iName.c_str(),
0288                               params[1] / cm,
0289                               params[2] / cm,
0290                               params[0] / cm,
0291                               params[3] / deg,
0292                               params[3] / deg + params[4] / deg,
0293                               params[5],
0294                               params[6],
0295                               params[7],
0296                               params[8],
0297                               params[9],
0298                               params[10]);
0299         break;
0300       case DDSolidShape::ddtrap:
0301         rSolid = new TGeoTrap(iName.c_str(),
0302                               params[0] / cm,     //dz
0303                               params[1] / deg,    //theta
0304                               params[2] / deg,    //phi
0305                               params[3] / cm,     //dy1
0306                               params[4] / cm,     //dx1
0307                               params[5] / cm,     //dx2
0308                               params[6] / deg,    //alpha1
0309                               params[7] / cm,     //dy2
0310                               params[8] / cm,     //dx3
0311                               params[9] / cm,     //dx4
0312                               params[10] / deg);  //alpha2
0313         break;
0314       case DDSolidShape::ddpolycone_rrz:
0315         rSolid = new TGeoPcon(iName.c_str(), params[0] / deg, params[1] / deg, (params.size() - 2) / 3);
0316         {
0317           std::vector<double> temp(params.size() + 1);
0318           temp.reserve(params.size() + 1);
0319           temp[0] = params[0] / deg;
0320           temp[1] = params[1] / deg;
0321           temp[2] = (params.size() - 2) / 3;
0322           std::copy(params.begin() + 2, params.end(), temp.begin() + 3);
0323           for (std::vector<double>::iterator it = temp.begin() + 3; it != temp.end(); ++it) {
0324             *it /= cm;
0325           }
0326           rSolid->SetDimensions(&(*(temp.begin())));
0327         }
0328         break;
0329       case DDSolidShape::ddpolyhedra_rrz:
0330         rSolid = new TGeoPgon(
0331             iName.c_str(), params[1] / deg, params[2] / deg, static_cast<int>(params[0]), (params.size() - 3) / 3);
0332         {
0333           std::vector<double> temp(params.size() + 1);
0334           temp[0] = params[1] / deg;
0335           temp[1] = params[2] / deg;
0336           temp[2] = params[0];
0337           temp[3] = (params.size() - 3) / 3;
0338           std::copy(params.begin() + 3, params.end(), temp.begin() + 4);
0339           for (std::vector<double>::iterator it = temp.begin() + 4; it != temp.end(); ++it) {
0340             *it /= cm;
0341           }
0342           rSolid->SetDimensions(&(*(temp.begin())));
0343         }
0344         break;
0345       case DDSolidShape::ddextrudedpolygon: {
0346         DDExtrudedPolygon extrPgon(iSolid);
0347         std::vector<double> x = extrPgon.xVec();
0348         std::transform(x.begin(), x.end(), x.begin(), [](double d) { return d / cm; });
0349         std::vector<double> y = extrPgon.yVec();
0350         std::transform(y.begin(), y.end(), y.begin(), [](double d) { return d / cm; });
0351         std::vector<double> z = extrPgon.zVec();
0352         std::vector<double> zx = extrPgon.zxVec();
0353         std::vector<double> zy = extrPgon.zyVec();
0354         std::vector<double> zscale = extrPgon.zscaleVec();
0355 
0356         TGeoXtru* mySolid = new TGeoXtru(z.size());
0357         mySolid->DefinePolygon(x.size(), &(*x.begin()), &(*y.begin()));
0358         for (size_t i = 0; i < params[0]; ++i) {
0359           mySolid->DefineSection(i, z[i] / cm, zx[i] / cm, zy[i] / cm, zscale[i]);
0360         }
0361 
0362         rSolid = mySolid;
0363       } break;
0364       case DDSolidShape::ddpseudotrap: {
0365         //implementation taken from SimG4Core/Geometry/src/DDG4SolidConverter.cc
0366         const static DDRotationMatrix s_rot(ROOT::Math::RotationX(90. * deg));
0367         DDPseudoTrap pt(iSolid);
0368 
0369         double r = pt.radius();
0370         bool atMinusZ = pt.atMinusZ();
0371         double x = 0;
0372         double h = 0;
0373         bool intersec = false;  // union or intersection solid
0374 
0375         if (atMinusZ) {
0376           x = pt.x1();  // tubs radius
0377         } else {
0378           x = pt.x2();  // tubs radius
0379         }
0380         double halfOpeningAngle = asin(x / std::abs(r)) / deg;
0381         double displacement = 0;
0382         double startPhi = 0;
0383         /* calculate the displacement of the tubs w.r.t. to the trap,
0384            determine the opening angle of the tubs */
0385         double delta = sqrt(r * r - x * x);
0386         std::string name = m_fullname ? pt.name().fullname() : pt.name().name();
0387 
0388         if (r < 0 && std::abs(r) >= x) {
0389           intersec = true;                            // intersection solid
0390           h = pt.y1() < pt.y2() ? pt.y2() : pt.y1();  // tubs half height
0391           h += h / 20.;                               // enlarge a bit - for subtraction solid
0392           if (atMinusZ) {
0393             displacement = -pt.halfZ() - delta;
0394             startPhi = 90. - halfOpeningAngle;
0395           } else {
0396             displacement = pt.halfZ() + delta;
0397             startPhi = -90. - halfOpeningAngle;
0398           }
0399         } else if (r > 0 && std::abs(r) >= x) {
0400           if (atMinusZ) {
0401             displacement = -pt.halfZ() + delta;
0402             startPhi = 270. - halfOpeningAngle;
0403             h = pt.y1();
0404           } else {
0405             displacement = pt.halfZ() - delta;
0406             startPhi = 90. - halfOpeningAngle;
0407             h = pt.y2();
0408           }
0409         } else {
0410           throw cms::Exception("Check parameters of the PseudoTrap! name=" + name);
0411         }
0412 
0413         std::unique_ptr<TGeoShape> trap(
0414             new TGeoTrd2(name.c_str(), pt.x1() / cm, pt.x2() / cm, pt.y1() / cm, pt.y2() / cm, pt.halfZ() / cm));
0415 
0416         std::unique_ptr<TGeoShape> tubs(new TGeoTubeSeg(name.c_str(),
0417                                                         0.,
0418                                                         std::abs(r) / cm,  // radius cannot be negative!!!
0419                                                         h / cm,
0420                                                         startPhi,
0421                                                         startPhi + halfOpeningAngle * 2.));
0422         if (intersec) {
0423           TGeoSubtraction* sub = new TGeoSubtraction(
0424               trap.release(), tubs.release(), nullptr, createPlacement(s_rot, DDTranslation(0., 0., displacement)));
0425           rSolid = new TGeoCompositeShape(iName.c_str(), sub);
0426         } else {
0427           std::unique_ptr<TGeoShape> box(new TGeoBBox(1.1 * x / cm, 1.1 * h / cm, sqrt(r * r - x * x) / cm));
0428 
0429           TGeoSubtraction* sub = new TGeoSubtraction(
0430               tubs.release(), box.release(), nullptr, createPlacement(s_rot, DDTranslation(0., 0., 0.)));
0431 
0432           std::unique_ptr<TGeoShape> tubicCap(new TGeoCompositeShape(iName.c_str(), sub));
0433 
0434           TGeoUnion* boolS = new TGeoUnion(
0435               trap.release(), tubicCap.release(), nullptr, createPlacement(s_rot, DDTranslation(0., 0., displacement)));
0436 
0437           rSolid = new TGeoCompositeShape(iName.c_str(), boolS);
0438         }
0439 
0440         break;
0441       }
0442       case DDSolidShape::ddtorus: {
0443         DDTorus solid(iSolid);
0444         rSolid = new TGeoTorus(iName.c_str(),
0445                                solid.rTorus() / cm,
0446                                solid.rMin() / cm,
0447                                solid.rMax() / cm,
0448                                solid.startPhi() / deg,
0449                                solid.deltaPhi() / deg);
0450         break;
0451       }
0452       case DDSolidShape::ddsubtraction: {
0453         DDBooleanSolid boolSolid(iSolid);
0454         if (!boolSolid) {
0455           throw cms::Exception("GeomConvert") << "conversion to DDBooleanSolid failed";
0456         }
0457 
0458         std::string nameA = m_fullname ? boolSolid.solidA().name().fullname() : boolSolid.solidA().name().name();
0459         std::string nameB = m_fullname ? boolSolid.solidB().name().fullname() : boolSolid.solidB().name().name();
0460         std::unique_ptr<TGeoShape> left(createShape(nameA, boolSolid.solidA()));
0461         std::unique_ptr<TGeoShape> right(createShape(nameB, boolSolid.solidB()));
0462         if (nullptr != left.get() && nullptr != right.get()) {
0463           TGeoSubtraction* sub =
0464               new TGeoSubtraction(left.release(),
0465                                   right.release(),
0466                                   nullptr,
0467                                   createPlacement(boolSolid.rotation().matrix(), boolSolid.translation()));
0468           rSolid = new TGeoCompositeShape(iName.c_str(), sub);
0469         }
0470         break;
0471       }
0472       case DDSolidShape::ddtrunctubs: {
0473         DDTruncTubs tt(iSolid);
0474         if (!tt) {
0475           throw cms::Exception("GeomConvert") << "conversion to DDTruncTubs failed";
0476         }
0477         double rIn(tt.rIn());
0478         double rOut(tt.rOut());
0479         double zHalf(tt.zHalf());
0480         double startPhi(tt.startPhi());
0481         double deltaPhi(tt.deltaPhi());
0482         double cutAtStart(tt.cutAtStart());
0483         double cutAtDelta(tt.cutAtDelta());
0484         bool cutInside(bool(tt.cutInside()));
0485         std::string name = m_fullname ? tt.name().fullname() : tt.name().name();
0486 
0487         // check the parameters
0488         if (rIn <= 0 || rOut <= 0 || cutAtStart <= 0 || cutAtDelta <= 0) {
0489           std::string s = "TruncTubs " + name + ": 0 <= rIn,cutAtStart,rOut,cutAtDelta,rOut violated!";
0490           throw cms::Exception(s);
0491         }
0492         if (rIn >= rOut) {
0493           std::string s = "TruncTubs " + name + ": rIn<rOut violated!";
0494           throw cms::Exception(s);
0495         }
0496         if (startPhi != 0.) {
0497           std::string s = "TruncTubs " + name + ": startPhi != 0 not supported!";
0498           throw cms::Exception(s);
0499         }
0500 
0501         startPhi = 0.;
0502         double r(cutAtStart);
0503         double R(cutAtDelta);
0504 
0505         // Note: startPhi is always 0.0
0506         std::unique_ptr<TGeoShape> tubs(
0507             new TGeoTubeSeg(name.c_str(), rIn / cm, rOut / cm, zHalf / cm, startPhi, deltaPhi / deg));
0508 
0509         double boxX(rOut), boxY(rOut);  // exaggerate dimensions - does not matter, it's subtracted!
0510 
0511         // width of the box > width of the tubs
0512         double boxZ(1.1 * zHalf);
0513 
0514         // angle of the box w.r.t. tubs
0515         double cath = r - R * cos(deltaPhi);
0516         double hypo = sqrt(r * r + R * R - 2. * r * R * cos(deltaPhi));
0517         double cos_alpha = cath / hypo;
0518         double alpha = -acos(cos_alpha);
0519 
0520         // rotationmatrix of box w.r.t. tubs
0521         TGeoRotation rot;
0522         rot.RotateX(90);
0523         rot.RotateZ(alpha / deg);
0524 
0525         // center point of the box
0526         double xBox;
0527         if (!cutInside) {
0528           xBox = r + boxX / sin(fabs(alpha));
0529         } else {
0530           xBox = -(boxX / sin(fabs(alpha)) - r);
0531         }
0532         std::unique_ptr<TGeoShape> box(new TGeoBBox(name.c_str(), boxX / cm, boxZ / cm, boxY / cm));
0533 
0534         TGeoTranslation trans(xBox / cm, 0., 0.);
0535 
0536         TGeoSubtraction* sub =
0537             new TGeoSubtraction(tubs.release(), box.release(), nullptr, new TGeoCombiTrans(trans, rot));
0538 
0539         rSolid = new TGeoCompositeShape(iName.c_str(), sub);
0540         break;
0541       }
0542       case DDSolidShape::ddunion: {
0543         DDBooleanSolid boolSolid(iSolid);
0544         if (!boolSolid) {
0545           throw cms::Exception("GeomConvert") << "conversion to DDBooleanSolid failed";
0546         }
0547 
0548         std::string nameA = m_fullname ? boolSolid.solidA().name().fullname() : boolSolid.solidA().name().name();
0549         std::string nameB = m_fullname ? boolSolid.solidB().name().fullname() : boolSolid.solidB().name().name();
0550         std::unique_ptr<TGeoShape> left(createShape(nameA, boolSolid.solidA()));
0551         std::unique_ptr<TGeoShape> right(createShape(nameB, boolSolid.solidB()));
0552         //DEBUGGING
0553         //break;
0554         if (nullptr != left.get() && nullptr != right.get()) {
0555           TGeoUnion* boolS = new TGeoUnion(left.release(),
0556                                            right.release(),
0557                                            nullptr,
0558                                            createPlacement(boolSolid.rotation().matrix(), boolSolid.translation()));
0559           rSolid = new TGeoCompositeShape(iName.c_str(), boolS);
0560         }
0561         break;
0562       }
0563       case DDSolidShape::ddintersection: {
0564         DDBooleanSolid boolSolid(iSolid);
0565         if (!boolSolid) {
0566           throw cms::Exception("GeomConvert") << "conversion to DDBooleanSolid failed";
0567         }
0568 
0569         std::string nameA = m_fullname ? boolSolid.solidA().name().fullname() : boolSolid.solidA().name().name();
0570         std::string nameB = m_fullname ? boolSolid.solidB().name().fullname() : boolSolid.solidB().name().name();
0571         std::unique_ptr<TGeoShape> left(createShape(nameA, boolSolid.solidA()));
0572         std::unique_ptr<TGeoShape> right(createShape(nameB, boolSolid.solidB()));
0573         if (nullptr != left.get() && nullptr != right.get()) {
0574           TGeoIntersection* boolS =
0575               new TGeoIntersection(left.release(),
0576                                    right.release(),
0577                                    nullptr,
0578                                    createPlacement(boolSolid.rotation().matrix(), boolSolid.translation()));
0579           rSolid = new TGeoCompositeShape(iName.c_str(), boolS);
0580         }
0581         break;
0582       }
0583       case DDSolidShape::ddellipticaltube: {
0584         DDEllipticalTube eSolid(iSolid);
0585         if (!eSolid) {
0586           throw cms::Exception("GeomConvert") << "conversion to DDEllipticalTube failed";
0587         }
0588         rSolid = new TGeoEltu(iName.c_str(), params[0] / cm, params[1] / cm, params[2] / cm);
0589         break;
0590       }
0591       default:
0592         break;
0593     }
0594     nameToShape_[iName] = rSolid;
0595   }
0596   if (rSolid == nullptr) {
0597     edm::LogError("TGeoMgrFromDdd") << "COULD NOT MAKE " << iName << " of a shape " << iSolid;
0598   }
0599 
0600   if (m_verbose)
0601     edm::LogVerbatim("TGeoMgrFromDdd") << "solid " << iName << " has been created.";
0602 
0603   return rSolid;
0604 }
0605 
0606 TGeoVolume* TGeoMgrFromDdd::createVolume(const std::string& iName, const DDSolid& iSolid, const DDMaterial& iMaterial) {
0607   if (m_verbose)
0608     edm::LogVerbatim("TGeoMgrFromDdd") << "createVolume with name: " << iName
0609                                        << " and solid: " << iSolid.name().fullname() << " and material "
0610                                        << iMaterial.name().fullname();
0611   TGeoVolume* v = nameToVolume_[iName];
0612   if (v == nullptr) {
0613     TGeoShape* solid =
0614         m_fullname ? createShape(iSolid.name().fullname(), iSolid) : createShape(iSolid.name().name(), iSolid);
0615     std::string mat_name = m_fullname ? iMaterial.name().fullname() : iMaterial.name().name();
0616     TGeoMedium* geo_med = nameToMedium_[mat_name];
0617     if (geo_med == nullptr) {
0618       TGeoMaterial* geo_mat = createMaterial(iMaterial);
0619       geo_med = new TGeoMedium(mat_name.c_str(), 0, geo_mat);
0620       nameToMedium_[mat_name] = geo_med;
0621     }
0622     if (solid) {
0623       v = new TGeoVolume(iName.c_str(), solid, geo_med);
0624     }
0625     nameToVolume_[iName] = v;
0626   }
0627   return v;
0628 }
0629 
0630 TGeoMaterial* TGeoMgrFromDdd::createMaterial(const DDMaterial& iMaterial) {
0631   std::string mat_name = m_fullname ? iMaterial.name().fullname() : iMaterial.name().name();
0632   if (m_verbose)
0633     edm::LogVerbatim("TGeoMgrFromDdd") << "createMaterial with name: " << mat_name;
0634   TGeoMaterial* mat = nameToMaterial_[mat_name];
0635 
0636   if (mat == nullptr) {
0637     if (iMaterial.noOfConstituents() > 0) {
0638       TGeoMixture* mix =
0639           new TGeoMixture(mat_name.c_str(), iMaterial.noOfConstituents(), iMaterial.density() * CLHEP::cm3 / CLHEP::g);
0640       for (int i = 0; i < iMaterial.noOfConstituents(); ++i) {
0641         mix->AddElement(createMaterial(iMaterial.constituent(i).first), iMaterial.constituent(i).second);
0642       }
0643       mat = mix;
0644     } else {
0645       mat = new TGeoMaterial(mat_name.c_str(),
0646                              iMaterial.a() * CLHEP::mole / CLHEP::g,
0647                              iMaterial.z(),
0648                              iMaterial.density() * CLHEP::cm3 / CLHEP::g);
0649     }
0650     nameToMaterial_[mat_name] = mat;
0651   }
0652 
0653   return mat;
0654 }
0655 
0656 //
0657 // const member functions
0658 //
0659 
0660 //
0661 // static member functions
0662 //
0663 DEFINE_FWK_EVENTSETUP_MODULE(TGeoMgrFromDdd);