CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/TrackingTools/GeomPropagators/src/HelixBarrelPlaneCrossingByCircle.cc

Go to the documentation of this file.
00001 #include "TrackingTools/GeomPropagators/interface/HelixBarrelPlaneCrossingByCircle.h"
00002 #include "TrackingTools/GeomPropagators/src/RealQuadEquation.h"
00003 #include "TrackingTools/GeomPropagators/interface/StraightLinePlaneCrossing.h"
00004 #include "DataFormats/GeometrySurface/interface/Plane.h"
00005 #include "DataFormats/Math/interface/SSEVec.h"
00006 
00007 #include <algorithm>
00008 #include <cfloat>
00009 
00010 HelixBarrelPlaneCrossingByCircle::
00011 HelixBarrelPlaneCrossingByCircle( const PositionType& pos,
00012                                   const DirectionType& dir,
00013                                   double rho, PropagationDirection propDir) :
00014   theStartingPos( pos), theStartingDir(dir), 
00015   theRho(rho), thePropDir(propDir) { init();}
00016 
00017 HelixBarrelPlaneCrossingByCircle::
00018 HelixBarrelPlaneCrossingByCircle( const GlobalPoint& pos,
00019                                   const GlobalVector& dir,
00020                                   double rho, PropagationDirection propDir) :
00021   theStartingPos( pos.basicVector()), theStartingDir(dir.basicVector()), 
00022   theRho(rho), thePropDir(propDir) { init();}
00023 
00024 void HelixBarrelPlaneCrossingByCircle::init()
00025 {
00026   double pabsI = 1./theStartingDir.mag();
00027   double pt   = theStartingDir.perp();
00028   theCosTheta = theStartingDir.z()*pabsI;
00029   theSinTheta = pt*pabsI;
00030 
00031   // protect for zero curvature case
00032   const double sraightLineCutoff = 1.e-7;
00033   if (fabs(theRho) < sraightLineCutoff && 
00034       fabs(theRho)*theStartingPos.perp()  < sraightLineCutoff) {
00035     useStraightLine = true;
00036   }else{
00037     // circle parameters
00038     // position of center of curvature is on a line perpendicular
00039     // to startingDir and at a distance 1/curvature.
00040     double o = 1./(pt*theRho);
00041     theXCenter = theStartingPos.x() - theStartingDir.y()*o;
00042     theYCenter = theStartingPos.y() + theStartingDir.x()*o;
00043     useStraightLine = false;
00044   }
00045 }
00046 
00047 std::pair<bool,double>
00048 HelixBarrelPlaneCrossingByCircle::pathLength( const Plane& plane)
00049 {
00050   typedef std::pair<bool,double>     ResultType;
00051   
00052   if(useStraightLine){
00053     // switch to straight line case
00054     StraightLinePlaneCrossing slc( theStartingPos, 
00055                                    theStartingDir, thePropDir);
00056     return slc.pathLength( plane);
00057   }
00058   
00059 
00060   // plane parameters
00061   GlobalVector n = plane.normalVector();
00062   double distToPlane = -plane.localZ( GlobalPoint( theStartingPos));
00063   //    double distToPlane = (plane.position().x()-theStartingPos.x()) * n.x() +
00064   //                         (plane.position().y()-theStartingPos.y()) * n.y();
00065   double nx = n.x();  // convert to double
00066   double ny = n.y();  // convert to double
00067   double distCx = theStartingPos.x() - theXCenter;
00068   double distCy = theStartingPos.y() - theYCenter;
00069 
00070   double nfac, dfac;
00071   double A, B, C;
00072   bool solveForX;
00073   if (fabs(nx) > fabs(ny)) {
00074     solveForX = false;
00075     nfac = ny/nx;
00076     dfac = distToPlane/nx;
00077     B = distCy - nfac*distCx;  // only part of B, may have large cancelation
00078     C = (2.*distCx + dfac)*dfac;
00079   }
00080   else {
00081     solveForX = true;
00082     nfac = nx/ny;
00083     dfac = distToPlane/ny;
00084     B = distCx - nfac*distCy; // only part of B, may have large cancelation
00085     C = (2.*distCy + dfac)*dfac;
00086   }
00087   B -= nfac*dfac; B *= 2;  // the rest of B (normally small)
00088   A = 1.+ nfac*nfac;
00089 
00090   double dx1, dx2, dy1, dy2;
00091   RealQuadEquation equation(A,B,C);
00092   if (!equation.hasSolution) return ResultType( false, 0.);
00093   else {
00094     if (solveForX) {
00095       dx1 = equation.first;
00096       dx2 = equation.second;
00097       dy1 = dfac - nfac*dx1;
00098       dy2 = dfac - nfac*dx2;
00099     }
00100     else {
00101       dy1 = equation.first;
00102       dy2 = equation.second;
00103       dx1 = dfac - nfac*dy1;
00104       dx2 = dfac - nfac*dy2;
00105     }
00106   }
00107   bool solved = chooseSolution( Vector2D(dx1, dy1), Vector2D(dx2, dy2));
00108   if (solved) {
00109     theDmag = theD.mag();
00110     // protect asin (taking some safety margin)
00111     double sinAlpha = 0.5*theDmag*theRho;
00112     if ( sinAlpha>(1.-10*DBL_EPSILON) )  sinAlpha = 1.-10*DBL_EPSILON;
00113     else if ( sinAlpha<-(1.-10*DBL_EPSILON) )  sinAlpha = -(1.-10*DBL_EPSILON);
00114     theS = theActualDir*2./(theRho*theSinTheta) * asin( sinAlpha);
00115     return ResultType( true, theS);
00116   }
00117   else return ResultType( false, 0.);
00118 }
00119 
00120 bool
00121 HelixBarrelPlaneCrossingByCircle::chooseSolution( const Vector2D& d1, 
00122                                                   const Vector2D& d2)
00123 {
00124   bool solved;
00125   double momProj1 = theStartingDir.x()*d1.x() + theStartingDir.y()*d1.y();
00126   double momProj2 = theStartingDir.x()*d2.x() + theStartingDir.y()*d2.y();
00127 
00128   if ( thePropDir == anyDirection ) {
00129     solved = true;
00130     if (d1.mag2()<d2.mag2()) {
00131       theD = d1;
00132       theActualDir = (momProj1 > 0) ? 1. : -1.;
00133     }
00134     else {
00135       theD = d2;
00136       theActualDir = (momProj2 > 0) ? 1. : -1.;
00137     }
00138 
00139   }
00140   else {
00141     double propSign = thePropDir==alongMomentum ? 1 : -1;
00142     if (!mathSSE::samesign(momProj1,momProj2)) {
00143       // if different signs return the positive one
00144       solved = true;
00145       theD         = mathSSE::samesign(momProj1,propSign) ? d1 : d2;
00146       theActualDir = propSign;
00147     }
00148     else if (mathSSE::samesign(momProj1,propSign)) {
00149       // if both positive, return the shortest
00150       solved = true;
00151       theD = (d1.mag2()<d2.mag2()) ? d1 : d2;
00152       theActualDir = propSign;
00153     }
00154     else solved = false;
00155   }
00156   return solved;
00157 }
00158 
00159 HelixPlaneCrossing::PositionType 
00160 HelixBarrelPlaneCrossingByCircle::position( double s) const
00161 {
00162   if(useStraightLine){
00163     return PositionType(theStartingPos+s*theStartingDir.unit());
00164   }else{
00165     if ( s==theS) {
00166       return PositionType( theStartingPos.x() + theD.x(),
00167                            theStartingPos.y() + theD.y(), 
00168                            theStartingPos.z() + s*theCosTheta);
00169     }
00170     else {
00171       double phi = s*theSinTheta*theRho;
00172       double x1Shift = theStartingPos.x() - theXCenter;
00173       double y1Shift = theStartingPos.y() - theYCenter;
00174       
00175       return PositionType(x1Shift*cos(phi)-y1Shift*sin(phi) + theXCenter,
00176                           x1Shift*sin(phi)+y1Shift*cos(phi) + theYCenter,
00177                           theStartingPos.z() + s*theCosTheta);
00178     }
00179   }
00180 }
00181 
00182 HelixPlaneCrossing::DirectionType 
00183 HelixBarrelPlaneCrossingByCircle::direction( double s) const
00184 {
00185   if(useStraightLine){return theStartingDir;}
00186   else{
00187     double sinPhi, cosPhi;
00188     if ( s==theS) {
00189       double tmp = 0.5*theDmag*theRho;
00190       if (s < 0) tmp = -tmp;
00191       // protect sqrt
00192       sinPhi = 1.-(tmp*tmp);
00193       if ( sinPhi<0 )  sinPhi = 0.;
00194       sinPhi = 2.*tmp*sqrt(sinPhi);
00195       cosPhi = 1.-2.*(tmp*tmp);
00196     }
00197     else {
00198       double phi = s*theSinTheta*theRho;
00199       sinPhi = sin(phi);
00200       cosPhi = cos(phi);
00201     }
00202     return DirectionType(theStartingDir.x()*cosPhi-theStartingDir.y()*sinPhi,
00203                          theStartingDir.x()*sinPhi+theStartingDir.y()*cosPhi,
00204                          theStartingDir.z());
00205   }
00206 }