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
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
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
00041
00042 double ceq[4];
00043 ceq[3] = 2*helix2.mag2();
00044
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
00054
00055 std::pair<bool,double>
00056 HelixExtrapolatorToLine2Order::pathLength (const Line& line) const {
00057
00058
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
00070
00071 double ceq[4];
00072 ceq[3] = 2*helix2.dot(helix2p);
00073
00074
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
00084
00085 std::pair<bool,double>
00086 HelixExtrapolatorToLine2Order::pathLengthFromCoefficients (const double ceq[4]) const
00087 {
00088
00089
00090
00091 double solutions[3];
00092 int nRaw = solve3rdOrder(ceq,solutions);
00093
00094
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
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
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
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
00158
00159 else if ( fabs(ceq[2])>FLT_MIN ) {
00160 return solve2ndOrder(ceq,solutions);
00161 }
00162 else {
00163
00164
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
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
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
00203
00204 HelixLineExtrapolation::PositionType
00205 HelixExtrapolatorToLine2Order::position (double s) const {
00206
00207
00208
00209 return PositionType(positionInDouble(s));
00210 }
00211
00212
00213
00214 HelixExtrapolatorToLine2Order::PositionTypeDouble
00215 HelixExtrapolatorToLine2Order::positionInDouble (double s) const {
00216
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
00224
00225 HelixLineExtrapolation::DirectionType
00226 HelixExtrapolatorToLine2Order::direction (double s) const {
00227
00228
00229
00230 return DirectionType(directionInDouble(s));
00231 }
00232
00233
00234
00235 HelixExtrapolatorToLine2Order::DirectionTypeDouble
00236 HelixExtrapolatorToLine2Order::directionInDouble (double s) const {
00237
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 }