CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/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/04/20 09:56:19 $
00007  *  $Revision: 1.13 $
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     } else {
00099       cout << "*** WARNING: volume does not have a SpecPar " << pname << endl;
00100       cout << " DDsvalues_type:  " << fv.mergedSpecifics() << endl;
00101     }
00102   }
00103 
00104   { // Extract the number of the master sector.
00105     std::vector<double> temp;
00106     const std::string pname = "masterSector";
00107     DDValue val(pname);
00108     if (DDfetch(&sv,val)) {
00109       temp = val.doubles();
00110       if (temp.size() != 1) {
00111         cout << "*** WARNING: volume has > 1 SpecPar " << pname << endl;
00112       }
00113       masterSector = int(temp[0]+.5);
00114     } else {
00115       cout << "*** WARNING: volume does not have a SpecPar " << pname << endl;
00116       cout << " DDsvalues_type:  " << fv.mergedSpecifics() << endl;
00117     }  
00118   }
00119   
00120   // Get material for this volume
00121   if (fv.logicalPart().material().name().name() == "Iron") isIronFlag=true;  
00122 
00123 
00124   if (MagGeoBuilderFromDDD::debug) {  
00125     cout << " RMin =  " << theRMin <<endl;
00126     cout << " RMax =  " << theRMax <<endl;
00127       
00128     if (theRMin < 0 || theRN < theRMin || theRMax < theRN) 
00129       cout << "*** WARNING: wrong RMin/RN/RMax , shape: " << (int) shape() << endl;
00130 
00131     cout << "Summary: " << name << " " << copyno
00132          << " Shape= " << (int) shape()
00133          << " trasl " << center()
00134          << " R " << center().perp()
00135          << " phi " << center().phi()
00136          << " magFile " << magFile
00137          << " Material= " << fv.logicalPart().material().name()
00138          << " isIron= " << isIronFlag
00139          << " masterSector= " << masterSector << std::endl;
00140 
00141     cout << " Orientation of surfaces:";
00142     std::string sideName[3] =  {"positiveSide", "negativeSide", "onSurface"};
00143     for (int i=0; i<6; ++i) {    
00144       cout << "  " << i << ":" << sideName[surfaces[i]->side(center_,0.3)];
00145     }
00146     cout << endl;
00147   }
00148 }
00149 
00150 
00151 const Surface::GlobalPoint & MagGeoBuilderFromDDD::volumeHandle::center() const {
00152   return center_;
00153 }
00154 
00155 void MagGeoBuilderFromDDD::volumeHandle::referencePlane(const DDExpandedView &fv){
00156   // The refPlane is the "main plane" for the solid. It corresponds to the 
00157   // x,y plane in the DDD local frame, and defines a frame where the local
00158   // coordinates are the same as in DDD. 
00159   // In the geometry version 85l_030919, this plane is normal to the 
00160   // beam line for all volumes but pseudotraps, so that global R is along Y,
00161   // global phi is along -X and global Z along Z:
00162   //
00163   //   Global(for vol at pi/2)    Local 
00164   //   +R (+Y)                    +Y
00165   //   +phi(-X)                   -X
00166   //   +Z                         +Z
00167   //
00168   // For pseudotraps the refPlane is parallel to beam line and global R is
00169   // along Z, global phi is along +-X and and global Z along Y:
00170   // 
00171   //   Global(for vol at pi/2)    Local 
00172   //   +R (+Y)                    +Z
00173   //   +phi(-X)                   +X
00174   //   +Z                         +Y
00175   //
00176   // Note that the frame is centered in the DDD volume center, which is
00177   // inside the volume for DDD boxes and (pesudo)trapezoids, on the beam line
00178   // for tubs, cons and trunctubs. 
00179 
00180   // In geometry version 1103l, trapezoids have X and Z in the opposite direction
00181   // than the above.  Boxes are either oriented as described above or in some case 
00182   // have opposite direction for Y and X.
00183 
00184   // The global position
00185   Surface::PositionType & posResult = center_;
00186 
00187   // The reference plane rotation
00188   DD3Vector x, y, z;
00189   fv.rotation().GetComponents(x,y,z);
00190   if (MagGeoBuilderFromDDD::debug) {
00191     if (x.Cross(y).Dot(z) < 0.5) {
00192       cout << "*** WARNING: Rotation is not RH "<< endl;
00193     }
00194   }
00195   
00196   // The global rotation
00197   Surface::RotationType
00198     rotResult(float(x.X()),float(x.Y()),float(x.Z()),
00199               float(y.X()),float(y.Y()),float(y.Z()),
00200               float(z.X()),float(z.Y()),float(z.Z()));
00201 
00202   refPlane = new GloballyPositioned<float>(posResult, rotResult);
00203 
00204   // Check correct orientation
00205   if (MagGeoBuilderFromDDD::debug) {
00206 
00207     cout << "Refplane pos  " << refPlane->position() << endl;
00208 
00209     // See comments above for the conventions for orientation.
00210     LocalVector globalZdir(0.,0.,1.); // Local direction of the axis along global Z 
00211     if (solid.shape() == ddpseudotrap) {
00212       globalZdir = LocalVector(0.,1.,0.);    
00213     }
00214     if (refPlane->toGlobal(globalZdir).z()<0.) {
00215       globalZdir=-globalZdir;
00216     }
00217 
00218     float chk = refPlane->toGlobal(globalZdir).dot(GlobalVector(0,0,1));
00219     if (chk < .999) cout << "*** WARNING RefPlane check failed!***"
00220                          << chk << endl; 
00221   }
00222 }
00223 
00224 
00225 
00226 void MagGeoBuilderFromDDD::volumeHandle::buildPhiZSurf(double startPhi,
00227                                                        double deltaPhi,
00228                                                        double zhalf,
00229                                                        double rCentr) {
00230   // This is 100% equal for cons and tubs!!!
00231 
00232   GlobalVector planeXAxis = refPlane->toGlobal(LocalVector( 1, 0, 0));
00233   GlobalVector planeYAxis = refPlane->toGlobal(LocalVector( 0, 1, 0));
00234   GlobalVector planeZAxis = refPlane->toGlobal(LocalVector( 0, 0, 1));
00235 
00236   // Local Y axis of the faces at +-phi.
00237   GlobalVector y_phiplus = refPlane->toGlobal(LocalVector(cos(startPhi+deltaPhi),
00238                                                           sin(startPhi+deltaPhi),0.));
00239   GlobalVector y_phiminus = refPlane->toGlobal(LocalVector(cos(startPhi),
00240                                                            sin(startPhi),0.));
00241 
00242   Surface::RotationType rot_Z(planeXAxis,planeYAxis);
00243   Surface::RotationType rot_phiplus(planeZAxis, y_phiplus); 
00244   Surface::RotationType rot_phiminus(planeZAxis, y_phiminus);
00245 
00246   GlobalPoint pos_zplus(center_.x(),center_.y(),center_.z()+zhalf);
00247   GlobalPoint pos_zminus(center_.x(),center_.y(),center_.z()-zhalf);
00248   // BEWARE: in this case, the origin for phiplus,phiminus surfaces is 
00249   // at radius R and not on a plane passing by center_ orthogonal to the radius.
00250   GlobalPoint pos_phiplus(refPlane->toGlobal(LocalPoint(rCentr*cos(startPhi+deltaPhi),rCentr*sin(startPhi+deltaPhi),0.)));
00251   GlobalPoint pos_phiminus(refPlane->toGlobal(LocalPoint(rCentr*cos(startPhi),
00252                                                          rCentr*sin(startPhi),
00253                                                          0.)));
00254   surfaces[zplus]    = new Plane(pos_zplus, rot_Z);
00255   surfaces[zminus]   = new Plane(pos_zminus, rot_Z);
00256   surfaces[phiplus]  = new Plane(pos_phiplus, rot_phiplus);
00257   surfaces[phiminus] = new Plane(pos_phiminus, rot_phiminus);  
00258   
00259   if (MagGeoBuilderFromDDD::debug) {
00260     cout << "Actual Center at: " << center_ << " R " << center_.perp()
00261          << " phi " << center_.phi() << endl;
00262     cout << "RN            " << theRN << endl;
00263 
00264     cout << "pos_zplus    " << pos_zplus << " "
00265          << pos_zplus.perp() << " " << pos_zplus.phi() << endl
00266          << "pos_zminus   " << pos_zminus << " "
00267          << pos_zminus.perp() << " " << pos_zminus.phi() << endl
00268          << "pos_phiplus  " << pos_phiplus << " "
00269          << pos_phiplus.perp() << " " << pos_phiplus.phi() <<endl
00270          << "pos_phiminus " << pos_phiminus << " "
00271          << pos_phiminus.perp() << " " << pos_phiminus.phi() <<endl;
00272 
00273     cout << "y_phiplus " << y_phiplus << endl;
00274     cout << "y_phiminus " << y_phiminus << endl;
00275 
00276     cout << "rot_Z " << surfaces[zplus]->toGlobal(LocalVector(0.,0.,1.)) << endl
00277          << "rot_phi+ " << surfaces[phiplus]->toGlobal(LocalVector(0.,0.,1.))
00278          << " phi " << surfaces[phiplus]->toGlobal(LocalVector(0.,0.,1.)).phi()
00279          << endl
00280          << "rot_phi- " << surfaces[phiminus]->toGlobal(LocalVector(0.,0.,1.))
00281          << " phi " << surfaces[phiminus]->toGlobal(LocalVector(0.,0.,1.)).phi()
00282          << endl;
00283   }
00284   
00285 //   // Check ordering.
00286   if (MagGeoBuilderFromDDD::debug) {
00287     if (pos_zplus.z() < pos_zminus.z()) {
00288       cout << "*** WARNING: pos_zplus < pos_zminus " << endl;
00289     }
00290     if (Geom::Phi<float>(pos_phiplus.phi()-pos_phiminus.phi()) < 0. ) {
00291       cout << "*** WARNING: pos_phiplus < pos_phiminus " << endl;
00292     }
00293   }
00294 }
00295 
00296 
00297 
00298 bool MagGeoBuilderFromDDD::volumeHandle::sameSurface(const Surface & s1, Sides which_side, float tolerance)
00299 {
00300   //Check for null comparison
00301   if (&s1==(surfaces[which_side]).get()){
00302     if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: OK (same ptr)" << endl;
00303     return true;
00304   }
00305 
00306   const float maxtilt  = 0.999;
00307 
00308   const Surface & s2 = *(surfaces[which_side]);
00309   // Try with a plane.
00310   const Plane * p1 = dynamic_cast<const Plane*>(&s1);
00311   if (p1!=0) {
00312     const Plane * p2 = dynamic_cast<const Plane*>(&s2);
00313     if (p2==0) {
00314       if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: different types" << endl;
00315       return false;
00316     }
00317     
00318     if ( (fabs(p1->normalVector().dot(p2->normalVector())) > maxtilt)
00319          && (fabs((p1->toLocal(p2->position())).z()) < tolerance) ) {
00320       if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: OK "
00321                       << fabs(p1->normalVector().dot(p2->normalVector()))
00322                       << " " << fabs((p1->toLocal(p2->position())).z()) << endl;
00323       return true;
00324     } else{
00325       if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: not the same: "
00326                       << p1->normalVector() << p1->position() << endl
00327                       << "                                 "
00328                       << p2->normalVector() << p2->position() << endl
00329                       << fabs(p1->normalVector().dot(p2->normalVector()))
00330                       << " " << (p1->toLocal(p2->position())).z()<< endl;
00331       return false;
00332     }
00333   }
00334 
00335   // Try with a cylinder.  
00336   const Cylinder * cy1 = dynamic_cast<const Cylinder*>(&s1);
00337   if (cy1!=0) {
00338     const Cylinder * cy2 = dynamic_cast<const Cylinder*>(&s2);
00339     if (cy2==0) {
00340       if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: different types" << endl;
00341       return false;
00342     }
00343     // Assume axis is the same!
00344     if (fabs(cy1->radius() - cy2->radius()) < tolerance) {
00345       return true;
00346     } else {
00347       return false;
00348     }
00349   }
00350 
00351   // Try with a cone.  
00352   const Cone * co1 = dynamic_cast<const Cone*>(&s1);
00353   if (co1!=0) {
00354     const Cone * co2 = dynamic_cast<const Cone*>(&s2);
00355     if (co2==0) {
00356       if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: different types" << endl;
00357       return false;
00358     }
00359     // FIXME
00360     if (fabs(co1->openingAngle()-co2->openingAngle()) < maxtilt 
00361         && (co1->vertex()-co2->vertex()).mag() < tolerance) {
00362       return true;
00363     } else {
00364       return false;
00365     }
00366   }
00367 
00368   if (MagGeoBuilderFromDDD::debug) cout << "      sameSurface: unknown surfaces..." << endl;
00369   return false;
00370 }
00371 
00372 
00373 
00374 bool MagGeoBuilderFromDDD::volumeHandle::setSurface(const Surface & s1, Sides which_side) 
00375 {
00376  //Check for null assignment
00377   if (&s1==(surfaces[which_side]).get()){
00378     isAssigned[which_side] = true;
00379     return true;
00380   }
00381 
00382   if (!sameSurface(s1,which_side)){
00383     cout << "***ERROR: setSurface: trying to assign a surface that does not match destination surface. Skipping." << endl;    
00384     const Surface & s2 = *(surfaces[which_side]);
00385     //FIXME: Just planes for the time being!!!
00386     const Plane * p1 = dynamic_cast<const Plane*>(&s1);
00387     const Plane * p2 = dynamic_cast<const Plane*>(&s2);
00388     if (p1!=0 && p2 !=0) 
00389       cout << p1->normalVector() << p1->position() << endl
00390            << p2->normalVector() << p2->position() << endl;
00391     return false;
00392   }
00393   
00394 
00395   if (isAssigned[which_side]) {
00396     if (&s1!=(surfaces[which_side]).get()){
00397       cout << "*** WARNING volumeHandle::setSurface: trying to reassign a surface to a different surface instance" << endl;
00398       return false;
00399     }
00400   } else {
00401     surfaces[which_side] = &s1;
00402     isAssigned[which_side] = true;
00403     if (MagGeoBuilderFromDDD::debug) cout << "     Volume " << name << " # " << copyno << " Assigned: " << (int) which_side << endl;
00404     return true;
00405   }
00406 
00407   return false; // let the compiler be happy
00408 }
00409 
00410 
00411 
00412 const Surface & 
00413 MagGeoBuilderFromDDD::volumeHandle::surface(Sides which_side) const {
00414   return *(surfaces[which_side]);
00415 }
00416 
00417 
00418 
00419 const Surface & 
00420 MagGeoBuilderFromDDD::volumeHandle::surface(int which_side) const {
00421   assert(which_side >=0 && which_side <6);
00422   return *(surfaces[which_side]);
00423 }
00424 
00425 
00426 std::vector<VolumeSide>
00427 MagGeoBuilderFromDDD::volumeHandle::sides() const{
00428   std::vector<VolumeSide> result;
00429   for (int i=0; i<6; ++i){
00430     // If this is just a master volume out of wich a 2pi volume
00431     // should be built (e.g. central cylinder), skip the phi boundaries.
00432     if (expand && (i==phiplus || i==phiminus)) continue;
00433 
00434     // FIXME: Skip null inner degenerate cylindrical surface
00435     if (solid.shape() == ddtubs && i == SurfaceOrientation::inner && theRMin < 0.001) continue;
00436 
00437     ReferenceCountingPointer<Surface> s = const_cast<Surface*> (surfaces[i].get());
00438     result.push_back(VolumeSide(s, GlobalFace(i),
00439                                 surfaces[i]->side(center_,0.3)));
00440   }
00441   return result;
00442 }
00443 
00444 void MagGeoBuilderFromDDD::volumeHandle::printUniqueNames(handles::const_iterator begin, handles::const_iterator end ) {
00445     std::vector<std::string> names;
00446     for (handles::const_iterator i = begin; 
00447          i != end; ++i){
00448       names.push_back((*i)->name);
00449     }
00450      
00451     sort(names.begin(),names.end());
00452     std::vector<std::string>::iterator i = unique(names.begin(),names.end());
00453     int nvols = int(i - names.begin());
00454     cout << nvols << " ";
00455     copy(names.begin(), i, ostream_iterator<std::string>(cout, " "));
00456      
00457     cout << endl;
00458 }
00459 
00460 
00461 #include "MagneticField/GeomBuilder/src/buildBox.icc"
00462 #include "MagneticField/GeomBuilder/src/buildTrap.icc"
00463 #include "MagneticField/GeomBuilder/src/buildTubs.icc"
00464 #include "MagneticField/GeomBuilder/src/buildCons.icc"
00465 #include "MagneticField/GeomBuilder/src/buildPseudoTrap.icc"
00466 #include "MagneticField/GeomBuilder/src/buildTruncTubs.icc"