CMS 3D CMS Logo

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