@@ -59,7 +59,7 @@ struct CrossInfo {
5959 float yDCA[2 ] = {};
6060 int nDCA = 0 ;
6161
62- int circlesCrossInfo (const TrackAuxPar& trax0, const TrackAuxPar& trax1, float maxDistXY = MaxDistXYDef)
62+ int circlesCrossInfo (const TrackAuxPar& trax0, const TrackAuxPar& trax1, float maxDistXY = MaxDistXYDef, bool isCollinear = false )
6363 {
6464 const auto & trcA = trax0.rC > trax1.rC ? trax0 : trax1; // designate the largest circle as A
6565 const auto & trcB = trax0.rC > trax1.rC ? trax1 : trax0;
@@ -74,14 +74,24 @@ struct CrossInfo {
7474 if (dist - rsum > maxDistXY) { // too large distance
7575 return nDCA;
7676 }
77- notTouchingXY (dist, xDist, yDist, trcA, trcB.rC );
77+ notTouchingXY (dist, xDist, yDist, trcA, trcB.rC , isCollinear );
7878 } else if (dist + trcB.rC < trcA.rC ) { // the small circle is nestled into large one w/o touching
7979 // select the point of closest approach of 2 circles
80- notTouchingXY (dist, xDist, yDist, trcA, -trcB.rC );
80+ notTouchingXY (dist, xDist, yDist, trcA, -trcB.rC , isCollinear );
8181 } else { // 2 intersection points
82- // to simplify calculations, we move to new frame x->x+Xc0, y->y+Yc0, so that
83- // the 1st one is centered in origin
84- if (std::abs (xDist) < std::abs (yDist)) {
82+ if (isCollinear) {
83+ // / collinear tracks, e.g. electrons from photon conversion
84+ // / if there are 2 crossings of the circle it is better to take
85+ // / a weighted average of the crossing points as a radius
86+ float r2r = trcA.rC + trcB.rC ;
87+ float r1_r = trcA.rC / r2r;
88+ float r2_r = trcB.rC / r2r;
89+ xDCA[0 ] = r2_r * trcA.xC + r1_r * trcB.xC ;
90+ yDCA[0 ] = r2_r * trcA.yC + r1_r * trcB.yC ;
91+ nDCA = 1 ;
92+ } else if (std::abs (xDist) < std::abs (yDist)) {
93+ // to simplify calculations, we move to new frame x->x+Xc0, y->y+Yc0, so that
94+ // the 1st one is centered in origin
8595 float a = (trcA.rC * trcA.rC - trcB.rC * trcB.rC + dist2) / (2 . * yDist), b = -xDist / yDist, ab = a * b, bb = b * b;
8696 float det = ab * ab - (1 . + bb) * (a * a - trcA.rC * trcA.rC );
8797 if (det > 0 .) {
@@ -116,18 +126,28 @@ struct CrossInfo {
116126 return nDCA;
117127 }
118128
119- void notTouchingXY (float dist, float xDist, float yDist, const TrackAuxPar& trcA, float rBSign)
129+ void notTouchingXY (float dist, float xDist, float yDist, const TrackAuxPar& trcA, float rBSign, bool isCollinear = false )
120130 {
121- // fast method to calculate DCA between 2 circles, assuming that they don't touch each outer:
122- // the parametric equation of lines connecting the centers is x = xA + t/dist * xDist, y = yA + t/dist * yDist
123- // with xA,yY being the center of the circle A ( = trcA.xC, trcA.yC ), xDist = trcB.xC = trcA.xC ...
124- // There are 2 special cases:
125- // (a) small circle is inside the large one: provide rBSign as -trcB.rC
126- // (b) circle are side by side: provide rBSign as trcB.rC
131+ if (isCollinear) {
132+ // / for collinear tracks it is better to take
133+ // / a weighted average of the crossing points as a radius
134+ float r2r = trcA.rC + std::abs (rBSign);
135+ float r1_r = trcA.rC / r2r;
136+ float r2_r = std::abs (rBSign) / r2r;
137+ xDCA[0 ] = r2_r * trcA.xC + r1_r * (xDist + trcA.xC );
138+ yDCA[0 ] = r2_r * trcA.yC + r1_r * (yDist + trcA.yC );
139+ } else {
140+ // fast method to calculate DCA between 2 circles, assuming that they don't touch each outer:
141+ // the parametric equation of lines connecting the centers is x = xA + t/dist * xDist, y = yA + t/dist * yDist
142+ // with xA,yY being the center of the circle A ( = trcA.xC, trcA.yC ), xDist = trcB.xC = trcA.xC ...
143+ // There are 2 special cases:
144+ // (a) small circle is inside the large one: provide rBSign as -trcB.rC
145+ // (b) circle are side by side: provide rBSign as trcB.rC
146+ auto t2d = (dist + trcA.rC - rBSign) / dist;
147+ xDCA[0 ] = trcA.xC + 0.5 * (xDist * t2d);
148+ yDCA[0 ] = trcA.yC + 0.5 * (yDist * t2d);
149+ }
127150 nDCA = 1 ;
128- auto t2d = (dist + trcA.rC - rBSign) / dist;
129- xDCA[0 ] = trcA.xC + 0.5 * (xDist * t2d);
130- yDCA[0 ] = trcA.yC + 0.5 * (yDist * t2d);
131151 }
132152
133153 template <typename T>
@@ -251,12 +271,12 @@ struct CrossInfo {
251271 }
252272
253273 template <typename T>
254- int set (const TrackAuxPar& trax0, const T& tr0, const TrackAuxPar& trax1, const T& tr1, float maxDistXY = MaxDistXYDef)
274+ int set (const TrackAuxPar& trax0, const T& tr0, const TrackAuxPar& trax1, const T& tr1, float maxDistXY = MaxDistXYDef, bool isCollinear = false )
255275 {
256276 // calculate up to 2 crossings between 2 circles
257277 nDCA = 0 ;
258278 if (trax0.rC > o2::constants::math::Almost0 && trax1.rC > o2::constants::math::Almost0) { // both are not straight lines
259- nDCA = circlesCrossInfo (trax0, trax1, maxDistXY);
279+ nDCA = circlesCrossInfo (trax0, trax1, maxDistXY, isCollinear );
260280 } else if (trax0.rC < o2::constants::math::Almost0 && trax1.rC < o2::constants::math::Almost0) { // both are straigt lines
261281 nDCA = linesCrossInfo (trax0, tr0, trax1, tr1, maxDistXY);
262282 } else {
@@ -269,9 +289,9 @@ struct CrossInfo {
269289 CrossInfo () = default ;
270290
271291 template <typename T>
272- CrossInfo (const TrackAuxPar& trax0, const T& tr0, const TrackAuxPar& trax1, const T& tr1, float maxDistXY = MaxDistXYDef)
292+ CrossInfo (const TrackAuxPar& trax0, const T& tr0, const TrackAuxPar& trax1, const T& tr1, float maxDistXY = MaxDistXYDef, bool isCollinear = false )
273293 {
274- set (trax0, tr0, trax1, tr1, maxDistXY);
294+ set (trax0, tr0, trax1, tr1, maxDistXY, isCollinear );
275295 }
276296 ClassDefNV (CrossInfo, 1 );
277297};
0 commit comments