CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch13/src/TrackingTools/GeomPropagators/src/HelixArbitraryPlaneCrossing2Order.cc

Go to the documentation of this file.
00001 #include "TrackingTools/GeomPropagators/interface/HelixArbitraryPlaneCrossing2Order.h"
00002 
00003 #include "DataFormats/GeometrySurface/interface/Plane.h"
00004 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00005 
00006 #include <cmath>
00007 #include <cfloat>
00008 
00009 HelixArbitraryPlaneCrossing2Order::HelixArbitraryPlaneCrossing2Order(const PositionType& point,
00010                                                                      const DirectionType& direction,
00011                                                                      const float curvature,
00012                                                                      const PropagationDirection propDir) :
00013   theX0(point.x()),
00014   theY0(point.y()),
00015   theZ0(point.z()),
00016   theRho(curvature),
00017   thePropDir(propDir)
00018 {
00019   //
00020   // Components of direction vector (with correct normalisation)
00021   //
00022   double px = direction.x();
00023   double py = direction.y();
00024   double pz = direction.z();
00025   double pt2 = px*px+py*py;
00026   double p2 = pt2+pz*pz;
00027   double pI = 1./sqrt(p2);
00028   double ptI = 1./sqrt(pt2);
00029   theCosPhi0 = px*ptI;
00030   theSinPhi0 = py*ptI;
00031   theCosTheta = pz*pI;
00032   theSinThetaI = p2*pI*ptI; //  (1/(pt/p)) = p/pt = p*ptI and p = p2/p = p2*pI
00033 }
00034 
00035 //
00036 // Propagation status and path length to intersection
00037 //
00038 std::pair<bool,double>
00039 HelixArbitraryPlaneCrossing2Order::pathLength(const Plane& plane) {
00040   //
00041   // get local z-vector in global co-ordinates and
00042   // distance to starting point
00043   //
00044   GlobalVector normalToPlane = plane.normalVector();
00045   double nPx = normalToPlane.x();
00046   double nPy = normalToPlane.y();
00047   double nPz = normalToPlane.z();
00048   double cP = plane.localZ(GlobalPoint(theX0,theY0,theZ0));
00049   //
00050   // coefficients of 2nd order equation to obtain intersection point
00051   // in approximation (without curvature-related factors).
00052   //
00053   double ceq1 = theRho*(nPx*theSinPhi0-nPy*theCosPhi0);
00054   double ceq2 = nPx*theCosPhi0 + nPy*theSinPhi0 + nPz*theCosTheta*theSinThetaI;
00055   double ceq3 = cP;
00056   //
00057   // Check for degeneration to linear equation (zero
00058   //   curvature, forward plane or direction perp. to plane)
00059   //
00060   double dS1,dS2;
00061   if ( fabs(ceq1)>FLT_MIN ) {
00062     double deq1 = ceq2*ceq2;
00063     double deq2 = ceq1*ceq3;
00064     if ( fabs(deq1)<FLT_MIN || fabs(deq2/deq1)>1.e-6 ) {
00065       //
00066       // Standard solution for quadratic equations
00067       //
00068       double deq = deq1+2*deq2;
00069       if ( deq<0. )  return std::pair<bool,double>(false,0);
00070       double ceq = -0.5*(ceq2+(ceq2>0?1:-1)*sqrt(deq));
00071       dS1 = -2*(ceq/ceq1)*theSinThetaI;
00072       dS2 = (ceq3/ceq)*theSinThetaI;
00073     }
00074     else {
00075       //
00076       // Solution by expansion of sqrt(1+deq)
00077       //
00078       double ceq = (ceq2/ceq1)*theSinThetaI;
00079       double deq = deq2/deq1;
00080       deq *= (1-0.5*deq);
00081       dS1 = -ceq*deq;
00082       dS2 = ceq*(2+deq);
00083     }
00084   }
00085   else {
00086     //
00087     // Special case: linear equation
00088     //
00089     dS1 = dS2 = -(ceq3/ceq2)*theSinThetaI;
00090   }
00091   //
00092   // Choose and return solution
00093   //
00094   return solutionByDirection(dS1,dS2);
00095 }
00096 
00097 //
00098 // Position after a step of path length s (2nd order)
00099 //
00100 HelixPlaneCrossing::PositionType
00101 HelixArbitraryPlaneCrossing2Order::position (double s) const {
00102   // use double precision result
00103   PositionTypeDouble pos = positionInDouble(s);
00104   return PositionType(pos.x(),pos.y(),pos.z());
00105 }
00106 //
00107 // Position after a step of path length s (2nd order) (in double precision)
00108 //
00109 HelixArbitraryPlaneCrossing2Order::PositionTypeDouble
00110 HelixArbitraryPlaneCrossing2Order::positionInDouble (double s) const {
00111   // based on path length in the transverse plane
00112   double st = s/theSinThetaI;
00113   return PositionTypeDouble(theX0+(theCosPhi0-(st*0.5*theRho)*theSinPhi0)*st,
00114                             theY0+(theSinPhi0+(st*0.5*theRho)*theCosPhi0)*st,
00115                             theZ0+st*theCosTheta*theSinThetaI);
00116 }
00117 //
00118 // Direction after a step of path length 2 (2nd order) (in double precision)
00119 //
00120 HelixPlaneCrossing::DirectionType
00121 HelixArbitraryPlaneCrossing2Order::direction (double s) const {
00122   // use double precision result
00123   DirectionTypeDouble dir = directionInDouble(s);
00124   return DirectionType(dir.x(),dir.y(),dir.z());
00125 }
00126 //
00127 // Direction after a step of path length 2 (2nd order)
00128 //
00129 HelixArbitraryPlaneCrossing2Order::DirectionTypeDouble
00130 HelixArbitraryPlaneCrossing2Order::directionInDouble (double s) const {
00131   // based on delta phi
00132   double dph = s*theRho/theSinThetaI;
00133   return DirectionTypeDouble(theCosPhi0-(theSinPhi0+0.5*dph*theCosPhi0)*dph,
00134                              theSinPhi0+(theCosPhi0-0.5*dph*theSinPhi0)*dph,
00135                              theCosTheta*theSinThetaI);
00136 }
00137 //
00138 // Choice of solution according to propagation direction
00139 //
00140 std::pair<bool,double>
00141 HelixArbitraryPlaneCrossing2Order::solutionByDirection(const double dS1,
00142                                                        const double dS2) const {
00143   bool valid = false;
00144   double path = 0;
00145   if ( thePropDir == anyDirection ) {
00146     valid = true;
00147     path = smallestPathLength(dS1,dS2);
00148   }
00149   else {
00150     // use same logic for both directions (invert if necessary)
00151     double propSign = thePropDir==alongMomentum ? 1 : -1;
00152     double s1(propSign*dS1);
00153     double s2(propSign*dS2);
00154     // sort
00155     if ( s1 > s2 ) {
00156       double aux = s1;
00157       s1 = s2;
00158       s2 = aux;
00159     }
00160     // choose solution (if any with positive sign)
00161     if ( s1<0 && s2>=0 ) {
00162       // First solution in backward direction: choose second one.
00163       valid = true;
00164       path = propSign*s2;
00165     }
00166     else if ( s1>=0 ) {
00167       // First solution in forward direction: choose it (s2 is further away!).
00168       valid = true;
00169       path = propSign*s1;
00170     }
00171   }
00172   return std::pair<bool,double>(valid,path);
00173 }