CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/Fireworks/Geometry/src/TGeoFromDddService.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     Geometry
00004 // Class  :     TGeoFromDddService
00005 // 
00006 // Implementation:
00007 //     [Notes on implementation]
00008 //
00009 // Original Author:  
00010 //         Created:  Fri Jul  2 16:11:42 CEST 2010
00011 // $Id: TGeoFromDddService.cc,v 1.4 2010/08/24 07:12:00 yana Exp $
00012 //
00013 
00014 // system include files
00015 
00016 // user include files
00017 
00018 #include "Fireworks/Geometry/interface/TGeoFromDddService.h"
00019 
00020 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00021 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
00022 #include "FWCore/Framework/interface/EventSetup.h"
00023 #include "FWCore/Framework/interface/ESTransientHandle.h"
00024 
00025 #include "DetectorDescription/Core/interface/DDCompactView.h"
00026 #include "DetectorDescription/Core/interface/DDSolid.h"
00027 #include "DetectorDescription/Core/interface/DDMaterial.h"
00028 
00029 #include "Geometry/Records/interface/IdealGeometryRecord.h"
00030 
00031 #include "TGeoManager.h"
00032 #include "TGeoMatrix.h"
00033 #include "TGeoCompositeShape.h"
00034 #include "TGeoPcon.h"
00035 #include "TGeoPgon.h"
00036 #include "TGeoCone.h"
00037 #include "TGeoBoolNode.h"
00038 #include "TGeoTube.h"
00039 #include "TGeoArb8.h"
00040 #include "TGeoTrd2.h"
00041 
00042 #include "Math/GenVector/RotationX.h"
00043 
00044 #include "CLHEP/Units/GlobalSystemOfUnits.h"
00045 
00046 
00047 //
00048 // constants, enums and typedefs
00049 //
00050 
00051 //
00052 // static data member definitions
00053 //
00054 
00055 //
00056 // constructors and destructor
00057 //
00058 TGeoFromDddService::TGeoFromDddService(const edm::ParameterSet& pset, edm::ActivityRegistry& ar) :
00059    m_level      (pset.getUntrackedParameter<int> ("level", 10)),
00060    m_verbose    (pset.getUntrackedParameter<bool>("verbose",false)),
00061    m_eventSetup (0),
00062    m_geoManager (0)
00063 {
00064    ar.watchPostBeginRun(this, &TGeoFromDddService::postBeginRun);
00065    ar.watchPostEndRun  (this, &TGeoFromDddService::postEndRun);
00066 }
00067 
00068 TGeoFromDddService::~TGeoFromDddService()
00069 {
00070    if (m_geoManager)
00071    {
00072       delete m_geoManager;
00073    }
00074 }
00075 
00076 
00077 //==============================================================================
00078 // public member functions
00079 //==============================================================================
00080 
00081 void TGeoFromDddService::postBeginRun(const edm::Run&, const edm::EventSetup& es)
00082 {
00083    printf("TGeoFromDddService::postBeginRun\n");
00084 
00085    m_eventSetup = &es;
00086 }
00087 
00088 void TGeoFromDddService::postEndRun(const edm::Run&, const edm::EventSetup&)
00089 {
00090    printf("TGeoFromDddService::postEndRun\n");
00091 
00092    // Construction of geometry fails miserably on second attempt ...
00093    /*
00094    if (m_geoManager)
00095    {
00096       delete m_geoManager;
00097       m_geoManager = 0;
00098    }
00099    */
00100    m_eventSetup = 0;
00101 }
00102 
00103 TGeoManager* TGeoFromDddService::getGeoManager()
00104 {
00105    if (m_geoManager == 0)
00106    {
00107       if (m_eventSetup == 0)
00108          edm::LogError("TGeoFromDddService") << "getGeoManager() -- EventSetup not present.\n";
00109       else
00110       {
00111          m_geoManager = createManager(m_level);
00112          if (m_geoManager == 0)
00113             edm::LogError("TGeoFromDddService") << "getGeoManager() -- creation failed.\n";
00114       }
00115    }
00116    gGeoManager = m_geoManager;
00117    return m_geoManager;
00118 }
00119 
00120 
00121 //==============================================================================
00122 // Local helpers
00123 //==============================================================================
00124 
00125 namespace
00126 {
00127    TGeoCombiTrans* createPlacement(const DDRotationMatrix& iRot,
00128                                    const DDTranslation&    iTrans)
00129    {
00130       //  std::cout << "in createPlacement" << std::endl;
00131       double elements[9];
00132       iRot.GetComponents(elements);
00133       TGeoRotation r;
00134       r.SetMatrix(elements);
00135 
00136       TGeoTranslation t(iTrans.x()/cm,
00137                         iTrans.y()/cm,
00138                         iTrans.z()/cm);
00139 
00140       return new TGeoCombiTrans(t,r);
00141    }
00142 }
00143 
00144 
00145 //==============================================================================
00146 // private member functions
00147 //==============================================================================
00148 
00149 
00150 TGeoManager*
00151 TGeoFromDddService::createManager(int level)
00152 {
00153    using namespace edm;
00154 
00155    ESTransientHandle<DDCompactView> viewH;
00156    m_eventSetup->get<IdealGeometryRecord>().get(viewH);
00157 
00158    if ( ! viewH.isValid() )
00159    {
00160       return 0;
00161    }
00162 
00163    TGeoManager *geo_mgr = new TGeoManager("cmsGeo","CMS Detector");
00164    // NOTE: the default constructor does not create the identity matrix
00165    if (gGeoIdentity == 0)
00166    {
00167       gGeoIdentity = new TGeoIdentity("Identity");
00168    }
00169 
00170    std::cout << "about to initialize the DDCompactView walker" << std::endl;
00171    DDCompactView::walker_type             walker(viewH->graph());
00172    DDCompactView::walker_type::value_type info = walker.current();
00173 
00174    // The top most item is actually the volume holding both the
00175    // geometry AND the magnetic field volumes!
00176    walker.firstChild();
00177 
00178    TGeoVolume *top = createVolume(info.first.name().fullname(),
00179                                   info.first.solid(),
00180                                   info.first.material());
00181    if (top == 0)
00182    {
00183       
00184       return 0;
00185    }
00186 
00187    geo_mgr->SetTopVolume(top);
00188    // ROOT chokes unless colors are assigned
00189    top->SetVisibility(kFALSE);
00190    top->SetLineColor(kBlue);
00191 
00192    std::vector<TGeoVolume*> parentStack;
00193    parentStack.push_back(top);
00194 
00195    if( ! walker.firstChild() ) {
00196       return 0;
00197    }
00198 
00199    do
00200    {
00201       DDCompactView::walker_type::value_type info = walker.current();
00202 
00203       if (m_verbose)
00204       {
00205          for(unsigned int i=0; i<parentStack.size();++i) {
00206             std::cout <<" ";
00207          }
00208          std::cout << info.first.name()<<" "<<info.second->copyno_<<" "
00209                    << DDSolidShapesName::name(info.first.solid().shape())<<std::endl;
00210       }
00211 
00212       bool childAlreadyExists = (0 != nameToVolume_[info.first.name().fullname()]);
00213       TGeoVolume *child = createVolume(info.first.name().fullname(),
00214                                        info.first.solid(),
00215                                        info.first.material());
00216       if (0!=child && info.second != 0)
00217       {
00218          parentStack.back()->AddNode(child,
00219                                  info.second->copyno_,
00220                                  createPlacement(info.second->rotation(),
00221                                                  info.second->translation()));
00222          child->SetLineColor(kBlue);
00223       }
00224       else
00225       {
00226         if ( info.second == 0 ) {
00227           break;
00228         }
00229       }
00230       if (0 == child || childAlreadyExists || level == int(parentStack.size()))
00231       {
00232          if (0!=child)
00233          {
00234             child->SetLineColor(kRed);
00235          }
00236          //stop descending
00237          if ( ! walker.nextSibling())
00238          {
00239             while (walker.parent())
00240             {
00241                parentStack.pop_back();
00242                if (walker.nextSibling()) {
00243                   break;
00244                }
00245             }
00246          }
00247       }
00248       else
00249       {
00250          if (walker.firstChild())
00251          {
00252             parentStack.push_back(child);
00253          }
00254          else
00255          {          
00256             if ( ! walker.nextSibling())
00257             {
00258                while (walker.parent())
00259                {
00260                   parentStack.pop_back();
00261                   if (walker.nextSibling()) {
00262                      break;
00263                   }
00264                }
00265             }
00266          }
00267       }
00268    } while ( ! parentStack.empty());
00269 
00270    geo_mgr->CloseGeometry();
00271 
00272    geo_mgr->DefaultColors();
00273 
00274    nameToShape_.clear();
00275    nameToVolume_.clear();
00276    nameToMaterial_.clear();
00277    nameToMedium_.clear();
00278 
00279    return geo_mgr;
00280 }
00281 
00282 TGeoShape* 
00283 TGeoFromDddService::createShape(const std::string& iName,
00284                       const DDSolid&     iSolid)
00285 {
00286    TGeoShape* rSolid= nameToShape_[iName];
00287    if (rSolid == 0)
00288    {
00289       const std::vector<double>& params = iSolid.parameters();
00290       //      std::cout <<"  shape "<<iSolid<<std::endl;
00291       switch(iSolid.shape())
00292       {
00293          case ddbox:
00294             rSolid = new TGeoBBox(
00295                                   iName.c_str(),
00296                                   params[0]/cm,
00297                                   params[1]/cm,
00298                                   params[2]/cm);
00299             break;
00300          case ddcons:
00301             rSolid = new TGeoConeSeg(
00302                                      iName.c_str(),
00303                                      params[0]/cm,
00304                                      params[1]/cm,
00305                                      params[2]/cm,
00306                                      params[3]/cm,
00307                                      params[4]/cm,
00308                                      params[5]/deg,
00309                                      params[6]/deg+params[5]/deg
00310                                      );
00311             break;
00312          case ddtubs:
00313             //Order in params is  zhalf,rIn,rOut,startPhi,deltaPhi
00314             rSolid= new TGeoTubeSeg(
00315                                     iName.c_str(),
00316                                     params[1]/cm,
00317                                     params[2]/cm,
00318                                     params[0]/cm,
00319                                     params[3]/deg,
00320                                     params[4]/deg);
00321             break;
00322          case ddtrap:
00323             rSolid =new TGeoTrap(
00324                                  iName.c_str(),
00325                                  params[0]/cm,  //dz
00326                                  params[1]/deg, //theta
00327                                  params[2]/deg, //phi
00328                                  params[3]/cm,  //dy1
00329                                  params[4]/cm,  //dx1
00330                                  params[5]/cm,  //dx2
00331                                  params[6]/deg, //alpha1
00332                                  params[7]/cm,  //dy2
00333                                  params[8]/cm,  //dx3
00334                                  params[9]/cm,  //dx4
00335                                  params[10]/deg);//alpha2
00336             break;
00337          case ddpolycone_rrz:    
00338             rSolid = new TGeoPcon(
00339                                   iName.c_str(),
00340                                   params[0]/deg,
00341                                   params[1]/deg,
00342                                   (params.size()-2)/3) ;
00343             {
00344                std::vector<double> temp(params.size()+1);
00345                temp.reserve(params.size()+1);
00346                temp[0]=params[0]/deg;
00347                temp[1]=params[1]/deg;
00348                temp[2]=(params.size()-2)/3;
00349                std::copy(params.begin()+2,params.end(),temp.begin()+3);
00350                for(std::vector<double>::iterator it=temp.begin()+3;
00351                    it != temp.end();
00352                    ++it) {
00353                   *it /=cm;
00354                }               
00355                rSolid->SetDimensions(&(*(temp.begin())));
00356             }
00357             break;
00358          case ddpolyhedra_rrz:
00359             rSolid = new TGeoPgon(
00360                                   iName.c_str(),
00361                                   params[1]/deg,
00362                                   params[2]/deg,
00363                                   static_cast<int>(params[0]),
00364                                   (params.size()-3)/3);
00365             {
00366                std::vector<double> temp(params.size()+1);
00367                temp[0]=params[1]/deg;
00368                temp[1]=params[2]/deg;
00369                temp[2]=params[0];
00370                temp[3]=(params.size()-3)/3;
00371                std::copy(params.begin()+3,params.end(),temp.begin()+4);
00372                for(std::vector<double>::iterator it=temp.begin()+4;
00373                    it != temp.end();
00374                    ++it) {
00375                   *it /=cm;
00376                }
00377                rSolid->SetDimensions(&(*(temp.begin())));
00378             }
00379             break;
00380          case ddpseudotrap:
00381          {
00382             //implementation taken from SimG4Core/Geometry/src/DDG4SolidConverter.cc
00383             static DDRotationMatrix s_rot(ROOT::Math::RotationX(90.*deg));
00384             DDPseudoTrap pt(iSolid);
00385             assert(pt.radius() < 0);
00386             double x=0;
00387             double r = fabs(pt.radius());
00388             if( pt.atMinusZ()) {
00389                x=pt.x1();
00390             } else {
00391                x=pt.x2();
00392             }
00393             double openingAngle = 2.0*asin(x/r);
00394             double h=pt.y1()<pt.y2()? pt.y2() :pt.y1();
00395             h+=h/20.;
00396             double displacement=0;
00397             double startPhi = 0;
00398             double delta = sqrt((r+x)*(r-x));
00399             if(pt.atMinusZ()) {
00400                displacement=-pt.halfZ() - delta;
00401                startPhi = 270.-openingAngle/deg/2.0;
00402             }else {
00403                displacement = pt.halfZ() + delta;
00404                startPhi = 90. - openingAngle/deg/2.;
00405             }
00406             std::auto_ptr<TGeoShape> trap( new TGeoTrd2(pt.name().name().c_str(),
00407                                                         pt.x1()/cm,
00408                                                         pt.x2()/cm,
00409                                                         pt.y1()/cm,
00410                                                         pt.y2()/cm,
00411                                                         pt.halfZ()/cm) );
00412             std::auto_ptr<TGeoShape> tubs( new TGeoTubeSeg(pt.name().name().c_str(),
00413                                                            0.,
00414                                                            r/cm,
00415                                                            h/cm,
00416                                                            startPhi,
00417                                                            openingAngle) );
00418             TGeoSubtraction* sub = new TGeoSubtraction(trap.release(),
00419                                                        tubs.release(),
00420                                                        createPlacement(s_rot,
00421                                                                        DDTranslation(0.,
00422                                                                                      0.,
00423                                                                                      displacement)));
00424             rSolid = new TGeoCompositeShape(iName.c_str(),
00425                                             sub);
00426             
00427             
00428             break;
00429          }
00430          case ddsubtraction:
00431          {
00432             DDBooleanSolid boolSolid(iSolid);
00433             if(!boolSolid) {
00434                throw cms::Exception("GeomConvert") <<"conversion to DDBooleanSolid failed";
00435             }
00436             
00437             std::auto_ptr<TGeoShape> left( createShape(boolSolid.solidA().name().fullname(),
00438                                                        boolSolid.solidA()) );
00439             std::auto_ptr<TGeoShape> right( createShape(boolSolid.solidB().name().fullname(),
00440                                                         boolSolid.solidB()));
00441             if( 0 != left.get() &&
00442                 0 != right.get() ) {
00443                TGeoSubtraction* sub = new TGeoSubtraction(left.release(),right.release(),
00444                                                           gGeoIdentity,
00445                                                           createPlacement(
00446                                                                           *(boolSolid.rotation().matrix()),
00447                                                                           boolSolid.translation()));
00448                rSolid = new TGeoCompositeShape(iName.c_str(),
00449                                                sub);
00450             }
00451             break;
00452          }
00453          case ddunion:
00454          {
00455             DDBooleanSolid boolSolid(iSolid);
00456             if(!boolSolid) {
00457                throw cms::Exception("GeomConvert") <<"conversion to DDBooleanSolid failed";
00458             }
00459             
00460             std::auto_ptr<TGeoShape> left( createShape(boolSolid.solidA().name().fullname(),
00461                                                        boolSolid.solidA()) );
00462             std::auto_ptr<TGeoShape> right( createShape(boolSolid.solidB().name().fullname(),
00463                                                         boolSolid.solidB()));
00464             //DEBUGGING
00465             //break;
00466             if( 0 != left.get() &&
00467                 0 != right.get() ) {
00468                TGeoUnion* boolS = new TGeoUnion(left.release(),right.release(),
00469                                                 gGeoIdentity,
00470                                                 createPlacement(
00471                                                                 *(boolSolid.rotation().matrix()),
00472                                                                 boolSolid.translation()));
00473                rSolid = new TGeoCompositeShape(iName.c_str(),
00474                                                boolS);
00475             }
00476             break;
00477          }
00478          case ddintersection:
00479          {
00480             DDBooleanSolid boolSolid(iSolid);
00481             if(!boolSolid) {
00482                throw cms::Exception("GeomConvert") <<"conversion to DDBooleanSolid failed";
00483             }
00484             
00485             std::auto_ptr<TGeoShape> left( createShape(boolSolid.solidA().name().fullname(),
00486                                                        boolSolid.solidA()) );
00487             std::auto_ptr<TGeoShape> right( createShape(boolSolid.solidB().name().fullname(),
00488                                                         boolSolid.solidB()));
00489             if( 0 != left.get() &&
00490                 0 != right.get() ) {
00491                TGeoIntersection* boolS = new TGeoIntersection(left.release(),
00492                                                               right.release(),
00493                                                               gGeoIdentity,
00494                                                               createPlacement(
00495                                                                               *(boolSolid.rotation().matrix()),
00496                                                                               boolSolid.translation()));
00497                rSolid = new TGeoCompositeShape(iName.c_str(),
00498                                                boolS);
00499             }
00500             break;
00501          }
00502          default:
00503             break;
00504       }
00505       nameToShape_[iName]=rSolid;
00506    }
00507    if (rSolid == 0)
00508    {
00509       std::cerr <<"COULD NOT MAKE "<<iName<<std::endl;
00510    }
00511    return rSolid;
00512 }
00513 
00514 TGeoVolume* 
00515 TGeoFromDddService::createVolume(const std::string& iName,
00516                        const DDSolid& iSolid,
00517                        const DDMaterial& iMaterial)
00518 {
00519    TGeoVolume* v=nameToVolume_[iName];
00520    if (v == 0)
00521    {
00522       TGeoShape* solid     = createShape(iSolid.name().fullname(),
00523                                          iSolid);
00524       std::string mat_name = iMaterial.name().fullname();
00525       TGeoMedium *geo_med  = nameToMedium_[mat_name];
00526       if (geo_med == 0)
00527       {
00528          TGeoMaterial *geo_mat = createMaterial(iMaterial);
00529          geo_med = new TGeoMedium(mat_name.c_str(), 0, geo_mat);
00530          nameToMedium_[mat_name] = geo_med;
00531       }
00532       if (solid)
00533       {
00534          v = new TGeoVolume(iName.c_str(),
00535                             solid,
00536                             geo_med);
00537       }
00538       nameToVolume_[iName] = v;
00539    }
00540    return v;
00541 }
00542 
00543 TGeoMaterial*
00544 TGeoFromDddService::createMaterial(const DDMaterial& iMaterial)
00545 {
00546    std::string   mat_name = iMaterial.name().fullname();
00547    TGeoMaterial *mat      = nameToMaterial_[mat_name];
00548 
00549    if (mat == 0)
00550    {
00551       if (iMaterial.noOfConstituents() > 0)
00552       {
00553          TGeoMixture *mix = new TGeoMixture(mat_name.c_str(),
00554                                             iMaterial.noOfConstituents(),
00555                                             iMaterial.density()*cm3/g);
00556          for (int i = 0; i < iMaterial.noOfConstituents(); ++i)
00557          {
00558             mix->AddElement(createMaterial(iMaterial.constituent(i).first),
00559                             iMaterial.constituent(i).second);
00560          }
00561          mat = mix;
00562       }
00563       else
00564       {
00565          mat = new TGeoMaterial(mat_name.c_str(),
00566                                 iMaterial.a()*mole/g, iMaterial.z(),
00567                                 iMaterial.density()*cm3/g);
00568       }
00569       nameToMaterial_[mat_name] = mat;
00570    }
00571 
00572    return mat;
00573 }
00574 
00575 //
00576 // const member functions
00577 //
00578 
00579 //
00580 // static member functions
00581 //