Belle II Software development
PerigeeCircle.test.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <tracking/trackFindingCDC/geometry/PerigeeCircle.h>
10#include <tracking/trackFindingCDC/geometry/GeneralizedCircle.h>
11#include <tracking/trackFindingCDC/geometry/Vector2D.h>
12
13#include <gtest/gtest.h>
14
15
16using namespace Belle2;
17using namespace TrackFindingCDC;
18
19TEST(TrackFindingCDCTest, geometry_PerigeeCircle_inheritance)
20{
21
22 double curvature = 1.0;
23 double phi0 = M_PI / 4.0;
24 double impact = 1.0;
25
26 // Checks if the normal parameters n follow the same sign convention
27 PerigeeCircle perigeeCircle(curvature, phi0, impact);
28
29 const GeneralizedCircle generalizedCircle(perigeeCircle.n0(),
30 perigeeCircle.n12(),
31 perigeeCircle.n3());
32
33 EXPECT_NEAR(curvature, generalizedCircle.curvature(), 10e-7);
34 EXPECT_NEAR(impact, generalizedCircle.impact(), 10e-7);
35 EXPECT_NEAR(perigeeCircle.tangential().x(), generalizedCircle.tangential().x(), 10e-7);
36 EXPECT_NEAR(perigeeCircle.tangential().y(), generalizedCircle.tangential().y(), 10e-7);
37
38 PerigeeCircle roundTripCircle(generalizedCircle);
39
40 EXPECT_NEAR(curvature, roundTripCircle.curvature(), 10e-7);
41 EXPECT_NEAR(impact, roundTripCircle.impact(), 10e-7);
42 EXPECT_NEAR(cos(phi0), roundTripCircle.phi0Vec().x(), 10e-7);
43 EXPECT_NEAR(sin(phi0), roundTripCircle.phi0Vec().y(), 10e-7);
44 EXPECT_NEAR(phi0, roundTripCircle.phi0(), 10e-7);
45
46 PerigeeCircle roundTripCircle2;
47 roundTripCircle2.setN(generalizedCircle);
48
49 EXPECT_NEAR(curvature, roundTripCircle2.curvature(), 10e-7);
50 EXPECT_NEAR(impact, roundTripCircle2.impact(), 10e-7);
51 EXPECT_NEAR(cos(phi0), roundTripCircle2.tangential().x(), 10e-7);
52 EXPECT_NEAR(sin(phi0), roundTripCircle2.tangential().y(), 10e-7);
53 EXPECT_NEAR(phi0, roundTripCircle2.phi0(), 10e-7);
54}
55
56TEST(TrackFindingCDCTest, geometry_PerigeeCircle_isLine)
57{
58 double radius = 1;
59 Vector2D center = Vector2D(2.0, 0.0);
61
62 EXPECT_FALSE(circle.isLine());
63
64 float curvature = 0;
65 float phi0 = M_PI / 2;
66 float impact = -1;
67 PerigeeCircle line = PerigeeCircle(curvature, phi0, impact);
68
69 EXPECT_TRUE(line.isLine());
70}
71
72TEST(TrackFindingCDCTest, geometry_PerigeeCircle_isCircle)
73{
74 double radius = 1;
75 Vector2D center = Vector2D(2.0, 0.0);
77
78 EXPECT_TRUE(circle.isCircle());
79
80 float curvature = 0;
81 float phi0 = M_PI / 2;
82 float impact = -1;
83 PerigeeCircle line = PerigeeCircle(curvature, phi0, impact);
84
85 EXPECT_FALSE(line.isCircle());
86}
87
88TEST(TrackFindingCDCTest, geometry_PerigeeCircle_orientation)
89{
90 double curvature = 1;
91 Vector2D phi0 = Vector2D::Phi(1);
92 double impact = 1;
93
94 PerigeeCircle circle(curvature, phi0, impact);
95 EXPECT_EQ(ERotation::c_CounterClockwise, circle.orientation());
96
97 PerigeeCircle reversedCircle = circle.reversed();
98 EXPECT_EQ(ERotation::c_Clockwise, reversedCircle.orientation());
99
100 curvature = 0;
101 PerigeeCircle line(curvature, phi0, impact);
102 EXPECT_EQ(ERotation::c_CounterClockwise, line.orientation());
103
104 PerigeeCircle reversedLine = line.reversed();
105 EXPECT_EQ(ERotation::c_Clockwise, reversedLine.orientation());
106}
107
108TEST(TrackFindingCDCTest, geometry_PerigeeCircle_minimalCylindricalR)
109{
110 double curvature = 1.0 / 2.0;
111 double tangtialPhi = M_PI / 4.0;
112 double impact = -1.0;
113
114 // Checks if the normal parameters n follow the same sign convention
115 PerigeeCircle perigeeCircle(curvature, tangtialPhi, impact);
116
117 EXPECT_EQ(1, perigeeCircle.minimalCylindricalR());
118}
119
120TEST(TrackFindingCDCTest, geometry_PerigeeCircle_maximalCylindricalR)
121{
122 double curvature = 1.0 / 2.0;
123 double tangtialPhi = M_PI / 4.0;
124 double impact = -1.0;
125
126 // Checks if the normal parameters n follow the same sign convention
127 PerigeeCircle perigeeCircle(curvature, tangtialPhi, impact);
128
129 EXPECT_EQ(3, perigeeCircle.maximalCylindricalR());
130}
131
132TEST(TrackFindingCDCTest, geometry_PerigeeCircle_setCenterAndRadius)
133{
134 PerigeeCircle circle;
135 Vector2D center(0.5, 0.0);
136 double radius = 1.5;
137 circle.setCenterAndRadius(center, radius, ERotation::c_CounterClockwise);
138
139 EXPECT_TRUE(circle.isCircle());
140 EXPECT_FALSE(circle.isLine());
141
142 EXPECT_NEAR(1.5, circle.radius(), 10e-7);
143 EXPECT_NEAR(0.5, circle.center().x(), 10e-7);
144 EXPECT_NEAR(0.0, circle.center().y(), 10e-7);
145}
146
147TEST(TrackFindingCDCTest, geometry_PerigeeCircle_distance)
148{
149
150 double curvature = -1.;
151 double phi0 = 3. * M_PI / 4.;
152 double impact = 1. - sqrt(2.);
153
154 PerigeeCircle circle(curvature, phi0, impact);
155
156 EXPECT_TRUE(circle.isCircle());
157 EXPECT_FALSE(circle.isLine());
158
159 EXPECT_NEAR(-1.0, circle.radius(), 10e-7);
160 EXPECT_NEAR(1.0, circle.center().x(), 10e-7);
161 EXPECT_NEAR(1.0, circle.center().y(), 10e-7);
162
163 EXPECT_NEAR(curvature, circle.curvature(), 10e-7);
164 EXPECT_NEAR(phi0, circle.phi0(), 10e-7);
165 EXPECT_NEAR(impact, circle.impact(), 10e-7);
166
167 EXPECT_NEAR(0, circle.distance(Vector2D(1.0, 0.0)), 10e-7);
168 EXPECT_NEAR(0, circle.distance(Vector2D(0.0, 1.0)), 10e-7);
169 EXPECT_NEAR(impact, circle.distance(Vector2D(0.0, 0.0)), 10e-7);
170
171 EXPECT_NEAR(0.5, circle.distance(Vector2D(1.0, 0.5)), 10e-7);
172
173 EXPECT_NEAR(-0.5, circle.distance(Vector2D(1.0, 2.5)), 10e-7);
174 EXPECT_NEAR(-0.5, circle.distance(Vector2D(2.5, 1.0)), 10e-7);
175}
176
177TEST(TrackFindingCDCTest, geometry_PerigeeCircle_invalidate)
178{
179 PerigeeCircle defaultCircle;
180 EXPECT_TRUE(defaultCircle.isInvalid());
181
182 double curvature = -1.;
183 double phi0 = 3. * M_PI / 4.;
184 double impact = 1. - sqrt(2.0);
185
186 PerigeeCircle circle(curvature, phi0, impact);
187
188 circle.invalidate();
189 EXPECT_TRUE(circle.isInvalid());
190
191 circle.reverse();
192 EXPECT_TRUE(circle.isInvalid());
193
194 circle = circle.reversed();
195 EXPECT_TRUE(circle.isInvalid());
196
197 GeneralizedCircle generalizedCircle;
198 generalizedCircle.invalidate();
199 circle.setN(generalizedCircle);
200
201 EXPECT_TRUE(circle.isInvalid());
202}
203
204TEST(TrackFindingCDCTest, geometry_PerigeeCircle_passiveMoveBy)
205{
206 Vector2D center(4.0, 2.0);
207 double radius = 5.0;
208 PerigeeCircle circle = PerigeeCircle::fromCenterAndRadius(center, radius);
209
210 circle.passiveMoveBy(Vector2D(4.0, 0.0));
211
212 EXPECT_NEAR(5.0, circle.radius(), 10e-7);
213 EXPECT_NEAR(0.0, circle.perigee().x(), 10e-7);
214 EXPECT_NEAR(-3.0, circle.perigee().y(), 10e-7);
215}
216
217TEST(TrackFindingCDCTest, geometry_PerigeeCircle_conformalTranform)
218{
219 Vector2D center(1.0, 0.0);
220 double radius = 1.0;
221 PerigeeCircle circle = PerigeeCircle::fromCenterAndRadius(center, radius);
222
223 // Get two points on the circle to check for the orientation to be correct
224 Vector2D firstPos = circle.atArcLength(1);
225 Vector2D secondPos = circle.atArcLength(2);
226
227 EXPECT_NEAR(1.0, circle.curvature(), 10e-7);
228 EXPECT_NEAR(-M_PI / 2.0, circle.phi0(), 10e-7);
229 EXPECT_NEAR(0.0, circle.impact(), 10e-7);
230 EXPECT_NEAR(0.0, circle.distance(firstPos), 10e-7);
231 EXPECT_NEAR(0.0, circle.distance(secondPos), 10e-7);
232
233 circle.conformalTransform();
234 firstPos.conformalTransform();
235 secondPos.conformalTransform();
236
237 EXPECT_NEAR(0.0, circle.curvature(), 10e-7);
238 EXPECT_NEAR(M_PI / 2.0, circle.phi0(), 10e-7);
239 EXPECT_NEAR(-1.0 / 2.0, circle.impact(), 10e-7);
240
241 double firstConformalArcLength = circle.arcLengthTo(firstPos);
242 double secondConformalArcLength = circle.arcLengthTo(secondPos);
243 EXPECT_LT(firstConformalArcLength, secondConformalArcLength);
244
245 EXPECT_NEAR(0.0, circle.distance(firstPos), 10e-7);
246 EXPECT_NEAR(0.0, circle.distance(secondPos), 10e-7);
247
248 // Another conformal transformation goes back to the original circle
249 PerigeeCircle conformalCopy = circle.conformalTransformed();
250 EXPECT_NEAR(1.0, conformalCopy.curvature(), 10e-7);
251 EXPECT_NEAR(-M_PI / 2.0, conformalCopy.phi0(), 10e-7);
252 EXPECT_NEAR(0.0, conformalCopy.impact(), 10e-7);
253}
254
255TEST(TrackFindingCDCTest, geometry_PerigeeCircle_closest)
256{
257 PerigeeCircle circle(1.0, Vector2D(0.0, -1.0), 1.0);
258 Vector2D up(2.0, 2.0);
259 Vector2D far(5.0, 0.0);
260
261 EXPECT_EQ(Vector2D(2.0, 1.0), circle.closest(up));
262 EXPECT_EQ(Vector2D(3.0, 0.0), circle.closest(far));
263
264 // This tests for point which is on the circle
265 double smallAngle = M_PI / 100;
266 Vector2D near(2.0 - cos(smallAngle), sin(smallAngle));
267
268 Vector2D closestOfNear = circle.closest(near);
269 EXPECT_NEAR(near.x(), closestOfNear.x(), 10e-7);
270 EXPECT_NEAR(near.y(), closestOfNear.y(), 10e-7);
271}
272
273TEST(TrackFindingCDCTest, geometry_PerigeeCircle_atArcLength)
274{
275 double radius = 1;
276 Vector2D center = Vector2D(2.0, 0.0);
277
278 PerigeeCircle circle = PerigeeCircle::fromCenterAndRadius(center, radius);
279
280 double smallAngle = M_PI / 100;
281 Vector2D near(2.0 - cos(smallAngle), sin(smallAngle));
282
283 double nearArcLength =
284 -smallAngle * radius; // Minus because of default counterclockwise orientation
285
286 Vector2D atNear = circle.atArcLength(nearArcLength);
287
288 EXPECT_NEAR(near.x(), atNear.x(), 10e-7);
289 EXPECT_NEAR(near.y(), atNear.y(), 10e-7);
290
291 Vector2D down(2.0, -1.0);
292 double downArcLength =
293 +M_PI / 2.0 * radius; // Plus because of default counterclockwise orientation
294
295 Vector2D atDown = circle.atArcLength(downArcLength);
296
297 EXPECT_NEAR(down.x(), atDown.x(), 10e-7);
298 EXPECT_NEAR(down.y(), atDown.y(), 10e-7);
299}
300
301TEST(TrackFindingCDCTest, geometry_PerigeeCircle_arcLengthToCylindricalR)
302{
303 double radius = 1;
304 Vector2D center = Vector2D(2.0, 0.0);
305
306 PerigeeCircle circle = PerigeeCircle::fromCenterAndRadius(center, radius);
307 {
308 double closestArcLength = circle.arcLengthToCylindricalR(1);
309 EXPECT_NEAR(0, closestArcLength, 10e-7);
310
311 double widestArcLength = circle.arcLengthToCylindricalR(3);
312 EXPECT_NEAR(M_PI, widestArcLength, 10e-7);
313
314 double halfArcLength = circle.arcLengthToCylindricalR(sqrt(5.0));
315 EXPECT_NEAR(M_PI / 2, halfArcLength, 10e-7);
316
317 double unreachableHighArcLength = circle.arcLengthToCylindricalR(4);
318 EXPECT_TRUE(std::isnan(unreachableHighArcLength));
319
320 double unreachableLowArcLength = circle.arcLengthToCylindricalR(0.5);
321 EXPECT_TRUE(std::isnan(unreachableLowArcLength));
322 }
323
324 PerigeeCircle reversedCircle = circle.reversed();
325 {
326 double closestArcLength = reversedCircle.arcLengthToCylindricalR(1);
327 EXPECT_NEAR(0, closestArcLength, 10e-7);
328
329 double widestArcLength = reversedCircle.arcLengthToCylindricalR(3);
330 EXPECT_NEAR(M_PI, widestArcLength, 10e-7);
331
332 double halfArcLength = reversedCircle.arcLengthToCylindricalR(sqrt(5.0));
333 EXPECT_NEAR(M_PI / 2, halfArcLength, 10e-7);
334
335 double unreachableHighArcLength = reversedCircle.arcLengthToCylindricalR(4);
336 EXPECT_TRUE(std::isnan(unreachableHighArcLength));
337
338 double unreachableLowArcLength = reversedCircle.arcLengthToCylindricalR(0.5);
339 EXPECT_TRUE(std::isnan(unreachableLowArcLength));
340 }
341}
342
343TEST(TrackFindingCDCTest, geometry_PerigeeCircle_atCylindricalR)
344{
345 double radius = 1;
346 Vector2D center = Vector2D(2.0, 0.0);
347 PerigeeCircle circle = PerigeeCircle::fromCenterAndRadius(center, radius);
348
349 std::pair<Vector2D, Vector2D> solutions = circle.atCylindricalR(sqrt(5.0));
350
351 EXPECT_NEAR(2, solutions.first.x(), 10e-7);
352 EXPECT_NEAR(1, solutions.first.y(), 10e-7);
353
354 EXPECT_NEAR(2, solutions.second.x(), 10e-7);
355 EXPECT_NEAR(-1, solutions.second.y(), 10e-7);
356}
357
358TEST(TrackFindingCDCTest, geometry_PerigeeCircle_atCylindricalR_opposite_orientation)
359{
360 double radius = 1;
361 Vector2D center = Vector2D(2.0, 0.0);
362 PerigeeCircle circle = PerigeeCircle::fromCenterAndRadius(center, radius, ERotation::c_Clockwise);
363
364 std::pair<Vector2D, Vector2D> solutions = circle.atCylindricalR(sqrt(5.0));
365
366 EXPECT_NEAR(2, solutions.first.x(), 10e-7);
367 EXPECT_NEAR(-1, solutions.first.y(), 10e-7);
368
369 EXPECT_NEAR(2, solutions.second.x(), 10e-7);
370 EXPECT_NEAR(1, solutions.second.y(), 10e-7);
371}
372
373TEST(TrackFindingCDCTest, geometry_PerigeeCircle_OriginCircleFromPointDirection)
374{
375 double expectedCurvature = 1.0 / 2.0;
376 double expectedPhi0 = M_PI / 4.0;
377 double impact = 0;
378
379 // Checks if the normal parameters n follow the same sign convention
380 const PerigeeCircle perigeeCircle(expectedCurvature, expectedPhi0, impact);
381 const Vector2D& expectedPhi0Vec = perigeeCircle.phi0Vec();
382
383 double randomArcLength = 2.0;
384 Vector2D pos2D = perigeeCircle.atArcLength(randomArcLength);
385 Vector2D phiVec = perigeeCircle.tangential(pos2D);
386
387 double curvature = 2 * pos2D.cross(phiVec) / pos2D.normSquared();
388 Vector2D phi0Vec = phiVec.flippedOver(pos2D);
389
390 EXPECT_NEAR(expectedCurvature, curvature, 10e-7);
391 EXPECT_NEAR(expectedPhi0Vec.x(), phi0Vec.x(), 10e-7);
392 EXPECT_NEAR(expectedPhi0Vec.y(), phi0Vec.y(), 10e-7);
393 EXPECT_NEAR(expectedPhi0, phi0Vec.phi(), 10e-7);
394 EXPECT_NEAR(1, phi0Vec.norm(), 10e-7);
395}
void invalidate()
Sets all circle parameters to zero.
Extension of the generalized circle also caching the perigee coordinates.
Definition: PerigeeCircle.h:36
Vector2D atArcLength(double arcLength) const
Calculates the point, which lies at the give perpendicular travel distance (counted from the perigee)
PerigeeCircle reversed() const
Returns a copy of the circle with opposite orientation.
void setCenterAndRadius(const Vector2D &center, double absRadius, ERotation orientation=ERotation::c_CounterClockwise)
Setter for the circle center and radius.
bool isLine() const
Indicates if the perigee parameters represent a line.
Vector2D perigee() const
Getter for the perigee point.
double phi0() const
Getter for the azimuth angle of the direction of flight at the perigee.
Vector2D tangential(const Vector2D &point) const
Tangential vector to the circle near the given position.
bool isInvalid() const
Indicates if all circle parameters are zero.
void reverse()
Flips the orientation of the circle in place.
double radius() const
Gives the signed radius of the circle. If it was a line this will be infinity.
double distance(const Vector2D &point) const
Getter for the proper signed distance of the point to the circle.
void passiveMoveBy(const Vector2D &by)
Moves the coordinates system by the given vector. Updates perigee parameters in place.
double impact() const
Getter for the signed distance of the origin to the circle.
Vector2D center() const
Getter for the center of the circle. If it was a line both components will be infinity.
static PerigeeCircle fromCenterAndRadius(const Vector2D &center, double absRadius, ERotation orientation=ERotation::c_CounterClockwise)
Constructor from center, radius and a optional orientation.
void invalidate()
Sets all circle parameters to zero.
void conformalTransform()
Transforms the generalized circle to conformal space inplace.
bool isCircle() const
Indicates if the perigee parameters represent a closed circle.
double curvature() const
Getter for the signed curvature.
void setN(double n0, double n1, double n2, double n3=0.0)
Setter for four generalised circle parameters.
Vector2D closest(const Vector2D &point) const
Calculates the point of closest approach on the circle to the given point.
PerigeeCircle conformalTransformed() const
Returns a copy of the circle in conformal space.
std::pair< Vector2D, Vector2D > atCylindricalR(double cylindricalR) const
Calculates the two points with the given cylindrical radius on the generalised circle.
ERotation orientation() const
Getter for the orientation of the circle.
double arcLengthTo(const Vector2D &point) const
Calculates the arc length between the perigee and the given point.
double arcLengthToCylindricalR(double cylindricalR) const
Calculates the two dimensional arc length till the cylindrical radius is reached If the radius can no...
A two dimensional vector which is equipped with functions for correct handling of orientation relate...
Definition: Vector2D.h:32
double cross(const Vector2D &rhs) const
Calculated the two dimensional cross product.
Definition: Vector2D.h:163
double x() const
Getter for the x coordinate.
Definition: Vector2D.h:595
void conformalTransform()
Transforms the vector to conformal space inplace.
Definition: Vector2D.h:385
double phi() const
Gives the azimuth angle being the angle to the x axes ( range -M_PI to M_PI )
Definition: Vector2D.h:569
double normSquared() const
Calculates .
Definition: Vector2D.h:169
double y() const
Getter for the y coordinate.
Definition: Vector2D.h:605
Vector2D flippedOver(const Vector2D &reflectionLine) const
Reflects this vector over line designated by the given vector.
Definition: Vector2D.h:371
double norm() const
Calculates the length of the vector.
Definition: Vector2D.h:175
static Vector2D Phi(const double phi)
Constructs a unit vector with azimuth angle equal to phi.
Definition: Vector2D.h:62
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.