2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
6 // should have maximum (average) error of 0.0015 (0.00089) radians or 0.0859
7 // (0.0509) degrees, fine for us and much faster (>4 times)
9 BoundaryCheck::FastArcTan(double x) const
12 bool complement = false; // true if arg was >1
13 bool sign = false; // true if arg was < 0
16 sign = true; // arctan(-x)=-arctan(x)
19 x = 1. / x; // keep arg between 0 and 1
22 y = M_PI_4 * x - x * (fabs(x) - 1) * (0.2447 + 0.0663 * fabs(x));
24 y = M_PI_2 - y; // correct for 1/x if we did that
26 y = -y; // correct for negative arg
30 // should have maximum (average) error of 0.001 (0.0005) radians or 0.0573
31 // (0.029) degrees, fine for us and much faster
34 BoundaryCheck::FastSinCos(double x) const
37 // always wrap input angle to -PI..PI
45 tmp.sinC = 1.27323954 * x + .405284735 * x * x;
48 tmp.sinC = .225 * (tmp.sinC * -tmp.sinC - tmp.sinC) + tmp.sinC;
50 tmp.sinC = .225 * (tmp.sinC * tmp.sinC - tmp.sinC) + tmp.sinC;
52 tmp.sinC = 1.27323954 * x - 0.405284735 * x * x;
55 tmp.sinC = .225 * (tmp.sinC * -tmp.sinC - tmp.sinC) + tmp.sinC;
57 tmp.sinC = .225 * (tmp.sinC * tmp.sinC - tmp.sinC) + tmp.sinC;
60 // compute cosine: sin(x + PI/2) = cos(x)
66 tmp.cosC = 1.27323954 * x + 0.405284735 * x * x;
69 tmp.cosC = .225 * (tmp.cosC * -tmp.cosC - tmp.cosC) + tmp.cosC;
71 tmp.cosC = .225 * (tmp.cosC * tmp.cosC - tmp.cosC) + tmp.cosC;
73 tmp.cosC = 1.27323954 * x - 0.405284735 * x * x;
76 tmp.cosC = .225 * (tmp.cosC * -tmp.cosC - tmp.cosC) + tmp.cosC;
78 tmp.cosC = .225 * (tmp.cosC * tmp.cosC - tmp.cosC) + tmp.cosC;
83 // does the conversion of an ellipse of height h and width w to an polygon with
84 // 4 + 4*resolution points
85 inline std::vector<Amg::Vector2D>
86 BoundaryCheck::EllipseToPoly(int resolution) const
88 const double h = nSigmas * sqrt(lCovariance(1, 1));
89 const double w = nSigmas * sqrt(lCovariance(0, 0));
91 // first add the four vertices
92 std::vector<Amg::Vector2D> v((1 + resolution) * 4);
93 v[0] = Amg::Vector2D ( w, 0.);
94 v[1] = Amg::Vector2D (-w, 0.);
95 v[2] = Amg::Vector2D ( 0., h);
96 v[3] = Amg::Vector2D ( 0., -h);
98 // now add a number, equal to the resolution, of equidistant points in each
99 // quadrant resolution == 3 seems to be a solid working point, but possibility
100 // open to change to any number in the future
102 // cppcheck-suppress constStatement
105 // cppcheck-suppress constStatement
108 // cppcheck-suppress constStatement
110 if (resolution != 3) {
111 sincosCache scResult;
112 for (int i = 1; i <= resolution; i++) {
113 scResult = FastSinCos(M_PI_2 * i / (resolution + 1));
114 Amg::Vector2D t (w * scResult.sinC, h * scResult.cosC);
116 v[i * 4 + 1] = t1 * t;
117 v[i * 4 + 2] = t2 * t;
118 v[i * 4 + 3] = t3 * t;
121 Amg::Vector2D t (w * s_cos22, h * s_cos67);
126 t = Amg::Vector2D (w * s_cos45, h * s_cos45);
131 t = Amg::Vector2D (w * s_cos67, h * s_cos22);
140 // calculates KDOP object from given polygon and set of axes
142 BoundaryCheck::ComputeKDOP(const std::vector<Amg::Vector2D>& v,
143 const std::vector<Amg::Vector2D>& KDOPAxes,
144 std::vector<KDOP>& kdop) const
146 // initialize KDOP to first point
147 unsigned int k = KDOPAxes.size();
148 for (unsigned int i = 0; i < k; i++) {
150 KDOPAxes[i](0, 0) * v[0](0, 0) + KDOPAxes[i](1, 0) * v[0](1, 0);
152 KDOPAxes[i](0, 0) * v[0](0, 0) + KDOPAxes[i](1, 0) * v[0](1, 0);
154 // now for each additional point, update KDOP bounds if necessary
156 for (unsigned int i = 1; i < v.size(); i++) {
157 for (unsigned int j = 0; j < k; j++) {
158 value = KDOPAxes[j](0, 0) * v[i](0, 0) + KDOPAxes[j](1, 0) * v[i](1, 0);
159 if (value < kdop[j].min)
161 else if (value > kdop[j].max)
167 // this is the method to actually check if two KDOPs overlap
169 BoundaryCheck::TestKDOPKDOP(const std::vector<KDOP>& a,
170 const std::vector<KDOP>& b) const
173 // check if any intervals are non-overlapping, return if so
174 for (int i = 0; i < k; i++)
175 if (a[i].min > b[i].max || a[i].max < b[i].min)
177 // all intervals are overlapping, so KDOPs must intersect