CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/RecoTracker/NuclearSeedGenerator/src/TangentCircle.cc

Go to the documentation of this file.
00001 #include "RecoTracker/NuclearSeedGenerator/interface/TangentCircle.h"
00002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00003 
00004 #define PI 3.1415926
00005 
00006 // TODO: is not valid don't do any calculations and return init values
00007 TangentCircle::TangentCircle(const GlobalVector& direction, const GlobalPoint& inner, const GlobalPoint& outer) : 
00008        theInnerPoint(inner), theOuterPoint(outer), theVertexPoint(inner) {
00009 
00010    if(theInnerPoint.perp2() > theOuterPoint.perp2()) { valid = false; }
00011    else valid=true;
00012 
00013    double x1 = inner.x();
00014    double y1 = inner.y();
00015    double x2 = outer.x();
00016    double y2 = outer.y();
00017    double alpha1 = (direction.y() != 0) ? atan(-direction.x()/direction.y()) : PI/2 ;
00018    double denominator = 2*((x1-x2)*cos(alpha1)+(y1-y2)*sin(alpha1));
00019    theRho = (denominator != 0) ? ((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))/denominator : 1E12;
00020 
00021    // TODO : variable not yet calculated look in nucl.C
00022    theX0 = 1E10;
00023    theY0 = 1E10;
00024 
00025    theDirectionAtVertex = direction;
00026    theDirectionAtVertex/=theDirectionAtVertex.mag();
00027 
00028    //theCharge = (theRho>0) ? -1 : 1;
00029 
00030    theCharge = 0;
00031    theRho = fabs(theRho);
00032 
00033    theVertexError = (theInnerPoint-theOuterPoint).mag();
00034 }
00035 
00036 TangentCircle::TangentCircle(const GlobalPoint& outerPoint, const GlobalPoint& innerPoint, const GlobalPoint& vertexPoint) : 
00037      theInnerPoint(innerPoint), theOuterPoint(outerPoint), theVertexPoint(vertexPoint) {
00038      FastCircle circle(outerPoint, innerPoint, vertexPoint);
00039      theX0 = circle.x0();
00040      theY0 = circle.y0();
00041      theRho = circle.rho();
00042      theVertexError = 0;
00043      theCharge = 0;
00044      theDirectionAtVertex = GlobalVector(1000, 1000, 1000);
00045      if(theInnerPoint.perp2() > theOuterPoint.perp2() || !circle.isValid()) { valid = false; }
00046      else valid=true;
00047 }
00048 
00049 TangentCircle::TangentCircle(const TangentCircle& primCircle, const GlobalPoint& outerPoint, const GlobalPoint& innerPoint) {
00050 
00051    if(theInnerPoint.perp2() > theOuterPoint.perp2()) { valid = false; }
00052    else valid = true;
00053 
00054    int NITER = 10; 
00055 
00056    // Initial vertex used = outerPoint of the primary circle (should be the first estimation of the nuclear interaction position)
00057    GlobalPoint InitialVertex( primCircle.outerPoint().x() , primCircle.outerPoint().y(), 0);
00058    GlobalPoint SecInnerPoint( innerPoint.x(), innerPoint.y(), 0);
00059    GlobalPoint SecOuterPoint( outerPoint.x(), outerPoint.y(), 0);
00060 
00061    // distance between the initial vertex and the inner point of the secondary circle
00062    double s = (SecInnerPoint - InitialVertex).mag();
00063    double deltaTheta = s/primCircle.rho();
00064 
00065    double minTangentCondition = 1E12;
00066    TangentCircle theCorrectSecCircle;
00067    GlobalPoint vertex = InitialVertex;
00068    int dir = 1;
00069    double theta = deltaTheta/(NITER-1);
00070 
00071    for(int i=0; i<NITER; i++) { 
00072    
00073      // get the circle which pass through outerPoint, innerPoint and the vertex
00074      TangentCircle secCircle( SecOuterPoint, SecInnerPoint, vertex );
00075 
00076      // get a value relative to the tangentness of the 2 circles
00077      double minCond = isTangent(primCircle, secCircle);
00078 
00079      // double dirDiff = (primCircle.direction(vertex) - secCircle.direction(vertex)).mag();
00080      // if( dirDiff > 1) dirDiff = 2-dirDiff;
00081 
00082      if(minCond < minTangentCondition) { 
00083                 minTangentCondition = minCond;
00084                 theCorrectSecCircle = secCircle;
00085                 vertex = getPosition( primCircle, secCircle.vertexPoint(), theta, dir );
00086                 if( i==0 && ((vertex-SecInnerPoint).mag() > (InitialVertex-SecInnerPoint).mag()) ) {
00087                        dir=-1;
00088                        vertex = getPosition( primCircle, InitialVertex, theta, dir );
00089                        LogDebug("NuclearSeedGenerator") << "Change direction to look for vertex" << "\n";
00090                  }
00091      }
00092      else break;
00093    
00094    }
00095    theInnerPoint = theCorrectSecCircle.innerPoint();
00096    theOuterPoint = theCorrectSecCircle.outerPoint();
00097    theVertexPoint = theCorrectSecCircle.vertexPoint();
00098    theX0 = theCorrectSecCircle.x0();
00099    theY0 = theCorrectSecCircle.y0();
00100    theRho = theCorrectSecCircle.rho();  
00101    theCharge = 0;
00102    theDirectionAtVertex = GlobalVector(1000, 1000, 1000);
00103 
00104    theVertexError = s/NITER;
00105 }
00106 
00107 double TangentCircle::isTangent(const TangentCircle& primCircle, const TangentCircle& secCircle) const {
00108    // return a value that should be equal to 0 if primCircle and secCircle are tangent
00109 
00110    double distanceBetweenCircle = (primCircle.x0() - secCircle.x0())*(primCircle.x0() - secCircle.x0())
00111            + (primCircle.y0() - secCircle.y0())*(primCircle.y0() - secCircle.y0());
00112    double RadiusSum = (primCircle.rho() + secCircle.rho())*(primCircle.rho() + secCircle.rho());
00113    double RadiusDifference = (primCircle.rho() - secCircle.rho())*(primCircle.rho() - secCircle.rho());
00114 
00115    return std::min( fabs(RadiusSum-distanceBetweenCircle), fabs(RadiusDifference-distanceBetweenCircle) ); 
00116 }
00117 
00118 GlobalVector TangentCircle::direction(const GlobalPoint& point) const {
00119 
00120      if(theY0 > 1E9 || theX0 > 1E9) {
00121         LogDebug("NuclearSeedGenerator") << "Center of TangentCircle not calculated but used !!!" << "\n";
00122      }
00123 
00124      // calculate the direction perpendicular to the vector v = point - center_of_circle
00125      GlobalVector dir(point.y() - theY0, theX0 - point.x(), 0);
00126 
00127      dir/=dir.mag();
00128 
00129      // Check the sign :
00130      GlobalVector fastDir = theOuterPoint - theInnerPoint;
00131      double diff = (dir - fastDir).mag();
00132      double sum = (dir + fastDir).mag();
00133 
00134      if( sum < diff ) dir = (-1)*dir;
00135 
00136      return dir;
00137 }
00138 
00139 GlobalVector TangentCircle::directionAtVertex()  {
00140       if(theDirectionAtVertex.x() > 999) 
00141                 theDirectionAtVertex = direction(theVertexPoint);
00142       return theDirectionAtVertex;
00143 }
00144 
00145 GlobalPoint TangentCircle::getPosition(const TangentCircle& circle, const GlobalPoint& initalPosition, double theta, int dir) const {
00146              
00147             int sign[3];
00148             double x2 = initalPosition.x();
00149             double y2 = initalPosition.y();
00150 
00151             if( (x2>circle.x0()) && dir >0) { sign[0] = 1;  sign[1] = -1; sign[2] = -1; }
00152             if( (x2>circle.x0()) && dir <0) { sign[0] = 1;  sign[1] = 1; sign[2] = 1; }
00153             if( (x2<circle.x0()) && dir >0) { sign[0] = -1;  sign[1] = 1; sign[2] = -1; }
00154             if( (x2<circle.x0()) && dir <0) { sign[0] = -1;  sign[1] = -1; sign[2] = 1; }
00155 
00156             double l = 2*circle.rho()*sin(theta/2);
00157             double alpha = atan((y2-circle.y0())/(x2-circle.x0()));
00158             double beta = PI/2-theta/2;
00159             double gamma = PI + sign[2]* alpha - beta;
00160 
00161             double xnew = x2 + sign[0]*l*cos(gamma);
00162             double ynew = y2 + sign[1]*l*sin(gamma);
00163 
00164             return GlobalPoint( xnew, ynew, 0 );
00165 }
00166 
00167 double TangentCircle::curvatureError() {
00168    if( (theInnerPoint - theVertexPoint).mag() < theVertexError ) {
00169         TangentCircle circle1( directionAtVertex() , theVertexPoint - theVertexError*directionAtVertex(), theOuterPoint);
00170         TangentCircle circle2( directionAtVertex() , theVertexPoint + theVertexError*directionAtVertex(), theOuterPoint);
00171         return fabs(1/circle1.rho() - 1/circle2.rho());
00172    }
00173    else {
00174        TangentCircle circle1( theOuterPoint, theInnerPoint, theVertexPoint - theVertexError*directionAtVertex());
00175        TangentCircle circle2( theOuterPoint, theInnerPoint, theVertexPoint + theVertexError*directionAtVertex());
00176        return fabs(1/circle1.rho() - 1/circle2.rho());
00177    }
00178 }
00179 
00180 int TangentCircle::charge(float magz) {
00181 
00182    if(theCharge != 0) return theCharge;
00183 
00184    if(theX0 > 1E9 || theY0 > 1E9) theCharge = chargeLocally(magz, directionAtVertex());
00185    else {
00186        GlobalPoint  center(theX0, theY0, 0);
00187        GlobalVector u = center - theVertexPoint;
00188        GlobalVector v = directionAtVertex();
00189 
00190        // F = force vector
00191        GlobalVector F( v.y() * magz, -v.x() * magz, 0);
00192        if( u.x() * F.x() + u.y() * F.y() > 0) theCharge=-1;
00193        else theCharge=1;
00194 
00195        if(theCharge != chargeLocally(magz, v)) {
00196           LogDebug("NuclearSeedGenerator") << "Inconsistency in calculation of the charge" << "\n";
00197      }
00198 
00199    }
00200    return theCharge;
00201 }
00202 
00203 int TangentCircle::chargeLocally(float magz, GlobalVector v) const {
00204     GlobalVector  u = theOuterPoint - theVertexPoint;
00205     double tz = v.x() * u.y() - v.y() * u.x() ;
00206 
00207     if(tz * magz > 0) return 1; else return -1;
00208 }