Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/solids/CSG/src/G4Sphere.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/CSG/src/G4Sphere.cc (Version 11.3.0) and /geometry/solids/CSG/src/G4Sphere.cc (Version 5.2.p2)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                    <<   3 // * DISCLAIMER                                                       *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th <<   5 // * The following disclaimer summarizes all the specific disclaimers *
  6 // * the Geant4 Collaboration.  It is provided <<   6 // * of contributors to this software. The specific disclaimers,which *
  7 // * conditions of the Geant4 Software License <<   7 // * govern, are listed with their locations in:                      *
  8 // * LICENSE and available at  http://cern.ch/ <<   8 // *   http://cern.ch/geant4/license                                  *
  9 // * include a list of copyright holders.      << 
 10 // *                                                9 // *                                                                  *
 11 // * Neither the authors of this software syst     10 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     11 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     12 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     13 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  <<  14 // * use.                                                             *
 16 // * for the full disclaimer and the limitatio << 
 17 // *                                               15 // *                                                                  *
 18 // * This  code  implementation is the result  <<  16 // * This  code  implementation is the  intellectual property  of the *
 19 // * technical work of the GEANT4 collaboratio <<  17 // * GEANT4 collaboration.                                            *
 20 // * By using,  copying,  modifying or  distri <<  18 // * By copying,  distributing  or modifying the Program (or any work *
 21 // * any work based  on the software)  you  ag <<  19 // * based  on  the Program)  you indicate  your  acceptance of  this *
 22 // * use  in  resulting  scientific  publicati <<  20 // * statement, and all its terms.                                    *
 23 // * acceptance of all terms of the Geant4 Sof << 
 24 // *******************************************     21 // ********************************************************************
 25 //                                                 22 //
                                                   >>  23 //
                                                   >>  24 // $Id: G4Sphere.cc,v 1.19 2003/06/16 16:53:38 gunter Exp $
                                                   >>  25 // GEANT4 tag $Name: geant4-05-02-patch-01 $
                                                   >>  26 //
                                                   >>  27 // class G4Sphere
                                                   >>  28 //
 26 // Implementation for G4Sphere class               29 // Implementation for G4Sphere class
 27 //                                                 30 //
                                                   >>  31 // History:
 28 // 28.03.94 P.Kent: old C++ code converted to      32 // 28.03.94 P.Kent: old C++ code converted to tolerant geometry
 29 // 17.09.96 V.Grichine: final modifications to     33 // 17.09.96 V.Grichine: final modifications to commit
 30 // 30.10.03 J.Apostolakis: new algorithm in In <<  34 // 09.10.98 V.Grichine: modifications in Distance ToOut(p,v,...)
 31 // 03.05.05 V.Grichine: SurfaceNormal(p) accor <<  35 // 12.11.98 V.Grichine: bug fixed in DistanceToIn(p,v), theta intersections
 32 // 22.07.05 O.Link: Added check for intersecti <<  36 // 25.11.98 V.Grichine: bug fixed in DistanceToIn(p,v), phi intersections
 33 // 26.03.09 G.Cosmo: optimisations and uniform <<  37 // 18.11.99 V.Grichine: side = kNull in Distance ToOut(p,v,...)
 34 // 26.10.16 E.Tcherniaev: re-implemented Calcu <<  38 // 06.03.00 V.Grichine: modifications in Distance ToOut(p,v,...)
 35 //                        G4BoundingEnvelope,  <<  39 // 30.01.02 V.Grichine: bug fixed in Inside(p), && -> || at l.451
 36 // ------------------------------------------- <<  40 // 19.06.02 V.Grichine: bug fixed in Inside(p), && -> && fDTheta - kAngTolerance
                                                   >>  41 //
                                                   >>  42 // ********************************************************************
 37                                                    43 
 38 #include "G4Sphere.hh"                         <<  44 #include <assert.h>
 39                                                    45 
 40 #if !defined(G4GEOM_USE_USPHERE)               <<  46 #include "G4Sphere.hh"
 41                                                    47 
 42 #include "G4GeomTools.hh"                      << 
 43 #include "G4VoxelLimits.hh"                        48 #include "G4VoxelLimits.hh"
 44 #include "G4AffineTransform.hh"                    49 #include "G4AffineTransform.hh"
 45 #include "G4GeometryTolerance.hh"              << 
 46 #include "G4BoundingEnvelope.hh"               << 
 47                                                    50 
 48 #include "G4VPVParameterisation.hh"                51 #include "G4VPVParameterisation.hh"
 49                                                    52 
 50 #include "G4QuickRand.hh"                      << 
 51                                                << 
 52 #include "meshdefs.hh"                             53 #include "meshdefs.hh"
 53                                                    54 
 54 #include "G4VGraphicsScene.hh"                     55 #include "G4VGraphicsScene.hh"
 55 #include "G4VisExtent.hh"                      <<  56 #include "G4Polyhedron.hh"
 56                                                <<  57 #include "G4NURBS.hh"
 57 using namespace CLHEP;                         <<  58 #include "G4NURBSbox.hh"
 58                                                    59 
 59 // Private enum: Not for external use - used b     60 // Private enum: Not for external use - used by distanceToOut
 60                                                    61 
 61 enum ESide {kNull,kRMin,kRMax,kSPhi,kEPhi,kSTh     62 enum ESide {kNull,kRMin,kRMax,kSPhi,kEPhi,kSTheta,kETheta};
 62                                                    63 
 63 // used by normal                                  64 // used by normal
 64                                                    65 
 65 enum ENorm {kNRMin,kNRMax,kNSPhi,kNEPhi,kNSThe     66 enum ENorm {kNRMin,kNRMax,kNSPhi,kNEPhi,kNSTheta,kNETheta};
 66                                                    67 
                                                   >>  68 /////////////////////////////////////////////////////////////////////
                                                   >>  69 //
                                                   >>  70 // Destructor
                                                   >>  71 
                                                   >>  72 G4Sphere::~G4Sphere()
                                                   >>  73 {
                                                   >>  74 }
                                                   >>  75 
 67 //////////////////////////////////////////////     76 ////////////////////////////////////////////////////////////////////////
 68 //                                                 77 //
 69 // constructor - check parameters, convert ang     78 // constructor - check parameters, convert angles so 0<sphi+dpshi<=2_PI
 70 //             - note if pDPhi>2PI then reset      79 //             - note if pDPhi>2PI then reset to 2PI
 71                                                    80 
 72 G4Sphere::G4Sphere( const G4String& pName,         81 G4Sphere::G4Sphere( const G4String& pName,
 73                           G4double pRmin, G4do     82                           G4double pRmin, G4double pRmax,
 74                           G4double pSPhi, G4do     83                           G4double pSPhi, G4double pDPhi,
 75                           G4double pSTheta, G4     84                           G4double pSTheta, G4double pDTheta )
 76   : G4CSGSolid(pName), fSPhi(0.0), fFullPhiSph <<  85   : G4CSGSolid(pName)
 77 {                                                  86 {
 78   kAngTolerance = G4GeometryTolerance::GetInst << 
 79   kRadTolerance = G4GeometryTolerance::GetInst << 
 80                                                << 
 81   halfCarTolerance = 0.5*kCarTolerance;        << 
 82   halfAngTolerance = 0.5*kAngTolerance;        << 
 83                                                    87 
 84   // Check radii and set radial tolerances     <<  88   // Check radii
 85                                                    89 
 86   if ( (pRmin >= pRmax) || (pRmax < 1.1*kRadTo <<  90   if (pRmin<pRmax&&pRmin>=0)
                                                   >>  91   {
                                                   >>  92     fRmin=pRmin; fRmax=pRmax;
                                                   >>  93   }
                                                   >>  94   else
 87   {                                                95   {
 88     std::ostringstream message;                <<  96     G4cout << "ERROR - G4Sphere()::G4Sphere(): " << GetName() << G4endl
 89     message << "Invalid radii for Solid: " <<  <<  97            << "        Invalid values for radii !" << G4endl
 90             << "        pRmin = " << pRmin <<  <<  98            << "        pRmin = " << pRmin << ", pRmax = " << pRmax << G4endl;
 91     G4Exception("G4Sphere::G4Sphere()", "GeomS <<  99     G4cerr << "ERROR - G4Sphere()::G4Sphere(): " << GetName() << G4endl
 92                 FatalException, message);      << 100            << "        Invalide values for radii ! - "
                                                   >> 101            << "        pRmin = " << pRmin << ", pRmax = " << pRmax << G4endl;
                                                   >> 102     G4Exception("G4Sphere::G4Sphere() - invalid radii");
 93   }                                               103   }
 94   fRmin=pRmin; fRmax=pRmax;                    << 
 95   fRminTolerance = (fRmin) != 0.0 ? std::max(  << 
 96   fRmaxTolerance = std::max( kRadTolerance, fE << 
 97                                                   104 
 98   // Check angles                                 105   // Check angles
 99                                                   106 
100   CheckPhiAngles(pSPhi, pDPhi);                << 107   if (pDPhi>=2.0*M_PI)
101   CheckThetaAngles(pSTheta, pDTheta);          << 108   {
102 }                                              << 109     fDPhi=2*M_PI;
103                                                << 110   }
104 ////////////////////////////////////////////// << 111   else if (pDPhi>0)
105 //                                             << 112   {
106 // Fake default constructor - sets only member << 113     fDPhi=pDPhi;
107 //                            for usage restri << 114   }
108 //                                             << 115   else
109 G4Sphere::G4Sphere( __void__& a )              << 116   {
110   : G4CSGSolid(a)                              << 117     G4cout << "ERROR - G4Sphere()::G4Sphere(): " << GetName() << G4endl
111 {                                              << 118            << "        Negative delta-Phi ! - "
112 }                                              << 119            << pDPhi << G4endl;
113                                                << 120     G4cerr << "ERROR - G4Sphere()::G4Sphere(): " << GetName() << G4endl
114 ////////////////////////////////////////////// << 121            << "        Negative Z delta-Phi ! - "
115 //                                             << 122            << pDPhi << G4endl;
116 // Destructor                                  << 123     G4Exception("G4Sphere::G4Sphere() - invalid DPhi");
                                                   >> 124   }
117                                                   125 
118 G4Sphere::~G4Sphere() = default;               << 126   // Convert fSPhi to 0-2PI
119                                                   127 
120 ////////////////////////////////////////////// << 128   if (pSPhi<0)
121 //                                             << 129   {
122 // Copy constructor                            << 130     fSPhi=2.0*M_PI-fmod(fabs(pSPhi),2.0*M_PI);
                                                   >> 131   }
                                                   >> 132   else
                                                   >> 133   {
                                                   >> 134     fSPhi=fmod(pSPhi,2.0*M_PI);
                                                   >> 135   }
123                                                   136 
124 G4Sphere::G4Sphere(const G4Sphere&) = default; << 137   // Sphere is placed such that fSPhi+fDPhi>2.0*M_PI !
                                                   >> 138   // fSPhi could be < 0 !!?
                                                   >> 139   //
                                                   >> 140   if (fSPhi+fDPhi>2.0*M_PI) fSPhi-=2.0*M_PI;
125                                                   141 
126 ////////////////////////////////////////////// << 142   // Check theta angles
127 //                                             << 
128 // Assignment operator                         << 
129                                                   143 
130 G4Sphere& G4Sphere::operator = (const G4Sphere << 144   if (pSTheta<0 || pSTheta>M_PI)
131 {                                              << 145   {
132    // Check assignment to self                 << 146     G4cout << "ERROR - G4Sphere()::G4Sphere(): " << GetName() << G4endl;
133    //                                          << 147     G4cerr << "ERROR - G4Sphere()::G4Sphere(): " << GetName() << G4endl;
134    if (this == &rhs)  { return *this; }        << 148     G4Exception("G4Sphere::G4Sphere() - stheta outside 0-PI range");
135                                                << 149   }
136    // Copy base class data                     << 150   else
137    //                                          << 151   {
138    G4CSGSolid::operator=(rhs);                 << 152     fSTheta=pSTheta;
139                                                << 153   }
140    // Copy data                                << 
141    //                                          << 
142    fRminTolerance = rhs.fRminTolerance; fRmaxT << 
143    kAngTolerance = rhs.kAngTolerance; kRadTole << 
144    fEpsilon = rhs.fEpsilon; fRmin = rhs.fRmin; << 
145    fSPhi = rhs.fSPhi; fDPhi = rhs.fDPhi; fSThe << 
146    fDTheta = rhs.fDTheta; sinCPhi = rhs.sinCPh << 
147    cosHDPhi = rhs.cosHDPhi;                    << 
148    cosHDPhiOT = rhs.cosHDPhiOT; cosHDPhiIT = r << 
149    sinSPhi = rhs.sinSPhi; cosSPhi = rhs.cosSPh << 
150    sinEPhi = rhs.sinEPhi; cosEPhi = rhs.cosEPh << 
151    hDPhi = rhs.hDPhi; cPhi = rhs.cPhi; ePhi =  << 
152    sinSTheta = rhs.sinSTheta; cosSTheta = rhs. << 
153    sinETheta = rhs.sinETheta; cosETheta = rhs. << 
154    tanSTheta = rhs.tanSTheta; tanSTheta2 = rhs << 
155    tanETheta = rhs.tanETheta; tanETheta2 = rhs << 
156    eTheta = rhs.eTheta; fFullPhiSphere = rhs.f << 
157    fFullThetaSphere = rhs.fFullThetaSphere; fF << 
158    halfCarTolerance = rhs.halfCarTolerance;    << 
159    halfAngTolerance = rhs.halfAngTolerance;    << 
160                                                   154 
161    return *this;                               << 155   if (pDTheta+pSTheta>=M_PI)
                                                   >> 156   {
                                                   >> 157     fDTheta=M_PI-pSTheta;
                                                   >> 158   }
                                                   >> 159   else if (pDTheta>0)
                                                   >> 160   {
                                                   >> 161     fDTheta=pDTheta;
                                                   >> 162   }
                                                   >> 163   else
                                                   >> 164   {
                                                   >> 165     G4cout << "ERROR - G4Sphere()::G4Sphere(): " << GetName() << G4endl
                                                   >> 166            << "        Negative delta-Theta ! - "
                                                   >> 167            << pDTheta << G4endl;
                                                   >> 168     G4cerr << "ERROR - G4Sphere()::G4Sphere(): " << GetName() << G4endl
                                                   >> 169            << "        Negative delta-Theta ! - "
                                                   >> 170            << pDTheta << G4endl;
                                                   >> 171     G4Exception("G4Sphere::G4Sphere() - invalid pDTheta");
                                                   >> 172   }
162 }                                                 173 }
163                                                   174 
164 //////////////////////////////////////////////    175 //////////////////////////////////////////////////////////////////////////
165 //                                                176 //
166 // Dispatch to parameterisation for replicatio    177 // Dispatch to parameterisation for replication mechanism dimension
167 // computation & modification.                    178 // computation & modification.
168                                                   179 
169 void G4Sphere::ComputeDimensions(       G4VPVP    180 void G4Sphere::ComputeDimensions(       G4VPVParameterisation* p,
170                                   const G4int     181                                   const G4int n,
171                                   const G4VPhy    182                                   const G4VPhysicalVolume* pRep)
172 {                                                 183 {
173   p->ComputeDimensions(*this,n,pRep);             184   p->ComputeDimensions(*this,n,pRep);
174 }                                                 185 }
175                                                   186 
176 ////////////////////////////////////////////// << 
177 //                                             << 
178 // Get bounding box                            << 
179                                                << 
180 void G4Sphere::BoundingLimits(G4ThreeVector& p << 
181 {                                              << 
182   G4double rmin = GetInnerRadius();            << 
183   G4double rmax = GetOuterRadius();            << 
184                                                << 
185   // Find bounding box                         << 
186   //                                           << 
187   if (GetDeltaThetaAngle() >= pi && GetDeltaPh << 
188   {                                            << 
189     pMin.set(-rmax,-rmax,-rmax);               << 
190     pMax.set( rmax, rmax, rmax);               << 
191   }                                            << 
192   else                                         << 
193   {                                            << 
194     G4double sinStart = GetSinStartTheta();    << 
195     G4double cosStart = GetCosStartTheta();    << 
196     G4double sinEnd   = GetSinEndTheta();      << 
197     G4double cosEnd   = GetCosEndTheta();      << 
198                                                << 
199     G4double stheta = GetStartThetaAngle();    << 
200     G4double etheta = stheta + GetDeltaThetaAn << 
201     G4double rhomin = rmin*std::min(sinStart,s << 
202     G4double rhomax = rmax;                    << 
203     if (stheta > halfpi) rhomax = rmax*sinStar << 
204     if (etheta < halfpi) rhomax = rmax*sinEnd; << 
205                                                << 
206     G4TwoVector xymin,xymax;                   << 
207     G4GeomTools::DiskExtent(rhomin,rhomax,     << 
208                             GetSinStartPhi(),G << 
209                             GetSinEndPhi(),Get << 
210                             xymin,xymax);      << 
211                                                << 
212     G4double zmin = std::min(rmin*cosEnd,rmax* << 
213     G4double zmax = std::max(rmin*cosStart,rma << 
214     pMin.set(xymin.x(),xymin.y(),zmin);        << 
215     pMax.set(xymax.x(),xymax.y(),zmax);        << 
216   }                                            << 
217                                                << 
218   // Check correctness of the bounding box     << 
219   //                                           << 
220   if (pMin.x() >= pMax.x() || pMin.y() >= pMax << 
221   {                                            << 
222     std::ostringstream message;                << 
223     message << "Bad bounding box (min >= max)  << 
224             << GetName() << " !"               << 
225             << "\npMin = " << pMin             << 
226             << "\npMax = " << pMax;            << 
227     G4Exception("G4Sphere::BoundingLimits()",  << 
228                 JustWarning, message);         << 
229     DumpInfo();                                << 
230   }                                            << 
231 }                                              << 
232                                                << 
233 //////////////////////////////////////////////    187 ////////////////////////////////////////////////////////////////////////////
234 //                                                188 //
235 // Calculate extent under transform and specif    189 // Calculate extent under transform and specified limit
236                                                   190 
237 G4bool G4Sphere::CalculateExtent( const EAxis     191 G4bool G4Sphere::CalculateExtent( const EAxis pAxis,
238                                   const G4Voxe    192                                   const G4VoxelLimits& pVoxelLimit,
239                                   const G4Affi    193                                   const G4AffineTransform& pTransform,
240                                         G4doub    194                                         G4double& pMin, G4double& pMax ) const
241 {                                                 195 {
242   G4ThreeVector bmin, bmax;                    << 196   if ( fDPhi==2.0*M_PI && fDTheta==M_PI)  // !pTransform.IsRotated() &&
243                                                << 
244   // Get bounding box                          << 
245   BoundingLimits(bmin,bmax);                   << 
246                                                << 
247   // Find extent                               << 
248   G4BoundingEnvelope bbox(bmin,bmax);          << 
249   return bbox.CalculateExtent(pAxis,pVoxelLimi << 
250 }                                              << 
251                                                << 
252 ////////////////////////////////////////////// << 
253 //                                             << 
254 // Return whether point inside/outside/on surf << 
255 // Split into radius, phi, theta checks        << 
256 // Each check modifies 'in', or returns as app << 
257                                                << 
258 EInside G4Sphere::Inside( const G4ThreeVector& << 
259 {                                              << 
260   G4double rho,rho2,rad2,tolRMin,tolRMax;      << 
261   G4double pPhi,pTheta;                        << 
262   EInside in = kOutside;                       << 
263                                                << 
264   const G4double halfRmaxTolerance = fRmaxTole << 
265   const G4double halfRminTolerance = fRminTole << 
266   const G4double Rmax_minus = fRmax - halfRmax << 
267   const G4double Rmin_plus  = (fRmin > 0) ? fR << 
268                                                << 
269   rho2 = p.x()*p.x() + p.y()*p.y() ;           << 
270   rad2 = rho2 + p.z()*p.z() ;                  << 
271                                                << 
272   // Check radial surfaces. Sets 'in'          << 
273                                                << 
274   tolRMin = Rmin_plus;                         << 
275   tolRMax = Rmax_minus;                        << 
276                                                << 
277   if(rad2 == 0.0)                              << 
278   {                                               197   {
279     if (fRmin > 0.0)                           << 198     // Special case handling for solid spheres-shells
280     {                                          << 199     // (rotation doesn't influence).
281       return in = kOutside;                    << 200     // Compute x/y/z mins and maxs for bounding box respecting limits,
282     }                                          << 201     // with early returns if outside limits. Then switch() on pAxis,
283     if ( (!fFullPhiSphere) || (!fFullThetaSphe << 202     // and compute exact x and y limit for x/y case
                                                   >> 203       
                                                   >> 204     G4double xoffset,xMin,xMax;
                                                   >> 205     G4double yoffset,yMin,yMax;
                                                   >> 206     G4double zoffset,zMin,zMax;
                                                   >> 207 
                                                   >> 208     G4double diff1,diff2,maxDiff,newMin,newMax;
                                                   >> 209     G4double xoff1,xoff2,yoff1,yoff2;
                                                   >> 210 
                                                   >> 211     xoffset=pTransform.NetTranslation().x();
                                                   >> 212     xMin=xoffset-fRmax;
                                                   >> 213     xMax=xoffset+fRmax;
                                                   >> 214     if (pVoxelLimit.IsXLimited())
284     {                                             215     {
285       return in = kSurface;                    << 216       if ( (xMin>pVoxelLimit.GetMaxXExtent()+kCarTolerance)
                                                   >> 217         || (xMax<pVoxelLimit.GetMinXExtent()-kCarTolerance) )
                                                   >> 218       {
                                                   >> 219         return false;
                                                   >> 220       }
                                                   >> 221       else
                                                   >> 222       {
                                                   >> 223         if (xMin<pVoxelLimit.GetMinXExtent())
                                                   >> 224         {
                                                   >> 225           xMin=pVoxelLimit.GetMinXExtent();
                                                   >> 226         }
                                                   >> 227         if (xMax>pVoxelLimit.GetMaxXExtent())
                                                   >> 228         {
                                                   >> 229           xMax=pVoxelLimit.GetMaxXExtent();
                                                   >> 230         }
                                                   >> 231       }
286     }                                             232     }
287     else                                       << 233 
                                                   >> 234     yoffset=pTransform.NetTranslation().y();
                                                   >> 235     yMin=yoffset-fRmax;
                                                   >> 236     yMax=yoffset+fRmax;
                                                   >> 237     if (pVoxelLimit.IsYLimited())
288     {                                             238     {
289       return in = kInside;                     << 239       if ( (yMin>pVoxelLimit.GetMaxYExtent()+kCarTolerance)
                                                   >> 240         || (yMax<pVoxelLimit.GetMinYExtent()-kCarTolerance) )
                                                   >> 241       {
                                                   >> 242         return false;
                                                   >> 243       }
                                                   >> 244       else
                                                   >> 245       {
                                                   >> 246         if (yMin<pVoxelLimit.GetMinYExtent())
                                                   >> 247         {
                                                   >> 248           yMin=pVoxelLimit.GetMinYExtent();
                                                   >> 249         }
                                                   >> 250         if (yMax>pVoxelLimit.GetMaxYExtent())
                                                   >> 251         {
                                                   >> 252           yMax=pVoxelLimit.GetMaxYExtent();
                                                   >> 253         }
                                                   >> 254       }
290     }                                             255     }
291   }                                            << 
292                                                   256 
293   if ( (rad2 <= Rmax_minus*Rmax_minus) && (rad << 257     zoffset=pTransform.NetTranslation().z();
294   {                                            << 258     zMin=zoffset-fRmax;
295     in = kInside;                              << 259     zMax=zoffset+fRmax;
296   }                                            << 260     if (pVoxelLimit.IsZLimited())
297   else                                         << 
298   {                                            << 
299     tolRMax = fRmax + halfRmaxTolerance;       << 
300     tolRMin = std::max(fRmin-halfRminTolerance << 
301     if ( (rad2 <= tolRMax*tolRMax) && (rad2 >= << 
302     {                                             261     {
303       in = kSurface;                           << 262       if ( (zMin>pVoxelLimit.GetMaxZExtent()+kCarTolerance)
                                                   >> 263         || (zMax<pVoxelLimit.GetMinZExtent()-kCarTolerance) )
                                                   >> 264       {
                                                   >> 265         return false;
                                                   >> 266       }
                                                   >> 267       else
                                                   >> 268       {
                                                   >> 269         if (zMin<pVoxelLimit.GetMinZExtent())
                                                   >> 270         {
                                                   >> 271           zMin=pVoxelLimit.GetMinZExtent();
                                                   >> 272         }
                                                   >> 273         if (zMax>pVoxelLimit.GetMaxZExtent())
                                                   >> 274         {
                                                   >> 275           zMax=pVoxelLimit.GetMaxZExtent();
                                                   >> 276         }
                                                   >> 277       }
304     }                                             278     }
305     else                                       << 279 
                                                   >> 280     // Known to cut sphere
                                                   >> 281 
                                                   >> 282     switch (pAxis)
306     {                                             283     {
307       return in = kOutside;                    << 284       case kXAxis:
                                                   >> 285         yoff1=yoffset-yMin;
                                                   >> 286         yoff2=yMax-yoffset;
                                                   >> 287         if (yoff1>=0&&yoff2>=0)
                                                   >> 288         {
                                                   >> 289           // Y limits cross max/min x => no change
                                                   >> 290           //
                                                   >> 291           pMin=xMin;
                                                   >> 292           pMax=xMax;
                                                   >> 293         }
                                                   >> 294         else
                                                   >> 295         {
                                                   >> 296           // Y limits don't cross max/min x => compute max delta x,
                                                   >> 297           // hence new mins/maxs
                                                   >> 298           //
                                                   >> 299           diff1=sqrt(fRmax*fRmax-yoff1*yoff1);
                                                   >> 300           diff2=sqrt(fRmax*fRmax-yoff2*yoff2);
                                                   >> 301           maxDiff=(diff1>diff2) ? diff1:diff2;
                                                   >> 302           newMin=xoffset-maxDiff;
                                                   >> 303           newMax=xoffset+maxDiff;
                                                   >> 304           pMin=(newMin<xMin) ? xMin : newMin;
                                                   >> 305           pMax=(newMax>xMax) ? xMax : newMax;
                                                   >> 306         }
                                                   >> 307         break;
                                                   >> 308       case kYAxis:
                                                   >> 309         xoff1=xoffset-xMin;
                                                   >> 310         xoff2=xMax-xoffset;
                                                   >> 311         if (xoff1>=0&&xoff2>=0)
                                                   >> 312         {
                                                   >> 313           // X limits cross max/min y => no change
                                                   >> 314           //
                                                   >> 315           pMin=yMin;
                                                   >> 316           pMax=yMax;
                                                   >> 317         }
                                                   >> 318         else
                                                   >> 319         {
                                                   >> 320           // X limits don't cross max/min y => compute max delta y,
                                                   >> 321           // hence new mins/maxs
                                                   >> 322           //
                                                   >> 323           diff1=sqrt(fRmax*fRmax-xoff1*xoff1);
                                                   >> 324           diff2=sqrt(fRmax*fRmax-xoff2*xoff2);
                                                   >> 325           maxDiff=(diff1>diff2) ? diff1:diff2;
                                                   >> 326           newMin=yoffset-maxDiff;
                                                   >> 327           newMax=yoffset+maxDiff;
                                                   >> 328           pMin=(newMin<yMin) ? yMin : newMin;
                                                   >> 329           pMax=(newMax>yMax) ? yMax : newMax;
                                                   >> 330         }
                                                   >> 331         break;
                                                   >> 332       case kZAxis:
                                                   >> 333         pMin=zMin;
                                                   >> 334         pMax=zMax;
                                                   >> 335         break;
                                                   >> 336       default:
                                                   >> 337         break;
308     }                                             338     }
                                                   >> 339     pMin-=kCarTolerance;
                                                   >> 340     pMax+=kCarTolerance;
                                                   >> 341 
                                                   >> 342     return true;  
309   }                                               343   }
                                                   >> 344   else       // Transformed cutted sphere
                                                   >> 345   {
                                                   >> 346     G4int i,j,noEntries,noBetweenSections;
                                                   >> 347     G4bool existsAfterClip=false;
310                                                   348 
311   // Phi boundaries   : Do not check if it has << 349     // Calculate rotated vertex coordinates
312                                                   350 
313   if ( !fFullPhiSphere && (rho2 != 0.0) )  //  << 351     G4ThreeVectorList* vertices;
314   {                                            << 352     G4int  noPolygonVertices ;
315     pPhi = std::atan2(p.y(),p.x()) ;           << 353     vertices=CreateRotatedVertices(pTransform,noPolygonVertices);
316                                                   354 
317     if      ( pPhi < fSPhi - halfAngTolerance  << 355     pMin=+kInfinity;
318     else if ( pPhi > ePhi + halfAngTolerance ) << 356     pMax=-kInfinity;
319                                                   357 
320     if ( (pPhi < fSPhi - halfAngTolerance)     << 358     noEntries=vertices->size();  // noPolygonVertices*noPhiCrossSections
321       || (pPhi > ePhi + halfAngTolerance) )    << 359     noBetweenSections=noEntries-noPolygonVertices;
322                                                   360 
323     else if (in == kInside)  // else it's kSur << 361     G4ThreeVectorList ThetaPolygon ;
                                                   >> 362     for (i=0;i<noEntries;i+=noPolygonVertices)
324     {                                             363     {
325       if ( (pPhi < fSPhi + halfAngTolerance)   << 364       for(j=0;j<(noPolygonVertices/2)-1;j++)
326         || (pPhi > ePhi - halfAngTolerance) )  << 365       {
                                                   >> 366         ThetaPolygon.push_back((*vertices)[i+j]) ;      
                                                   >> 367         ThetaPolygon.push_back((*vertices)[i+j+1]) ;      
                                                   >> 368         ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-2-j]) ;      
                                                   >> 369         ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-1-j]) ;      
                                                   >> 370         CalculateClippedPolygonExtent(ThetaPolygon,pVoxelLimit,pAxis,pMin,pMax);
                                                   >> 371         ThetaPolygon.clear() ;
                                                   >> 372       }
327     }                                             373     }
328   }                                            << 374     for (i=0;i<noBetweenSections;i+=noPolygonVertices)
329                                                << 
330   // Theta bondaries                           << 
331                                                << 
332   if ( ((rho2 != 0.0) || (p.z() != 0.0)) && (! << 
333   {                                            << 
334     rho    = std::sqrt(rho2);                  << 
335     pTheta = std::atan2(rho,p.z());            << 
336                                                << 
337     if ( in == kInside )                       << 
338     {                                             375     {
339       if ( ((fSTheta > 0.0) && (pTheta < fSThe << 376       for(j=0;j<noPolygonVertices-1;j++)
340         || ((eTheta < pi) && (pTheta > eTheta  << 
341       {                                           377       {
342         if ( (( (fSTheta>0.0)&&(pTheta>=fSThet << 378         ThetaPolygon.push_back((*vertices)[i+j]) ;      
343              || (fSTheta == 0.0) )             << 379         ThetaPolygon.push_back((*vertices)[i+j+1]) ;      
344           && ((eTheta==pi)||(pTheta <= eTheta  << 380         ThetaPolygon.push_back((*vertices)[i+noPolygonVertices+j+1]) ;      
345         {                                      << 381         ThetaPolygon.push_back((*vertices)[i+noPolygonVertices+j]) ;      
346           in = kSurface;                       << 382         CalculateClippedPolygonExtent(ThetaPolygon,pVoxelLimit,pAxis,pMin,pMax);
347         }                                      << 383         ThetaPolygon.clear() ;
348         else                                   << 
349         {                                      << 
350           in = kOutside;                       << 
351         }                                      << 
352       }                                           384       }
                                                   >> 385       ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-1]) ;      
                                                   >> 386       ThetaPolygon.push_back((*vertices)[i]) ;  
                                                   >> 387       ThetaPolygon.push_back((*vertices)[i+noPolygonVertices]) ;      
                                                   >> 388       ThetaPolygon.push_back((*vertices)[i+2*noPolygonVertices-1]) ;      
                                                   >> 389       CalculateClippedPolygonExtent(ThetaPolygon,pVoxelLimit,pAxis,pMin,pMax);
                                                   >> 390       ThetaPolygon.clear() ;
                                                   >> 391     }
                                                   >> 392       
                                                   >> 393     if (pMin!=kInfinity || pMax!=-kInfinity)
                                                   >> 394     {
                                                   >> 395       existsAfterClip=true;
                                                   >> 396 
                                                   >> 397       // Add 2*tolerance to avoid precision troubles
                                                   >> 398       //
                                                   >> 399       pMin-=kCarTolerance;
                                                   >> 400       pMax+=kCarTolerance;
353     }                                             401     }
354     else                                          402     else
355     {                                             403     {
356         if ( ((fSTheta > 0.0)&&(pTheta < fSThe << 404       // Check for case where completely enveloping clipping volume
357            ||((eTheta < pi  )&&(pTheta > eThet << 405       // If point inside then we are confident that the solid completely
358       {                                        << 406       // envelopes the clipping volume. Hence set min/max extents according
359         in = kOutside;                         << 407       // to clipping volume extents along the specified axis.
                                                   >> 408 
                                                   >> 409       G4ThreeVector clipCentre(
                                                   >> 410           (pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
                                                   >> 411           (pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
                                                   >> 412           (pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5);
                                                   >> 413         
                                                   >> 414       if (Inside(pTransform.Inverse().TransformPoint(clipCentre))!=kOutside)
                                                   >> 415       {
                                                   >> 416         existsAfterClip=true;
                                                   >> 417         pMin=pVoxelLimit.GetMinExtent(pAxis);
                                                   >> 418         pMax=pVoxelLimit.GetMaxExtent(pAxis);
360       }                                           419       }
361     }                                             420     }
                                                   >> 421     delete vertices;
                                                   >> 422     return existsAfterClip;
362   }                                               423   }
363   return in;                                   << 
364 }                                                 424 }
365                                                   425 
366 ////////////////////////////////////////////// << 426 ///////////////////////////////////////////////////////////////////////////
367 //                                                427 //
368 // Return unit normal of surface closest to p  << 428 // Return whether point inside/outside/on surface
369 // - note if point on z axis, ignore phi divid << 429 // Split into radius, phi, theta checks
370 // - unsafe if point close to z axis a rmin=0  << 430 // Each check modifies `in', or returns as approprate
371                                                   431 
372 G4ThreeVector G4Sphere::SurfaceNormal( const G << 432 EInside G4Sphere::Inside( const G4ThreeVector& p ) const
373 {                                                 433 {
374   G4int noSurfaces = 0;                        << 434   G4double rho,rho2,rad2,tolRMin,tolRMax;
375   G4double rho, rho2, radius, pTheta, pPhi=0.; << 435   G4double pPhi,pTheta;
376   G4double distRMin = kInfinity;               << 436   EInside in;
377   G4double distSPhi = kInfinity, distEPhi = kI << 
378   G4double distSTheta = kInfinity, distETheta  << 
379   G4ThreeVector nR, nPs, nPe, nTs, nTe, nZ(0., << 
380   G4ThreeVector norm, sumnorm(0.,0.,0.);       << 
381                                                << 
382   rho2 = p.x()*p.x()+p.y()*p.y();              << 
383   radius = std::sqrt(rho2+p.z()*p.z());        << 
384   rho  = std::sqrt(rho2);                      << 
385                                                   437 
386   G4double    distRMax = std::fabs(radius-fRma << 438   rho2 = p.x()*p.x() + p.y()*p.y() ;
387   if (fRmin != 0.0)  distRMin = std::fabs(radi << 439   rad2 = rho2 + p.z()*p.z() ;
388                                                   440 
389   if ( (rho != 0.0) && !fFullSphere )          << 441   // G4double rad = sqrt(rad2);
                                                   >> 442   // Check radial surfaces
                                                   >> 443   // sets `in'
                                                   >> 444 
                                                   >> 445   if ( fRmin ) tolRMin = fRmin + kRadTolerance*0.5;
                                                   >> 446   else         tolRMin = 0 ;
                                                   >> 447   
                                                   >> 448   tolRMax = fRmax - kRadTolerance*0.5 ;
                                                   >> 449     
                                                   >> 450   if ( rad2 <= tolRMax*tolRMax && rad2 >= tolRMin*tolRMin )  in = kInside ;
                                                   >> 451   else
390   {                                               452   {
391     pPhi = std::atan2(p.y(),p.x());            << 453     tolRMax = fRmax + kRadTolerance*0.5 ;
                                                   >> 454     tolRMin = fRmin - kRadTolerance*0.5 ;
392                                                   455 
393     if (pPhi < fSPhi-halfAngTolerance)     { p << 456     if ( tolRMin < 0.0 ) tolRMin = 0.0 ;
394     else if (pPhi > ePhi+halfAngTolerance) { p << 457     
                                                   >> 458     if ( rad2 <= tolRMax*tolRMax && rad2 >= tolRMin*tolRMin )  in = kSurface ;
                                                   >> 459     else                                                return in = kOutside ;
395   }                                               460   }
396   if ( !fFullPhiSphere )                       << 
397   {                                            << 
398     if ( rho != 0.0 )                          << 
399     {                                          << 
400       distSPhi = std::fabs( pPhi-fSPhi );      << 
401       distEPhi = std::fabs( pPhi-ePhi );       << 
402     }                                          << 
403     else if( fRmin == 0.0 )                    << 
404     {                                          << 
405       distSPhi = 0.;                           << 
406       distEPhi = 0.;                           << 
407     }                                          << 
408     nPs = G4ThreeVector(sinSPhi,-cosSPhi,0);   << 
409     nPe = G4ThreeVector(-sinEPhi,cosEPhi,0);   << 
410   }                                            << 
411   if ( !fFullThetaSphere )                     << 
412   {                                            << 
413     if ( rho != 0.0 )                          << 
414     {                                          << 
415       pTheta     = std::atan2(rho,p.z());      << 
416       distSTheta = std::fabs(pTheta-fSTheta);  << 
417       distETheta = std::fabs(pTheta-eTheta);   << 
418                                                   461 
419       nTs = G4ThreeVector(-cosSTheta*p.x()/rho << 462   // Phi boundaries   : Do not check if it has no phi boundary!
420                           -cosSTheta*p.y()/rho << 463   // (in != kOutside)
421                            sinSTheta           << 
422                                                   464 
423       nTe = G4ThreeVector( cosETheta*p.x()/rho << 465   if ( ( fDPhi < 2*M_PI - kAngTolerance ) &&
424                            cosETheta*p.y()/rho << 466        ( (p.x() != 0.0 ) || (p.y() != 0.0) ) )
425                           -sinETheta           << 467   {
426     }                                          << 468     pPhi = atan2(p.y(),p.x()) ;
427     else if( fRmin == 0.0 )                    << 469     if ( pPhi < 0.0)  pPhi += 2*M_PI ; // 0<=pPhi<2pi
                                                   >> 470     if ( fSPhi >= 0.0 )
428     {                                             471     {
429       if ( fSTheta != 0.0 )                    << 472       if (in == kInside)
430       {                                           473       {
431         distSTheta = 0.;                       << 474         if ( (pPhi < fSPhi + kAngTolerance*0.5)
432         nTs = G4ThreeVector(0.,0.,-1.);        << 475           || (pPhi > fSPhi + fDPhi - kAngTolerance*0.5) )
                                                   >> 476         {
                                                   >> 477           // Not `inside' tolerant bounds
                                                   >> 478           //
                                                   >> 479           if ( (pPhi >= fSPhi - kAngTolerance*0.5)
                                                   >> 480             && (pPhi <= fSPhi + fDPhi + kAngTolerance*0.5) )
                                                   >> 481           {
                                                   >> 482             in = kSurface ;
                                                   >> 483           }
                                                   >> 484           else
                                                   >> 485           {
                                                   >> 486             return in = kOutside ;
                                                   >> 487           }
                                                   >> 488         }
433       }                                           489       }
434       if ( eTheta < pi )                       << 490       else  // in==kSurface
435       {                                           491       {
436         distETheta = 0.;                       << 492         if ( (pPhi < fSPhi - kAngTolerance*0.5)
437         nTe = G4ThreeVector(0.,0.,1.);         << 493           || (pPhi > fSPhi + fDPhi + kAngTolerance*0.5) )    // && bug216
                                                   >> 494         {
                                                   >> 495           return in = kOutside ;
                                                   >> 496         }
438       }                                           497       }
439     }                                             498     }
440   }                                            << 499     else
441   if( radius != 0.0 )  { nR = G4ThreeVector(p. << 
442                                                << 
443   if( distRMax <= halfCarTolerance )           << 
444   {                                            << 
445     ++noSurfaces;                              << 
446     sumnorm += nR;                             << 
447   }                                            << 
448   if( (fRmin != 0.0) && (distRMin <= halfCarTo << 
449   {                                            << 
450     ++noSurfaces;                              << 
451     sumnorm -= nR;                             << 
452   }                                            << 
453   if( !fFullPhiSphere )                        << 
454   {                                            << 
455     if (distSPhi <= halfAngTolerance)          << 
456     {                                          << 
457       ++noSurfaces;                            << 
458       sumnorm += nPs;                          << 
459     }                                          << 
460     if (distEPhi <= halfAngTolerance)          << 
461     {                                             500     {
462       ++noSurfaces;                            << 501       if ( pPhi < fSPhi + 2*M_PI ) pPhi += 2*M_PI ;
463       sumnorm += nPe;                          << 502 
                                                   >> 503       if ( (pPhi < fSPhi + 2*M_PI + kAngTolerance*0.5)
                                                   >> 504         || (pPhi > fSPhi + fDPhi + 2*M_PI - kAngTolerance*0.5) )
                                                   >> 505       {
                                                   >> 506         // Not `inside' tolerant bounds
                                                   >> 507         //
                                                   >> 508         if ( (pPhi >= fSPhi + 2*M_PI - kAngTolerance*0.5)
                                                   >> 509           && (pPhi <= fSPhi + fDPhi + 2*M_PI + kAngTolerance*0.5) )
                                                   >> 510         {
                                                   >> 511           in = kSurface ;
                                                   >> 512         }
                                                   >> 513         else
                                                   >> 514         {
                                                   >> 515           return in = kOutside ;
                                                   >> 516         }
                                                   >> 517       }
464     }                                             518     }
465   }                                               519   }
466   if ( !fFullThetaSphere )                     << 520   // Theta bondaries
                                                   >> 521   // (in!=kOutside)
                                                   >> 522   
                                                   >> 523   if ( (rho2 || p.z()) && fDTheta < M_PI - kAngTolerance*0.5 )
467   {                                               524   {
468     if ((distSTheta <= halfAngTolerance) && (f << 525     rho    = sqrt(rho2);
                                                   >> 526     pTheta = atan2(rho,p.z());
                                                   >> 527 
                                                   >> 528     if ( in == kInside )
469     {                                             529     {
470       ++noSurfaces;                            << 530       if ( (pTheta < fSTheta + kAngTolerance*0.5)
471       if ((radius <= halfCarTolerance) && fFul << 531         || (pTheta > fSTheta + fDTheta - kAngTolerance*0.5) )
472       else                                     << 532       {
                                                   >> 533         if ( (pTheta >= fSTheta - kAngTolerance*0.5)
                                                   >> 534           && (pTheta <= fSTheta + fDTheta + kAngTolerance*0.5) )
                                                   >> 535         {
                                                   >> 536           in = kSurface ;
                                                   >> 537         }
                                                   >> 538         else
                                                   >> 539         {
                                                   >> 540           in = kOutside ;
                                                   >> 541         }
                                                   >> 542       }
473     }                                             543     }
474     if ((distETheta <= halfAngTolerance) && (e << 544     else
475     {                                             545     {
476       ++noSurfaces;                            << 546       if ( (pTheta < fSTheta - kAngTolerance*0.5)
477       if ((radius <= halfCarTolerance) && fFul << 547         || (pTheta > fSTheta + fDTheta + kAngTolerance*0.5) )
478       else                                     << 548       {
479       if(sumnorm.z() == 0.)  { sumnorm += nZ;  << 549         in = kOutside ;
                                                   >> 550       }
480     }                                             551     }
481   }                                               552   }
482   if ( noSurfaces == 0 )                       << 553   return in;
483   {                                            << 
484 #ifdef G4CSGDEBUG                              << 
485     G4Exception("G4Sphere::SurfaceNormal(p)",  << 
486                 JustWarning, "Point p is not o << 
487 #endif                                         << 
488      norm = ApproxSurfaceNormal(p);            << 
489   }                                            << 
490   else if ( noSurfaces == 1 )  { norm = sumnor << 
491   else                         { norm = sumnor << 
492   return norm;                                 << 
493 }                                                 554 }
494                                                   555 
495                                                << 
496 //////////////////////////////////////////////    556 /////////////////////////////////////////////////////////////////////
497 //                                                557 //
498 // Algorithm for SurfaceNormal() following the << 558 // Return unit normal of surface closest to p
499 // for points not on the surface               << 559 // - note if point on z axis, ignore phi divided sides
                                                   >> 560 // - unsafe if point close to z axis a rmin=0 - no explicit checks
500                                                   561 
501 G4ThreeVector G4Sphere::ApproxSurfaceNormal( c << 562 G4ThreeVector G4Sphere::SurfaceNormal( const G4ThreeVector& p ) const
502 {                                                 563 {
503   ENorm side;                                     564   ENorm side;
504   G4ThreeVector norm;                             565   G4ThreeVector norm;
505   G4double rho,rho2,radius,pPhi,pTheta;        << 566   G4double rho,rho2,rad,pPhi,pTheta;
506   G4double distRMin,distRMax,distSPhi,distEPhi    567   G4double distRMin,distRMax,distSPhi,distEPhi,
507            distSTheta,distETheta,distMin;         568            distSTheta,distETheta,distMin;
508                                                   569 
509   rho2=p.x()*p.x()+p.y()*p.y();                   570   rho2=p.x()*p.x()+p.y()*p.y();
510   radius=std::sqrt(rho2+p.z()*p.z());          << 571   rad=sqrt(rho2+p.z()*p.z());
511   rho=std::sqrt(rho2);                         << 572   rho=sqrt(rho2);
512                                                   573 
513   //                                              574   //
514   // Distance to r shells                         575   // Distance to r shells
515   //                                              576   //
516                                                   577 
517   distRMax=std::fabs(radius-fRmax);            << 578   distRMax=fabs(rad-fRmax);
518   if (fRmin != 0.0)                            << 579   if (fRmin)
519   {                                               580   {
520     distRMin=std::fabs(radius-fRmin);          << 581     distRMin=fabs(rad-fRmin);
521                                                << 582       
522     if (distRMin<distRMax)                        583     if (distRMin<distRMax)
523     {                                             584     {
524       distMin=distRMin;                           585       distMin=distRMin;
525       side=kNRMin;                                586       side=kNRMin;
526     }                                             587     }
527     else                                          588     else
528     {                                          << 589     {   
529       distMin=distRMax;                           590       distMin=distRMax;
530       side=kNRMax;                                591       side=kNRMax;
531     }                                             592     }
532   }                                               593   }
533   else                                            594   else
534   {                                               595   {
535     distMin=distRMax;                             596     distMin=distRMax;
536     side=kNRMax;                                  597     side=kNRMax;
537   }                                               598   }
538                                                   599 
539   //                                              600   //
540   // Distance to phi planes                       601   // Distance to phi planes
541   //                                              602   //
542   // Protected against (0,0,z)                 << 603   if (fDPhi<2.0*M_PI&&rho)
543                                                << 
544   pPhi = std::atan2(p.y(),p.x());              << 
545   if (pPhi<0) { pPhi += twopi; }               << 
546                                                << 
547   if (!fFullPhiSphere && (rho != 0.0))         << 
548   {                                               604   {
                                                   >> 605     // Protected against (0,0,z) (above)
                                                   >> 606     //
                                                   >> 607     pPhi=atan2(p.y(),p.x());
                                                   >> 608     if (pPhi<0) pPhi+=2*M_PI;
549     if (fSPhi<0)                                  609     if (fSPhi<0)
550     {                                             610     {
551       distSPhi=std::fabs(pPhi-(fSPhi+twopi))*r << 611       distSPhi=fabs(pPhi-(fSPhi+2.0*M_PI))*rho;
552     }                                             612     }
553     else                                          613     else
554     {                                             614     {
555       distSPhi=std::fabs(pPhi-fSPhi)*rho;      << 615       distSPhi=fabs(pPhi-fSPhi)*rho;
556     }                                             616     }
557                                                   617 
558     distEPhi=std::fabs(pPhi-fSPhi-fDPhi)*rho;  << 618     distEPhi=fabs(pPhi-fSPhi-fDPhi)*rho;
559                                                   619 
560     // Find new minimum                           620     // Find new minimum
561     //                                            621     //
562     if (distSPhi<distEPhi)                        622     if (distSPhi<distEPhi)
563     {                                             623     {
564       if (distSPhi<distMin)                       624       if (distSPhi<distMin)
565       {                                           625       {
566         distMin = distSPhi;                    << 626         distMin=distSPhi;
567         side = kNSPhi;                         << 627         side=kNSPhi;
568       }                                           628       }
569     }                                             629     }
570     else                                          630     else
571     {                                             631     {
572       if (distEPhi<distMin)                       632       if (distEPhi<distMin)
573       {                                           633       {
574         distMin = distEPhi;                    << 634         distMin=distEPhi;
575         side = kNEPhi;                         << 635         side=kNEPhi;
576       }                                           636       }
577     }                                             637     }
578   }                                               638   }
579                                                   639 
580   //                                              640   //
581   // Distance to theta planes                     641   // Distance to theta planes
582   //                                              642   //
583                                                   643 
584   if (!fFullThetaSphere && (radius != 0.0))    << 644   if (fDTheta<M_PI&&rad)
585   {                                               645   {
586     pTheta=std::atan2(rho,p.z());              << 646     pTheta=atan2(rho,p.z());
587     distSTheta=std::fabs(pTheta-fSTheta)*radiu << 647     distSTheta=fabs(pTheta-fSTheta)*rad;
588     distETheta=std::fabs(pTheta-fSTheta-fDThet << 648     distETheta=fabs(pTheta-fSTheta-fDTheta)*rad;
589                                                   649 
590     // Find new minimum                           650     // Find new minimum
591     //                                            651     //
592     if (distSTheta<distETheta)                    652     if (distSTheta<distETheta)
593     {                                             653     {
594       if (distSTheta<distMin)                     654       if (distSTheta<distMin)
595       {                                           655       {
596         distMin = distSTheta ;                    656         distMin = distSTheta ;
597         side = kNSTheta ;                         657         side = kNSTheta ;
598       }                                           658       }
599     }                                             659     }
600     else                                          660     else
601     {                                             661     {
602       if (distETheta<distMin)                     662       if (distETheta<distMin)
603       {                                           663       {
604         distMin = distETheta ;                    664         distMin = distETheta ;
605         side = kNETheta ;                         665         side = kNETheta ;
606       }                                           666       }
607     }                                             667     }
608   }                                               668   }
609                                                   669 
610   switch (side)                                   670   switch (side)
611   {                                               671   {
612     case kNRMin:      // Inner radius             672     case kNRMin:      // Inner radius
613       norm=G4ThreeVector(-p.x()/radius,-p.y()/ << 673       norm=G4ThreeVector(-p.x()/rad,-p.y()/rad,-p.z()/rad);
614       break;                                      674       break;
615     case kNRMax:      // Outer radius             675     case kNRMax:      // Outer radius
616       norm=G4ThreeVector(p.x()/radius,p.y()/ra << 676       norm=G4ThreeVector(p.x()/rad,p.y()/rad,p.z()/rad);
617       break;                                      677       break;
618     case kNSPhi:                                  678     case kNSPhi:
619       norm=G4ThreeVector(sinSPhi,-cosSPhi,0);  << 679       norm=G4ThreeVector(sin(fSPhi),-cos(fSPhi),0);
620       break;                                      680       break;
621     case kNEPhi:                                  681     case kNEPhi:
622       norm=G4ThreeVector(-sinEPhi,cosEPhi,0);  << 682       norm=G4ThreeVector(-sin(fSPhi+fDPhi),cos(fSPhi+fDPhi),0);
623       break;                                      683       break;
                                                   >> 684 
624     case kNSTheta:                                685     case kNSTheta:
625       norm=G4ThreeVector(-cosSTheta*std::cos(p << 686       norm=G4ThreeVector(-cos(fSTheta)*sin(fSPhi),
626                          -cosSTheta*std::sin(p << 687              -cos(fSTheta)*cos(fSPhi),sin(fSTheta));
627                           sinSTheta            << 
628       break;                                      688       break;
629     case kNETheta:                                689     case kNETheta:
630       norm=G4ThreeVector( cosETheta*std::cos(p << 690       norm=G4ThreeVector(-cos(fSTheta+fDTheta)*cos(fSPhi+fDPhi),
631                           cosETheta*std::sin(p << 691              -cos(fSTheta+fDTheta)*sin(fSPhi+fDPhi),
632                          -sinETheta            << 692              -sin(fSTheta+fDTheta));
633       break;                                      693       break;
634     default:          // Should never reach th << 694     default:
635       DumpInfo();                                 695       DumpInfo();
636       G4Exception("G4Sphere::ApproxSurfaceNorm << 696       G4Exception("G4Sphere::SurfaceNormal() - Logic error");
637                   "GeomSolids1002", JustWarnin << 697       break;    
638                   "Undefined side for valid su << 698   } // end case
639       break;                                   << 
640   }                                            << 
641                                                   699 
642   return norm;                                    700   return norm;
643 }                                                 701 }
644                                                   702 
645 //////////////////////////////////////////////    703 ///////////////////////////////////////////////////////////////////////////////
646 //                                                704 //
647 // Calculate distance to shape from outside, a    705 // Calculate distance to shape from outside, along normalised vector
648 // - return kInfinity if no intersection, or i    706 // - return kInfinity if no intersection, or intersection distance <= tolerance
649 //                                                707 //
650 // -> If point is outside outer radius, comput    708 // -> If point is outside outer radius, compute intersection with rmax
651 //        - if no intersection return             709 //        - if no intersection return
652 //        - if  valid phi,theta return interse    710 //        - if  valid phi,theta return intersection Dist
653 //                                                711 //
654 // -> If shell, compute intersection with inne    712 // -> If shell, compute intersection with inner radius, taking largest +ve root
655 //        - if valid phi,theta, save intersect    713 //        - if valid phi,theta, save intersection
656 //                                                714 //
657 // -> If phi segmented, compute intersection w    715 // -> If phi segmented, compute intersection with phi half planes
658 //        - if valid intersection(r,theta), re    716 //        - if valid intersection(r,theta), return smallest intersection of
659 //          inner shell & phi intersection        717 //          inner shell & phi intersection
660 //                                                718 //
661 // -> If theta segmented, compute intersection    719 // -> If theta segmented, compute intersection with theta cones
662 //        - if valid intersection(r,phi), retu    720 //        - if valid intersection(r,phi), return smallest intersection of
663 //          inner shell & theta intersection      721 //          inner shell & theta intersection
664 //                                                722 //
665 //                                                723 //
666 // NOTE:                                          724 // NOTE:
667 // - `if valid' (above) implies tolerant check    725 // - `if valid' (above) implies tolerant checking of intersection points
668 //                                                726 //
669 // OPT:                                           727 // OPT:
670 // Move tolIO/ORmin/RMax2 precalcs to where th    728 // Move tolIO/ORmin/RMax2 precalcs to where they are needed -
671 // not required for most cases.                   729 // not required for most cases.
672 // Avoid atan2 for non theta cut G4Sphere.        730 // Avoid atan2 for non theta cut G4Sphere.
673                                                   731 
674 G4double G4Sphere::DistanceToIn( const G4Three    732 G4double G4Sphere::DistanceToIn( const G4ThreeVector& p,
675                                  const G4Three    733                                  const G4ThreeVector& v  ) const
676 {                                                 734 {
677   G4double snxt = kInfinity ;      // snxt = d    735   G4double snxt = kInfinity ;      // snxt = default return value
                                                   >> 736 
678   G4double rho2, rad2, pDotV2d, pDotV3d, pThet    737   G4double rho2, rad2, pDotV2d, pDotV3d, pTheta ;
679   G4double tolSTheta=0., tolETheta=0. ;        << 
680   const G4double dRmax = 100.*fRmax;           << 
681                                                   738 
682   const G4double halfRmaxTolerance = fRmaxTole << 739   G4double tolIRMin2, tolORMin2, tolORMax2, tolIRMax2 ;
683   const G4double halfRminTolerance = fRminTole << 740   G4double tolSTheta=0., tolETheta=0. ;
684   const G4double tolORMin2 = (fRmin>halfRminTo << 
685                ? (fRmin-halfRminTolerance)*(fR << 
686   const G4double tolIRMin2 =                   << 
687                (fRmin+halfRminTolerance)*(fRmi << 
688   const G4double tolORMax2 =                   << 
689                (fRmax+halfRmaxTolerance)*(fRma << 
690   const G4double tolIRMax2 =                   << 
691                (fRmax-halfRmaxTolerance)*(fRma << 
692                                                   741 
693   // Intersection point                           742   // Intersection point
694   //                                           << 743 
695   G4double xi, yi, zi, rhoi, rhoi2, radi2, iTh    744   G4double xi, yi, zi, rhoi, rhoi2, radi2, iTheta ;
696                                                   745 
697   // Phi intersection                             746   // Phi intersection
698   //                                           << 
699   G4double Comp ;                              << 
700                                                   747 
701   // Phi precalcs                              << 748   G4double sinSPhi, cosSPhi, ePhi, sinEPhi, cosEPhi , Comp ; 
702   //                                           << 749 
                                                   >> 750   // Phi flag and precalcs
                                                   >> 751 
                                                   >> 752   G4bool segPhi ;        
                                                   >> 753   G4double hDPhi, hDPhiOT, hDPhiIT, cPhi, sinCPhi=0., cosCPhi=0. ; 
                                                   >> 754   G4double cosHDPhiOT=0., cosHDPhiIT=0. ;
703   G4double Dist, cosPsi ;                         755   G4double Dist, cosPsi ;
704                                                   756 
705   // Theta precalcs                            << 757   G4bool segTheta ;                             // Theta flag and precals
706   //                                           << 758   G4double tanSTheta, tanETheta ;
                                                   >> 759   G4double tanSTheta2, tanETheta2 ;
707   G4double dist2STheta, dist2ETheta ;             760   G4double dist2STheta, dist2ETheta ;
708   G4double t1, t2, b, c, d2, d, sd = kInfinity << 761   G4double t1, t2, b, c, d2, d, s = kInfinity ;
709                                                   762 
710   // General Precalcs                             763   // General Precalcs
711   //                                           << 764 
712   rho2 = p.x()*p.x() + p.y()*p.y() ;              765   rho2 = p.x()*p.x() + p.y()*p.y() ;
713   rad2 = rho2 + p.z()*p.z() ;                     766   rad2 = rho2 + p.z()*p.z() ;
714   pTheta = std::atan2(std::sqrt(rho2),p.z()) ; << 767   pTheta = atan2(sqrt(rho2),p.z()) ;
715                                                   768 
716   pDotV2d = p.x()*v.x() + p.y()*v.y() ;           769   pDotV2d = p.x()*v.x() + p.y()*v.y() ;
717   pDotV3d = pDotV2d + p.z()*v.z() ;               770   pDotV3d = pDotV2d + p.z()*v.z() ;
718                                                   771 
719   // Theta precalcs                            << 772   // Radial Precalcs
720   //                                           << 773 
721   if (!fFullThetaSphere)                       << 774   if (fRmin > kRadTolerance*0.5)
                                                   >> 775   {
                                                   >> 776     tolORMin2=(fRmin-kRadTolerance*0.5)*(fRmin-kRadTolerance*0.5);
                                                   >> 777   }
                                                   >> 778   else
722   {                                               779   {
723     tolSTheta = fSTheta - halfAngTolerance ;   << 780     tolORMin2 = 0 ;
724     tolETheta = eTheta + halfAngTolerance ;    << 781   }
                                                   >> 782   tolIRMin2 = (fRmin+kRadTolerance*0.5)*(fRmin+kRadTolerance*0.5) ;
                                                   >> 783   tolORMax2 = (fRmax+kRadTolerance*0.5)*(fRmax+kRadTolerance*0.5) ;
                                                   >> 784   tolIRMax2 = (fRmax-kRadTolerance*0.5)*(fRmax-kRadTolerance*0.5) ;
725                                                   785 
726     // Special case rad2 = 0 comparing with di << 786   // Set phi divided flag and precalcs
727     //                                         << 787 
728     if ((rad2!=0.0) || (fRmin!=0.0))           << 788   if (fDPhi < 2.0*M_PI)
729     {                                          << 789   {
730       // Keep going for computation of distanc << 790     segPhi = true ;
731     }                                          << 791     hDPhi = 0.5*fDPhi ;    // half delta phi
732     else  // Positioned on the sphere's origin << 792     cPhi = fSPhi + hDPhi ;
733     {                                          << 793 
734       G4double vTheta = std::atan2(std::sqrt(v << 794     hDPhiOT = hDPhi+0.5*kAngTolerance; // Outer Tolerant half delta phi 
735       if ( (vTheta < tolSTheta) || (vTheta > t << 795     hDPhiIT = hDPhi-0.5*kAngTolerance;
736       {                                        << 796 
737         return snxt ; // kInfinity             << 797     sinCPhi    = sin(cPhi) ;
738       }                                        << 798     cosCPhi    = cos(cPhi) ;
739       return snxt = 0.0 ;                      << 799     cosHDPhiOT = cos(hDPhiOT) ;
740     }                                          << 800     cosHDPhiIT = cos(hDPhiIT) ;
                                                   >> 801   }
                                                   >> 802   else
                                                   >> 803   {
                                                   >> 804     segPhi = false ;
                                                   >> 805   }
                                                   >> 806 
                                                   >> 807   // Theta precalcs
                                                   >> 808     
                                                   >> 809   if (fDTheta < M_PI )
                                                   >> 810   {
                                                   >> 811     segTheta  = true ;
                                                   >> 812     tolSTheta = fSTheta - kAngTolerance*0.5 ;
                                                   >> 813     tolETheta = fSTheta + fDTheta + kAngTolerance*0.5 ;
                                                   >> 814   }
                                                   >> 815   else
                                                   >> 816   {
                                                   >> 817     segTheta = false ;
741   }                                               818   }
742                                                   819 
743   // Outer spherical shell intersection           820   // Outer spherical shell intersection
744   // - Only if outside tolerant fRmax             821   // - Only if outside tolerant fRmax
745   // - Check for if inside and outer G4Sphere     822   // - Check for if inside and outer G4Sphere heading through solid (-> 0)
746   // - No intersect -> no intersection with G4    823   // - No intersect -> no intersection with G4Sphere
747   //                                              824   //
748   // Shell eqn: x^2+y^2+z^2=RSPH^2                825   // Shell eqn: x^2+y^2+z^2=RSPH^2
749   //                                              826   //
750   // => (px+svx)^2+(py+svy)^2+(pz+svz)^2=R^2      827   // => (px+svx)^2+(py+svy)^2+(pz+svz)^2=R^2
751   //                                              828   //
752   // => (px^2+py^2+pz^2) +2sd(pxvx+pyvy+pzvz)+ << 829   // => (px^2+py^2+pz^2) +2s(pxvx+pyvy+pzvz)+s^2(vx^2+vy^2+vz^2)=R^2
753   // =>      rad2        +2sd(pDotV3d)       + << 830   // =>      rad2        +2s(pDotV3d)       +s^2                =R^2
754   //                                              831   //
755   // => sd=-pDotV3d+-std::sqrt(pDotV3d^2-(rad2 << 832   // => s=-pDotV3d+-sqrt(pDotV3d^2-(rad2-R^2))
756                                                   833 
757   c = rad2 - fRmax*fRmax ;                        834   c = rad2 - fRmax*fRmax ;
758                                                   835 
759   if (c > fRmaxTolerance*fRmax)                << 836   if (c > kRadTolerance*fRmax)
760   {                                               837   {
761     // If outside tolerant boundary of outer G << 838     // If outside toleranct boundary of outer G4Sphere
762     // [should be std::sqrt(rad2)-fRmax > half << 839     // [should be sqrt(rad2)-fRmax > kRadTolerance*0.5]
763                                                   840 
764     d2 = pDotV3d*pDotV3d - c ;                    841     d2 = pDotV3d*pDotV3d - c ;
765                                                   842 
766     if ( d2 >= 0 )                                843     if ( d2 >= 0 )
767     {                                             844     {
768       sd = -pDotV3d - std::sqrt(d2) ;          << 845       s = -pDotV3d - sqrt(d2) ;
769                                                   846 
770       if (sd >= 0 )                            << 847       if (s >= 0 )
771       {                                           848       {
772         if ( sd>dRmax ) // Avoid rounding erro << 849         xi   = p.x() + s*v.x() ;
773         {               // 64 bits systems. Sp << 850         yi   = p.y() + s*v.y() ;
774           G4double fTerm = sd-std::fmod(sd,dRm << 851         rhoi = sqrt(xi*xi + yi*yi) ;
775           sd = fTerm + DistanceToIn(p+fTerm*v, << 
776         }                                      << 
777         xi   = p.x() + sd*v.x() ;              << 
778         yi   = p.y() + sd*v.y() ;              << 
779         rhoi = std::sqrt(xi*xi + yi*yi) ;      << 
780                                                   852 
781         if (!fFullPhiSphere && (rhoi != 0.0))  << 853         if (segPhi && rhoi)    // Check phi intersection
782         {                                         854         {
783           cosPsi = (xi*cosCPhi + yi*sinCPhi)/r    855           cosPsi = (xi*cosCPhi + yi*sinCPhi)/rhoi ;
784                                                   856 
785           if (cosPsi >= cosHDPhiOT)               857           if (cosPsi >= cosHDPhiOT)
786           {                                       858           {
787             if (!fFullThetaSphere)   // Check  << 859             if (segTheta)   // Check theta intersection
788             {                                     860             {
789               zi = p.z() + sd*v.z() ;          << 861               zi = p.z() + s*v.z() ;
790                                                   862 
791               // rhoi & zi can never both be 0    863               // rhoi & zi can never both be 0
792               // (=>intersect at origin =>fRma    864               // (=>intersect at origin =>fRmax=0)
793               //                                  865               //
794               iTheta = std::atan2(rhoi,zi) ;   << 866               iTheta = atan2(rhoi,zi) ;
795               if ( (iTheta >= tolSTheta) && (i    867               if ( (iTheta >= tolSTheta) && (iTheta <= tolETheta) )
796               {                                   868               {
797                 return snxt = sd ;             << 869                 return snxt = s ;
798               }                                   870               }
799             }                                     871             }
800             else                                  872             else
801             {                                     873             {
802               return snxt=sd;                  << 874               return snxt=s;
803             }                                     875             }
804           }                                       876           }
805         }                                         877         }
806         else                                      878         else
807         {                                         879         {
808           if (!fFullThetaSphere)    // Check t << 880           if (segTheta)    // Check theta intersection
809           {                                       881           {
810             zi = p.z() + sd*v.z() ;            << 882             zi = p.z() + s*v.z() ;
811                                                   883 
812             // rhoi & zi can never both be 0      884             // rhoi & zi can never both be 0
813             // (=>intersect at origin => fRmax    885             // (=>intersect at origin => fRmax=0 !)
814             //                                    886             //
815             iTheta = std::atan2(rhoi,zi) ;     << 887             iTheta = atan2(rhoi,zi) ;
816             if ( (iTheta >= tolSTheta) && (iTh    888             if ( (iTheta >= tolSTheta) && (iTheta <= tolETheta) )
817             {                                     889             {
818               return snxt=sd;                  << 890               return snxt=s;
819             }                                     891             }
820           }                                       892           }
821           else                                    893           else
822           {                                       894           {
823             return snxt = sd;                  << 895             return snxt = s ;
824           }                                       896           }
825         }                                      << 897         }          
826       }                                           898       }
827     }                                             899     }
828     else    // No intersection with G4Sphere      900     else    // No intersection with G4Sphere
829     {                                             901     {
830       return snxt=kInfinity;                      902       return snxt=kInfinity;
831     }                                             903     }
832   }                                               904   }
833   else                                            905   else
834   {                                               906   {
835     // Inside outer radius                        907     // Inside outer radius
836     // check not inside, and heading through G    908     // check not inside, and heading through G4Sphere (-> 0 to in)
837                                                   909 
838     d2 = pDotV3d*pDotV3d - c ;                 << 910     if (rad2 > tolIRMin2 && pDotV3d < 0 )
839                                                << 
840     if ( (rad2 > tolIRMax2)                    << 
841       && ( (d2 >= fRmaxTolerance*fRmax) && (pD << 
842     {                                             911     {
843       if (!fFullPhiSphere)                     << 912       if (segPhi)
844       {                                           913       {
845         // Use inner phi tolerant boundary ->     914         // Use inner phi tolerant boundary -> if on tolerant
846         // phi boundaries, phi intersect code     915         // phi boundaries, phi intersect code handles leaving/entering checks
847                                                   916 
848         cosPsi = (p.x()*cosCPhi + p.y()*sinCPh << 917         cosPsi = (p.x()*cosCPhi + p.y()*sinCPhi)/sqrt(rho2) ;
849                                                   918 
850         if (cosPsi>=cosHDPhiIT)                   919         if (cosPsi>=cosHDPhiIT)
851         {                                      << 920         { 
852           // inside radii, delta r -ve, inside    921           // inside radii, delta r -ve, inside phi
853                                                   922 
854           if ( !fFullThetaSphere )             << 923           if (segTheta)
855           {                                       924           {
856             if ( (pTheta >= tolSTheta + kAngTo    925             if ( (pTheta >= tolSTheta + kAngTolerance)
857               && (pTheta <= tolETheta - kAngTo    926               && (pTheta <= tolETheta - kAngTolerance) )
858             {                                     927             {
859               return snxt=0;                      928               return snxt=0;
860             }                                     929             }
861           }                                       930           }
862           else    // strictly inside Theta in     931           else    // strictly inside Theta in both cases
863           {                                       932           {
864             return snxt=0;                        933             return snxt=0;
865           }                                       934           }
866         }                                         935         }
867       }                                           936       }
868       else                                        937       else
869       {                                           938       {
870         if ( !fFullThetaSphere )               << 939         if ( segTheta )
871         {                                         940         {
872           if ( (pTheta >= tolSTheta + kAngTole    941           if ( (pTheta >= tolSTheta + kAngTolerance)
873             && (pTheta <= tolETheta - kAngTole    942             && (pTheta <= tolETheta - kAngTolerance) )
874           {                                       943           {
875             return snxt=0;                        944             return snxt=0;
876           }                                       945           }
877         }                                         946         }
878         else   // strictly inside Theta in bot    947         else   // strictly inside Theta in both cases
879         {                                         948         {
880           return snxt=0;                          949           return snxt=0;
881         }                                         950         }
882       }                                           951       }
883     }                                             952     }
884   }                                               953   }
885                                                   954 
886   // Inner spherical shell intersection           955   // Inner spherical shell intersection
887   // - Always farthest root, because would hav    956   // - Always farthest root, because would have passed through outer
888   //   surface first.                             957   //   surface first.
889   // - Tolerant check if travelling through so << 958   // - Tolerant check for if travelling through solid
890                                                   959 
891   if (fRmin != 0.0)                            << 960   if (fRmin)
892   {                                               961   {
893     c  = rad2 - fRmin*fRmin ;                  << 962     c = rad2 - fRmin*fRmin ;
894     d2 = pDotV3d*pDotV3d - c ;                 << 
895                                                   963 
896     // Within tolerance inner radius of inner     964     // Within tolerance inner radius of inner G4Sphere
897     // Check for immediate entry/already insid    965     // Check for immediate entry/already inside and travelling outwards
898                                                   966 
899     if ( (c > -halfRminTolerance) && (rad2 < t << 967     if (c >- kRadTolerance*0.5 && pDotV3d >= 0 && rad2 < tolIRMax2 )
900       && ( (d2 < fRmin*kCarTolerance) || (pDot << 
901     {                                             968     {
902       if ( !fFullPhiSphere )                   << 969       if (segPhi)
903       {                                           970       {
904         // Use inner phi tolerant boundary ->     971         // Use inner phi tolerant boundary -> if on tolerant
905         // phi boundaries, phi intersect code     972         // phi boundaries, phi intersect code handles leaving/entering checks
906                                                   973 
907         cosPsi = (p.x()*cosCPhi+p.y()*sinCPhi) << 974         cosPsi = (p.x()*cosCPhi+p.y()*sinCPhi)/sqrt(rho2) ;
908         if (cosPsi >= cosHDPhiIT)                 975         if (cosPsi >= cosHDPhiIT)
909         {                                      << 976         { 
910           // inside radii, delta r -ve, inside    977           // inside radii, delta r -ve, inside phi
911           //                                      978           //
912           if ( !fFullThetaSphere )             << 979           if (segTheta)
913           {                                       980           {
914             if ( (pTheta >= tolSTheta + kAngTo    981             if ( (pTheta >= tolSTheta + kAngTolerance)
915               && (pTheta <= tolETheta - kAngTo    982               && (pTheta <= tolETheta - kAngTolerance) )
916             {                                     983             {
917               return snxt=0;                      984               return snxt=0;
918             }                                     985             }
919           }                                       986           }
920           else                                    987           else
921           {                                       988           {
922             return snxt = 0 ;                     989             return snxt = 0 ;
923           }                                       990           }
924         }                                         991         }
925       }                                           992       }
926       else                                        993       else
927       {                                           994       {
928         if ( !fFullThetaSphere )               << 995         if (segTheta)
929         {                                         996         {
930           if ( (pTheta >= tolSTheta + kAngTole    997           if ( (pTheta >= tolSTheta + kAngTolerance)
931             && (pTheta <= tolETheta - kAngTole    998             && (pTheta <= tolETheta - kAngTolerance) )
932           {                                       999           {
933             return snxt = 0 ;                     1000             return snxt = 0 ;
934           }                                       1001           }
935         }                                         1002         }
936         else                                      1003         else
937         {                                         1004         {
938           return snxt=0;                          1005           return snxt=0;
939         }                                         1006         }
940       }                                           1007       }
941     }                                             1008     }
942     else   // Not special tolerant case           1009     else   // Not special tolerant case
943     {                                             1010     {
                                                   >> 1011       d2 = pDotV3d*pDotV3d - c ;
944       if (d2 >= 0)                                1012       if (d2 >= 0)
945       {                                           1013       {
946         sd = -pDotV3d + std::sqrt(d2) ;        << 1014         s = -pDotV3d + sqrt(d2) ;
947         if ( sd >= halfRminTolerance )  // It  << 1015         if ( s >= kRadTolerance*0.5 )  // It was >= 0 ??
948         {                                         1016         {
949           xi   = p.x() + sd*v.x() ;            << 1017           xi   = p.x() + s*v.x() ;
950           yi   = p.y() + sd*v.y() ;            << 1018           yi   = p.y() + s*v.y() ;
951           rhoi = std::sqrt(xi*xi+yi*yi) ;      << 1019           rhoi = sqrt(xi*xi+yi*yi) ;
952                                                   1020 
953           if ( !fFullPhiSphere && (rhoi != 0.0 << 1021           if ( segPhi && rhoi )   // Check phi intersection
954           {                                       1022           {
955             cosPsi = (xi*cosCPhi + yi*sinCPhi)    1023             cosPsi = (xi*cosCPhi + yi*sinCPhi)/rhoi ;
956                                                   1024 
957             if (cosPsi >= cosHDPhiOT)             1025             if (cosPsi >= cosHDPhiOT)
958             {                                     1026             {
959               if ( !fFullThetaSphere )  // Che << 1027               if (segTheta)  // Check theta intersection
960               {                                   1028               {
961                 zi = p.z() + sd*v.z() ;        << 1029                 zi = p.z() + s*v.z() ;
962                                                   1030 
963                 // rhoi & zi can never both be    1031                 // rhoi & zi can never both be 0
964                 // (=>intersect at origin =>fR    1032                 // (=>intersect at origin =>fRmax=0)
965                 //                                1033                 //
966                 iTheta = std::atan2(rhoi,zi) ; << 1034                 iTheta = atan2(rhoi,zi) ;
967                 if ( (iTheta >= tolSTheta) &&     1035                 if ( (iTheta >= tolSTheta) && (iTheta<=tolETheta) )
968                 {                                 1036                 {
969                   snxt = sd;                   << 1037                   snxt = s ;
970                 }                                 1038                 }
971               }                                   1039               }
972               else                                1040               else
973               {                                   1041               {
974                 snxt=sd;                       << 1042                 snxt=s;
975               }                                   1043               }
976             }                                     1044             }
977           }                                       1045           }
978           else                                    1046           else
979           {                                       1047           {
980             if ( !fFullThetaSphere )   // Chec << 1048             if (segTheta)   // Check theta intersection
981             {                                     1049             {
982               zi = p.z() + sd*v.z() ;          << 1050               zi = p.z() + s*v.z() ;
983                                                   1051 
984               // rhoi & zi can never both be 0    1052               // rhoi & zi can never both be 0
985               // (=>intersect at origin => fRm    1053               // (=>intersect at origin => fRmax=0 !)
986               //                                  1054               //
987               iTheta = std::atan2(rhoi,zi) ;   << 1055               iTheta = atan2(rhoi,zi) ;
988               if ( (iTheta >= tolSTheta) && (i    1056               if ( (iTheta >= tolSTheta) && (iTheta <= tolETheta) )
989               {                                   1057               {
990                 snxt = sd;                     << 1058                 snxt = s ;
991               }                                   1059               }
992             }                                     1060             }
993             else                                  1061             else
994             {                                     1062             {
995               snxt = sd;                       << 1063               snxt=s;
996             }                                     1064             }
997           }                                       1065           }
998         }                                         1066         }
999       }                                           1067       }
1000     }                                            1068     }
1001   }                                              1069   }
1002                                                  1070 
1003   // Phi segment intersection                    1071   // Phi segment intersection
1004   //                                             1072   //
1005   // o Tolerant of points inside phi planes b    1073   // o Tolerant of points inside phi planes by up to kCarTolerance*0.5
1006   //                                             1074   //
1007   // o NOTE: Large duplication of code betwee    1075   // o NOTE: Large duplication of code between sphi & ephi checks
1008   //         -> only diffs: sphi -> ephi, Com    1076   //         -> only diffs: sphi -> ephi, Comp -> -Comp and half-plane
1009   //            intersection check <=0 -> >=0    1077   //            intersection check <=0 -> >=0
1010   //         -> Should use some form of loop     1078   //         -> Should use some form of loop Construct
1011   //                                             1079   //
1012   if ( !fFullPhiSphere )                      << 1080   if ( segPhi )
1013   {                                              1081   {
1014     // First phi surface ('S'tarting phi)     << 1082     // First phi surface (`S'tarting phi)
                                                   >> 1083 
                                                   >> 1084     sinSPhi = sin(fSPhi) ;
                                                   >> 1085     cosSPhi = cos(fSPhi) ;
                                                   >> 1086 
1015     // Comp = Component in outwards normal di    1087     // Comp = Component in outwards normal dirn
1016     //                                           1088     //
1017     Comp = v.x()*sinSPhi - v.y()*cosSPhi ;    << 1089     Comp    = v.x()*sinSPhi - v.y()*cosSPhi  ;
1018                                               << 1090                     
1019     if ( Comp < 0 )                              1091     if ( Comp < 0 )
1020     {                                            1092     {
1021       Dist = p.y()*cosSPhi - p.x()*sinSPhi ;     1093       Dist = p.y()*cosSPhi - p.x()*sinSPhi ;
1022                                                  1094 
1023       if (Dist < halfCarTolerance)            << 1095       if (Dist < kCarTolerance*0.5)
1024       {                                          1096       {
1025         sd = Dist/Comp ;                      << 1097         s = Dist/Comp ;
1026                                                  1098 
1027         if (sd < snxt)                        << 1099         if (s < snxt)
1028         {                                        1100         {
1029           if ( sd > 0 )                       << 1101           if ( s > 0 )
1030           {                                      1102           {
1031             xi    = p.x() + sd*v.x() ;        << 1103             xi    = p.x() + s*v.x() ;
1032             yi    = p.y() + sd*v.y() ;        << 1104             yi    = p.y() + s*v.y() ;
1033             zi    = p.z() + sd*v.z() ;        << 1105             zi    = p.z() + s*v.z() ;
1034             rhoi2 = xi*xi + yi*yi   ;            1106             rhoi2 = xi*xi + yi*yi   ;
1035             radi2 = rhoi2 + zi*zi   ;            1107             radi2 = rhoi2 + zi*zi   ;
1036           }                                      1108           }
1037           else                                   1109           else
1038           {                                      1110           {
1039             sd    = 0     ;                   << 1111             s     = 0     ;
1040             xi    = p.x() ;                      1112             xi    = p.x() ;
1041             yi    = p.y() ;                      1113             yi    = p.y() ;
1042             zi    = p.z() ;                      1114             zi    = p.z() ;
1043             rhoi2 = rho2  ;                      1115             rhoi2 = rho2  ;
1044             radi2 = rad2  ;                      1116             radi2 = rad2  ;
1045           }                                      1117           }
1046           if ( (radi2 <= tolORMax2)              1118           if ( (radi2 <= tolORMax2)
1047             && (radi2 >= tolORMin2)              1119             && (radi2 >= tolORMin2)
1048             && ((yi*cosCPhi-xi*sinCPhi) <= 0)    1120             && ((yi*cosCPhi-xi*sinCPhi) <= 0) )
1049           {                                      1121           {
1050             // Check theta intersection          1122             // Check theta intersection
1051             // rhoi & zi can never both be 0     1123             // rhoi & zi can never both be 0
1052             // (=>intersect at origin =>fRmax    1124             // (=>intersect at origin =>fRmax=0)
1053             //                                   1125             //
1054             if ( !fFullThetaSphere )          << 1126             if ( segTheta )
1055             {                                    1127             {
1056               iTheta = std::atan2(std::sqrt(r << 1128               iTheta = atan2(sqrt(rhoi2),zi) ;
1057               if ( (iTheta >= tolSTheta) && (    1129               if ( (iTheta >= tolSTheta) && (iTheta <= tolETheta) )
1058               {                                  1130               {
1059                 // r and theta intersections     1131                 // r and theta intersections good
1060                 // - check intersecting with     1132                 // - check intersecting with correct half-plane
1061                                                  1133 
1062                 if ((yi*cosCPhi-xi*sinCPhi) <    1134                 if ((yi*cosCPhi-xi*sinCPhi) <= 0)
1063                 {                                1135                 {
1064                   snxt = sd;                  << 1136                   snxt = s ;
1065                 }                                1137                 }
1066               }                                  1138               }
1067             }                                    1139             }
1068             else                                 1140             else
1069             {                                    1141             {
1070               snxt = sd;                      << 1142               snxt = s ;
1071             }                                    1143             }
1072           }                                      1144           }
1073         }                                        1145         }
1074       }                                          1146       }
1075     }                                            1147     }
1076                                                  1148 
1077     // Second phi surface ('E'nding phi)      << 1149     // Second phi surface (`E'nding phi)
1078     // Component in outwards normal dirn      << 
1079                                                  1150 
1080     Comp = -( v.x()*sinEPhi-v.y()*cosEPhi ) ; << 1151     ePhi    = fSPhi + fDPhi ;
                                                   >> 1152     sinEPhi = sin(ePhi)     ;
                                                   >> 1153     cosEPhi = cos(ePhi)     ;
1081                                                  1154 
                                                   >> 1155     // Compnent in outwards normal dirn
                                                   >> 1156 
                                                   >> 1157     Comp    = -( v.x()*sinEPhi-v.y()*cosEPhi ) ;
                                                   >> 1158         
1082     if (Comp < 0)                                1159     if (Comp < 0)
1083     {                                            1160     {
1084       Dist = -(p.y()*cosEPhi-p.x()*sinEPhi) ;    1161       Dist = -(p.y()*cosEPhi-p.x()*sinEPhi) ;
1085       if ( Dist < halfCarTolerance )          << 1162       if ( Dist < kCarTolerance*0.5 )
1086       {                                          1163       {
1087         sd = Dist/Comp ;                      << 1164         s = Dist/Comp ;
1088                                                  1165 
1089         if ( sd < snxt )                      << 1166         if ( s < snxt )
1090         {                                        1167         {
1091           if (sd > 0)                         << 1168           if (s > 0)
1092           {                                      1169           {
1093             xi    = p.x() + sd*v.x() ;        << 1170             xi    = p.x() + s*v.x() ;
1094             yi    = p.y() + sd*v.y() ;        << 1171             yi    = p.y() + s*v.y() ;
1095             zi    = p.z() + sd*v.z() ;        << 1172             zi    = p.z() + s*v.z() ;
1096             rhoi2 = xi*xi + yi*yi   ;            1173             rhoi2 = xi*xi + yi*yi   ;
1097             radi2 = rhoi2 + zi*zi   ;            1174             radi2 = rhoi2 + zi*zi   ;
1098           }                                      1175           }
1099           else                                   1176           else
1100           {                                      1177           {
1101             sd    = 0     ;                   << 1178             s     = 0     ;
1102             xi    = p.x() ;                      1179             xi    = p.x() ;
1103             yi    = p.y() ;                      1180             yi    = p.y() ;
1104             zi    = p.z() ;                      1181             zi    = p.z() ;
1105             rhoi2 = rho2  ;                      1182             rhoi2 = rho2  ;
1106             radi2 = rad2  ;                      1183             radi2 = rad2  ;
1107           }                                      1184           }
1108           if ( (radi2 <= tolORMax2)              1185           if ( (radi2 <= tolORMax2)
1109             && (radi2 >= tolORMin2)              1186             && (radi2 >= tolORMin2)
1110             && ((yi*cosCPhi-xi*sinCPhi) >= 0)    1187             && ((yi*cosCPhi-xi*sinCPhi) >= 0) )
1111           {                                      1188           {
1112             // Check theta intersection          1189             // Check theta intersection
1113             // rhoi & zi can never both be 0     1190             // rhoi & zi can never both be 0
1114             // (=>intersect at origin =>fRmax    1191             // (=>intersect at origin =>fRmax=0)
1115             //                                   1192             //
1116             if ( !fFullThetaSphere )          << 1193             if ( segTheta )
1117             {                                    1194             {
1118               iTheta = std::atan2(std::sqrt(r << 1195               iTheta = atan2(sqrt(rhoi2),zi) ;
1119               if ( (iTheta >= tolSTheta) && (    1196               if ( (iTheta >= tolSTheta) && (iTheta <= tolETheta) )
1120               {                                  1197               {
1121                 // r and theta intersections     1198                 // r and theta intersections good
1122                 // - check intersecting with     1199                 // - check intersecting with correct half-plane
1123                                                  1200 
1124                 if ((yi*cosCPhi-xi*sinCPhi) >    1201                 if ((yi*cosCPhi-xi*sinCPhi) >= 0)
1125                 {                                1202                 {
1126                   snxt = sd;                  << 1203                   snxt = s ;
1127                 }                                1204                 }
1128               }                                  1205               }
1129             }                                    1206             }
1130             else                                 1207             else
1131             {                                    1208             {
1132               snxt = sd;                      << 1209               snxt = s ;
1133             }                                    1210             }
1134           }                                      1211           }
1135         }                                        1212         }
1136       }                                          1213       }
1137     }                                            1214     }
1138   }                                              1215   }
1139                                                  1216 
1140   // Theta segment intersection                  1217   // Theta segment intersection
1141                                                  1218 
1142   if ( !fFullThetaSphere )                    << 1219   if ( segTheta )
1143   {                                              1220   {
1144                                                  1221 
1145     // Intersection with theta surfaces          1222     // Intersection with theta surfaces
1146     // Known failure cases:                      1223     // Known failure cases:
1147     // o  Inside tolerance of stheta surface,    1224     // o  Inside tolerance of stheta surface, skim
1148     //    ~parallel to cone and Hit & enter e    1225     //    ~parallel to cone and Hit & enter etheta surface [& visa versa]
1149     //                                           1226     //
1150     //    To solve: Check 2nd root of etheta     1227     //    To solve: Check 2nd root of etheta surface in addition to stheta
1151     //                                           1228     //
1152     // o  start/end theta is exactly pi/2     << 1229     // o  start/end theta is exactly pi/2 
1153     // Intersections with cones                  1230     // Intersections with cones
1154     //                                           1231     //
1155     // Cone equation: x^2+y^2=z^2tan^2(t)        1232     // Cone equation: x^2+y^2=z^2tan^2(t)
1156     //                                           1233     //
1157     // => (px+svx)^2+(py+svy)^2=(pz+svz)^2tan    1234     // => (px+svx)^2+(py+svy)^2=(pz+svz)^2tan^2(t)
1158     //                                           1235     //
1159     // => (px^2+py^2-pz^2tan^2(t))+2sd(pxvx+p << 1236     // => (px^2+py^2-pz^2tan^2(t))+2s(pxvx+pyvy-pzvztan^2(t))
1160     //       + sd^2(vx^2+vy^2-vz^2tan^2(t)) = << 1237     //       + s^2(vx^2+vy^2-vz^2tan^2(t)) = 0
1161     //                                           1238     //
1162     // => sd^2(1-vz^2(1+tan^2(t))+2sd(pdotv2d << 1239     // => s^2(1-vz^2(1+tan^2(t))+2s(pdotv2d-pzvztan^2(t))+(rho2-pz^2tan^2(t))=0
1163     //       + (rho2-pz^2tan^2(t)) = 0        << 
1164                                                  1240 
1165     if (fSTheta != 0.0)                       << 1241     tanSTheta  = tan(fSTheta)         ;
                                                   >> 1242     tanSTheta2 = tanSTheta*tanSTheta  ;
                                                   >> 1243     tanETheta  = tan(fSTheta+fDTheta) ;
                                                   >> 1244     tanETheta2 = tanETheta*tanETheta  ;
                                                   >> 1245       
                                                   >> 1246     if (fSTheta)
1166     {                                            1247     {
1167       dist2STheta = rho2 - p.z()*p.z()*tanSTh    1248       dist2STheta = rho2 - p.z()*p.z()*tanSTheta2 ;
1168     }                                            1249     }
1169     else                                         1250     else
1170     {                                            1251     {
1171       dist2STheta = kInfinity ;                  1252       dist2STheta = kInfinity ;
1172     }                                            1253     }
1173     if ( eTheta < pi )                        << 1254     if ( fSTheta + fDTheta < M_PI )
1174     {                                            1255     {
1175       dist2ETheta=rho2-p.z()*p.z()*tanETheta2    1256       dist2ETheta=rho2-p.z()*p.z()*tanETheta2;
1176     }                                            1257     }
1177     else                                      << 1258       else
1178     {                                            1259     {
1179       dist2ETheta=kInfinity;                     1260       dist2ETheta=kInfinity;
1180     }                                         << 1261     }      
1181     if ( pTheta < tolSTheta )                 << 1262     if ( pTheta < tolSTheta) // dist2STheta<-kRadTolerance*0.5 && dist2ETheta>0)
1182     {                                            1263     {
1183       // Inside (theta<stheta-tol) stheta con << 1264       // Inside (theta<stheta-tol) s theta cone
1184       // First root of stheta cone, second if    1265       // First root of stheta cone, second if first root -ve
1185                                                  1266 
1186       t1 = 1 - v.z()*v.z()*(1 + tanSTheta2) ;    1267       t1 = 1 - v.z()*v.z()*(1 + tanSTheta2) ;
1187       t2 = pDotV2d - p.z()*v.z()*tanSTheta2 ;    1268       t2 = pDotV2d - p.z()*v.z()*tanSTheta2 ;
1188       if (t1 != 0.0)                          << 1269         
                                                   >> 1270       b  = t2/t1 ;
                                                   >> 1271       c  = dist2STheta/t1 ;
                                                   >> 1272       d2 = b*b - c ;
                                                   >> 1273 
                                                   >> 1274       if ( d2 >= 0 )
1189       {                                          1275       {
                                                   >> 1276         d = sqrt(d2) ;
                                                   >> 1277         s = -b - d ;    // First root
                                                   >> 1278 
                                                   >> 1279         if ( s < 0 )
                                                   >> 1280         {
                                                   >> 1281           s=-b+d;    // Second root
                                                   >> 1282         }
                                                   >> 1283         if (s >= 0 && s < snxt)
                                                   >> 1284         {
                                                   >> 1285           xi    = p.x() + s*v.x() ;
                                                   >> 1286           yi    = p.y() + s*v.y() ;
                                                   >> 1287           zi    = p.z() + s*v.z() ;
                                                   >> 1288           rhoi2 = xi*xi + yi*yi   ;
                                                   >> 1289           radi2 = rhoi2 + zi*zi   ;
                                                   >> 1290           if ( (radi2 <= tolORMax2)
                                                   >> 1291             && (radi2 >= tolORMin2)
                                                   >> 1292             && (zi*(fSTheta - 0.5*pi) <= 0) )
                                                   >> 1293           {
                                                   >> 1294             if ( segPhi && rhoi2 )  // Check phi intersection
                                                   >> 1295             {
                                                   >> 1296               cosPsi = (xi*cosCPhi + yi*sinCPhi)/sqrt(rhoi2) ;
                                                   >> 1297               if (cosPsi >= cosHDPhiOT)
                                                   >> 1298               {
                                                   >> 1299                 snxt = s ;
                                                   >> 1300               }
                                                   >> 1301             }
                                                   >> 1302             else
                                                   >> 1303             {
                                                   >> 1304               snxt = s ;
                                                   >> 1305             }
                                                   >> 1306           }
                                                   >> 1307         }
                                                   >> 1308       }
                                                   >> 1309 
                                                   >> 1310       // Possible intersection with ETheta cone. 
                                                   >> 1311       // Second >= 0 root should be considered
                                                   >> 1312         
                                                   >> 1313       if ( fSTheta + fDTheta < M_PI )
                                                   >> 1314       {
                                                   >> 1315         t1 = 1 - v.z()*v.z()*(1 + tanETheta2) ;
                                                   >> 1316         t2 = pDotV2d - p.z()*v.z()*tanETheta2 ;
                                                   >> 1317         
1190         b  = t2/t1 ;                             1318         b  = t2/t1 ;
1191         c  = dist2STheta/t1 ;                 << 1319         c  = dist2ETheta/t1 ;
1192         d2 = b*b - c ;                           1320         d2 = b*b - c ;
1193                                                  1321 
1194         if ( d2 >= 0 )                        << 1322         if (d2 >= 0)
1195         {                                        1323         {
1196           d  = std::sqrt(d2) ;                << 1324           d = sqrt(d2) ;
1197           sd = -b - d ;    // First root      << 1325           s = -b + d ;    // Second root
1198           zi = p.z() + sd*v.z();              << 
1199                                                  1326 
1200           if ( (sd < 0) || (zi*(fSTheta - hal << 1327           if (s >= 0 && s < snxt)
1201           {                                      1328           {
1202             sd = -b+d;    // Second root      << 1329             xi    = p.x() + s*v.x() ;
1203           }                                   << 1330             yi    = p.y() + s*v.y() ;
1204           if ((sd >= 0) && (sd < snxt))       << 1331             zi    = p.z() + s*v.z() ;
1205           {                                   << 1332             rhoi2 = xi*xi + yi*yi   ;
1206             xi    = p.x() + sd*v.x();         << 1333             radi2 = rhoi2 + zi*zi   ;
1207             yi    = p.y() + sd*v.y();         << 1334 
1208             zi    = p.z() + sd*v.z();         << 
1209             rhoi2 = xi*xi + yi*yi;            << 
1210             radi2 = rhoi2 + zi*zi;            << 
1211             if ( (radi2 <= tolORMax2)            1335             if ( (radi2 <= tolORMax2)
1212               && (radi2 >= tolORMin2)            1336               && (radi2 >= tolORMin2)
1213               && (zi*(fSTheta - halfpi) <= 0) << 1337               && (zi*(fSTheta + fDTheta - 0.5*pi) <= 0) )
1214             {                                    1338             {
1215               if ( !fFullPhiSphere && (rhoi2  << 1339               if (segPhi && rhoi2)   // Check phi intersection
1216               {                                  1340               {
1217                 cosPsi = (xi*cosCPhi + yi*sin << 1341                 cosPsi = (xi*cosCPhi + yi*sinCPhi)/sqrt(rhoi2) ;
1218                 if (cosPsi >= cosHDPhiOT)        1342                 if (cosPsi >= cosHDPhiOT)
1219                 {                                1343                 {
1220                   snxt = sd;                  << 1344                   snxt = s ;
1221                 }                                1345                 }
1222               }                                  1346               }
1223               else                               1347               else
1224               {                                  1348               {
1225                 snxt = sd;                    << 1349                 snxt = s ;
1226               }                                  1350               }
1227             }                                    1351             }
1228           }                                      1352           }
1229         }                                        1353         }
1230       }                                          1354       }
                                                   >> 1355     }  
                                                   >> 1356     else if (pTheta > tolETheta) 
                                                   >> 1357     { // dist2ETheta<-kRadTolerance*0.5 && dist2STheta>0)
                                                   >> 1358       // Inside (theta>etheta+tol) e theta cone
                                                   >> 1359       // First root of etheta cone, second if first root `imaginary'
1231                                                  1360 
1232       // Possible intersection with ETheta co << 1361       t1 = 1 - v.z()*v.z()*(1 + tanETheta2) ;
1233       // Second >= 0 root should be considere << 1362       t2 = pDotV2d - p.z()*v.z()*tanETheta2 ;
                                                   >> 1363         
                                                   >> 1364       b  = t2/t1 ;
                                                   >> 1365       c  = dist2ETheta/t1 ;
                                                   >> 1366       d2 = b*b - c ;
1234                                                  1367 
1235       if ( eTheta < pi )                      << 1368       if (d2 >= 0)
1236       {                                          1369       {
1237         t1 = 1 - v.z()*v.z()*(1 + tanETheta2) << 1370         d = sqrt(d2) ;
1238         t2 = pDotV2d - p.z()*v.z()*tanETheta2 << 1371         s = -b - d ;    // First root
1239         if (t1 != 0.0)                        << 1372         if (s < 0)
1240         {                                     << 1373         {
1241           b  = t2/t1 ;                        << 1374           s = -b + d ;           // second root
1242           c  = dist2ETheta/t1 ;               << 1375         }
1243           d2 = b*b - c ;                      << 1376         if (s >= 0 && s < snxt)
                                                   >> 1377         {
                                                   >> 1378           xi    = p.x() + s*v.x() ;
                                                   >> 1379           yi    = p.y() + s*v.y() ;
                                                   >> 1380           zi    = p.z() + s*v.z() ;
                                                   >> 1381           rhoi2 = xi*xi + yi*yi   ;
                                                   >> 1382           radi2 = rhoi2 + zi*zi   ;
1244                                                  1383 
1245           if (d2 >= 0)                        << 1384           if ( (radi2 <= tolORMax2)
                                                   >> 1385             && (radi2 >= tolORMin2) 
                                                   >> 1386             && (zi*(fSTheta + fDTheta - 0.5*pi) <= 0) )
1246           {                                      1387           {
1247             d  = std::sqrt(d2) ;              << 1388             if (segPhi && rhoi2)  // Check phi intersection
1248             sd = -b + d ;    // Second root   << 
1249                                               << 
1250             if ( (sd >= 0) && (sd < snxt) )   << 
1251             {                                    1389             {
1252               xi    = p.x() + sd*v.x() ;      << 1390               cosPsi = (xi*cosCPhi + yi*sinCPhi)/sqrt(rhoi2) ;
1253               yi    = p.y() + sd*v.y() ;      << 1391               if (cosPsi >= cosHDPhiOT)
1254               zi    = p.z() + sd*v.z() ;      << 
1255               rhoi2 = xi*xi + yi*yi   ;       << 
1256               radi2 = rhoi2 + zi*zi   ;       << 
1257                                               << 
1258               if ( (radi2 <= tolORMax2)       << 
1259                 && (radi2 >= tolORMin2)       << 
1260                 && (zi*(eTheta - halfpi) <= 0 << 
1261               {                                  1392               {
1262                 if (!fFullPhiSphere && (rhoi2 << 1393                 snxt = s ;
1263                 {                             << 
1264                   cosPsi = (xi*cosCPhi + yi*s << 
1265                   if (cosPsi >= cosHDPhiOT)   << 
1266                   {                           << 
1267                     snxt = sd;                << 
1268                   }                           << 
1269                 }                             << 
1270                 else                          << 
1271                 {                             << 
1272                   snxt = sd;                  << 
1273                 }                             << 
1274               }                                  1394               }
1275             }                                    1395             }
                                                   >> 1396             else
                                                   >> 1397             {
                                                   >> 1398               snxt = s ;
                                                   >> 1399             }
1276           }                                      1400           }
1277         }                                        1401         }
1278       }                                          1402       }
1279     }                                         << 
1280     else if ( pTheta > tolETheta )            << 
1281     {                                         << 
1282       // dist2ETheta<-kRadTolerance*0.5 && di << 
1283       // Inside (theta > etheta+tol) e-theta  << 
1284       // First root of etheta cone, second if << 
1285                                                  1403 
1286       t1 = 1 - v.z()*v.z()*(1 + tanETheta2) ; << 1404       // Possible intersection with STheta cone. 
1287       t2 = pDotV2d - p.z()*v.z()*tanETheta2 ; << 1405       // Second >= 0 root should be considered
1288       if (t1 != 0.0)                          << 1406         
                                                   >> 1407       if ( fSTheta )
1289       {                                          1408       {
                                                   >> 1409         t1 = 1 - v.z()*v.z()*(1 + tanSTheta2) ;
                                                   >> 1410         t2 = pDotV2d - p.z()*v.z()*tanSTheta2 ;
                                                   >> 1411 
1290         b  = t2/t1 ;                             1412         b  = t2/t1 ;
1291         c  = dist2ETheta/t1 ;                 << 1413         c  = dist2STheta/t1 ;
1292         d2 = b*b - c ;                           1414         d2 = b*b - c ;
1293                                                  1415 
1294         if (d2 >= 0)                             1416         if (d2 >= 0)
1295         {                                        1417         {
1296           d  = std::sqrt(d2) ;                << 1418           d = sqrt(d2) ;
1297           sd = -b - d ;    // First root      << 1419           s = -b + d ;    // Second root
1298           zi = p.z() + sd*v.z();              << 
1299                                                  1420 
1300           if ( (sd < 0) || (zi*(eTheta - half << 1421           if ( (s >= 0) && (s < snxt) )
1301           {                                      1422           {
1302             sd = -b + d ;           // second << 1423             xi    = p.x() + s*v.x() ;
1303           }                                   << 1424             yi    = p.y() + s*v.y() ;
1304           if ( (sd >= 0) && (sd < snxt) )     << 1425             zi    = p.z() + s*v.z() ;
1305           {                                   << 
1306             xi    = p.x() + sd*v.x() ;        << 
1307             yi    = p.y() + sd*v.y() ;        << 
1308             zi    = p.z() + sd*v.z() ;        << 
1309             rhoi2 = xi*xi + yi*yi   ;            1426             rhoi2 = xi*xi + yi*yi   ;
1310             radi2 = rhoi2 + zi*zi   ;            1427             radi2 = rhoi2 + zi*zi   ;
1311                                                  1428 
1312             if ( (radi2 <= tolORMax2)            1429             if ( (radi2 <= tolORMax2)
1313               && (radi2 >= tolORMin2)            1430               && (radi2 >= tolORMin2)
1314               && (zi*(eTheta - halfpi) <= 0)  << 1431               && (zi*(fSTheta - 0.5*pi) <= 0) )
1315             {                                    1432             {
1316               if (!fFullPhiSphere && (rhoi2 ! << 1433               if (segPhi && rhoi2)   // Check phi intersection
1317               {                                  1434               {
1318                 cosPsi = (xi*cosCPhi + yi*sin << 1435                 cosPsi = (xi*cosCPhi + yi*sinCPhi)/sqrt(rhoi2) ;
1319                 if (cosPsi >= cosHDPhiOT)        1436                 if (cosPsi >= cosHDPhiOT)
1320                 {                                1437                 {
1321                   snxt = sd;                  << 1438                   snxt = s ;
1322                 }                                1439                 }
1323               }                                  1440               }
1324               else                               1441               else
1325               {                                  1442               {
1326                 snxt = sd;                    << 1443                 snxt = s ;
1327               }                                  1444               }
1328             }                                    1445             }
1329           }                                      1446           }
1330         }                                        1447         }
1331       }                                       << 1448       }  
1332                                               << 1449     }     
1333       // Possible intersection with STheta co << 1450     else if ( (pTheta <tolSTheta + kAngTolerance)
1334       // Second >= 0 root should be considere << 1451            && (fSTheta > kAngTolerance) )
1335                                               << 
1336       if ( fSTheta != 0.0 )                   << 
1337       {                                       << 
1338         t1 = 1 - v.z()*v.z()*(1 + tanSTheta2) << 
1339         t2 = pDotV2d - p.z()*v.z()*tanSTheta2 << 
1340         if (t1 != 0.0)                        << 
1341         {                                     << 
1342           b  = t2/t1 ;                        << 
1343           c  = dist2STheta/t1 ;               << 
1344           d2 = b*b - c ;                      << 
1345                                               << 
1346           if (d2 >= 0)                        << 
1347           {                                   << 
1348             d  = std::sqrt(d2) ;              << 
1349             sd = -b + d ;    // Second root   << 
1350                                               << 
1351             if ( (sd >= 0) && (sd < snxt) )   << 
1352             {                                 << 
1353               xi    = p.x() + sd*v.x() ;      << 
1354               yi    = p.y() + sd*v.y() ;      << 
1355               zi    = p.z() + sd*v.z() ;      << 
1356               rhoi2 = xi*xi + yi*yi   ;       << 
1357               radi2 = rhoi2 + zi*zi   ;       << 
1358                                               << 
1359               if ( (radi2 <= tolORMax2)       << 
1360                 && (radi2 >= tolORMin2)       << 
1361                 && (zi*(fSTheta - halfpi) <=  << 
1362               {                               << 
1363                 if (!fFullPhiSphere && (rhoi2 << 
1364                 {                             << 
1365                   cosPsi = (xi*cosCPhi + yi*s << 
1366                   if (cosPsi >= cosHDPhiOT)   << 
1367                   {                           << 
1368                     snxt = sd;                << 
1369                   }                           << 
1370                 }                             << 
1371                 else                          << 
1372                 {                             << 
1373                   snxt = sd;                  << 
1374                 }                             << 
1375               }                               << 
1376             }                                 << 
1377           }                                   << 
1378         }                                     << 
1379       }                                       << 
1380     }                                         << 
1381     else if ( (pTheta < tolSTheta + kAngToler << 
1382            && (fSTheta > halfAngTolerance) )  << 
1383     {                                            1452     {
1384       // In tolerance of stheta                  1453       // In tolerance of stheta
1385       // If entering through solid [r,phi] =>    1454       // If entering through solid [r,phi] => 0 to in
1386       // else try 2nd root                       1455       // else try 2nd root
1387                                                  1456 
1388       t2 = pDotV2d - p.z()*v.z()*tanSTheta2 ;    1457       t2 = pDotV2d - p.z()*v.z()*tanSTheta2 ;
1389       if ( (t2>=0 && tolIRMin2<rad2 && rad2<t << 1458       if ( (t2>=0 && tolIRMin2<rad2 && rad2<tolIRMax2 && fSTheta<M_PI*.5)
1390         || (t2<0  && tolIRMin2<rad2 && rad2<t << 1459         || (t2<0  && tolIRMin2<rad2 && rad2<tolIRMax2 && fSTheta>M_PI*.5)
1391         || (v.z()<0 && tolIRMin2<rad2 && rad2 << 1460         || (v.z()<0 && tolIRMin2<rad2 && rad2<tolIRMax2 && fSTheta==M_PI*.5) )
1392       {                                          1461       {
1393         if (!fFullPhiSphere && (rho2 != 0.0)) << 1462         if (segPhi && rho2)  // Check phi intersection
1394         {                                        1463         {
1395           cosPsi = (p.x()*cosCPhi + p.y()*sin << 1464           cosPsi = (p.x()*cosCPhi + p.y()*sinCPhi)/sqrt(rho2) ;
1396           if (cosPsi >= cosHDPhiIT)              1465           if (cosPsi >= cosHDPhiIT)
1397           {                                      1466           {
1398             return 0 ;                           1467             return 0 ;
1399           }                                      1468           }
1400         }                                        1469         }
1401         else                                     1470         else
1402         {                                        1471         {
1403           return 0 ;                             1472           return 0 ;
1404         }                                        1473         }
1405       }                                          1474       }
1406                                                  1475 
1407       // Not entering immediately/travelling     1476       // Not entering immediately/travelling through
1408                                                  1477 
1409       t1 = 1 - v.z()*v.z()*(1 + tanSTheta2) ;    1478       t1 = 1 - v.z()*v.z()*(1 + tanSTheta2) ;
1410       if (t1 != 0.0)                          << 1479       b  = t2/t1 ;
1411       {                                       << 1480       c  = dist2STheta/t1 ;
1412         b  = t2/t1 ;                          << 1481       d2 = b*b - c ;
1413         c  = dist2STheta/t1 ;                 << 
1414         d2 = b*b - c ;                        << 
1415                                                  1482 
1416         if (d2 >= 0)                          << 1483       if (d2 >= 0)
1417         {                                     << 1484       {
1418           d  = std::sqrt(d2) ;                << 1485         d = sqrt(d2) ;
1419           sd = -b + d ;                       << 1486         s = -b + d ;
1420           if ( (sd >= halfCarTolerance) && (s << 1487         if ( (s >= kCarTolerance*0.5) && (s < snxt) && (fSTheta < M_PI*0.5) )
1421           {   // ^^^^^^^^^^^^^^^^^^^^^  shoul << 1488         {
1422             xi    = p.x() + sd*v.x() ;        << 1489           xi    = p.x() + s*v.x() ;
1423             yi    = p.y() + sd*v.y() ;        << 1490           yi    = p.y() + s*v.y() ;
1424             zi    = p.z() + sd*v.z() ;        << 1491           zi    = p.z() + s*v.z() ;
1425             rhoi2 = xi*xi + yi*yi   ;         << 1492           rhoi2 = xi*xi + yi*yi   ;
1426             radi2 = rhoi2 + zi*zi   ;         << 1493           radi2 = rhoi2 + zi*zi   ;
1427                                                  1494 
1428             if ( (radi2 <= tolORMax2)         << 1495           if ( (radi2 <= tolORMax2)
1429               && (radi2 >= tolORMin2)         << 1496             && (radi2 >= tolORMin2)
1430               && (zi*(fSTheta - halfpi) <= 0) << 1497             && (zi*(fSTheta - 0.5*pi) <= 0) )
                                                   >> 1498           {
                                                   >> 1499             if ( segPhi && rhoi2 )    // Check phi intersection
1431             {                                    1500             {
1432               if ( !fFullPhiSphere && (rhoi2  << 1501               cosPsi = (xi*cosCPhi + yi*sinCPhi)/sqrt(rhoi2) ;
1433               {                               << 1502               if ( cosPsi >= cosHDPhiOT )
1434                 cosPsi = (xi*cosCPhi + yi*sin << 
1435                 if ( cosPsi >= cosHDPhiOT )   << 
1436                 {                             << 
1437                   snxt = sd;                  << 
1438                 }                             << 
1439               }                               << 
1440               else                            << 
1441               {                                  1503               {
1442                 snxt = sd;                    << 1504                 snxt = s ;
1443               }                                  1505               }
1444             }                                    1506             }
                                                   >> 1507             else
                                                   >> 1508             {
                                                   >> 1509               snxt = s ;
                                                   >> 1510             }
1445           }                                      1511           }
1446         }                                        1512         }
1447       }                                          1513       }
1448     }                                         << 1514     }   
1449     else if ((pTheta > tolETheta-kAngToleranc << 1515     else if ( (pTheta > tolETheta - kAngTolerance)
                                                   >> 1516            && ((fSTheta + fDTheta) < M_PI-kAngTolerance) )   
1450     {                                            1517     {
1451                                                  1518 
1452       // In tolerance of etheta                  1519       // In tolerance of etheta
1453       // If entering through solid [r,phi] =>    1520       // If entering through solid [r,phi] => 0 to in
1454       // else try 2nd root                       1521       // else try 2nd root
1455                                                  1522 
1456       t2 = pDotV2d - p.z()*v.z()*tanETheta2 ;    1523       t2 = pDotV2d - p.z()*v.z()*tanETheta2 ;
1457                                                  1524 
1458       if (   ((t2<0) && (eTheta < halfpi)     << 1525       if (
1459           && (tolIRMin2 < rad2) && (rad2 < to << 1526     (t2<0    && (fSTheta+fDTheta) <M_PI*0.5 && tolIRMin2<rad2 && rad2<tolIRMax2)
1460         ||   ((t2>=0) && (eTheta > halfpi)    << 1527  || (t2>=0   && (fSTheta+fDTheta) >M_PI*0.5 && tolIRMin2<rad2 && rad2<tolIRMax2)
1461           && (tolIRMin2 < rad2) && (rad2 < to << 1528  || (v.z()>0 && (fSTheta+fDTheta)==M_PI*0.5 && tolIRMin2<rad2 && rad2<tolIRMax2)
1462         ||   ((v.z()>0) && (eTheta == halfpi) << 1529          )
1463           && (tolIRMin2 < rad2) && (rad2 < to << 
1464       {                                          1530       {
1465         if (!fFullPhiSphere && (rho2 != 0.0)) << 1531         if (segPhi && rho2)   // Check phi intersection
1466         {                                        1532         {
1467           cosPsi = (p.x()*cosCPhi + p.y()*sin << 1533           cosPsi = (p.x()*cosCPhi + p.y()*sinCPhi)/sqrt(rho2) ;
1468           if (cosPsi >= cosHDPhiIT)              1534           if (cosPsi >= cosHDPhiIT)
1469           {                                      1535           {
1470             return 0 ;                           1536             return 0 ;
1471           }                                      1537           }
1472         }                                        1538         }
1473         else                                     1539         else
1474         {                                        1540         {
1475           return 0 ;                             1541           return 0 ;
1476         }                                        1542         }
1477       }                                          1543       }
1478                                                  1544 
1479       // Not entering immediately/travelling     1545       // Not entering immediately/travelling through
1480                                                  1546 
1481       t1 = 1 - v.z()*v.z()*(1 + tanETheta2) ;    1547       t1 = 1 - v.z()*v.z()*(1 + tanETheta2) ;
1482       if (t1 != 0.0)                          << 1548       b  = t2/t1 ;
1483       {                                       << 1549       c  = dist2ETheta/t1 ;
1484         b  = t2/t1 ;                          << 1550       d2 = b*b - c ;
1485         c  = dist2ETheta/t1 ;                 << 
1486         d2 = b*b - c ;                        << 
1487                                                  1551 
1488         if (d2 >= 0)                          << 1552       if (d2 >= 0)
1489         {                                     << 1553       {
1490           d  = std::sqrt(d2) ;                << 1554         d = sqrt(d2) ;
1491           sd = -b + d ;                       << 1555         s = -b + d ;
                                                   >> 1556         
                                                   >> 1557         if ( (s >= kCarTolerance*0.5)
                                                   >> 1558           && (s < snxt) && ((fSTheta + fDTheta) > M_PI*0.5) )
                                                   >> 1559         {
                                                   >> 1560           xi    = p.x() + s*v.x() ;
                                                   >> 1561           yi    = p.y() + s*v.y() ;
                                                   >> 1562           zi    = p.z() + s*v.z() ;
                                                   >> 1563           rhoi2 = xi*xi + yi*yi   ;
                                                   >> 1564           radi2 = rhoi2 + zi*zi   ;
1492                                                  1565 
1493           if ( (sd >= halfCarTolerance)       << 1566           if ( (radi2 <= tolORMax2)
1494             && (sd < snxt) && (eTheta > halfp << 1567             && (radi2 >= tolORMin2)
                                                   >> 1568             && (zi*(fSTheta + fDTheta - 0.5*pi) <= 0) )
1495           {                                      1569           {
1496             xi    = p.x() + sd*v.x() ;        << 1570             if (segPhi && rhoi2)   // Check phi intersection
1497             yi    = p.y() + sd*v.y() ;        << 
1498             zi    = p.z() + sd*v.z() ;        << 
1499             rhoi2 = xi*xi + yi*yi   ;         << 
1500             radi2 = rhoi2 + zi*zi   ;         << 
1501                                               << 
1502             if ( (radi2 <= tolORMax2)         << 
1503               && (radi2 >= tolORMin2)         << 
1504               && (zi*(eTheta - halfpi) <= 0)  << 
1505             {                                    1571             {
1506               if (!fFullPhiSphere && (rhoi2 ! << 1572               cosPsi = (xi*cosCPhi + yi*sinCPhi)/sqrt(rhoi2) ;
1507               {                               << 1573               if (cosPsi>=cosHDPhiOT)
1508                 cosPsi = (xi*cosCPhi + yi*sin << 
1509                 if (cosPsi >= cosHDPhiOT)     << 
1510                 {                             << 
1511                   snxt = sd;                  << 
1512                 }                             << 
1513               }                               << 
1514               else                            << 
1515               {                                  1574               {
1516                 snxt = sd;                    << 1575                 snxt = s ;
1517               }                                  1576               }
1518             }                                    1577             }
                                                   >> 1578             else
                                                   >> 1579             {
                                                   >> 1580               snxt = s ;
                                                   >> 1581             }
1519           }                                      1582           }
1520         }                                        1583         }
1521       }                                       << 1584       }    
1522     }                                         << 1585     }  
1523     else                                         1586     else
1524     {                                            1587     {
1525       // stheta+tol<theta<etheta-tol             1588       // stheta+tol<theta<etheta-tol
1526       // For BOTH stheta & etheta check 2nd r    1589       // For BOTH stheta & etheta check 2nd root for validity [r,phi]
1527                                                  1590 
1528       t1 = 1 - v.z()*v.z()*(1 + tanSTheta2) ;    1591       t1 = 1 - v.z()*v.z()*(1 + tanSTheta2) ;
1529       t2 = pDotV2d - p.z()*v.z()*tanSTheta2 ;    1592       t2 = pDotV2d - p.z()*v.z()*tanSTheta2 ;
1530       if (t1 != 0.0)                          << 1593 
                                                   >> 1594       b  = t2/t1;
                                                   >> 1595       c  = dist2STheta/t1 ;
                                                   >> 1596       d2 = b*b - c ;
                                                   >> 1597 
                                                   >> 1598       if (d2 >= 0)
1531       {                                          1599       {
1532         b  = t2/t1;                           << 1600         d = sqrt(d2) ;
1533         c  = dist2STheta/t1 ;                 << 1601         s = -b + d ;    // second root
1534         d2 = b*b - c ;                        << 
1535                                                  1602 
1536         if (d2 >= 0)                          << 1603         if (s >= 0 && s < snxt)
1537         {                                        1604         {
1538           d  = std::sqrt(d2) ;                << 1605           xi    = p.x() + s*v.x() ;
1539           sd = -b + d ;    // second root     << 1606           yi    = p.y() + s*v.y() ;
                                                   >> 1607           zi    = p.z() + s*v.z() ;
                                                   >> 1608           rhoi2 = xi*xi + yi*yi   ;
                                                   >> 1609           radi2 = rhoi2 + zi*zi   ;
1540                                                  1610 
1541           if ((sd >= 0) && (sd < snxt))       << 1611           if ( (radi2 <= tolORMax2)
                                                   >> 1612             && (radi2 >= tolORMin2)
                                                   >> 1613             && (zi*(fSTheta - 0.5*pi) <= 0) )
1542           {                                      1614           {
1543             xi    = p.x() + sd*v.x() ;        << 1615             if (segPhi && rhoi2)   // Check phi intersection
1544             yi    = p.y() + sd*v.y() ;        << 
1545             zi    = p.z() + sd*v.z() ;        << 
1546             rhoi2 = xi*xi + yi*yi   ;         << 
1547             radi2 = rhoi2 + zi*zi   ;         << 
1548                                               << 
1549             if ( (radi2 <= tolORMax2)         << 
1550               && (radi2 >= tolORMin2)         << 
1551               && (zi*(fSTheta - halfpi) <= 0) << 
1552             {                                    1616             {
1553               if (!fFullPhiSphere && (rhoi2 ! << 1617               cosPsi = (xi*cosCPhi + yi*sinCPhi)/sqrt(rhoi2) ;
1554               {                               << 1618               if (cosPsi >= cosHDPhiOT)
1555                 cosPsi = (xi*cosCPhi + yi*sin << 
1556                 if (cosPsi >= cosHDPhiOT)     << 
1557                 {                             << 
1558                   snxt = sd;                  << 
1559                 }                             << 
1560               }                               << 
1561               else                            << 
1562               {                                  1619               {
1563                 snxt = sd;                    << 1620                 snxt = s ;
1564               }                                  1621               }
1565             }                                    1622             }
                                                   >> 1623             else
                                                   >> 1624             {
                                                   >> 1625               snxt = s ;
                                                   >> 1626             }
1566           }                                      1627           }
1567         }                                        1628         }
1568       }                                       << 1629       }        
1569       t1 = 1 - v.z()*v.z()*(1 + tanETheta2) ;    1630       t1 = 1 - v.z()*v.z()*(1 + tanETheta2) ;
1570       t2 = pDotV2d - p.z()*v.z()*tanETheta2 ;    1631       t2 = pDotV2d - p.z()*v.z()*tanETheta2 ;
1571       if (t1 != 0.0)                          << 1632         
                                                   >> 1633       b  = t2/t1 ;
                                                   >> 1634       c  = dist2ETheta/t1 ;
                                                   >> 1635       d2 = b*b - c ;
                                                   >> 1636 
                                                   >> 1637       if (d2 >= 0)
1572       {                                          1638       {
1573         b  = t2/t1 ;                          << 1639         d = sqrt(d2) ;
1574         c  = dist2ETheta/t1 ;                 << 1640         s = -b + d;    // second root
1575         d2 = b*b - c ;                        << 
1576                                                  1641 
1577         if (d2 >= 0)                          << 1642         if (s >= 0 && s < snxt)
1578         {                                        1643         {
1579           d  = std::sqrt(d2) ;                << 1644           xi    = p.x() + s*v.x() ;
1580           sd = -b + d;    // second root      << 1645           yi    = p.y() + s*v.y() ;
                                                   >> 1646           zi    = p.z() + s*v.z() ;
                                                   >> 1647           rhoi2 = xi*xi + yi*yi   ;
                                                   >> 1648           radi2 = rhoi2 + zi*zi   ;
1581                                                  1649 
1582           if ((sd >= 0) && (sd < snxt))       << 1650           if ( (radi2 <= tolORMax2)
                                                   >> 1651             && (radi2 >= tolORMin2)
                                                   >> 1652             && (zi*(fSTheta + fDTheta - 0.5*pi) <= 0) )
1583           {                                      1653           {
1584             xi    = p.x() + sd*v.x() ;        << 1654             if (segPhi && rhoi2)   // Check phi intersection
1585             yi    = p.y() + sd*v.y() ;        << 
1586             zi    = p.z() + sd*v.z() ;        << 
1587             rhoi2 = xi*xi + yi*yi   ;         << 
1588             radi2 = rhoi2 + zi*zi   ;         << 
1589                                               << 
1590             if ( (radi2 <= tolORMax2)         << 
1591               && (radi2 >= tolORMin2)         << 
1592               && (zi*(eTheta - halfpi) <= 0)  << 
1593             {                                    1655             {
1594               if (!fFullPhiSphere && (rhoi2 ! << 1656               cosPsi = (xi*cosCPhi + yi*sinCPhi)/sqrt(rhoi2) ;
                                                   >> 1657               if ( cosPsi >= cosHDPhiOT )
1595               {                                  1658               {
1596                 cosPsi = (xi*cosCPhi + yi*sin << 1659                 snxt=s;
1597                 if ( cosPsi >= cosHDPhiOT )   << 
1598                 {                             << 
1599                   snxt = sd;                  << 
1600                 }                             << 
1601               }                               << 
1602               else                            << 
1603               {                               << 
1604                 snxt = sd;                    << 
1605               }                                  1660               }
1606             }                                    1661             }
                                                   >> 1662             else
                                                   >> 1663             {
                                                   >> 1664               snxt = s ;
                                                   >> 1665             }
1607           }                                      1666           }
1608         }                                        1667         }
1609       }                                          1668       }
1610     }                                         << 1669     }  
1611   }                                              1670   }
1612   return snxt;                                   1671   return snxt;
1613 }                                                1672 }
1614                                                  1673 
1615 /////////////////////////////////////////////    1674 //////////////////////////////////////////////////////////////////////
1616 //                                               1675 //
1617 // Calculate distance (<= actual) to closest     1676 // Calculate distance (<= actual) to closest surface of shape from outside
1618 // - Calculate distance to radial planes         1677 // - Calculate distance to radial planes
1619 // - Only to phi planes if outside phi extent    1678 // - Only to phi planes if outside phi extent
1620 // - Only to theta planes if outside theta ex    1679 // - Only to theta planes if outside theta extent
1621 // - Return 0 if point inside                    1680 // - Return 0 if point inside
1622                                                  1681 
1623 G4double G4Sphere::DistanceToIn( const G4Thre    1682 G4double G4Sphere::DistanceToIn( const G4ThreeVector& p ) const
1624 {                                                1683 {
1625   G4double safe=0.0,safeRMin,safeRMax,safePhi << 1684   G4double safe,safeRMin,safeRMax,safePhi,safeTheta;
1626   G4double rho2,rds,rho;                      << 1685   G4double rho2,rad,rho;
1627   G4double cosPsi;                            << 1686   G4double phiC,cosPhiC,sinPhiC,cosPsi,ePhi;
1628   G4double pTheta,dTheta1,dTheta2;               1687   G4double pTheta,dTheta1,dTheta2;
1629   rho2=p.x()*p.x()+p.y()*p.y();                  1688   rho2=p.x()*p.x()+p.y()*p.y();
1630   rds=std::sqrt(rho2+p.z()*p.z());            << 1689   rad=sqrt(rho2+p.z()*p.z());
1631   rho=std::sqrt(rho2);                        << 1690   rho=sqrt(rho2);
1632                                                  1691 
1633   //                                             1692   //
1634   // Distance to r shells                        1693   // Distance to r shells
1635   //                                          << 1694   //    
1636   if (fRmin != 0.0)                           << 1695   if (fRmin)
1637   {                                              1696   {
1638     safeRMin=fRmin-rds;                       << 1697     safeRMin=fRmin-rad;
1639     safeRMax=rds-fRmax;                       << 1698     safeRMax=rad-fRmax;
1640     if (safeRMin>safeRMax)                       1699     if (safeRMin>safeRMax)
1641     {                                            1700     {
1642       safe=safeRMin;                             1701       safe=safeRMin;
1643     }                                            1702     }
1644     else                                         1703     else
1645     {                                            1704     {
1646       safe=safeRMax;                             1705       safe=safeRMax;
1647     }                                            1706     }
1648   }                                              1707   }
1649   else                                           1708   else
1650   {                                              1709   {
1651     safe=rds-fRmax;                           << 1710     safe=rad-fRmax;
1652   }                                              1711   }
1653                                                  1712 
1654   //                                             1713   //
1655   // Distance to phi extent                      1714   // Distance to phi extent
1656   //                                             1715   //
1657   if (!fFullPhiSphere && (rho != 0.0))        << 1716   if (fDPhi<2.0*M_PI&&rho)
1658   {                                              1717   {
                                                   >> 1718     phiC=fSPhi+fDPhi*0.5;
                                                   >> 1719     cosPhiC=cos(phiC);
                                                   >> 1720     sinPhiC=sin(phiC);
                                                   >> 1721 
1659     // Psi=angle from central phi to point       1722     // Psi=angle from central phi to point
1660     //                                           1723     //
1661     cosPsi=(p.x()*cosCPhi+p.y()*sinCPhi)/rho; << 1724     cosPsi=(p.x()*cosPhiC+p.y()*sinPhiC)/rho;
1662     if (cosPsi<cosHDPhi)                      << 1725     if (cosPsi<cos(fDPhi*0.5))
1663     {                                            1726     {
1664       // Point lies outside phi range            1727       // Point lies outside phi range
1665       //                                         1728       //
1666       if ((p.y()*cosCPhi-p.x()*sinCPhi)<=0)   << 1729       if ((p.y()*cosPhiC-p.x()*sinPhiC)<=0)
1667       {                                          1730       {
1668         safePhi=std::fabs(p.x()*sinSPhi-p.y() << 1731         safePhi=fabs(p.x()*sin(fSPhi)-p.y()*cos(fSPhi));
1669       }                                          1732       }
1670       else                                       1733       else
1671       {                                          1734       {
1672         safePhi=std::fabs(p.x()*sinEPhi-p.y() << 1735         ePhi=fSPhi+fDPhi;
                                                   >> 1736         safePhi=fabs(p.x()*sin(ePhi)-p.y()*cos(ePhi));
1673       }                                          1737       }
1674       if (safePhi>safe)  { safe=safePhi; }    << 1738       if (safePhi>safe) safe=safePhi;
1675     }                                            1739     }
1676   }                                              1740   }
1677   //                                             1741   //
1678   // Distance to Theta extent                    1742   // Distance to Theta extent
1679   //                                          << 1743   //    
1680   if ((rds!=0.0) && (!fFullThetaSphere))      << 1744   if ((rad!=0.0) && (fDTheta<M_PI))
1681   {                                              1745   {
1682     pTheta=std::acos(p.z()/rds);              << 1746     pTheta=acos(p.z()/rad);
1683     if (pTheta<0)  { pTheta+=pi; }            << 1747     if (pTheta<0) pTheta+=M_PI;
1684     dTheta1=fSTheta-pTheta;                      1748     dTheta1=fSTheta-pTheta;
1685     dTheta2=pTheta-eTheta;                    << 1749     dTheta2=pTheta-(fSTheta+fDTheta);
1686     if (dTheta1>dTheta2)                         1750     if (dTheta1>dTheta2)
1687     {                                            1751     {
1688       if (dTheta1>=0)             // WHY ????    1752       if (dTheta1>=0)             // WHY ???????????
1689       {                                          1753       {
1690         safeTheta=rds*std::sin(dTheta1);      << 1754         safeTheta=rad*sin(dTheta1);
1691         if (safe<=safeTheta)                     1755         if (safe<=safeTheta)
1692         {                                        1756         {
1693           safe=safeTheta;                        1757           safe=safeTheta;
1694         }                                        1758         }
1695       }                                          1759       }
1696     }                                            1760     }
1697     else                                         1761     else
1698     {                                            1762     {
1699       if (dTheta2>=0)                            1763       if (dTheta2>=0)
1700       {                                          1764       {
1701         safeTheta=rds*std::sin(dTheta2);      << 1765         safeTheta=rad*sin(dTheta2);
1702         if (safe<=safeTheta)                     1766         if (safe<=safeTheta)
1703         {                                        1767         {
1704           safe=safeTheta;                        1768           safe=safeTheta;
1705         }                                        1769         }
1706       }                                          1770       }
1707     }                                            1771     }
1708   }                                              1772   }
1709                                                  1773 
1710   if (safe<0)  { safe=0; }                    << 1774   if (safe<0) safe=0;
1711   return safe;                                   1775   return safe;
1712 }                                                1776 }
1713                                                  1777 
1714 /////////////////////////////////////////////    1778 /////////////////////////////////////////////////////////////////////
1715 //                                               1779 //
1716 // Calculate distance to surface of shape fro << 1780 // Calculate distance to surface of shape from `inside', allowing for tolerance
1717 // - Only Calc rmax intersection if no valid     1781 // - Only Calc rmax intersection if no valid rmin intersection
1718                                                  1782 
1719 G4double G4Sphere::DistanceToOut( const G4Thr    1783 G4double G4Sphere::DistanceToOut( const G4ThreeVector& p,
1720                                   const G4Thr    1784                                   const G4ThreeVector& v,
1721                                   const G4boo    1785                                   const G4bool calcNorm,
1722                                         G4boo << 1786                                         G4bool *validNorm,
1723                                         G4Thr << 1787                                         G4ThreeVector *n   ) const
1724 {                                                1788 {
1725   G4double snxt = kInfinity;     // snxt is d    1789   G4double snxt = kInfinity;     // snxt is default return value
1726   G4double sphi= kInfinity,stheta= kInfinity;    1790   G4double sphi= kInfinity,stheta= kInfinity;
1727   ESide side=kNull,sidephi=kNull,sidetheta=kN << 1791   ESide side=kNull,sidephi=kNull,sidetheta=kNull;  
1728                                                  1792 
1729   const G4double halfRmaxTolerance = fRmaxTol << 
1730   const G4double halfRminTolerance = fRminTol << 
1731   const G4double Rmax_plus  = fRmax + halfRma << 
1732   const G4double Rmin_minus = (fRmin) != 0.0  << 
1733   G4double t1,t2;                                1793   G4double t1,t2;
1734   G4double b,c,d;                                1794   G4double b,c,d;
1735                                                  1795 
1736   // Variables for phi intersection:             1796   // Variables for phi intersection:
1737                                                  1797 
                                                   >> 1798   G4double sinSPhi,cosSPhi,ePhi,sinEPhi,cosEPhi;
                                                   >> 1799   G4double cPhi,sinCPhi,cosCPhi;
1738   G4double pDistS,compS,pDistE,compE,sphi2,vp    1800   G4double pDistS,compS,pDistE,compE,sphi2,vphi;
                                                   >> 1801     
                                                   >> 1802   G4double rho2,rad2,pDotV2d,pDotV3d,pTheta;
1739                                                  1803 
1740   G4double rho2,rad2,pDotV2d,pDotV3d;         << 1804   G4double tolSTheta=0.,tolETheta=0.;
1741                                               << 
1742   G4double xi,yi,zi;      // Intersection poi    1805   G4double xi,yi,zi;      // Intersection point
1743                                                  1806 
1744   // Theta precals                            << 1807   // G4double Comp; // Phi intersection
1745   //                                          << 1808 
1746   G4double rhoSecTheta;                       << 1809   G4bool segPhi;        // Phi flag and precalcs
1747   G4double dist2STheta, dist2ETheta, distThet << 1810   G4double hDPhi,hDPhiOT,hDPhiIT; 
1748   G4double d2,sd;                             << 1811   G4double cosHDPhiOT,cosHDPhiIT;
                                                   >> 1812 
                                                   >> 1813   G4bool segTheta;                             // Theta flag and precals
                                                   >> 1814   G4double tanSTheta=0.,tanETheta, rhoSecTheta;
                                                   >> 1815   G4double tanSTheta2=0.,tanETheta2=0.;
                                                   >> 1816   G4double dist2STheta,dist2ETheta;
                                                   >> 1817   G4double d2,s;
1749                                                  1818 
1750   // General Precalcs                            1819   // General Precalcs
1751   //                                          << 
1752   rho2 = p.x()*p.x()+p.y()*p.y();             << 
1753   rad2 = rho2+p.z()*p.z();                    << 
1754                                                  1820 
1755   pDotV2d = p.x()*v.x()+p.y()*v.y();          << 1821   rho2=p.x()*p.x()+p.y()*p.y();
1756   pDotV3d = pDotV2d+p.z()*v.z();              << 1822   rad2=rho2+p.z()*p.z();
                                                   >> 1823   pTheta=atan2(sqrt(rho2),p.z());
                                                   >> 1824 
                                                   >> 1825   pDotV2d=p.x()*v.x()+p.y()*v.y();
                                                   >> 1826   pDotV3d=pDotV2d+p.z()*v.z();
                                                   >> 1827 
                                                   >> 1828   // Set phi divided flag and precalcs
                                                   >> 1829 
                                                   >> 1830   if(fDPhi<2.0*M_PI)
                                                   >> 1831   {
                                                   >> 1832     segPhi=true;
                                                   >> 1833     hDPhi=0.5*fDPhi;    // half delta phi
                                                   >> 1834     cPhi=fSPhi+hDPhi;;
                                                   >> 1835     hDPhiOT=hDPhi+0.5*kAngTolerance; // Outer Tolerant half delta phi 
                                                   >> 1836     hDPhiIT=hDPhi-0.5*kAngTolerance;
                                                   >> 1837     sinCPhi=sin(cPhi);
                                                   >> 1838     cosCPhi=cos(cPhi);
                                                   >> 1839     cosHDPhiOT=cos(hDPhiOT);
                                                   >> 1840     cosHDPhiIT=cos(hDPhiIT);
                                                   >> 1841   }
                                                   >> 1842   else
                                                   >> 1843   {
                                                   >> 1844     segPhi=false;
                                                   >> 1845   }
1757                                                  1846 
                                                   >> 1847   // Theta precalcs
                                                   >> 1848     
                                                   >> 1849   if (fDTheta < M_PI)
                                                   >> 1850   {
                                                   >> 1851     segTheta=true;
                                                   >> 1852     tolSTheta=fSTheta-kAngTolerance*0.5;
                                                   >> 1853     tolETheta=fSTheta+fDTheta+kAngTolerance*0.5;
                                                   >> 1854   }
                                                   >> 1855   else
                                                   >> 1856   {
                                                   >> 1857     segTheta=false;
                                                   >> 1858   }
                                                   >> 1859     
1758   // Radial Intersections from G4Sphere::Dist    1860   // Radial Intersections from G4Sphere::DistanceToIn
1759   //                                             1861   //
1760   // Outer spherical shell intersection          1862   // Outer spherical shell intersection
1761   // - Only if outside tolerant fRmax            1863   // - Only if outside tolerant fRmax
1762   // - Check for if inside and outer G4Sphere    1864   // - Check for if inside and outer G4Sphere heading through solid (-> 0)
1763   // - No intersect -> no intersection with G    1865   // - No intersect -> no intersection with G4Sphere
1764   //                                             1866   //
1765   // Shell eqn: x^2+y^2+z^2=RSPH^2               1867   // Shell eqn: x^2+y^2+z^2=RSPH^2
1766   //                                             1868   //
1767   // => (px+svx)^2+(py+svy)^2+(pz+svz)^2=R^2     1869   // => (px+svx)^2+(py+svy)^2+(pz+svz)^2=R^2
1768   //                                             1870   //
1769   // => (px^2+py^2+pz^2) +2sd(pxvx+pyvy+pzvz) << 1871   // => (px^2+py^2+pz^2) +2s(pxvx+pyvy+pzvz)+s^2(vx^2+vy^2+vz^2)=R^2
1770   // =>      rad2        +2sd(pDotV3d)        << 1872   // =>      rad2        +2s(pDotV3d)       +s^2                =R^2
                                                   >> 1873   //
                                                   >> 1874   // => s=-pDotV3d+-sqrt(pDotV3d^2-(rad2-R^2))
1771   //                                             1875   //
1772   // => sd=-pDotV3d+-std::sqrt(pDotV3d^2-(rad << 1876   const G4double  fractionTolerance = 1.0e-14;
                                                   >> 1877   const G4double  flexRadMaxTolerance = std::max(kRadTolerance, 
                                                   >> 1878                      fractionTolerance * fRmax);
                                                   >> 1879   const G4double  Rmax_plus = fRmax + flexRadMaxTolerance*0.5;
                                                   >> 1880   const G4double  flexRadMinTolerance = std::max(kRadTolerance, 
                                                   >> 1881                      fractionTolerance * fRmin);
                                                   >> 1882   const G4double  Rmin_minus= (fRmin>0) ? fRmin-flexRadMinTolerance*0.5 : 0 ;
1773                                                  1883 
1774   if( (rad2 <= Rmax_plus*Rmax_plus) && (rad2  << 1884   if(rad2 <= Rmax_plus*Rmax_plus && rad2 >= Rmin_minus*Rmin_minus)
1775   {                                              1885   {
1776     c = rad2 - fRmax*fRmax;                   << 1886     c=rad2-fRmax*fRmax ;
1777                                                  1887 
1778     if (c < fRmaxTolerance*fRmax)             << 1888     if (c < flexRadMaxTolerance*fRmax) 
1779     {                                            1889     {
1780       // Within tolerant Outer radius         << 1890       // Within tolerant Outer radius 
1781       //                                      << 1891       // 
1782       // The test is                             1892       // The test is
1783       //     rad  - fRmax < 0.5*kRadTolerance    1893       //     rad  - fRmax < 0.5*kRadTolerance
1784       // =>  rad  < fRmax + 0.5*kRadTol          1894       // =>  rad  < fRmax + 0.5*kRadTol
1785       // =>  rad2 < (fRmax + 0.5*kRadTol)^2      1895       // =>  rad2 < (fRmax + 0.5*kRadTol)^2
1786       // =>  rad2 < fRmax^2 + 2.*0.5*fRmax*kR    1896       // =>  rad2 < fRmax^2 + 2.*0.5*fRmax*kRadTol + 0.25*kRadTol*kRadTol
1787       // =>  rad2 - fRmax^2    <~    fRmax*kR << 1897       // =>  rad2 - fRmax^2    <~    fRmax*kRadTol 
1788                                                  1898 
1789       d2 = pDotV3d*pDotV3d - c;               << 1899       d2=pDotV3d*pDotV3d-c ;
1790                                                  1900 
1791       if( (c >- fRmaxTolerance*fRmax)       / << 1901       if( (c >- flexRadMaxTolerance*fRmax)       // on tolerant surface
1792        && ((pDotV3d >=0) || (d2 < 0)) )     / << 1902        && ((pDotV3d >=0) || (d2 < 0)) )          // leaving outside from Rmax 
1793                                             / << 1903                                                  // not re-entering
1794       {                                          1904       {
1795         if(calcNorm)                             1905         if(calcNorm)
1796         {                                        1906         {
1797           *validNorm = true ;                    1907           *validNorm = true ;
1798           *n         = G4ThreeVector(p.x()/fR    1908           *n         = G4ThreeVector(p.x()/fRmax,p.y()/fRmax,p.z()/fRmax) ;
1799         }                                        1909         }
1800         return snxt = 0;                         1910         return snxt = 0;
1801       }                                          1911       }
1802       else                                    << 1912       else 
1803       {                                          1913       {
1804         snxt = -pDotV3d+std::sqrt(d2);    //  << 1914         snxt=-pDotV3d+sqrt(d2);    // second root since inside Rmax
1805         side =  kRMax ;                       << 1915         side = kRMax ; 
1806       }                                          1916       }
1807     }                                            1917     }
1808                                                  1918 
1809     // Inner spherical shell intersection:       1919     // Inner spherical shell intersection:
1810     // Always first >=0 root, because would h    1920     // Always first >=0 root, because would have passed
1811     // from outside of Rmin surface .            1921     // from outside of Rmin surface .
1812                                                  1922 
1813     if (fRmin != 0.0)                         << 1923     if (fRmin)
1814     {                                            1924     {
1815       c  = rad2 - fRmin*fRmin;                << 1925       c=rad2-fRmin*fRmin ;
1816       d2 = pDotV3d*pDotV3d - c;               << 
1817                                                  1926 
1818       if (c >- fRminTolerance*fRmin) // 2.0 * << 1927       if (c >- flexRadMinTolerance*fRmin) // 2.0 * (0.5*kRadTolerance) * fRmin
1819       {                                          1928       {
1820         if ( (c < fRminTolerance*fRmin)       << 1929         if( c < flexRadMinTolerance*fRmin && pDotV3d < 0 ) // leaving from Rmin
1821           && (d2 >= fRminTolerance*fRmin) &&  << 
1822         {                                        1930         {
1823           if(calcNorm)  { *validNorm = false; << 1931           if(calcNorm)
                                                   >> 1932           {
                                                   >> 1933             *validNorm = false ;   // Rmin surface is concave
                                                   >> 1934           }
1824           return snxt = 0 ;                      1935           return snxt = 0 ;
1825         }                                        1936         }
1826         else                                     1937         else
1827         {                                     << 1938         {  
1828           if ( d2 >= 0. )                     << 1939           d2=pDotV3d*pDotV3d-c ;
                                                   >> 1940           if (d2 >= 0)
1829           {                                      1941           {
1830             sd = -pDotV3d-std::sqrt(d2);      << 1942             s = -pDotV3d-sqrt(d2) ;
1831                                               << 1943             if (s>=0)     // Always intersect Rmin first
1832             if ( sd >= 0. )     // Always int << 
1833             {                                    1944             {
1834               snxt = sd ;                     << 1945               snxt = s ;
1835               side = kRMin ;                     1946               side = kRMin ;
1836             }                                    1947             }
1837           }                                      1948           }
1838         }                                        1949         }
1839       }                                          1950       }
1840     }                                            1951     }
1841   }                                              1952   }
1842                                                  1953 
1843   // Theta segment intersection                  1954   // Theta segment intersection
1844                                                  1955 
1845   if ( !fFullThetaSphere )                    << 1956   if (segTheta)
1846   {                                              1957   {
1847     // Intersection with theta surfaces          1958     // Intersection with theta surfaces
1848     //                                           1959     //
1849     // Known failure cases:                      1960     // Known failure cases:
1850     // o  Inside tolerance of stheta surface,    1961     // o  Inside tolerance of stheta surface, skim
1851     //    ~parallel to cone and Hit & enter e    1962     //    ~parallel to cone and Hit & enter etheta surface [& visa versa]
1852     //                                           1963     //
1853     //    To solve: Check 2nd root of etheta     1964     //    To solve: Check 2nd root of etheta surface in addition to stheta
1854     //                                           1965     //
1855     // o  start/end theta is exactly pi/2     << 1966     // o  start/end theta is exactly pi/2 
1856     //                                           1967     //
1857     // Intersections with cones                  1968     // Intersections with cones
1858     //                                           1969     //
1859     // Cone equation: x^2+y^2=z^2tan^2(t)        1970     // Cone equation: x^2+y^2=z^2tan^2(t)
1860     //                                           1971     //
1861     // => (px+svx)^2+(py+svy)^2=(pz+svz)^2tan    1972     // => (px+svx)^2+(py+svy)^2=(pz+svz)^2tan^2(t)
1862     //                                           1973     //
1863     // => (px^2+py^2-pz^2tan^2(t))+2sd(pxvx+p << 1974     // => (px^2+py^2-pz^2tan^2(t))+2s(pxvx+pyvy-pzvztan^2(t))
1864     //       + sd^2(vx^2+vy^2-vz^2tan^2(t)) = << 1975     //       + s^2(vx^2+vy^2-vz^2tan^2(t)) = 0
1865     //                                           1976     //
1866     // => sd^2(1-vz^2(1+tan^2(t))+2sd(pdotv2d << 1977     // => s^2(1-vz^2(1+tan^2(t))+2s(pdotv2d-pzvztan^2(t))+(rho2-pz^2tan^2(t))=0
1867     //       + (rho2-pz^2tan^2(t)) = 0        << 
1868     //                                           1978     //
1869                                               << 1979     tanSTheta=tan(fSTheta);
1870     if(fSTheta != 0.0) // intersection with f << 1980     tanSTheta2=tanSTheta*tanSTheta;
                                                   >> 1981     tanETheta=tan(fSTheta+fDTheta);
                                                   >> 1982     tanETheta2=tanETheta*tanETheta;
                                                   >> 1983       
                                                   >> 1984     if (fSTheta)
                                                   >> 1985     {
                                                   >> 1986       dist2STheta=rho2-p.z()*p.z()*tanSTheta2;
                                                   >> 1987     }
                                                   >> 1988     else
                                                   >> 1989     {
                                                   >> 1990       dist2STheta = kInfinity;
                                                   >> 1991     }
                                                   >> 1992     if (fSTheta + fDTheta < M_PI)
                                                   >> 1993     {
                                                   >> 1994       dist2ETheta = rho2-p.z()*p.z()*tanETheta2;
                                                   >> 1995     }
                                                   >> 1996     else
1871     {                                            1997     {
1872       if( std::fabs(tanSTheta) > 5./kAngToler << 1998       dist2ETheta = kInfinity ;
                                                   >> 1999     }
                                                   >> 2000     if (pTheta > tolSTheta && pTheta < tolETheta)   // Inside theta  
                                                   >> 2001     {
                                                   >> 2002       // In tolerance of STheta and possible leaving out to small thetas N-
                                                   >> 2003 
                                                   >> 2004       if(pTheta < tolSTheta + kAngTolerance  && fSTheta > kAngTolerance)  
1873       {                                          2005       {
1874         if( v.z() > 0. )                      << 2006         t2=pDotV2d-p.z()*v.z()*tanSTheta2 ; // =(VdotN+)*rhoSecSTheta
                                                   >> 2007 
                                                   >> 2008         if( fSTheta < M_PI*0.5 && t2 < 0)
                                                   >> 2009         {
                                                   >> 2010           if(calcNorm) *validNorm = false ;
                                                   >> 2011           return snxt = 0 ;
                                                   >> 2012         }
                                                   >> 2013         else if(fSTheta > M_PI*0.5 && t2 >= 0)
1875         {                                        2014         {
1876           if ( std::fabs( p.z() ) <= halfRmax << 2015           if(calcNorm)
1877           {                                      2016           {
1878             if(calcNorm)                      << 2017             rhoSecTheta = sqrt(rho2*(1+tanSTheta2)) ;
1879             {                                 << 2018             *validNorm = true ;
1880               *validNorm = true;              << 2019             *n = G4ThreeVector(-p.x()/rhoSecTheta,   // N-
1881               *n = G4ThreeVector(0.,0.,1.);   << 2020                                -p.y()/rhoSecTheta,
1882             }                                 << 2021                                tanSTheta/sqrt(1+tanSTheta2) ) ;
1883             return snxt = 0 ;                 << 
1884           }                                      2022           }
1885           stheta    = -p.z()/v.z();           << 2023           return snxt = 0 ;
1886           sidetheta = kSTheta;                << 2024         }
                                                   >> 2025         else if( fSTheta == M_PI*0.5 && v.z() > 0)
                                                   >> 2026         {
                                                   >> 2027           if(calcNorm)
                                                   >> 2028           {
                                                   >> 2029             *validNorm = true ;
                                                   >> 2030             *n = G4ThreeVector(0,0,1) ;
                                                   >> 2031           }
                                                   >> 2032           return snxt = 0 ;
1887         }                                        2033         }
1888       }                                          2034       }
1889       else // kons is not plane               << 
1890       {                                       << 
1891         t1          = 1-v.z()*v.z()*(1+tanSTh << 
1892         t2          = pDotV2d-p.z()*v.z()*tan << 
1893         dist2STheta = rho2-p.z()*p.z()*tanSTh << 
1894                                                  2035 
1895         distTheta = std::sqrt(rho2)-p.z()*tan << 2036       // In tolerance of ETheta and possible leaving out to larger thetas N+
1896                                                  2037 
1897         if( std::fabs(t1) < halfAngTolerance  << 2038       if ( (pTheta  > tolETheta - kAngTolerance)
1898         {                                     << 2039         && (( fSTheta + fDTheta) < M_PI - kAngTolerance) )  
1899           if( v.z() > 0. )                    << 2040       {
1900           {                                   << 2041         t2=pDotV2d-p.z()*v.z()*tanETheta2 ;
1901             if(std::fabs(distTheta) < halfRma << 2042         if((fSTheta+fDTheta)>M_PI*0.5 && t2<0)
1902             {                                 << 
1903               if( (fSTheta < halfpi) && (p.z( << 
1904               {                               << 
1905                 if( calcNorm )  { *validNorm  << 
1906                 return snxt = 0.;             << 
1907               }                               << 
1908               else if( (fSTheta > halfpi) &&  << 
1909               {                               << 
1910                 if( calcNorm )                << 
1911                 {                             << 
1912                   *validNorm = true;          << 
1913                   if (rho2 != 0.0)            << 
1914                   {                           << 
1915                     rhoSecTheta = std::sqrt(r << 
1916                                               << 
1917                     *n = G4ThreeVector( p.x() << 
1918                                         p.y() << 
1919                                         std:: << 
1920                   }                           << 
1921                   else *n = G4ThreeVector(0., << 
1922                 }                             << 
1923                 return snxt = 0.;             << 
1924               }                               << 
1925             }                                 << 
1926             stheta    = -0.5*dist2STheta/t2;  << 
1927             sidetheta = kSTheta;              << 
1928           }                                   << 
1929         }      // 2nd order equation, 1st roo << 
1930         else   // 2nd if 1st root -ve         << 
1931         {                                        2043         {
1932           if( std::fabs(distTheta) < halfRmax << 2044           if(calcNorm) *validNorm = false ;
                                                   >> 2045           return snxt = 0 ;
                                                   >> 2046         }
                                                   >> 2047         else if( (fSTheta+fDTheta) < M_PI*0.5 && t2 >= 0 )
                                                   >> 2048         {
                                                   >> 2049           if(calcNorm)
1933           {                                      2050           {
1934             if( (fSTheta > halfpi) && (t2 >=  << 2051             rhoSecTheta = sqrt(rho2*(1+tanETheta2)) ;
1935             {                                 << 2052             *validNorm = true ;
1936               if( calcNorm )                  << 2053             *n = G4ThreeVector( p.x()/rhoSecTheta,  // N+
1937               {                               << 2054                                 p.y()/rhoSecTheta,
1938                 *validNorm = true;            << 2055                                 -tanETheta/sqrt(1+tanETheta2)  ) ; 
1939                 if (rho2 != 0.0)              << 
1940                 {                             << 
1941                   rhoSecTheta = std::sqrt(rho << 
1942                                               << 
1943                   *n = G4ThreeVector( p.x()/r << 
1944                                       p.y()/r << 
1945                                       std::si << 
1946                 }                             << 
1947                 else  { *n = G4ThreeVector(0. << 
1948               }                               << 
1949               return snxt = 0.;               << 
1950             }                                 << 
1951             else if( (fSTheta < halfpi) && (t << 
1952             {                                 << 
1953               if( calcNorm )  { *validNorm =  << 
1954               return snxt = 0.;               << 
1955             }                                 << 
1956           }                                      2056           }
1957           b  = t2/t1;                         << 2057           return snxt = 0 ;
1958           c  = dist2STheta/t1;                << 2058         }
1959           d2 = b*b - c ;                      << 2059         else if( ( fSTheta+fDTheta) == M_PI*0.5 && v.z() < 0 )
1960                                               << 2060         {
1961           if ( d2 >= 0. )                     << 2061           if(calcNorm)
1962           {                                      2062           {
1963             d = std::sqrt(d2);                << 2063             *validNorm = true ;
1964                                               << 2064             *n = G4ThreeVector(0,0,-1) ;
1965             if( fSTheta > halfpi )            << 
1966             {                                 << 
1967               sd = -b - d;         // First r << 
1968                                               << 
1969               if ( ((std::fabs(s) < halfRmaxT << 
1970                ||  (sd < 0.)  || ( (sd > 0.)  << 
1971               {                               << 
1972                 sd = -b + d ; // 2nd root     << 
1973               }                               << 
1974               if( (sd > halfRmaxTolerance) && << 
1975               {                               << 
1976                 stheta    = sd;               << 
1977                 sidetheta = kSTheta;          << 
1978               }                               << 
1979             }                                 << 
1980             else // sTheta < pi/2, concave su << 
1981             {                                 << 
1982               sd = -b - d;         // First r << 
1983                                               << 
1984               if ( ( (std::fabs(sd) < halfRma << 
1985                 || (sd < 0.) || ( (sd > 0.) & << 
1986               {                               << 
1987                 sd = -b + d ; // 2nd root     << 
1988               }                               << 
1989               if( (sd > halfRmaxTolerance) && << 
1990               {                               << 
1991                 stheta    = sd;               << 
1992                 sidetheta = kSTheta;          << 
1993               }                               << 
1994             }                                 << 
1995           }                                      2065           }
                                                   >> 2066           return snxt = 0 ;
1996         }                                        2067         }
1997       }                                          2068       }
1998     }                                         << 2069       if( fSTheta > 0 )
1999     if (eTheta < pi) // intersection with sec << 2070       {       
2000     {                                         << 2071         // First root of fSTheta cone, second if first root -ve
2001       if( std::fabs(tanETheta) > 5./kAngToler << 2072 
2002       {                                       << 2073         t1 = 1-v.z()*v.z()*(1+tanSTheta2);
2003         if( v.z() < 0. )                      << 2074         t2 = pDotV2d-p.z()*v.z()*tanSTheta2;
                                                   >> 2075         
                                                   >> 2076         b  = t2/t1;
                                                   >> 2077         c  = dist2STheta/t1;
                                                   >> 2078         d2 = b*b - c ;
                                                   >> 2079 
                                                   >> 2080         if ( d2 >= 0 )
2004         {                                        2081         {
2005           if ( std::fabs( p.z() ) <= halfRmax << 2082           d = sqrt(d2) ;
                                                   >> 2083           s = -b - d ;    // First root
                                                   >> 2084 
                                                   >> 2085           if ( s < 0 )
2006           {                                      2086           {
2007             if(calcNorm)                      << 2087             s = -b + d ;    // Second root
2008             {                                 << 
2009               *validNorm = true;              << 
2010               *n = G4ThreeVector(0.,0.,-1.);  << 
2011             }                                 << 
2012             return snxt = 0 ;                 << 
2013           }                                      2088           }
2014           sd = -p.z()/v.z();                  << 2089           if (s > flexRadMaxTolerance*0.5 )   // && s<sr)
2015                                               << 
2016           if( sd < stheta )                   << 
2017           {                                      2090           {
2018             stheta    = sd;                   << 2091             stheta = s ;
2019             sidetheta = kETheta;              << 2092             sidetheta = kSTheta ;
2020           }                                      2093           }
2021         }                                        2094         }
2022       }                                          2095       }
2023       else // kons is not plane               << 
2024       {                                       << 
2025         t1          = 1-v.z()*v.z()*(1+tanETh << 
2026         t2          = pDotV2d-p.z()*v.z()*tan << 
2027         dist2ETheta = rho2-p.z()*p.z()*tanETh << 
2028                                                  2096 
2029         distTheta = std::sqrt(rho2)-p.z()*tan << 2097       // Possible intersection with ETheta cone  
2030                                               << 2098       
2031         if( std::fabs(t1) < halfAngTolerance  << 2099       if (fSTheta + fDTheta < M_PI)
2032         {                                     << 2100       {
2033           if( v.z() < 0. )                    << 2101         t1 = 1-v.z()*v.z()*(1+tanETheta2);
2034           {                                   << 2102         t2 = pDotV2d-p.z()*v.z()*tanETheta2;        
2035             if(std::fabs(distTheta) < halfRma << 2103         b  = t2/t1;
2036             {                                 << 2104         c  = dist2ETheta/t1;
2037               if( (eTheta > halfpi) && (p.z() << 2105         d2 = b*b-c ;
2038               {                               << 
2039                 if( calcNorm )  { *validNorm  << 
2040                 return snxt = 0.;             << 
2041               }                               << 
2042               else if ( (eTheta < halfpi) &&  << 
2043               {                               << 
2044                 if( calcNorm )                << 
2045                 {                             << 
2046                   *validNorm = true;          << 
2047                   if (rho2 != 0.0)            << 
2048                   {                           << 
2049                     rhoSecTheta = std::sqrt(r << 
2050                     *n = G4ThreeVector( p.x() << 
2051                                         p.y() << 
2052                                         -sinE << 
2053                   }                           << 
2054                   else  { *n = G4ThreeVector( << 
2055                 }                             << 
2056                 return snxt = 0.;             << 
2057               }                               << 
2058             }                                 << 
2059             sd = -0.5*dist2ETheta/t2;         << 
2060                                                  2106 
2061             if( sd < stheta )                 << 2107         if ( d2 >= 0 )
2062             {                                 << 
2063               stheta    = sd;                 << 
2064               sidetheta = kETheta;            << 
2065             }                                 << 
2066           }                                   << 
2067         }      // 2nd order equation, 1st roo << 
2068         else   // 2nd if 1st root -ve         << 
2069         {                                        2108         {
2070           if ( std::fabs(distTheta) < halfRma << 2109           d = sqrt(d2);
                                                   >> 2110           s = -b - d ;          // First root
                                                   >> 2111 
                                                   >> 2112           if ( s < 0 )
2071           {                                      2113           {
2072             if( (eTheta < halfpi) && (t2 >= 0 << 2114             s=-b+d;    // Second root
2073             {                                 << 
2074               if( calcNorm )                  << 
2075               {                               << 
2076                 *validNorm = true;            << 
2077                 if (rho2 != 0.0)              << 
2078                 {                             << 
2079                     rhoSecTheta = std::sqrt(r << 
2080                     *n = G4ThreeVector( p.x() << 
2081                                         p.y() << 
2082                                         -sinE << 
2083                 }                             << 
2084                 else *n = G4ThreeVector(0.,0. << 
2085               }                               << 
2086               return snxt = 0.;               << 
2087             }                                 << 
2088             else if ( (eTheta > halfpi)       << 
2089                    && (t2 < 0.) && (p.z() <=0 << 
2090             {                                 << 
2091               if( calcNorm )  { *validNorm =  << 
2092               return snxt = 0.;               << 
2093             }                                 << 
2094           }                                      2115           }
2095           b  = t2/t1;                         << 2116           if (s > flexRadMaxTolerance*0.5 && s < stheta )
2096           c  = dist2ETheta/t1;                << 
2097           d2 = b*b - c ;                      << 
2098           if ( (d2 <halfRmaxTolerance) && (d2 << 
2099           {                                      2117           {
2100             d2 = 0.;                          << 2118             stheta = s ;
2101           }                                   << 2119             sidetheta = kETheta ;
2102           if ( d2 >= 0. )                     << 
2103           {                                   << 
2104             d = std::sqrt(d2);                << 
2105                                               << 
2106             if( eTheta < halfpi )             << 
2107             {                                 << 
2108               sd = -b - d;         // First r << 
2109                                               << 
2110               if( ((std::fabs(sd) < halfRmaxT << 
2111                || (sd < 0.) )                 << 
2112               {                               << 
2113                 sd = -b + d ; // 2nd root     << 
2114               }                               << 
2115               if( sd > halfRmaxTolerance )    << 
2116               {                               << 
2117                 if( sd < stheta )             << 
2118                 {                             << 
2119                   stheta    = sd;             << 
2120                   sidetheta = kETheta;        << 
2121                 }                             << 
2122               }                               << 
2123             }                                 << 
2124             else // sTheta+fDTheta > pi/2, co << 
2125             {                                 << 
2126               sd = -b - d;         // First r << 
2127                                               << 
2128               if ( ((std::fabs(sd) < halfRmax << 
2129                 || (sd < 0.)                  << 
2130                 || ( (sd > 0.) && (p.z() + sd << 
2131               {                               << 
2132                 sd = -b + d ; // 2nd root     << 
2133               }                               << 
2134               if ( ( sd>halfRmaxTolerance )   << 
2135                 && ( p.z()+sd*v.z() <= halfRm << 
2136               {                               << 
2137                 if( sd < stheta )             << 
2138                 {                             << 
2139                   stheta    = sd;             << 
2140                   sidetheta = kETheta;        << 
2141                 }                             << 
2142               }                               << 
2143             }                                 << 
2144           }                                      2120           }
2145         }                                        2121         }
2146       }                                          2122       }
2147     }                                         << 2123     }  
2148                                               << 2124   }
2149   } // end theta intersections                << 
2150                                                  2125 
2151   // Phi Intersection                            2126   // Phi Intersection
2152                                               << 2127     
2153   if ( !fFullPhiSphere )                      << 2128   if ( fDPhi < 2.0*M_PI)
2154   {                                              2129   {
2155     if ( (p.x() != 0.0) || (p.y() != 0.0) ) / << 2130     sinSPhi=sin(fSPhi);
                                                   >> 2131     cosSPhi=cos(fSPhi);
                                                   >> 2132     ePhi=fSPhi+fDPhi;
                                                   >> 2133     sinEPhi=sin(ePhi);
                                                   >> 2134     cosEPhi=cos(ePhi);
                                                   >> 2135     cPhi=fSPhi+fDPhi*0.5;
                                                   >> 2136     sinCPhi=sin(cPhi);
                                                   >> 2137     cosCPhi=cos(cPhi);
                                                   >> 2138 
                                                   >> 2139     if ( p.x()||p.y() ) // Check if on z axis (rho not needed later)
2156     {                                            2140     {
2157       // pDist -ve when inside                   2141       // pDist -ve when inside
2158                                                  2142 
2159       pDistS=p.x()*sinSPhi-p.y()*cosSPhi;        2143       pDistS=p.x()*sinSPhi-p.y()*cosSPhi;
2160       pDistE=-p.x()*sinEPhi+p.y()*cosEPhi;       2144       pDistE=-p.x()*sinEPhi+p.y()*cosEPhi;
2161                                                  2145 
2162       // Comp -ve when in direction of outwar    2146       // Comp -ve when in direction of outwards normal
2163                                                  2147 
2164       compS   = -sinSPhi*v.x()+cosSPhi*v.y()     2148       compS   = -sinSPhi*v.x()+cosSPhi*v.y() ;
2165       compE   =  sinEPhi*v.x()-cosEPhi*v.y()     2149       compE   =  sinEPhi*v.x()-cosEPhi*v.y() ;
2166       sidephi = kNull ;                          2150       sidephi = kNull ;
2167                                                  2151 
2168       if ( (pDistS <= 0) && (pDistE <= 0) )   << 2152       if ( pDistS <= 0 && pDistE <= 0 )
2169       {                                          2153       {
2170         // Inside both phi *full* planes         2154         // Inside both phi *full* planes
2171                                                  2155 
2172         if ( compS < 0 )                         2156         if ( compS < 0 )
2173         {                                        2157         {
2174           sphi = pDistS/compS ;                  2158           sphi = pDistS/compS ;
2175           xi   = p.x()+sphi*v.x() ;              2159           xi   = p.x()+sphi*v.x() ;
2176           yi   = p.y()+sphi*v.y() ;              2160           yi   = p.y()+sphi*v.y() ;
2177                                                  2161 
2178           // Check intersection with correct  << 2162           // Check intersecting with correct half-plane
2179           //                                  << 2163           // (if not -> no intersect)
2180           if( (std::fabs(xi)<=kCarTolerance)  << 2164 
2181           {                                   << 2165           if ( ( yi*cosCPhi - xi*sinCPhi ) >= 0 )
2182             vphi = std::atan2(v.y(),v.x());   << 
2183             sidephi = kSPhi;                  << 
2184             if ( ( (fSPhi-halfAngTolerance) < << 
2185               && ( (ePhi+halfAngTolerance)  > << 
2186             {                                 << 
2187               sphi = kInfinity;               << 
2188             }                                 << 
2189           }                                   << 
2190           else if ( ( yi*cosCPhi - xi*sinCPhi << 
2191           {                                      2166           {
2192             sphi=kInfinity;                      2167             sphi=kInfinity;
2193           }                                      2168           }
2194           else                                   2169           else
2195           {                                      2170           {
2196             sidephi = kSPhi ;                    2171             sidephi = kSPhi ;
2197             if ( pDistS > -halfCarTolerance)  << 2172             if ( pDistS > -0.5*kCarTolerance) sphi =0 ; // Leave by sphi 
2198           }                                      2173           }
2199         }                                        2174         }
2200         else  { sphi = kInfinity; }           << 2175         else sphi = kInfinity ;
2201                                                  2176 
2202         if ( compE < 0 )                         2177         if ( compE < 0 )
2203         {                                        2178         {
2204           sphi2=pDistE/compE ;                   2179           sphi2=pDistE/compE ;
2205           if (sphi2 < sphi) // Only check fur    2180           if (sphi2 < sphi) // Only check further if < starting phi intersection
2206           {                                      2181           {
2207             xi = p.x()+sphi2*v.x() ;             2182             xi = p.x()+sphi2*v.x() ;
2208             yi = p.y()+sphi2*v.y() ;             2183             yi = p.y()+sphi2*v.y() ;
2209                                                  2184 
2210             // Check intersection with correc << 2185             // Check intersecting with correct half-plane
2211             //                                << 2186  
2212             if ( (std::fabs(xi)<=kCarToleranc << 2187             if ((yi*cosCPhi-xi*sinCPhi)>=0) // Leaving via ending phi
2213               && (std::fabs(yi)<=kCarToleranc << 
2214             {                                 << 
2215               // Leaving via ending phi       << 
2216               //                              << 
2217               vphi = std::atan2(v.y(),v.x())  << 
2218                                               << 
2219               if( (fSPhi-halfAngTolerance > v << 
2220                   ||(fSPhi+fDPhi+halfAngToler << 
2221               {                               << 
2222                 sidephi = kEPhi;              << 
2223                 if ( pDistE <= -halfCarTolera << 
2224                 else                          << 
2225               }                               << 
2226             }                                 << 
2227             else if ((yi*cosCPhi-xi*sinCPhi)> << 
2228             {                                    2188             {
2229               sidephi = kEPhi ;                  2189               sidephi = kEPhi ;
2230               if ( pDistE <= -halfCarToleranc << 2190               if ( pDistE <= -0.5*kCarTolerance )
2231               {                                  2191               {
2232                 sphi=sphi2;                      2192                 sphi=sphi2;
2233               }                                  2193               }
2234               else                            << 2194               else 
2235               {                                  2195               {
2236                 sphi = 0 ;                       2196                 sphi = 0 ;
2237               }                                  2197               }
2238             }                                    2198             }
2239           }                                      2199           }
2240         }                                     << 2200         }        
2241       }                                          2201       }
2242       else if ((pDistS >= 0) && (pDistE >= 0) << 2202       else if ( pDistS >= 0 && pDistE >= 0 ) // Outside both *full* phi planes
2243       {                                          2203       {
2244         if ( pDistS <= pDistE )                  2204         if ( pDistS <= pDistE )
2245         {                                        2205         {
2246           sidephi = kSPhi ;                      2206           sidephi = kSPhi ;
2247         }                                        2207         }
2248         else                                     2208         else
2249         {                                        2209         {
2250           sidephi = kEPhi ;                      2210           sidephi = kEPhi ;
2251         }                                        2211         }
2252         if ( fDPhi > pi )                     << 2212         if ( fDPhi > M_PI )
2253         {                                        2213         {
2254           if ( (compS < 0) && (compE < 0) )   << 2214           if ( compS < 0 && compE < 0 ) sphi = 0 ;
2255           else                                << 2215           else                          sphi = kInfinity ;
2256         }                                        2216         }
2257         else                                     2217         else
2258         {                                        2218         {
2259           // if towards both >=0 then once in    2219           // if towards both >=0 then once inside (after error)
2260           // will remain inside                  2220           // will remain inside
2261                                                  2221 
2262           if ( (compS >= 0) && (compE >= 0) ) << 2222           if ( compS >= 0 && compE >= 0 )
2263           else                                << 2223           {
2264         }                                     << 2224             sphi=kInfinity;
                                                   >> 2225           }
                                                   >> 2226           else
                                                   >> 2227           {
                                                   >> 2228             sphi=0;
                                                   >> 2229           }
                                                   >> 2230         }    
2265       }                                          2231       }
2266       else if ( (pDistS > 0) && (pDistE < 0)  << 2232       else if ( pDistS > 0 && pDistE < 0 )
2267       {                                          2233       {
2268         // Outside full starting plane, insid    2234         // Outside full starting plane, inside full ending plane
2269                                                  2235 
2270         if ( fDPhi > pi )                     << 2236         if ( fDPhi > M_PI )
2271         {                                        2237         {
2272           if ( compE < 0 )                       2238           if ( compE < 0 )
2273           {                                      2239           {
2274             sphi = pDistE/compE ;                2240             sphi = pDistE/compE ;
2275             xi   = p.x() + sphi*v.x() ;          2241             xi   = p.x() + sphi*v.x() ;
2276             yi   = p.y() + sphi*v.y() ;          2242             yi   = p.y() + sphi*v.y() ;
2277                                                  2243 
2278             // Check intersection in correct     2244             // Check intersection in correct half-plane
2279             // (if not -> not leaving phi ext    2245             // (if not -> not leaving phi extent)
2280             //                                   2246             //
2281             if( (std::fabs(xi)<=kCarTolerance << 2247             if ( ( yi*cosCPhi - xi*sinCPhi ) <= 0 )
2282             {                                 << 
2283               vphi = std::atan2(v.y(),v.x()); << 
2284               sidephi = kSPhi;                << 
2285               if ( ( (fSPhi-halfAngTolerance) << 
2286                 && ( (ePhi+halfAngTolerance)  << 
2287               {                               << 
2288                 sphi = kInfinity;             << 
2289               }                               << 
2290             }                                 << 
2291             else if ( ( yi*cosCPhi - xi*sinCP << 
2292             {                                    2248             {
2293               sphi = kInfinity ;                 2249               sphi = kInfinity ;
2294             }                                    2250             }
2295             else // Leaving via Ending phi       2251             else // Leaving via Ending phi
2296             {                                    2252             {
2297               sidephi = kEPhi ;                  2253               sidephi = kEPhi ;
2298               if ( pDistE > -halfCarTolerance << 2254               if ( pDistE > -0.5*kCarTolerance ) sphi = 0. ;
2299             }                                    2255             }
2300           }                                      2256           }
2301           else                                   2257           else
2302           {                                      2258           {
2303             sphi = kInfinity ;                   2259             sphi = kInfinity ;
2304           }                                      2260           }
2305         }                                        2261         }
2306         else                                     2262         else
2307         {                                        2263         {
2308           if ( compS >= 0 )                      2264           if ( compS >= 0 )
2309           {                                      2265           {
2310             if ( compE < 0 )                     2266             if ( compE < 0 )
2311             {                                 << 2267             {            
2312               sphi = pDistE/compE ;              2268               sphi = pDistE/compE ;
2313               xi   = p.x() + sphi*v.x() ;        2269               xi   = p.x() + sphi*v.x() ;
2314               yi   = p.y() + sphi*v.y() ;        2270               yi   = p.y() + sphi*v.y() ;
2315                                                  2271 
2316               // Check intersection in correc    2272               // Check intersection in correct half-plane
2317               // (if not -> remain in extent)    2273               // (if not -> remain in extent)
2318               //                                 2274               //
2319               if( (std::fabs(xi)<=kCarToleran << 2275               if ( ( yi*cosCPhi - xi*sinCPhi) <= 0 )
2320                && (std::fabs(yi)<=kCarToleran << 
2321               {                               << 
2322                 vphi = std::atan2(v.y(),v.x() << 
2323                 sidephi = kSPhi;              << 
2324                 if ( ( (fSPhi-halfAngToleranc << 
2325                   && ( (ePhi+halfAngTolerance << 
2326                 {                             << 
2327                   sphi = kInfinity;           << 
2328                 }                             << 
2329               }                               << 
2330               else if ( ( yi*cosCPhi - xi*sin << 
2331               {                                  2276               {
2332                 sphi=kInfinity;                  2277                 sphi=kInfinity;
2333               }                                  2278               }
2334               else // otherwise leaving via E    2279               else // otherwise leaving via Ending phi
2335               {                                  2280               {
2336                 sidephi = kEPhi ;                2281                 sidephi = kEPhi ;
2337               }                                  2282               }
2338             }                                    2283             }
2339             else sphi=kInfinity;                 2284             else sphi=kInfinity;
2340           }                                      2285           }
2341           else // leaving immediately by star    2286           else // leaving immediately by starting phi
2342           {                                      2287           {
2343             sidephi = kSPhi ;                    2288             sidephi = kSPhi ;
2344             sphi    = 0 ;                        2289             sphi    = 0 ;
2345           }                                      2290           }
2346         }                                        2291         }
2347       }                                          2292       }
2348       else                                       2293       else
2349       {                                          2294       {
2350         // Must be pDistS < 0 && pDistE > 0      2295         // Must be pDistS < 0 && pDistE > 0
2351         // Inside full starting plane, outsid    2296         // Inside full starting plane, outside full ending plane
2352                                                  2297 
2353         if ( fDPhi > pi )                     << 2298         if ( fDPhi > M_PI )
2354         {                                        2299         {
2355           if ( compS < 0 )                       2300           if ( compS < 0 )
2356           {                                      2301           {
2357             sphi=pDistS/compS;                   2302             sphi=pDistS/compS;
2358             xi=p.x()+sphi*v.x();                 2303             xi=p.x()+sphi*v.x();
2359             yi=p.y()+sphi*v.y();                 2304             yi=p.y()+sphi*v.y();
2360                                                  2305 
2361             // Check intersection in correct     2306             // Check intersection in correct half-plane
2362             // (if not -> not leaving phi ext    2307             // (if not -> not leaving phi extent)
2363             //                                   2308             //
2364             if( (std::fabs(xi)<=kCarTolerance << 2309             if ( ( yi*cosCPhi - xi*sinCPhi ) >= 0 )
2365             {                                 << 
2366               vphi = std::atan2(v.y(),v.x())  << 
2367               sidephi = kSPhi;                << 
2368               if ( ( (fSPhi-halfAngTolerance) << 
2369                 && ( (ePhi+halfAngTolerance)  << 
2370               {                               << 
2371               sphi = kInfinity;               << 
2372               }                               << 
2373             }                                 << 
2374             else if ( ( yi*cosCPhi - xi*sinCP << 
2375             {                                    2310             {
2376               sphi = kInfinity ;                 2311               sphi = kInfinity ;
2377             }                                    2312             }
2378             else  // Leaving via Starting phi << 2313            else  // Leaving via Starting phi
2379             {                                 << 2314            {
2380               sidephi = kSPhi ;                  2315               sidephi = kSPhi ;
2381               if ( pDistS > -halfCarTolerance << 2316              if ( pDistS > -0.5*kCarTolerance ) sphi = 0 ;
2382             }                                    2317             }
2383           }                                      2318           }
2384           else                                   2319           else
2385           {                                      2320           {
2386             sphi = kInfinity ;                   2321             sphi = kInfinity ;
2387           }                                      2322           }
2388         }                                        2323         }
2389         else                                     2324         else
2390         {                                        2325         {
2391           if ( compE >= 0 )                      2326           if ( compE >= 0 )
2392           {                                      2327           {
2393             if ( compS < 0 )                     2328             if ( compS < 0 )
2394             {                                    2329             {
2395               sphi = pDistS/compS ;              2330               sphi = pDistS/compS ;
2396               xi   = p.x()+sphi*v.x() ;          2331               xi   = p.x()+sphi*v.x() ;
2397               yi   = p.y()+sphi*v.y() ;          2332               yi   = p.y()+sphi*v.y() ;
2398                                                  2333 
2399               // Check intersection in correc    2334               // Check intersection in correct half-plane
2400               // (if not -> remain in extent)    2335               // (if not -> remain in extent)
2401               //                                 2336               //
2402               if( (std::fabs(xi)<=kCarToleran << 2337               if ( ( yi*cosCPhi - xi*sinCPhi ) >= 0 )
2403                && (std::fabs(yi)<=kCarToleran << 
2404               {                               << 
2405                 vphi = std::atan2(v.y(),v.x() << 
2406                 sidephi = kSPhi;              << 
2407                 if ( ( (fSPhi-halfAngToleranc << 
2408                   && ( (ePhi+halfAngTolerance << 
2409                 {                             << 
2410                   sphi = kInfinity;           << 
2411                 }                             << 
2412               }                               << 
2413               else if ( ( yi*cosCPhi - xi*sin << 
2414               {                                  2338               {
2415                 sphi = kInfinity ;               2339                 sphi = kInfinity ;
2416               }                                  2340               }
2417               else // otherwise leaving via S    2341               else // otherwise leaving via Starting phi
2418               {                                  2342               {
2419                 sidephi = kSPhi ;                2343                 sidephi = kSPhi ;
2420               }                                  2344               }
2421             }                                    2345             }
2422             else                                 2346             else
2423             {                                    2347             {
2424               sphi = kInfinity ;                 2348               sphi = kInfinity ;
2425             }                                    2349             }
2426           }                                      2350           }
2427           else // leaving immediately by endi    2351           else // leaving immediately by ending
2428           {                                      2352           {
2429             sidephi = kEPhi ;                    2353             sidephi = kEPhi ;
2430             sphi    = 0     ;                    2354             sphi    = 0     ;
2431           }                                      2355           }
2432         }                                        2356         }
2433       }                                       << 2357       }      
2434     }                                            2358     }
2435     else                                         2359     else
2436     {                                            2360     {
2437       // On z axis + travel not || to z axis     2361       // On z axis + travel not || to z axis -> if phi of vector direction
2438       // within phi of shape, Step limited by    2362       // within phi of shape, Step limited by rmax, else Step =0
2439                                                  2363 
2440       if ( (v.x() != 0.0) || (v.y() != 0.0) ) << 2364       if ( v.x() || v.y() )
2441       {                                          2365       {
2442         vphi = std::atan2(v.y(),v.x()) ;      << 2366         vphi = atan2(v.y(),v.x()) ;
2443         if ((fSPhi-halfAngTolerance < vphi) & << 2367         if ( fSPhi < vphi && vphi < fSPhi + fDPhi )
2444         {                                        2368         {
2445           sphi = kInfinity;                   << 2369           sphi=kInfinity;
2446         }                                        2370         }
2447         else                                     2371         else
2448         {                                        2372         {
2449           sidephi = kSPhi ; // arbitrary      << 2373           sidephi = kSPhi ; // arbitrary 
2450           sphi    = 0     ;                      2374           sphi    = 0     ;
2451         }                                        2375         }
2452       }                                          2376       }
2453       else  // travel along z - no phi inters << 2377       else  // travel along z - no phi intersaction
2454       {                                          2378       {
2455         sphi = kInfinity ;                       2379         sphi = kInfinity ;
2456       }                                          2380       }
2457     }                                            2381     }
2458     if ( sphi < snxt )  // Order intersecttio    2382     if ( sphi < snxt )  // Order intersecttions
2459     {                                            2383     {
2460       snxt = sphi ;                              2384       snxt = sphi ;
2461       side = sidephi ;                           2385       side = sidephi ;
2462     }                                            2386     }
2463   }                                              2387   }
2464   if (stheta < snxt ) // Order intersections     2388   if (stheta < snxt ) // Order intersections
2465   {                                              2389   {
2466     snxt = stheta ;                              2390     snxt = stheta ;
2467     side = sidetheta ;                           2391     side = sidetheta ;
2468   }                                              2392   }
2469                                                  2393 
2470   if (calcNorm)    // Output switch operator     2394   if (calcNorm)    // Output switch operator
2471   {                                              2395   {
2472     switch( side )                               2396     switch( side )
2473     {                                            2397     {
2474       case kRMax:                                2398       case kRMax:
2475         xi=p.x()+snxt*v.x();                     2399         xi=p.x()+snxt*v.x();
2476         yi=p.y()+snxt*v.y();                     2400         yi=p.y()+snxt*v.y();
2477         zi=p.z()+snxt*v.z();                     2401         zi=p.z()+snxt*v.z();
2478         *n=G4ThreeVector(xi/fRmax,yi/fRmax,zi    2402         *n=G4ThreeVector(xi/fRmax,yi/fRmax,zi/fRmax);
2479         *validNorm=true;                         2403         *validNorm=true;
2480         break;                                   2404         break;
2481                                               << 
2482       case kRMin:                                2405       case kRMin:
2483         *validNorm=false;  // Rmin is concave    2406         *validNorm=false;  // Rmin is concave
2484         break;                                   2407         break;
2485                                               << 
2486       case kSPhi:                                2408       case kSPhi:
2487         if ( fDPhi <= pi )     // Normal to P << 2409         if (fDPhi<=M_PI)     // Normal to Phi-
2488         {                                        2410         {
2489           *n=G4ThreeVector(sinSPhi,-cosSPhi,0 << 2411           *n=G4ThreeVector(sin(fSPhi),-cos(fSPhi),0);
2490           *validNorm=true;                       2412           *validNorm=true;
2491         }                                        2413         }
2492         else  { *validNorm=false; }           << 2414         else *validNorm=false;
2493         break ;                                  2415         break ;
2494                                               << 
2495       case kEPhi:                                2416       case kEPhi:
2496         if ( fDPhi <= pi )      // Normal to  << 2417         if (fDPhi<=M_PI)      // Normal to Phi+
2497         {                                        2418         {
2498           *n=G4ThreeVector(-sinEPhi,cosEPhi,0 << 2419           *n=G4ThreeVector(-sin(fSPhi+fDPhi),cos(fSPhi+fDPhi),0);
2499           *validNorm=true;                       2420           *validNorm=true;
2500         }                                        2421         }
2501         else  { *validNorm=false; }           << 2422         else *validNorm=false;
2502         break;                                   2423         break;
2503                                               << 
2504       case kSTheta:                              2424       case kSTheta:
2505         if( fSTheta == halfpi )               << 2425         if( fSTheta == M_PI*0.5 )
2506         {                                        2426         {
2507           *n=G4ThreeVector(0.,0.,1.);         << 2427           *n=G4ThreeVector(0,0,1);
2508           *validNorm=true;                       2428           *validNorm=true;
2509         }                                        2429         }
2510         else if ( fSTheta > halfpi )          << 2430         else if ( fSTheta > M_PI )
2511         {                                        2431         {
2512           xi = p.x() + snxt*v.x();            << 2432           xi=p.x()+snxt*v.x();
2513           yi = p.y() + snxt*v.y();            << 2433           yi=p.y()+snxt*v.y();
2514           rho2=xi*xi+yi*yi;                   << 2434           rhoSecTheta = sqrt((xi*xi+yi*yi)*(1+tanSTheta2)) ;
2515           if (rho2 != 0.0)                    << 2435           *n = G4ThreeVector(-xi/rhoSecTheta,   // N-
2516           {                                   << 2436                              -yi/rhoSecTheta,
2517             rhoSecTheta = std::sqrt(rho2*(1+t << 2437                              tanSTheta/sqrt(1+tanSTheta2)) ;
2518             *n = G4ThreeVector( xi/rhoSecThet << 
2519                                -tanSTheta/std << 
2520           }                                   << 
2521           else                                << 
2522           {                                   << 
2523             *n = G4ThreeVector(0.,0.,1.);     << 
2524           }                                   << 
2525           *validNorm=true;                       2438           *validNorm=true;
2526         }                                        2439         }
2527         else  { *validNorm=false; }  // Conca << 2440         else *validNorm=false;  // Concave STheta cone
2528         break;                                   2441         break;
2529                                               << 
2530       case kETheta:                              2442       case kETheta:
2531         if( eTheta == halfpi )                << 2443         if( ( fSTheta + fDTheta ) == M_PI*0.5 )
2532         {                                        2444         {
2533           *n         = G4ThreeVector(0.,0.,-1 << 2445           *n         = G4ThreeVector(0,0,-1);
2534           *validNorm = true;                  << 2446           *validNorm = true ;
2535         }                                        2447         }
2536         else if ( eTheta < halfpi )           << 2448         else if ( ( fSTheta + fDTheta ) < M_PI )
2537         {                                        2449         {
2538           xi=p.x()+snxt*v.x();                   2450           xi=p.x()+snxt*v.x();
2539           yi=p.y()+snxt*v.y();                   2451           yi=p.y()+snxt*v.y();
2540           rho2=xi*xi+yi*yi;                   << 2452           rhoSecTheta = sqrt((xi*xi+yi*yi)*(1+tanETheta2)) ;
2541           if (rho2 != 0.0)                    << 2453           *n = G4ThreeVector( xi/rhoSecTheta,   // N+
2542           {                                   << 2454                               yi/rhoSecTheta,
2543             rhoSecTheta = std::sqrt(rho2*(1+t << 2455                               -tanSTheta/sqrt(1+tanSTheta2) ) ;
2544             *n = G4ThreeVector( xi/rhoSecThet << 
2545                                -tanETheta/std << 
2546           }                                   << 
2547           else                                << 
2548           {                                   << 
2549             *n = G4ThreeVector(0.,0.,-1.);    << 
2550           }                                   << 
2551           *validNorm=true;                       2456           *validNorm=true;
2552         }                                        2457         }
2553         else  { *validNorm=false; }   // Conc << 2458         else *validNorm=false;   // Concave ETheta cone
2554         break;                                   2459         break;
2555                                               << 
2556       default:                                   2460       default:
                                                   >> 2461         G4cout.precision(16);
2557         G4cout << G4endl;                        2462         G4cout << G4endl;
2558         DumpInfo();                              2463         DumpInfo();
2559         std::ostringstream message;           << 2464         G4cout << "Position:"  << G4endl << G4endl;
2560         G4long oldprc = message.precision(16) << 2465         G4cout << "p.x() = "   << p.x()/mm << " mm" << G4endl;
2561         message << "Undefined side for valid  << 2466         G4cout << "p.y() = "   << p.y()/mm << " mm" << G4endl;
2562                 << G4endl                     << 2467         G4cout << "p.z() = "   << p.z()/mm << " mm" << G4endl << G4endl;
2563                 << "Position:"  << G4endl <<  << 2468         G4cout << "Direction:" << G4endl << G4endl;
2564                 << "p.x() = "   << p.x()/mm < << 2469         G4cout << "v.x() = "   << v.x() << G4endl;
2565                 << "p.y() = "   << p.y()/mm < << 2470         G4cout << "v.y() = "   << v.y() << G4endl;
2566                 << "p.z() = "   << p.z()/mm < << 2471         G4cout << "v.z() = "   << v.z() << G4endl << G4endl;
2567                 << "Direction:" << G4endl <<  << 2472         G4cout << "Proposed distance :" << G4endl << G4endl;
2568                 << "v.x() = "   << v.x() << G << 2473         G4cout << "snxt = "    << snxt/mm << " mm" << G4endl << G4endl;
2569                 << "v.y() = "   << v.y() << G << 2474         G4Exception("G4Sphere::DistanceToOut() - Invalid enum");
2570                 << "v.z() = "   << v.z() << G << 
2571                 << "Proposed distance :" << G << 
2572                 << "snxt = "    << snxt/mm << << 
2573         message.precision(oldprc);            << 
2574         G4Exception("G4Sphere::DistanceToOut( << 
2575                     "GeomSolids1002", JustWar << 
2576         break;                                   2475         break;
2577     }                                            2476     }
2578   }                                              2477   }
2579   if (snxt == kInfinity)                      << 
2580   {                                           << 
2581     G4cout << G4endl;                         << 
2582     DumpInfo();                               << 
2583     std::ostringstream message;               << 
2584     G4long oldprc = message.precision(16);    << 
2585     message << "Logic error: snxt = kInfinity << 
2586             << "Position:"  << G4endl << G4en << 
2587             << "p.x() = "   << p.x()/mm << "  << 
2588             << "p.y() = "   << p.y()/mm << "  << 
2589             << "p.z() = "   << p.z()/mm << "  << 
2590             << "Rp = "<< std::sqrt( p.x()*p.x << 
2591             << " mm" << G4endl << G4endl      << 
2592             << "Direction:" << G4endl << G4en << 
2593             << "v.x() = "   << v.x() << G4end << 
2594             << "v.y() = "   << v.y() << G4end << 
2595             << "v.z() = "   << v.z() << G4end << 
2596             << "Proposed distance :" << G4end << 
2597             << "snxt = "    << snxt/mm << " m << 
2598     message.precision(oldprc);                << 
2599     G4Exception("G4Sphere::DistanceToOut(p,v, << 
2600                 "GeomSolids1002", JustWarning << 
2601   }                                           << 
2602                                               << 
2603   return snxt;                                   2478   return snxt;
2604 }                                                2479 }
2605                                                  2480 
2606 /////////////////////////////////////////////    2481 /////////////////////////////////////////////////////////////////////////
2607 //                                               2482 //
2608 // Calculate distance (<=actual) to closest s << 2483 // Calcluate distance (<=actual) to closest surface of shape from inside
2609                                                  2484 
2610 G4double G4Sphere::DistanceToOut( const G4Thr    2485 G4double G4Sphere::DistanceToOut( const G4ThreeVector& p ) const
2611 {                                                2486 {
2612   G4double safe=0.0,safeRMin,safeRMax,safePhi << 2487   G4double safe,safeRMin,safeRMax,safePhi,safeTheta;
2613   G4double rho2,rds,rho;                      << 2488   G4double rho2,rad,rho;
2614   G4double pTheta,dTheta1 = kInfinity,dTheta2 << 2489   G4double phiC,cosPhiC,sinPhiC,ePhi;
                                                   >> 2490   G4double pTheta,dTheta1,dTheta2;
2615   rho2=p.x()*p.x()+p.y()*p.y();                  2491   rho2=p.x()*p.x()+p.y()*p.y();
2616   rds=std::sqrt(rho2+p.z()*p.z());            << 2492   rad=sqrt(rho2+p.z()*p.z());
2617   rho=std::sqrt(rho2);                        << 2493   rho=sqrt(rho2);
2618                                                  2494 
2619 #ifdef G4CSGDEBUG                                2495 #ifdef G4CSGDEBUG
2620   if( Inside(p) == kOutside )                    2496   if( Inside(p) == kOutside )
2621   {                                              2497   {
2622      G4long old_prc = G4cout.precision(16);   << 2498      G4cout.precision(16) ;
2623      G4cout << G4endl;                        << 2499      G4cout << G4endl ;
2624      DumpInfo();                                 2500      DumpInfo();
2625      G4cout << "Position:"  << G4endl << G4en    2501      G4cout << "Position:"  << G4endl << G4endl ;
2626      G4cout << "p.x() = "   << p.x()/mm << "     2502      G4cout << "p.x() = "   << p.x()/mm << " mm" << G4endl ;
2627      G4cout << "p.y() = "   << p.y()/mm << "     2503      G4cout << "p.y() = "   << p.y()/mm << " mm" << G4endl ;
2628      G4cout << "p.z() = "   << p.z()/mm << "     2504      G4cout << "p.z() = "   << p.z()/mm << " mm" << G4endl << G4endl ;
2629      G4cout.precision(old_prc) ;              << 2505      G4cout << "G4Sphere::DistanceToOut(p) - point p is outside ?!" << G4endl ;
2630      G4Exception("G4Sphere::DistanceToOut(p)" << 2506      G4cerr << "G4Sphere::DistanceToOut(p) - point p is outside ?!" << G4endl ;
2631                  "GeomSolids1002", JustWarnin << 
2632   }                                              2507   }
2633 #endif                                           2508 #endif
2634                                                  2509 
2635   // Distance to r shells                     << 
2636   //                                             2510   //
2637   safeRMax = fRmax-rds;                       << 2511   // Distance to r shells
2638   safe = safeRMax;                            << 2512   //    
2639   if (fRmin != 0.0)                           << 2513   if (fRmin)
                                                   >> 2514   {
                                                   >> 2515     safeRMin=rad-fRmin;
                                                   >> 2516     safeRMax=fRmax-rad;
                                                   >> 2517     if (safeRMin<safeRMax)
                                                   >> 2518     {
                                                   >> 2519       safe=safeRMin;
                                                   >> 2520     }
                                                   >> 2521     else
                                                   >> 2522     {
                                                   >> 2523       safe=safeRMax;
                                                   >> 2524     }
                                                   >> 2525   }
                                                   >> 2526   else
2640   {                                              2527   {
2641      safeRMin = rds-fRmin;                    << 2528     safe=fRmax-rad;
2642      safe = std::min( safeRMin, safeRMax );   << 
2643   }                                              2529   }
2644                                                  2530 
                                                   >> 2531   //
2645   // Distance to phi extent                      2532   // Distance to phi extent
2646   //                                             2533   //
2647   if ( !fFullPhiSphere )                      << 2534   if (fDPhi<2.0*M_PI && rho)
2648   {                                              2535   {
2649      if (rho>0.0)                             << 2536     phiC=fSPhi+fDPhi*0.5;
2650      {                                        << 2537     cosPhiC=cos(phiC);
2651         if ((p.y()*cosCPhi-p.x()*sinCPhi)<=0) << 2538     sinPhiC=sin(phiC);
2652         {                                     << 2539     if ((p.y()*cosPhiC-p.x()*sinPhiC)<=0)
2653            safePhi=-(p.x()*sinSPhi-p.y()*cosS << 2540     {
2654         }                                     << 2541       safePhi=-(p.x()*sin(fSPhi)-p.y()*cos(fSPhi));
2655         else                                  << 2542     }
2656         {                                     << 2543     else
2657            safePhi=(p.x()*sinEPhi-p.y()*cosEP << 2544     {
2658         }                                     << 2545       ePhi=fSPhi+fDPhi;
2659      }                                        << 2546       safePhi=(p.x()*sin(ePhi)-p.y()*cos(ePhi));
2660      else                                     << 2547     }
2661      {                                        << 2548     if (safePhi<safe) safe=safePhi;
2662         safePhi = 0.0;  // Distance to both P << 
2663      }                                        << 
2664      // Both cases above can be improved - in << 
2665      //  although it may be costlier (good fo << 
2666                                               << 
2667      safe= std::min(safe, safePhi);           << 
2668   }                                              2549   }
2669                                                  2550 
2670   // Distance to Theta extent                 << 
2671   //                                             2551   //
2672   if ( !fFullThetaSphere )                    << 2552   // Distance to Theta extent
                                                   >> 2553   //    
                                                   >> 2554   if (rad)
2673   {                                              2555   {
2674     if( rds > 0.0 )                           << 2556     pTheta=acos(p.z()/rad);
                                                   >> 2557     if (pTheta<0) pTheta+=M_PI;
                                                   >> 2558     dTheta1=pTheta-fSTheta;
                                                   >> 2559     dTheta2=(fSTheta+fDTheta)-pTheta;
                                                   >> 2560     if (dTheta1<dTheta2)
2675     {                                            2561     {
2676        pTheta=std::acos(p.z()/rds);           << 2562       safeTheta=rad*sin(dTheta1);
2677        if (pTheta<0) { pTheta+=pi; }          << 2563       if (safe>safeTheta)
2678        if(fSTheta>0.)                         << 2564       {
2679        { dTheta1=pTheta-fSTheta;}             << 2565         safe=safeTheta;
2680        if(eTheta<pi)                          << 2566       }
2681        { dTheta2=eTheta-pTheta;}              << 
2682                                               << 
2683        safeTheta=rds*std::sin(std::min(dTheta << 
2684     }                                            2567     }
2685     else                                         2568     else
2686     {                                            2569     {
2687        safeTheta= 0.0;                        << 2570       safeTheta=rad*sin(dTheta2);
2688          // An improvement will be to return  << 2571       if (safe>safeTheta)
                                                   >> 2572       {
                                                   >> 2573         safe=safeTheta;
                                                   >> 2574       }
2689     }                                            2575     }
2690     safe = std::min( safe, safeTheta );       << 
2691   }                                              2576   }
2692                                                  2577 
2693   if (safe<0.0) { safe=0; }                   << 2578   if (safe<0) safe=0;
2694     // An improvement to return negative answ << 2579     return safe;
2695                                               << 
2696   return safe;                                << 
2697 }                                                2580 }
2698                                                  2581 
2699 /////////////////////////////////////////////    2582 //////////////////////////////////////////////////////////////////////////
2700 //                                               2583 //
2701 // G4EntityType                               << 2584 // Create a List containing the transformed vertices
                                                   >> 2585 // Ordering [0-3] -fDz cross section
                                                   >> 2586 //          [4-7] +fDz cross section such that [0] is below [4],
                                                   >> 2587 //                                             [1] below [5] etc.
                                                   >> 2588 // Note:
                                                   >> 2589 //  Caller has deletion resposibility
                                                   >> 2590 //  Potential improvement: For last slice, use actual ending angle
                                                   >> 2591 //                         to avoid rounding error problems.
                                                   >> 2592 
                                                   >> 2593 G4ThreeVectorList*
                                                   >> 2594 G4Sphere::CreateRotatedVertices( const G4AffineTransform& pTransform,
                                                   >> 2595                                        G4int& noPolygonVertices ) const
                                                   >> 2596 {
                                                   >> 2597   G4ThreeVectorList *vertices;
                                                   >> 2598   G4ThreeVector vertex;
                                                   >> 2599   G4double meshAnglePhi,meshRMax,crossAnglePhi,
                                                   >> 2600            coscrossAnglePhi,sincrossAnglePhi,sAnglePhi;
                                                   >> 2601   G4double meshTheta,crossTheta,startTheta;
                                                   >> 2602   G4double rMaxX,rMaxY,rMinX,rMinY,rMinZ,rMaxZ;
                                                   >> 2603   G4int crossSectionPhi,noPhiCrossSections,crossSectionTheta,noThetaSections;
                                                   >> 2604 
                                                   >> 2605   // Phi cross sections
                                                   >> 2606     
                                                   >> 2607   noPhiCrossSections=G4int (fDPhi/kMeshAngleDefault)+1;
                                                   >> 2608     
                                                   >> 2609   if (noPhiCrossSections<kMinMeshSections)
                                                   >> 2610   {
                                                   >> 2611     noPhiCrossSections=kMinMeshSections;
                                                   >> 2612   }
                                                   >> 2613   else if (noPhiCrossSections>kMaxMeshSections)
                                                   >> 2614   {
                                                   >> 2615     noPhiCrossSections=kMaxMeshSections;
                                                   >> 2616   }
                                                   >> 2617   meshAnglePhi=fDPhi/(noPhiCrossSections-1);
                                                   >> 2618     
                                                   >> 2619   // If complete in phi, set start angle such that mesh will be at fRMax
                                                   >> 2620   // on the x axis. Will give better extent calculations when not rotated.
                                                   >> 2621     
                                                   >> 2622   if (fDPhi==M_PI*2.0 && fSPhi==0)
                                                   >> 2623   {
                                                   >> 2624     sAnglePhi = -meshAnglePhi*0.5;
                                                   >> 2625   }
                                                   >> 2626     else
                                                   >> 2627   {
                                                   >> 2628     sAnglePhi=fSPhi;
                                                   >> 2629   }    
2702                                                  2630 
2703 G4GeometryType G4Sphere::GetEntityType() cons << 2631   // Theta cross sections
2704 {                                             << 2632     
2705   return {"G4Sphere"};                        << 2633   noThetaSections = G4int(fDTheta/kMeshAngleDefault)+1;
                                                   >> 2634     
                                                   >> 2635   if (noThetaSections<kMinMeshSections)
                                                   >> 2636   {
                                                   >> 2637     noThetaSections=kMinMeshSections;
                                                   >> 2638   }
                                                   >> 2639   else if (noThetaSections>kMaxMeshSections)
                                                   >> 2640   {
                                                   >> 2641     noThetaSections=kMaxMeshSections;
                                                   >> 2642   }
                                                   >> 2643   meshTheta=fDTheta/(noThetaSections-1);
                                                   >> 2644     
                                                   >> 2645   // If complete in Theta, set start angle such that mesh will be at fRMax
                                                   >> 2646   // on the z axis. Will give better extent calculations when not rotated.
                                                   >> 2647     
                                                   >> 2648   if (fDTheta==M_PI && fSTheta==0)
                                                   >> 2649   {
                                                   >> 2650     startTheta = -meshTheta*0.5;
                                                   >> 2651   }
                                                   >> 2652   else
                                                   >> 2653   {
                                                   >> 2654     startTheta=fSTheta;
                                                   >> 2655   }    
                                                   >> 2656 
                                                   >> 2657   meshRMax = (meshAnglePhi >= meshTheta) ?
                                                   >> 2658              fRmax/cos(meshAnglePhi*0.5) : fRmax/cos(meshTheta*0.5);
                                                   >> 2659   G4double* cosCrossTheta = new G4double[noThetaSections];
                                                   >> 2660   G4double* sinCrossTheta = new G4double[noThetaSections];    
                                                   >> 2661   vertices=new G4ThreeVectorList();
                                                   >> 2662   vertices->reserve(noPhiCrossSections*(noThetaSections*2));
                                                   >> 2663   if (vertices && cosCrossTheta && sinCrossTheta)
                                                   >> 2664   {
                                                   >> 2665     for (crossSectionPhi=0;
                                                   >> 2666          crossSectionPhi<noPhiCrossSections; crossSectionPhi++)
                                                   >> 2667     {
                                                   >> 2668       crossAnglePhi=sAnglePhi+crossSectionPhi*meshAnglePhi;
                                                   >> 2669       coscrossAnglePhi=cos(crossAnglePhi);
                                                   >> 2670       sincrossAnglePhi=sin(crossAnglePhi);
                                                   >> 2671       for (crossSectionTheta=0;
                                                   >> 2672            crossSectionTheta<noThetaSections;crossSectionTheta++)
                                                   >> 2673       {
                                                   >> 2674         // Compute coordinates of cross section at section crossSectionPhi
                                                   >> 2675         //
                                                   >> 2676         crossTheta=startTheta+crossSectionTheta*meshTheta;
                                                   >> 2677         cosCrossTheta[crossSectionTheta]=cos(crossTheta);
                                                   >> 2678         sinCrossTheta[crossSectionTheta]=sin(crossTheta);
                                                   >> 2679 
                                                   >> 2680         rMinX=fRmin*sinCrossTheta[crossSectionTheta]*coscrossAnglePhi;
                                                   >> 2681         rMinY=fRmin*sinCrossTheta[crossSectionTheta]*sincrossAnglePhi;
                                                   >> 2682         rMinZ=fRmin*cosCrossTheta[crossSectionTheta];
                                                   >> 2683         
                                                   >> 2684         vertex=G4ThreeVector(rMinX,rMinY,rMinZ);
                                                   >> 2685         vertices->push_back(pTransform.TransformPoint(vertex));
                                                   >> 2686         
                                                   >> 2687       }    // Theta forward 
                                                   >> 2688     
                                                   >> 2689       for (crossSectionTheta=noThetaSections-1;
                                                   >> 2690            crossSectionTheta>=0; crossSectionTheta--)
                                                   >> 2691       {
                                                   >> 2692         rMaxX=meshRMax*sinCrossTheta[crossSectionTheta]*coscrossAnglePhi;
                                                   >> 2693         rMaxY=meshRMax*sinCrossTheta[crossSectionTheta]*sincrossAnglePhi;
                                                   >> 2694         rMaxZ=meshRMax*cosCrossTheta[crossSectionTheta];
                                                   >> 2695         
                                                   >> 2696         vertex=G4ThreeVector(rMaxX,rMaxY,rMaxZ);
                                                   >> 2697         vertices->push_back(pTransform.TransformPoint(vertex));
                                                   >> 2698 
                                                   >> 2699       }   // Theta back 
                                                   >> 2700     }   // Phi
                                                   >> 2701     noPolygonVertices = noThetaSections*2 ;
                                                   >> 2702   }
                                                   >> 2703   else
                                                   >> 2704   {
                                                   >> 2705     DumpInfo();
                                                   >> 2706     G4Exception("G4Sphere::CreateRotatedVertices() - Out of memory !");
                                                   >> 2707   }
                                                   >> 2708 
                                                   >> 2709   delete[] cosCrossTheta;
                                                   >> 2710   delete[] sinCrossTheta;
                                                   >> 2711 
                                                   >> 2712   return vertices;
2706 }                                                2713 }
2707                                                  2714 
2708 /////////////////////////////////////////////    2715 //////////////////////////////////////////////////////////////////////////
2709 //                                               2716 //
2710 // Make a clone of the object                 << 2717 // G4EntityType
2711 //                                            << 2718 
2712 G4VSolid* G4Sphere::Clone() const             << 2719 G4GeometryType G4Sphere::GetEntityType() const
2713 {                                                2720 {
2714   return new G4Sphere(*this);                 << 2721   return G4String("G4Sphere");
2715 }                                                2722 }
2716                                                  2723 
2717 /////////////////////////////////////////////    2724 //////////////////////////////////////////////////////////////////////////
2718 //                                               2725 //
2719 // Stream object contents to an output stream    2726 // Stream object contents to an output stream
2720                                                  2727 
2721 std::ostream& G4Sphere::StreamInfo( std::ostr    2728 std::ostream& G4Sphere::StreamInfo( std::ostream& os ) const
2722 {                                                2729 {
2723   G4long oldprc = os.precision(16);           << 
2724   os << "------------------------------------    2730   os << "-----------------------------------------------------------\n"
2725      << "    *** Dump for solid - " << GetNam    2731      << "    *** Dump for solid - " << GetName() << " ***\n"
2726      << "    ================================    2732      << "    ===================================================\n"
2727      << " Solid type: G4Sphere\n"                2733      << " Solid type: G4Sphere\n"
2728      << " Parameters: \n"                        2734      << " Parameters: \n"
2729      << "    inner radius: " << fRmin/mm << "    2735      << "    inner radius: " << fRmin/mm << " mm \n"
2730      << "    outer radius: " << fRmax/mm << "    2736      << "    outer radius: " << fRmax/mm << " mm \n"
2731      << "    starting phi of segment  : " <<     2737      << "    starting phi of segment  : " << fSPhi/degree << " degrees \n"
2732      << "    delta phi of segment     : " <<     2738      << "    delta phi of segment     : " << fDPhi/degree << " degrees \n"
2733      << "    starting theta of segment: " <<     2739      << "    starting theta of segment: " << fSTheta/degree << " degrees \n"
2734      << "    delta theta of segment   : " <<     2740      << "    delta theta of segment   : " << fDTheta/degree << " degrees \n"
2735      << "------------------------------------    2741      << "-----------------------------------------------------------\n";
2736   os.precision(oldprc);                       << 
2737                                                  2742 
2738   return os;                                     2743   return os;
2739 }                                                2744 }
2740                                                  2745 
2741 ///////////////////////////////////////////// << 
2742 //                                            << 
2743 // Get volume                                 << 
2744                                               << 
2745 G4double G4Sphere::GetCubicVolume()           << 
2746 {                                             << 
2747   if (fCubicVolume == 0.)                     << 
2748   {                                           << 
2749     G4double RRR = fRmax*fRmax*fRmax;         << 
2750     G4double rrr = fRmin*fRmin*fRmin;         << 
2751     fCubicVolume = fDPhi*(cosSTheta - cosEThe << 
2752   }                                           << 
2753   return fCubicVolume;                        << 
2754 }                                             << 
2755                                               << 
2756 ///////////////////////////////////////////// << 
2757 //                                            << 
2758 // Get surface area                           << 
2759                                               << 
2760 G4double G4Sphere::GetSurfaceArea()           << 
2761 {                                             << 
2762   if (fSurfaceArea == 0.)                     << 
2763   {                                           << 
2764     G4double RR = fRmax*fRmax;                << 
2765     G4double rr = fRmin*fRmin;                << 
2766     fSurfaceArea = fDPhi*(RR + rr)*(cosSTheta << 
2767     if (!fFullPhiSphere)    fSurfaceArea += f << 
2768     if (fSTheta > 0)        fSurfaceArea += 0 << 
2769     if (eTheta < CLHEP::pi) fSurfaceArea += 0 << 
2770   }                                           << 
2771   return fSurfaceArea;                        << 
2772 }                                             << 
2773                                               << 
2774 ///////////////////////////////////////////// << 
2775 //                                            << 
2776 // Return a point randomly and uniformly sele << 
2777                                               << 
2778 G4ThreeVector G4Sphere::GetPointOnSurface() c << 
2779 {                                             << 
2780   G4double RR = fRmax*fRmax;                  << 
2781   G4double rr = fRmin*fRmin;                  << 
2782                                               << 
2783   // Find surface areas                       << 
2784   //                                          << 
2785   G4double aInner   = fDPhi*rr*(cosSTheta - c << 
2786   G4double aOuter   = fDPhi*RR*(cosSTheta - c << 
2787   G4double aPhi     = (!fFullPhiSphere) ? fDT << 
2788   G4double aSTheta  = (fSTheta > 0) ? 0.5*fDP << 
2789   G4double aETheta  = (eTheta < pi) ? 0.5*fDP << 
2790   G4double aTotal   = aInner + aOuter + aPhi  << 
2791                                               << 
2792   // Select surface and generate a point      << 
2793   //                                          << 
2794   G4double select = aTotal*G4QuickRand();     << 
2795   G4double u = G4QuickRand();                 << 
2796   G4double v = G4QuickRand();                 << 
2797   if (select < aInner + aOuter)            // << 
2798   {                                           << 
2799     G4double r   = (select < aInner) ? fRmin  << 
2800     G4double z   = cosSTheta + (cosETheta - c << 
2801     G4double rho = std::sqrt(1. - z*z);       << 
2802     G4double phi = fDPhi*v + fSPhi;           << 
2803     return { r*rho*std::cos(phi), r*rho*std:: << 
2804   }                                           << 
2805   else if (select < aInner + aOuter + aPhi) / << 
2806   {                                           << 
2807     G4double phi   = (select < aInner + aOute << 
2808     G4double r     = std::sqrt((RR - rr)*u +  << 
2809     G4double theta = fDTheta*v + fSTheta;     << 
2810     G4double z     = std::cos(theta);         << 
2811     G4double rho   = std::sin(theta);         << 
2812     return { r*rho*std::cos(phi), r*rho*std:: << 
2813   }                                           << 
2814   else                                     // << 
2815   {                                           << 
2816     G4double theta = (select < aTotal - aEThe << 
2817     G4double r     = std::sqrt((RR - rr)*u +  << 
2818     G4double phi   = fDPhi*v + fSPhi;         << 
2819     G4double z     = std::cos(theta);         << 
2820     G4double rho   = std::sin(theta);         << 
2821     return { r*rho*std::cos(phi), r*rho*std:: << 
2822   }                                           << 
2823 }                                             << 
2824                                               << 
2825 /////////////////////////////////////////////    2746 /////////////////////////////////////////////////////////////////////////////
2826 //                                               2747 //
2827 // Methods for visualisation                     2748 // Methods for visualisation
2828                                                  2749 
2829 G4VisExtent G4Sphere::GetExtent() const       << 
2830 {                                             << 
2831   return { -fRmax, fRmax,-fRmax, fRmax,-fRmax << 
2832 }                                             << 
2833                                               << 
2834                                               << 
2835 void G4Sphere::DescribeYourselfTo ( G4VGraphi    2750 void G4Sphere::DescribeYourselfTo ( G4VGraphicsScene& scene ) const
2836 {                                                2751 {
2837   scene.AddSolid (*this);                     << 2752   scene.AddThis (*this);
2838 }                                                2753 }
2839                                                  2754 
2840 G4Polyhedron* G4Sphere::CreatePolyhedron () c    2755 G4Polyhedron* G4Sphere::CreatePolyhedron () const
2841 {                                                2756 {
2842   return new G4PolyhedronSphere (fRmin, fRmax    2757   return new G4PolyhedronSphere (fRmin, fRmax, fSPhi, fDPhi, fSTheta, fDTheta);
2843 }                                                2758 }
2844                                                  2759 
2845 #endif                                        << 2760 G4NURBS* G4Sphere::CreateNURBS () const
                                                   >> 2761 {
                                                   >> 2762   return new G4NURBSbox (fRmax, fRmax, fRmax);       // Box for now!!!
                                                   >> 2763 }
                                                   >> 2764 
                                                   >> 2765 
                                                   >> 2766 // ******************************  End of G4Sphere.cc  ****************************************
2846                                                  2767