Go to the documentation of this file.00001 #include "TrackingTools/GeomPropagators/interface/HelixBarrelPlaneCrossingByCircle.h"
00002 #include "TrackingTools/GeomPropagators/src/RealQuadEquation.h"
00003 #include "TrackingTools/GeomPropagators/interface/StraightLinePlaneCrossing.h"
00004 #include "DataFormats/GeometrySurface/interface/Plane.h"
00005 #include "DataFormats/Math/interface/SSEVec.h"
00006
00007 #include <algorithm>
00008 #include <cfloat>
00009
00010 HelixBarrelPlaneCrossingByCircle::
00011 HelixBarrelPlaneCrossingByCircle( const PositionType& pos,
00012 const DirectionType& dir,
00013 double rho, PropagationDirection propDir) :
00014 theStartingPos( pos), theStartingDir(dir),
00015 theRho(rho), thePropDir(propDir) { init();}
00016
00017 HelixBarrelPlaneCrossingByCircle::
00018 HelixBarrelPlaneCrossingByCircle( const GlobalPoint& pos,
00019 const GlobalVector& dir,
00020 double rho, PropagationDirection propDir) :
00021 theStartingPos( pos.basicVector()), theStartingDir(dir.basicVector()),
00022 theRho(rho), thePropDir(propDir) { init();}
00023
00024 void HelixBarrelPlaneCrossingByCircle::init()
00025 {
00026 double pabsI = 1./theStartingDir.mag();
00027 double pt = theStartingDir.perp();
00028 theCosTheta = theStartingDir.z()*pabsI;
00029 theSinTheta = pt*pabsI;
00030
00031
00032 const double sraightLineCutoff = 1.e-7;
00033 if (fabs(theRho) < sraightLineCutoff &&
00034 fabs(theRho)*theStartingPos.perp() < sraightLineCutoff) {
00035 useStraightLine = true;
00036 }else{
00037
00038
00039
00040 double o = 1./(pt*theRho);
00041 theXCenter = theStartingPos.x() - theStartingDir.y()*o;
00042 theYCenter = theStartingPos.y() + theStartingDir.x()*o;
00043 useStraightLine = false;
00044 }
00045 }
00046
00047 std::pair<bool,double>
00048 HelixBarrelPlaneCrossingByCircle::pathLength( const Plane& plane)
00049 {
00050 typedef std::pair<bool,double> ResultType;
00051
00052 if(useStraightLine){
00053
00054 StraightLinePlaneCrossing slc( theStartingPos,
00055 theStartingDir, thePropDir);
00056 return slc.pathLength( plane);
00057 }
00058
00059
00060
00061 GlobalVector n = plane.normalVector();
00062 double distToPlane = -plane.localZ( GlobalPoint( theStartingPos));
00063
00064
00065 double nx = n.x();
00066 double ny = n.y();
00067 double distCx = theStartingPos.x() - theXCenter;
00068 double distCy = theStartingPos.y() - theYCenter;
00069
00070 double nfac, dfac;
00071 double A, B, C;
00072 bool solveForX;
00073 if (fabs(nx) > fabs(ny)) {
00074 solveForX = false;
00075 nfac = ny/nx;
00076 dfac = distToPlane/nx;
00077 B = distCy - nfac*distCx;
00078 C = (2.*distCx + dfac)*dfac;
00079 }
00080 else {
00081 solveForX = true;
00082 nfac = nx/ny;
00083 dfac = distToPlane/ny;
00084 B = distCx - nfac*distCy;
00085 C = (2.*distCy + dfac)*dfac;
00086 }
00087 B -= nfac*dfac; B *= 2;
00088 A = 1.+ nfac*nfac;
00089
00090 double dx1, dx2, dy1, dy2;
00091 RealQuadEquation equation(A,B,C);
00092 if (!equation.hasSolution) return ResultType( false, 0.);
00093 else {
00094 if (solveForX) {
00095 dx1 = equation.first;
00096 dx2 = equation.second;
00097 dy1 = dfac - nfac*dx1;
00098 dy2 = dfac - nfac*dx2;
00099 }
00100 else {
00101 dy1 = equation.first;
00102 dy2 = equation.second;
00103 dx1 = dfac - nfac*dy1;
00104 dx2 = dfac - nfac*dy2;
00105 }
00106 }
00107 bool solved = chooseSolution( Vector2D(dx1, dy1), Vector2D(dx2, dy2));
00108 if (solved) {
00109 theDmag = theD.mag();
00110
00111 double sinAlpha = 0.5*theDmag*theRho;
00112 if ( sinAlpha>(1.-10*DBL_EPSILON) ) sinAlpha = 1.-10*DBL_EPSILON;
00113 else if ( sinAlpha<-(1.-10*DBL_EPSILON) ) sinAlpha = -(1.-10*DBL_EPSILON);
00114 theS = theActualDir*2./(theRho*theSinTheta) * asin( sinAlpha);
00115 return ResultType( true, theS);
00116 }
00117 else return ResultType( false, 0.);
00118 }
00119
00120 bool
00121 HelixBarrelPlaneCrossingByCircle::chooseSolution( const Vector2D& d1,
00122 const Vector2D& d2)
00123 {
00124 bool solved;
00125 double momProj1 = theStartingDir.x()*d1.x() + theStartingDir.y()*d1.y();
00126 double momProj2 = theStartingDir.x()*d2.x() + theStartingDir.y()*d2.y();
00127
00128 if ( thePropDir == anyDirection ) {
00129 solved = true;
00130 if (d1.mag2()<d2.mag2()) {
00131 theD = d1;
00132 theActualDir = (momProj1 > 0) ? 1. : -1.;
00133 }
00134 else {
00135 theD = d2;
00136 theActualDir = (momProj2 > 0) ? 1. : -1.;
00137 }
00138
00139 }
00140 else {
00141 double propSign = thePropDir==alongMomentum ? 1 : -1;
00142 if (!mathSSE::samesign(momProj1,momProj2)) {
00143
00144 solved = true;
00145 theD = mathSSE::samesign(momProj1,propSign) ? d1 : d2;
00146 theActualDir = propSign;
00147 }
00148 else if (mathSSE::samesign(momProj1,propSign)) {
00149
00150 solved = true;
00151 theD = (d1.mag2()<d2.mag2()) ? d1 : d2;
00152 theActualDir = propSign;
00153 }
00154 else solved = false;
00155 }
00156 return solved;
00157 }
00158
00159 HelixPlaneCrossing::PositionType
00160 HelixBarrelPlaneCrossingByCircle::position( double s) const
00161 {
00162 if(useStraightLine){
00163 return PositionType(theStartingPos+s*theStartingDir.unit());
00164 }else{
00165 if ( s==theS) {
00166 return PositionType( theStartingPos.x() + theD.x(),
00167 theStartingPos.y() + theD.y(),
00168 theStartingPos.z() + s*theCosTheta);
00169 }
00170 else {
00171 double phi = s*theSinTheta*theRho;
00172 double x1Shift = theStartingPos.x() - theXCenter;
00173 double y1Shift = theStartingPos.y() - theYCenter;
00174
00175 return PositionType(x1Shift*cos(phi)-y1Shift*sin(phi) + theXCenter,
00176 x1Shift*sin(phi)+y1Shift*cos(phi) + theYCenter,
00177 theStartingPos.z() + s*theCosTheta);
00178 }
00179 }
00180 }
00181
00182 HelixPlaneCrossing::DirectionType
00183 HelixBarrelPlaneCrossingByCircle::direction( double s) const
00184 {
00185 if(useStraightLine){return theStartingDir;}
00186 else{
00187 double sinPhi, cosPhi;
00188 if ( s==theS) {
00189 double tmp = 0.5*theDmag*theRho;
00190 if (s < 0) tmp = -tmp;
00191
00192 sinPhi = 1.-(tmp*tmp);
00193 if ( sinPhi<0 ) sinPhi = 0.;
00194 sinPhi = 2.*tmp*sqrt(sinPhi);
00195 cosPhi = 1.-2.*(tmp*tmp);
00196 }
00197 else {
00198 double phi = s*theSinTheta*theRho;
00199 sinPhi = sin(phi);
00200 cosPhi = cos(phi);
00201 }
00202 return DirectionType(theStartingDir.x()*cosPhi-theStartingDir.y()*sinPhi,
00203 theStartingDir.x()*sinPhi+theStartingDir.y()*cosPhi,
00204 theStartingDir.z());
00205 }
00206 }