CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/TrackingTools/GeomPropagators/src/HelixBarrelCylinderCrossing.cc

Go to the documentation of this file.
00001 #include "TrackingTools/GeomPropagators/interface/HelixBarrelCylinderCrossing.h"
00002 #include "TrackingTools/GeomPropagators/src/RealQuadEquation.h"
00003 #include "TrackingTools/GeomPropagators/interface/StraightLineCylinderCrossing.h"
00004 
00005 #include "DataFormats/GeometrySurface/interface/Cylinder.h"
00006 
00007 #include <iostream>
00008 #include <cmath>
00009 
00010 template <typename T> 
00011 inline T sqr(const T& t) {return t*t;}
00012 
00013 HelixBarrelCylinderCrossing::
00014 HelixBarrelCylinderCrossing( const GlobalPoint& startingPos,
00015                              const GlobalVector& startingDir,
00016                              double rho, PropagationDirection propDir, 
00017                              const Cylinder& cyl)
00018 {
00019   // assumes the cylinder is centered at 0,0
00020   double R = cyl.radius();
00021 
00022   // protect for zero curvature case
00023   const double sraightLineCutoff = 1.e-7;
00024   if (fabs(rho)*R < sraightLineCutoff && 
00025       fabs(rho)*startingPos.perp()  < sraightLineCutoff) {
00026     // switch to straight line case
00027     StraightLineCylinderCrossing slc( cyl.toLocal(startingPos), 
00028                                       cyl.toLocal(startingDir), propDir);
00029     std::pair<bool,double> pl = slc.pathLength( cyl);
00030     if (pl.first) {
00031       theSolExists = true;
00032       theS = pl.second;
00033       thePos = cyl.toGlobal(slc.position(theS));
00034       theDir = startingDir;
00035     }
00036     else theSolExists = false;
00037     return; // all needed data members have been set
00038   }
00039 
00040   double R2cyl = R*R;
00041   double pt   = startingDir.perp();
00042   Point center( startingPos.x()-startingDir.y()/(pt*rho),
00043                 startingPos.y()+startingDir.x()/(pt*rho));
00044   double p2 = startingPos.perp2();
00045   bool solveForX;
00046   double B, C, E, F;
00047   if (fabs(center.x()) > fabs(center.y())) {
00048     solveForX = false;
00049     E = (R2cyl - p2) / (2.*center.x());
00050     F = center.y()/center.x();
00051     B = 2.*( startingPos.y() - F*startingPos.x() - E*F);
00052     C = 2.*E*startingPos.x() + E*E + p2 - R2cyl;
00053   }
00054   else {
00055     solveForX = true;
00056     E = (R2cyl - p2) / (2.*center.y());
00057     F = center.x()/center.y();
00058     B = 2.*( startingPos.x() - F*startingPos.y() - E*F);
00059     C = 2.*E*startingPos.y() + E*E + p2 - R2cyl;
00060   }
00061 
00062   RealQuadEquation eq( 1+F*F, B, C);
00063   if (!eq.hasSolution) {
00064     theSolExists = false;
00065     return;
00066   }
00067 
00068   Vector d1, d2;;
00069   if (solveForX) {
00070     d1 = Point(eq.first,  E-F*eq.first);
00071     d2 = Point(eq.second, E-F*eq.second);
00072   }
00073   else {
00074     d1 = Point( E-F*eq.first,  eq.first);
00075     d2 = Point( E-F*eq.second, eq.second);
00076   }
00077   
00078   chooseSolution(d1, d2, startingPos, startingDir, propDir);
00079   if (!theSolExists) return;
00080 
00081   double ipabs = 1./startingDir.mag();
00082   double sinTheta = pt * ipabs;
00083   double cosTheta = startingDir.z() * ipabs;
00084 
00085 
00086   //-----  BM  
00087   //double momProj1 = startingDir.x()*d1.x() + startingDir.y()*d1.y();
00088   //double momProj2 = startingDir.x()*d2.x() + startingDir.y()*d2.y();
00089 
00090  
00091   int theActualDir1 = propDir==alongMomentum ? 1 : -1;
00092   int theActualDir2 = propDir==alongMomentum ? 1 : -1;
00093 
00094 
00095   double dMag1 = d1.mag();
00096   double tmp1 = 0.5 * dMag1 * rho;
00097   if (std::abs(tmp1)>1.) tmp1 = ::copysign(1.,tmp1);
00098   double theS1 = theActualDir1 * 2.* asin( tmp1 ) / (rho*sinTheta);
00099   thePos1 =  GlobalPoint( startingPos.x() + d1.x(),
00100                           startingPos.y() + d1.y(),
00101                           startingPos.z() + theS1*cosTheta);
00102 
00103 
00104   double dMag2 = d2.mag();
00105   double tmp2 = 0.5 * dMag2 * rho;
00106   if (std::abs(tmp2)>1.) tmp2 = ::copysign(1.,tmp2);
00107   double theS2 = theActualDir2 * 2.* asin( tmp2 ) / (rho*sinTheta);
00108   thePos2 =  GlobalPoint( startingPos.x() + d2.x(),
00109                           startingPos.y() + d2.y(),
00110                           startingPos.z() + theS2*cosTheta);    
00111   // -------
00112 
00113   double dMag = theD.mag();
00114   double tmp = 0.5 * dMag * rho;
00115   if (std::abs(tmp)>1.) tmp = ::copysign(1.,tmp);
00116   theS = theActualDir * 2.* asin( tmp ) / (rho*sinTheta);
00117   thePos =  GlobalPoint( startingPos.x() + theD.x(),
00118                          startingPos.y() + theD.y(),
00119                          startingPos.z() + theS*cosTheta);
00120 
00121   if (theS < 0) tmp = -tmp;
00122   double sinPhi = 2.*tmp*sqrt(1.-tmp*tmp);
00123   double cosPhi = 1.-2.*tmp*tmp;
00124   theDir = DirectionType(startingDir.x()*cosPhi-startingDir.y()*sinPhi,
00125                          startingDir.x()*sinPhi+startingDir.y()*cosPhi,
00126                          startingDir.z());
00127 }
00128 
00129 void HelixBarrelCylinderCrossing::chooseSolution( const Vector& d1, const Vector& d2,
00130                                                   const PositionType& startingPos,
00131                                                   const DirectionType& startingDir, 
00132                                                   PropagationDirection propDir)
00133 {
00134   double momProj1 = startingDir.x()*d1.x() + startingDir.y()*d1.y();
00135   double momProj2 = startingDir.x()*d2.x() + startingDir.y()*d2.y();
00136 
00137   if ( propDir == anyDirection ) {
00138     theSolExists = true;
00139     if (d1.mag2()<d2.mag2()) {
00140       theD = d1;
00141       theActualDir = (momProj1 > 0) ? 1 : -1;
00142     }
00143     else {
00144       theD = d2;
00145       theActualDir = (momProj2 > 0) ? 1 : -1;
00146     }
00147   }
00148   else {
00149     int propSign = propDir==alongMomentum ? 1 : -1;
00150     if (momProj1*momProj2 < 0) {
00151       // if different signs return the positive one
00152       theSolExists = true;
00153       theD = (momProj1*propSign > 0) ? d1 : d2;
00154       theActualDir = propSign;
00155     }
00156     else if (momProj1*propSign > 0) {
00157       // if both positive, return the shortest
00158       theSolExists = true;
00159       theD = (d1.mag2()<d2.mag2()) ? d1 : d2;
00160       theActualDir = propSign;
00161     }
00162     else theSolExists = false;
00163   }
00164 }
00165