00001 #include "RecoTracker/NuclearSeedGenerator/interface/TangentCircle.h"
00002 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00003
00004 #define PI 3.1415926
00005
00006
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
00022 theX0 = 1E10;
00023 theY0 = 1E10;
00024
00025 theDirectionAtVertex = direction;
00026 theDirectionAtVertex/=theDirectionAtVertex.mag();
00027
00028
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
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
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
00074 TangentCircle secCircle( SecOuterPoint, SecInnerPoint, vertex );
00075
00076
00077 double minCond = isTangent(primCircle, secCircle);
00078
00079
00080
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
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
00125 GlobalVector dir(point.y() - theY0, theX0 - point.x(), 0);
00126
00127 dir/=dir.mag();
00128
00129
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
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 }