00001 #include "TrackingTools/GeomPropagators/interface/HelixArbitraryPlaneCrossing.h"
00002 #include "DataFormats/GeometrySurface/interface/Plane.h"
00003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00004
00005 #include <cmath>
00006 #include <iostream>
00007
00008 HelixArbitraryPlaneCrossing::HelixArbitraryPlaneCrossing(const PositionType& point,
00009 const DirectionType& direction,
00010 const float curvature,
00011 const PropagationDirection propDir) :
00012 theQuadraticCrossingFromStart(point,direction,curvature,propDir),
00013 theX0(point.x()),
00014 theY0(point.y()),
00015 theZ0(point.z()),
00016 theRho(curvature),
00017 thePropDir(propDir),
00018 theCachedS(0),
00019 theCachedDPhi(0.),
00020 theCachedSDPhi(0.),
00021 theCachedCDPhi(1.)
00022 {
00023
00024
00025
00026 double px = direction.x();
00027 double py = direction.y();
00028 double pz = direction.z();
00029 double pt2 = px*px+py*py;
00030 double p2 = pt2+pz*pz;
00031 double pI = 1./sqrt(p2);
00032 double ptI = 1./sqrt(pt2);
00033 theCosPhi0 = px*ptI;
00034 theSinPhi0 = py*ptI;
00035 theCosTheta = pz*pI;
00036 theSinTheta = pt2*ptI*pI;
00037 }
00038
00039
00040
00041 std::pair<bool,double>
00042 HelixArbitraryPlaneCrossing::pathLength(const Plane& plane) {
00043
00044
00045
00046 const int maxIterations(100);
00047
00048
00049
00050 float maxNumDz = theNumericalPrecision*plane.position().mag();
00051 float safeMaxDist = (theMaxDistToPlane>maxNumDz?theMaxDistToPlane:maxNumDz);
00052
00053
00054
00055 PropagationDirection propDir = thePropDir;
00056 PositionTypeDouble xnew(theX0,theY0,theZ0);
00057 DirectionTypeDouble pnew(theCosPhi0,theSinPhi0,theCosTheta/theSinTheta);
00058
00059
00060
00061 int iteration(maxIterations);
00062 double dSTotal(0.);
00063
00064 bool first = true;
00065 while ( notAtSurface(plane,xnew,safeMaxDist) ) {
00066
00067
00068
00069 if ( --iteration<0 ) {
00070 edm::LogInfo("HelixArbitraryPlaneCrossing") << "pathLength : no convergence";
00071 return std::pair<bool,double>(false,0);
00072 }
00073
00074
00075
00076
00077
00078 std::pair<bool,double> deltaS2;
00079 if ( first ) {
00080 first = false;
00081 deltaS2 = theQuadraticCrossingFromStart.pathLength(plane);
00082 }
00083 else {
00084 HelixArbitraryPlaneCrossing2Order quadraticCrossing(xnew.x(),xnew.y(),xnew.z(),
00085 pnew.x(),pnew.y(),
00086 theCosTheta,theSinTheta,
00087 theRho,
00088 anyDirection);
00089
00090 deltaS2 = quadraticCrossing.pathLength(plane);
00091 }
00092
00093 if ( !deltaS2.first ) return deltaS2;
00094
00095
00096
00097 dSTotal += deltaS2.second;
00098 PropagationDirection newDir = dSTotal>=0 ? alongMomentum : oppositeToMomentum;
00099 if ( propDir == anyDirection ) {
00100 propDir = newDir;
00101 }
00102 else {
00103 if ( newDir!=propDir ) return std::pair<bool,double>(false,0);
00104 }
00105
00106
00107
00108 xnew = positionInDouble(dSTotal);
00109 pnew = directionInDouble(dSTotal);
00110 }
00111
00112
00113
00114 return std::pair<bool,double>(true,dSTotal);
00115 }
00116
00117
00118
00119 HelixPlaneCrossing::PositionType
00120 HelixArbitraryPlaneCrossing::position (double s) const {
00121
00122 PositionTypeDouble pos = positionInDouble(s);
00123 return PositionType(pos.x(),pos.y(),pos.z());
00124 }
00125
00126
00127
00128 HelixArbitraryPlaneCrossing::PositionTypeDouble
00129 HelixArbitraryPlaneCrossing::positionInDouble (double s) const {
00130
00131
00132
00133 if ( s!=theCachedS ) {
00134 theCachedS = s;
00135 theCachedDPhi = theCachedS*theRho*theSinTheta;
00136 theCachedSDPhi = sin(theCachedDPhi);
00137 theCachedCDPhi = cos(theCachedDPhi);
00138 }
00139
00140
00141
00142
00143
00144 if ( std::abs(theCachedDPhi)>1.e-4 ) {
00145
00146 double o = 1./theRho;
00147 return PositionTypeDouble(theX0+(-theSinPhi0*(1.-theCachedCDPhi)+theCosPhi0*theCachedSDPhi)*o,
00148 theY0+( theCosPhi0*(1.-theCachedCDPhi)+theSinPhi0*theCachedSDPhi)*o,
00149 theZ0+theCachedS*theCosTheta);
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159 else {
00160
00161 return theQuadraticCrossingFromStart.positionInDouble(theCachedS);
00162 }
00163 }
00164
00165
00166
00167 HelixPlaneCrossing::DirectionType
00168 HelixArbitraryPlaneCrossing::direction (double s) const {
00169
00170 DirectionTypeDouble dir = directionInDouble(s);
00171 return DirectionType(dir.x(),dir.y(),dir.z());
00172 }
00173
00174
00175
00176 HelixArbitraryPlaneCrossing::DirectionTypeDouble
00177 HelixArbitraryPlaneCrossing::directionInDouble (double s) const {
00178
00179
00180
00181 if ( s!=theCachedS ) {
00182 theCachedS = s;
00183 theCachedDPhi = theCachedS*theRho*theSinTheta;
00184 theCachedSDPhi = sin(theCachedDPhi);
00185 theCachedCDPhi = cos(theCachedDPhi);
00186 }
00187
00188 if ( std::abs(theCachedDPhi)>1.e-4 ) {
00189
00190 return DirectionTypeDouble(theCosPhi0*theCachedCDPhi-theSinPhi0*theCachedSDPhi,
00191 theSinPhi0*theCachedCDPhi+theCosPhi0*theCachedSDPhi,
00192 theCosTheta/theSinTheta);
00193 }
00194 else {
00195
00196 return theQuadraticCrossingFromStart.directionInDouble(theCachedS);
00197 }
00198 }
00199
00200
00201 bool HelixArbitraryPlaneCrossing::notAtSurface (const Plane& plane,
00202 const PositionTypeDouble& point,
00203 const float maxDist) const {
00204 float dz = plane.localZ(Surface::GlobalPoint(point.x(),point.y(),point.z()));
00205 return std::abs(dz)>maxDist;
00206 }
00207
00208 const float HelixArbitraryPlaneCrossing::theNumericalPrecision = 5.e-7f;
00209 const float HelixArbitraryPlaneCrossing::theMaxDistToPlane = 1.e-4f;