CMS 3D CMS Logo

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

Generated on Tue Jun 9 17:40:32 2009 for CMSSW by  doxygen 1.5.4