Go to the documentation of this file.00001 #include <cmath>
00002 #include "DataFormats/GeometryVector/interface/GlobalVector.h"
00003 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
00004
00005 #include "RecoTracker/TkMSParametrization/interface/PixelRecoUtilities.h"
00006 #include "RecoTracker/TkMSParametrization/interface/PixelRecoRange.h"
00007
00008 #include "RecoPixelVertexing/PixelTriplets/interface/ThirdHitPredictionFromCircle.h"
00009
00010
00011
00012
00013 #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__)
00014 # define likely(expr) (__builtin_expect(!!(expr), 1))
00015 # define unlikely(expr) (__builtin_expect(!!(expr), 0))
00016 #else
00017 # define likely(expr) (expr)
00018 # define unlikely(expr) (expr)
00019 #endif
00020
00021 typedef Basic3DVector<double> Point3D;
00022 typedef Basic2DVector<double> Point2D;
00023
00024 namespace {
00025 template<class T> static inline T sqr(T t) { return t * t; }
00026 template<class T> static inline T sgn(T t) { return std::signbit(t) ? -1. : 1.; }
00027 template<class T> static inline T clamped_acos(T t)
00028 { return unlikely(t <= -1) ? M_PI : unlikely(t >= 1) ? T(0) : std::acos(t); }
00029 template<class T> static inline T clamped_sqrt(T t)
00030 { return likely(t > 0) ? std::sqrt(t) : T(0); }
00031 }
00032
00033 ThirdHitPredictionFromCircle::ThirdHitPredictionFromCircle(
00034 const GlobalPoint& P1, const GlobalPoint& P2, float tolerance)
00035 : p1(P1.x(), P1.y()), theTolerance(tolerance)
00036 {
00037 Point2D p2(P2.x(), P2.y());
00038 Point2D diff = 0.5 * (p2 - p1);
00039 delta2 = diff.mag2();
00040 delta = std::sqrt(delta2);
00041 axis = Point2D(-diff.y(), diff.x()) / delta;
00042 center = p1 + diff;
00043 }
00044
00045 double ThirdHitPredictionFromCircle::phi(double curvature, double radius) const
00046 {
00047 double phi;
00048 if (unlikely(std::abs(curvature) < 1.0e-5)) {
00049 double cos = (center * axis) / radius;
00050 phi = axis.phi() - clamped_acos(cos);
00051 } else {
00052 double sign = sgn(curvature);
00053 double radius2 = sqr(1.0 / curvature);
00054 double orthog = clamped_sqrt(radius2 - delta2);
00055 Basic2DVector<double> lcenter = center - sign * orthog * axis;
00056 double rc2 = lcenter.mag2();
00057 double cos = (rc2 + sqr(radius) - radius2) /
00058 (2. *std:: sqrt(rc2) * radius);
00059 phi = lcenter.phi() + sign * clamped_acos(cos);
00060 }
00061
00062 while(unlikely(phi >= M_PI)) phi -= 2. * M_PI;
00063 while(unlikely(phi < -M_PI)) phi += 2. * M_PI;
00064
00065 return phi;
00066 }
00067
00068 double ThirdHitPredictionFromCircle::angle(double curvature, double radius) const
00069 {
00070 if (unlikely(std::abs(curvature) < 1.0e-5)) {
00071 double sin = (center * axis) / radius;
00072 return sin / clamped_sqrt(1 - sqr(sin));
00073 } else {
00074 double radius2 = sqr(1.0 / curvature);
00075 double orthog = clamped_sqrt(radius2 - delta2);
00076 Basic2DVector<double> lcenter = center - sgn(curvature) * orthog * axis;
00077
00078 double cos = (radius2 + sqr(radius) - lcenter.mag2()) *
00079 curvature / (2. * radius);
00080 return - cos / clamped_sqrt(1 - sqr(cos));
00081 }
00082 }
00083
00084 ThirdHitPredictionFromCircle::Range
00085 ThirdHitPredictionFromCircle::operator()(Range curvature, double radius) const
00086 {
00087 double phi1 = phi(curvature.second, radius);
00088 double phi2 = phi(curvature.first, radius);
00089
00090 while(unlikely(phi2 < phi1)) phi2 += 2. * M_PI;
00091
00092 return Range(phi1 * radius - theTolerance, phi2 * radius + theTolerance);
00093 }
00094
00095 ThirdHitPredictionFromCircle::Range
00096 ThirdHitPredictionFromCircle::curvature(double transverseIP) const
00097 {
00098
00099
00100 transverseIP = std::abs(transverseIP);
00101 double transverseIP2 = sqr(transverseIP);
00102 double tip = axis * center;
00103 double tip2 = sqr(tip);
00104 double lip = axis.x() * center.y() - axis.y() * center.x();
00105 double lip2 = sqr(lip);
00106
00107 double origin = std::sqrt(tip2 + lip2);
00108 double tmp1 = lip2 + tip2 - transverseIP2;
00109 double tmp2 = 2. * (tip - transverseIP) * (tip + transverseIP);
00110 double tmp3 = 2. * delta * origin;
00111 double tmp4 = tmp1 + delta2;
00112 double tmp5 = 2. * delta * lip;
00113
00114
00115
00116
00117 double u1, u2;
00118 if (unlikely(tmp4 - tmp5 < 1.0e-5)) {
00119 u1 = -0.;
00120 u2 = +0.;
00121 } else {
00122 if (unlikely(std::abs(tmp2) < 1.0e-5)) {
00123
00124
00125
00126 double tmp = lip2 - delta2;
00127 u1 = INFINITY;
00128 u2 = (sqr(0.5 * tmp) - delta2 * tip2) / (tmp * tip);
00129 if (tip < 0)
00130 std::swap(u1, u2);
00131 } else {
00132 double tmp6 = (tmp4 - tmp5) * (tmp4 + tmp5);
00133 if (unlikely(tmp6 < 1.0e-5)) {
00134 u1 = -0.;
00135 u2 = +0.;
00136 } else {
00137 double tmp7 = tmp6 > 0 ? (transverseIP * std::sqrt(tmp6) / tmp2) : 0.;
00138 double tmp8 = tip * (tmp1 - delta2) / tmp2;
00139
00140 u1 = tmp8 + tmp7;
00141 u2 = tmp8 - tmp7;
00142 }
00143 }
00144
00145 if (tmp4 <= std::abs(tmp3)) {
00146 if ((tmp3 < 0) == (tip < 0))
00147 u2 = +0.;
00148 else
00149 u1 = -0.;
00150 }
00151 }
00152
00153 return Range(sgn(u1) / std::sqrt(sqr(u1) + delta2),
00154 sgn(u2) / std::sqrt(sqr(u2) + delta2));
00155 }
00156
00157 double ThirdHitPredictionFromCircle::invCenterOnAxis(const Point2D &p2) const
00158 {
00159 Point2D delta = p2 - p1;
00160 Point2D axis2 = Point2D(-delta.y(), delta.x()) / delta.mag();
00161 Point2D diff = p1 + 0.5 * delta - center;
00162 double a = diff.y() * axis2.x() - diff.x() * axis2.y();
00163 double b = axis.y() * axis2.x() - axis.x() * axis2.y();
00164 return b / a;
00165 }
00166
00167 double ThirdHitPredictionFromCircle::curvature(const Point2D &p2) const
00168 {
00169 double invDist = invCenterOnAxis(p2);
00170 double invDist2 = sqr(invDist);
00171 double curv = std::sqrt(invDist2 / (1. + invDist2 * delta2));
00172 return sgn(invDist) * curv;
00173 }
00174
00175 double ThirdHitPredictionFromCircle::transverseIP(const Point2D &p2) const
00176 {
00177 double invDist = invCenterOnAxis(p2);
00178 if (unlikely(std::abs(invDist) < 1.0e-5))
00179 return std::abs(p2 * axis);
00180 else {
00181 double dist = 1.0 / invDist;
00182 double radius = std::sqrt(sqr(dist) + delta2);
00183 return std::abs((center + axis * dist).mag() - radius);
00184 }
00185 }
00186
00187 ThirdHitPredictionFromCircle::HelixRZ::HelixRZ(
00188 const ThirdHitPredictionFromCircle *circle, double z1, double z2, double curv) :
00189 circle(circle), curvature(curv), z1(z1)
00190 {
00191 double absCurv = std::abs(curv);
00192 seg = circle->delta;
00193
00194 if (likely(absCurv > 1.0e-5)) {
00195 seg *= absCurv;
00196 seg = seg < -1.0 ? -M_PI_2 : seg > 1.0 ? M_PI_2 : std::asin(seg);
00197 seg /= absCurv;
00198 }
00199
00200 seg *= 2.;
00201 dzdu = likely(std::abs(seg) > 1.0e-5) ? ((z2 - z1) / seg) : 99999.0;
00202 }
00203
00204 double ThirdHitPredictionFromCircle::HelixRZ::maxCurvature(
00205 const ThirdHitPredictionFromCircle *circle, double z1, double z2, double z3)
00206 {
00207 static const double maxAngle = M_PI;
00208 double halfAngle = (0.5 * maxAngle) * (z2 - z1) / (z3 - z1);
00209 if (unlikely(halfAngle <= 0.0))
00210 return 0.0;
00211
00212 return std::sin(halfAngle) / circle->delta;
00213 }
00214
00215 double ThirdHitPredictionFromCircle::HelixRZ::zAtR(double r) const
00216 {
00217 if (unlikely(std::abs(curvature) < 1.0e-5)) {
00218 double tip = circle->axis * circle->p1;
00219 double lip = circle->axis.y() * circle->p1.x() -
00220 circle->axis.x() * circle->p1.y();
00221 return z1 + (std::sqrt(sqr(r) - sqr(tip)) - lip) * dzdu;
00222 }
00223
00224 double radius = 1.0 / curvature;
00225 double radius2 = sqr(radius);
00226 double orthog = sgn(curvature) * clamped_sqrt(radius2 - circle->delta2);
00227 Point2D center = circle->center + orthog * circle->axis;
00228
00229 double b2 = center.mag2();
00230 double b = std::sqrt(b2);
00231
00232 double cos1 = 0.5 * (radius2 + b2 - sqr(r)) * curvature / b;
00233 double cos2 = 0.5 * (radius2 + b2 - circle->p1.mag2()) * curvature / b;
00234
00235 double phi1 = clamped_acos(cos1);
00236 double phi2 = clamped_acos(cos2);
00237
00238
00239
00240 double u1 = std::abs((phi1 - phi2) * radius);
00241 double u2 = std::abs((phi1 + phi2) * radius);
00242
00243 return z1 + ((u1 >= seg && u1 < u2)? u1 : u2) * dzdu;
00244 }
00245
00246 double ThirdHitPredictionFromCircle::HelixRZ::rAtZ(double z) const
00247 {
00248 if (unlikely(std::abs(dzdu) < 1.0e-5))
00249 return 99999.0;
00250
00251 if (unlikely(std::abs(curvature) < 1.0e-5)) {
00252 double tip = circle->axis * circle->p1;
00253 double lip = circle->axis.y() * circle->p1.x() -
00254 circle->axis.x() * circle->p1.y();
00255 return std::sqrt(sqr(tip) + sqr(lip + (z - z1) / dzdu));
00256 }
00257
00258
00259 double minR = (2. * circle->center - circle->p1).mag();
00260
00261 double phi = curvature * (z - z1) / dzdu;
00262
00263 if (unlikely(std::abs(phi) > 2. * M_PI)) {
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 return minR;
00274 }
00275
00276 double radius = 1. / curvature;
00277 double orthog = sgn(curvature) * clamped_sqrt(sqr(radius) - circle->delta2);
00278 Point2D center = circle->center + orthog * circle->axis;
00279 Point2D rel = circle->p1 - center;
00280
00281 double c = cos(phi);
00282 double s = sin(phi);
00283
00284 Point2D p(center.x() + c * rel.x() - s * rel.y(),
00285 center.y() + s * rel.x() + c * rel.y());
00286
00287 return std::max(minR, p.mag());
00288 }