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