00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00049
00050
00051
00052
00053
00054
00055
00056
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
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
00093
00094
00095
00096
00097
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
00123
00124
00125 namespace
00126 {
00127 TGeoCombiTrans* createPlacement(const DDRotationMatrix& iRot,
00128 const DDTranslation& iTrans)
00129 {
00130
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
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
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
00175
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
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
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
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
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,
00326 params[1]/deg,
00327 params[2]/deg,
00328 params[3]/cm,
00329 params[4]/cm,
00330 params[5]/cm,
00331 params[6]/deg,
00332 params[7]/cm,
00333 params[8]/cm,
00334 params[9]/cm,
00335 params[10]/deg);
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
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
00465
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
00577
00578
00579
00580
00581