CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/src/TrackingTools/GeomPropagators/src/HelixExtrapolatorToLine2Order.cc

Go to the documentation of this file.
00001 #include "TrackingTools/GeomPropagators/interface/HelixExtrapolatorToLine2Order.h"
00002 #include "DataFormats/GeometrySurface/interface/Line.h"
00003 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00004 
00005 #include <cfloat>
00006 
00007 HelixExtrapolatorToLine2Order::HelixExtrapolatorToLine2Order(const PositionType& point,
00008                                                              const DirectionType& direction,
00009                                                              const float curvature,
00010                                                              const PropagationDirection propDir) :
00011   thePosition(point),
00012   theRho(curvature),
00013   thePropDir(propDir)
00014 {
00015   //
00016   // Components of direction vector (with correct normalisation)
00017   //
00018   double px = direction.x();
00019   double py = direction.y();
00020   double pz = direction.z();
00021   double pt = px*px+py*py;
00022   double p = sqrt(pt+pz*pz);
00023   pt = sqrt(pt);
00024   theDirection = DirectionTypeDouble(px/pt,py/pt,pz/pt);
00025   theSinTheta = pt/p;
00026 }
00027 
00028 //
00029 // Propagation status and path length to closest approach with point
00030 //
00031 std::pair<bool,double>
00032 HelixExtrapolatorToLine2Order::pathLength (const GlobalPoint& point) const {
00033   //
00034   PositionTypeDouble position(point);
00035   DirectionTypeDouble helix2(-0.5*theRho*theDirection.y(),
00036                              0.5*theRho*theDirection.x(),
00037                              0.);
00038   DirectionTypeDouble deltaPos(thePosition-position);
00039   //
00040   // coefficients of 3rd order equation
00041   //
00042   double ceq[4];
00043   ceq[3] = 2*helix2.mag2();
00044   // ceq[2] = 3*theDirection.dot(helix2) = 0 since they are orthogonal 
00045   ceq[2] = 0.;
00046   ceq[1] = theDirection.mag2()+2*deltaPos.dot(helix2);
00047   ceq[0] = deltaPos.dot(theDirection);
00048   //
00049   return pathLengthFromCoefficients(ceq);
00050 }
00051 
00052 //
00053 // Propagation status and path length to closest approach with line
00054 //
00055 std::pair<bool,double>
00056 HelixExtrapolatorToLine2Order::pathLength (const Line& line) const {
00057   //
00058   // Auxiliary vectors. Assumes that line.direction().mag()=1 !
00059   //
00060   PositionTypeDouble linePosition(line.position());
00061   DirectionTypeDouble lineDirection(line.direction());
00062   DirectionTypeDouble helix2(-0.5*theRho*theDirection.y(),
00063                              0.5*theRho*theDirection.x(),
00064                              0.);
00065   DirectionTypeDouble deltaPos(thePosition-linePosition);
00066   DirectionTypeDouble helix1p(theDirection-lineDirection*theDirection.dot(lineDirection));
00067   DirectionTypeDouble helix2p(helix2-lineDirection*helix2.dot(lineDirection));
00068   //
00069   // coefficients of 3rd order equation
00070   //
00071   double ceq[4];
00072   ceq[3] = 2*helix2.dot(helix2p);
00073   // ceq[2] = 3*helix1.dot(helix1p); 
00074   // since theDirection.dot(helix2)==0 equivalent to
00075   ceq[2] = 3*theDirection.dot(lineDirection)*helix2.dot(lineDirection);
00076   ceq[1] = theDirection.dot(helix1p)+2*deltaPos.dot(helix2p);
00077   ceq[0] = deltaPos.dot(helix1p);
00078   //
00079   return pathLengthFromCoefficients(ceq);
00080 }
00081 
00082 //
00083 // Propagation status and path length to intersection
00084 //
00085 std::pair<bool,double>
00086 HelixExtrapolatorToLine2Order::pathLengthFromCoefficients (const double ceq[4]) const 
00087 {
00088   //
00089   // Solution of 3rd order equation
00090   //
00091   double solutions[3];
00092   int nRaw = solve3rdOrder(ceq,solutions);
00093   //
00094   // check compatibility with propagation direction
00095   //
00096   int nDir(0);
00097   for ( int i=0; i<nRaw; i++ ) {
00098     if ( thePropDir==anyDirection ||
00099          (solutions[i]>=0&&thePropDir==alongMomentum) ||
00100          (solutions[i]<=0&&thePropDir==oppositeToMomentum) )
00101       solutions[nDir++] = solutions[i];
00102   }
00103   if ( nDir==0 )  return std::make_pair(false,0.);
00104   //
00105   // check 2nd derivative
00106   //
00107   int nMin(0);
00108   for ( int i=0; i<nDir; i++ ) {
00109     double st = solutions[i];
00110     double deri2 = (3*ceq[3]*st+2*ceq[2])*st+ceq[1];
00111     if ( deri2>0. )  solutions[nMin++] = st;
00112   }
00113   if ( nMin==0 )  return std::make_pair(false,0.);
00114   //
00115   // choose smallest path length
00116   //
00117   double dSt = solutions[0];
00118   for ( int i=1; i<nMin; i++ ) {
00119     if ( fabs(solutions[i])<fabs(dSt) )  dSt = solutions[i];
00120   }
00121 
00122   return std::make_pair(true,dSt/theSinTheta);
00123 }
00124 
00125 int
00126 HelixExtrapolatorToLine2Order::solve3rdOrder (const double ceq[], 
00127                                               double solutions[]) const
00128 {
00129   //
00130   // Real 3rd order equation? Follow numerical recipes ..
00131   //
00132   if ( fabs(ceq[3])>FLT_MIN ) {
00133     int result(0);
00134     double q = (ceq[2]*ceq[2]-3*ceq[3]*ceq[1]) / (ceq[3]*ceq[3]) / 9.;
00135     double r = (2*ceq[2]*ceq[2]*ceq[2]-9*ceq[3]*ceq[2]*ceq[1]+27*ceq[3]*ceq[3]*ceq[0]) 
00136       / (ceq[3]*ceq[3]*ceq[3]) / 54.;
00137     double q3 = q*q*q;
00138     if ( r*r<q3 ) {
00139       double phi = acos(r/sqrt(q3))/3.;
00140       double rootq = sqrt(q);
00141       for ( int i=0; i<3; i++ ) {
00142         solutions[i] = -2*rootq*cos(phi) - ceq[2]/ceq[3]/3.;
00143         phi += 2./3.*M_PI;
00144       }
00145       result = 3;
00146     }
00147     else {
00148       double a = pow(fabs(r)+sqrt(r*r-q3),1./3.);
00149       if ( r>0. ) a *= -1;
00150       double b = fabs(a)>FLT_MIN ? q/a : 0.;
00151       solutions[0] = a + b - ceq[2]/ceq[3]/3.;
00152       result = 1;
00153     }
00154     return result;
00155   }
00156   //
00157   // Second order equation
00158   //
00159   else if ( fabs(ceq[2])>FLT_MIN ) {
00160     return solve2ndOrder(ceq,solutions);
00161   }
00162   else {
00163     //
00164     // Special case: linear equation
00165     //
00166     solutions[0] = -ceq[0]/ceq[1];
00167     return 1;
00168   }
00169 }
00170 
00171 int
00172 HelixExtrapolatorToLine2Order::solve2ndOrder (const double coeff[], 
00173                                               double solutions[]) const
00174 {
00175   //
00176   double deq1 = coeff[1]*coeff[1];
00177   double deq2 = coeff[2]*coeff[0];
00178   if ( fabs(deq1)<FLT_MIN || fabs(deq2/deq1)>1.e-6 ) {
00179     //
00180     // Standard solution for quadratic equations
00181     //
00182     double deq = deq1+2*deq2;
00183     if ( deq<0. )  return 0;
00184     double ceq = -0.5*(coeff[1]+(coeff[1]>0?1:-1)*sqrt(deq));
00185     solutions[0] = -2*ceq/coeff[2];
00186     solutions[1] = coeff[0]/ceq;
00187     return 2;
00188   }
00189   else {
00190     //
00191     // Solution by expansion of sqrt(1+deq)
00192     //
00193     double ceq = coeff[1]/coeff[2];
00194     double deq = deq2/deq1;
00195     deq *= (1-deq/2);
00196     solutions[0] = -ceq*deq;
00197     solutions[1] = ceq*(2+deq);
00198     return 2;
00199   }
00200 }
00201 //
00202 // Position after a step of path length s (2nd order)
00203 //
00204 HelixLineExtrapolation::PositionType
00205 HelixExtrapolatorToLine2Order::position (double s) const {
00206   // use double precision result
00207 //   PositionTypeDouble pos = positionInDouble(s);
00208 //   return PositionType(pos.x(),pos.y(),pos.z());
00209   return PositionType(positionInDouble(s));
00210 }
00211 //
00212 // Position after a step of path length s (2nd order) (in double precision)
00213 //
00214 HelixExtrapolatorToLine2Order::PositionTypeDouble
00215 HelixExtrapolatorToLine2Order::positionInDouble (double s) const {
00216   // based on path length in the transverse plane
00217   double st = s*theSinTheta;
00218   return PositionTypeDouble(thePosition.x()+(theDirection.x()-st*0.5*theRho*theDirection.y())*st,
00219                             thePosition.y()+(theDirection.y()+st*0.5*theRho*theDirection.x())*st,
00220                             thePosition.z()+st*theDirection.z());
00221 }
00222 //
00223 // Direction after a step of path length 2 (2nd order) (in double precision)
00224 //
00225 HelixLineExtrapolation::DirectionType
00226 HelixExtrapolatorToLine2Order::direction (double s) const {
00227   // use double precision result
00228 //   DirectionTypeDouble dir = directionInDouble(s);
00229 //   return DirectionType(dir.x(),dir.y(),dir.z());
00230    return DirectionType(directionInDouble(s));
00231 }
00232 //
00233 // Direction after a step of path length 2 (2nd order)
00234 //
00235 HelixExtrapolatorToLine2Order::DirectionTypeDouble
00236 HelixExtrapolatorToLine2Order::directionInDouble (double s) const {
00237   // based on delta phi
00238   double dph = s*theRho*theSinTheta;
00239   return DirectionTypeDouble(theDirection.x()-(theDirection.y()+0.5*theDirection.x()*dph)*dph,
00240                              theDirection.y()+(theDirection.x()-0.5*theDirection.y()*dph)*dph,
00241                              theDirection.z());
00242 }