Belle II Software  release-08-01-10
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 
23 using namespace Belle2;
24 using 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 
44 GeneralizedCircle::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;
72  generalizedCircle.setCenterAndRadius(center, absRadius, orientation);
73  return generalizedCircle;
74 }
75 
77  const Vector2D& tangential,
78  const double impact)
79 {
80  GeneralizedCircle generalizedCircle;
81  generalizedCircle.setPerigeeParameters(curvature, tangential, impact);
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 
106 void 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 minization | 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 muliplicator 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 
209 std::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 
244 double 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 
276 double 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 
290 double GeneralizedCircle::arcLengthFactor(const double directDistance, const double curvature)
291 {
292  double x = directDistance * curvature / 2.0;
293  return asinc(x);
294 }
295 
296 double GeneralizedCircle::distance(const Vector2D& point) const
297 {
298  const double fastD = fastDistance(point);
299  return distance(fastD);
300 }
301 
302 double 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 
321 std::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 
352 Vector2D 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 
362 std::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)
const Vector2D & n12() const
Getter for the second and third circle parameter which natuarally from a vector.
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...
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 handeling of orientation relat...
Definition: Vector2D.h:35
double normalize()
Normalizes the vector to unit length.
Definition: Vector2D.h:315
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:83
double distance(const Vector2D &rhs=Vector2D(0.0, 0.0)) const
Calculates the distance of this point to the rhs.
Definition: Vector2D.h:216
double unnormalizedParallelComp(const Vector2D &relativTo) const
Same as parallelComp() but assumes the given vector to be of unit length.
Definition: Vector2D.h:437
double cross(const Vector2D &rhs) const
Calculated the two dimensional cross product.
Definition: Vector2D.h:175
double x() const
Getter for the x coordinate.
Definition: Vector2D.h:607
double second() const
Getter for the second coordinate.
Definition: Vector2D.h:651
double normSquared() const
Calculates .
Definition: Vector2D.h:181
Vector2D orthogonal() const
Orthogonal vector to the counterclockwise direction.
Definition: Vector2D.h:301
double y() const
Getter for the y coordinate.
Definition: Vector2D.h:617
double first() const
Getter for the first coordinate.
Definition: Vector2D.h:641
Vector2D unit() const
Returns a unit vector colaligned with this.
Definition: Vector2D.h:333
double norm() const
Calculates the length of the vector.
Definition: Vector2D.h:187
double unnormalizedOrthogonalComp(const Vector2D &relativTo) const
Same as orthogonalComp() but assumes the given vector to be of unit length.
Definition: Vector2D.h:458
std::ostream & operator<<(std::ostream &output, const IntervalOfValidity &iov)
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.