ATLAS Offline Software
Loading...
Searching...
No Matches
BoundaryCheck.icc
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
5namespace Trk {
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)
8inline double
9BoundaryCheck::FastArcTan(double x) const
10{
11 double y;
12 bool complement = false; // true if arg was >1
13 bool sign = false; // true if arg was < 0
14 if (x < 0.) {
15 x = -x;
16 sign = true; // arctan(-x)=-arctan(x)
17 }
18 if (x > 1.) {
19 x = 1. / x; // keep arg between 0 and 1
20 complement = true;
21 }
22 y = M_PI_4 * x - x * (fabs(x) - 1) * (0.2447 + 0.0663 * fabs(x));
23 if (complement)
24 y = M_PI_2 - y; // correct for 1/x if we did that
25 if (sign)
26 y = -y; // correct for negative arg
27 return y;
28}
29
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
32// (>8 times)
33inline sincosCache
34BoundaryCheck::FastSinCos(double x) const
35{
36 sincosCache tmp;
37 // always wrap input angle to -PI..PI
38 if (x < -M_PI)
39 x += 2. * M_PI;
40 else if (x > M_PI)
41 x -= 2. * M_PI;
42
43 // compute sine
44 if (x < 0.) {
45 tmp.sinC = 1.27323954 * x + .405284735 * x * x;
46
47 if (tmp.sinC < 0.)
48 tmp.sinC = .225 * (tmp.sinC * -tmp.sinC - tmp.sinC) + tmp.sinC;
49 else
50 tmp.sinC = .225 * (tmp.sinC * tmp.sinC - tmp.sinC) + tmp.sinC;
51 } else {
52 tmp.sinC = 1.27323954 * x - 0.405284735 * x * x;
53
54 if (tmp.sinC < 0.)
55 tmp.sinC = .225 * (tmp.sinC * -tmp.sinC - tmp.sinC) + tmp.sinC;
56 else
57 tmp.sinC = .225 * (tmp.sinC * tmp.sinC - tmp.sinC) + tmp.sinC;
58 }
59
60 // compute cosine: sin(x + PI/2) = cos(x)
61 x += M_PI_2;
62 if (x > M_PI)
63 x -= 2. * M_PI;
64
65 if (x < 0.) {
66 tmp.cosC = 1.27323954 * x + 0.405284735 * x * x;
67
68 if (tmp.cosC < 0.)
69 tmp.cosC = .225 * (tmp.cosC * -tmp.cosC - tmp.cosC) + tmp.cosC;
70 else
71 tmp.cosC = .225 * (tmp.cosC * tmp.cosC - tmp.cosC) + tmp.cosC;
72 } else {
73 tmp.cosC = 1.27323954 * x - 0.405284735 * x * x;
74
75 if (tmp.cosC < 0.)
76 tmp.cosC = .225 * (tmp.cosC * -tmp.cosC - tmp.cosC) + tmp.cosC;
77 else
78 tmp.cosC = .225 * (tmp.cosC * tmp.cosC - tmp.cosC) + tmp.cosC;
79 }
80 return tmp;
81}
82
83// does the conversion of an ellipse of height h and width w to an polygon with
84// 4 + 4*resolution points
85inline std::vector<Amg::Vector2D>
86BoundaryCheck::EllipseToPoly(int resolution) const
87{
88 const double h = nSigmas * sqrt(lCovariance(1, 1));
89 const double w = nSigmas * sqrt(lCovariance(0, 0));
90
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);
97
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
101 AmgSymMatrix(2) t1;
102 // cppcheck-suppress constStatement
103 t1 << 1, 0, 0, -1;
104 AmgSymMatrix(2) t2;
105 // cppcheck-suppress constStatement
106 t2 << -1, 0, 0, -1;
107 AmgSymMatrix(2) t3;
108 // cppcheck-suppress constStatement
109 t3 << -1, 0, 0, 1;
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);
115 v[i * 4 + 0] = t;
116 v[i * 4 + 1] = t1 * t;
117 v[i * 4 + 2] = t2 * t;
118 v[i * 4 + 3] = t3 * t;
119 }
120 } else {
121 Amg::Vector2D t (w * s_cos22, h * s_cos67);
122 v[4] = t;
123 v[5] = t1 * t;
124 v[6] = t2 * t;
125 v[7] = t3 * t;
126 t = Amg::Vector2D (w * s_cos45, h * s_cos45);
127 v[8] = t;
128 v[9] = t1 * t;
129 v[10] = t2 * t;
130 v[11] = t3 * t;
131 t = Amg::Vector2D (w * s_cos67, h * s_cos22);
132 v[12] = t;
133 v[13] = t1 * t;
134 v[14] = t2 * t;
135 v[15] = t3 * t;
136 }
137 return v;
138}
139
140// calculates KDOP object from given polygon and set of axes
141inline void
142BoundaryCheck::ComputeKDOP(const std::vector<Amg::Vector2D>& v,
143 const std::vector<Amg::Vector2D>& KDOPAxes,
144 std::vector<KDOP>& kdop) const
145{
146 // initialize KDOP to first point
147 unsigned int k = KDOPAxes.size();
148 for (unsigned int i = 0; i < k; i++) {
149 kdop[i].max =
150 KDOPAxes[i](0, 0) * v[0](0, 0) + KDOPAxes[i](1, 0) * v[0](1, 0);
151 kdop[i].min =
152 KDOPAxes[i](0, 0) * v[0](0, 0) + KDOPAxes[i](1, 0) * v[0](1, 0);
153 }
154 // now for each additional point, update KDOP bounds if necessary
155 float value;
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)
160 kdop[j].min = value;
161 else if (value > kdop[j].max)
162 kdop[j].max = value;
163 }
164 }
165}
166
167// this is the method to actually check if two KDOPs overlap
168inline bool
169BoundaryCheck::TestKDOPKDOP(const std::vector<KDOP>& a,
170 const std::vector<KDOP>& b) const
171{
172 int k = a.size();
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)
176 return false;
177 // all intervals are overlapping, so KDOPs must intersect
178 return true;
179}
180
181}
182