00001 #include "TrackingTools/GeomPropagators/interface/PropagationDirectionChooser.h"
00002 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00003 #include "TrackingTools/GeomPropagators/interface/PropagationExceptions.h"
00004
00005 #include "DataFormats/GeometrySurface/interface/Surface.h"
00006 #include "DataFormats/GeometrySurface/interface/Cylinder.h"
00007 #include "DataFormats/GeometrySurface/interface/Plane.h"
00008
00009 #include "MagneticField/Engine/interface/MagneticField.h"
00010
00011 #include <cmath>
00012
00013 PropagationDirection
00014 PropagationDirectionChooser::operator() (const FreeTrajectoryState& fts,
00015 const Surface& surface) const
00016 {
00017
00018
00019
00020 Surface* sur = (Surface*)&surface;
00021 const Cylinder* bc = dynamic_cast<Cylinder*>(sur);
00022 const Plane* bp = dynamic_cast<Plane*>(sur);
00023 if (bc != 0) {
00024
00025
00026
00027 return (*this)(fts, *bc);
00028 }
00029 else if (bp != 0) {
00030
00031
00032
00033 return (*this)(fts, *bp);
00034 }
00035 else {
00036 throw PropagationException("The surface is neither Cylinder nor Plane");
00037 }
00038 }
00039
00040 PropagationDirection
00041 PropagationDirectionChooser::operator() (const FreeTrajectoryState& fts,
00042 const Plane& plane) const
00043 {
00044
00045
00046
00047
00048 PropagationDirection dir = anyDirection;
00049
00050 GlobalPoint x = fts.position();
00051 GlobalVector p = fts.momentum().unit();
00052 GlobalPoint sp = plane.toGlobal(LocalPoint(0.,0.));
00053 GlobalVector v = plane.toGlobal(LocalVector(1.,0.,0.));
00054 GlobalVector w = plane.toGlobal(LocalVector(0.,1.,0.));
00055 AlgebraicMatrix33 a;
00056 a(0,0) = v.x(); a(0,1) = w.x(); a(0,2) = -p.x();
00057 a(1,0) = v.y(); a(1,1) = w.y(); a(1,2) = -p.y();
00058 a(2,0) = v.z(); a(2,1) = w.z(); a(2,2) = -p.z();
00059 AlgebraicVector3 b;
00060 b[0] = x.x() - sp.x();
00061 b[1] = x.y() - sp.y();
00062 b[2] = x.z() - sp.z();
00063
00064 int ifail = !a.Invert();
00065 if (ifail == 0) {
00066
00067 b = a*b;
00068
00069
00070 const double small = 1.e-4;
00071 if (fabs(b[2]) < small) {
00072
00073 dir = alongMomentum;
00074 }
00075 else if (b[2] < 0.) {
00076 dir = oppositeToMomentum;
00077 }
00078 else {
00079 dir = alongMomentum;
00080 }
00081 }
00082 return dir;
00083 }
00084
00085
00086 PropagationDirection
00087 PropagationDirectionChooser::operator() (const FreeTrajectoryState& fts,
00088 const Cylinder& cylinder) const
00089 {
00090
00091
00092 PropagationDirection dir = anyDirection;
00093
00094 GlobalPoint sp = cylinder.toGlobal(LocalPoint(0.,0.));
00095 if (sp.x() != 0. || sp.y() != 0.) {
00096 throw PropagationException("Cannot propagate to an arbitrary cylinder");
00097 }
00098
00099 GlobalPoint x = fts.position();
00100 GlobalVector p = fts.momentum();
00101
00102 const double small = 1.e-4;
00103 double rdiff = x.perp() - cylinder.radius();
00104
00105 if ( fabs(rdiff) < small ) {
00106
00107 dir = alongMomentum;
00108 }
00109 else {
00110 int rSign = ( rdiff >= 0. ) ? 1 : -1 ;
00111 if ( rSign == -1 ) {
00112
00113
00114 dir = alongMomentum;
00115 }
00116 else {
00117
00118
00119 double proj = (x.x()*p.x() + x.y()*p.y()) * rSign;
00120 if (proj < 0.) {
00121 dir = alongMomentum;
00122 }
00123 else {
00124 dir = oppositeToMomentum;
00125 }
00126 }
00127 }
00128 return dir;
00129 }