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