CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_2_7_hltpatch2/src/TrackingTools/GeomPropagators/src/PropagationDirectionChooser.cc

Go to the documentation of this file.
00001 #include "TrackingTools/GeomPropagators/interface/PropagationDirectionChooser.h"
00002 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00003 #include "TrackingTools/GeomPropagators/interface/PropagationExceptions.h"
00004 
00005 #include "DataFormats/GeometrySurface/interface/Surface.h"
00006 #include "DataFormats/GeometrySurface/interface/Cylinder.h"
00007 #include "DataFormats/GeometrySurface/interface/Plane.h"
00008 
00009 #include "MagneticField/Engine/interface/MagneticField.h"
00010 
00011 #include <cmath>
00012 
00013 PropagationDirection
00014 PropagationDirectionChooser::operator() (const FreeTrajectoryState& fts, 
00015                                          const Surface& surface) const
00016 {
00017   // understand the surface type (expect cylinder/plane)
00018   // unfortunately dynamic_cast on Sun is broken -- cannot deal with const
00019   // so here we get rid of const
00020   Surface* sur = (Surface*)&surface;
00021   const Cylinder* bc = dynamic_cast<Cylinder*>(sur);
00022   const Plane* bp = dynamic_cast<Plane*>(sur);
00023   if (bc != 0) {
00024     //
00025     // cylinder
00026     //
00027     return (*this)(fts, *bc);
00028   }
00029   else if (bp != 0) {
00030     //
00031     // plane
00032     //
00033     return (*this)(fts, *bp);
00034   }
00035   else {
00036     throw PropagationException("The surface is neither Cylinder nor Plane");
00037   }
00038 }
00039 
00040 PropagationDirection
00041 PropagationDirectionChooser::operator() (const FreeTrajectoryState& fts, 
00042                                          const Plane& plane) const 
00043 {
00044   // propagation towards arbitrary plane
00045   // need computation of intersection point between plane 
00046   // and track (straight line approximation) to set direction
00047   // Copied from BidirectionalPropagator.
00048   PropagationDirection dir = anyDirection;
00049 
00050   GlobalPoint x = fts.position();
00051   GlobalVector p = fts.momentum().unit();
00052   GlobalPoint sp = plane.toGlobal(LocalPoint(0.,0.));
00053   GlobalVector v = plane.toGlobal(LocalVector(1.,0.,0.));
00054   GlobalVector w = plane.toGlobal(LocalVector(0.,1.,0.));
00055   AlgebraicMatrix33 a;
00056   a(0,0) = v.x(); a(0,1) = w.x(); a(0,2) = -p.x();
00057   a(1,0) = v.y(); a(1,1) = w.y(); a(1,2) = -p.y();
00058   a(2,0) = v.z(); a(2,1) = w.z(); a(2,2) = -p.z();
00059   AlgebraicVector3 b;
00060   b[0] = x.x() - sp.x();
00061   b[1] = x.y() - sp.y();
00062   b[2] = x.z() - sp.z();
00063 
00064   int ifail = !a.Invert();
00065   if (ifail == 0) {
00066     // plane and momentum are not parallel
00067     b = a*b;
00068     // b[2] nb of steps along unit vector parallel to momentum to reach plane
00069 
00070     const double small = 1.e-4; // 1 micron distance
00071     if (fabs(b[2]) < small) { 
00072       // already on plane, choose forward as default
00073       dir = alongMomentum;
00074     } 
00075     else if (b[2] < 0.) {
00076       dir = oppositeToMomentum;
00077     }
00078     else {
00079       dir = alongMomentum;    
00080     }
00081   } 
00082   return dir;
00083 }
00084 
00085 
00086 PropagationDirection
00087 PropagationDirectionChooser::operator() (const FreeTrajectoryState& fts, 
00088                                          const Cylinder& cylinder) const
00089 {
00090   // propagation to cylinder with axis along z
00091   // Copied from BidirectionalPropagator.
00092   PropagationDirection dir = anyDirection;
00093 
00094   GlobalPoint sp = cylinder.toGlobal(LocalPoint(0.,0.));
00095   if (sp.x() != 0. || sp.y() != 0.) {
00096     throw PropagationException("Cannot propagate to an arbitrary cylinder");
00097   }
00098 
00099   GlobalPoint x = fts.position();
00100   GlobalVector p = fts.momentum();
00101 
00102   const double small = 1.e-4; // 1 micron distance
00103   double rdiff = x.perp() - cylinder.radius();
00104   
00105   if ( fabs(rdiff) < small ) { 
00106     // already on cylinder, choose forward as default
00107     dir = alongMomentum;
00108   } 
00109   else {
00110     int rSign = ( rdiff >= 0. ) ? 1 : -1 ;
00111     if ( rSign == -1 ) {
00112       // starting point inside cylinder 
00113       // propagate always in direction of momentum
00114       dir = alongMomentum;
00115     }
00116     else {
00117       // starting point outside cylinder
00118       // choose direction so as to approach cylinder surface
00119       double proj = (x.x()*p.x() + x.y()*p.y()) * rSign;
00120       if (proj < 0.) {
00121         dir = alongMomentum;
00122       }
00123       else {
00124         dir = oppositeToMomentum;    
00125       }
00126     }
00127   }
00128   return dir;
00129 }