Belle II Software development
PerigeeCircle.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/PerigeeCircle.h>
9
10#include <tracking/trackingUtilities/geometry/PerigeeParameters.h>
11
12#include <tracking/trackingUtilities/geometry/Circle2D.h>
13
14#include <tracking/trackingUtilities/numerics/EForwardBackward.h>
15#include <tracking/trackingUtilities/numerics/ERotation.h>
16#include <tracking/trackingUtilities/numerics/Quadratic.h>
17#include <tracking/trackingUtilities/numerics/SpecialFunctions.h>
18#include <tracking/trackingUtilities/numerics/Angle.h>
19
20#include <ostream>
21#include <utility>
22#include <cmath>
23
24namespace Belle2 {
29 namespace TrackingUtilities {
31 class Line2D;
32 }
34}
35
36using namespace Belle2;
37using namespace TrackingUtilities;
38
39
40
45
46PerigeeCircle::PerigeeCircle(double curvature, const ROOT::Math::XYVector& phi0Vec, double impact)
48 , m_phi0(phi0Vec.Phi())
51{
52}
53
56 , m_phi0(phi0)
57 , m_phi0Vec(VectorUtil::Phi(phi0))
59{
60}
61
63 : PerigeeCircle(perigeeParameters(EPerigeeParameter::c_Curv),
64 perigeeParameters(EPerigeeParameter::c_Phi0),
65 perigeeParameters(EPerigeeParameter::c_I))
66{
67}
68
69PerigeeCircle::PerigeeCircle(double curvature, double phi0, const ROOT::Math::XYVector& phi0Vec, double impact)
71 , m_phi0(phi0)
74{
76}
77
79{
80 setN(n012);
81}
82
84{
85 setN(n0123);
86}
87
89{
90 setCenterAndRadius(circle.center(), circle.absRadius(), circle.orientation());
91}
92
93PerigeeCircle PerigeeCircle::fromN(double n0, double n1, double n2, double n3)
94{
95 PerigeeCircle circle;
96 circle.setN(n0, n1, n2, n3);
97 return circle;
98}
99
100PerigeeCircle PerigeeCircle::fromN(double n0, const ROOT::Math::XYVector& n12, double n3)
101{
102 PerigeeCircle circle;
103 circle.setN(n0, n12, n3);
104 return circle;
105}
106
108PerigeeCircle::fromCenterAndRadius(const ROOT::Math::XYVector& center, double absRadius, ERotation orientation)
109{
110 PerigeeCircle circle;
112 return circle;
113}
114
115ROOT::Math::XYVector PerigeeCircle::atArcLength(double arcLength) const
116{
117 double chi = arcLength * curvature();
118 double chiHalf = chi / 2.0;
119
120 double atX = arcLength * sinc(chi);
121 double atY = arcLength * sinc(chiHalf) * sin(chiHalf) + impact();
122 return VectorUtil::compose(phi0Vec(), atX, atY);
123}
124
132
137
139{
140 double denominator = 2 + curvature() * impact();
141 std::swap(m_impact, m_curvature);
142 m_curvature *= denominator;
143 m_impact /= denominator;
144 // Also properly fixing the orientation to the opposite.
145 reverse();
146}
147
149{
150 double denominator = 2 + curvature() * impact();
151 // Properly fixing the orientation to the opposite by the minus signs
152 double newCurvature = -impact() * denominator;
153 double newPhi0 = AngleUtil::reversed(phi0());
154 ROOT::Math::XYVector newPhi0Vec = -phi0Vec();
155 double newImpact = -curvature() / denominator;
156 return PerigeeCircle(newCurvature, newPhi0, newPhi0Vec, newImpact);
157}
158
160{
161 m_curvature = 0.0;
162 m_phi0 = NAN;
163 m_phi0Vec = ROOT::Math::XYVector(0.0, 0.0);
164 m_impact = 0;
165}
166
168{
169 return (not std::isfinite(phi0()) or not std::isfinite(curvature()) or
170 not std::isfinite(impact()) or VectorUtil::isNull(phi0Vec()));
171}
172
173void PerigeeCircle::passiveMoveBy(const ROOT::Math::XYVector& by)
174{
175 double arcLength = arcLengthTo(by);
176 m_impact = distance(by);
177 m_phi0 = m_phi0 + curvature() * arcLength;
179 m_phi0Vec = VectorUtil::Phi(m_phi0);
180}
181
182PerigeeJacobian PerigeeCircle::passiveMoveByJacobian(const ROOT::Math::XYVector& by) const
183{
184 PerigeeJacobian jacobian = PerigeeUtil::identity();
185 passiveMoveByJacobian(by, jacobian);
186 return jacobian;
187}
188
189void PerigeeCircle::passiveMoveByJacobian(const ROOT::Math::XYVector& by, PerigeeJacobian& jacobian) const
190{
191 ROOT::Math::XYVector deltaVec = by - perigee();
192 double delta = deltaVec.R();
193 double deltaParallel = phi0Vec().Dot(deltaVec);
194 // double deltaOrthogonal = VectorUtil::Cross(phi0Vec(), deltaVec);
195 // double zeta = deltaVec.Mag2();
196
197 ROOT::Math::XYVector UVec = gradient(by);
198 double U = UVec.R();
199 double USquared = UVec.Mag2();
200 double UOrthogonal = VectorUtil::Cross(phi0Vec(), UVec);
201 // double UParallel = phi0Vec().Dot(UVec);
202
203 // ROOT::Math::XYVector CB = VectorUtil::Orthogonal(gradient(by));
204 // double U = sqrt(1 + curvature() * A);
205 // double xi = 1.0 / CB.Mag2();
206 // double nu = 1 - curvature() * deltaOrthogonal;
207 // double mu = 1.0 / (U * (U + 1)) + curvature() * lambda;
208 // double mu = 1.0 / U / 2.0;
209 // double nu = -UOrthogonal;
210 // double xi = 1 / USquared;
211
212 // double halfA = fastDistance(by);
213 // double A = 2 * halfA;
214 // double lambda = halfA / ((1 + U) * (1 + U) * U);
215 double dr = distance(by);
216
217 // ROOT::Math::XYVector uVec = gradient(ROOT::Math::XYVector(0.0, 0.0));
218 // double u = uVec.R();
219 double u = 1 + curvature() * impact(); //= n12().R()
220
221 using namespace NPerigeeParameterIndices;
222 jacobian(c_Curv, c_Curv) = 1;
223 jacobian(c_Curv, c_Phi0) = 0;
224 jacobian(c_Curv, c_I) = 0;
225
226 jacobian(c_Phi0, c_Curv) = deltaParallel / USquared;
227 jacobian(c_Phi0, c_Phi0) = -u * UOrthogonal / USquared;
228 jacobian(c_Phi0, c_I) = -curvature() * curvature() * deltaParallel / USquared;
229
230 jacobian(c_I, c_Curv) = (delta - dr) * (delta + dr) / U / 2;
231 jacobian(c_I, c_Phi0) = u * deltaParallel / U;
232 jacobian(c_I, c_I) = -UOrthogonal / U;
233}
234
235double PerigeeCircle::arcLengthTo(const ROOT::Math::XYVector& point) const
236{
237 ROOT::Math::XYVector closestToPoint = closest(point);
238 double secantLength = VectorUtil::Distance(perigee(), closestToPoint);
239 double deltaParallel = phi0Vec().Dot(point);
240 return copysign(arcLengthAtSecantLength(secantLength), deltaParallel);
241}
242
243double PerigeeCircle::arcLengthBetween(const ROOT::Math::XYVector& from, const ROOT::Math::XYVector& to) const
244{
245 EForwardBackward lengthSign = isForwardOrBackwardOf(from, to);
246 if (not NForwardBackward::isValid(lengthSign)) return NAN;
247 // Handling the rare case that from and to correspond to opposing points on the circle
248 if (lengthSign == EForwardBackward::c_Unknown) lengthSign = EForwardBackward::c_Forward;
249 ROOT::Math::XYVector closestAtFrom = closest(from);
250 ROOT::Math::XYVector closestAtTo = closest(to);
251 double secantLength = VectorUtil::Distance(closestAtFrom, closestAtTo);
252 return static_cast<double>(lengthSign) * arcLengthAtSecantLength(secantLength);
253}
254
255double PerigeeCircle::arcLengthToCylindricalR(double cylindricalR) const
256{
257 // Slight trick here
258 // Since the sought point is on the helix we treat it as the perigee
259 // and the origin as the point to extrapolate to.
260 // We know the distance of the origin to the circle, which is just d0
261 // The direct distance from the origin to the imaginary perigee is just the given cylindricalR.
262 return arcLengthAtDeltaLength(cylindricalR, impact());
263}
264
265double PerigeeCircle::arcLengthAtDeltaLength(double delta, double dr) const
266{
267 const double secantLength = sqrt((delta + dr) * (delta - dr) / (1 + dr * curvature()));
268 const double arcLength = arcLengthAtSecantLength(secantLength);
269 return arcLength;
270}
271
272double PerigeeCircle::arcLengthAtSecantLength(double secantLength) const
273{
274 double x = secantLength * curvature() / 2.0;
275 double arcLengthFactor = asinc(x);
276 return secantLength * arcLengthFactor;
277}
278
279std::pair<ROOT::Math::XYVector, ROOT::Math::XYVector> PerigeeCircle::atCylindricalR(const double cylindricalR) const
280{
281 const double u = (1 + curvature() * impact());
282 const double orthogonal = ((square(impact()) + square(cylindricalR)) * curvature() / 2.0 + impact()) / u;
283 const double parallel = sqrt(square(cylindricalR) - square(orthogonal));
284 ROOT::Math::XYVector atCylindricalR1 = VectorUtil::compose(phi0Vec(), -parallel, orthogonal);
285 ROOT::Math::XYVector atCylindricalR2 = VectorUtil::compose(phi0Vec(), parallel, orthogonal);
286 std::pair<ROOT::Math::XYVector, ROOT::Math::XYVector> result(atCylindricalR1, atCylindricalR2);
287 return result;
288}
289
290ROOT::Math::XYVector PerigeeCircle::atCylindricalRForwardOf(const ROOT::Math::XYVector& startPoint,
291 const double cylindricalR) const
292{
293 std::pair<ROOT::Math::XYVector, ROOT::Math::XYVector> candidatePoints = atCylindricalR(cylindricalR);
294 return chooseNextForwardOf(startPoint, candidatePoints.first, candidatePoints.second);
295}
296
297ROOT::Math::XYVector PerigeeCircle::chooseNextForwardOf(const ROOT::Math::XYVector& start,
298 const ROOT::Math::XYVector& end1,
299 const ROOT::Math::XYVector& end2) const
300{
301 double arcLength1 = arcLengthBetween(start, end1);
302 double arcLength2 = arcLengthBetween(start, end2);
303 if (arcLength1 < 0) arcLength1 += arcLengthPeriod();
304 if (arcLength2 < 0) arcLength2 += arcLengthPeriod();
305 if (fmin(arcLength1, arcLength2) == arcLength1) {
306 return end1;
307 } else if (fmin(arcLength1, arcLength2) == arcLength2) {
308 return end2;
309 } else {
310 return ROOT::Math::XYVector(NAN, NAN);
311 }
312}
313
314ROOT::Math::XYVector PerigeeCircle::closest(const ROOT::Math::XYVector& point) const
315{
316 return point - normal(point) * distance(point);
317}
318
320{
321 double A = 2 * fastDistance;
322 double U = std::sqrt(1 + A * curvature());
323 return A / (1.0 + U);
324}
325
326double PerigeeCircle::fastDistance(const ROOT::Math::XYVector& point) const
327{
328 ROOT::Math::XYVector delta = point - perigee();
329 double deltaOrthogonal = VectorUtil::Cross(phi0Vec(), delta);
330 return -deltaOrthogonal + curvature() * delta.Mag2() / 2;
331}
332
333void PerigeeCircle::setCenterAndRadius(const ROOT::Math::XYVector& center,
334 double absRadius,
335 ERotation orientation)
336{
337 m_curvature = static_cast<double>(orientation) / std::fabs(absRadius);
338 m_phi0Vec = VectorUtil::Orthogonal(center, NRotation::reversed(orientation));
339 if (m_phi0Vec.R() != 0.0) {
340 m_phi0Vec *= (1. / m_phi0Vec.R());
341 }
342 m_phi0 = m_phi0Vec.Phi();
343 m_impact = (center.R() - std::fabs(absRadius)) * static_cast<double>(orientation);
344}
345
346void PerigeeCircle::setN(double n0, const ROOT::Math::XYVector& n12, double n3)
347{
348 double normalization = sqrt(n12.Mag2() - 4 * n0 * n3);
349 m_curvature = 2 * n3 / normalization;
350 m_phi0Vec = VectorUtil::Orthogonal(n12);
351 if (m_phi0Vec.R() != 0.0) {
352 m_phi0Vec *= (1. / m_phi0Vec.R());
353 }
354 m_phi0 = m_phi0Vec.Phi();
355 m_impact = distance(n0 / normalization); // Uses the new curvature
356}
357
358std::ostream& TrackingUtilities::operator<<(std::ostream& output, const PerigeeCircle& circle)
359{
360 return output << "PerigeeCircle("
361 << "curvature=" << circle.curvature() << ","
362 << "phi0=" << circle.phi0() << ","
363 << "impact=" << circle.impact() << ")";
364}
A two dimensional circle in its natural representation using center and radius as parameters.
Definition Circle2D.h:32
double absRadius() const
Getter for the absolute radius.
Definition Circle2D.h:219
ROOT::Math::XYVector center() const
Getter for the central point of the circle.
Definition Circle2D.h:231
ERotation orientation() const
Indicates if the circle is to be interpreted counterclockwise or clockwise.
Definition Circle2D.h:225
A two dimensional normal line.
Definition Line2D.h:39
Extension of the generalized circle also caching the perigee coordinates.
PerigeeCircle reversed() const
Returns a copy of the circle with opposite orientation.
static PerigeeCircle fromCenterAndRadius(const ROOT::Math::XYVector &center, double absRadius, ERotation orientation=ERotation::c_CounterClockwise)
Constructor from center, radius and a optional orientation.
double m_phi0
Memory for the azimuth angle of the direction of flight at the perigee.
double n1() const
Getter for the generalised circle parameters n1.
double arcLengthTo(const ROOT::Math::XYVector &point) const
Calculates the arc length between the perigee and the given point.
ROOT::Math::XYVector gradient(const ROOT::Math::XYVector &point) const
Gradient of the distance field, hence indicates the direction of increasing distance.
double phi0() const
Getter for the azimuth angle of the direction of flight at the perigee.
double fastDistance(const ROOT::Math::XYVector &point) const
Getter for the linearised distance measure to a point.
bool isInvalid() const
Indicates if all circle parameters are zero.
void reverse()
Flips the orientation of the circle in place.
double arcLengthBetween(const ROOT::Math::XYVector &from, const ROOT::Math::XYVector &to) const
Calculates the arc length between two points of closest approach on the circle.
void setCenterAndRadius(const ROOT::Math::XYVector &center, double absRadius, ERotation orientation=ERotation::c_CounterClockwise)
Setter for the circle center and radius.
ROOT::Math::XYVector closest(const ROOT::Math::XYVector &point) const
Calculates the point of closest approach on the circle to the given point.
EForwardBackward isForwardOrBackwardOf(const ROOT::Math::XYVector &from, const ROOT::Math::XYVector &to) const
Indicates whether to given point lies in the forward direction from the perigee.
ROOT::Math::XYVector normal(const ROOT::Math::XYVector &point) const
Unit normal vector from the circle to the given point.
double impact() const
Getter for the signed distance of the origin to the circle.
double distance(const ROOT::Math::XYVector &point) const
Getter for the proper signed distance of the point to the circle.
double arcLengthAtDeltaLength(double delta, double dr) const
Helper method to calculate the arc length to a point at distance delta to the perigee and dr to circl...
double n3() const
Getter for the generalised circle parameter n3.
void invalidate()
Sets all circle parameters to zero.
ROOT::Math::XYVector perigee() const
Getter for the perigee point.
PerigeeParameters perigeeParameters() const
Getter for the three perigee parameters in the order defined by EPerigeeParameter....
void passiveMoveBy(const ROOT::Math::XYVector &by)
Moves the coordinates system by the given vector. Updates perigee parameters in place.
void conformalTransform()
Transforms the generalized circle to conformal space inplace.
double m_impact
Memory for the signed impact parameter.
double n2() const
Getter for the generalised circle parameters n2.
PerigeeJacobian passiveMoveByJacobian(const ROOT::Math::XYVector &by) const
Computes the Jacobi matrix for a move of the coordinate system by the given vector.
PerigeeCircle()
Default constructor for ROOT compatibility.
ROOT::Math::XYVector chooseNextForwardOf(const ROOT::Math::XYVector &start, const ROOT::Math::XYVector &end1, const ROOT::Math::XYVector &end2) const
Returns the one of two end point which is first reached from the given start if one strictly follows ...
ROOT::Math::XYVector atArcLength(double arcLength) const
Calculates the point, which lies at the give perpendicular travel distance (counted from the perigee)
double m_curvature
Memory for the signed curvature.
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.
double absRadius() const
Gives the signed radius of the circle. If it was a line this will be infinity.
std::pair< ROOT::Math::XYVector, ROOT::Math::XYVector > atCylindricalR(double cylindricalR) const
Calculates the two points with the given cylindrical radius on the generalised circle.
double arcLengthAtSecantLength(double secantLength) const
Helper method to calculate the arc length between to points on the circle from a given direct secant ...
PerigeeCircle conformalTransformed() const
Returns a copy of the circle in conformal space.
ROOT::Math::XYVector atCylindricalRForwardOf(const ROOT::Math::XYVector &startPoint, double cylindricalR) const
Approach on the circle with the given cylindrical radius that lies in the forward direction of a star...
ROOT::Math::XYVector center() const
Getter for the center of the circle. If it was a line both components will be infinity.
const ROOT::Math::XYVector & phi0Vec() const
Getter for the unit vector of the direction of flight at the perigee.
ROOT::Math::XYVector n12() const
Getter for the generalised circle parameters n1 and n2.
double n0() const
Getter for the generalised circle parameter n0.
ROOT::Math::XYVector m_phi0Vec
Cached unit direction of flight at the perigee.
static PerigeeCircle fromN(double n0, double n1, double n2, double n3=0)
Constructor with the four parameters of the generalized circle.
ERotation orientation() const
Getter for the orientation of the circle.
double arcLengthPeriod() const
Getter for the arc length for a full round 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...
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.
Namespace to hide the contained enum constants.
ERotation reversed(ERotation eRotation)
Return the reversed rotation. Leaves ERotation::c_Invalid the same.
Definition ERotation.h:41
Abstract base class for different kinds of events.
static void normalise(double &angle)
Normalise an angle inplace to lie in the range from [-pi, pi].
Definition Angle.h:41
static double reversed(const double angle)
Get the angle that point in the opposite direction.
Definition Angle.h:54