CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/MagneticField/GeomBuilder/src/volumeHandle.cc

Go to the documentation of this file.
00001 // #include "Utilities/Configuration/interface/Architecture.h"
00002 
00003 /*
00004  *  See header file for a description of this class.
00005  *
00006  *  $Date: 2010/10/13 15:21:58 $
00007  *  $Revision: 1.14 $
00008  *  \author N. Amapane - INFN Torino
00009  */
00010 
00011 #include "MagneticField/GeomBuilder/src/volumeHandle.h"
00012 #include "DetectorDescription/Core/interface/DDExpandedView.h"
00013 #include "DetectorDescription/Base/interface/DDTranslation.h"
00014 #include "DetectorDescription/Core/interface/DDSolid.h"
00015 #include "DetectorDescription/Core/interface/DDValue.h"
00016 #include "DetectorDescription/Core/interface/DDMaterial.h"
00017 
00018 #include "DataFormats/GeometrySurface/interface/Plane.h"
00019 #include "DataFormats/GeometrySurface/interface/Cylinder.h"
00020 #include "DataFormats/GeometrySurface/interface/Cone.h"
00021 #include "DataFormats/GeometryVector/interface/CoordinateSets.h"
00022 
00023 #include "CLHEP/Units/GlobalSystemOfUnits.h"
00024 
00025 #include "MagneticField/Layers/interface/MagVerbosity.h"
00026 
00027 #include <string>
00028 #include <iterator>
00029 #include <iomanip>
00030 #include <iostream>
00031 
00032 using namespace SurfaceOrientation;
00033 using namespace std;
00034 
00035 
00036 MagGeoBuilderFromDDD::volumeHandle::~volumeHandle(){
00037   delete refPlane;
00038 }
00039 
00040 MagGeoBuilderFromDDD::volumeHandle::volumeHandle(const DDExpandedView &fv, bool expand2Pi)
00041   : name(fv.logicalPart().name().name()),
00042     copyno(fv.copyno()),
00043     magVolume(0),
00044     masterSector(1),
00045     theRN(0.),
00046     theRMin(0.),
00047     theRMax(0.),
00048     refPlane(0),
00049     solid(fv.logicalPart().solid()),
00050     center_(GlobalPoint(fv.translation().x()/cm,
00051                         fv.translation().y()/cm,
00052                         fv.translation().z()/cm)),
00053     expand(expand2Pi),
00054     isIronFlag(false)
00055 {
00056   for (int i=0; i<6; ++i) {
00057     isAssigned[i] = false;
00058   }
00059 
00060   
00061   if (MagGeoBuilderFromDDD::debug) {  
00062     cout.precision(7);
00063   }
00064   
00065 
00066   referencePlane(fv);
00067 
00068   if (solid.shape() == ddbox) {
00069     buildBox(fv);
00070   } else if (solid.shape() == ddtrap) {
00071     buildTrap(fv);
00072   } else if (solid.shape() == ddcons) {
00073     buildCons(fv);
00074   } else if (solid.shape() == ddtubs) {   
00075     buildTubs(fv);
00076   } else if (solid.shape() == ddpseudotrap) {   
00077     buildPseudoTrap(fv);
00078   } else if (solid.shape() == ddtrunctubs) {   
00079     buildTruncTubs(fv);
00080   } else {
00081     cout << "volumeHandle ctor: Unexpected solid: " << (int) solid.shape() << endl;
00082   }
00083 
00084 
00085   DDsvalues_type sv(fv.mergedSpecifics());
00086     
00087   { // Extract the name of associated field file.
00088     std::vector<std::string> temp;
00089     std::string pname = "table";
00090     DDValue val(pname);
00091     DDsvalues_type sv(fv.mergedSpecifics());
00092     if (DDfetch(&sv,val)) {
00093       temp = val.strings();
00094       if (temp.size() != 1) {
00095         cout << "*** WARNING: volume has > 1 SpecPar " << pname << endl;
00096       }
00097       magFile = temp[0];
00098 
00099       string find="[copyNo]";
00100       std::size_t j;
00101       for ( ; (j = magFile.find(find)) != string::npos ; ) {
00102         stringstream conv;
00103         conv << setfill('0') << setw(2) << copyno;
00104         string repl;
00105         conv >> repl;
00106         magFile.replace(j, find.length(), repl);
00107       }
00108       
00109     } else {
00110       cout << "*** WARNING: volume does not have a SpecPar " << pname << endl;
00111       cout << " DDsvalues_type:  " << fv.mergedSpecifics() << endl;
00112     }
00113   }
00114 
00115   { // Extract the number of the master sector.
00116     std::vector<double> temp;
00117     const std::string pname = "masterSector";
00118     DDValue val(pname);
00119     if (DDfetch(&sv,val)) {
00120       temp = val.doubles();
00121       if (temp.size() != 1) {
00122         cout << "*** WARNING: volume has > 1 SpecPar " << pname << endl;
00123       }
00124       masterSector = int(temp[0]+.5);
00125     } else {
00126       if (MagGeoBuilderFromDDD::debug) { 
00127         cout << "Volume does not have a SpecPar " << pname 
00128              << " using: " << copyno << endl;
00129         cout << " DDsvalues_type:  " << fv.mergedSpecifics() << endl;
00130       }
00131       masterSector = copyno;
00132     }  
00133   }
00134   
00135   // Get material for this volume
00136   if (fv.logicalPart().material().name().name() == "Iron") isIronFlag=true;  
00137 
00138 
00139   if (MagGeoBuilderFromDDD::debug) {  
00140     cout << " RMin =  " << theRMin <<endl;
00141     cout << " RMax =  " << theRMax <<endl;
00142       
00143     if (theRMin < 0 || theRN < theRMin || theRMax < theRN) 
00144       cout << "*** WARNING: wrong RMin/RN/RMax , shape: " << (int) shape() << endl;
00145 
00146     cout << "Summary: " << name << " " << copyno
00147          << " Shape= " << (int) shape()
00148          << " trasl " << center()
00149          << " R " << center().perp()
00150          << " phi " << center().phi()
00151          << " magFile " << magFile
00152          << " Material= " << fv.logicalPart().material().name()
00153          << " isIron= " << isIronFlag
00154          << " masterSector= " << masterSector << std::endl;
00155 
00156     cout << " Orientation of surfaces:";
00157     std::string sideName[3] =  {"positiveSide", "negativeSide", "onSurface"};
00158     for (int i=0; i<6; ++i) {    
00159       cout << "  " << i << ":" << sideName[surfaces[i]->side(center_,0.3)];
00160     }
00161     cout << endl;
00162   }
00163 }
00164 
00165 
00166 const Surface::GlobalPoint & MagGeoBuilderFromDDD::volumeHandle::center() const {
00167   return center_;
00168 }
00169 
00170 void MagGeoBuilderFromDDD::volumeHandle::referencePlane(const DDExpandedView &fv){
00171   // The refPlane is the "main plane" for the solid. It corresponds to the 
00172   // x,y plane in the DDD local frame, and defines a frame where the local
00173   // coordinates are the same as in DDD. 
00174   // In the geometry version 85l_030919, this plane is normal to the 
00175   // beam line for all volumes but pseudotraps, so that global R is along Y,
00176   // global phi is along -X and global Z along Z:
00177   //
00178   //   Global(for vol at pi/2)    Local 
00179   //   +R (+Y)                    +Y
00180   //   +phi(-X)                   -X
00181   //   +Z                         +Z
00182   //
00183   // For pseudotraps the refPlane is parallel to beam line and global R is
00184   // along Z, global phi is along +-X and and global Z along Y:
00185   // 
00186   //   Global(for vol at pi/2)    Local 
00187   //   +R (+Y)                    +Z
00188   //   +phi(-X)                   +X
00189   //   +Z                         +Y
00190   //
00191   // Note that the frame is centered in the DDD volume center, which is
00192   // inside the volume for DDD boxes and (pesudo)trapezoids, on the beam line
00193   // for tubs, cons and trunctubs. 
00194 
00195   // In geometry version 1103l, trapezoids have X and Z in the opposite direction
00196   // than the above.  Boxes are either oriented as described above or in some case 
00197   // have opposite direction for Y and X.
00198 
00199   // The global position
00200   Surface::PositionType & posResult = center_;
00201 
00202   // The reference plane rotation
00203   DD3Vector x, y, z;
00204   fv.rotation().GetComponents(x,y,z);
00205   if (MagGeoBuilderFromDDD::debug) {
00206     if (x.Cross(y).Dot(z) < 0.5) {
00207       cout << "*** WARNING: Rotation is not RH "<< endl;
00208     }
00209   }
00210   
00211   // The global rotation
00212   Surface::RotationType
00213     rotResult(float(x.X()),float(x.Y()),float(x.Z()),
00214               float(y.X()),float(y.Y()),float(y.Z()),
00215               float(z.X()),float(z.Y()),float(z.Z()));
00216 
00217   refPlane = new GloballyPositioned<float>(posResult, rotResult);
00218 
00219   // Check correct orientation
00220   if (MagGeoBuilderFromDDD::debug) {
00221 
00222     cout << "Refplane pos  " << refPlane->position() << endl;
00223 
00224     // See comments above for the conventions for orientation.
00225     LocalVector globalZdir(0.,0.,1.); // Local direction of the axis along global Z 
00226     if (solid.shape() == ddpseudotrap) {
00227       globalZdir = LocalVector(0.,1.,0.);    
00228     }
00229     if (refPlane->toGlobal(globalZdir).z()<0.) {
00230       globalZdir=-globalZdir;
00231     }
00232 
00233     float chk = refPlane->toGlobal(globalZdir).dot(GlobalVector(0,0,1));
00234     if (chk < .999) cout << "*** WARNING RefPlane check failed!***"
00235                          << chk << endl; 
00236   }
00237 }
00238 
00239 
00240 
00241 void MagGeoBuilderFromDDD::volumeHandle::buildPhiZSurf(double startPhi,
00242                                                        double deltaPhi,
00243                                                        double zhalf,
00244                                                        double rCentr) {
00245   // This is 100% equal for cons and tubs!!!
00246 
00247   GlobalVector planeXAxis = refPlane->toGlobal(LocalVector( 1, 0, 0));
00248   GlobalVector planeYAxis = refPlane->toGlobal(LocalVector( 0, 1, 0));
00249   GlobalVector planeZAxis = refPlane->toGlobal(LocalVector( 0, 0, 1));
00250 
00251   // Local Y axis of the faces at +-phi.
00252   GlobalVector y_phiplus = refPlane->toGlobal(LocalVector(cos(startPhi+deltaPhi),
00253                                                           sin(startPhi+deltaPhi),0.));
00254   GlobalVector y_phiminus = refPlane->toGlobal(LocalVector(cos(startPhi),
00255                                                            sin(startPhi),0.));
00256 
00257   Surface::RotationType rot_Z(planeXAxis,planeYAxis);
00258   Surface::RotationType rot_phiplus(planeZAxis, y_phiplus); 
00259   Surface::RotationType rot_phiminus(planeZAxis, y_phiminus);
00260 
00261   GlobalPoint pos_zplus(center_.x(),center_.y(),center_.z()+zhalf);
00262   GlobalPoint pos_zminus(center_.x(),center_.y(),center_.z()-zhalf);
00263   // BEWARE: in this case, the origin for phiplus,phiminus surfaces is 
00264   // at radius R and not on a plane passing by center_ orthogonal to the radius.
00265   GlobalPoint pos_phiplus(refPlane->toGlobal(LocalPoint(rCentr*cos(startPhi+deltaPhi),rCentr*sin(startPhi+deltaPhi),0.)));
00266   GlobalPoint pos_phiminus(refPlane->toGlobal(LocalPoint(rCentr*cos(startPhi),
00267                                                          rCentr*sin(startPhi),
00268                                                          0.)));
00269   surfaces[zplus]    = new Plane(pos_zplus, rot_Z);
00270   surfaces[zminus]   = new Plane(pos_zminus, rot_Z);
00271   surfaces[phiplus]  = new Plane(pos_phiplus, rot_phiplus);
00272   surfaces[phiminus] = new Plane(pos_phiminus, rot_phiminus);  
00273   
00274   if (MagGeoBuilderFromDDD::debug) {
00275     cout << "Actual Center at: " << center_ << " R " << center_.perp()
00276          << " phi " << center_.phi() << endl;
00277     cout << "RN            " << theRN << endl;
00278 
00279     cout << "pos_zplus    " << pos_zplus << " "
00280          << pos_zplus.perp() << " " << pos_zplus.phi() << endl
00281          << "pos_zminus   " << pos_zminus << " "
00282          << pos_zminus.perp() << " " << pos_zminus.phi() << endl
00283          << "pos_phiplus  " << pos_phiplus << " "
00284          << pos_phiplus.perp() << " " << pos_phiplus.phi() <<endl
00285          << "pos_phiminus " << pos_phiminus << " "
00286          << pos_phiminus.perp() << " " << pos_phiminus.phi() <<endl;
00287 
00288     cout << "y_phiplus " << y_phiplus << endl;
00289     cout << "y_phiminus " << y_phiminus << endl;
00290 
00291     cout << "rot_Z " << surfaces[zplus]->toGlobal(LocalVector(0.,0.,1.)) << endl
00292          << "rot_phi+ " << surfaces[phiplus]->toGlobal(LocalVector(0.,0.,1.))
00293          << " phi " << surfaces[phiplus]->toGlobal(LocalVector(0.,0.,1.)).phi()
00294          << endl
00295          << "rot_phi- " << surfaces[phiminus]->toGlobal(LocalVector(0.,0.,1.))
00296          << " phi " << surfaces[phiminus]->toGlobal(LocalVector(0.,0.,1.)).phi()
00297          << endl;
00298   }
00299   
00300 //   // Check ordering.
00301   if (MagGeoBuilderFromDDD::debug) {
00302     if (pos_zplus.z() < pos_zminus.z()) {
00303       cout << "*** WARNING: pos_zplus < pos_zminus " << endl;
00304     }
00305     if (Geom::Phi<float>(pos_phiplus.phi()-pos_phiminus.phi()) < 0. ) {
00306       cout << "*** WARNING: pos_phiplus < pos_phiminus " << endl;
00307     }
00308   }
00309 }
00310 
00311 
00312 
00313 bool MagGeoBuilderFromDDD::volumeHandle::sameSurface(const Surface & s1, Sides which_side, float tolerance)
00314 {
00315   //Check for null comparison
00316   if (&s1==(surfaces[which_side]).get()){
00317     if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: OK (same ptr)" << endl;
00318     return true;
00319   }
00320 
00321   const float maxtilt  = 0.999;
00322 
00323   const Surface & s2 = *(surfaces[which_side]);
00324   // Try with a plane.
00325   const Plane * p1 = dynamic_cast<const Plane*>(&s1);
00326   if (p1!=0) {
00327     const Plane * p2 = dynamic_cast<const Plane*>(&s2);
00328     if (p2==0) {
00329       if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: different types" << endl;
00330       return false;
00331     }
00332     
00333     if ( (fabs(p1->normalVector().dot(p2->normalVector())) > maxtilt)
00334          && (fabs((p1->toLocal(p2->position())).z()) < tolerance) ) {
00335       if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: OK "
00336                       << fabs(p1->normalVector().dot(p2->normalVector()))
00337                       << " " << fabs((p1->toLocal(p2->position())).z()) << endl;
00338       return true;
00339     } else{
00340       if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: not the same: "
00341                       << p1->normalVector() << p1->position() << endl
00342                       << "                                 "
00343                       << p2->normalVector() << p2->position() << endl
00344                       << fabs(p1->normalVector().dot(p2->normalVector()))
00345                       << " " << (p1->toLocal(p2->position())).z()<< endl;
00346       return false;
00347     }
00348   }
00349 
00350   // Try with a cylinder.  
00351   const Cylinder * cy1 = dynamic_cast<const Cylinder*>(&s1);
00352   if (cy1!=0) {
00353     const Cylinder * cy2 = dynamic_cast<const Cylinder*>(&s2);
00354     if (cy2==0) {
00355       if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: different types" << endl;
00356       return false;
00357     }
00358     // Assume axis is the same!
00359     if (fabs(cy1->radius() - cy2->radius()) < tolerance) {
00360       return true;
00361     } else {
00362       return false;
00363     }
00364   }
00365 
00366   // Try with a cone.  
00367   const Cone * co1 = dynamic_cast<const Cone*>(&s1);
00368   if (co1!=0) {
00369     const Cone * co2 = dynamic_cast<const Cone*>(&s2);
00370     if (co2==0) {
00371       if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: different types" << endl;
00372       return false;
00373     }
00374     // FIXME
00375     if (fabs(co1->openingAngle()-co2->openingAngle()) < maxtilt 
00376         && (co1->vertex()-co2->vertex()).mag() < tolerance) {
00377       return true;
00378     } else {
00379       return false;
00380     }
00381   }
00382 
00383   if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: unknown surfaces..." << endl;
00384   return false;
00385 }
00386 
00387 
00388 
00389 bool MagGeoBuilderFromDDD::volumeHandle::setSurface(const Surface & s1, Sides which_side) 
00390 {
00391  //Check for null assignment
00392   if (&s1==(surfaces[which_side]).get()){
00393     isAssigned[which_side] = true;
00394     return true;
00395   }
00396 
00397   if (!sameSurface(s1,which_side)){
00398     cout << "***ERROR: setSurface: trying to assign a surface that does not match destination surface. Skipping." << endl;    
00399     const Surface & s2 = *(surfaces[which_side]);
00400     //FIXME: Just planes for the time being!!!
00401     const Plane * p1 = dynamic_cast<const Plane*>(&s1);
00402     const Plane * p2 = dynamic_cast<const Plane*>(&s2);
00403     if (p1!=0 && p2 !=0) 
00404       cout << p1->normalVector() << p1->position() << endl
00405            << p2->normalVector() << p2->position() << endl;
00406     return false;
00407   }
00408   
00409 
00410   if (isAssigned[which_side]) {
00411     if (&s1!=(surfaces[which_side]).get()){
00412       cout << "*** WARNING volumeHandle::setSurface: trying to reassign a surface to a different surface instance" << endl;
00413       return false;
00414     }
00415   } else {
00416     surfaces[which_side] = &s1;
00417     isAssigned[which_side] = true;
00418     if (MagGeoBuilderFromDDD::debug) cout << "     Volume " << name << " # " << copyno << " Assigned: " << (int) which_side << endl;
00419     return true;
00420   }
00421 
00422   return false; // let the compiler be happy
00423 }
00424 
00425 
00426 
00427 const Surface & 
00428 MagGeoBuilderFromDDD::volumeHandle::surface(Sides which_side) const {
00429   return *(surfaces[which_side]);
00430 }
00431 
00432 
00433 
00434 const Surface & 
00435 MagGeoBuilderFromDDD::volumeHandle::surface(int which_side) const {
00436   assert(which_side >=0 && which_side <6);
00437   return *(surfaces[which_side]);
00438 }
00439 
00440 
00441 std::vector<VolumeSide>
00442 MagGeoBuilderFromDDD::volumeHandle::sides() const{
00443   std::vector<VolumeSide> result;
00444   for (int i=0; i<6; ++i){
00445     // If this is just a master volume out of wich a 2pi volume
00446     // should be built (e.g. central cylinder), skip the phi boundaries.
00447     if (expand && (i==phiplus || i==phiminus)) continue;
00448 
00449     // FIXME: Skip null inner degenerate cylindrical surface
00450     if (solid.shape() == ddtubs && i == SurfaceOrientation::inner && theRMin < 0.001) continue;
00451 
00452     ReferenceCountingPointer<Surface> s = const_cast<Surface*> (surfaces[i].get());
00453     result.push_back(VolumeSide(s, GlobalFace(i),
00454                                 surfaces[i]->side(center_,0.3)));
00455   }
00456   return result;
00457 }
00458 
00459 void MagGeoBuilderFromDDD::volumeHandle::printUniqueNames(handles::const_iterator begin, handles::const_iterator end ) {
00460     std::vector<std::string> names;
00461     for (handles::const_iterator i = begin; 
00462          i != end; ++i){
00463       names.push_back((*i)->name);
00464     }
00465      
00466     sort(names.begin(),names.end());
00467     std::vector<std::string>::iterator i = unique(names.begin(),names.end());
00468     int nvols = int(i - names.begin());
00469     cout << nvols << " ";
00470     copy(names.begin(), i, ostream_iterator<std::string>(cout, " "));
00471      
00472     cout << endl;
00473 }
00474 
00475 
00476 #include "MagneticField/GeomBuilder/src/buildBox.icc"
00477 #include "MagneticField/GeomBuilder/src/buildTrap.icc"
00478 #include "MagneticField/GeomBuilder/src/buildTubs.icc"
00479 #include "MagneticField/GeomBuilder/src/buildCons.icc"
00480 #include "MagneticField/GeomBuilder/src/buildPseudoTrap.icc"
00481 #include "MagneticField/GeomBuilder/src/buildTruncTubs.icc"