CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/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   double dMag = theD.mag();
00086   double tmp = 0.5 * dMag * rho;
00087   if (std::abs(tmp)>1.) tmp = ::copysign(1.,tmp);
00088   theS = theActualDir * 2.* asin( tmp ) / (rho*sinTheta);
00089   thePos =  GlobalPoint( startingPos.x() + theD.x(),
00090                          startingPos.y() + theD.y(),
00091                          startingPos.z() + theS*cosTheta);
00092 
00093   if (theS < 0) tmp = -tmp;
00094   double sinPhi = 2.*tmp*sqrt(1.-tmp*tmp);
00095   double cosPhi = 1.-2.*tmp*tmp;
00096   theDir = DirectionType(startingDir.x()*cosPhi-startingDir.y()*sinPhi,
00097                          startingDir.x()*sinPhi+startingDir.y()*cosPhi,
00098                          startingDir.z());
00099 }
00100 
00101 void HelixBarrelCylinderCrossing::chooseSolution( const Vector& d1, const Vector& d2,
00102                                                   const PositionType& startingPos,
00103                                                   const DirectionType& startingDir, 
00104                                                   PropagationDirection propDir)
00105 {
00106   double momProj1 = startingDir.x()*d1.x() + startingDir.y()*d1.y();
00107   double momProj2 = startingDir.x()*d2.x() + startingDir.y()*d2.y();
00108 
00109   if ( propDir == anyDirection ) {
00110     theSolExists = true;
00111     if (d1.mag2()<d2.mag2()) {
00112       theD = d1;
00113       theActualDir = (momProj1 > 0) ? 1 : -1;
00114     }
00115     else {
00116       theD = d2;
00117       theActualDir = (momProj2 > 0) ? 1 : -1;
00118     }
00119   }
00120   else {
00121     int propSign = propDir==alongMomentum ? 1 : -1;
00122     if (momProj1*momProj2 < 0) {
00123       // if different signs return the positive one
00124       theSolExists = true;
00125       theD = (momProj1*propSign > 0) ? d1 : d2;
00126       theActualDir = propSign;
00127     }
00128     else if (momProj1*propSign > 0) {
00129       // if both positive, return the shortest
00130       theSolExists = true;
00131       theD = (d1.mag2()<d2.mag2()) ? d1 : d2;
00132       theActualDir = propSign;
00133     }
00134     else theSolExists = false;
00135   }
00136 }
00137