Belle II Software  release-08-01-10
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 
14 using namespace Belle2;
15 using namespace TrackFindingCDC;
16 
17 TEST(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 
41 TEST(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 
56 TEST(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 
95 TEST(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 
113 TEST(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 
123 TEST(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 
156 TEST(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 
169 TEST(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 
187 TEST(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 
215 TEST(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 
257 TEST(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 
272 TEST(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 
288 TEST(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 
304 TEST(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 
316 TEST(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:35
double x() const
Getter for the x coordinate.
Definition: Vector2D.h:607
void conformalTransform()
Transforms the vector to conformal space inplace.
Definition: Vector2D.h:397
double second() const
Getter for the second coordinate.
Definition: Vector2D.h:651
double y() const
Getter for the y coordinate.
Definition: Vector2D.h:617
double first() const
Getter for the first coordinate.
Definition: Vector2D.h:641
TEST(TestgetDetectorRegion, TestgetDetectorRegion)
Test Constructors.
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.