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