Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-05-10 02:20:42

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