Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/solids/specific/src/G4IntersectingCone.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /geometry/solids/specific/src/G4IntersectingCone.cc (Version 11.3.0) and /geometry/solids/specific/src/G4IntersectingCone.cc (Version 11.2.2)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
 26 // Implementation of G4IntersectingCone, a uti     26 // Implementation of G4IntersectingCone, a utility class which calculates
 27 // the intersection of an arbitrary line with      27 // the intersection of an arbitrary line with a fixed cone
 28 //                                                 28 //
 29 // Author: David C. Williams (davidw@scipp.ucs     29 // Author: David C. Williams (davidw@scipp.ucsc.edu)
 30 // -------------------------------------------     30 // --------------------------------------------------------------------
 31                                                    31 
 32 #include "G4IntersectingCone.hh"                   32 #include "G4IntersectingCone.hh"
 33 #include "G4GeometryTolerance.hh"                  33 #include "G4GeometryTolerance.hh"
 34                                                    34 
 35 // Constructor                                     35 // Constructor
 36 //                                                 36 //
 37 G4IntersectingCone::G4IntersectingCone( const      37 G4IntersectingCone::G4IntersectingCone( const G4double r[2],
 38                                         const      38                                         const G4double z[2] )
 39 {                                                  39 {
 40   const G4double halfCarTolerance                  40   const G4double halfCarTolerance
 41     = 0.5 * G4GeometryTolerance::GetInstance()     41     = 0.5 * G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
 42                                                    42 
 43   // What type of cone are we?                     43   // What type of cone are we?
 44   //                                               44   //
 45   type1 = (std::abs(z[1]-z[0]) > std::abs(r[1]     45   type1 = (std::abs(z[1]-z[0]) > std::abs(r[1]-r[0]));
 46                                                    46 
 47   if (type1) // tube like                          47   if (type1) // tube like
 48   {                                                48   {
 49     B = (r[1] - r[0]) / (z[1] - z[0]);             49     B = (r[1] - r[0]) / (z[1] - z[0]);
 50     A = (r[0]*z[1] - r[1]*z[0]) / (z[1] -z[0])     50     A = (r[0]*z[1] - r[1]*z[0]) / (z[1] -z[0]);
 51   }                                                51   }
 52   else // disk like                                52   else // disk like
 53   {                                                53   {
 54     B = (z[1] - z[0]) / (r[1] - r[0]);             54     B = (z[1] - z[0]) / (r[1] - r[0]);
 55     A = (z[0]*r[1] - z[1]*r[0]) / (r[1] - r[0]     55     A = (z[0]*r[1] - z[1]*r[0]) / (r[1] - r[0]);
 56   }                                                56   }
 57                                                    57 
 58   // Calculate extent                              58   // Calculate extent
 59   //                                               59   //
 60   rLo = std::min(r[0], r[1]) - halfCarToleranc     60   rLo = std::min(r[0], r[1]) - halfCarTolerance;
 61   rHi = std::max(r[0], r[1]) + halfCarToleranc     61   rHi = std::max(r[0], r[1]) + halfCarTolerance;
 62   zLo = std::min(z[0], z[1]) - halfCarToleranc     62   zLo = std::min(z[0], z[1]) - halfCarTolerance;
 63   zHi = std::max(z[0], z[1]) + halfCarToleranc     63   zHi = std::max(z[0], z[1]) + halfCarTolerance;
 64 }                                                  64 }
 65                                                    65 
 66 // Fake default constructor - sets only member     66 // Fake default constructor - sets only member data and allocates memory
 67 //                            for usage restri     67 //                            for usage restricted to object persistency.
 68 //                                                 68 //
 69 G4IntersectingCone::G4IntersectingCone( __void     69 G4IntersectingCone::G4IntersectingCone( __void__& )
 70   : zLo(0.), zHi(0.), rLo(0.), rHi(0.), A(0.),     70   : zLo(0.), zHi(0.), rLo(0.), rHi(0.), A(0.), B(0.)
 71 {                                                  71 {
 72 }                                                  72 }
 73                                                    73 
 74 // Destructor                                      74 // Destructor
 75 //                                                 75 //
 76 G4IntersectingCone::~G4IntersectingCone() = de     76 G4IntersectingCone::~G4IntersectingCone() = default;
 77                                                    77 
 78 // HitOn                                           78 // HitOn
 79 //                                                 79 //
 80 // Check r or z extent, as appropriate, to see     80 // Check r or z extent, as appropriate, to see if the point is possibly
 81 // on the cone.                                    81 // on the cone.
 82 //                                                 82 //
 83 G4bool G4IntersectingCone::HitOn( const G4doub     83 G4bool G4IntersectingCone::HitOn( const G4double r,
 84                                   const G4doub     84                                   const G4double z )
 85 {                                                  85 {
 86   //                                               86   //
 87   // Be careful! The inequalities cannot be "<     87   // Be careful! The inequalities cannot be "<=" and ">=" here without
 88   // punching a tiny hole in our shape!            88   // punching a tiny hole in our shape!
 89   //                                               89   //
 90   if (type1)                                       90   if (type1)
 91   {                                                91   {
 92     if (z < zLo || z > zHi) return false;          92     if (z < zLo || z > zHi) return false;
 93   }                                                93   }
 94   else                                             94   else
 95   {                                                95   {
 96     if (r < rLo || r > rHi) return false;          96     if (r < rLo || r > rHi) return false;
 97   }                                                97   }
 98                                                    98 
 99   return true;                                     99   return true;
100 }                                                 100 }
101                                                   101 
102 // LineHitsCone                                   102 // LineHitsCone
103 //                                                103 //
104 // Calculate the intersection of a line with o    104 // Calculate the intersection of a line with our conical surface, ignoring
105 // any phi division                               105 // any phi division
106 //                                                106 //
107 G4int G4IntersectingCone::LineHitsCone( const     107 G4int G4IntersectingCone::LineHitsCone( const G4ThreeVector& p,
108                                         const     108                                         const G4ThreeVector& v,
109                                                   109                                               G4double* s1, G4double* s2 )
110 {                                                 110 {
111   if (type1)                                      111   if (type1)
112   {                                               112   {
113     return LineHitsCone1( p, v, s1, s2 );         113     return LineHitsCone1( p, v, s1, s2 );
114   }                                               114   }
115   else                                            115   else
116   {                                               116   {
117     return LineHitsCone2( p, v, s1, s2 );         117     return LineHitsCone2( p, v, s1, s2 );
118   }                                               118   }
119 }                                                 119 }
120                                                   120 
121 // LineHitsCone1                                  121 // LineHitsCone1
122 //                                                122 //
123 // Calculate the intersections of a line with     123 // Calculate the intersections of a line with a conical surface. Only
124 // suitable if zPlane[0] != zPlane[1].            124 // suitable if zPlane[0] != zPlane[1].
125 //                                                125 //
126 // Equation of a line:                            126 // Equation of a line:
127 //                                                127 //
128 //       x = x0 + s*tx      y = y0 + s*ty         128 //       x = x0 + s*tx      y = y0 + s*ty      z = z0 + s*tz
129 //                                                129 //
130 // Equation of a conical surface:                 130 // Equation of a conical surface:
131 //                                                131 //
132 //       x**2 + y**2 = (A + B*z)**2               132 //       x**2 + y**2 = (A + B*z)**2
133 //                                                133 //
134 // Solution is quadratic:                         134 // Solution is quadratic:
135 //                                                135 //
136 //  a*s**2 + b*s + c = 0                          136 //  a*s**2 + b*s + c = 0
137 //                                                137 //
138 // where:                                         138 // where:
139 //                                                139 //
140 //  a = tx**2 + ty**2 - (B*tz)**2                 140 //  a = tx**2 + ty**2 - (B*tz)**2
141 //                                                141 //
142 //  b = 2*( px*vx + py*vy - B*(A + B*pz)*vz )     142 //  b = 2*( px*vx + py*vy - B*(A + B*pz)*vz )
143 //                                                143 //
144 //  c = x0**2 + y0**2 - (A + B*z0)**2             144 //  c = x0**2 + y0**2 - (A + B*z0)**2
145 //                                                145 //
146 // Notice, that if a < 0, this indicates that     146 // Notice, that if a < 0, this indicates that the two solutions (assuming
147 // they exist) are in opposite cones (that is,    147 // they exist) are in opposite cones (that is, given z0 = -A/B, one z < z0
148 // and the other z > z0). For our shapes, the     148 // and the other z > z0). For our shapes, the invalid solution is one
149 // which produces A + Bz < 0, or the one where    149 // which produces A + Bz < 0, or the one where Bz is smallest (most negative).
150 // Since Bz = B*s*tz, if B*tz > 0, we want the    150 // Since Bz = B*s*tz, if B*tz > 0, we want the largest s, otherwise,
151 // the smaller.                                   151 // the smaller.
152 //                                                152 //
153 // If there are two solutions on one side of t    153 // If there are two solutions on one side of the cone, we want to make
154 // sure that they are on the "correct" side, t    154 // sure that they are on the "correct" side, that is A + B*z0 + s*B*tz >= 0.
155 //                                                155 //
156 // If a = 0, we have a linear problem: s = c/b    156 // If a = 0, we have a linear problem: s = c/b, which again gives one solution.
157 // This should be rare.                           157 // This should be rare.
158 //                                                158 //
159 // For b*b - 4*a*c = 0, we also have one solut    159 // For b*b - 4*a*c = 0, we also have one solution, which is almost always
160 // a line just grazing the surface of a the co    160 // a line just grazing the surface of a the cone, which we want to ignore.
161 // However, there are two other, very rare, po    161 // However, there are two other, very rare, possibilities:
162 // a line intersecting the z axis and either:     162 // a line intersecting the z axis and either:
163 //       1. At the same angle std::atan(B) to     163 //       1. At the same angle std::atan(B) to just miss one side of the cone, or
164 //       2. Intersecting the cone apex (0,0,-A    164 //       2. Intersecting the cone apex (0,0,-A/B)
165 // We *don't* want to miss these! How do we id    165 // We *don't* want to miss these! How do we identify them? Well, since
166 // this case is rare, we can at least swallow     166 // this case is rare, we can at least swallow a little more CPU than we would
167 // normally be comfortable with. Intersection     167 // normally be comfortable with. Intersection with the z axis means
168 // x0*ty - y0*tx = 0. Case (1) means a==0, and    168 // x0*ty - y0*tx = 0. Case (1) means a==0, and we've already dealt with that
169 // above. Case (2) means a < 0.                   169 // above. Case (2) means a < 0.
170 //                                                170 //
171 // Now: x0*tx + y0*ty = 0 in terms of roundoff    171 // Now: x0*tx + y0*ty = 0 in terms of roundoff error. We can write:
172 //             Delta = x0*tx + y0*ty              172 //             Delta = x0*tx + y0*ty
173 //             b = 2*( Delta - B*(A + B*z0)*tz    173 //             b = 2*( Delta - B*(A + B*z0)*tz )
174 // For:                                           174 // For:
175 //             b*b - 4*a*c = epsilon              175 //             b*b - 4*a*c = epsilon
176 // where epsilon is small, then:                  176 // where epsilon is small, then:
177 //             Delta = epsilon/2/B                177 //             Delta = epsilon/2/B
178 //                                                178 //
179 G4int G4IntersectingCone::LineHitsCone1( const    179 G4int G4IntersectingCone::LineHitsCone1( const G4ThreeVector& p,
180                                          const    180                                          const G4ThreeVector& v,
181                                                   181                                                G4double* s1, G4double* s2 )
182 {                                                 182 {
183   static const G4double EPS = DBL_EPSILON; //     183   static const G4double EPS = DBL_EPSILON; // Precision constant,
184                                            //     184                                            // originally it was 1E-6
185   G4double x0 = p.x(), y0 = p.y(), z0 = p.z();    185   G4double x0 = p.x(), y0 = p.y(), z0 = p.z();
186   G4double tx = v.x(), ty = v.y(), tz = v.z();    186   G4double tx = v.x(), ty = v.y(), tz = v.z();
187                                                   187 
188   // Value of radical can be inaccurate due to    188   // Value of radical can be inaccurate due to loss of precision
189   // if to calculate the coefficiets a,b,c lik    189   // if to calculate the coefficiets a,b,c like the following:
190   //     G4double a = tx*tx + ty*ty - sqr(B*tz    190   //     G4double a = tx*tx + ty*ty - sqr(B*tz);
191   //     G4double b = 2*( x0*tx + y0*ty - B*(A    191   //     G4double b = 2*( x0*tx + y0*ty - B*(A + B*z0)*tz);
192   //     G4double c = x0*x0 + y0*y0 - sqr(A +     192   //     G4double c = x0*x0 + y0*y0 - sqr(A + B*z0);
193   //                                              193   //
194   // For more accurate calculation of radical     194   // For more accurate calculation of radical the coefficients
195   // are splitted in two components, radial an    195   // are splitted in two components, radial and along z-axis
196   //                                              196   //
197   G4double ar = tx*tx + ty*ty;                    197   G4double ar = tx*tx + ty*ty;
198   G4double az = sqr(B*tz);                        198   G4double az = sqr(B*tz);
199   G4double br = 2*(x0*tx + y0*ty);                199   G4double br = 2*(x0*tx + y0*ty);
200   G4double bz = 2*B*(A + B*z0)*tz;                200   G4double bz = 2*B*(A + B*z0)*tz;
201   G4double cr = x0*x0 + y0*y0;                    201   G4double cr = x0*x0 + y0*y0;
202   G4double cz = sqr(A + B*z0);                    202   G4double cz = sqr(A + B*z0);
203                                                   203 
204   // Instead radical = b*b - 4*a*c                204   // Instead radical = b*b - 4*a*c
205   G4double arcz = 4*ar*cz;                        205   G4double arcz = 4*ar*cz;
206   G4double azcr = 4*az*cr;                        206   G4double azcr = 4*az*cr;
207   G4double radical = (br*br - 4*ar*cr) + ((std    207   G4double radical = (br*br - 4*ar*cr) + ((std::max(arcz,azcr) - 2*bz*br) + std::min(arcz,azcr));
208                                                   208 
209   // Find the coefficients                        209   // Find the coefficients
210   G4double a = ar - az;                           210   G4double a = ar - az;
211   G4double b = br - bz;                           211   G4double b = br - bz;
212   G4double c = cr - cz;                           212   G4double c = cr - cz;
213                                                   213 
214   if (radical < -EPS*std::fabs(b))  { return 0    214   if (radical < -EPS*std::fabs(b))  { return 0; } // No solution
215                                                   215 
216   if (radical < EPS*std::fabs(b))                 216   if (radical < EPS*std::fabs(b))
217   {                                               217   {
218     //                                            218     //
219     // The radical is roughly zero: check for     219     // The radical is roughly zero: check for special, very rare, cases
220     //                                            220     //
221     if (std::fabs(a) > 1/kInfinity)               221     if (std::fabs(a) > 1/kInfinity)
222       {                                           222       {
223       if(B==0.) { return 0; }                     223       if(B==0.) { return 0; }
224       if ( std::fabs(x0*ty - y0*tx) < std::fab    224       if ( std::fabs(x0*ty - y0*tx) < std::fabs(EPS/B) )
225       {                                           225       {
226          *s1 = -0.5*b/a;                          226          *s1 = -0.5*b/a;
227          return 1;                                227          return 1;
228       }                                           228       }
229       return 0;                                   229       return 0;
230     }                                             230     }
231   }                                               231   }
232   else                                            232   else
233   {                                               233   {
234     radical = std::sqrt(radical);                 234     radical = std::sqrt(radical);
235   }                                               235   }
236                                                   236 
237   if (a > 1/kInfinity)                            237   if (a > 1/kInfinity)
238   {                                               238   {
239     G4double sa, sb, q = -0.5*( b + (b < 0 ? -    239     G4double sa, sb, q = -0.5*( b + (b < 0 ? -radical : +radical) );
240     sa = q/a;                                     240     sa = q/a;
241     sb = c/q;                                     241     sb = c/q;
242     if (sa < sb) { *s1 = sa; *s2 = sb; } else     242     if (sa < sb) { *s1 = sa; *s2 = sb; } else { *s1 = sb; *s2 = sa; }
243     if (A + B*(z0+(*s1)*tz) < 0)  { return 0;     243     if (A + B*(z0+(*s1)*tz) < 0)  { return 0; }
244     return 2;                                     244     return 2;
245   }                                               245   }
246   else if (a < -1/kInfinity)                      246   else if (a < -1/kInfinity)
247   {                                               247   {
248     G4double sa, sb, q = -0.5*( b + (b < 0 ? -    248     G4double sa, sb, q = -0.5*( b + (b < 0 ? -radical : +radical) );
249     sa = q/a;                                     249     sa = q/a;
250     sb = c/q;                                     250     sb = c/q;
251     *s1 = (B*tz > 0)^(sa > sb) ? sb : sa;         251     *s1 = (B*tz > 0)^(sa > sb) ? sb : sa;
252     return 1;                                     252     return 1;
253   }                                               253   }
254   else if (std::fabs(b) < 1/kInfinity)            254   else if (std::fabs(b) < 1/kInfinity)
255   {                                               255   {
256     return 0;                                     256     return 0;
257   }                                               257   }
258   else                                            258   else
259   {                                               259   {
260     *s1 = -c/b;                                   260     *s1 = -c/b;
261     if (A + B*(z0+(*s1)*tz) < 0)  { return 0;     261     if (A + B*(z0+(*s1)*tz) < 0)  { return 0; }
262     return 1;                                     262     return 1;
263   }                                               263   }
264 }                                                 264 }
265                                                   265 
266 // LineHitsCone2                                  266 // LineHitsCone2
267 //                                                267 //
268 // See comments under LineHitsCone1. In this r    268 // See comments under LineHitsCone1. In this routine, case2, we have:
269 //                                                269 //
270 //   Z = A + B*R                                  270 //   Z = A + B*R
271 //                                                271 //
272 // The solution is still quadratic:               272 // The solution is still quadratic:
273 //                                                273 //
274 //  a = tz**2 - B*B*(tx**2 + ty**2)               274 //  a = tz**2 - B*B*(tx**2 + ty**2)
275 //                                                275 //
276 //  b = 2*( (z0-A)*tz - B*B*(x0*tx+y0*ty) )       276 //  b = 2*( (z0-A)*tz - B*B*(x0*tx+y0*ty) )
277 //                                                277 //
278 //  c = ( (z0-A)**2 - B*B*(x0**2 + y0**2) )       278 //  c = ( (z0-A)**2 - B*B*(x0**2 + y0**2) )
279 //                                                279 //
280 // The rest is much the same, except some deta    280 // The rest is much the same, except some details.
281 //                                                281 //
282 // a > 0 now means we intersect only once in t    282 // a > 0 now means we intersect only once in the correct hemisphere.
283 //                                                283 //
284 // a > 0 ? We only want solution which produce    284 // a > 0 ? We only want solution which produces R > 0.
285 // since R = (z0+s*tz-A)/B, for tz/B > 0, this    285 // since R = (z0+s*tz-A)/B, for tz/B > 0, this is the largest s
286 //          for tz/B < 0, this is the smallest    286 //          for tz/B < 0, this is the smallest s
287 // thus, same as in case 1 ( since sign(tz/B)     287 // thus, same as in case 1 ( since sign(tz/B) = sign(tz*B) )
288 //                                                288 //
289 G4int G4IntersectingCone::LineHitsCone2( const    289 G4int G4IntersectingCone::LineHitsCone2( const G4ThreeVector& p,
290                                          const    290                                          const G4ThreeVector& v,
291                                                   291                                                G4double* s1, G4double* s2 )
292 {                                                 292 {
293   static const G4double EPS = DBL_EPSILON; //     293   static const G4double EPS = DBL_EPSILON; // Precision constant,
294                                            //     294                                            // originally it was 1E-6
295   G4double x0 = p.x(), y0 = p.y(), z0 = p.z();    295   G4double x0 = p.x(), y0 = p.y(), z0 = p.z();
296   G4double tx = v.x(), ty = v.y(), tz = v.z();    296   G4double tx = v.x(), ty = v.y(), tz = v.z();
297                                                   297 
298   // Special case which might not be so rare:     298   // Special case which might not be so rare: B = 0 (precisely)
299   //                                              299   //
300   if (B==0)                                       300   if (B==0)
301   {                                               301   {
302     if (std::fabs(tz) < 1/kInfinity)  { return    302     if (std::fabs(tz) < 1/kInfinity)  { return 0; }
303                                                   303 
304     *s1 = (A-z0)/tz;                              304     *s1 = (A-z0)/tz;
305     return 1;                                     305     return 1;
306   }                                               306   }
307                                                   307 
308   // Value of radical can be inaccurate due to    308   // Value of radical can be inaccurate due to loss of precision
309   // if to calculate the coefficiets a,b,c lik    309   // if to calculate the coefficiets a,b,c like the following:
310   //   G4double a = tz*tz - B2*(tx*tx + ty*ty)    310   //   G4double a = tz*tz - B2*(tx*tx + ty*ty);
311   //   G4double b = 2*( (z0-A)*tz - B2*(x0*tx     311   //   G4double b = 2*( (z0-A)*tz - B2*(x0*tx + y0*ty) );
312   //   G4double c = sqr(z0-A) - B2*( x0*x0 + y    312   //   G4double c = sqr(z0-A) - B2*( x0*x0 + y0*y0 );
313   //                                              313   //
314   // For more accurate calculation of radical     314   // For more accurate calculation of radical the coefficients
315   // are splitted in two components, radial an    315   // are splitted in two components, radial and along z-axis
316   //                                              316   //
317   G4double B2 = B*B;                              317   G4double B2 = B*B;
318                                                   318 
319   G4double az = tz*tz;                            319   G4double az = tz*tz;
320   G4double ar = B2*(tx*tx + ty*ty);               320   G4double ar = B2*(tx*tx + ty*ty);
321   G4double bz = 2*(z0-A)*tz;                      321   G4double bz = 2*(z0-A)*tz;
322   G4double br = 2*B2*(x0*tx + y0*ty);             322   G4double br = 2*B2*(x0*tx + y0*ty);
323   G4double cz = sqr(z0-A);                        323   G4double cz = sqr(z0-A);
324   G4double cr = B2*(x0*x0 + y0*y0);               324   G4double cr = B2*(x0*x0 + y0*y0);
325                                                   325 
326   // Instead radical = b*b - 4*a*c                326   // Instead radical = b*b - 4*a*c
327   G4double arcz = 4*ar*cz;                        327   G4double arcz = 4*ar*cz;
328   G4double azcr = 4*az*cr;                        328   G4double azcr = 4*az*cr;
329   G4double radical = (br*br - 4*ar*cr) + ((std    329   G4double radical = (br*br - 4*ar*cr) + ((std::max(arcz,azcr) - 2*bz*br) + std::min(arcz,azcr));
330                                                   330 
331   // Find the coefficients                        331   // Find the coefficients
332   G4double a = az - ar;                           332   G4double a = az - ar;
333   G4double b = bz - br;                           333   G4double b = bz - br;
334   G4double c = cz - cr;                           334   G4double c = cz - cr;
335                                                   335 
336   if (radical < -EPS*std::fabs(b)) { return 0;    336   if (radical < -EPS*std::fabs(b)) { return 0; } // No solution
337                                                   337 
338   if (radical < EPS*std::fabs(b))                 338   if (radical < EPS*std::fabs(b))
339   {                                               339   {
340     //                                            340     //
341     // The radical is roughly zero: check for     341     // The radical is roughly zero: check for special, very rare, cases
342     //                                            342     //
343     if (std::fabs(a) > 1/kInfinity)               343     if (std::fabs(a) > 1/kInfinity)
344     {                                             344     {
345       if ( std::fabs(x0*ty - y0*tx) < std::fab    345       if ( std::fabs(x0*ty - y0*tx) < std::fabs(EPS/B) )
346       {                                           346       {
347         *s1 = -0.5*b/a;                           347         *s1 = -0.5*b/a;
348         return 1;                                 348         return 1;
349       }                                           349       }
350       return 0;                                   350       return 0;
351     }                                             351     }
352   }                                               352   }
353   else                                            353   else
354   {                                               354   {
355     radical = std::sqrt(radical);                 355     radical = std::sqrt(radical);
356   }                                               356   }
357                                                   357 
358   if (a < -1/kInfinity)                           358   if (a < -1/kInfinity)
359   {                                               359   {
360     G4double sa, sb, q = -0.5*( b + (b < 0 ? -    360     G4double sa, sb, q = -0.5*( b + (b < 0 ? -radical : +radical) );
361     sa = q/a;                                     361     sa = q/a;
362     sb = c/q;                                     362     sb = c/q;
363     if (sa < sb) { *s1 = sa; *s2 = sb; } else     363     if (sa < sb) { *s1 = sa; *s2 = sb; } else { *s1 = sb; *s2 = sa; }
364     if ((z0 + (*s1)*tz  - A)/B < 0)  { return     364     if ((z0 + (*s1)*tz  - A)/B < 0)  { return 0; }
365     return 2;                                     365     return 2;
366   }                                               366   }
367   else if (a > 1/kInfinity)                       367   else if (a > 1/kInfinity)
368   {                                               368   {
369     G4double sa, sb, q = -0.5*( b + (b < 0 ? -    369     G4double sa, sb, q = -0.5*( b + (b < 0 ? -radical : +radical) );
370     sa = q/a;                                     370     sa = q/a;
371     sb = c/q;                                     371     sb = c/q;
372     *s1 = (tz*B > 0)^(sa > sb) ? sb : sa;         372     *s1 = (tz*B > 0)^(sa > sb) ? sb : sa;
373     return 1;                                     373     return 1;
374   }                                               374   }
375   else if (std::fabs(b) < 1/kInfinity)            375   else if (std::fabs(b) < 1/kInfinity)
376   {                                               376   {
377     return 0;                                     377     return 0;
378   }                                               378   }
379   else                                            379   else
380   {                                               380   {
381     *s1 = -c/b;                                   381     *s1 = -c/b;
382     if ((z0 + (*s1)*tz  - A)/B < 0)  { return     382     if ((z0 + (*s1)*tz  - A)/B < 0)  { return 0; }
383     return 1;                                     383     return 1;
384   }                                               384   }
385 }                                                 385 }
386                                                   386