Belle II Software development
GeneralizedCircle.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/GeneralizedCircle.h>
10#include <tracking/trackFindingCDC/geometry/Vector2D.h>
11
12#include <gtest/gtest.h>
13
14using namespace Belle2;
15using namespace TrackFindingCDC;
16
17TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_Getters)
18{
19 float absError = 10e-6;
20
21 float n0 = 0.0;
22 float n1 = 1.0;
23 float n2 = 0.0;
24 float n3 = 1.0;
25
26 GeneralizedCircle circle(n0, n1, n2, n3);
27
28 EXPECT_NEAR(n0, circle.n0(), absError);
29 EXPECT_NEAR(n1, circle.n1(), absError);
30 EXPECT_NEAR(n2, circle.n2(), absError);
31 EXPECT_NEAR(n3, circle.n3(), absError);
32
33 EXPECT_NEAR(2.0 * n3, circle.curvature(), absError);
34 EXPECT_NEAR(1.0 / (2.0 * n3), circle.radius(), absError);
35
36 EXPECT_NEAR(M_PI / 2.0, circle.tangentialPhi(), absError);
37
38 EXPECT_NEAR(0, circle.impact(), absError);
39}
40
41TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_orientation)
42{
43 GeneralizedCircle circle(1.0, 0.0, 0.0, 1.0);
44 EXPECT_EQ(ERotation::c_CounterClockwise, circle.orientation());
45
46 GeneralizedCircle reversedCircle(1.0, 0.0, 0.0, -1.0);
47 EXPECT_EQ(ERotation::c_Clockwise, reversedCircle.orientation());
48
49 GeneralizedCircle line(1.0, 0.0, 0.0, 0.0);
50 EXPECT_EQ(ERotation::c_CounterClockwise, line.orientation());
51
52 GeneralizedCircle reversedLine(1.0, 0.0, 0.0, -0.0);
53 EXPECT_EQ(ERotation::c_Clockwise, reversedLine.orientation());
54}
55
56TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_conformalTranform)
57{
58 Vector2D center(1.0, 0.0);
59 double radius = 1.0;
61
62 // Get two points on the circle to check for the orientation to be correct
63 Vector2D firstPos = circle.atArcLength(1);
64 Vector2D secondPos = circle.atArcLength(2);
65
66 EXPECT_NEAR(1.0, circle.curvature(), 10e-7);
67 EXPECT_NEAR(-M_PI / 2.0, circle.tangentialPhi(), 10e-7);
68 EXPECT_NEAR(0.0, circle.impact(), 10e-7);
69 EXPECT_NEAR(0.0, circle.distance(firstPos), 10e-7);
70 EXPECT_NEAR(0.0, circle.distance(secondPos), 10e-7);
71
72 circle.conformalTransform();
73 firstPos.conformalTransform();
74 secondPos.conformalTransform();
75
76 EXPECT_NEAR(0.0, circle.curvature(), 10e-7);
77 EXPECT_NEAR(M_PI / 2.0, circle.tangentialPhi(), 10e-7);
78 EXPECT_NEAR(-1.0 / 2.0, circle.impact(), 10e-7);
79
80 double firstConformalArcLength = circle.arcLengthTo(firstPos);
81 double secondConformalArcLength = circle.arcLengthTo(secondPos);
82 EXPECT_TRUE(firstConformalArcLength < secondConformalArcLength);
83 EXPECT_LT(firstConformalArcLength, secondConformalArcLength);
84
85 EXPECT_NEAR(0.0, circle.distance(firstPos), 10e-7);
86 EXPECT_NEAR(0.0, circle.distance(secondPos), 10e-7);
87
88 // Another conformal transformation goes back to the original circle
89 GeneralizedCircle conformalCopy = circle.conformalTransformed();
90 EXPECT_NEAR(1.0, conformalCopy.curvature(), 10e-7);
91 EXPECT_NEAR(-M_PI / 2.0, conformalCopy.tangentialPhi(), 10e-7);
92 EXPECT_NEAR(0.0, conformalCopy.impact(), 10e-7);
93}
94
95TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_closest)
96{
97 GeneralizedCircle circle(0.0, -1.0, 0.0, 1.0 / 2.0);
98 Vector2D up(1.0, 2.0);
99 Vector2D far(4.0, 0.0);
100
101 EXPECT_EQ(Vector2D(1.0, 1.0), circle.closest(up));
102 EXPECT_EQ(Vector2D(2.0, 0.0), circle.closest(far));
103
104 // This tests for point which is on the circle
105 double smallAngle = M_PI / 100;
106 Vector2D near(1.0 - cos(smallAngle), sin(smallAngle));
107
108 Vector2D closestOfNear = circle.closest(near);
109 EXPECT_NEAR(near.x(), closestOfNear.x(), 10e-7);
110 EXPECT_NEAR(near.y(), closestOfNear.y(), 10e-7);
111}
112
113TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_arcLengthFactor)
114{
115 GeneralizedCircle circle(0.0, -1.0, 0.0, 1.0 / 2.0);
116 double smallAngle = M_PI / 100;
117 Vector2D near(1.0 - cos(smallAngle), sin(smallAngle));
118
119 double expectedArcLengthFactor = smallAngle / near.cylindricalR();
120 EXPECT_NEAR(expectedArcLengthFactor, circle.arcLengthFactor(near.cylindricalR()), 10e-7);
121}
122
123TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_arcLengthBetween)
124{
125 GeneralizedCircle circle(0.0, -1.0, 0.0, 1.0 / 2.0);
126 Vector2D origin(0.0, 0.0);
127 Vector2D up(1.0, 2.0);
128 Vector2D down(1.0, -2.0);
129 Vector2D far(4.0, 0.0);
130
131 double smallAngle = M_PI / 100;
132 Vector2D close(1.0 - cos(smallAngle), sin(smallAngle));
133
134 EXPECT_NEAR(-M_PI / 2.0, circle.arcLengthBetween(origin, up), 10e-7);
135 EXPECT_NEAR(M_PI / 2.0, circle.arcLengthBetween(origin, down), 10e-7);
136
137 EXPECT_NEAR(M_PI / 2.0, circle.arcLengthBetween(up, origin), 10e-7);
138 EXPECT_NEAR(-M_PI / 2.0, circle.arcLengthBetween(down, origin), 10e-7);
139
140 // Sign of the length at the far end is unstable, which is why fabs is taken here
141 EXPECT_NEAR(M_PI, fabs(circle.arcLengthBetween(origin, far)), 10e-7);
142
143 EXPECT_NEAR(-smallAngle, circle.arcLengthBetween(origin, close), 10e-7);
144
145 GeneralizedCircle line(0.0, -1.0, 0.0, 0.0);
146 EXPECT_NEAR(-2, line.arcLengthBetween(origin, up), 10e-7);
147 EXPECT_NEAR(2, line.arcLengthBetween(origin, down), 10e-7);
148 EXPECT_NEAR(0, line.arcLengthBetween(origin, far), 10e-7);
149
150 GeneralizedCircle reverseLine(0.0, 1.0, 0.0, -0.0);
151 EXPECT_NEAR(2, reverseLine.arcLengthBetween(origin, up), 10e-7);
152 EXPECT_NEAR(-2, reverseLine.arcLengthBetween(origin, down), 10e-7);
153 EXPECT_NEAR(0, reverseLine.arcLengthBetween(origin, far), 10e-7);
154}
155
156TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_passiveMoveBy)
157{
158 Vector2D center(4.0, 2.0);
159 double radius = 5.0;
161
162 circle.passiveMoveBy(Vector2D(3.0, 3.0));
163
164 EXPECT_NEAR(5.0, circle.radius(), 10e-7);
165 EXPECT_NEAR(1.0, circle.center().x(), 10e-7);
166 EXPECT_NEAR(-1.0, circle.center().y(), 10e-7);
167}
168
169TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_intersections)
170{
171
173 GeneralizedCircle line = GeneralizedCircle(sqrt(2.0), -Vector2D(1.0, 1.0).unit());
174
175 std::pair<Vector2D, Vector2D> intersections = circle.intersections(line);
176
177 const Vector2D& intersection1 = intersections.first;
178 const Vector2D& intersection2 = intersections.second;
179
180 EXPECT_NEAR(1 - sqrt(2.0) / 2.0, intersection1.x(), 10e-7);
181 EXPECT_NEAR(1 + sqrt(2.0) / 2.0, intersection1.y(), 10e-7);
182
183 EXPECT_NEAR(1 + sqrt(2.0) / 2.0, intersection2.x(), 10e-7);
184 EXPECT_NEAR(1 - sqrt(2.0) / 2.0, intersection2.y(), 10e-7);
185}
186
187TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_atArcLength)
188{
189 double radius = 1;
190 Vector2D center = Vector2D(2.0, 0.0);
191
193
194 double smallAngle = M_PI / 100;
195 Vector2D near(2.0 - cos(smallAngle), sin(smallAngle));
196
197 double nearArcLength =
198 -smallAngle * radius; // Minus because of default counterclockwise orientation
199
200 Vector2D atNear = circle.atArcLength(nearArcLength);
201
202 EXPECT_NEAR(near.x(), atNear.x(), 10e-7);
203 EXPECT_NEAR(near.y(), atNear.y(), 10e-7);
204
205 Vector2D down(2.0, -1.0);
206 double downArcLength =
207 +M_PI / 2.0 * radius; // Plus because of default counterclockwise orientation
208
209 Vector2D atDown = circle.atArcLength(downArcLength);
210
211 EXPECT_NEAR(down.x(), atDown.x(), 10e-7);
212 EXPECT_NEAR(down.y(), atDown.y(), 10e-7);
213}
214
215TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_arcLengthToCylindricalR)
216{
217 double radius = 1;
218 Vector2D center = Vector2D(2.0, 0.0);
219
221 {
222 double closestArcLength = circle.arcLengthToCylindricalR(1);
223 EXPECT_NEAR(0, closestArcLength, 10e-7);
224
225 double widestArcLength = circle.arcLengthToCylindricalR(3);
226 EXPECT_NEAR(M_PI, widestArcLength, 10e-7);
227
228 double halfArcLength = circle.arcLengthToCylindricalR(sqrt(5.0));
229 EXPECT_NEAR(M_PI / 2, halfArcLength, 10e-7);
230
231 double unreachableHighArcLength = circle.arcLengthToCylindricalR(4);
232 EXPECT_TRUE(std::isnan(unreachableHighArcLength));
233
234 double unreachableLowArcLength = circle.arcLengthToCylindricalR(0.5);
235 EXPECT_TRUE(std::isnan(unreachableLowArcLength));
236 }
237
238 GeneralizedCircle reversedCircle = circle.reversed();
239 {
240 double closestArcLength = reversedCircle.arcLengthToCylindricalR(1);
241 EXPECT_NEAR(0, closestArcLength, 10e-7);
242
243 double widestArcLength = reversedCircle.arcLengthToCylindricalR(3);
244 EXPECT_NEAR(M_PI, widestArcLength, 10e-7);
245
246 double halfArcLength = reversedCircle.arcLengthToCylindricalR(sqrt(5.0));
247 EXPECT_NEAR(M_PI / 2, halfArcLength, 10e-7);
248
249 double unreachableHighArcLength = reversedCircle.arcLengthToCylindricalR(4);
250 EXPECT_TRUE(std::isnan(unreachableHighArcLength));
251
252 double unreachableLowArcLength = reversedCircle.arcLengthToCylindricalR(0.5);
253 EXPECT_TRUE(std::isnan(unreachableLowArcLength));
254 }
255}
256
257TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_atCylindricalR)
258{
259 double radius = 1;
260 Vector2D center = Vector2D(2.0, 0.0);
262
263 std::pair<Vector2D, Vector2D> solutions = circle.atCylindricalR(sqrt(5.0));
264
265 EXPECT_NEAR(2, solutions.first.x(), 10e-7);
266 EXPECT_NEAR(1, solutions.first.y(), 10e-7);
267
268 EXPECT_NEAR(2, solutions.second.x(), 10e-7);
269 EXPECT_NEAR(-1, solutions.second.y(), 10e-7);
270}
271
272TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_isLine)
273{
274 double radius = 1;
275 Vector2D center = Vector2D(2.0, 0.0);
277
278 EXPECT_FALSE(circle.isLine());
279
280 float curvature = 0;
281 float phi0 = M_PI / 2;
282 float impact = -1;
283 GeneralizedCircle line = GeneralizedCircle::fromPerigeeParameters(curvature, phi0, impact);
284
285 EXPECT_TRUE(line.isLine());
286}
287
288TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_isCircle)
289{
290 double radius = 1;
291 Vector2D center = Vector2D(2.0, 0.0);
293
294 EXPECT_TRUE(circle.isCircle());
295
296 float curvature = 0;
297 float phi0 = M_PI / 2;
298 float impact = -1;
299 GeneralizedCircle line = GeneralizedCircle::fromPerigeeParameters(curvature, phi0, impact);
300
301 EXPECT_FALSE(line.isCircle());
302}
303
304TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_perigeeConversion)
305{
306 float curvature = -0.5;
307 float phi0 = M_PI / 2;
308 float impact = -1;
309 GeneralizedCircle circle = GeneralizedCircle::fromPerigeeParameters(curvature, phi0, impact);
310
311 EXPECT_NEAR(impact, circle.impact(), 10e-7);
312 EXPECT_NEAR(phi0, circle.tangentialPhi(), 10e-7);
313 EXPECT_NEAR(curvature, circle.curvature(), 10e-7);
314}
315
316TEST(TrackFindingCDCTest, geometry_GeneralizedCircle_distance)
317{
318 float absError = 10e-6;
319
320 float radius = 1.5;
321 Vector2D center = Vector2D(0.5, 0.0);
322
324
325 Vector2D testPoint(3, 0);
326
327 EXPECT_NEAR(1, circle.distance(testPoint), absError);
328 EXPECT_NEAR(1, circle.absDistance(testPoint), absError);
329 // Approximated distance is already quite far of since the circle radius is of the order of the
330 // distance
331 EXPECT_NEAR(1.33333, circle.fastDistance(testPoint), absError);
332
333 // Now clockwise orientation. All points outside the circle have negative distance
334 circle.reverse();
335
336 EXPECT_NEAR(-1, circle.distance(testPoint), absError);
337 EXPECT_NEAR(1, circle.absDistance(testPoint), absError);
338 EXPECT_NEAR(-1.33333, circle.fastDistance(testPoint), absError);
339}
Vector2D atArcLength(double arcLength) const
Calculates the point, which lies at the give perpendicular travel distance (counted from the perigee)
double fastDistance(const Vector2D &point) const
Approximate distance.
double absDistance(const Vector2D &point) const
Gives the proper absolute distance of the point to the circle line.
bool isLine() const
Indicates if the generalized circle is actually a line.
GeneralizedCircle reversed() const
Returns a copy of the circle with opposite orientation.
double arcLengthBetween(const Vector2D &from, const Vector2D &to) const
Calculates the arc length between two points of closest approach on the circle.
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
Gives the proper distance of the point to the circle line retaining the sign of the fast distance.
void passiveMoveBy(const Vector2D &by)
Moves the coordinate system by the given vector.
double impact() const
Gives the signed distance of the origin to the circle.
Vector2D center() const
Gives the center of the circle. If it was a line both components will be infinity.
static GeneralizedCircle fromPerigeeParameters(double curvature, const Vector2D &tangential, double impact)
Constructor of a generalized circle from perigee parameters.
void conformalTransform()
Transforms the generalized circle to conformal space inplace Applies the conformal map in the self-in...
static GeneralizedCircle fromCenterAndRadius(const Vector2D &center, double absRadius, ERotation orientation=ERotation::c_CounterClockwise)
Constructor from center, radius and a optional orientation.
bool isCircle() const
Indicates if the generalized circle is actually a circle.
double arcLengthTo(const Vector2D &to) const
Calculates the arc length between the perigee and the given point.
double curvature() const
Gives the signed curvature of the generalized circle.
Vector2D closest(const Vector2D &point) const
Closest approach on the circle to the point.
double arcLengthFactor(const double directDistance) const
Helper function the calculate the factor between the length of a secant line and the length on the ar...
std::pair< Belle2::TrackFindingCDC::Vector2D, Belle2::TrackFindingCDC::Vector2D > atCylindricalR(double cylindricalR) const
Calculates the two points with the given cylindrical radius on the generalised circle.
double tangentialPhi() const
Gives to azimuth angle phi of the direction of flight at the perigee.
double arcLengthToCylindricalR(double cylindricalR) const
Calculates the two dimensional arc length till the cylindrical radius is reached If the radius can no...
std::pair< Vector2D, Vector2D > intersections(const GeneralizedCircle &generalizedCircle) const
Calculates the two points common to both circles.
GeneralizedCircle conformalTransformed() const
Returns a copy of the circle in conformal space.
A two dimensional vector which is equipped with functions for correct handeling of orientation relat...
Definition: Vector2D.h:32
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 second() const
Getter for the second coordinate.
Definition: Vector2D.h:639
double y() const
Getter for the y coordinate.
Definition: Vector2D.h:605
double first() const
Getter for the first coordinate.
Definition: Vector2D.h:629
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.