Belle II Software development
GeneralizedCircle.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#include <tracking/trackFindingCDC/geometry/GeneralizedCircle.h>
9
10#include <tracking/trackFindingCDC/geometry/Circle2D.h>
11#include <tracking/trackFindingCDC/geometry/Line2D.h>
12#include <tracking/trackFindingCDC/geometry/Vector2D.h>
13
14#include <tracking/trackFindingCDC/numerics/EForwardBackward.h>
15#include <tracking/trackFindingCDC/numerics/ERotation.h>
16
17#include <tracking/trackFindingCDC/numerics/SpecialFunctions.h>
18#include <tracking/trackFindingCDC/numerics/Quadratic.h>
19
20#include <ostream>
21#include <cmath>
22
23using namespace Belle2;
24using namespace TrackFindingCDC;
25
27 : m_n3(0.0)
28 , m_n12(0.0, 0.0)
29 , m_n0(0.0)
30{
31}
32
34 const double n1,
35 const double n2,
36 const double n3)
37 : m_n3(n3)
38 , m_n12(n1, n2)
39 , m_n0(n0)
40{
41 normalize();
42}
43
44GeneralizedCircle::GeneralizedCircle(const double n0, const Vector2D& n12, const double n3)
45 : m_n3(n3)
46 , m_n12(n12)
47 , m_n0(n0)
48{
49 normalize();
50}
51
53 : m_n3(0.0)
54 , m_n12(n012.n12())
55 , m_n0(n012.n0())
56{
57 normalize();
58}
59
61 : m_n3(1.0 / 2.0 / circle.radius())
62 , m_n12(-circle.center().x() * (m_n3 * 2.0), -circle.center().y() * (m_n3 * 2.0))
63 , m_n0((circle.center().normSquared() - circle.radiusSquared()) * m_n3)
64{
65}
66
68 const double absRadius,
69 const ERotation orientation)
70{
71 GeneralizedCircle generalizedCircle;
73 return generalizedCircle;
74}
75
77 const Vector2D& tangential,
78 const double impact)
79{
80 GeneralizedCircle generalizedCircle;
82 return generalizedCircle;
83}
84
86 const double tangentialPhi,
87 const double impact)
88{
89 GeneralizedCircle generalizedCircle;
91 return generalizedCircle;
92}
93
95 const double absRadius,
96 const ERotation orientation)
97{
98 double curvature = static_cast<double>(orientation) / fabs(absRadius);
100 setN1(-center.x() * curvature);
101 setN2(-center.y() * curvature);
102 setN3(curvature / 2.0);
103 normalize(); // the call to normalize should be superfluous
104}
105
106void GeneralizedCircle::setPerigeeParameters(const double curvature,
107 const Vector2D& tangential,
108 const double impact)
109{
110 double n0 = impact * (impact * curvature / 2.0 + 1.0);
112 double n3 = curvature / 2.0;
113 setN(n0, n12, n3);
114}
115
117{
118 if (fastDistance(point) == 0) return point;
119
120 // solve the minimization | point - pointOnCirlce | ^2 subjected to the on circle constraint
121 // 1.0 * m_n0 +
122 // point.x() * m_n1 +
123 // point.y() * m_n2 +
124 // point.cylindricalRSquared() * m_n3 == 0
125 // solved with a Lagrangian multiplicator for the constraint
126
127 Vector2D gradientAtPoint = gradient(point);
128 Vector2D coordinateSystem = gradientAtPoint.unit();
129
130 // component of closest approach orthogonal to coordinateSystem
131 double closestOrthogonal = n12().cross(point) / gradientAtPoint.norm();
132
133 // component of closest approach parallel to coordinateSystem - two solutions expected
134 double nOrthogonal = n12().unnormalizedOrthogonalComp(coordinateSystem);
135 double nParallel = n12().unnormalizedParallelComp(coordinateSystem);
136
137 double closestParallel = 0.0;
138 if (isLine()) {
139 closestParallel = -(nOrthogonal * closestOrthogonal + n0()) / nParallel;
140
141 } else {
142 const double a = n3();
143 const double b = nParallel;
144 const double c = n0() + (nOrthogonal + n3() * closestOrthogonal) * closestOrthogonal;
145
146 const std::pair<double, double> closestParallel12 = solveQuadraticABC(a, b, c);
147
148 // take the solution with smaller distance to point
149 const double pointParallel = point.unnormalizedParallelComp(coordinateSystem);
150
151 const double criterion1 =
152 closestParallel12.first * (closestParallel12.first - 2 * pointParallel);
153 const double criterion2 =
154 closestParallel12.second * (closestParallel12.second - 2 * pointParallel);
155
156 closestParallel = criterion1 < criterion2 ? closestParallel12.first : closestParallel12.second;
157 }
158 return Vector2D::compose(coordinateSystem, closestParallel, closestOrthogonal);
159}
160
162{
163 Vector2D result(n12());
164 result.setCylindricalR(-impact());
165 return result;
166}
167
169{
170 Vector2D result(n12());
171 result.setCylindricalR(-impact() - 2 * radius());
172 return result;
173}
174
176 const Vector2D& end1,
177 const Vector2D& end2) const
178{
179 double lengthOnCurve1 = arcLengthBetween(start, end1);
180 double lengthOnCurve2 = arcLengthBetween(start, end2);
181
182 if (lengthOnCurve1 >= 0.0) {
183
184 if (lengthOnCurve2 >= 0.0) {
185 return lengthOnCurve1 < lengthOnCurve2 ? end1 : end2;
186 } else {
187 return end1;
188 }
189 } else {
190
191 if (lengthOnCurve2 >= 0.0) {
192 return end2;
193 } else {
194
195 // both lengths on curve have a negative sign
196 // the candidate with the lesser length on curve wins because of the discontinuaty
197 // unless the generalized circle is a line
198 // in this case their is no forward intersection with the same cylindrical radius
199 if (isLine()) {
200 return Vector2D(NAN, NAN);
201 } else {
202 return lengthOnCurve1 < lengthOnCurve2 ? end1 : end2;
203 }
204 }
205 }
206 return Vector2D(NAN, NAN); // just avoid a compiler warning
207}
208
209std::pair<Vector2D, Vector2D> GeneralizedCircle::atCylindricalR(const double cylindricalR) const
210{
211 // extraploted to r
212 // solve
213 // n0 + n1*x + n2*y + n3*r*r == 0
214 // and r = cylindricalR
215 // search for x and y
216
217 // solve the equation in a coordinate system parallel and orthogonal to the reduced circle center
218 const Vector2D nUnit = n12().unit();
219
220 // parallel component
221 const double sameCylindricalRParallel = -(n0() + n3() * square(cylindricalR)) / n12().norm();
222
223 // orthogonal component
224 const double sameCylindricalROrthogonal = sqrt(square(cylindricalR) - square(sameCylindricalRParallel));
225
227 Vector2D sameCylindricalR1 =
228 Vector2D::compose(nUnit, sameCylindricalRParallel, -sameCylindricalROrthogonal);
229
230 Vector2D sameCylindricalR2 =
231 Vector2D::compose(nUnit, sameCylindricalRParallel, sameCylindricalROrthogonal);
232
233 std::pair<Vector2D, Vector2D> result(sameCylindricalR1, sameCylindricalR2);
234 return result;
235}
236
238 const double cylindricalR) const
239{
240 std::pair<Vector2D, Vector2D> candidatePoints = atCylindricalR(cylindricalR);
241 return chooseNextForwardOf(startPoint, candidatePoints.first, candidatePoints.second);
242}
243
244double GeneralizedCircle::arcLengthBetween(const Vector2D& from, const Vector2D& to) const
245{
246 EForwardBackward lengthSign = isForwardOrBackwardOf(from, to);
247 if (not NForwardBackward::isValid(lengthSign)) return NAN;
248
249 // Handling the rare case that from and to correspond to opposing points on the circle
250 if (lengthSign == EForwardBackward::c_Unknown) lengthSign = EForwardBackward::c_Forward;
251
252 Vector2D closestAtFrom = closest(from);
253 Vector2D closestAtTo = closest(to);
254 double directDistance = closestAtFrom.distance(closestAtTo);
255
256 return static_cast<double>(lengthSign) * arcLengthFactor(directDistance) * directDistance;
257}
258
260{
261 const Vector2D from = perigee();
262
263 EForwardBackward lengthSign = isForwardOrBackwardOf(from, to);
264 if (not NForwardBackward::isValid(lengthSign)) return NAN;
265
266 // Handling the rare case that from and to correspond to opposing points on the circle
267 if (lengthSign == EForwardBackward::c_Unknown) lengthSign = EForwardBackward::c_Forward;
268
269 const Vector2D& closestAtFrom = from;
270 Vector2D closestAtTo = closest(to);
271 double directDistance = closestAtFrom.distance(closestAtTo);
272
273 return static_cast<double>(lengthSign) * arcLengthFactor(directDistance) * directDistance;
274}
275
276double GeneralizedCircle::arcLengthToCylindricalR(const double cylindricalR) const
277{
278 // Slight trick here
279 // Since the sought point is on the helix we treat it as the perigee
280 // and the origin as the point to extrapolate to.
281 // We know the distance of the origin to the circle, which is just d0
282 // The direct distance from the origin to the imaginary perigee is just the given cylindricalR.
283 const double dr = d0();
284 const double directDistance =
285 sqrt((cylindricalR + dr) * (cylindricalR - dr) / (1 + dr * omega()));
286 const double arcLength = arcLengthFactor(directDistance) * directDistance;
287 return arcLength;
288}
289
290double GeneralizedCircle::arcLengthFactor(const double directDistance, const double curvature)
291{
292 double x = directDistance * curvature / 2.0;
293 return asinc(x);
294}
295
296double GeneralizedCircle::distance(const Vector2D& point) const
297{
298 const double fastD = fastDistance(point);
299 return distance(fastD);
300}
301
302double GeneralizedCircle::distance(const double fastDistance) const
303{
304 if (fastDistance == 0.0 or isLine()) {
305 // special case for unfitted state
306 // and line
307 return fastDistance;
308 } else {
309
310 const double a = n3();
311 const double b = 1;
312 const double c = -fastDistance;
313
314 std::pair<double, double> distance12 = solveQuadraticABC(a, b, c);
315
316 // take the small solution which has always the same sign of the fastDistance
317 return distance12.second;
318 }
319}
320
321std::pair<Vector2D, Vector2D>
323{
324 const double m0 = generalizedCircle.n0();
325 const Vector2D& m12 = generalizedCircle.n12();
326 const double m3 = generalizedCircle.n3();
327
328 const double n0 = this->n0();
329 const Vector2D& n12 = this->n12();
330 const double n3 = this->n3();
331
332 Vector2D unitC = n12 * m3 - m12 * n3;
333 double absC = unitC.normalize();
334
335 double xParallel = (m0 * n3 - m3 * n0) / absC;
336
337 // Use symmetric solution and use all input parameters
338 Vector2D mn12 = n12 + m12;
339 double mn12Parallel = unitC.unnormalizedParallelComp(mn12);
340 double mn12Orthogonal = unitC.unnormalizedOrthogonalComp(mn12);
341
342 double a = m3 + n3;
343 double b = mn12Orthogonal;
344 double c = (a * xParallel + mn12Parallel) * xParallel + m0 + n0;
345
346 std::pair<double, double> xOrthogonal = solveQuadraticABC(a, b, c);
347
348 return std::make_pair(Vector2D::compose(unitC, xParallel, xOrthogonal.first),
349 Vector2D::compose(unitC, xParallel, xOrthogonal.second));
350}
351
352Vector2D GeneralizedCircle::atArcLength(const double arcLength) const
353{
354 double chi = arcLength * curvature();
355 double chiHalf = chi / 2.0;
356
357 double atX = arcLength * sinc(chiHalf) * sin(chiHalf) + impact();
358 double atY = -arcLength * sinc(chi);
359 return Vector2D::compose(-n12().unit(), atX, atY);
360}
361
362std::ostream& TrackFindingCDC::operator<<(std::ostream& output, const GeneralizedCircle& circle)
363{
364 if (circle.isLine()) {
365 output << "Line support point = " << circle.perigee();
366 return output;
367 } else {
368 output << "CircleCenter = " << circle.center() << ", Radius = " << circle.absRadius();
369 return output;
370 }
371}
A two dimensional circle in its natural representation using center and radius as parameters.
Definition: Circle2D.h:26
Vector2D atArcLength(double arcLength) const
Calculates the point, which lies at the give perpendicular travel distance (counted from the perigee)
void setCenterAndRadius(const Vector2D &center, double absRadius, ERotation orientation=ERotation::c_CounterClockwise)
Setter for the circle center and radius.
Vector2D tangential() const
Gives the tangential vector at the closest approach to the origin / at the perigee.
double fastDistance(const Vector2D &point) const
Approximate distance.
bool isLine() const
Indicates if the generalized circle is actually a line.
Vector2D perigee() const
Calculates the closest approach to the two dimensional origin.
Vector2D gradient(const Vector2D &point) const
Gradient of the distance field Gives the gradient of the approximated distance field for the given po...
Vector2D atCylindricalRForwardOf(const Vector2D &startPoint, double cylindricalR) const
Approach on the circle with the given cylindrical radius that lies in the forward direction of a star...
double arcLengthBetween(const Vector2D &from, const Vector2D &to) const
Calculates the arc length between two points of closest approach on the circle.
void setPerigeeParameters(double curvature, const Vector2D &tangential, double impact)
Setter for the perigee parameters.
void setN0(const double n0)
Setter for first circle parameter.
double radius() const
Gives the signed radius of the circle. If it was a line this will be infinity.
Vector2D chooseNextForwardOf(const Vector2D &start, const Vector2D &end1, const Vector2D &end2) const
Returns the end point which is first reached if one follows the forward direction of the circle start...
const Vector2D & n12() const
Getter for the second and third circle parameter which natuarally from a vector.
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 setN2(const double n2)
Setter for third circle parameter.
Vector2D apogee() const
Calculates the point on the circle that is furthest away from the origin.
double omega() const
Gives the omega parameter as used by the framework helix.
void setN3(const double n3)
Setter for fourth circle parameter.
void setN1(const double n1)
Setter for second circle parameter.
EForwardBackward isForwardOrBackwardOf(const Vector2D &from, const Vector2D &to) const
Calculates if the to vector is closer to the from vector following the along orientation of the circl...
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.
GeneralizedCircle()
Default constructor for ROOT compatibility.
double n3() const
Getter for the fourth circle parameter.
static GeneralizedCircle fromCenterAndRadius(const Vector2D &center, double absRadius, ERotation orientation=ERotation::c_CounterClockwise)
Constructor from center, radius and a optional orientation.
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.
double d0() const
Getter for the absolute distance to the z axes at the support point.
double absRadius() const
Gives the signed radius of the circle. If it was a line this will be infinity.
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.
void normalize()
Normalizes the circle parameters.
double tangentialPhi() const
Gives to azimuth angle phi of the direction of flight at the perigee.
double n0() const
Getter for the first circle parameter.
void setN(const double n0, const double n1, const double n2, const double n3=0.0)
Setter for all four circle parameters.
ERotation orientation() const
Gives the orientation of the circle.
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.
A two dimensional normal line.
Definition: Line2D.h:37
A two dimensional vector which is equipped with functions for correct handling of orientation relate...
Definition: Vector2D.h:32
double normalize()
Normalizes the vector to unit length.
Definition: Vector2D.h:303
static Vector2D compose(const Vector2D &coordinateVec, const double parallelCoor, const double orthoCoor)
Constructs a vector from a unit coordinate system vector and the coordinates in that system.
Definition: Vector2D.h:74
double distance(const Vector2D &rhs=Vector2D(0.0, 0.0)) const
Calculates the distance of this point to the rhs.
Definition: Vector2D.h:204
double unnormalizedParallelComp(const Vector2D &relativTo) const
Same as parallelComp() but assumes the given vector to be of unit length.
Definition: Vector2D.h:425
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
double second() const
Getter for the second coordinate.
Definition: Vector2D.h:639
double normSquared() const
Calculates .
Definition: Vector2D.h:169
Vector2D orthogonal() const
Orthogonal vector to the counterclockwise direction.
Definition: Vector2D.h:289
double y() const
Getter for the y coordinate.
Definition: Vector2D.h:605
double first() const
Getter for the first coordinate.
Definition: Vector2D.h:629
Vector2D unit() const
Returns a unit vector colaligned with this.
Definition: Vector2D.h:321
double norm() const
Calculates the length of the vector.
Definition: Vector2D.h:175
double unnormalizedOrthogonalComp(const Vector2D &relativTo) const
Same as orthogonalComp() but assumes the given vector to be of unit length.
Definition: Vector2D.h:446
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
bool isValid(EForwardBackward eForwardBackward)
Check whether the given enum instance is one of the valid values.
EForwardBackward
Enumeration to represent the distinct possibilities of the right left passage information.
ERotation
Enumeration to represent the distinct possibilities of the right left passage information.
Definition: ERotation.h:25
Abstract base class for different kinds of events.