Geant4 Cross Reference

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


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
 26 // G4Torus implementation                      << 
 27 //                                                 26 //
 28 // 30.10.96 V.Grichine: first implementation w <<  27 // $Id: G4Torus.cc,v 1.63 2007/10/02 09:34:17 gcosmo Exp $
 29 // 26.05.00 V.Grichine: added new fuctions dev <<  28 // GEANT4 tag $Name: geant4-09-02 $
 30 // 31.08.00 E.Medernach: numerical computation <<  29 //
 31 // 11.01.01 E.Medernach: Use G4PolynomialSolve <<  30 // 
 32 // 03.05.05 V.Grichine: SurfaceNormal(p) accor <<  31 // class G4Torus
                                                   >>  32 //
                                                   >>  33 // Implementation
                                                   >>  34 //
                                                   >>  35 // 02.10.07 T.Nikitina: Bug fixed in SolveNumericJT(), b.969:segmentation fault.
                                                   >>  36 //                      rootsrefined is used only if the number of refined roots
                                                   >>  37 //                      is the same as for primary roots. 
                                                   >>  38 // 02.10.07 T.Nikitina: Bug fixed in CalculateExtent() for case of non-rotated
                                                   >>  39 //                      full-phi torus:protect against negative value for sqrt,
                                                   >>  40 //                      correct  formula for delta.  
                                                   >>  41 // 20.11.05 V.Grichine: Bug fixed in Inside(p) for phi sections, b.810 
 33 // 25.08.05 O.Link: new methods for DistanceTo     42 // 25.08.05 O.Link: new methods for DistanceToIn/Out using JTPolynomialSolver
 34 // 28.10.16 E.Tcherniaev: new CalculateExtent( <<  43 // 07.06.05 V.Grichine: SurfaceNormal(p) for rho=0, Constructor as G4Cons 
 35 // 16.12.16 H.Burkhardt: use radius difference <<  44 // 03.05.05 V.Grichine: SurfaceNormal(p) according to J. Apostolakis proposal
 36 // ------------------------------------------- <<  45 // 18.03.04 V.Grichine: bug fixed in DistanceToIn(p)
                                                   >>  46 // 11.01.01 E.Medernach: Use G4PolynomialSolver to find roots
                                                   >>  47 // 03.10.00 E.Medernach: SafeNewton added
                                                   >>  48 // 31.08.00 E.Medernach: numerical computation of roots wuth bounding
                                                   >>  49 //                       volume technique
                                                   >>  50 // 26.05.00 V.Grichine: new fuctions developed by O.Cremonesi were added
                                                   >>  51 // 06.03.00 V.Grichine: modifications in Distance ToOut(p,v,...)
                                                   >>  52 // 19.11.99 V.Grichine: side = kNull in Distance ToOut(p,v,...)
                                                   >>  53 // 09.10.98 V.Grichine: modifications in Distance ToOut(p,v,...)
                                                   >>  54 // 30.10.96 V.Grichine: first implementation with G4Tubs elements in Fs
                                                   >>  55 //
 37                                                    56 
 38 #include "G4Torus.hh"                              57 #include "G4Torus.hh"
 39                                                    58 
 40 #if !(defined(G4GEOM_USE_UTORUS) && defined(G4 << 
 41                                                << 
 42 #include "G4GeomTools.hh"                      << 
 43 #include "G4VoxelLimits.hh"                        59 #include "G4VoxelLimits.hh"
 44 #include "G4AffineTransform.hh"                    60 #include "G4AffineTransform.hh"
 45 #include "G4BoundingEnvelope.hh"               << 
 46 #include "G4GeometryTolerance.hh"                  61 #include "G4GeometryTolerance.hh"
 47 #include "G4JTPolynomialSolver.hh"                 62 #include "G4JTPolynomialSolver.hh"
 48                                                    63 
 49 #include "G4VPVParameterisation.hh"                64 #include "G4VPVParameterisation.hh"
 50                                                    65 
 51 #include "meshdefs.hh"                             66 #include "meshdefs.hh"
 52                                                    67 
 53 #include "Randomize.hh"                            68 #include "Randomize.hh"
 54                                                    69 
 55 #include "G4VGraphicsScene.hh"                     70 #include "G4VGraphicsScene.hh"
 56 #include "G4Polyhedron.hh"                         71 #include "G4Polyhedron.hh"
                                                   >>  72 #include "G4NURBS.hh"
                                                   >>  73 #include "G4NURBStube.hh"
                                                   >>  74 #include "G4NURBScylinder.hh"
                                                   >>  75 #include "G4NURBStubesector.hh"
 57                                                    76 
 58 using namespace CLHEP;                             77 using namespace CLHEP;
 59                                                    78 
 60 //////////////////////////////////////////////     79 ///////////////////////////////////////////////////////////////
 61 //                                                 80 //
 62 // Constructor - check parameters, convert ang     81 // Constructor - check parameters, convert angles so 0<sphi+dpshi<=2_PI
 63 //             - note if pdphi>2PI then reset      82 //             - note if pdphi>2PI then reset to 2PI
 64                                                    83 
 65 G4Torus::G4Torus( const G4String& pName,       <<  84 G4Torus::G4Torus( const G4String &pName,
 66                         G4double pRmin,            85                         G4double pRmin,
 67                         G4double pRmax,            86                         G4double pRmax,
 68                         G4double pRtor,            87                         G4double pRtor,
 69                         G4double pSPhi,            88                         G4double pSPhi,
 70                         G4double pDPhi )       <<  89                         G4double pDPhi)
 71   : G4CSGSolid(pName)                              90   : G4CSGSolid(pName)
 72 {                                                  91 {
 73   SetAllParameters(pRmin, pRmax, pRtor, pSPhi,     92   SetAllParameters(pRmin, pRmax, pRtor, pSPhi, pDPhi);
 74 }                                                  93 }
 75                                                    94 
 76 //////////////////////////////////////////////     95 ////////////////////////////////////////////////////////////////////////////
 77 //                                                 96 //
 78 //                                                 97 //
 79                                                    98 
 80 void                                               99 void
 81 G4Torus::SetAllParameters( G4double pRmin,        100 G4Torus::SetAllParameters( G4double pRmin,
 82                            G4double pRmax,        101                            G4double pRmax,
 83                            G4double pRtor,        102                            G4double pRtor,
 84                            G4double pSPhi,        103                            G4double pSPhi,
 85                            G4double pDPhi )       104                            G4double pDPhi )
 86 {                                                 105 {
 87   const G4double fEpsilon = 4.e-11;  // relati << 
 88                                                << 
 89   fCubicVolume = 0.;                              106   fCubicVolume = 0.;
 90   fSurfaceArea = 0.;                              107   fSurfaceArea = 0.;
 91   fRebuildPolyhedron = true;                   << 108   fpPolyhedron = 0;
 92                                                   109 
 93   kRadTolerance = G4GeometryTolerance::GetInst    110   kRadTolerance = G4GeometryTolerance::GetInstance()->GetRadialTolerance();
 94   kAngTolerance = G4GeometryTolerance::GetInst    111   kAngTolerance = G4GeometryTolerance::GetInstance()->GetAngularTolerance();
 95                                                   112 
 96   halfCarTolerance = 0.5*kCarTolerance;        << 
 97   halfAngTolerance = 0.5*kAngTolerance;        << 
 98                                                << 
 99   if ( pRtor >= pRmax+1.e3*kCarTolerance )  //    113   if ( pRtor >= pRmax+1.e3*kCarTolerance )  // Check swept radius, as in G4Cons
100   {                                               114   {
101     fRtor = pRtor ;                               115     fRtor = pRtor ;
102   }                                               116   }
103   else                                            117   else
104   {                                               118   {
105     std::ostringstream message;                << 119     G4cerr << "ERROR - G4Torus()::SetAllParameters(): " << GetName() << G4endl
106     message << "Invalid swept radius for Solid << 120            << "        Invalid swept radius !" << G4endl
107             << "        pRtor = " << pRtor <<  << 121            << "pRtor = " << pRtor << ", pRmax = " << pRmax << G4endl;
108     G4Exception("G4Torus::SetAllParameters()",    122     G4Exception("G4Torus::SetAllParameters()",
109                 "GeomSolids0002", FatalExcepti << 123                 "InvalidSetup", FatalException, "Invalid swept radius.");
110   }                                               124   }
111                                                   125 
112   // Check radii, as in G4Cons                    126   // Check radii, as in G4Cons
113   //                                              127   //
114   if ( pRmin < pRmax - 1.e2*kCarTolerance && p    128   if ( pRmin < pRmax - 1.e2*kCarTolerance && pRmin >= 0 )
115   {                                               129   {
116     if (pRmin >= 1.e2*kCarTolerance) { fRmin =    130     if (pRmin >= 1.e2*kCarTolerance) { fRmin = pRmin ; }
117     else                             { fRmin =    131     else                             { fRmin = 0.0   ; }
118     fRmax = pRmax ;                               132     fRmax = pRmax ;
119   }                                               133   }
120   else                                            134   else
121   {                                               135   {
122     std::ostringstream message;                << 136     G4cerr << "ERROR - G4Torus()::SetAllParameters(): " << GetName() << G4endl
123     message << "Invalid values of radii for So << 137            << "        Invalid values for radii !" << G4endl
124             << "        pRmin = " << pRmin <<  << 138            << "        pRmin = " << pRmin << ", pRmax = " << pRmax << G4endl;
125     G4Exception("G4Torus::SetAllParameters()",    139     G4Exception("G4Torus::SetAllParameters()",
126                 "GeomSolids0002", FatalExcepti << 140                 "InvalidSetup", FatalException, "Invalid radii.");
127   }                                               141   }
128                                                   142 
129   // Relative tolerances                       << 
130   //                                           << 
131   fRminTolerance = (fRmin) != 0.0              << 
132                  ? 0.5*std::max( kRadTolerance << 
133   fRmaxTolerance = 0.5*std::max( kRadTolerance << 
134                                                << 
135   // Check angles                                 143   // Check angles
136   //                                              144   //
137   if ( pDPhi >= twopi )  { fDPhi = twopi ; }      145   if ( pDPhi >= twopi )  { fDPhi = twopi ; }
138   else                                            146   else
139   {                                               147   {
140     if (pDPhi > 0)       { fDPhi = pDPhi ; }      148     if (pDPhi > 0)       { fDPhi = pDPhi ; }
141     else                                          149     else
142     {                                             150     {
143       std::ostringstream message;              << 151       G4cerr << "ERROR - G4Torus::SetAllParameters(): " << GetName() << G4endl
144       message << "Invalid Z delta-Phi for Soli << 152              << "        Negative Z delta-Phi ! - "
145               << "        pDPhi = " << pDPhi;  << 153              << pDPhi << G4endl;
146       G4Exception("G4Torus::SetAllParameters()    154       G4Exception("G4Torus::SetAllParameters()",
147                   "GeomSolids0002", FatalExcep << 155                   "InvalidSetup", FatalException, "Invalid dphi.");
148     }                                             156     }
149   }                                               157   }
150                                                   158   
151   // Ensure psphi in 0-2PI or -2PI-0 range if     159   // Ensure psphi in 0-2PI or -2PI-0 range if shape crosses 0
152   //                                              160   //
153   fSPhi = pSPhi;                                  161   fSPhi = pSPhi;
154                                                   162 
155   if (fSPhi < 0)  { fSPhi = twopi-std::fmod(st    163   if (fSPhi < 0)  { fSPhi = twopi-std::fmod(std::fabs(fSPhi),twopi) ; }
156   else            { fSPhi = std::fmod(fSPhi,tw    164   else            { fSPhi = std::fmod(fSPhi,twopi) ; }
157                                                   165 
158   if (fSPhi+fDPhi > twopi)  { fSPhi-=twopi ; }    166   if (fSPhi+fDPhi > twopi)  { fSPhi-=twopi ; }
159 }                                                 167 }
160                                                   168 
161 //////////////////////////////////////////////    169 ///////////////////////////////////////////////////////////////////////
162 //                                                170 //
163 // Fake default constructor - sets only member    171 // Fake default constructor - sets only member data and allocates memory
164 //                            for usage restri    172 //                            for usage restricted to object persistency.
165 //                                                173 //
166 G4Torus::G4Torus( __void__& a )                   174 G4Torus::G4Torus( __void__& a )
167   : G4CSGSolid(a)                                 175   : G4CSGSolid(a)
168 {                                                 176 {
169 }                                                 177 }
170                                                   178 
171 //////////////////////////////////////////////    179 //////////////////////////////////////////////////////////////////////
172 //                                                180 //
173 // Destructor                                     181 // Destructor
174                                                   182 
175 G4Torus::~G4Torus() = default;                 << 183 G4Torus::~G4Torus()
176                                                << 184 {}
177 ////////////////////////////////////////////// << 
178 //                                             << 
179 // Copy constructor                            << 
180                                                << 
181 G4Torus::G4Torus(const G4Torus&) = default;    << 
182                                                << 
183 ////////////////////////////////////////////// << 
184 //                                             << 
185 // Assignment operator                         << 
186                                                << 
187 G4Torus& G4Torus::operator = (const G4Torus& r << 
188 {                                              << 
189    // Check assignment to self                 << 
190    //                                          << 
191    if (this == &rhs)  { return *this; }        << 
192                                                << 
193    // Copy base class data                     << 
194    //                                          << 
195    G4CSGSolid::operator=(rhs);                 << 
196                                                << 
197    // Copy data                                << 
198    //                                          << 
199    fRmin = rhs.fRmin; fRmax = rhs.fRmax;       << 
200    fRtor = rhs.fRtor; fSPhi = rhs.fSPhi; fDPhi << 
201    fRminTolerance = rhs.fRminTolerance; fRmaxT << 
202    kRadTolerance = rhs.kRadTolerance; kAngTole << 
203    halfCarTolerance = rhs.halfCarTolerance;    << 
204    halfAngTolerance = rhs.halfAngTolerance;    << 
205                                                << 
206    return *this;                               << 
207 }                                              << 
208                                                   185 
209 //////////////////////////////////////////////    186 //////////////////////////////////////////////////////////////////////
210 //                                                187 //
211 // Dispatch to parameterisation for replicatio    188 // Dispatch to parameterisation for replication mechanism dimension
212 // computation & modification.                    189 // computation & modification.
213                                                   190 
214 void G4Torus::ComputeDimensions(       G4VPVPa    191 void G4Torus::ComputeDimensions(       G4VPVParameterisation* p,
215                                  const G4int n    192                                  const G4int n,
216                                  const G4VPhys    193                                  const G4VPhysicalVolume* pRep )
217 {                                                 194 {
218   p->ComputeDimensions(*this,n,pRep);             195   p->ComputeDimensions(*this,n,pRep);
219 }                                                 196 }
220                                                   197 
221                                                   198 
222                                                   199 
223 //////////////////////////////////////////////    200 ////////////////////////////////////////////////////////////////////////////////
224 //                                                201 //
225 // Calculate the real roots to torus surface.     202 // Calculate the real roots to torus surface. 
226 // Returns negative solutions as well.            203 // Returns negative solutions as well.
227                                                   204 
228 void G4Torus::TorusRootsJT( const G4ThreeVecto << 205 std::vector<G4double> G4Torus::TorusRootsJT( const G4ThreeVector& p,
229                             const G4ThreeVecto << 206                                              const G4ThreeVector& v,
230                                   G4double r,  << 207                                                    G4double r ) const
231                                   std::vector< << 
232 {                                                 208 {
233                                                   209 
234   G4int i, num ;                                  210   G4int i, num ;
235   G4double c[5], srd[4], si[4] ;               << 211   G4double c[5], sr[4], si[4] ;
                                                   >> 212   std::vector<G4double> roots ;
236                                                   213 
237   G4double Rtor2 = fRtor*fRtor, r2 = r*r  ;       214   G4double Rtor2 = fRtor*fRtor, r2 = r*r  ;
238                                                   215 
239   G4double pDotV = p.x()*v.x() + p.y()*v.y() +    216   G4double pDotV = p.x()*v.x() + p.y()*v.y() + p.z()*v.z() ;
240   G4double pRad2 = p.x()*p.x() + p.y()*p.y() +    217   G4double pRad2 = p.x()*p.x() + p.y()*p.y() + p.z()*p.z() ;
241                                                   218 
242   G4double d=pRad2 - Rtor2;                    << 
243   c[0] = 1.0 ;                                    219   c[0] = 1.0 ;
244   c[1] = 4*pDotV ;                                220   c[1] = 4*pDotV ;
245   c[2] = 2*( (d + 2*pDotV*pDotV  - r2) + 2*Rto << 221   c[2] = 2*(pRad2 + 2*pDotV*pDotV - Rtor2 - r2 + 2*Rtor2*v.z()*v.z()) ;
246   c[3] = 4*(pDotV*(d - r2) + 2*Rtor2*p.z()*v.z << 222   c[3] = 4*(pDotV*(pRad2 - Rtor2 - r2) + 2*Rtor2*p.z()*v.z()) ;
247   c[4] = (d-r2)*(d-r2) +4*Rtor2*(p.z()*p.z()-r << 223   c[4] = pRad2*pRad2 - 2*pRad2*(Rtor2+r2) 
248                                                << 224        + 4*Rtor2*p.z()*p.z() + (Rtor2-r2)*(Rtor2-r2) ;
                                                   >> 225   
249   G4JTPolynomialSolver  torusEq;                  226   G4JTPolynomialSolver  torusEq;
250                                                   227 
251   num = torusEq.FindRoots( c, 4, srd, si );    << 228   num = torusEq.FindRoots( c, 4, sr, si );
252                                                   229   
253   for ( i = 0; i < num; ++i )                  << 230   for ( i = 0; i < num; i++ ) 
254   {                                               231   {
255     if( si[i] == 0. )  { roots.push_back(srd[i << 232     if( si[i] == 0. )  { roots.push_back(sr[i]) ; }  // store real roots
256   }                                               233   }  
257                                                   234 
258   std::sort(roots.begin() , roots.end() ) ;  / << 235   std::sort(roots.begin() , roots.end() ) ;  // sorting  with < 
                                                   >> 236 
                                                   >> 237   return roots;
259 }                                                 238 }
260                                                   239 
261 //////////////////////////////////////////////    240 //////////////////////////////////////////////////////////////////////////////
262 //                                                241 //
263 // Interface for DistanceToIn and DistanceToOu    242 // Interface for DistanceToIn and DistanceToOut.
264 // Calls TorusRootsJT and returns the smalles     243 // Calls TorusRootsJT and returns the smalles possible distance to 
265 // the surface.                                   244 // the surface.
266 // Attention: Difference in DistanceToIn/Out f    245 // Attention: Difference in DistanceToIn/Out for points p on the surface.
267                                                   246 
268 G4double G4Torus::SolveNumericJT( const G4Thre    247 G4double G4Torus::SolveNumericJT( const G4ThreeVector& p,
269                                   const G4Thre    248                                   const G4ThreeVector& v,
270                                         G4doub    249                                         G4double r,
271                                         G4bool    250                                         G4bool IsDistanceToIn ) const
272 {                                                 251 {
273   G4double bigdist = 10*mm ;                      252   G4double bigdist = 10*mm ;
274   G4double tmin = kInfinity ;                     253   G4double tmin = kInfinity ;
275   G4double t, scal ;                              254   G4double t, scal ;
276                                                   255 
277   // calculate the distances to the intersecti    256   // calculate the distances to the intersections with the Torus
278   // from a given point p and direction v.        257   // from a given point p and direction v.
279   //                                              258   //
280   std::vector<G4double> roots ;                   259   std::vector<G4double> roots ;
281   std::vector<G4double> rootsrefined ;            260   std::vector<G4double> rootsrefined ;
282   TorusRootsJT(p,v,r,roots) ;                  << 261   roots = TorusRootsJT(p,v,r) ;
283                                                   262 
284   G4ThreeVector ptmp ;                            263   G4ThreeVector ptmp ;
285                                                   264 
286   // determine the smallest non-negative solut    265   // determine the smallest non-negative solution
287   //                                              266   //
288   for ( std::size_t k = 0 ; k<roots.size() ; + << 267   for ( size_t k = 0 ; k<roots.size() ; k++ )
289   {                                               268   {
290     t = roots[k] ;                                269     t = roots[k] ;
291                                                   270 
292     if ( t < -halfCarTolerance )  { continue ; << 271     if ( t < -0.5*kCarTolerance )  { continue ; }  // skip negative roots
293                                                   272 
294     if ( t > bigdist && t<kInfinity )    // pr    273     if ( t > bigdist && t<kInfinity )    // problem with big distances
295     {                                             274     {
296       ptmp = p + t*v ;                            275       ptmp = p + t*v ;
297       TorusRootsJT(ptmp,v,r,rootsrefined) ;    << 276       rootsrefined = TorusRootsJT(ptmp,v,r) ;
298       if ( rootsrefined.size()==roots.size() )    277       if ( rootsrefined.size()==roots.size() )
299       {                                           278       {
300         t = t + rootsrefined[k] ;                 279         t = t + rootsrefined[k] ;
301       }                                           280       }
302     }                                             281     }
303                                                   282 
304     ptmp = p + t*v ;   // calculate the positi    283     ptmp = p + t*v ;   // calculate the position of the proposed intersection
305                                                   284 
306     G4double theta = std::atan2(ptmp.y(),ptmp.    285     G4double theta = std::atan2(ptmp.y(),ptmp.x());
                                                   >> 286 
                                                   >> 287     if (theta < 0)  { theta += twopi; }
307                                                   288     
308     if ( fSPhi >= 0 )                          << 
309     {                                          << 
310       if ( theta < - halfAngTolerance )  { the << 
311       if ( (std::fabs(theta) < halfAngToleranc << 
312         && (std::fabs(fSPhi + fDPhi - twopi) < << 
313       {                                        << 
314         theta += twopi ; // 0 <= theta < 2pi   << 
315       }                                        << 
316     }                                          << 
317     if ((fSPhi <= -pi )&&(theta>halfAngToleran << 
318                                                << 
319     // We have to verify if this root is insid    289     // We have to verify if this root is inside the region between
320     // fSPhi and fSPhi + fDPhi                    290     // fSPhi and fSPhi + fDPhi
321     //                                            291     //
322     if ( (theta - fSPhi >= - halfAngTolerance) << 292     if ( (theta - fSPhi >= - kAngTolerance*0.5)
323       && (theta - (fSPhi + fDPhi) <=  halfAngT << 293       && (theta - (fSPhi + fDPhi) <=  kAngTolerance*0.5) )
324     {                                             294     {
325       // check if P is on the surface, and cal    295       // check if P is on the surface, and called from DistanceToIn
326       // DistanceToIn has to return 0.0 if par    296       // DistanceToIn has to return 0.0 if particle is going inside the solid
327                                                   297 
328       if ( IsDistanceToIn )                    << 298       if ( IsDistanceToIn == true )
329       {                                           299       {
330         if (std::fabs(t) < halfCarTolerance )  << 300         if (std::fabs(t) < 0.5*kCarTolerance )
331         {                                         301         {
332           // compute scalar product at positio    302           // compute scalar product at position p : v.n
333           // ( n taken from SurfaceNormal, not    303           // ( n taken from SurfaceNormal, not normalized )
334                                                   304 
335           scal = v* G4ThreeVector( p.x()*(1-fR << 305           scal = v* G4ThreeVector( p.x()*(1-fRtor/std::sqrt(p.x()*p.x()
336                                    p.y()*(1-fR << 306                                           + p.y()*p.y())),
                                                   >> 307                                    p.y()*(1-fRtor/std::sqrt(p.x()*p.x()
                                                   >> 308                                           + p.y()*p.y())),
337                                    p.z() );       309                                    p.z() );
338                                                   310 
339           // change sign in case of inner radi    311           // change sign in case of inner radius
340           //                                      312           //
341           if ( r == GetRmin() )  { scal = -sca    313           if ( r == GetRmin() )  { scal = -scal ; }
342           if ( scal < 0 )  { return 0.0  ; }      314           if ( scal < 0 )  { return 0.0  ; }
343         }                                         315         }
344       }                                           316       }
345                                                   317 
346       // check if P is on the surface, and cal    318       // check if P is on the surface, and called from DistanceToOut
347       // DistanceToIn has to return 0.0 if par    319       // DistanceToIn has to return 0.0 if particle is leaving the solid
348                                                   320 
349       if ( !IsDistanceToIn )                   << 321       if ( IsDistanceToIn == false )
350       {                                           322       {
351         if (std::fabs(t) < halfCarTolerance )  << 323         if (std::fabs(t) < 0.5*kCarTolerance )
352         {                                         324         {
353           // compute scalar product at positio    325           // compute scalar product at position p : v.n   
354           //                                      326           //
355           scal = v* G4ThreeVector( p.x()*(1-fR << 327           scal = v* G4ThreeVector( p.x()*(1-fRtor/std::sqrt(p.x()*p.x()
356                                    p.y()*(1-fR << 328                                           + p.y()*p.y())),
                                                   >> 329                                    p.y()*(1-fRtor/std::sqrt(p.x()*p.x()
                                                   >> 330                                           + p.y()*p.y())),
357                                    p.z() );       331                                    p.z() );
358                                                   332 
359           // change sign in case of inner radi    333           // change sign in case of inner radius
360           //                                      334           //
361           if ( r == GetRmin() )  { scal = -sca    335           if ( r == GetRmin() )  { scal = -scal ; }
362           if ( scal > 0 )  { return 0.0  ; }      336           if ( scal > 0 )  { return 0.0  ; }
363         }                                         337         }
364       }                                           338       }
365                                                   339 
366       // check if distance is larger than 1/2     340       // check if distance is larger than 1/2 kCarTolerance
367       //                                          341       //
368       if(  t > halfCarTolerance  )             << 342       if(  t > 0.5*kCarTolerance  )
369       {                                           343       {
370         tmin = t  ;                               344         tmin = t  ;
371         return tmin  ;                            345         return tmin  ;
372       }                                           346       }
373     }                                             347     }
374   }                                               348   }
375                                                   349 
376   return tmin;                                    350   return tmin;
377 }                                                 351 }
378                                                   352 
379 //////////////////////////////////////////////    353 /////////////////////////////////////////////////////////////////////////////
380 //                                                354 //
381 // Get bounding box                            << 
382                                                << 
383 void G4Torus::BoundingLimits(G4ThreeVector& pM << 
384 {                                              << 
385   G4double rmax = GetRmax();                   << 
386   G4double rtor = GetRtor();                   << 
387   G4double rint = rtor - rmax;                 << 
388   G4double rext = rtor + rmax;                 << 
389   G4double dz   = rmax;                        << 
390                                                << 
391   // Find bounding box                         << 
392   //                                           << 
393   if (GetDPhi() >= twopi)                      << 
394   {                                            << 
395     pMin.set(-rext,-rext,-dz);                 << 
396     pMax.set( rext, rext, dz);                 << 
397   }                                            << 
398   else                                         << 
399   {                                            << 
400     G4TwoVector vmin,vmax;                     << 
401     G4GeomTools::DiskExtent(rint,rext,         << 
402                             GetSinStartPhi(),G << 
403                             GetSinEndPhi(),Get << 
404                             vmin,vmax);        << 
405     pMin.set(vmin.x(),vmin.y(),-dz);           << 
406     pMax.set(vmax.x(),vmax.y(), dz);           << 
407   }                                            << 
408                                                << 
409   // Check correctness of the bounding box     << 
410   //                                           << 
411   if (pMin.x() >= pMax.x() || pMin.y() >= pMax << 
412   {                                            << 
413     std::ostringstream message;                << 
414     message << "Bad bounding box (min >= max)  << 
415             << GetName() << " !"               << 
416             << "\npMin = " << pMin             << 
417             << "\npMax = " << pMax;            << 
418     G4Exception("G4Torus::BoundingLimits()", " << 
419                 JustWarning, message);         << 
420     DumpInfo();                                << 
421   }                                            << 
422 }                                              << 
423                                                << 
424 ////////////////////////////////////////////// << 
425 //                                             << 
426 // Calculate extent under transform and specif    355 // Calculate extent under transform and specified limit
427                                                   356 
428 G4bool G4Torus::CalculateExtent( const EAxis p    357 G4bool G4Torus::CalculateExtent( const EAxis pAxis,
429                                  const G4Voxel    358                                  const G4VoxelLimits& pVoxelLimit,
430                                  const G4Affin    359                                  const G4AffineTransform& pTransform,
431                                        G4doubl    360                                        G4double& pMin, G4double& pMax) const
432 {                                                 361 {
433   G4ThreeVector bmin, bmax;                    << 362   if ((!pTransform.IsRotated()) && (fDPhi==twopi) && (fRmin==0))
434   G4bool exist;                                << 363   {
                                                   >> 364     // Special case handling for unrotated solid torus
                                                   >> 365     // Compute x/y/z mins and maxs for bounding box respecting limits,
                                                   >> 366     // with early returns if outside limits. Then switch() on pAxis,
                                                   >> 367     // and compute exact x and y limit for x/y case
                                                   >> 368       
                                                   >> 369     G4double xoffset,xMin,xMax;
                                                   >> 370     G4double yoffset,yMin,yMax;
                                                   >> 371     G4double zoffset,zMin,zMax;
                                                   >> 372 
                                                   >> 373     G4double RTorus,delta,diff1,diff2,maxDiff,newMin,newMax;
                                                   >> 374     G4double xoff1,xoff2,yoff1,yoff2;
                                                   >> 375 
                                                   >> 376     xoffset = pTransform.NetTranslation().x();
                                                   >> 377     xMin    = xoffset - fRmax - fRtor ;
                                                   >> 378     xMax    = xoffset + fRmax + fRtor ;
                                                   >> 379 
                                                   >> 380     if (pVoxelLimit.IsXLimited())
                                                   >> 381     {
                                                   >> 382       if ( (xMin > pVoxelLimit.GetMaxXExtent()+kCarTolerance)
                                                   >> 383         || (xMax < pVoxelLimit.GetMinXExtent()-kCarTolerance) )
                                                   >> 384         return false ;
                                                   >> 385       else
                                                   >> 386       {
                                                   >> 387         if (xMin < pVoxelLimit.GetMinXExtent())
                                                   >> 388         {
                                                   >> 389           xMin = pVoxelLimit.GetMinXExtent() ;
                                                   >> 390         }
                                                   >> 391         if (xMax > pVoxelLimit.GetMaxXExtent())
                                                   >> 392         {
                                                   >> 393           xMax = pVoxelLimit.GetMaxXExtent() ;
                                                   >> 394         }
                                                   >> 395       }
                                                   >> 396     }
                                                   >> 397     yoffset = pTransform.NetTranslation().y();
                                                   >> 398     yMin    = yoffset - fRmax - fRtor ;
                                                   >> 399     yMax    = yoffset + fRmax + fRtor ;
435                                                   400 
436   // Get bounding box                          << 401     if (pVoxelLimit.IsYLimited())
437   BoundingLimits(bmin,bmax);                   << 402     {
                                                   >> 403       if ( (yMin > pVoxelLimit.GetMaxYExtent()+kCarTolerance)
                                                   >> 404         || (yMax < pVoxelLimit.GetMinYExtent()-kCarTolerance) )
                                                   >> 405       {
                                                   >> 406         return false ;
                                                   >> 407       }
                                                   >> 408       else
                                                   >> 409       {
                                                   >> 410         if (yMin < pVoxelLimit.GetMinYExtent() )
                                                   >> 411         {
                                                   >> 412           yMin = pVoxelLimit.GetMinYExtent() ;
                                                   >> 413         }
                                                   >> 414         if (yMax > pVoxelLimit.GetMaxYExtent() )
                                                   >> 415         {
                                                   >> 416           yMax = pVoxelLimit.GetMaxYExtent() ;
                                                   >> 417         }
                                                   >> 418       }
                                                   >> 419     }
                                                   >> 420     zoffset = pTransform.NetTranslation().z() ;
                                                   >> 421     zMin    = zoffset - fRmax ;
                                                   >> 422     zMax    = zoffset + fRmax ;
438                                                   423 
439   // Check bounding box                        << 424     if (pVoxelLimit.IsZLimited())
440   G4BoundingEnvelope bbox(bmin,bmax);          << 425     {
441 #ifdef G4BBOX_EXTENT                           << 426       if ( (zMin > pVoxelLimit.GetMaxZExtent()+kCarTolerance)
442   return bbox.CalculateExtent(pAxis,pVoxelLimi << 427         || (zMax < pVoxelLimit.GetMinZExtent()-kCarTolerance) )
443 #endif                                         << 428       {
444   if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox << 429         return false ;
445   {                                            << 430       }
446     return exist = pMin < pMax;                << 431       else
                                                   >> 432       {
                                                   >> 433         if (zMin < pVoxelLimit.GetMinZExtent() )
                                                   >> 434         {
                                                   >> 435           zMin = pVoxelLimit.GetMinZExtent() ;
                                                   >> 436         }
                                                   >> 437         if (zMax > pVoxelLimit.GetMaxZExtent() )
                                                   >> 438         {
                                                   >> 439           zMax = pVoxelLimit.GetMaxZExtent() ;
                                                   >> 440         }
                                                   >> 441       }
                                                   >> 442     }
                                                   >> 443 
                                                   >> 444     // Known to cut cylinder
                                                   >> 445     
                                                   >> 446     switch (pAxis)
                                                   >> 447     {
                                                   >> 448       case kXAxis:
                                                   >> 449         yoff1=yoffset-yMin;
                                                   >> 450         yoff2=yMax-yoffset;
                                                   >> 451         if ( yoff1 >= 0 && yoff2 >= 0 )
                                                   >> 452         {
                                                   >> 453           // Y limits cross max/min x => no change
                                                   >> 454           //
                                                   >> 455           pMin = xMin ;
                                                   >> 456           pMax = xMax ;
                                                   >> 457         }
                                                   >> 458         else
                                                   >> 459         {
                                                   >> 460           // Y limits don't cross max/min x => compute max delta x,
                                                   >> 461           // hence new mins/maxs
                                                   >> 462           //
                                                   >> 463           RTorus=fRmax+fRtor;
                                                   >> 464           delta   = RTorus*RTorus - yoff1*yoff1;
                                                   >> 465           diff1   = (delta>0.) ? std::sqrt(delta) : 0.;
                                                   >> 466           delta   = RTorus*RTorus - yoff2*yoff2;
                                                   >> 467           diff2   = (delta>0.) ? std::sqrt(delta) : 0.;
                                                   >> 468           maxDiff = (diff1 > diff2) ? diff1:diff2 ;
                                                   >> 469           newMin  = xoffset - maxDiff ;
                                                   >> 470           newMax  = xoffset + maxDiff ;
                                                   >> 471           pMin    = (newMin < xMin) ? xMin : newMin ;
                                                   >> 472           pMax    = (newMax > xMax) ? xMax : newMax ;
                                                   >> 473         }
                                                   >> 474         break;
                                                   >> 475 
                                                   >> 476       case kYAxis:
                                                   >> 477         xoff1 = xoffset - xMin ;
                                                   >> 478         xoff2 = xMax - xoffset ;
                                                   >> 479         if (xoff1 >= 0 && xoff2 >= 0 )
                                                   >> 480         {
                                                   >> 481           // X limits cross max/min y => no change
                                                   >> 482           //
                                                   >> 483           pMin = yMin ;
                                                   >> 484           pMax = yMax ;
                                                   >> 485         } 
                                                   >> 486         else
                                                   >> 487         {
                                                   >> 488           // X limits don't cross max/min y => compute max delta y,
                                                   >> 489           // hence new mins/maxs
                                                   >> 490           //
                                                   >> 491           RTorus=fRmax+fRtor;
                                                   >> 492           delta   = RTorus*RTorus - xoff1*xoff1;
                                                   >> 493           diff1   = (delta>0.) ? std::sqrt(delta) : 0.;
                                                   >> 494           delta   = RTorus*RTorus - xoff2*xoff2;
                                                   >> 495           diff2   = (delta>0.) ? std::sqrt(delta) : 0.;
                                                   >> 496           maxDiff = (diff1 > diff2) ? diff1 : diff2 ;
                                                   >> 497           newMin  = yoffset - maxDiff ;
                                                   >> 498           newMax  = yoffset + maxDiff ;
                                                   >> 499           pMin    = (newMin < yMin) ? yMin : newMin ;
                                                   >> 500           pMax    = (newMax > yMax) ? yMax : newMax ;
                                                   >> 501         }
                                                   >> 502         break;
                                                   >> 503 
                                                   >> 504       case kZAxis:
                                                   >> 505         pMin=zMin;
                                                   >> 506         pMax=zMax;
                                                   >> 507         break;
                                                   >> 508 
                                                   >> 509       default:
                                                   >> 510         break;
                                                   >> 511     }
                                                   >> 512     pMin -= kCarTolerance ;
                                                   >> 513     pMax += kCarTolerance ;
                                                   >> 514 
                                                   >> 515     return true;
447   }                                               516   }
                                                   >> 517   else
                                                   >> 518   {
                                                   >> 519     G4int i, noEntries, noBetweenSections4 ;
                                                   >> 520     G4bool existsAfterClip = false ;
448                                                   521 
449   // Get parameters of the solid               << 522     // Calculate rotated vertex coordinates
450   G4double rmin = GetRmin();                   << 
451   G4double rmax = GetRmax();                   << 
452   G4double rtor = GetRtor();                   << 
453   G4double dphi = GetDPhi();                   << 
454   G4double sinStart = GetSinStartPhi();        << 
455   G4double cosStart = GetCosStartPhi();        << 
456   G4double sinEnd   = GetSinEndPhi();          << 
457   G4double cosEnd   = GetCosEndPhi();          << 
458   G4double rint = rtor - rmax;                 << 
459   G4double rext = rtor + rmax;                 << 
460                                                   523 
461   // Find bounding envelope and calculate exte << 524     G4ThreeVectorList *vertices ;
462   //                                           << 525     G4int noPolygonVertices ;  // will be 4 
463   static const G4int NPHI  = 24; // number of  << 526     vertices = CreateRotatedVertices(pTransform,noPolygonVertices) ;
464   static const G4int NDISK = 16; // number of  << 527 
465   static const G4double sinHalfDisk = std::sin << 528     pMin = +kInfinity ;
466   static const G4double cosHalfDisk = std::cos << 529     pMax = -kInfinity ;
467   static const G4double sinStepDisk = 2.*sinHa << 530 
468   static const G4double cosStepDisk = 1. - 2.* << 531     noEntries          = vertices->size() ;
469                                                << 532     noBetweenSections4 = noEntries - noPolygonVertices ;
470   G4double astep = (360/NPHI)*deg; // max angl << 533       
471   G4int    kphi  = (dphi <= astep) ? 1 : (G4in << 534     for (i=0;i<noEntries;i+=noPolygonVertices)
472   G4double ang   = dphi/kphi;                  << 535     {
473                                                << 536       ClipCrossSection(vertices,i,pVoxelLimit,pAxis,pMin,pMax);
474   G4double sinHalf = std::sin(0.5*ang);        << 537     }    
475   G4double cosHalf = std::cos(0.5*ang);        << 538     for (i=0;i<noBetweenSections4;i+=noPolygonVertices)
476   G4double sinStep = 2.*sinHalf*cosHalf;       << 539     {
477   G4double cosStep = 1. - 2.*sinHalf*sinHalf;  << 540       ClipBetweenSections(vertices,i,pVoxelLimit,pAxis,pMin,pMax);
478                                                << 541     }
479   // define vectors for bounding envelope      << 542     if (pMin!=kInfinity||pMax!=-kInfinity)
480   G4ThreeVectorList pols[NDISK+1];             << 543     {
481   for (auto & pol : pols) pol.resize(4);       << 544       existsAfterClip = true ; // Add 2*tolerance to avoid precision troubles
482                                                << 545       pMin           -= kCarTolerance ;
483   std::vector<const G4ThreeVectorList *> polyg << 546       pMax           += kCarTolerance ;
484   polygons.resize(NDISK+1);                    << 
485   for (G4int k=0; k<NDISK+1; ++k) polygons[k]  << 
486                                                << 
487   // set internal and external reference circl << 
488   G4TwoVector rzmin[NDISK];                    << 
489   G4TwoVector rzmax[NDISK];                    << 
490                                                << 
491   if ((rtor-rmin*sinHalfDisk)/cosHalf > (rtor+ << 
492   rmax /= cosHalfDisk;                         << 
493   G4double sinCurDisk = sinHalfDisk;           << 
494   G4double cosCurDisk = cosHalfDisk;           << 
495   for (G4int k=0; k<NDISK; ++k)                << 
496   {                                            << 
497     G4double rmincur = rtor + rmin*cosCurDisk; << 
498     if (cosCurDisk < 0 && rmin > 0) rmincur /= << 
499     rzmin[k].set(rmincur,rmin*sinCurDisk);     << 
500                                                << 
501     G4double rmaxcur = rtor + rmax*cosCurDisk; << 
502     if (cosCurDisk > 0) rmaxcur /= cosHalf;    << 
503     rzmax[k].set(rmaxcur,rmax*sinCurDisk);     << 
504                                                << 
505     G4double sinTmpDisk = sinCurDisk;          << 
506     sinCurDisk = sinCurDisk*cosStepDisk + cosC << 
507     cosCurDisk = cosCurDisk*cosStepDisk - sinT << 
508   }                                            << 
509                                                << 
510   // Loop along slices in Phi. The extent is c << 
511   // extent of the slices                      << 
512   pMin =  kInfinity;                           << 
513   pMax = -kInfinity;                           << 
514   G4double eminlim = pVoxelLimit.GetMinExtent( << 
515   G4double emaxlim = pVoxelLimit.GetMaxExtent( << 
516   G4double sinCur1 = 0, cosCur1 = 0, sinCur2 = << 
517   for (G4int i=0; i<kphi+1; ++i)               << 
518   {                                            << 
519     if (i == 0)                                << 
520     {                                          << 
521       sinCur1 = sinStart;                      << 
522       cosCur1 = cosStart;                      << 
523       sinCur2 = sinCur1*cosHalf + cosCur1*sinH << 
524       cosCur2 = cosCur1*cosHalf - sinCur1*sinH << 
525     }                                             547     }
526     else                                          548     else
527     {                                             549     {
528       sinCur1 = sinCur2;                       << 550       // Check for case where completely enveloping clipping volume
529       cosCur1 = cosCur2;                       << 551       // If point inside then we are confident that the solid completely
530       sinCur2 = (i == kphi) ? sinEnd : sinCur1 << 552       // envelopes the clipping volume. Hence set min/max extents according
531       cosCur2 = (i == kphi) ? cosEnd : cosCur1 << 553       // to clipping volume extents along the specified axis.
532     }                                          << 554 
533     for (G4int k=0; k<NDISK; ++k)              << 555       G4ThreeVector clipCentre(
534     {                                          << 556           (pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
535       G4double r1 = rzmin[k].x(), r2 = rzmax[k << 557           (pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
536       G4double z1 = rzmin[k].y(), z2 = rzmax[k << 558           (pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5  ) ;
537       pols[k][0].set(r1*cosCur1,r1*sinCur1,z1) << 559         
538       pols[k][1].set(r2*cosCur1,r2*sinCur1,z2) << 560       if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside )
539       pols[k][2].set(r2*cosCur2,r2*sinCur2,z2) << 561       {
540       pols[k][3].set(r1*cosCur2,r1*sinCur2,z1) << 562         existsAfterClip = true ;
541     }                                          << 563         pMin            = pVoxelLimit.GetMinExtent(pAxis) ;
542     pols[NDISK] = pols[0];                     << 564         pMax            = pVoxelLimit.GetMaxExtent(pAxis) ;
543                                                << 565       }
544     // get bounding box of current slice       << 566     }
545     G4TwoVector vmin,vmax;                     << 567     delete vertices;
546     G4GeomTools::                              << 568     return existsAfterClip;
547       DiskExtent(rint,rext,sinCur1,cosCur1,sin << 
548     bmin.setX(vmin.x()); bmin.setY(vmin.y());  << 
549     bmax.setX(vmax.x()); bmax.setY(vmax.y());  << 
550                                                << 
551     // set bounding envelope for current slice << 
552     G4double emin,emax;                        << 
553     G4BoundingEnvelope benv(bmin,bmax,polygons << 
554     if (!benv.CalculateExtent(pAxis,pVoxelLimi << 
555     if (emin < pMin) pMin = emin;              << 
556     if (emax > pMax) pMax = emax;              << 
557     if (eminlim > pMin && emaxlim < pMax) brea << 
558   }                                               569   }
559   return (pMin < pMax);                        << 
560 }                                                 570 }
561                                                   571 
562 //////////////////////////////////////////////    572 //////////////////////////////////////////////////////////////////////////////
563 //                                                573 //
564 // Return whether point inside/outside/on surf    574 // Return whether point inside/outside/on surface
565                                                   575 
566 EInside G4Torus::Inside( const G4ThreeVector&     576 EInside G4Torus::Inside( const G4ThreeVector& p ) const
567 {                                                 577 {
568   G4double r, pt2, pPhi, tolRMin, tolRMax ;    << 578   G4double r2, pt2, pPhi, tolRMin, tolRMax ;
569                                                   579 
570   EInside in = kOutside ;                         580   EInside in = kOutside ;
                                                   >> 581                                               // General precals
                                                   >> 582   r2  = p.x()*p.x() + p.y()*p.y() ;
                                                   >> 583   pt2 = r2 + p.z()*p.z() + fRtor*fRtor - 2*fRtor*std::sqrt(r2) ;
571                                                   584 
572   // General precals                           << 585   if (fRmin) tolRMin = fRmin + kRadTolerance*0.5 ;
573   //                                           << 
574   r   = std::hypot(p.x(),p.y());               << 
575   pt2 = p.z()*p.z() + (r-fRtor)*(r-fRtor);     << 
576                                                << 
577   if (fRmin != 0.0) tolRMin = fRmin + fRminTol << 
578   else       tolRMin = 0 ;                        586   else       tolRMin = 0 ;
579                                                   587 
580   tolRMax = fRmax - fRmaxTolerance;            << 588   tolRMax = fRmax - kRadTolerance*0.5;
581                                                   589       
582   if (pt2 >= tolRMin*tolRMin && pt2 <= tolRMax    590   if (pt2 >= tolRMin*tolRMin && pt2 <= tolRMax*tolRMax )
583   {                                               591   {
584     if ( fDPhi == twopi || pt2 == 0 )  // on t    592     if ( fDPhi == twopi || pt2 == 0 )  // on torus swept axis
585     {                                             593     {
586       in = kInside ;                              594       in = kInside ;
587     }                                             595     }
588     else                                          596     else
589     {                                             597     {
590       // Try inner tolerant phi boundaries (=>    598       // Try inner tolerant phi boundaries (=>inside)
591       // if not inside, try outer tolerant phi    599       // if not inside, try outer tolerant phi boundaries
592                                                   600 
593       pPhi = std::atan2(p.y(),p.x()) ;            601       pPhi = std::atan2(p.y(),p.x()) ;
594                                                   602 
595       if ( pPhi < -halfAngTolerance )  { pPhi  << 603       if ( pPhi < -kAngTolerance*0.5 )  { pPhi += twopi ; }  // 0<=pPhi<2pi
596       if ( fSPhi >= 0 )                           604       if ( fSPhi >= 0 )
597       {                                           605       {
598         if ( (std::fabs(pPhi) < halfAngToleran << 606         if ( (std::abs(pPhi) < kAngTolerance*0.5)
599             && (std::fabs(fSPhi + fDPhi - twop << 607             && (std::abs(fSPhi + fDPhi - twopi) < kAngTolerance*0.5) )
600         {                                         608         { 
601             pPhi += twopi ; // 0 <= pPhi < 2pi    609             pPhi += twopi ; // 0 <= pPhi < 2pi
602         }                                         610         }
603         if ( (pPhi >= fSPhi + halfAngTolerance << 611         if ( (pPhi >= fSPhi + kAngTolerance*0.5)
604             && (pPhi <= fSPhi + fDPhi - halfAn << 612             && (pPhi <= fSPhi + fDPhi - kAngTolerance*0.5) )
605         {                                         613         {
606           in = kInside ;                          614           in = kInside ;
607         }                                         615         }
608           else if ( (pPhi >= fSPhi - halfAngTo << 616           else if ( (pPhi >= fSPhi - kAngTolerance*0.5)
609                  && (pPhi <= fSPhi + fDPhi + h << 617                  && (pPhi <= fSPhi + fDPhi + kAngTolerance*0.5) )
610         {                                         618         {
611           in = kSurface ;                         619           in = kSurface ;
612         }                                         620         }
613       }                                           621       }
614       else  // fSPhi < 0                          622       else  // fSPhi < 0
615       {                                           623       {
616           if ( (pPhi <= fSPhi + twopi - halfAn << 624           if ( (pPhi <= fSPhi + twopi - kAngTolerance*0.5)
617             && (pPhi >= fSPhi + fDPhi  + halfA << 625             && (pPhi >= fSPhi + fDPhi  + kAngTolerance*0.5) )  {;}
618           else                                    626           else
619           {                                       627           {
620             in = kSurface ;                       628             in = kSurface ;
621           }                                       629           }
622       }                                           630       }
623     }                                             631     }
624   }                                               632   }
625   else   // Try generous boundaries               633   else   // Try generous boundaries
626   {                                               634   {
627     tolRMin = fRmin - fRminTolerance ;         << 635     tolRMin = fRmin - kRadTolerance*0.5 ;
628     tolRMax = fRmax + fRmaxTolerance ;         << 636     tolRMax = fRmax + kRadTolerance*0.5 ;
629                                                   637 
630     if (tolRMin < 0 )  { tolRMin = 0 ; }          638     if (tolRMin < 0 )  { tolRMin = 0 ; }
631                                                   639 
632     if ( (pt2 >= tolRMin*tolRMin) && (pt2 <= t    640     if ( (pt2 >= tolRMin*tolRMin) && (pt2 <= tolRMax*tolRMax) )
633     {                                             641     {
634       if ( (fDPhi == twopi) || (pt2 == 0) ) //    642       if ( (fDPhi == twopi) || (pt2 == 0) ) // Continuous in phi or on z-axis
635       {                                           643       {
636         in = kSurface ;                           644         in = kSurface ;
637       }                                           645       }
638       else // Try outer tolerant phi boundarie    646       else // Try outer tolerant phi boundaries only
639       {                                           647       {
640         pPhi = std::atan2(p.y(),p.x()) ;          648         pPhi = std::atan2(p.y(),p.x()) ;
641                                                   649 
642         if ( pPhi < -halfAngTolerance )  { pPh << 650         if ( pPhi < -kAngTolerance*0.5 )  { pPhi += twopi ; }  // 0<=pPhi<2pi
643         if ( fSPhi >= 0 )                         651         if ( fSPhi >= 0 )
644         {                                         652         {
645           if ( (std::fabs(pPhi) < halfAngToler << 653           if ( (std::abs(pPhi) < kAngTolerance*0.5)
646             && (std::fabs(fSPhi + fDPhi - twop << 654             && (std::abs(fSPhi + fDPhi - twopi) < kAngTolerance*0.5) )
647           {                                       655           { 
648             pPhi += twopi ; // 0 <= pPhi < 2pi    656             pPhi += twopi ; // 0 <= pPhi < 2pi
649           }                                       657           }
650           if ( (pPhi >= fSPhi - halfAngToleran << 658           if ( (pPhi >= fSPhi - kAngTolerance*0.5)
651             && (pPhi <= fSPhi + fDPhi + halfAn << 659             && (pPhi <= fSPhi + fDPhi + kAngTolerance*0.5) )
652           {                                       660           {
653             in = kSurface;                        661             in = kSurface;
654           }                                       662           }
655         }                                         663         }
656         else  // fSPhi < 0                        664         else  // fSPhi < 0
657         {                                         665         {
658           if ( (pPhi <= fSPhi + twopi - halfAn << 666           if ( (pPhi <= fSPhi + twopi - kAngTolerance*0.5)
659             && (pPhi >= fSPhi + fDPhi  + halfA << 667             && (pPhi >= fSPhi + fDPhi  + kAngTolerance*0.5) )  {;}
660           else                                    668           else
661           {                                       669           {
662             in = kSurface ;                       670             in = kSurface ;
663           }                                       671           }
664         }                                         672         }
665       }                                           673       }
666     }                                             674     }
667   }                                               675   }
668   return in ;                                     676   return in ;
669 }                                                 677 }
670                                                   678 
671 //////////////////////////////////////////////    679 /////////////////////////////////////////////////////////////////////////////
672 //                                                680 //
673 // Return unit normal of surface closest to p     681 // Return unit normal of surface closest to p
674 // - note if point on z axis, ignore phi divid    682 // - note if point on z axis, ignore phi divided sides
675 // - unsafe if point close to z axis a rmin=0     683 // - unsafe if point close to z axis a rmin=0 - no explicit checks
676                                                   684 
677 G4ThreeVector G4Torus::SurfaceNormal( const G4    685 G4ThreeVector G4Torus::SurfaceNormal( const G4ThreeVector& p ) const
678 {                                                 686 {
679   G4int noSurfaces = 0;                           687   G4int noSurfaces = 0;  
680   G4double rho, pt, pPhi;                      << 688   G4double rho2, rho, pt2, pt, pPhi;
681   G4double distRMin = kInfinity;                  689   G4double distRMin = kInfinity;
682   G4double distSPhi = kInfinity, distEPhi = kI    690   G4double distSPhi = kInfinity, distEPhi = kInfinity;
683                                                << 691   G4double delta = 0.5*kCarTolerance, dAngle = 0.5*kAngTolerance;
684   // To cope with precision loss               << 
685   //                                           << 
686   const G4double delta = std::max(10.0*kCarTol << 
687                                   1.0e-8*(fRto << 
688   const G4double dAngle = 10.0*kAngTolerance;  << 
689                                                << 
690   G4ThreeVector nR, nPs, nPe;                     692   G4ThreeVector nR, nPs, nPe;
691   G4ThreeVector norm, sumnorm(0.,0.,0.);          693   G4ThreeVector norm, sumnorm(0.,0.,0.);
692                                                   694 
693   rho = std::hypot(p.x(),p.y());               << 695   rho2 = p.x()*p.x() + p.y()*p.y();
694   pt  = std::hypot(p.z(),rho-fRtor);           << 696   rho = std::sqrt(rho2);
                                                   >> 697   pt2 = std::fabs(rho2+p.z()*p.z() +fRtor*fRtor - 2*fRtor*rho);
                                                   >> 698   pt = std::sqrt(pt2) ;
695                                                   699 
696   G4double  distRMax = std::fabs(pt - fRmax);     700   G4double  distRMax = std::fabs(pt - fRmax);
697   if(fRmin != 0.0) distRMin = std::fabs(pt - f << 701   if(fRmin) distRMin = std::fabs(pt - fRmin);
698                                                   702 
699   if( rho > delta && pt != 0.0 )               << 703   if( rho > delta )
700   {                                               704   {
701     G4double redFactor= (rho-fRtor)/rho;       << 705     nR = G4ThreeVector( p.x()*(1-fRtor/rho)/pt,
702     nR = G4ThreeVector( p.x()*redFactor,  // p << 706                         p.y()*(1-fRtor/rho)/pt,
703                         p.y()*redFactor,  // p << 707                         p.z()/pt                 );
704                         p.z()          );      << 
705     nR *= 1.0/pt;                              << 
706   }                                               708   }
707                                                   709 
708   if ( fDPhi < twopi ) // && rho ) // old limi    710   if ( fDPhi < twopi ) // && rho ) // old limitation against (0,0,z)
709   {                                               711   {
710     if ( rho != 0.0 )                          << 712     if ( rho )
711     {                                             713     {
712       pPhi = std::atan2(p.y(),p.x());             714       pPhi = std::atan2(p.y(),p.x());
713                                                   715 
714       if(pPhi < fSPhi-delta)            { pPhi    716       if(pPhi < fSPhi-delta)            { pPhi += twopi; }
715       else if(pPhi > fSPhi+fDPhi+delta) { pPhi    717       else if(pPhi > fSPhi+fDPhi+delta) { pPhi -= twopi; }
716                                                   718 
717       distSPhi = std::fabs( pPhi - fSPhi );       719       distSPhi = std::fabs( pPhi - fSPhi );
718       distEPhi = std::fabs(pPhi-fSPhi-fDPhi);     720       distEPhi = std::fabs(pPhi-fSPhi-fDPhi);
719     }                                             721     }
720     nPs = G4ThreeVector(std::sin(fSPhi),-std::    722     nPs = G4ThreeVector(std::sin(fSPhi),-std::cos(fSPhi),0);
721     nPe = G4ThreeVector(-std::sin(fSPhi+fDPhi)    723     nPe = G4ThreeVector(-std::sin(fSPhi+fDPhi),std::cos(fSPhi+fDPhi),0);
722   }                                               724   } 
723   if( distRMax <= delta )                         725   if( distRMax <= delta )
724   {                                               726   {
725     ++noSurfaces;                              << 727     noSurfaces ++;
726     sumnorm += nR;                                728     sumnorm += nR;
727   }                                               729   }
728   else if( (fRmin != 0.0) && (distRMin <= delt << 730   if( fRmin && distRMin <= delta )
729   {                                               731   {
730     ++noSurfaces;                              << 732     noSurfaces ++;
731     sumnorm -= nR;                                733     sumnorm -= nR;
732   }                                               734   }
733                                                << 735   if( fDPhi < twopi )   
734   //  To be on one of the 'phi' surfaces,      << 
735   //  it must be within the 'tube' - with tole << 
736                                                << 
737   if( (fDPhi < twopi) && (fRmin-delta <= pt) & << 
738   {                                               736   {
739     if (distSPhi <= dAngle)                       737     if (distSPhi <= dAngle)
740     {                                             738     {
741       ++noSurfaces;                            << 739       noSurfaces ++;
742       sumnorm += nPs;                             740       sumnorm += nPs;
743     }                                             741     }
744     if (distEPhi <= dAngle)                       742     if (distEPhi <= dAngle) 
745     {                                             743     {
746       ++noSurfaces;                            << 744       noSurfaces ++;
747       sumnorm += nPe;                             745       sumnorm += nPe;
748     }                                             746     }
749   }                                               747   }
750   if ( noSurfaces == 0 )                          748   if ( noSurfaces == 0 )
751   {                                               749   {
752 #ifdef G4CSGDEBUG                                 750 #ifdef G4CSGDEBUG
753      G4ExceptionDescription ed;                << 751     G4Exception("G4Torus::SurfaceNormal(p)", "Notification", JustWarning, 
754      ed.precision(16);                         << 752                 "Point p is not on surface !?" );
755                                                << 753 #endif 
756      EInside  inIt= Inside( p );               << 
757                                                << 
758      if( inIt != kSurface )                    << 
759      {                                         << 
760         ed << " ERROR>  Surface Normal was cal << 
761            << " with point not on surface." << << 
762      }                                         << 
763      else                                      << 
764      {                                         << 
765         ed << " ERROR>  Surface Normal has not << 
766            << " despite the point being on the << 
767      }                                         << 
768                                                << 
769      if( inIt != kInside)                      << 
770      {                                         << 
771          ed << " Safety (Dist To In)  = " << D << 
772      }                                         << 
773      if( inIt != kOutside)                     << 
774      {                                         << 
775          ed << " Safety (Dist to Out) = " << D << 
776      }                                         << 
777      ed << " Coordinates of point : " << p <<  << 
778      ed << " Parameters  of solid : " << G4end << 
779                                                << 
780      if( inIt == kSurface )                    << 
781      {                                         << 
782         G4Exception("G4Torus::SurfaceNormal(p) << 
783                     JustWarning, ed,           << 
784                     "Failing to find normal, e << 
785      }                                         << 
786      else                                      << 
787      {                                         << 
788         static const char* NameInside[3]= { "I << 
789         ed << "  The point is " << NameInside[ << 
790         G4Exception("G4Torus::SurfaceNormal(p) << 
791                     JustWarning, ed, "Point p  << 
792      }                                         << 
793 #endif                                         << 
794      norm = ApproxSurfaceNormal(p);               754      norm = ApproxSurfaceNormal(p);
795   }                                               755   }
796   else if ( noSurfaces == 1 )  { norm = sumnor    756   else if ( noSurfaces == 1 )  { norm = sumnorm; }
797   else                         { norm = sumnor    757   else                         { norm = sumnorm.unit(); }
798                                                   758 
799   return norm ;                                   759   return norm ;
800 }                                                 760 }
801                                                   761 
802 //////////////////////////////////////////////    762 //////////////////////////////////////////////////////////////////////////////
803 //                                                763 //
804 // Algorithm for SurfaceNormal() following the    764 // Algorithm for SurfaceNormal() following the original specification
805 // for points not on the surface                  765 // for points not on the surface
806                                                   766 
807 G4ThreeVector G4Torus::ApproxSurfaceNormal( co    767 G4ThreeVector G4Torus::ApproxSurfaceNormal( const G4ThreeVector& p ) const
808 {                                                 768 {
809   ENorm side ;                                    769   ENorm side ;
810   G4ThreeVector norm;                             770   G4ThreeVector norm;
811   G4double rho,pt,phi;                         << 771   G4double rho2,rho,pt2,pt,phi;
812   G4double distRMin,distRMax,distSPhi,distEPhi    772   G4double distRMin,distRMax,distSPhi,distEPhi,distMin;
813                                                   773 
814   rho = std::hypot(p.x(),p.y());               << 774   rho2 = p.x()*p.x() + p.y()*p.y();
815   pt  = std::hypot(p.z(),rho-fRtor);           << 775   rho = std::sqrt(rho2) ;
                                                   >> 776   pt2 = std::fabs(rho2+p.z()*p.z() +fRtor*fRtor - 2*fRtor*rho) ;
                                                   >> 777   pt = std::sqrt(pt2) ;
816                                                   778 
817 #ifdef G4CSGDEBUG                              << 
818   G4cout << " G4Torus::ApproximateSurfaceNorma << 
819          << G4endl;                            << 
820 #endif                                         << 
821                                                << 
822   distRMax = std::fabs(pt - fRmax) ;              779   distRMax = std::fabs(pt - fRmax) ;
823                                                   780 
824   if(fRmin != 0.0)  // First minimum radius    << 781   if(fRmin)  // First minimum radius
825   {                                               782   {
826     distRMin = std::fabs(pt - fRmin) ;            783     distRMin = std::fabs(pt - fRmin) ;
827                                                   784 
828     if (distRMin < distRMax)                      785     if (distRMin < distRMax)
829     {                                             786     {
830       distMin = distRMin ;                        787       distMin = distRMin ;
831       side    = kNRMin ;                          788       side    = kNRMin ;
832     }                                             789     }
833     else                                          790     else
834     {                                             791     {
835       distMin = distRMax ;                        792       distMin = distRMax ;
836       side    = kNRMax ;                          793       side    = kNRMax ;
837     }                                             794     }
838   }                                               795   }
839   else                                            796   else
840   {                                               797   {
841     distMin = distRMax ;                          798     distMin = distRMax ;
842     side    = kNRMax ;                            799     side    = kNRMax ;
843   }                                               800   }    
844   if ( (fDPhi < twopi) && (rho != 0.0) )       << 801   if ( (fDPhi < twopi) && rho )
845   {                                               802   {
846     phi = std::atan2(p.y(),p.x()) ; // Protect    803     phi = std::atan2(p.y(),p.x()) ; // Protected against (0,0,z) (above rho!=0)
847                                                   804 
848     if (phi < 0)  { phi += twopi ; }              805     if (phi < 0)  { phi += twopi ; }
849                                                   806 
850     if (fSPhi < 0 )  { distSPhi = std::fabs(ph    807     if (fSPhi < 0 )  { distSPhi = std::fabs(phi-(fSPhi+twopi))*rho ; }
851     else             { distSPhi = std::fabs(ph    808     else             { distSPhi = std::fabs(phi-fSPhi)*rho ; }
852                                                   809 
853     distEPhi = std::fabs(phi - fSPhi - fDPhi)*    810     distEPhi = std::fabs(phi - fSPhi - fDPhi)*rho ;
854                                                   811 
855     if (distSPhi < distEPhi) // Find new minim    812     if (distSPhi < distEPhi) // Find new minimum
856     {                                             813     {
857       if (distSPhi<distMin) side = kNSPhi ;       814       if (distSPhi<distMin) side = kNSPhi ;
858     }                                             815     }
859     else                                          816     else
860     {                                             817     {
861       if (distEPhi < distMin)  { side = kNEPhi    818       if (distEPhi < distMin)  { side = kNEPhi ; }
862     }                                             819     }
863   }                                               820   }  
864   switch (side)                                   821   switch (side)
865   {                                               822   {
866     case kNRMin:      // Inner radius             823     case kNRMin:      // Inner radius
867       norm = G4ThreeVector( -p.x()*(1-fRtor/rh    824       norm = G4ThreeVector( -p.x()*(1-fRtor/rho)/pt,
868                             -p.y()*(1-fRtor/rh    825                             -p.y()*(1-fRtor/rho)/pt,
869                             -p.z()/pt             826                             -p.z()/pt                 ) ;
870       break ;                                     827       break ;
871     case kNRMax:      // Outer radius             828     case kNRMax:      // Outer radius
872       norm = G4ThreeVector( p.x()*(1-fRtor/rho    829       norm = G4ThreeVector( p.x()*(1-fRtor/rho)/pt,
873                             p.y()*(1-fRtor/rho    830                             p.y()*(1-fRtor/rho)/pt,
874                             p.z()/pt              831                             p.z()/pt                  ) ;
875       break;                                      832       break;
876     case kNSPhi:                                  833     case kNSPhi:
877       norm = G4ThreeVector(std::sin(fSPhi),-st    834       norm = G4ThreeVector(std::sin(fSPhi),-std::cos(fSPhi),0) ;
878       break;                                      835       break;
879     case kNEPhi:                                  836     case kNEPhi:
880       norm = G4ThreeVector(-std::sin(fSPhi+fDP    837       norm = G4ThreeVector(-std::sin(fSPhi+fDPhi),std::cos(fSPhi+fDPhi),0) ;
881       break;                                      838       break;
882     default:          // Should never reach th << 839     default:
883       DumpInfo();                                 840       DumpInfo();
884       G4Exception("G4Torus::ApproxSurfaceNorma    841       G4Exception("G4Torus::ApproxSurfaceNormal()",
885                   "GeomSolids1002", JustWarnin << 842                   "Notification", JustWarning,
886                   "Undefined side for valid su    843                   "Undefined side for valid surface normal to solid.");
887       break ;                                     844       break ;
888   }                                               845   } 
889   return norm ;                                   846   return norm ;
890 }                                                 847 }
891                                                   848 
892 //////////////////////////////////////////////    849 ///////////////////////////////////////////////////////////////////////
893 //                                                850 //
894 // Calculate distance to shape from outside, a    851 // Calculate distance to shape from outside, along normalised vector
895 // - return kInfinity if no intersection, or i    852 // - return kInfinity if no intersection, or intersection distance <= tolerance
896 //                                                853 //
897 // - Compute the intersection with the z plane    854 // - Compute the intersection with the z planes 
898 //        - if at valid r, phi, return            855 //        - if at valid r, phi, return
899 //                                                856 //
900 // -> If point is outer outer radius, compute     857 // -> If point is outer outer radius, compute intersection with rmax
901 //        - if at valid phi,z return              858 //        - if at valid phi,z return
902 //                                                859 //
903 // -> Compute intersection with inner radius,     860 // -> Compute intersection with inner radius, taking largest +ve root
904 //        - if valid (phi), save intersction      861 //        - if valid (phi), save intersction
905 //                                                862 //
906 //    -> If phi segmented, compute intersectio    863 //    -> If phi segmented, compute intersections with phi half planes
907 //        - return smallest of valid phi inter    864 //        - return smallest of valid phi intersections and
908 //          inner radius intersection             865 //          inner radius intersection
909 //                                                866 //
910 // NOTE:                                          867 // NOTE:
911 // - Precalculations for phi trigonometry are     868 // - Precalculations for phi trigonometry are Done `just in time'
912 // - `if valid' implies tolerant checking of i    869 // - `if valid' implies tolerant checking of intersection points
913                                                   870 
914 G4double G4Torus::DistanceToIn( const G4ThreeV    871 G4double G4Torus::DistanceToIn( const G4ThreeVector& p,
915                                 const G4ThreeV    872                                 const G4ThreeVector& v ) const
916 {                                                 873 {
917   // Get bounding box of full torus            << 
918   //                                           << 
919   G4double boxDx  = fRtor + fRmax;             << 
920   G4double boxDy  = boxDx;                     << 
921   G4double boxDz  = fRmax;                     << 
922   G4double boxMax = boxDx;                     << 
923   G4double boxMin = boxDz;                     << 
924                                                << 
925   // Check if point is traveling away          << 
926   //                                           << 
927   G4double distX = std::abs(p.x()) - boxDx;    << 
928   G4double distY = std::abs(p.y()) - boxDy;    << 
929   G4double distZ = std::abs(p.z()) - boxDz;    << 
930   if (distX >= -halfCarTolerance && p.x()*v.x( << 
931   if (distY >= -halfCarTolerance && p.y()*v.y( << 
932   if (distZ >= -halfCarTolerance && p.z()*v.z( << 
933                                                << 
934   // Calculate safety distance to bounding box << 
935   // If point is too far, move it closer and c << 
936   //                                           << 
937   G4double Dmax = 32*boxMax;                   << 
938   G4double safe = std::max(std::max(distX,dist << 
939   if (safe > Dmax)                             << 
940   {                                            << 
941     G4double dist = safe - 1.e-8*safe - boxMin << 
942     dist += DistanceToIn(p + dist*v, v);       << 
943     return (dist >= kInfinity) ? kInfinity : d << 
944   }                                            << 
945                                                   874 
946   // Find intersection with torus              << 
947   //                                           << 
948   G4double snxt=kInfinity, sphi=kInfinity; //     875   G4double snxt=kInfinity, sphi=kInfinity; // snxt = default return value
949                                                   876 
950   G4double  sd[4] ;                            << 877   G4double  s[4] ;
951                                                   878 
952   // Precalculated trig for phi intersections     879   // Precalculated trig for phi intersections - used by r,z intersections to
953   //                                              880   //                                            check validity
954                                                   881 
955   G4bool seg;        // true if segmented         882   G4bool seg;        // true if segmented
956   G4double hDPhi;    // half dphi              << 883   G4double hDPhi,hDPhiOT,hDPhiIT,cosHDPhiOT=0.,cosHDPhiIT=0.;
                                                   >> 884                      // half dphi + outer tolerance
957   G4double cPhi,sinCPhi=0.,cosCPhi=0.;  // cen    885   G4double cPhi,sinCPhi=0.,cosCPhi=0.;  // central phi
958                                                   886 
959   G4double tolORMin2;  // `generous' radii squ << 887   G4double tolORMin2,tolIRMin2;  // `generous' radii squared
960   G4double tolORMax2;                          << 888   G4double tolORMax2,tolIRMax2 ;
                                                   >> 889 
                                                   >> 890   G4double Dist,xi,yi,zi,rhoi2,it2; // Intersection point variables
961                                                   891 
962   G4double Dist,xi,yi,zi,rhoi,it2; // Intersec << 
963                                                   892 
964   G4double Comp;                                  893   G4double Comp;
965   G4double cosSPhi,sinSPhi;       // Trig for     894   G4double cosSPhi,sinSPhi;       // Trig for phi start intersect
966   G4double ePhi,cosEPhi,sinEPhi;  // for phi e    895   G4double ePhi,cosEPhi,sinEPhi;  // for phi end intersect
967                                                   896 
968   // Set phi divided flag and precalcs            897   // Set phi divided flag and precalcs
969   //                                              898   //
970   if ( fDPhi < twopi )                            899   if ( fDPhi < twopi )
971   {                                               900   {
972     seg        = true ;                           901     seg        = true ;
973     hDPhi      = 0.5*fDPhi ;    // half delta     902     hDPhi      = 0.5*fDPhi ;    // half delta phi
974     cPhi       = fSPhi + hDPhi ;                  903     cPhi       = fSPhi + hDPhi ;
                                                   >> 904     hDPhiOT    = hDPhi+0.5*kAngTolerance ;  // outers tol' half delta phi 
                                                   >> 905     hDPhiIT    = hDPhi - 0.5*kAngTolerance ;
975     sinCPhi    = std::sin(cPhi) ;                 906     sinCPhi    = std::sin(cPhi) ;
976     cosCPhi    = std::cos(cPhi) ;                 907     cosCPhi    = std::cos(cPhi) ;
                                                   >> 908     cosHDPhiOT = std::cos(hDPhiOT) ;
                                                   >> 909     cosHDPhiIT = std::cos(hDPhiIT) ;
977   }                                               910   }
978   else                                            911   else
979   {                                               912   {
980     seg = false ;                                 913     seg = false ;
981   }                                               914   }
982                                                   915 
983   if (fRmin > fRminTolerance) // Calculate tol << 916   if (fRmin > kRadTolerance) // Calculate tolerant rmin and rmax
984   {                                               917   {
985     tolORMin2 = (fRmin - fRminTolerance)*(fRmi << 918     tolORMin2 = (fRmin - 0.5*kRadTolerance)*(fRmin - 0.5*kRadTolerance) ;
                                                   >> 919     tolIRMin2 = (fRmin + 0.5*kRadTolerance)*(fRmin + 0.5*kRadTolerance) ;
986   }                                               920   }
987   else                                            921   else
988   {                                               922   {
989     tolORMin2 = 0 ;                               923     tolORMin2 = 0 ;
                                                   >> 924     tolIRMin2 = 0 ;
990   }                                               925   }
991   tolORMax2 = (fRmax + fRmaxTolerance)*(fRmax  << 926   tolORMax2 = (fRmax + 0.5*kRadTolerance)*(fRmax + 0.5*kRadTolerance) ;
                                                   >> 927   tolIRMax2 = (fRmax - kRadTolerance*0.5)*(fRmax - kRadTolerance*0.5) ;
992                                                   928 
993   // Intersection with Rmax (possible return)     929   // Intersection with Rmax (possible return) and Rmin (must also check phi)
994                                                   930 
995   snxt = SolveNumericJT(p,v,fRmax,true);       << 931   G4double Rtor2 = fRtor*fRtor ;
996                                                   932 
997   if (fRmin != 0.0)  // Possible Rmin intersec << 933   snxt = SolveNumericJT(p,v,fRmax,true);
                                                   >> 934   if (fRmin)  // Possible Rmin intersection
998   {                                               935   {
999     sd[0] = SolveNumericJT(p,v,fRmin,true);    << 936     s[0] = SolveNumericJT(p,v,fRmin,true);
1000     if ( sd[0] < snxt )  { snxt = sd[0] ; }   << 937     if ( s[0] < snxt )  { snxt = s[0] ; }
1001   }                                              938   }
1002                                                  939 
1003   //                                             940   //
1004   // Phi segment intersection                    941   // Phi segment intersection
1005   //                                             942   //
1006   // o Tolerant of points inside phi planes b    943   // o Tolerant of points inside phi planes by up to kCarTolerance*0.5
1007   //                                             944   //
1008   // o NOTE: Large duplication of code betwee    945   // o NOTE: Large duplication of code between sphi & ephi checks
1009   //         -> only diffs: sphi -> ephi, Com    946   //         -> only diffs: sphi -> ephi, Comp -> -Comp and half-plane
1010   //            intersection check <=0 -> >=0    947   //            intersection check <=0 -> >=0
1011   //         -> use some form of loop Constru    948   //         -> use some form of loop Construct ?
1012                                                  949 
1013   if (seg)                                       950   if (seg)
1014   {                                              951   {
1015     sinSPhi = std::sin(fSPhi) ; // First phi  << 952     sinSPhi = std::sin(fSPhi) ; // First phi surface (`S'tarting phi)
1016     cosSPhi = std::cos(fSPhi) ;                  953     cosSPhi = std::cos(fSPhi) ;
1017     Comp    = v.x()*sinSPhi - v.y()*cosSPhi ;    954     Comp    = v.x()*sinSPhi - v.y()*cosSPhi ;  // Component in outwards
1018                                                  955                                                // normal direction
1019     if (Comp < 0 )                               956     if (Comp < 0 )
1020     {                                            957     {
1021       Dist = (p.y()*cosSPhi - p.x()*sinSPhi)     958       Dist = (p.y()*cosSPhi - p.x()*sinSPhi) ;
1022                                                  959 
1023       if (Dist < halfCarTolerance)            << 960       if (Dist < kCarTolerance*0.5)
1024       {                                          961       {
1025         sphi = Dist/Comp ;                       962         sphi = Dist/Comp ;
1026         if (sphi < snxt)                         963         if (sphi < snxt)
1027         {                                        964         {
1028           if ( sphi < 0 )  { sphi = 0 ; }        965           if ( sphi < 0 )  { sphi = 0 ; }
1029                                                  966 
1030           xi    = p.x() + sphi*v.x() ;           967           xi    = p.x() + sphi*v.x() ;
1031           yi    = p.y() + sphi*v.y() ;           968           yi    = p.y() + sphi*v.y() ;
1032           zi    = p.z() + sphi*v.z() ;           969           zi    = p.z() + sphi*v.z() ;
1033           rhoi = std::hypot(xi,yi);           << 970           rhoi2 = xi*xi + yi*yi ;
1034           it2 = zi*zi + (rhoi-fRtor)*(rhoi-fR << 971           it2   = std::fabs(rhoi2 + zi*zi + Rtor2 - 2*fRtor*std::sqrt(rhoi2)) ;
1035                                                  972 
1036           if ( it2 >= tolORMin2 && it2 <= tol    973           if ( it2 >= tolORMin2 && it2 <= tolORMax2 )
1037           {                                      974           {
1038             // r intersection is good - check    975             // r intersection is good - check intersecting
1039             // with correct half-plane           976             // with correct half-plane
1040             //                                   977             //
1041             if ((yi*cosCPhi-xi*sinCPhi)<=0)      978             if ((yi*cosCPhi-xi*sinCPhi)<=0)  { snxt=sphi; }
1042           }                                   << 979           }    
1043         }                                        980         }
1044       }                                          981       }
1045     }                                            982     }
1046     ePhi=fSPhi+fDPhi;    // Second phi surfac << 983     ePhi=fSPhi+fDPhi;    // Second phi surface (`E'nding phi)
1047     sinEPhi=std::sin(ePhi);                      984     sinEPhi=std::sin(ePhi);
1048     cosEPhi=std::cos(ePhi);                      985     cosEPhi=std::cos(ePhi);
1049     Comp=-(v.x()*sinEPhi-v.y()*cosEPhi);         986     Comp=-(v.x()*sinEPhi-v.y()*cosEPhi);
1050                                                  987         
1051     if ( Comp < 0 )   // Component in outward    988     if ( Comp < 0 )   // Component in outwards normal dirn
1052     {                                            989     {
1053       Dist = -(p.y()*cosEPhi - p.x()*sinEPhi)    990       Dist = -(p.y()*cosEPhi - p.x()*sinEPhi) ;
1054                                                  991 
1055       if (Dist < halfCarTolerance )           << 992       if (Dist < kCarTolerance*0.5 )
1056       {                                          993       {
1057         sphi = Dist/Comp ;                       994         sphi = Dist/Comp ;
1058                                               << 
1059         if (sphi < snxt )                        995         if (sphi < snxt )
1060         {                                        996         {
1061           if (sphi < 0 )  { sphi = 0 ; }         997           if (sphi < 0 )  { sphi = 0 ; }
1062                                                  998        
1063           xi    = p.x() + sphi*v.x() ;           999           xi    = p.x() + sphi*v.x() ;
1064           yi    = p.y() + sphi*v.y() ;           1000           yi    = p.y() + sphi*v.y() ;
1065           zi    = p.z() + sphi*v.z() ;           1001           zi    = p.z() + sphi*v.z() ;
1066           rhoi = std::hypot(xi,yi);           << 1002           rhoi2 = xi*xi + yi*yi ;
1067           it2 = zi*zi + (rhoi-fRtor)*(rhoi-fR << 1003           it2   = std::fabs(rhoi2 + zi*zi + Rtor2 - 2*fRtor*std::sqrt(rhoi2)) ;
1068                                                  1004 
1069           if (it2 >= tolORMin2 && it2 <= tolO    1005           if (it2 >= tolORMin2 && it2 <= tolORMax2)
1070           {                                      1006           {
1071             // z and r intersections good - c    1007             // z and r intersections good - check intersecting
1072             // with correct half-plane           1008             // with correct half-plane
1073             //                                   1009             //
1074             if ((yi*cosCPhi-xi*sinCPhi)>=0)      1010             if ((yi*cosCPhi-xi*sinCPhi)>=0)  { snxt=sphi; }
1075           }                                      1011           }    
1076         }                                        1012         }
1077       }                                          1013       }
1078     }                                            1014     }
1079   }                                              1015   }
1080   if(snxt < halfCarTolerance)  { snxt = 0.0 ; << 1016   if(snxt < 0.5*kCarTolerance)  { snxt = 0.0 ; }
1081                                                  1017 
1082   return snxt ;                                  1018   return snxt ;
1083 }                                                1019 }
1084                                                  1020 
1085 /////////////////////////////////////////////    1021 /////////////////////////////////////////////////////////////////////////////
1086 //                                               1022 //
1087 // Calculate distance (<= actual) to closest     1023 // Calculate distance (<= actual) to closest surface of shape from outside
1088 // - Calculate distance to z, radial planes      1024 // - Calculate distance to z, radial planes
1089 // - Only to phi planes if outside phi extent    1025 // - Only to phi planes if outside phi extent
1090 // - Return 0 if point inside                    1026 // - Return 0 if point inside
1091                                                  1027 
1092 G4double G4Torus::DistanceToIn( const G4Three    1028 G4double G4Torus::DistanceToIn( const G4ThreeVector& p ) const
1093 {                                                1029 {
1094   G4double safe=0.0, safe1, safe2 ;              1030   G4double safe=0.0, safe1, safe2 ;
1095   G4double phiC, cosPhiC, sinPhiC, safePhi, e    1031   G4double phiC, cosPhiC, sinPhiC, safePhi, ePhi, cosPsi ;
1096   G4double rho, pt ;                          << 1032   G4double rho2, rho, pt2, pt ;
1097                                               << 1033     
1098   rho = std::hypot(p.x(),p.y());              << 1034   rho2 = p.x()*p.x() + p.y()*p.y() ;
1099   pt  = std::hypot(p.z(),rho-fRtor);          << 1035   rho  = std::sqrt(rho2) ;
                                                   >> 1036   pt2  = std::fabs(rho2 + p.z()*p.z() + fRtor*fRtor - 2*fRtor*rho) ;
                                                   >> 1037   pt   = std::sqrt(pt2) ;
                                                   >> 1038 
1100   safe1 = fRmin - pt ;                           1039   safe1 = fRmin - pt ;
1101   safe2 = pt - fRmax ;                           1040   safe2 = pt - fRmax ;
1102                                                  1041 
1103   if (safe1 > safe2)  { safe = safe1; }          1042   if (safe1 > safe2)  { safe = safe1; }
1104   else                { safe = safe2; }          1043   else                { safe = safe2; }
1105                                                  1044 
1106   if ( fDPhi < twopi && (rho != 0.0) )        << 1045   if ( fDPhi < twopi && rho )
1107   {                                              1046   {
1108     phiC    = fSPhi + fDPhi*0.5 ;                1047     phiC    = fSPhi + fDPhi*0.5 ;
1109     cosPhiC = std::cos(phiC) ;                   1048     cosPhiC = std::cos(phiC) ;
1110     sinPhiC = std::sin(phiC) ;                   1049     sinPhiC = std::sin(phiC) ;
1111     cosPsi  = (p.x()*cosPhiC + p.y()*sinPhiC)    1050     cosPsi  = (p.x()*cosPhiC + p.y()*sinPhiC)/rho ;
1112                                                  1051 
1113     if (cosPsi < std::cos(fDPhi*0.5) ) // Psi    1052     if (cosPsi < std::cos(fDPhi*0.5) ) // Psi=angle from central phi to point
1114     {                                  // Poi    1053     {                                  // Point lies outside phi range
1115       if ((p.y()*cosPhiC - p.x()*sinPhiC) <=     1054       if ((p.y()*cosPhiC - p.x()*sinPhiC) <= 0 )
1116       {                                          1055       {
1117         safePhi = std::fabs(p.x()*std::sin(fS    1056         safePhi = std::fabs(p.x()*std::sin(fSPhi) - p.y()*std::cos(fSPhi)) ;
1118       }                                          1057       }
1119       else                                       1058       else
1120       {                                          1059       {
1121         ePhi    = fSPhi + fDPhi ;                1060         ePhi    = fSPhi + fDPhi ;
1122         safePhi = std::fabs(p.x()*std::sin(eP    1061         safePhi = std::fabs(p.x()*std::sin(ePhi) - p.y()*std::cos(ePhi)) ;
1123       }                                          1062       }
1124       if (safePhi > safe)  { safe = safePhi ;    1063       if (safePhi > safe)  { safe = safePhi ; }
1125     }                                            1064     }
1126   }                                              1065   }
1127   if (safe < 0 )  { safe = 0 ; }                 1066   if (safe < 0 )  { safe = 0 ; }
1128   return safe;                                   1067   return safe;
1129 }                                                1068 }
1130                                                  1069 
1131 /////////////////////////////////////////////    1070 ///////////////////////////////////////////////////////////////////////////
1132 //                                               1071 //
1133 // Calculate distance to surface of shape fro    1072 // Calculate distance to surface of shape from `inside', allowing for tolerance
1134 // - Only Calc rmax intersection if no valid     1073 // - Only Calc rmax intersection if no valid rmin intersection
1135 //                                               1074 //
1136                                                  1075 
1137 G4double G4Torus::DistanceToOut( const G4Thre    1076 G4double G4Torus::DistanceToOut( const G4ThreeVector& p,
1138                                  const G4Thre    1077                                  const G4ThreeVector& v,
1139                                  const G4bool    1078                                  const G4bool calcNorm,
1140                                        G4bool << 1079                                        G4bool *validNorm,
1141                                        G4Thre << 1080                                        G4ThreeVector  *n  ) const
1142 {                                                1081 {
1143   ESide    side = kNull, sidephi = kNull ;       1082   ESide    side = kNull, sidephi = kNull ;
1144   G4double snxt = kInfinity, sphi, sd[4] ;    << 1083   G4double snxt = kInfinity, sphi, s[4] ;
1145                                                  1084 
1146   // Vars for phi intersection                   1085   // Vars for phi intersection
1147   //                                             1086   //
1148   G4double sinSPhi, cosSPhi, ePhi, sinEPhi, c    1087   G4double sinSPhi, cosSPhi, ePhi, sinEPhi, cosEPhi;
1149   G4double cPhi, sinCPhi, cosCPhi ;              1088   G4double cPhi, sinCPhi, cosCPhi ;
1150   G4double pDistS, compS, pDistE, compE, sphi    1089   G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, zi, vphi ;
1151                                                  1090 
1152   // Radial Intersections Defenitions & Gener    1091   // Radial Intersections Defenitions & General Precals
1153                                                  1092 
1154   //////////////////////// new calculation //    1093   //////////////////////// new calculation //////////////////////
1155                                                  1094 
1156 #if 1                                            1095 #if 1
1157                                                  1096 
1158   // This is the version with the calculation    1097   // This is the version with the calculation of CalcNorm = true 
1159   // To be done: Check the precision of this     1098   // To be done: Check the precision of this calculation.
1160   // If you want return always validNorm = fa    1099   // If you want return always validNorm = false, then take the version below
1161                                                  1100   
1162                                               << 1101   G4double Rtor2 = fRtor*fRtor ;
1163   G4double rho = std::hypot(p.x(),p.y());     << 1102   G4double rho2  = p.x()*p.x()+p.y()*p.y();
1164   G4double pt = hypot(p.z(),rho-fRtor);       << 1103   G4double rho   = std::sqrt(rho2) ;
                                                   >> 1104 
                                                   >> 1105 
                                                   >> 1106   G4double pt2   = std::fabs(rho2 + p.z()*p.z() + Rtor2 - 2*fRtor*rho) ;
                                                   >> 1107   G4double pt    = std::sqrt(pt2) ;
1165                                                  1108 
1166   G4double pDotV = p.x()*v.x() + p.y()*v.y()     1109   G4double pDotV = p.x()*v.x() + p.y()*v.y() + p.z()*v.z() ;
1167                                                  1110 
1168   G4double tolRMax = fRmax - fRmaxTolerance ; << 1111   G4double tolRMax = fRmax - kRadTolerance*0.5 ;
1169                                                  1112    
1170   G4double vDotNmax   = pDotV - fRtor*(v.x()*    1113   G4double vDotNmax   = pDotV - fRtor*(v.x()*p.x() + v.y()*p.y())/rho ;
1171   G4double pDotxyNmax = (1 - fRtor/rho) ;        1114   G4double pDotxyNmax = (1 - fRtor/rho) ;
1172                                                  1115 
1173   if( (pt*pt > tolRMax*tolRMax) && (vDotNmax  << 1116   if( (pt2 > tolRMax*tolRMax) && (vDotNmax >= 0) )
1174   {                                              1117   {
1175     // On tolerant boundary & heading outward    1118     // On tolerant boundary & heading outwards (or perpendicular to) outer
1176     // radial surface -> leaving immediately     1119     // radial surface -> leaving immediately with *n for really convex part
1177     // only                                      1120     // only
1178                                                  1121       
1179     if ( calcNorm && (pDotxyNmax >= -2.*fRmax << 1122     if ( calcNorm && (pDotxyNmax >= -kRadTolerance) ) 
1180     {                                            1123     {
1181       *n = G4ThreeVector( p.x()*(1 - fRtor/rh    1124       *n = G4ThreeVector( p.x()*(1 - fRtor/rho)/pt,
1182                           p.y()*(1 - fRtor/rh    1125                           p.y()*(1 - fRtor/rho)/pt,
1183                           p.z()/pt               1126                           p.z()/pt                  ) ;
1184       *validNorm = true ;                        1127       *validNorm = true ;
1185     }                                            1128     }
1186                                               << 
1187     return snxt = 0 ; // Leaving by Rmax imme    1129     return snxt = 0 ; // Leaving by Rmax immediately
1188   }                                              1130   }
1189                                                  1131   
1190   snxt = SolveNumericJT(p,v,fRmax,false);        1132   snxt = SolveNumericJT(p,v,fRmax,false);  
1191   side = kRMax ;                                 1133   side = kRMax ;
1192                                                  1134 
1193   // rmin                                        1135   // rmin
1194                                                  1136 
1195   if ( fRmin != 0.0 )                         << 1137   if ( fRmin )
1196   {                                              1138   {
1197     G4double tolRMin = fRmin + fRminTolerance << 1139     G4double tolRMin = fRmin + kRadTolerance*0.5 ;
1198                                                  1140 
1199     if ( (pt*pt < tolRMin*tolRMin) && (vDotNm << 1141     if ( (pt2 < tolRMin*tolRMin) && (vDotNmax < 0) )
1200     {                                            1142     {
1201       if (calcNorm)  { *validNorm = false ; }    1143       if (calcNorm)  { *validNorm = false ; } // Concave surface of the torus
1202       return  snxt = 0 ;                         1144       return  snxt = 0 ;                      // Leaving by Rmin immediately
1203     }                                            1145     }
1204                                                  1146     
1205     sd[0] = SolveNumericJT(p,v,fRmin,false);  << 1147     s[0] = SolveNumericJT(p,v,fRmin,false);
1206     if ( sd[0] < snxt )                       << 1148     if ( s[0] < snxt )
1207     {                                            1149     {
1208       snxt = sd[0] ;                          << 1150       snxt = s[0] ;
1209       side = kRMin ;                             1151       side = kRMin ;
1210     }                                            1152     }
1211   }                                              1153   }
1212                                                  1154 
1213 #else                                            1155 #else
1214                                                  1156 
1215   // this is the "conservative" version which    1157   // this is the "conservative" version which return always validnorm = false
1216   // NOTE: using this version the unit test t    1158   // NOTE: using this version the unit test testG4Torus will break
1217                                                  1159 
1218   snxt = SolveNumericJT(p,v,fRmax,false);        1160   snxt = SolveNumericJT(p,v,fRmax,false);  
1219   side = kRMax ;                                 1161   side = kRMax ;
1220                                                  1162 
1221   if ( fRmin )                                   1163   if ( fRmin )
1222   {                                              1164   {
1223     sd[0] = SolveNumericJT(p,v,fRmin,false);  << 1165     s[0] = SolveNumericJT(p,v,fRmin,false);
1224     if ( sd[0] < snxt )                       << 1166     if ( s[0] < snxt )
1225     {                                            1167     {
1226       snxt = sd[0] ;                          << 1168       snxt = s[0] ;
1227       side = kRMin ;                             1169       side = kRMin ;
1228     }                                            1170     }
1229   }                                              1171   }
1230                                                  1172 
1231   if ( calcNorm && (snxt == 0.0) )               1173   if ( calcNorm && (snxt == 0.0) )
1232   {                                              1174   {
1233     *validNorm = false ;    // Leaving solid,    1175     *validNorm = false ;    // Leaving solid, but possible re-intersection
1234     return snxt  ;                               1176     return snxt  ;
1235   }                                              1177   }
1236                                                  1178 
1237 #endif                                           1179 #endif
1238                                               << 1180 
1239   if (fDPhi < twopi)  // Phi Intersections       1181   if (fDPhi < twopi)  // Phi Intersections
1240   {                                              1182   {
1241     sinSPhi = std::sin(fSPhi) ;                  1183     sinSPhi = std::sin(fSPhi) ;
1242     cosSPhi = std::cos(fSPhi) ;                  1184     cosSPhi = std::cos(fSPhi) ;
1243     ePhi    = fSPhi + fDPhi ;                    1185     ePhi    = fSPhi + fDPhi ;
1244     sinEPhi = std::sin(ePhi) ;                   1186     sinEPhi = std::sin(ePhi) ;
1245     cosEPhi = std::cos(ePhi) ;                   1187     cosEPhi = std::cos(ePhi) ;
1246     cPhi    = fSPhi + fDPhi*0.5 ;                1188     cPhi    = fSPhi + fDPhi*0.5 ;
1247     sinCPhi = std::sin(cPhi) ;                   1189     sinCPhi = std::sin(cPhi) ;
1248     cosCPhi = std::cos(cPhi) ;                   1190     cosCPhi = std::cos(cPhi) ;
1249                                               << 
1250     // angle calculation with correction      << 
1251     // of difference in domain of atan2 and S << 
1252     //                                        << 
1253     vphi = std::atan2(v.y(),v.x()) ;          << 
1254                                               << 
1255     if ( vphi < fSPhi - halfAngTolerance  )   << 
1256     else if ( vphi > ePhi + halfAngTolerance  << 
1257                                                  1191 
1258     if ( (p.x() != 0.0) || (p.y() != 0.0) ) / << 1192     if ( p.x() || p.y() ) // Check if on z axis (rho not needed later)
1259     {                                            1193     {
1260       pDistS = p.x()*sinSPhi - p.y()*cosSPhi     1194       pDistS = p.x()*sinSPhi - p.y()*cosSPhi ; // pDist -ve when inside
1261       pDistE = -p.x()*sinEPhi + p.y()*cosEPhi    1195       pDistE = -p.x()*sinEPhi + p.y()*cosEPhi ;
1262                                                  1196 
1263       // Comp -ve when in direction of outwar    1197       // Comp -ve when in direction of outwards normal
1264       //                                         1198       //
1265       compS   = -sinSPhi*v.x() + cosSPhi*v.y(    1199       compS   = -sinSPhi*v.x() + cosSPhi*v.y() ;
1266       compE   = sinEPhi*v.x() - cosEPhi*v.y()    1200       compE   = sinEPhi*v.x() - cosEPhi*v.y() ;
1267       sidephi = kNull ;                          1201       sidephi = kNull ;
1268                                               << 1202 
1269       if( ( (fDPhi <= pi) && ( (pDistS <= hal << 1203       if ( (pDistS <= 0) && (pDistE <= 0) )
1270                             && (pDistE <= hal << 
1271        || ( (fDPhi >  pi) && ((pDistS <=  hal << 
1272                             || (pDistE <=  ha << 
1273       {                                          1204       {
1274         // Inside both phi *full* planes         1205         // Inside both phi *full* planes
1275                                                  1206 
1276         if ( compS < 0 )                      << 1207         if (compS<0)
                                                   >> 1208         {
                                                   >> 1209           sphi=pDistS/compS;
                                                   >> 1210           xi=p.x()+sphi*v.x();
                                                   >> 1211           yi=p.y()+sphi*v.y();
                                                   >> 1212 
                                                   >> 1213           // Check intersecting with correct half-plane
                                                   >> 1214           // (if not -> no intersect)
                                                   >> 1215           //
                                                   >> 1216           if ((yi*cosCPhi-xi*sinCPhi)>=0)
                                                   >> 1217           {
                                                   >> 1218             sphi=kInfinity;
                                                   >> 1219           }
                                                   >> 1220           else
                                                   >> 1221           {
                                                   >> 1222             sidephi=kSPhi;
                                                   >> 1223             if (pDistS>-kCarTolerance*0.5)  { sphi=0; }  // Leave by sphi
                                                   >> 1224                                                          // immediately
                                                   >> 1225           }
                                                   >> 1226         }
                                                   >> 1227         else
                                                   >> 1228         {
                                                   >> 1229           sphi=kInfinity;
                                                   >> 1230         }
                                                   >> 1231 
                                                   >> 1232         if (compE<0)
1277         {                                        1233         {
1278           sphi = pDistS/compS ;               << 1234           sphi2=pDistE/compE;
1279                                               << 1235 
1280           if (sphi >= -halfCarTolerance)      << 1236           // Only check further if < starting phi intersection
                                                   >> 1237           //
                                                   >> 1238           if (sphi2<sphi)
1281           {                                      1239           {
1282             xi = p.x() + sphi*v.x() ;         << 1240             xi=p.x()+sphi2*v.x();
1283             yi = p.y() + sphi*v.y() ;         << 1241             yi=p.y()+sphi2*v.y();
1284                                               << 1242 
1285             // Check intersecting with correc    1243             // Check intersecting with correct half-plane
1286             // (if not -> no intersect)       << 1244             // 
1287             //                                << 1245             if ((yi*cosCPhi-xi*sinCPhi)>=0)
1288             if ( (std::fabs(xi)<=kCarToleranc << 
1289               && (std::fabs(yi)<=kCarToleranc << 
1290             {                                    1246             {
1291               sidephi = kSPhi;                << 1247               // Leaving via ending phi
1292               if ( ((fSPhi-halfAngTolerance)< << 1248               //
1293                 && ((ePhi+halfAngTolerance)>= << 1249               sidephi=kEPhi;
                                                   >> 1250               if (pDistE<=-kCarTolerance*0.5)
1294               {                                  1251               {
1295                 sphi = kInfinity;             << 1252                 sphi=sphi2;
                                                   >> 1253               }
                                                   >> 1254               else 
                                                   >> 1255               {
                                                   >> 1256                 sphi=0;
1296               }                                  1257               }
1297             }                                    1258             }
1298             else if ( yi*cosCPhi-xi*sinCPhi > << 1259           }
                                                   >> 1260         }
                                                   >> 1261       }
                                                   >> 1262       else if ( (pDistS>=0) && (pDistE>=0) )
                                                   >> 1263       {
                                                   >> 1264         // Outside both *full* phi planes
                                                   >> 1265 
                                                   >> 1266         if (pDistS <= pDistE)
                                                   >> 1267         {
                                                   >> 1268           sidephi = kSPhi ;
                                                   >> 1269         }
                                                   >> 1270         else
                                                   >> 1271         {
                                                   >> 1272           sidephi = kEPhi ;
                                                   >> 1273         }
                                                   >> 1274         if (fDPhi>pi)
                                                   >> 1275         {
                                                   >> 1276           if ( (compS<0) && (compE<0) )  { sphi=0; }
                                                   >> 1277           else                           { sphi=kInfinity; }
                                                   >> 1278         }
                                                   >> 1279         else
                                                   >> 1280         {
                                                   >> 1281           // if towards both >=0 then once inside (after error)
                                                   >> 1282           // will remain inside
                                                   >> 1283           //
                                                   >> 1284           if ( (compS>=0) && (compE>=0) )
                                                   >> 1285           {
                                                   >> 1286             sphi=kInfinity;
                                                   >> 1287           }
                                                   >> 1288           else
                                                   >> 1289           {
                                                   >> 1290             sphi=0;
                                                   >> 1291           }
                                                   >> 1292         }
                                                   >> 1293       }
                                                   >> 1294       else if ( (pDistS>0) && (pDistE<0) )
                                                   >> 1295       {
                                                   >> 1296         // Outside full starting plane, inside full ending plane
                                                   >> 1297 
                                                   >> 1298         if (fDPhi>pi)
                                                   >> 1299         {
                                                   >> 1300           if (compE<0)
                                                   >> 1301           {
                                                   >> 1302             sphi=pDistE/compE;
                                                   >> 1303             xi=p.x()+sphi*v.x();
                                                   >> 1304             yi=p.y()+sphi*v.y();
                                                   >> 1305 
                                                   >> 1306             // Check intersection in correct half-plane
                                                   >> 1307             // (if not -> not leaving phi extent)
                                                   >> 1308             //
                                                   >> 1309             if ((yi*cosCPhi-xi*sinCPhi)<=0)
1299             {                                    1310             {
1300               sphi = kInfinity ;              << 1311               sphi=kInfinity;
1301             }                                    1312             }
1302             else                                 1313             else
1303             {                                    1314             {
1304               sidephi = kSPhi ;               << 1315               // Leaving via Ending phi
1305             }                                 << 1316               //
                                                   >> 1317               sidephi = kEPhi ;
                                                   >> 1318               if (pDistE>-kCarTolerance*0.5)  { sphi=0; }
                                                   >> 1319             }
1306           }                                      1320           }
1307           else                                   1321           else
1308           {                                      1322           {
1309             sphi = kInfinity ;                << 1323             sphi=kInfinity;
1310           }                                      1324           }
1311         }                                        1325         }
1312         else                                     1326         else
1313         {                                        1327         {
1314           sphi = kInfinity ;                  << 1328           if (compS>=0)
1315         }                                     << 
1316                                               << 
1317         if ( compE < 0 )                      << 
1318         {                                     << 
1319           sphi2 = pDistE/compE ;              << 
1320                                               << 
1321           // Only check further if < starting << 
1322           //                                  << 
1323           if ( (sphi2 > -kCarTolerance) && (s << 
1324           {                                      1329           {
1325             xi = p.x() + sphi2*v.x() ;        << 1330             if (compE<0)
1326             yi = p.y() + sphi2*v.y() ;        << 
1327                                               << 
1328             if ( (std::fabs(xi)<=kCarToleranc << 
1329               && (std::fabs(yi)<=kCarToleranc << 
1330             {                                    1331             {
1331               // Leaving via ending phi       << 1332               sphi=pDistE/compE;
                                                   >> 1333               xi=p.x()+sphi*v.x();
                                                   >> 1334               yi=p.y()+sphi*v.y();
                                                   >> 1335 
                                                   >> 1336               // Check intersection in correct half-plane
                                                   >> 1337               // (if not -> remain in extent)
1332               //                                 1338               //
1333               if( (fSPhi-halfAngTolerance > v << 1339               if ((yi*cosCPhi-xi*sinCPhi)<=0)
1334                   || (ePhi+halfAngTolerance < << 
1335               {                                  1340               {
1336                 sidephi = kEPhi ;             << 1341                 sphi=kInfinity;
1337                 sphi = sphi2;                 << 
1338               }                                  1342               }
1339             }                                 << 1343               else
1340             else    // Check intersecting wit << 
1341             {                                 << 
1342               if ( (yi*cosCPhi-xi*sinCPhi) >= << 
1343               {                                  1344               {
1344                 // Leaving via ending phi     << 1345                 // otherwise leaving via Ending phi
1345                 //                               1346                 //
1346                 sidephi = kEPhi ;             << 1347                 sidephi=kEPhi;
1347                 sphi = sphi2;                 << 
1348                                               << 
1349               }                                  1348               }
1350             }                                    1349             }
                                                   >> 1350             else  { sphi=kInfinity; }
                                                   >> 1351           }
                                                   >> 1352           else
                                                   >> 1353           {
                                                   >> 1354             // leaving immediately by starting phi
                                                   >> 1355             //
                                                   >> 1356             sidephi=kSPhi;
                                                   >> 1357             sphi=0;
1351           }                                      1358           }
1352         }                                        1359         }
1353       }                                          1360       }
1354       else                                       1361       else
1355       {                                          1362       {
1356         sphi = kInfinity ;                    << 1363         // Must be pDistS<0&&pDistE>0
                                                   >> 1364         // Inside full starting plane, outside full ending plane
                                                   >> 1365 
                                                   >> 1366         if (fDPhi>pi)
                                                   >> 1367         {
                                                   >> 1368           if (compS<0)
                                                   >> 1369           {
                                                   >> 1370             sphi=pDistS/compS;
                                                   >> 1371             xi=p.x()+sphi*v.x();
                                                   >> 1372             yi=p.y()+sphi*v.y();
                                                   >> 1373 
                                                   >> 1374             // Check intersection in correct half-plane
                                                   >> 1375             // (if not -> not leaving phi extent)
                                                   >> 1376             //
                                                   >> 1377             if ((yi*cosCPhi-xi*sinCPhi)>=0)
                                                   >> 1378             {
                                                   >> 1379               sphi=kInfinity;
                                                   >> 1380             }
                                                   >> 1381             else
                                                   >> 1382             {
                                                   >> 1383               // Leaving via Starting phi
                                                   >> 1384               //
                                                   >> 1385               sidephi = kSPhi ;   
                                                   >> 1386               if (pDistS>-kCarTolerance*0.5)  { sphi=0; }
                                                   >> 1387             }
                                                   >> 1388           }
                                                   >> 1389           else
                                                   >> 1390           {
                                                   >> 1391             sphi=kInfinity;
                                                   >> 1392           }
                                                   >> 1393         }
                                                   >> 1394         else
                                                   >> 1395         {
                                                   >> 1396           if (compE>=0)
                                                   >> 1397           {
                                                   >> 1398             if (compS<0)
                                                   >> 1399             {
                                                   >> 1400               sphi=pDistS/compS;
                                                   >> 1401               xi=p.x()+sphi*v.x();
                                                   >> 1402               yi=p.y()+sphi*v.y();
                                                   >> 1403 
                                                   >> 1404               // Check intersection in correct half-plane
                                                   >> 1405               // (if not -> remain in extent)
                                                   >> 1406               //
                                                   >> 1407               if ((yi*cosCPhi-xi*sinCPhi)>=0)
                                                   >> 1408               {
                                                   >> 1409                 sphi=kInfinity;
                                                   >> 1410               }
                                                   >> 1411               else
                                                   >> 1412               {
                                                   >> 1413                 // otherwise leaving via Starting phi
                                                   >> 1414                 //
                                                   >> 1415                 sidephi=kSPhi;
                                                   >> 1416               }
                                                   >> 1417             }
                                                   >> 1418             else  { sphi=kInfinity; }
                                                   >> 1419           }
                                                   >> 1420           else
                                                   >> 1421           {
                                                   >> 1422             // leaving immediately by ending
                                                   >> 1423             //
                                                   >> 1424             sidephi=kEPhi;
                                                   >> 1425             sphi=0;
                                                   >> 1426           }
                                                   >> 1427         }
1357       }                                          1428       }
1358     }                                         << 1429     }
1359     else                                         1430     else
1360     {                                            1431     {
1361       // On z axis + travel not || to z axis     1432       // On z axis + travel not || to z axis -> if phi of vector direction
1362       // within phi of shape, Step limited by    1433       // within phi of shape, Step limited by rmax, else Step =0
1363                                                  1434 
1364       vphi = std::atan2(v.y(),v.x());         << 1435       vphi=std::atan2(v.y(),v.x());
1365                                               << 1436       if ( (fSPhi<vphi) && (vphi<fSPhi+fDPhi) )
1366       if ( ( fSPhi-halfAngTolerance <= vphi ) << 
1367            ( vphi <= ( ePhi+halfAngTolerance  << 
1368       {                                          1437       {
1369         sphi = kInfinity;                     << 1438         sphi=kInfinity;
1370       }                                          1439       }
1371       else                                       1440       else
1372       {                                          1441       {
1373         sidephi = kSPhi ; // arbitrary           1442         sidephi = kSPhi ; // arbitrary 
1374         sphi=0;                                  1443         sphi=0;
1375       }                                          1444       }
1376     }                                            1445     }
1377                                                  1446 
1378     // Order intersections                       1447     // Order intersections
1379                                                  1448 
1380     if (sphi<snxt)                               1449     if (sphi<snxt)
1381     {                                            1450     {
1382       snxt=sphi;                                 1451       snxt=sphi;
1383       side=sidephi;                              1452       side=sidephi;
1384     }                                         << 1453     }
1385   }                                              1454   }
                                                   >> 1455   G4double rhoi2,rhoi,it2,it,iDotxyNmax ;
1386                                                  1456 
1387   G4double rhoi,it,iDotxyNmax ;               << 
1388   // Note: by numerical computation we know w    1457   // Note: by numerical computation we know where the ray hits the torus
1389   // So I propose to return the side where th    1458   // So I propose to return the side where the ray hits
1390                                                  1459 
1391   if (calcNorm)                                  1460   if (calcNorm)
1392   {                                              1461   {
1393     switch(side)                                 1462     switch(side)
1394     {                                            1463     {
1395       case kRMax:                     // n is    1464       case kRMax:                     // n is unit vector 
1396         xi    = p.x() + snxt*v.x() ;             1465         xi    = p.x() + snxt*v.x() ;
1397         yi    = p.y() + snxt*v.y() ;          << 1466         yi    =p.y() + snxt*v.y() ;
1398         zi    = p.z() + snxt*v.z() ;             1467         zi    = p.z() + snxt*v.z() ;
1399         rhoi = std::hypot(xi,yi);             << 1468         rhoi2 = xi*xi + yi*yi ;
1400         it = hypot(zi,rhoi-fRtor);            << 1469         rhoi  = std::sqrt(rhoi2) ;
1401                                               << 1470         it2   = std::fabs(rhoi2 + zi*zi + fRtor*fRtor - 2*fRtor*rhoi) ;
                                                   >> 1471         it    = std::sqrt(it2) ;
1402         iDotxyNmax = (1-fRtor/rhoi) ;            1472         iDotxyNmax = (1-fRtor/rhoi) ;
1403         if(iDotxyNmax >= -2.*fRmaxTolerance)  << 1473         if(iDotxyNmax >= -kRadTolerance) // really convex part of Rmax
1404         {                                        1474         {                       
1405           *n = G4ThreeVector( xi*(1-fRtor/rho    1475           *n = G4ThreeVector( xi*(1-fRtor/rhoi)/it,
1406                               yi*(1-fRtor/rho    1476                               yi*(1-fRtor/rhoi)/it,
1407                               zi/it              1477                               zi/it                 ) ;
1408           *validNorm = true ;                    1478           *validNorm = true ;
1409         }                                        1479         }
1410         else                                     1480         else
1411         {                                        1481         {
1412           *validNorm = false ; // concave-con    1482           *validNorm = false ; // concave-convex part of Rmax
1413         }                                        1483         }
1414         break ;                                  1484         break ;
1415                                                  1485 
1416       case kRMin:                                1486       case kRMin:
1417         *validNorm = false ;  // Rmin is conc    1487         *validNorm = false ;  // Rmin is concave or concave-convex
1418         break;                                   1488         break;
1419                                                  1489 
1420       case kSPhi:                                1490       case kSPhi:
1421         if (fDPhi <= pi )                        1491         if (fDPhi <= pi )
1422         {                                        1492         {
1423           *n=G4ThreeVector(std::sin(fSPhi),-s    1493           *n=G4ThreeVector(std::sin(fSPhi),-std::cos(fSPhi),0);
1424           *validNorm=true;                       1494           *validNorm=true;
1425         }                                        1495         }
1426         else                                     1496         else
1427         {                                        1497         {
1428           *validNorm = false ;                   1498           *validNorm = false ;
1429         }                                        1499         }
1430         break ;                                  1500         break ;
1431                                                  1501 
1432       case kEPhi:                                1502       case kEPhi:
1433         if (fDPhi <= pi)                         1503         if (fDPhi <= pi)
1434         {                                        1504         {
1435           *n=G4ThreeVector(-std::sin(fSPhi+fD    1505           *n=G4ThreeVector(-std::sin(fSPhi+fDPhi),std::cos(fSPhi+fDPhi),0);
1436           *validNorm=true;                       1506           *validNorm=true;
1437         }                                        1507         }
1438         else                                     1508         else
1439         {                                        1509         {
1440           *validNorm = false ;                   1510           *validNorm = false ;
1441         }                                        1511         }
1442         break;                                   1512         break;
1443                                                  1513 
1444       default:                                   1514       default:
1445                                                  1515 
1446         // It seems we go here from time to t    1516         // It seems we go here from time to time ...
1447                                                  1517 
                                                   >> 1518         G4cout.precision(16);
1448         G4cout << G4endl;                        1519         G4cout << G4endl;
1449         DumpInfo();                              1520         DumpInfo();
1450         std::ostringstream message;           << 1521         G4cout << "Position:"  << G4endl << G4endl;
1451         G4long oldprc = message.precision(16) << 1522         G4cout << "p.x() = "   << p.x()/mm << " mm" << G4endl;
1452         message << "Undefined side for valid  << 1523         G4cout << "p.y() = "   << p.y()/mm << " mm" << G4endl;
1453                 << G4endl                     << 1524         G4cout << "p.z() = "   << p.z()/mm << " mm" << G4endl << G4endl;
1454                 << "Position:"  << G4endl <<  << 1525         G4cout << "Direction:" << G4endl << G4endl;
1455                 << "p.x() = "   << p.x()/mm < << 1526         G4cout << "v.x() = "   << v.x() << G4endl;
1456                 << "p.y() = "   << p.y()/mm < << 1527         G4cout << "v.y() = "   << v.y() << G4endl;
1457                 << "p.z() = "   << p.z()/mm < << 1528         G4cout << "v.z() = "   << v.z() << G4endl << G4endl;
1458                 << "Direction:" << G4endl <<  << 1529         G4cout << "Proposed distance :" << G4endl << G4endl;
1459                 << "v.x() = "   << v.x() << G << 1530         G4cout << "snxt = " << snxt/mm << " mm" << G4endl << G4endl;
1460                 << "v.y() = "   << v.y() << G << 
1461                 << "v.z() = "   << v.z() << G << 
1462                 << "Proposed distance :" << G << 
1463                 << "snxt = " << snxt/mm << "  << 
1464         message.precision(oldprc);            << 
1465         G4Exception("G4Torus::DistanceToOut(p    1531         G4Exception("G4Torus::DistanceToOut(p,v,..)",
1466                     "GeomSolids1002",JustWarn << 1532                     "Notification",JustWarning,
                                                   >> 1533                     "Undefined side for valid surface normal to solid.");
1467         break;                                   1534         break;
1468     }                                            1535     }
1469   }                                              1536   }
1470   if ( snxt<halfCarTolerance )  { snxt=0 ; }  << 
1471                                                  1537 
1472   return snxt;                                   1538   return snxt;
1473 }                                                1539 }
1474                                                  1540 
1475 /////////////////////////////////////////////    1541 /////////////////////////////////////////////////////////////////////////
1476 //                                               1542 //
1477 // Calculate distance (<=actual) to closest s    1543 // Calculate distance (<=actual) to closest surface of shape from inside
1478                                                  1544 
1479 G4double G4Torus::DistanceToOut( const G4Thre    1545 G4double G4Torus::DistanceToOut( const G4ThreeVector& p ) const
1480 {                                                1546 {
1481   G4double safe=0.0,safeR1,safeR2;               1547   G4double safe=0.0,safeR1,safeR2;
1482   G4double rho,pt ;                           << 1548   G4double rho2,rho,pt2,pt ;
1483   G4double safePhi,phiC,cosPhiC,sinPhiC,ePhi;    1549   G4double safePhi,phiC,cosPhiC,sinPhiC,ePhi;
1484                                               << 1550   rho2 = p.x()*p.x() + p.y()*p.y() ;
1485   rho = std::hypot(p.x(),p.y());              << 1551   rho  = std::sqrt(rho2) ;
1486   pt  = std::hypot(p.z(),rho-fRtor);          << 1552   pt2  = std::fabs(rho2 + p.z()*p.z() + fRtor*fRtor - 2*fRtor*rho) ;
1487                                               << 1553   pt   = std::sqrt(pt2) ;
                                                   >> 1554 
1488 #ifdef G4CSGDEBUG                                1555 #ifdef G4CSGDEBUG
1489   if( Inside(p) == kOutside )                    1556   if( Inside(p) == kOutside )
1490   {                                              1557   {
1491      G4long oldprc = G4cout.precision(16) ;   << 1558      G4cout.precision(16) ;
1492      G4cout << G4endl ;                          1559      G4cout << G4endl ;
1493      DumpInfo();                                 1560      DumpInfo();
1494      G4cout << "Position:"  << G4endl << G4en    1561      G4cout << "Position:"  << G4endl << G4endl ;
1495      G4cout << "p.x() = "   << p.x()/mm << "     1562      G4cout << "p.x() = "   << p.x()/mm << " mm" << G4endl ;
1496      G4cout << "p.y() = "   << p.y()/mm << "     1563      G4cout << "p.y() = "   << p.y()/mm << " mm" << G4endl ;
1497      G4cout << "p.z() = "   << p.z()/mm << "     1564      G4cout << "p.z() = "   << p.z()/mm << " mm" << G4endl << G4endl ;
1498      G4cout.precision(oldprc);                << 1565      G4Exception("G4Torus::DistanceToOut(p)", "Notification",
1499      G4Exception("G4Torus::DistanceToOut(p)", << 
1500                  JustWarning, "Point p is out    1566                  JustWarning, "Point p is outside !?" );
1501   }                                              1567   }
1502 #endif                                           1568 #endif
1503                                                  1569 
1504   if (fRmin != 0.0)                           << 1570   if (fRmin)
1505   {                                              1571   {
1506     safeR1 = pt - fRmin ;                        1572     safeR1 = pt - fRmin ;
1507     safeR2 = fRmax - pt ;                        1573     safeR2 = fRmax - pt ;
1508                                                  1574 
1509     if (safeR1 < safeR2)  { safe = safeR1 ; }    1575     if (safeR1 < safeR2)  { safe = safeR1 ; }
1510     else                  { safe = safeR2 ; }    1576     else                  { safe = safeR2 ; }
1511   }                                              1577   }
1512   else                                           1578   else
1513   {                                              1579   {
1514     safe = fRmax - pt ;                          1580     safe = fRmax - pt ;
1515   }                                              1581   }  
1516                                                  1582 
1517   // Check if phi divided, Calc distances clo    1583   // Check if phi divided, Calc distances closest phi plane
1518   //                                             1584   //
1519   if (fDPhi < twopi) // Above/below central p << 1585   if (fDPhi<twopi) // Above/below central phi of Torus?
1520   {                                              1586   {
1521     phiC    = fSPhi + fDPhi*0.5 ;                1587     phiC    = fSPhi + fDPhi*0.5 ;
1522     cosPhiC = std::cos(phiC) ;                   1588     cosPhiC = std::cos(phiC) ;
1523     sinPhiC = std::sin(phiC) ;                   1589     sinPhiC = std::sin(phiC) ;
1524                                                  1590 
1525     if ((p.y()*cosPhiC-p.x()*sinPhiC)<=0)        1591     if ((p.y()*cosPhiC-p.x()*sinPhiC)<=0)
1526     {                                            1592     {
1527       safePhi = -(p.x()*std::sin(fSPhi) - p.y    1593       safePhi = -(p.x()*std::sin(fSPhi) - p.y()*std::cos(fSPhi)) ;
1528     }                                            1594     }
1529     else                                         1595     else
1530     {                                            1596     {
1531       ePhi    = fSPhi + fDPhi ;                  1597       ePhi    = fSPhi + fDPhi ;
1532       safePhi = (p.x()*std::sin(ePhi) - p.y()    1598       safePhi = (p.x()*std::sin(ePhi) - p.y()*std::cos(ePhi)) ;
1533     }                                            1599     }
1534     if (safePhi < safe)  { safe = safePhi ; }    1600     if (safePhi < safe)  { safe = safePhi ; }
1535   }                                              1601   }
1536   if (safe < 0)  { safe = 0 ; }                  1602   if (safe < 0)  { safe = 0 ; }
1537   return safe ;                                  1603   return safe ;  
1538 }                                                1604 }
1539                                                  1605 
1540 ///////////////////////////////////////////// << 1606 /////////////////////////////////////////////////////////////////////////////
1541 //                                               1607 //
1542 // Stream object contents to an output stream << 1608 // Create a List containing the transformed vertices
                                                   >> 1609 // Ordering [0-3] -fRtor cross section
                                                   >> 1610 //          [4-7] +fRtor cross section such that [0] is below [4],
                                                   >> 1611 //                                             [1] below [5] etc.
                                                   >> 1612 // Note:
                                                   >> 1613 //  Caller has deletion resposibility
                                                   >> 1614 //  Potential improvement: For last slice, use actual ending angle
                                                   >> 1615 //                         to avoid rounding error problems.
1543                                                  1616 
1544 G4GeometryType G4Torus::GetEntityType() const << 1617 G4ThreeVectorList*
                                                   >> 1618 G4Torus::CreateRotatedVertices( const G4AffineTransform& pTransform,
                                                   >> 1619                                       G4int& noPolygonVertices ) const
1545 {                                                1620 {
1546   return {"G4Torus"};                         << 1621   G4ThreeVectorList *vertices;
                                                   >> 1622   G4ThreeVector vertex0,vertex1,vertex2,vertex3;
                                                   >> 1623   G4double meshAngle,meshRMax,crossAngle,cosCrossAngle,sinCrossAngle,sAngle;
                                                   >> 1624   G4double rMaxX,rMaxY,rMinX,rMinY;
                                                   >> 1625   G4int crossSection,noCrossSections;
                                                   >> 1626 
                                                   >> 1627   // Compute no of cross-sections necessary to mesh tube
                                                   >> 1628   //
                                                   >> 1629   noCrossSections = G4int (fDPhi/kMeshAngleDefault) + 1 ;
                                                   >> 1630 
                                                   >> 1631   if (noCrossSections < kMinMeshSections)
                                                   >> 1632   {
                                                   >> 1633     noCrossSections = kMinMeshSections ;
                                                   >> 1634   }
                                                   >> 1635   else if (noCrossSections>kMaxMeshSections)
                                                   >> 1636   {
                                                   >> 1637     noCrossSections=kMaxMeshSections;
                                                   >> 1638   }
                                                   >> 1639   meshAngle = fDPhi/(noCrossSections - 1) ;
                                                   >> 1640   meshRMax  = (fRtor + fRmax)/std::cos(meshAngle*0.5) ;
                                                   >> 1641 
                                                   >> 1642   // If complete in phi, set start angle such that mesh will be at fRmax
                                                   >> 1643   // on the x axis. Will give better extent calculations when not rotated
                                                   >> 1644 
                                                   >> 1645   if ( (fDPhi == pi*2.0) && (fSPhi == 0) )
                                                   >> 1646   {
                                                   >> 1647     sAngle = -meshAngle*0.5 ;
                                                   >> 1648   }
                                                   >> 1649   else
                                                   >> 1650   {
                                                   >> 1651     sAngle = fSPhi ;
                                                   >> 1652   }
                                                   >> 1653   vertices = new G4ThreeVectorList();
                                                   >> 1654   vertices->reserve(noCrossSections*4) ;
                                                   >> 1655   
                                                   >> 1656   if (vertices)
                                                   >> 1657   {
                                                   >> 1658     for (crossSection=0;crossSection<noCrossSections;crossSection++)
                                                   >> 1659     {
                                                   >> 1660       // Compute coordinates of cross section at section crossSection
                                                   >> 1661 
                                                   >> 1662       crossAngle=sAngle+crossSection*meshAngle;
                                                   >> 1663       cosCrossAngle=std::cos(crossAngle);
                                                   >> 1664       sinCrossAngle=std::sin(crossAngle);
                                                   >> 1665 
                                                   >> 1666       rMaxX=meshRMax*cosCrossAngle;
                                                   >> 1667       rMaxY=meshRMax*sinCrossAngle;
                                                   >> 1668       rMinX=(fRtor-fRmax)*cosCrossAngle;
                                                   >> 1669       rMinY=(fRtor-fRmax)*sinCrossAngle;
                                                   >> 1670       vertex0=G4ThreeVector(rMinX,rMinY,-fRmax);
                                                   >> 1671       vertex1=G4ThreeVector(rMaxX,rMaxY,-fRmax);
                                                   >> 1672       vertex2=G4ThreeVector(rMaxX,rMaxY,+fRmax);
                                                   >> 1673       vertex3=G4ThreeVector(rMinX,rMinY,+fRmax);
                                                   >> 1674 
                                                   >> 1675       vertices->push_back(pTransform.TransformPoint(vertex0));
                                                   >> 1676       vertices->push_back(pTransform.TransformPoint(vertex1));
                                                   >> 1677       vertices->push_back(pTransform.TransformPoint(vertex2));
                                                   >> 1678       vertices->push_back(pTransform.TransformPoint(vertex3));
                                                   >> 1679     }
                                                   >> 1680     noPolygonVertices = 4 ;
                                                   >> 1681   }
                                                   >> 1682   else
                                                   >> 1683   {
                                                   >> 1684     DumpInfo();
                                                   >> 1685     G4Exception("G4Torus::CreateRotatedVertices()",
                                                   >> 1686                 "FatalError", FatalException,
                                                   >> 1687                 "Error in allocation of vertices. Out of memory !");
                                                   >> 1688   }
                                                   >> 1689   return vertices;
1547 }                                                1690 }
1548                                                  1691 
1549 /////////////////////////////////////////////    1692 //////////////////////////////////////////////////////////////////////////
1550 //                                               1693 //
1551 // Make a clone of the object                 << 1694 // Stream object contents to an output stream
1552 //                                            << 1695 
1553 G4VSolid* G4Torus::Clone() const              << 1696 G4GeometryType G4Torus::GetEntityType() const
1554 {                                                1697 {
1555   return new G4Torus(*this);                  << 1698   return G4String("G4Torus");
1556 }                                                1699 }
1557                                                  1700 
1558 /////////////////////////////////////////////    1701 //////////////////////////////////////////////////////////////////////////
1559 //                                               1702 //
1560 // Stream object contents to an output stream    1703 // Stream object contents to an output stream
1561                                                  1704 
1562 std::ostream& G4Torus::StreamInfo( std::ostre    1705 std::ostream& G4Torus::StreamInfo( std::ostream& os ) const
1563 {                                                1706 {
1564   G4long oldprc = os.precision(16);           << 
1565   os << "------------------------------------    1707   os << "-----------------------------------------------------------\n"
1566      << "    *** Dump for solid - " << GetNam    1708      << "    *** Dump for solid - " << GetName() << " ***\n"
1567      << "    ================================    1709      << "    ===================================================\n"
1568      << " Solid type: G4Torus\n"                 1710      << " Solid type: G4Torus\n"
1569      << " Parameters: \n"                        1711      << " Parameters: \n"
1570      << "    inner radius: " << fRmin/mm << "    1712      << "    inner radius: " << fRmin/mm << " mm \n"
1571      << "    outer radius: " << fRmax/mm << "    1713      << "    outer radius: " << fRmax/mm << " mm \n"
1572      << "    swept radius: " << fRtor/mm << "    1714      << "    swept radius: " << fRtor/mm << " mm \n"
1573      << "    starting phi: " << fSPhi/degree     1715      << "    starting phi: " << fSPhi/degree << " degrees \n"
1574      << "    delta phi   : " << fDPhi/degree     1716      << "    delta phi   : " << fDPhi/degree << " degrees \n"
1575      << "------------------------------------    1717      << "-----------------------------------------------------------\n";
1576   os.precision(oldprc);                       << 
1577                                                  1718 
1578   return os;                                     1719   return os;
1579 }                                                1720 }
1580                                                  1721 
1581 /////////////////////////////////////////////    1722 ////////////////////////////////////////////////////////////////////////////
1582 //                                               1723 //
1583 // GetPointOnSurface                             1724 // GetPointOnSurface
1584                                                  1725 
1585 G4ThreeVector G4Torus::GetPointOnSurface() co    1726 G4ThreeVector G4Torus::GetPointOnSurface() const
1586 {                                                1727 {
1587   G4double cosu, sinu,cosv, sinv, aOut, aIn,     1728   G4double cosu, sinu,cosv, sinv, aOut, aIn, aSide, chose, phi, theta, rRand;
1588                                                  1729    
1589   phi   = G4RandFlat::shoot(fSPhi,fSPhi+fDPhi << 1730   phi   = RandFlat::shoot(fSPhi,fSPhi+fDPhi);
1590   theta = G4RandFlat::shoot(0.,twopi);        << 1731   theta = RandFlat::shoot(0.,2.*pi);
1591                                                  1732   
1592   cosu   = std::cos(phi);    sinu = std::sin(    1733   cosu   = std::cos(phi);    sinu = std::sin(phi);
1593   cosv   = std::cos(theta);  sinv = std::sin(    1734   cosv   = std::cos(theta);  sinv = std::sin(theta); 
1594                                                  1735 
1595   // compute the areas                           1736   // compute the areas
1596                                                  1737 
1597   aOut   = (fDPhi)*twopi*fRtor*fRmax;         << 1738   aOut   = (fDPhi)*2.*pi*fRtor*fRmax;
1598   aIn    = (fDPhi)*twopi*fRtor*fRmin;         << 1739   aIn    = (fDPhi)*2.*pi*fRtor*fRmin;
1599   aSide  = pi*(fRmax*fRmax-fRmin*fRmin);         1740   aSide  = pi*(fRmax*fRmax-fRmin*fRmin);
1600                                                  1741   
1601   if ((fSPhi == 0) && (fDPhi == twopi)){ aSid << 1742   if(fSPhi == 0 && fDPhi == twopi){ aSide = 0; }
1602   chose = G4RandFlat::shoot(0.,aOut + aIn + 2 << 1743   chose = RandFlat::shoot(0.,aOut + aIn + 2.*aSide);
1603                                                  1744 
1604   if(chose < aOut)                               1745   if(chose < aOut)
1605   {                                              1746   {
1606     return { (fRtor+fRmax*cosv)*cosu, (fRtor+ << 1747     return G4ThreeVector ((fRtor+fRmax*cosv)*cosu,
                                                   >> 1748                           (fRtor+fRmax*cosv)*sinu, fRmax*sinv);
1607   }                                              1749   }
1608   else if( (chose >= aOut) && (chose < aOut +    1750   else if( (chose >= aOut) && (chose < aOut + aIn) )
1609   {                                              1751   {
1610     return { (fRtor+fRmin*cosv)*cosu, (fRtor+ << 1752     return G4ThreeVector ((fRtor+fRmin*cosv)*cosu,
                                                   >> 1753                           (fRtor+fRmin*cosv)*sinu, fRmin*sinv);
1611   }                                              1754   }
1612   else if( (chose >= aOut + aIn) && (chose <     1755   else if( (chose >= aOut + aIn) && (chose < aOut + aIn + aSide) )
1613   {                                              1756   {
1614     rRand = GetRadiusInRing(fRmin,fRmax);     << 1757     rRand = RandFlat::shoot(fRmin,fRmax);
1615     return { (fRtor+rRand*cosv)*std::cos(fSPh << 1758     return G4ThreeVector ((fRtor+rRand*cosv)*std::cos(fSPhi),
1616              (fRtor+rRand*cosv)*std::sin(fSPh << 1759                           (fRtor+rRand*cosv)*std::sin(fSPhi), rRand*sinv);
1617   }                                              1760   }
1618   else                                           1761   else
1619   {                                              1762   {   
1620     rRand = GetRadiusInRing(fRmin,fRmax);     << 1763     rRand = RandFlat::shoot(fRmin,fRmax);
1621     return { (fRtor+rRand*cosv)*std::cos(fSPh << 1764     return G4ThreeVector ((fRtor+rRand*cosv)*std::cos(fSPhi+fDPhi),
1622              (fRtor+rRand*cosv)*std::sin(fSPh << 1765                           (fRtor+rRand*cosv)*std::sin(fSPhi+fDPhi), 
                                                   >> 1766                           rRand*sinv);
1623    }                                             1767    }
1624 }                                                1768 }
1625                                                  1769 
1626 /////////////////////////////////////////////    1770 ///////////////////////////////////////////////////////////////////////
1627 //                                               1771 //
1628 // Visualisation Functions                       1772 // Visualisation Functions
1629                                                  1773 
1630 void G4Torus::DescribeYourselfTo ( G4VGraphic    1774 void G4Torus::DescribeYourselfTo ( G4VGraphicsScene& scene ) const 
1631 {                                                1775 {
1632   scene.AddSolid (*this);                        1776   scene.AddSolid (*this);
1633 }                                                1777 }
1634                                                  1778 
1635 G4Polyhedron* G4Torus::CreatePolyhedron () co    1779 G4Polyhedron* G4Torus::CreatePolyhedron () const 
1636 {                                                1780 {
1637   return new G4PolyhedronTorus (fRmin, fRmax,    1781   return new G4PolyhedronTorus (fRmin, fRmax, fRtor, fSPhi, fDPhi);
1638 }                                                1782 }
1639                                                  1783 
1640 #endif // !defined(G4GEOM_USE_TORUS) || !defi << 1784 G4NURBS* G4Torus::CreateNURBS () const 
                                                   >> 1785 {
                                                   >> 1786   G4NURBS* pNURBS;
                                                   >> 1787   if (fRmin != 0) 
                                                   >> 1788   {
                                                   >> 1789     if (fDPhi >= 2.0 * pi) 
                                                   >> 1790     {
                                                   >> 1791       pNURBS = new G4NURBStube(fRmin, fRmax, fRtor);
                                                   >> 1792     }
                                                   >> 1793     else 
                                                   >> 1794     {
                                                   >> 1795       pNURBS = new G4NURBStubesector(fRmin, fRmax, fRtor, fSPhi, fSPhi + fDPhi);
                                                   >> 1796     }
                                                   >> 1797   }
                                                   >> 1798   else 
                                                   >> 1799   {
                                                   >> 1800     if (fDPhi >= 2.0 * pi) 
                                                   >> 1801     {
                                                   >> 1802       pNURBS = new G4NURBScylinder (fRmax, fRtor);
                                                   >> 1803     }
                                                   >> 1804     else 
                                                   >> 1805     {
                                                   >> 1806       const G4double epsilon = 1.e-4; // Cylinder sector not yet available!
                                                   >> 1807       pNURBS = new G4NURBStubesector (epsilon, fRmax, fRtor,
                                                   >> 1808                                       fSPhi, fSPhi + fDPhi);
                                                   >> 1809     }
                                                   >> 1810   }
                                                   >> 1811   return pNURBS;
                                                   >> 1812 }
1641                                                  1813