Geant4 Cross Reference

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


                                                   >>   1 // This code implementation is the intellectual property of
                                                   >>   2 // the GEANT4 collaboration.
  1 //                                                  3 //
  2 // ******************************************* <<   4 // By copying, distributing or modifying the Program (or any work
  3 // * License and Disclaimer                    <<   5 // based on the Program) you indicate your acceptance of this statement,
  4 // *                                           <<   6 // and all its terms.
  5 // * The  Geant4 software  is  copyright of th <<   7 //
  6 // * the Geant4 Collaboration.  It is provided <<   8 // $Id: G4Cons.cc,v 1.6 1999/12/15 14:50:07 gunter Exp $
  7 // * conditions of the Geant4 Software License <<   9 // GEANT4 tag $Name: geant4-01-01 $
  8 // * LICENSE and available at  http://cern.ch/ <<  10 //
  9 // * include a list of copyright holders.      <<  11 // class G4Cons
 10 // *                                           << 
 11 // * Neither the authors of this software syst << 
 12 // * institutes,nor the agencies providing fin << 
 13 // * work  make  any representation or  warran << 
 14 // * regarding  this  software system or assum << 
 15 // * use.  Please see the license in the file  << 
 16 // * for the full disclaimer and the limitatio << 
 17 // *                                           << 
 18 // * This  code  implementation is the result  << 
 19 // * technical work of the GEANT4 collaboratio << 
 20 // * By using,  copying,  modifying or  distri << 
 21 // * any work based  on the software)  you  ag << 
 22 // * use  in  resulting  scientific  publicati << 
 23 // * acceptance of all terms of the Geant4 Sof << 
 24 // ******************************************* << 
 25 //                                                 12 //
 26 // Implementation for G4Cons class                 13 // Implementation for G4Cons class
 27 //                                                 14 //
 28 // ~1994    P.Kent: Created, as main part of t <<  15 // History:
 29 // 13.09.96 V.Grichine: Review and final modif <<  16 //
 30 // 03.05.05 V.Grichine: SurfaceNormal(p) accor <<  17 // 18.11.99 V.Grichine side = kNull initialisation in DistanceToOut(p,v,...)
 31 // 12.10.09 T.Nikitina: Added to DistanceToIn( <<  18 // 28.04.99 V. Grichine bugs fixed in  Distance ToOut(p,v,...) and  
 32 //                      case of point on surfa <<  19 //          Distance ToIn(p,v)
 33 // 03.10.16 E.Tcherniaev: use G4BoundingEnvelo <<  20 // 09.10.98 V. Grichine modifications in Distance ToOut(p,v,...)
 34 //                      removed CreateRotatedV <<  21 // 13.09.96 V. Grichine: final modifications to commit
 35 // ------------------------------------------- <<  22 // ~1994 P. Kent: main part of geometry functions
 36                                                    23 
 37 #include "G4Cons.hh"                               24 #include "G4Cons.hh"
 38                                                    25 
 39 #if !defined(G4GEOM_USE_UCONS)                 << 
 40                                                << 
 41 #include "G4GeomTools.hh"                      << 
 42 #include "G4VoxelLimits.hh"                        26 #include "G4VoxelLimits.hh"
 43 #include "G4AffineTransform.hh"                    27 #include "G4AffineTransform.hh"
 44 #include "G4BoundingEnvelope.hh"               << 
 45 #include "G4GeometryTolerance.hh"              << 
 46                                                    28 
 47 #include "G4VPVParameterisation.hh"                29 #include "G4VPVParameterisation.hh"
 48                                                    30 
 49 #include "meshdefs.hh"                             31 #include "meshdefs.hh"
 50                                                    32 
 51 #include "Randomize.hh"                        << 
 52                                                << 
 53 #include "G4VGraphicsScene.hh"                     33 #include "G4VGraphicsScene.hh"
                                                   >>  34 #include "G4Polyhedron.hh"
                                                   >>  35 #include "G4NURBS.hh"
                                                   >>  36 #include "G4NURBSbox.hh"
                                                   >>  37 #include "G4VisExtent.hh"
 54                                                    38 
 55 using namespace CLHEP;                         << 
 56                                                << 
 57 //////////////////////////////////////////////     39 ////////////////////////////////////////////////////////////////////////
 58 //                                                 40 //
 59 // Private enums: Not for external use         <<  41 // Private enum: Not for external use - used by distanceToOut
 60                                                    42 
 61 namespace                                      <<  43 enum ESide {kNull,kRMin,kRMax,kSPhi,kEPhi,kPZ,kMZ};
 62 {                                              << 
 63   // used by DistanceToOut()                   << 
 64   //                                           << 
 65   enum ESide {kNull,kRMin,kRMax,kSPhi,kEPhi,kP << 
 66                                                << 
 67   // used by ApproxSurfaceNormal()             << 
 68   //                                           << 
 69   enum ENorm {kNRMin,kNRMax,kNSPhi,kNEPhi,kNZ} << 
 70 }                                              << 
 71                                                    44 
 72 ////////////////////////////////////////////// <<  45 // used by normal
 73 //                                             << 
 74 // constructor - check parameters, convert ang << 
 75 //             - note if pDPhi>2PI then reset  << 
 76                                                    46 
 77 G4Cons::G4Cons( const G4String& pName,         <<  47 enum ENorm {kNRMin,kNRMax,kNSPhi,kNEPhi,kNZ};
 78                       G4double  pRmin1, G4doub << 
 79                       G4double  pRmin2, G4doub << 
 80                       G4double pDz,            << 
 81                       G4double pSPhi, G4double << 
 82   : G4CSGSolid(pName), fRmin1(pRmin1), fRmin2( << 
 83     fRmax1(pRmax1), fRmax2(pRmax2), fDz(pDz),  << 
 84 {                                              << 
 85   kRadTolerance = G4GeometryTolerance::GetInst << 
 86   kAngTolerance = G4GeometryTolerance::GetInst << 
 87                                                << 
 88   halfCarTolerance=kCarTolerance*0.5;          << 
 89   halfRadTolerance=kRadTolerance*0.5;          << 
 90   halfAngTolerance=kAngTolerance*0.5;          << 
 91                                                << 
 92   // Check z-len                               << 
 93   //                                           << 
 94   if ( pDz < 0 )                               << 
 95   {                                            << 
 96     std::ostringstream message;                << 
 97     message << "Invalid Z half-length for Soli << 
 98             << "        hZ = " << pDz;         << 
 99     G4Exception("G4Cons::G4Cons()", "GeomSolid << 
100                 FatalException, message);      << 
101   }                                            << 
102                                                << 
103   // Check radii                               << 
104   //                                           << 
105   if (((pRmin1>=pRmax1) || (pRmin2>=pRmax2) || << 
106   {                                            << 
107     std::ostringstream message;                << 
108     message << "Invalid values of radii for So << 
109             << "        pRmin1 = " << pRmin1 < << 
110             << ", pRmax1 = " << pRmax1 << ", p << 
111     G4Exception("G4Cons::G4Cons()", "GeomSolid << 
112                 FatalException, message) ;     << 
113   }                                            << 
114   if( (pRmin1 == 0.0) && (pRmin2 > 0.0) ) { fR << 
115   if( (pRmin2 == 0.0) && (pRmin1 > 0.0) ) { fR << 
116                                                << 
117   // Check angles                              << 
118   //                                           << 
119   CheckPhiAngles(pSPhi, pDPhi);                << 
120 }                                              << 
121                                                    48 
122 //////////////////////////////////////////////     49 ///////////////////////////////////////////////////////////////////////
123 //                                                 50 //
124 // Fake default constructor - sets only member <<  51 // Destructor
125 //                            for usage restri <<  52 
126 //                                             <<  53 G4Cons::~G4Cons()
127 G4Cons::G4Cons( __void__& a )                  << 
128   : G4CSGSolid(a)                              << 
129 {                                                  54 {
                                                   >>  55    ;
130 }                                                  56 }
131                                                    57 
132 ////////////////////////////////////////////// <<  58 //////////////////////////////////////////////////////////////////////////
133 //                                                 59 //
134 // Destructor                                  <<  60 // constructor - check parameters, convert angles so 0<sphi+dpshi<=2_PI
                                                   >>  61 //               - note if pDPhi>2PI then reset to 2PI
135                                                    62 
136 G4Cons::~G4Cons() = default;                   <<  63 G4Cons::G4Cons( const G4String& pName,
                                                   >>  64           G4double pRmin1, G4double pRmax1,
                                                   >>  65           G4double pRmin2, G4double pRmax2,
                                                   >>  66           G4double pDz,
                                                   >>  67           G4double pSPhi, G4double pDPhi) : G4CSGSolid(pName)
                                                   >>  68 {
                                                   >>  69 // Check z-len
137                                                    70 
138 ////////////////////////////////////////////// <<  71     if (pDz>0)
139 //                                             <<  72     {
140 // Copy constructor                            <<  73        fDz=pDz;
                                                   >>  74     }
                                                   >>  75     else
                                                   >>  76     {
                                                   >>  77        G4Exception("Error in G4Cons::G4Cons - invalid z half-length");
                                                   >>  78     }
141                                                    79 
142 G4Cons::G4Cons(const G4Cons&) = default;       <<  80 // Check radii
143                                                    81 
144 ////////////////////////////////////////////// <<  82     if ( pRmin1 < pRmax1 && pRmin2 < pRmax2 && pRmin1 >= 0 && pRmin2 >= 0 )
145 //                                             <<  83     {
146 // Assignment operator                         <<  84        fRmin1=pRmin1; fRmax1=pRmax1;
                                                   >>  85        fRmin2=pRmin2; fRmax2=pRmax2;
                                                   >>  86     }
                                                   >>  87     else
                                                   >>  88     {
                                                   >>  89        G4Exception("Error in G4Cons::G4Cons - invalid radii");
                                                   >>  90     }
147                                                    91 
148 G4Cons& G4Cons::operator = (const G4Cons& rhs) <<  92 // Check angles
149 {                                              << 
150    // Check assignment to self                 << 
151    //                                          << 
152    if (this == &rhs)  { return *this; }        << 
153                                                << 
154    // Copy base class data                     << 
155    //                                          << 
156    G4CSGSolid::operator=(rhs);                 << 
157                                                << 
158    // Copy data                                << 
159    //                                          << 
160    kRadTolerance = rhs.kRadTolerance;          << 
161    kAngTolerance = rhs.kAngTolerance;          << 
162    fRmin1 = rhs.fRmin1; fRmin2 = rhs.fRmin2;   << 
163    fRmax1 = rhs.fRmax1; fRmax2 = rhs.fRmax2;   << 
164    fDz = rhs.fDz; fSPhi = rhs.fSPhi; fDPhi = r << 
165    sinCPhi = rhs.sinCPhi; cosCPhi = rhs.cosCPh << 
166    cosHDPhiOT = rhs.cosHDPhiOT; cosHDPhiIT = r << 
167    sinSPhi = rhs.sinSPhi; cosSPhi = rhs.cosSPh << 
168    sinEPhi = rhs.sinEPhi; cosEPhi = rhs.cosEPh << 
169    fPhiFullCone = rhs.fPhiFullCone;            << 
170    halfCarTolerance = rhs.halfCarTolerance;    << 
171    halfRadTolerance = rhs.halfRadTolerance;    << 
172    halfAngTolerance = rhs.halfAngTolerance;    << 
173                                                    93 
174    return *this;                               <<  94     if ( pDPhi >= 2.0*M_PI )
                                                   >>  95     {
                                                   >>  96        fDPhi=2*M_PI;
                                                   >>  97        fSPhi=0;
                                                   >>  98     }
                                                   >>  99     else
                                                   >> 100     {
                                                   >> 101        if ( pDPhi > 0 )
                                                   >> 102        {
                                                   >> 103     fDPhi = pDPhi ;
                                                   >> 104        }
                                                   >> 105        else
                                                   >> 106        {
                                                   >> 107     G4Exception("Error in G4Cons::G4Cons - invalid pDPhi");
                                                   >> 108        }
                                                   >> 109   
                                                   >> 110 // Ensure pSPhi in 0-2PI or -2PI-0 range if shape crosses 0
                                                   >> 111 
                                                   >> 112        if (pSPhi < 0)
                                                   >> 113        {
                                                   >> 114     fSPhi = 2.0*M_PI - fmod(fabs(pSPhi),2.0*M_PI) ;
                                                   >> 115        }
                                                   >> 116        else
                                                   >> 117        {
                                                   >> 118     fSPhi=fmod(pSPhi,2.0*M_PI);
                                                   >> 119        }      
                                                   >> 120        if (fSPhi+fDPhi>2.0*M_PI) fSPhi-=2.0*M_PI;
                                                   >> 121     }
175 }                                                 122 }
176                                                   123 
177 //////////////////////////////////////////////    124 /////////////////////////////////////////////////////////////////////
178 //                                                125 //
179 // Return whether point inside/outside/on surf    126 // Return whether point inside/outside/on surface
180                                                   127 
181 EInside G4Cons::Inside(const G4ThreeVector& p)    128 EInside G4Cons::Inside(const G4ThreeVector& p) const
182 {                                                 129 {
183   G4double r2, rl, rh, pPhi, tolRMin, tolRMax; << 130     G4double r2,rl,rh,pPhi,tolRMin,tolRMax;
184   EInside in;                                  << 131     EInside in=kOutside;
185                                                << 132     if (fabs(p.z())<=fDz-kCarTolerance/2)
186   if (std::fabs(p.z()) > fDz + halfCarToleranc << 133   {
187   else if(std::fabs(p.z()) >= fDz - halfCarTol << 134       r2=p.x()*p.x()+p.y()*p.y();
188   else                                         << 135       rl=0.5*(fRmin2*(p.z()+fDz)+fRmin1*(fDz-p.z()))/fDz;
189                                                << 136 // inner radius at z of point
190   r2 = p.x()*p.x() + p.y()*p.y() ;             << 137       rh=0.5*(fRmax2*(p.z()+fDz)+fRmax1*(fDz-p.z()))/fDz;
191   rl = 0.5*(fRmin2*(p.z() + fDz) + fRmin1*(fDz << 138 // outer radius at z of point
192   rh = 0.5*(fRmax2*(p.z()+fDz)+fRmax1*(fDz-p.z << 139 
193                                                << 140       if (rl)
194   // rh2 = rh*rh;                              << 141     {
195                                                << 142         tolRMin=rl+kRadTolerance/2;
196   tolRMin = rl - halfRadTolerance;             << 143     }
197   if ( tolRMin < 0 )  { tolRMin = 0; }         << 144       else
198   tolRMax = rh + halfRadTolerance;             << 145     {
199                                                << 146         tolRMin=0;
200   if ( (r2<tolRMin*tolRMin) || (r2>tolRMax*tol << 147     }
201                                                << 148       tolRMax=rh-kRadTolerance/2;
202   if (rl != 0.0) { tolRMin = rl + halfRadToler << 149       
203   else    { tolRMin = 0.0; }                   << 150       if (r2>=tolRMin*tolRMin && r2<=tolRMax*tolRMax)
204   tolRMax = rh - halfRadTolerance;             << 151     {
205                                                << 152         if (fDPhi==2*M_PI||r2==0)
206   if (in == kInside) // else it's kSurface alr << 153       {
207   {                                            << 154           in=kInside;
208      if ( (r2 < tolRMin*tolRMin) || (r2 >= tol << 155       }
209   }                                            << 156         else
210   if ( !fPhiFullCone && ((p.x() != 0.0) || (p. << 157       {
211   {                                            << 158 // Try inner tolerant phi boundaries (=>inside)
212     pPhi = std::atan2(p.y(),p.x()) ;           << 159 // if not inside, try outer tolerant phi boundaries
213                                                << 160           pPhi=atan2(p.y(),p.x());
214     if ( pPhi < fSPhi - halfAngTolerance  )    << 161           if (pPhi<0) pPhi+=2*M_PI; // 0<=pPhi<2pi
215     else if ( pPhi > fSPhi + fDPhi + halfAngTo << 162           if (fSPhi>=0)
216                                                << 163         {
217     if ( (pPhi < fSPhi - halfAngTolerance) ||  << 164             if (pPhi>=fSPhi+kAngTolerance/2 &&
218          (pPhi > fSPhi + fDPhi + halfAngTolera << 165           pPhi<=fSPhi+fDPhi-kAngTolerance/2)
219                                                << 166           {
220     else if (in == kInside)  // else it's kSur << 167               in=kInside;
221     {                                          << 168           }
222        if ( (pPhi < fSPhi + halfAngTolerance)  << 169             else if (pPhi>=fSPhi-kAngTolerance/2 &&
223             (pPhi > fSPhi + fDPhi - halfAngTol << 170                pPhi<=fSPhi+fDPhi+kAngTolerance/2)
224     }                                          << 171           {
225   }                                            << 172               in=kSurface;
226   else if ( !fPhiFullCone )  { in = kSurface;  << 173           }
227                                                << 174         }
228   return in ;                                  << 175           else
                                                   >> 176         {
                                                   >> 177             if (pPhi<fSPhi+2*M_PI) pPhi+=2*M_PI;
                                                   >> 178             if (pPhi>=fSPhi+2*M_PI+kAngTolerance/2 &&
                                                   >> 179           pPhi<=fSPhi+fDPhi+2*M_PI-kAngTolerance/2)
                                                   >> 180           {
                                                   >> 181               in=kInside;
                                                   >> 182           }
                                                   >> 183             else if (pPhi>=fSPhi+2*M_PI-kAngTolerance/2 &&
                                                   >> 184                pPhi<=fSPhi+fDPhi+2*M_PI+kAngTolerance/2)
                                                   >> 185           {
                                                   >> 186               in=kSurface;
                                                   >> 187           }
                                                   >> 188         }
                                                   >> 189           
                                                   >> 190           
                                                   >> 191       }
                                                   >> 192     }
                                                   >> 193       else
                                                   >> 194     {
                                                   >> 195 // Try generous boundaries
                                                   >> 196         tolRMin=rl-kRadTolerance/2;
                                                   >> 197         tolRMax=rh+kRadTolerance/2;
                                                   >> 198         if (tolRMin<0) tolRMin=0;
                                                   >> 199         if (r2>=tolRMin*tolRMin && r2 <= tolRMax*tolRMax)
                                                   >> 200       {
                                                   >> 201           if (fDPhi==2*M_PI||r2==0)
                                                   >> 202         {
                                                   >> 203 // Continuous in phi or on z-axis
                                                   >> 204             in=kSurface;
                                                   >> 205         }
                                                   >> 206           else
                                                   >> 207         {
                                                   >> 208 // Try outer tolerant phi boundaries only
                                                   >> 209             pPhi=atan2(p.y(),p.x());
                                                   >> 210             if (pPhi<0) pPhi+=2*M_PI; // 0<=pPhi<2pi
                                                   >> 211             if (fSPhi>=0)
                                                   >> 212           {
                                                   >> 213               if (pPhi>=fSPhi-kAngTolerance/2 &&
                                                   >> 214             pPhi<=fSPhi+fDPhi+kAngTolerance/2)
                                                   >> 215             {
                                                   >> 216                 in=kSurface;
                                                   >> 217             }
                                                   >> 218           }
                                                   >> 219             else
                                                   >> 220           {
                                                   >> 221               if (pPhi<fSPhi+2*M_PI) pPhi+=2*M_PI;
                                                   >> 222               if (pPhi>=fSPhi+2*M_PI-kAngTolerance/2 &&
                                                   >> 223             pPhi<=fSPhi+fDPhi+2*M_PI+kAngTolerance/2)
                                                   >> 224             {
                                                   >> 225                 in=kSurface;
                                                   >> 226             }
                                                   >> 227           }
                                                   >> 228             
                                                   >> 229 
                                                   >> 230         }
                                                   >> 231       }
                                                   >> 232     }
                                                   >> 233   }
                                                   >> 234     else if (fabs(p.z())<=fDz+kCarTolerance/2)
                                                   >> 235   {
                                                   >> 236 // Check within tolerant r limits
                                                   >> 237       r2=p.x()*p.x()+p.y()*p.y();
                                                   >> 238       rl=0.5*(fRmin2*(p.z()+fDz)+fRmin1*(fDz-p.z()))/fDz;
                                                   >> 239 // inner radius at z of point
                                                   >> 240       rh=0.5*(fRmax2*(p.z()+fDz)+fRmax1*(fDz-p.z()))/fDz;
                                                   >> 241 // outer radius at z of point
                                                   >> 242       tolRMin=rl-kRadTolerance/2;
                                                   >> 243       if (tolRMin<0) tolRMin=0;
                                                   >> 244       tolRMax=rh+kRadTolerance/2;
                                                   >> 245       if (r2>=tolRMin*tolRMin && r2 <= tolRMax*tolRMax)
                                                   >> 246     {
                                                   >> 247         if (fDPhi==2*M_PI||r2==0)
                                                   >> 248       {
                                                   >> 249 // Continuous in phi or on z-axis
                                                   >> 250           in=kSurface;
                                                   >> 251       }
                                                   >> 252         else
                                                   >> 253       {
                                                   >> 254 // Try outer tolerant phi boundaries
                                                   >> 255           pPhi=atan2(p.y(),p.x());
                                                   >> 256           if (pPhi<0) pPhi+=2*M_PI;   // 0<=pPhi<2pi
                                                   >> 257           if (fSPhi>=0)
                                                   >> 258         {
                                                   >> 259             if (pPhi>=fSPhi-kAngTolerance/2 &&
                                                   >> 260           pPhi<=fSPhi+fDPhi+kAngTolerance/2)
                                                   >> 261           {
                                                   >> 262               in=kSurface;
                                                   >> 263           }
                                                   >> 264         }
                                                   >> 265           else
                                                   >> 266         {
                                                   >> 267             if (pPhi<fSPhi+2*M_PI) pPhi+=2*M_PI;
                                                   >> 268             if (pPhi>=fSPhi+2*M_PI-kAngTolerance/2 &&
                                                   >> 269           pPhi<=fSPhi+fDPhi+2*M_PI+kAngTolerance/2)
                                                   >> 270           {
                                                   >> 271               in=kSurface;
                                                   >> 272           }
                                                   >> 273         }
                                                   >> 274           
                                                   >> 275       }
                                                   >> 276     }
                                                   >> 277   }
                                                   >> 278     return in;
229 }                                                 279 }
230                                                   280 
231 //////////////////////////////////////////////    281 /////////////////////////////////////////////////////////////////////////
232 //                                                282 //
233 // Dispatch to parameterisation for replicatio    283 // Dispatch to parameterisation for replication mechanism dimension
234 // computation & modification.                    284 // computation & modification.
235                                                   285 
236 void G4Cons::ComputeDimensions(      G4VPVPara << 286 void G4Cons::ComputeDimensions(G4VPVParameterisation* p,
237                                const G4int     << 287                               const G4int n,
238                                const G4VPhysic << 288                               const G4VPhysicalVolume* pRep)
239 {                                                 289 {
240   p->ComputeDimensions(*this,n,pRep) ;         << 290     p->ComputeDimensions(*this,n,pRep);
241 }                                                 291 }
242                                                   292 
243 ////////////////////////////////////////////// << 
244 //                                             << 
245 // Get bounding box                            << 
246                                                   293 
247 void G4Cons::BoundingLimits(G4ThreeVector& pMi << 294 ///////////////////////////////////////////////////////////////////////////
248 {                                              << 
249   G4double rmin = std::min(GetInnerRadiusMinus << 
250   G4double rmax = std::max(GetOuterRadiusMinus << 
251   G4double dz   = GetZHalfLength();            << 
252                                                << 
253   // Find bounding box                         << 
254   //                                           << 
255   if (GetDeltaPhiAngle() < twopi)              << 
256   {                                            << 
257     G4TwoVector vmin,vmax;                     << 
258     G4GeomTools::DiskExtent(rmin,rmax,         << 
259                             GetSinStartPhi(),G << 
260                             GetSinEndPhi(),Get << 
261                             vmin,vmax);        << 
262     pMin.set(vmin.x(),vmin.y(),-dz);           << 
263     pMax.set(vmax.x(),vmax.y(), dz);           << 
264   }                                            << 
265   else                                         << 
266   {                                            << 
267     pMin.set(-rmax,-rmax,-dz);                 << 
268     pMax.set( rmax, rmax, dz);                 << 
269   }                                            << 
270                                                << 
271   // Check correctness of the bounding box     << 
272   //                                           << 
273   if (pMin.x() >= pMax.x() || pMin.y() >= pMax << 
274   {                                            << 
275     std::ostringstream message;                << 
276     message << "Bad bounding box (min >= max)  << 
277             << GetName() << " !"               << 
278             << "\npMin = " << pMin             << 
279             << "\npMax = " << pMax;            << 
280     G4Exception("G4Cons::BoundingLimits()", "G << 
281                 JustWarning, message);         << 
282     DumpInfo();                                << 
283   }                                            << 
284 }                                              << 
285                                                << 
286 ////////////////////////////////////////////// << 
287 //                                                295 //
288 // Calculate extent under transform and specif    296 // Calculate extent under transform and specified limit
289                                                   297 
290 G4bool G4Cons::CalculateExtent( const EAxis    << 298 G4bool G4Cons::CalculateExtent(const EAxis pAxis,
291                                 const G4VoxelL << 299              const G4VoxelLimits& pVoxelLimit,
292                                 const G4Affine << 300              const G4AffineTransform& pTransform,
293                                       G4double << 301              G4double& pMin,
294                                       G4double << 302              G4double& pMax) const
295 {                                                 303 {
296   G4ThreeVector bmin, bmax;                    << 304     if (!pTransform.IsRotated() && fDPhi==2.0*M_PI && fRmin1==0 && fRmin2==0)
297   G4bool exist;                                << 305   {
298                                                << 306 // Special case handling for unrotated solid cones
299   // Get bounding box                          << 307 // Compute z/x/y mins and maxs for bounding box respecting limits,
300   BoundingLimits(bmin,bmax);                   << 308 // with early returns if outside limits. Then switch() on pAxis,
301                                                << 309 // and compute exact x and y limit for x/y case
302   // Check bounding box                        << 310       
303   G4BoundingEnvelope bbox(bmin,bmax);          << 311       G4double xoffset,xMin,xMax;
304 #ifdef G4BBOX_EXTENT                           << 312       G4double yoffset,yMin,yMax;
305   if (true) return bbox.CalculateExtent(pAxis, << 313       G4double zoffset,zMin,zMax;
306 #endif                                         << 314 
307   if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox << 315       G4double diff1,diff2,maxDiff,newMin,newMax;
308   {                                            << 316       G4double xoff1,xoff2,yoff1,yoff2;
309     return exist = pMin < pMax;                << 317       
310   }                                            << 318       zoffset=pTransform.NetTranslation().z();
311                                                << 319       zMin=zoffset-fDz;
312   // Get parameters of the solid               << 320       zMax=zoffset+fDz;
313   G4double rmin1 = GetInnerRadiusMinusZ();     << 321       if (pVoxelLimit.IsZLimited())
314   G4double rmax1 = GetOuterRadiusMinusZ();     << 322     {
315   G4double rmin2 = GetInnerRadiusPlusZ();      << 323         if (zMin > pVoxelLimit.GetMaxZExtent()+kCarTolerance
316   G4double rmax2 = GetOuterRadiusPlusZ();      << 324       || zMax < pVoxelLimit.GetMinZExtent()-kCarTolerance)
317   G4double dz    = GetZHalfLength();           << 325       {
318   G4double dphi  = GetDeltaPhiAngle();         << 326           return false;
319                                                << 327       }
320   // Find bounding envelope and calculate exte << 328         else
321   //                                           << 329       {
322   const G4int NSTEPS = 24;            // numbe << 330           if (zMin<pVoxelLimit.GetMinZExtent())
323   G4double astep  = twopi/NSTEPS;     // max a << 331         {
324   G4int    ksteps = (dphi <= astep) ? 1 : (G4i << 332             zMin=pVoxelLimit.GetMinZExtent();
325   G4double ang    = dphi/ksteps;               << 333         }
326                                                << 334           if (zMax>pVoxelLimit.GetMaxZExtent())
327   G4double sinHalf = std::sin(0.5*ang);        << 335         {
328   G4double cosHalf = std::cos(0.5*ang);        << 336             zMax=pVoxelLimit.GetMaxZExtent();
329   G4double sinStep = 2.*sinHalf*cosHalf;       << 337         }
330   G4double cosStep = 1. - 2.*sinHalf*sinHalf;  << 338       }
331   G4double rext1   = rmax1/cosHalf;            << 339     }
332   G4double rext2   = rmax2/cosHalf;            << 340 
333                                                << 341       xoffset=pTransform.NetTranslation().x() ;
334   // bounding envelope for full cone without h << 342             G4double RMax = (fRmax2 >= fRmax1) ?  zMax : zMin  ;                  
335   // in other cases it is a sequence of quadri << 343       xMax = xoffset + (fRmax1 + fRmax2)*0.5 + (RMax - zoffset)*(fRmax2 - fRmax1)/(2*fDz) ;
336   if (rmin1 == 0 && rmin2 == 0 && dphi == twop << 344       xMin = 2*xoffset-xMax ;
337   {                                            << 345       if (pVoxelLimit.IsXLimited())
338     G4double sinCur = sinHalf;                 << 346     {
339     G4double cosCur = cosHalf;                 << 347         if (xMin > pVoxelLimit.GetMaxXExtent()+kCarTolerance
340                                                << 348       || xMax < pVoxelLimit.GetMinXExtent()-kCarTolerance)
341     G4ThreeVectorList baseA(NSTEPS),baseB(NSTE << 349       {
342     for (G4int k=0; k<NSTEPS; ++k)             << 350           return false;
343     {                                          << 351       }
344       baseA[k].set(rext1*cosCur,rext1*sinCur,- << 352         else
345       baseB[k].set(rext2*cosCur,rext2*sinCur,  << 353       {
346                                                << 354           if (xMin<pVoxelLimit.GetMinXExtent())
347       G4double sinTmp = sinCur;                << 355         {
348       sinCur = sinCur*cosStep + cosCur*sinStep << 356             xMin=pVoxelLimit.GetMinXExtent();
349       cosCur = cosCur*cosStep - sinTmp*sinStep << 357         }
350     }                                          << 358           if (xMax>pVoxelLimit.GetMaxXExtent())
351     std::vector<const G4ThreeVectorList *> pol << 359         {
352     polygons[0] = &baseA;                      << 360             xMax=pVoxelLimit.GetMaxXExtent();
353     polygons[1] = &baseB;                      << 361         }
354     G4BoundingEnvelope benv(bmin,bmax,polygons << 362       }
355     exist = benv.CalculateExtent(pAxis,pVoxelL << 363     }
356   }                                            << 364 
357   else                                         << 365       yoffset=pTransform.NetTranslation().y();
358   {                                            << 366       yMax = yoffset + (fRmax1 + fRmax2)*0.5 + (RMax - zoffset)*(fRmax2 - fRmax1)/(2*fDz) ;
359     G4double sinStart = GetSinStartPhi();      << 367       yMin = 2*yoffset-yMax ;
360     G4double cosStart = GetCosStartPhi();      << 368       RMax = yMax - yoffset ;  // is equal to max radius due to Zmax/Zmin cuttings
361     G4double sinEnd   = GetSinEndPhi();        << 369       if (pVoxelLimit.IsYLimited())
362     G4double cosEnd   = GetCosEndPhi();        << 370     {
363     G4double sinCur   = sinStart*cosHalf + cos << 371         if (yMin > pVoxelLimit.GetMaxYExtent()+kCarTolerance
364     G4double cosCur   = cosStart*cosHalf - sin << 372       || yMax < pVoxelLimit.GetMinYExtent()-kCarTolerance)
365                                                << 373       {
366     // set quadrilaterals                      << 374           return false;
367     G4ThreeVectorList pols[NSTEPS+2];          << 375       }
368     for (G4int k=0; k<ksteps+2; ++k) pols[k].r << 376         else
369     pols[0][0].set(rmin2*cosStart,rmin2*sinSta << 377       {
370     pols[0][1].set(rmin1*cosStart,rmin1*sinSta << 378           if (yMin<pVoxelLimit.GetMinYExtent())
371     pols[0][2].set(rmax1*cosStart,rmax1*sinSta << 379         {
372     pols[0][3].set(rmax2*cosStart,rmax2*sinSta << 380             yMin=pVoxelLimit.GetMinYExtent();
373     for (G4int k=1; k<ksteps+1; ++k)           << 381         }
374     {                                          << 382           if (yMax>pVoxelLimit.GetMaxYExtent())
375       pols[k][0].set(rmin2*cosCur,rmin2*sinCur << 383         {
376       pols[k][1].set(rmin1*cosCur,rmin1*sinCur << 384             yMax=pVoxelLimit.GetMaxYExtent();
377       pols[k][2].set(rext1*cosCur,rext1*sinCur << 385         }
378       pols[k][3].set(rext2*cosCur,rext2*sinCur << 386       }
379                                                << 387     }
380       G4double sinTmp = sinCur;                << 388 
381       sinCur = sinCur*cosStep + cosCur*sinStep << 389 
382       cosCur = cosCur*cosStep - sinTmp*sinStep << 390 // Known to cut cones
383     }                                          << 391       
384     pols[ksteps+1][0].set(rmin2*cosEnd,rmin2*s << 392       switch (pAxis)
385     pols[ksteps+1][1].set(rmin1*cosEnd,rmin1*s << 393     {
386     pols[ksteps+1][2].set(rmax1*cosEnd,rmax1*s << 394     case kXAxis:
387     pols[ksteps+1][3].set(rmax2*cosEnd,rmax2*s << 395         yoff1=yoffset-yMin;
388                                                << 396         yoff2=yMax-yoffset;
389     // set envelope and calculate extent       << 397         if (yoff1 >= 0 && yoff2 >= 0)
390     std::vector<const G4ThreeVectorList *> pol << 398       {
391     polygons.resize(ksteps+2);                 << 399 // Y limits cross max/min x => no change
392     for (G4int k=0; k<ksteps+2; ++k) polygons[ << 400           pMin=xMin;
393     G4BoundingEnvelope benv(bmin,bmax,polygons << 401           pMax=xMax;
394     exist = benv.CalculateExtent(pAxis,pVoxelL << 402       }
395   }                                            << 403         else
396   return exist;                                << 404       {
                                                   >> 405 // Y limits don't cross max/min x => compute max delta x, hence new mins/maxs
                                                   >> 406          
                                                   >> 407           diff1=sqrt(RMax*RMax-yoff1*yoff1);
                                                   >> 408           diff2=sqrt(RMax*RMax-yoff2*yoff2);
                                                   >> 409           maxDiff=(diff1>diff2) ? diff1:diff2;
                                                   >> 410           newMin=xoffset-maxDiff;
                                                   >> 411           newMax=xoffset+maxDiff;
                                                   >> 412           pMin=(newMin<xMin) ? xMin : newMin ;
                                                   >> 413           pMax=(newMax>xMax) ? xMax : newMax ;
                                                   >> 414       }
                                                   >> 415       
                                                   >> 416         break;
                                                   >> 417     case kYAxis:
                                                   >> 418         xoff1=xoffset-xMin;
                                                   >> 419         xoff2=xMax-xoffset;
                                                   >> 420         if (xoff1>=0&&xoff2>=0)
                                                   >> 421       {
                                                   >> 422 // X limits cross max/min y => no change
                                                   >> 423           pMin=yMin;
                                                   >> 424           pMax=yMax;
                                                   >> 425       }
                                                   >> 426         else
                                                   >> 427       {
                                                   >> 428 // X limits don't cross max/min y => compute max delta y, hence new mins/maxs
                                                   >> 429           diff1=sqrt(RMax*RMax-xoff1*xoff1);
                                                   >> 430           diff2=sqrt(RMax*RMax-xoff2*xoff2);
                                                   >> 431           maxDiff=(diff1>diff2) ? diff1:diff2;
                                                   >> 432           newMin=yoffset-maxDiff;
                                                   >> 433           newMax=yoffset+maxDiff;
                                                   >> 434           pMin=(newMin<yMin) ? yMin : newMin;
                                                   >> 435           pMax=(newMax>yMax) ? yMax : newMax;
                                                   >> 436       }
                                                   >> 437         break;
                                                   >> 438     case kZAxis:
                                                   >> 439         pMin=zMin;
                                                   >> 440         pMax=zMax;
                                                   >> 441         break;
                                                   >> 442     }
                                                   >> 443 
                                                   >> 444       pMin-=kCarTolerance;
                                                   >> 445       pMax+=kCarTolerance;
                                                   >> 446 
                                                   >> 447       return true;
                                                   >> 448       
                                                   >> 449   }
                                                   >> 450     else
                                                   >> 451   {
                                                   >> 452       G4int i,noEntries,noBetweenSections4;
                                                   >> 453       G4bool existsAfterClip=false;
                                                   >> 454 
                                                   >> 455 // Calculate rotated vertex coordinates
                                                   >> 456       G4ThreeVectorList *vertices;
                                                   >> 457 
                                                   >> 458       vertices=CreateRotatedVertices(pTransform);
                                                   >> 459 
                                                   >> 460       pMin=+kInfinity;
                                                   >> 461       pMax=-kInfinity;
                                                   >> 462 
                                                   >> 463       noEntries=vertices->entries();
                                                   >> 464       noBetweenSections4=noEntries-4;
                                                   >> 465       
                                                   >> 466       for (i=0;i<noEntries;i+=4)
                                                   >> 467     {
                                                   >> 468         ClipCrossSection(vertices,i,pVoxelLimit,pAxis,pMin,pMax);
                                                   >> 469     }
                                                   >> 470       
                                                   >> 471       for (i=0;i<noBetweenSections4;i+=4)
                                                   >> 472     {
                                                   >> 473         ClipBetweenSections(vertices,i,pVoxelLimit,pAxis,pMin,pMax);
                                                   >> 474     }
                                                   >> 475       
                                                   >> 476       if (pMin!=kInfinity||pMax!=-kInfinity)
                                                   >> 477     {
                                                   >> 478         existsAfterClip=true;
                                                   >> 479         
                                                   >> 480 // Add 2*tolerance to avoid precision troubles
                                                   >> 481         pMin-=kCarTolerance;
                                                   >> 482         pMax+=kCarTolerance;
                                                   >> 483 
                                                   >> 484     }
                                                   >> 485       else
                                                   >> 486     {
                                                   >> 487 // Check for case where completely enveloping clipping volume
                                                   >> 488 // If point inside then we are confident that the solid completely
                                                   >> 489 // envelopes the clipping volume. Hence set min/max extents according
                                                   >> 490 // to clipping volume extents along the specified axis.
                                                   >> 491        
                                                   >> 492         G4ThreeVector clipCentre(
                                                   >> 493       (pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
                                                   >> 494       (pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
                                                   >> 495       (pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5);
                                                   >> 496         
                                                   >> 497         if (Inside(pTransform.Inverse().TransformPoint(clipCentre))!=kOutside)
                                                   >> 498       {
                                                   >> 499           existsAfterClip=true;
                                                   >> 500           pMin=pVoxelLimit.GetMinExtent(pAxis);
                                                   >> 501           pMax=pVoxelLimit.GetMaxExtent(pAxis);
                                                   >> 502       }
                                                   >> 503     }
                                                   >> 504       delete vertices;
                                                   >> 505       return existsAfterClip;
                                                   >> 506   }
397 }                                                 507 }
398                                                   508 
399 //////////////////////////////////////////////    509 ////////////////////////////////////////////////////////////////////////
400 //                                                510 //
401 // Return unit normal of surface closest to p     511 // Return unit normal of surface closest to p
402 // - note if point on z axis, ignore phi divid    512 // - note if point on z axis, ignore phi divided sides
403 // - unsafe if point close to z axis a rmin=0     513 // - unsafe if point close to z axis a rmin=0 - no explicit checks
404                                                   514 
405 G4ThreeVector G4Cons::SurfaceNormal( const G4T    515 G4ThreeVector G4Cons::SurfaceNormal( const G4ThreeVector& p) const
406 {                                                 516 {
407   G4int noSurfaces = 0;                        << 517     ENorm side;
408   G4double rho, pPhi;                          << 518     G4ThreeVector norm;
409   G4double distZ, distRMin, distRMax;          << 519     G4double rho,phi;
410   G4double distSPhi = kInfinity, distEPhi = kI << 520     G4double distZ,distRMin,distRMax,distSPhi,distEPhi,distMin;
411   G4double tanRMin, secRMin, pRMin, widRMin;   << 521     G4double tanRMin,secRMin,pRMin,widRMin;
412   G4double tanRMax, secRMax, pRMax, widRMax;   << 522     G4double tanRMax,secRMax,pRMax,widRMax;
413                                                << 523 
414   G4ThreeVector norm, sumnorm(0.,0.,0.), nZ =  << 524     distZ=fabs(fabs(p.z())-fDz);
415   G4ThreeVector nR, nr(0.,0.,0.), nPs, nPe;    << 525 
416                                                << 526     rho=sqrt(p.x()*p.x()+p.y()*p.y());
417   distZ = std::fabs(std::fabs(p.z()) - fDz);   << 527 
418   rho   = std::sqrt(p.x()*p.x() + p.y()*p.y()) << 528     tanRMin=(fRmin2-fRmin1)*0.5/fDz;
419                                                << 529     secRMin=sqrt(1+tanRMin*tanRMin);
420   tanRMin  = (fRmin2 - fRmin1)*0.5/fDz;        << 530     pRMin=rho-p.z()*tanRMin;
421   secRMin  = std::sqrt(1 + tanRMin*tanRMin);   << 531     widRMin=fRmin2-fDz*tanRMin;
422   pRMin    = rho - p.z()*tanRMin;              << 532     distRMin=fabs(pRMin-widRMin)/secRMin;
423   widRMin  = fRmin2 - fDz*tanRMin;             << 533 
424   distRMin = std::fabs(pRMin - widRMin)/secRMi << 534     tanRMax=(fRmax2-fRmax1)*0.5/fDz;
425                                                << 535     secRMax=sqrt(1+tanRMax*tanRMax);
426   tanRMax  = (fRmax2 - fRmax1)*0.5/fDz;        << 536     pRMax=rho-p.z()*tanRMax;
427   secRMax  = std::sqrt(1+tanRMax*tanRMax);     << 537     widRMax=fRmax2-fDz*tanRMax;
428   pRMax    = rho - p.z()*tanRMax;              << 538     distRMax=fabs(pRMax-widRMax)/secRMax;
429   widRMax  = fRmax2 - fDz*tanRMax;             << 539 
430   distRMax = std::fabs(pRMax - widRMax)/secRMa << 540 
431                                                << 541 // First minimum
432   if (!fPhiFullCone)   // Protected against (0 << 542     if (distRMin<distRMax)
433   {                                            << 543   {
434     if ( rho != 0.0 )                          << 544       if (distZ<distRMin)
435     {                                          << 545     {
436       pPhi = std::atan2(p.y(),p.x());          << 546         distMin=distZ;
437                                                << 547         side=kNZ;
438       if (pPhi  < fSPhi-halfCarTolerance)      << 548     }
439       else if (pPhi > fSPhi+fDPhi+halfCarToler << 549       else
440                                                << 550     {
441       distSPhi = std::fabs( pPhi - fSPhi );    << 551         distMin=distRMin;
442       distEPhi = std::fabs( pPhi - fSPhi - fDP << 552         side=kNRMin;
443     }                                          << 553     }
444     else if( ((fRmin1) == 0.0) || ((fRmin2) == << 554   }
445     {                                          << 
446       distSPhi = 0.;                           << 
447       distEPhi = 0.;                           << 
448     }                                          << 
449     nPs = G4ThreeVector( sinSPhi, -cosSPhi, 0  << 
450     nPe = G4ThreeVector( -sinEPhi, cosEPhi, 0  << 
451   }                                            << 
452   if ( rho > halfCarTolerance )                << 
453   {                                            << 
454     nR = G4ThreeVector(p.x()/rho/secRMax, p.y( << 
455     if ((fRmin1 != 0.0) || (fRmin2 != 0.0))    << 
456     {                                          << 
457       nr = G4ThreeVector(-p.x()/rho/secRMin,-p << 
458     }                                          << 
459   }                                            << 
460                                                << 
461   if( distRMax <= halfCarTolerance )           << 
462   {                                            << 
463     ++noSurfaces;                              << 
464     sumnorm += nR;                             << 
465   }                                            << 
466   if( ((fRmin1 != 0.0) || (fRmin2 != 0.0)) &&  << 
467   {                                            << 
468     ++noSurfaces;                              << 
469     sumnorm += nr;                             << 
470   }                                            << 
471   if( !fPhiFullCone )                          << 
472   {                                            << 
473     if (distSPhi <= halfAngTolerance)          << 
474     {                                          << 
475       ++noSurfaces;                            << 
476       sumnorm += nPs;                          << 
477     }                                          << 
478     if (distEPhi <= halfAngTolerance)          << 
479     {                                          << 
480       ++noSurfaces;                            << 
481       sumnorm += nPe;                          << 
482     }                                          << 
483   }                                            << 
484   if (distZ <= halfCarTolerance)               << 
485   {                                            << 
486     ++noSurfaces;                              << 
487     if ( p.z() >= 0.)  { sumnorm += nZ; }      << 
488     else               { sumnorm -= nZ; }      << 
489   }                                            << 
490   if ( noSurfaces == 0 )                       << 
491   {                                            << 
492 #ifdef G4CSGDEBUG                              << 
493     G4Exception("G4Cons::SurfaceNormal(p)", "G << 
494                 JustWarning, "Point p is not o << 
495 #endif                                         << 
496      norm = ApproxSurfaceNormal(p);            << 
497   }                                            << 
498   else if ( noSurfaces == 1 )  { norm = sumnor << 
499   else                         { norm = sumnor << 
500                                                << 
501   return norm ;                                << 
502 }                                              << 
503                                                << 
504 ////////////////////////////////////////////// << 
505 //                                             << 
506 // Algorithm for SurfaceNormal() following the << 
507 // for points not on the surface               << 
508                                                << 
509 G4ThreeVector G4Cons::ApproxSurfaceNormal( con << 
510 {                                              << 
511   ENorm side ;                                 << 
512   G4ThreeVector norm ;                         << 
513   G4double rho, phi ;                          << 
514   G4double distZ, distRMin, distRMax, distSPhi << 
515   G4double tanRMin, secRMin, pRMin, widRMin ;  << 
516   G4double tanRMax, secRMax, pRMax, widRMax ;  << 
517                                                << 
518   distZ = std::fabs(std::fabs(p.z()) - fDz) ;  << 
519   rho   = std::sqrt(p.x()*p.x() + p.y()*p.y()) << 
520                                                << 
521   tanRMin  = (fRmin2 - fRmin1)*0.5/fDz ;       << 
522   secRMin  = std::sqrt(1 + tanRMin*tanRMin) ;  << 
523   pRMin    = rho - p.z()*tanRMin ;             << 
524   widRMin  = fRmin2 - fDz*tanRMin ;            << 
525   distRMin = std::fabs(pRMin - widRMin)/secRMi << 
526                                                << 
527   tanRMax  = (fRmax2 - fRmax1)*0.5/fDz ;       << 
528   secRMax  = std::sqrt(1+tanRMax*tanRMax) ;    << 
529   pRMax    = rho - p.z()*tanRMax ;             << 
530   widRMax  = fRmax2 - fDz*tanRMax ;            << 
531   distRMax = std::fabs(pRMax - widRMax)/secRMa << 
532                                                << 
533   if (distRMin < distRMax)  // First minimum   << 
534   {                                            << 
535     if (distZ < distRMin)                      << 
536     {                                          << 
537       distMin = distZ ;                        << 
538       side    = kNZ ;                          << 
539     }                                          << 
540     else                                          555     else
541     {                                          << 556   {
542       distMin = distRMin ;                     << 557       if (distZ<distRMax)
543       side    = kNRMin ;                       << 558     {
544     }                                          << 559         distMin=distZ;
545   }                                            << 560         side=kNZ;
546   else                                         << 561     }
547   {                                            << 562       else
548     if (distZ < distRMax)                      << 563     {
549     {                                          << 564         distMin=distRMax;
550       distMin = distZ ;                        << 565         side=kNRMax;
551       side    = kNZ ;                          << 566     }
552     }                                          << 567   }
553     else                                       << 568     
554     {                                          << 569     if (fDPhi<2.0*M_PI&&rho)
555       distMin = distRMax ;                     << 570   {
556       side    = kNRMax ;                       << 571 // Protected against (0,0,z) (above)
557     }                                          << 572       phi=atan2(p.y(),p.x());
558   }                                            << 573       if (phi<0) phi+=2*M_PI;
559   if ( !fPhiFullCone && (rho != 0.0) )  // Pro << 574       if (fSPhi<0)
560   {                                            << 575     {
561     phi = std::atan2(p.y(),p.x()) ;            << 576         distSPhi=fabs(phi-(fSPhi+2.0*M_PI))*rho;
562                                                << 577     }
563     if (phi < 0)  { phi += twopi; }            << 578       else
564                                                << 579     {
565     if (fSPhi < 0)  { distSPhi = std::fabs(phi << 580         distSPhi=fabs(phi-fSPhi)*rho;
566     else            { distSPhi = std::fabs(phi << 581     }
567                                                << 582 
568     distEPhi = std::fabs(phi - fSPhi - fDPhi)* << 583       distEPhi=fabs(phi-fSPhi-fDPhi)*rho;
569                                                << 584 
570     // Find new minimum                        << 585 // Find new minimum
                                                   >> 586       if (distSPhi<distEPhi)
                                                   >> 587     {
                                                   >> 588         if (distSPhi<distMin)
                                                   >> 589       {
                                                   >> 590           side=kNSPhi;
                                                   >> 591       }
                                                   >> 592     }
                                                   >> 593       else
                                                   >> 594     {
                                                   >> 595         if (distEPhi<distMin)
                                                   >> 596       {
                                                   >> 597           side=kNEPhi;
                                                   >> 598       }
                                                   >> 599     }
                                                   >> 600   }
                                                   >> 601     
                                                   >> 602     
                                                   >> 603     switch (side)
                                                   >> 604   {
                                                   >> 605   case kNRMin:      // Inner radius
                                                   >> 606       rho*=secRMin;
                                                   >> 607       norm=G4ThreeVector(-p.x()/rho,-p.y()/rho,tanRMin/secRMin);
                                                   >> 608       break;
                                                   >> 609   case kNRMax:      // Outer radius
                                                   >> 610       rho*=secRMax;
                                                   >> 611       norm=G4ThreeVector(p.x()/rho,p.y()/rho,-tanRMax/secRMax);
                                                   >> 612       break;
                                                   >> 613   case kNZ:     // +/- dz
                                                   >> 614       if (p.z()>0)
                                                   >> 615     { norm=G4ThreeVector(0,0,1); }
                                                   >> 616       else
                                                   >> 617     { norm=G4ThreeVector(0,0,-1); }
                                                   >> 618       break;
                                                   >> 619   case kNSPhi:
                                                   >> 620       norm=G4ThreeVector(sin(fSPhi),-cos(fSPhi),0);
                                                   >> 621       break;
                                                   >> 622   case kNEPhi:
                                                   >> 623       norm=G4ThreeVector(-sin(fSPhi+fDPhi),cos(fSPhi+fDPhi),0);
                                                   >> 624       break;
                                                   >> 625   default:
                                                   >> 626       G4Exception("Logic error in G4Cons::SurfaceNormal");
                                                   >> 627       break;
                                                   >> 628       
                                                   >> 629   } // end case
571                                                   630 
572     if (distSPhi < distEPhi)                   << 631     return norm;
573     {                                          << 
574       if (distSPhi < distMin)  { side = kNSPhi << 
575     }                                          << 
576     else                                       << 
577     {                                          << 
578       if (distEPhi < distMin)  { side = kNEPhi << 
579     }                                          << 
580   }                                            << 
581   switch (side)                                << 
582   {                                            << 
583     case kNRMin:      // Inner radius          << 
584     {                                          << 
585       rho *= secRMin ;                         << 
586       norm = G4ThreeVector(-p.x()/rho, -p.y()/ << 
587       break ;                                  << 
588     }                                          << 
589     case kNRMax:      // Outer radius          << 
590     {                                          << 
591       rho *= secRMax ;                         << 
592       norm = G4ThreeVector(p.x()/rho, p.y()/rh << 
593       break ;                                  << 
594     }                                          << 
595     case kNZ:         // +/- dz                << 
596     {                                          << 
597       if (p.z() > 0)  { norm = G4ThreeVector(0 << 
598       else            { norm = G4ThreeVector(0 << 
599       break ;                                  << 
600     }                                          << 
601     case kNSPhi:                               << 
602     {                                          << 
603       norm = G4ThreeVector(sinSPhi, -cosSPhi,  << 
604       break ;                                  << 
605     }                                          << 
606     case kNEPhi:                               << 
607     {                                          << 
608       norm = G4ThreeVector(-sinEPhi, cosEPhi,  << 
609       break ;                                  << 
610     }                                          << 
611     default:          // Should never reach th << 
612     {                                          << 
613       DumpInfo();                              << 
614       G4Exception("G4Cons::ApproxSurfaceNormal << 
615                   "GeomSolids1002", JustWarnin << 
616                   "Undefined side for valid su << 
617       break ;                                  << 
618     }                                          << 
619   }                                            << 
620   return norm ;                                << 
621 }                                                 632 }
622                                                   633 
623 //////////////////////////////////////////////    634 ////////////////////////////////////////////////////////////////////////
624 //                                                635 //
625 // Calculate distance to shape from outside, a    636 // Calculate distance to shape from outside, along normalised vector
626 // - return kInfinity if no intersection, or i    637 // - return kInfinity if no intersection, or intersection distance <= tolerance
627 //                                                638 //
628 // - Compute the intersection with the z plane    639 // - Compute the intersection with the z planes 
629 //        - if at valid r, phi, return            640 //        - if at valid r, phi, return
630 //                                                641 //
631 // -> If point is outside cone, compute inters << 642 // -> If point is outside cone, compute intersection with rmax1/2
632 //        - if at valid phi,z return              643 //        - if at valid phi,z return
633 //        - if inside outer cone, handle case     644 //        - if inside outer cone, handle case when on tolerant outer cone
634 //          boundary and heading inwards(->0 t    645 //          boundary and heading inwards(->0 to in)
635 //                                                646 //
636 // -> Compute intersection with inner cone, ta    647 // -> Compute intersection with inner cone, taking largest +ve root
637 //        - if valid (in z,phi), save intersct    648 //        - if valid (in z,phi), save intersction
638 //                                                649 //
639 //    -> If phi segmented, compute intersectio    650 //    -> If phi segmented, compute intersections with phi half planes
640 //        - return smallest of valid phi inter    651 //        - return smallest of valid phi intersections and
641 //          inner radius intersection             652 //          inner radius intersection
642 //                                                653 //
643 // NOTE:                                          654 // NOTE:
                                                   >> 655 // - Precalculations for phi trigonometry are Done `just in time'
644 // - `if valid' implies tolerant checking of i    656 // - `if valid' implies tolerant checking of intersection points
645 // - z, phi intersection from Tubs                657 // - z, phi intersection from Tubs
646                                                   658 
647 G4double G4Cons::DistanceToIn( const G4ThreeVe << 659 G4double G4Cons::DistanceToIn(const G4ThreeVector& p,
648                                const G4ThreeVe << 660             const G4ThreeVector& v) const
649 {                                                 661 {
650   G4double snxt = kInfinity ;      // snxt = d << 662     G4double snxt=kInfinity;      // snxt = default return value
651   const G4double dRmax = 50*(fRmax1+fRmax2);// << 
652                                                   663 
653   G4double tanRMax,secRMax,rMaxAv,rMaxOAv ;  / << 664     G4bool seg;       // true if segmented in phi
654   G4double tanRMin,secRMin,rMinAv,rMinOAv ;    << 665     G4double hDPhi,hDPhiOT,hDPhiIT,cosHDPhiOT,cosHDPhiIT;
655   G4double rout,rin ;                          << 666           // half dphi + outer tolerance
656                                                << 667     G4double cPhi,sinCPhi,cosCPhi;  // central phi
657   G4double tolORMin,tolORMin2,tolIRMin,tolIRMi << 668 
658   G4double tolORMax2,tolIRMax,tolIRMax2 ;      << 669     G4double tanRMax,secRMax,rMaxAv,rMaxOAv;  // Data for cones
659   G4double tolODz,tolIDz ;                     << 670     G4double tanRMin,secRMin,rMinAv,rMinIAv,rMinOAv;
660                                                << 671     G4double rout,rin;
661   G4double Dist,sd,xi,yi,zi,ri=0.,risec,rhoi2, << 672 
662                                                << 673     G4double tolORMin,tolORMin2;  // `generous' radii squared
663   G4double t1,t2,t3,b,c,d ;    // Quadratic so << 674     G4double tolORMax2;
664   G4double nt1,nt2,nt3 ;                       << 675     G4double tolODz,tolIDz;
665   G4double Comp ;                              << 676 
666                                                << 677     G4double Dist,s,xi,yi,zi,ri,rho2,cosPsi; // Intersection point variables
667   G4ThreeVector Normal;                        << 678 
668                                                << 679     G4double t1,t2,t3,b,c,d;    // Quadratic solver variables 
669   // Cone Precalcs                             << 680     G4double nt1,nt2,nt3;
670                                                << 681     G4double Comp;
671   tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;        << 682     G4double cosSPhi,sinSPhi;   // Trig for phi start intersect
672   secRMin = std::sqrt(1.0 + tanRMin*tanRMin) ; << 683     G4double ePhi,cosEPhi,sinEPhi;  // for phi end intersect
673   rMinAv  = (fRmin1 + fRmin2)*0.5 ;            << 684 
674                                                << 685 //
675   if (rMinAv > halfRadTolerance)               << 686 // Set phi divided flag and precalcs
676   {                                            << 687 //
677     rMinOAv = rMinAv - halfRadTolerance ;      << 688     if (fDPhi<2.0*M_PI)
678   }                                            << 689   {
679   else                                         << 690       seg=true;
680   {                                            << 691       hDPhi=0.5*fDPhi;    // half delta phi
681     rMinOAv = 0.0 ;                            << 692       cPhi=fSPhi+hDPhi;;
682   }                                            << 693       hDPhiOT=hDPhi+0.5*kAngTolerance;  // outers tol' half delta phi 
683   tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;        << 694       hDPhiIT=hDPhi-0.5*kAngTolerance;
684   secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ; << 695       sinCPhi=sin(cPhi);
685   rMaxAv  = (fRmax1 + fRmax2)*0.5 ;            << 696       cosCPhi=cos(cPhi);
686   rMaxOAv = rMaxAv + halfRadTolerance ;        << 697       cosHDPhiOT=cos(hDPhiOT);
687                                                << 698       cosHDPhiIT=cos(hDPhiIT);
688   // Intersection with z-surfaces              << 699   }
689                                                << 700     else
690   tolIDz = fDz - halfCarTolerance ;            << 701   {
691   tolODz = fDz + halfCarTolerance ;            << 702       seg=false;
                                                   >> 703   }
692                                                   704 
693   if (std::fabs(p.z()) >= tolIDz)              << 705 //
694   {                                            << 706 // Cone Precalcs
695     if ( p.z()*v.z() < 0 )    // at +Z going i << 707 //
696     {                                          << 708     tanRMin=(fRmin2-fRmin1)*0.5/fDz;
697       sd = (std::fabs(p.z()) - fDz)/std::fabs( << 709     secRMin=sqrt(1.0+tanRMin*tanRMin);
                                                   >> 710     rMinAv=(fRmin1+fRmin2)*0.5;
                                                   >> 711     if (rMinAv>kRadTolerance/2)
                                                   >> 712   {
                                                   >> 713       rMinOAv=rMinAv-kRadTolerance/2;
                                                   >> 714       rMinIAv=rMinAv+kRadTolerance/2;
                                                   >> 715   }
                                                   >> 716     else
                                                   >> 717   {
                                                   >> 718       rMinOAv=0;
                                                   >> 719       rMinIAv=0;
                                                   >> 720   }
698                                                   721 
699       if( sd < 0.0 )  { sd = 0.0; }            << 722     
                                                   >> 723     tanRMax=(fRmax2-fRmax1)*0.5/fDz;
                                                   >> 724     secRMax=sqrt(1.0+tanRMax*tanRMax);
                                                   >> 725     rMaxAv=(fRmax1+fRmax2)*0.5;
700                                                   726 
701       xi   = p.x() + sd*v.x() ;  // Intersecti << 727     rMaxOAv=rMaxAv+kRadTolerance/2;
702       yi   = p.y() + sd*v.y() ;                << 728    
703       rhoi2 = xi*xi + yi*yi  ;                 << 729 //
704                                                << 730 // Intersection with Z surfaces
705       // Check validity of intersection        << 731 //
706       // Calculate (outer) tolerant radi^2 at  << 732     tolIDz=fDz-kCarTolerance/2;
707                                                << 733     tolODz=fDz+kCarTolerance/2;
708       if (v.z() > 0)                           << 734     if (fabs(p.z())>=tolIDz)
709       {                                        << 735     {
710         tolORMin  = fRmin1 - halfRadTolerance* << 736        if (p.z()*v.z()<0)   // at +Z going in -Z or visa versa
711         tolIRMin  = fRmin1 + halfRadTolerance* << 737        {
712         tolIRMax  = fRmax1 - halfRadTolerance* << 738     s=(fabs(p.z())-fDz)/fabs(v.z());  // Z intersect distance
713         // tolORMax2 = (fRmax1 + halfRadTolera << 739 
714         //             (fRmax1 + halfRadTolera << 740           if(s<0.0) s = 0.0 ;                  // negative dist -> zero
715       }                                        << 741 
716       else                                     << 742     xi=p.x()+s*v.x(); // Intersection coords
717       {                                        << 743     yi=p.y()+s*v.y();
718         tolORMin  = fRmin2 - halfRadTolerance* << 744     rho2=xi*xi+yi*yi;
719         tolIRMin  = fRmin2 + halfRadTolerance* << 745 
720         tolIRMax  = fRmax2 - halfRadTolerance* << 746           // Check validity of intersection
721         // tolORMax2 = (fRmax2 + halfRadTolera << 747     //
722         //             (fRmax2 + halfRadTolera << 748           // Calculate (outer) tolerant radi^2 at intersecion
723       }                                        << 749 
724       if ( tolORMin > 0 )                      << 750     if (v.z()>0)
725       {                                        << 751     {
726         // tolORMin2 = tolORMin*tolORMin ;     << 752        tolORMin=fRmin1-kRadTolerance;
727         tolIRMin2 = tolIRMin*tolIRMin ;        << 753        tolORMax2=(fRmax1+kRadTolerance)*(fRmax1+kRadTolerance);
728       }                                        << 754     }
729       else                                     << 755     else
730       {                                        << 756     {
731         // tolORMin2 = 0.0 ;                   << 757        tolORMin=fRmin2-kRadTolerance;
732         tolIRMin2 = 0.0 ;                      << 758        tolORMax2=(fRmax2+kRadTolerance)*(fRmax2+kRadTolerance);
733       }                                        << 759     }
734       if ( tolIRMax > 0 )  { tolIRMax2 = tolIR << 760     if ( tolORMin > 0 )
735       else                 { tolIRMax2 = 0.0;  << 761     {
736                                                << 762           tolORMin2=tolORMin*tolORMin;
737       if ( (tolIRMin2 <= rhoi2) && (rhoi2 <= t << 763     }
738       {                                        << 764     else
739         if ( !fPhiFullCone && (rhoi2 != 0.0) ) << 765     {
740         {                                      << 766        tolORMin2=0;
741           // Psi = angle made with central (av << 767     }
742                                                << 768     if (tolORMin2 <= rho2 && rho2 <= tolORMax2)
743           cosPsi = (xi*cosCPhi + yi*sinCPhi)/s << 769     {
744                                                << 770        if (seg&&rho2)
745           if (cosPsi >= cosHDPhiIT)  { return  << 771        {
746         }                                      << 772 // Psi = angle made with central (average) phi of shape
747         else                                   << 773 
748         {                                      << 774     cosPsi=(xi*cosCPhi+yi*sinCPhi)/sqrt(rho2);
749           return sd;                           << 775 
750         }                                      << 776     if (cosPsi >= cosHDPhiOT)
751       }                                        << 777     {
752     }                                          << 778        return s ;
753     else  // On/outside extent, and heading aw << 779     }
754     {                                          << 780        }
755       return snxt ;                            << 781        else
                                                   >> 782        {
                                                   >> 783     return s ;
                                                   >> 784        }
                                                   >> 785     }
                                                   >> 786        }
                                                   >> 787        else  // On/outside extent, and heading away  -> cannot intersect
                                                   >> 788        {
                                                   >> 789     return snxt ; 
                                                   >> 790        }
756     }                                             791     }
757   }                                            << 792     //
758                                                << 793     // -> Can not intersect z surfaces
759 // ----> Can not intersect z surfaces          << 
760                                                   794 
761                                                   795 
                                                   >> 796 
                                                   >> 797 //
762 // Intersection with outer cone (possible retu    798 // Intersection with outer cone (possible return) and
763 //                   inner cone (must also che    799 //                   inner cone (must also check phi)
764 //                                                800 //
                                                   >> 801 
765 // Intersection point (xi,yi,zi) on line x=p.x    802 // Intersection point (xi,yi,zi) on line x=p.x+t*v.x etc.
766 //                                                803 //
767 // Intersects with x^2+y^2=(a*z+b)^2              804 // Intersects with x^2+y^2=(a*z+b)^2
768 //                                                805 //
769 // where a=tanRMax or tanRMin                     806 // where a=tanRMax or tanRMin
770 //       b=rMaxAv  or rMinAv                      807 //       b=rMaxAv  or rMinAv
771 //                                                808 //
772 // (vx^2+vy^2-(a*vz)^2)t^2+2t(pxvx+pyvy-a*vz(a << 809 // (vx^2+vy^2-(a*vz)^2)t^2+2t(pxvx+pyvy-a*vz(a*pz+b))+px^2+py^2-(a*pz+b)^2=0;
773 //     t1                        t2               810 //     t1                        t2                      t3  
774 //                                                811 //
775 //  \--------u-------/       \-----------v----    812 //  \--------u-------/       \-----------v----------/ \---------w--------/
776 //                                                813 //
777                                                   814 
778   t1   = 1.0 - v.z()*v.z() ;                   << 815     t1=1.0-v.z()*v.z();
779   t2   = p.x()*v.x() + p.y()*v.y() ;           << 816     t2=p.x()*v.x()+p.y()*v.y();
780   t3   = p.x()*p.x() + p.y()*p.y() ;           << 817     t3=p.x()*p.x()+p.y()*p.y();
781   rin  = tanRMin*p.z() + rMinAv ;              << 818     rin=tanRMin*p.z()+rMinAv;
782   rout = tanRMax*p.z() + rMaxAv ;              << 819     rout=tanRMax*p.z()+rMaxAv;
783                                                << 820 
784   // Outer Cone Intersection                   << 821 // Outer Cone Intersection
785   // Must be outside/on outer cone for valid i << 822 //
786                                                << 823 // Must be outside/on outer cone for valid intersection
787   nt1 = t1 - (tanRMax*v.z())*(tanRMax*v.z()) ; << 824 
788   nt2 = t2 - tanRMax*v.z()*rout ;              << 825     nt1=t1-(tanRMax*v.z())*(tanRMax*v.z());
789   nt3 = t3 - rout*rout ;                       << 826     nt2=t2-tanRMax*v.z()*rout;
790                                                << 827     nt3=t3-rout*rout;
791   if (std::fabs(nt1) > kRadTolerance)  // Equa << 828 
792   {                                            << 829 
793     b = nt2/nt1;                               << 830     if (fabs(nt1) > kRadTolerance)  // Equation quadratic => 2 roots
794     c = nt3/nt1;                               << 831     {
795     d = b*b-c  ;                               << 832        if (nt3>kRadTolerance/2||rout<0)
796     if ( (nt3 > rout*rout*kRadTolerance*kRadTo << 833        {
797       || (rout < 0) )                          << 834 // If outside real cone (should be rho-rout>kRadTolerance/2 NOT rho^2 etc)
798     {                                          << 835 //                       saves a sqrt() at expense of accuracy
799       // If outside real cone (should be rho-r << 836 
800       // NOT rho^2 etc) saves a std::sqrt() at << 837     b=nt2/nt1;
801                                                << 838     c=nt3/nt1;
802       if (d >= 0)                              << 839     d=b*b-c;
803       {                                        << 840 
804                                                << 841           if (d>=0)
805         if ((rout < 0) && (nt3 <= 0))          << 842           {
806         {                                      << 843           
807           // Inside `shadow cone' with -ve rad << 844              if (rout < 0 && nt3 <= 0 )
808           // -> 2nd root could be on real cone << 845              {
809                                                << 846 // Inside `shadow cone' with -ve radius -> 2nd root could be on real cone
810           if (b>0) { sd = c/(-b-std::sqrt(d)); << 847 
811           else     { sd = -b + std::sqrt(d);   << 848                 s = -b + sqrt(d) ;
812         }                                      << 849        }
813         else                                   << 850        else
814         {                                      << 851        {
815           if ((b <= 0) && (c >= 0)) // both >= << 852           if ( b <= 0 && c >= 0 ) // both >=0, try smaller
816           {                                    << 853           {
817             sd=c/(-b+std::sqrt(d));            << 854              s = -b - sqrt(d);
818           }                                    << 855           }
819           else                                 << 
820           {                                    << 
821             if ( c <= 0 ) // second >=0        << 
822             {                                  << 
823               sd = -b + std::sqrt(d) ;         << 
824               if((sd<0.0) && (sd>-halfRadToler << 
825             }                                  << 
826             else  // both negative, travel awa << 
827             {                                  << 
828               return kInfinity ;               << 
829             }                                  << 
830           }                                    << 
831         }                                      << 
832         if ( sd >= 0 )  // If 'forwards'. Chec << 
833         {                                      << 
834           if ( sd>dRmax ) // Avoid rounding er << 
835           {               // 64 bits systems.  << 
836             G4double fTerm = sd-std::fmod(sd,d << 
837             sd = fTerm + DistanceToIn(p+fTerm* << 
838           }                                    << 
839           zi = p.z() + sd*v.z() ;              << 
840                                                << 
841           if (std::fabs(zi) <= tolODz)         << 
842           {                                    << 
843             // Z ok. Check phi intersection if << 
844                                                << 
845             if ( fPhiFullCone )  { return sd;  << 
846             else                               << 
847             {                                  << 
848               xi     = p.x() + sd*v.x() ;      << 
849               yi     = p.y() + sd*v.y() ;      << 
850               ri     = rMaxAv + zi*tanRMax ;   << 
851               cosPsi = (xi*cosCPhi + yi*sinCPh << 
852                                                << 
853               if ( cosPsi >= cosHDPhiIT )  { r << 
854             }                                  << 
855           }                                    << 
856         }                // end if (sd>0)      << 
857       }                                        << 
858     }                                          << 
859     else                                       << 
860     {                                          << 
861       // Inside outer cone                     << 
862       // check not inside, and heading through << 
863                                                << 
864       if ( ( t3  > (rin + halfRadTolerance*sec << 
865                    (rin + halfRadTolerance*sec << 
866         && (nt2 < 0) && (d >= 0) && (std::fabs << 
867       {                                        << 
868         // Inside cones, delta r -ve, inside z << 
869         // Point is on the Surface => check Di << 
870                                                << 
871         xi     = p.x() ;                       << 
872         yi     = p.y()  ;                      << 
873         risec  = std::sqrt(xi*xi + yi*yi)*secR << 
874         Normal = G4ThreeVector(xi/risec,yi/ris << 
875         if ( !fPhiFullCone )                   << 
876         {                                      << 
877           cosPsi = (p.x()*cosCPhi + p.y()*sinC << 
878           if ( cosPsi >= cosHDPhiIT )          << 
879           {                                    << 
880             if ( Normal.dot(v) <= 0 )  { retur << 
881           }                                    << 
882         }                                      << 
883         else                                   << 
884         {                                      << 
885           if ( Normal.dot(v) <= 0 )  { return  << 
886         }                                      << 
887       }                                        << 
888     }                                          << 
889   }                                            << 
890   else  //  Single root case                   << 
891   {                                            << 
892     if ( std::fabs(nt2) > kRadTolerance )      << 
893     {                                          << 
894       sd = -0.5*nt3/nt2 ;                      << 
895                                                << 
896       if ( sd < 0 )  { return kInfinity; }   / << 
897       else  // sd >= 0,  If 'forwards'. Check  << 
898       {                                        << 
899         zi = p.z() + sd*v.z() ;                << 
900                                                << 
901         if ((std::fabs(zi) <= tolODz) && (nt2  << 
902         {                                      << 
903           // Z ok. Check phi intersection if r << 
904                                                << 
905           if ( fPhiFullCone )  { return sd; }  << 
906           else                                 << 
907           {                                    << 
908             xi     = p.x() + sd*v.x() ;        << 
909             yi     = p.y() + sd*v.y() ;        << 
910             ri     = rMaxAv + zi*tanRMax ;     << 
911             cosPsi = (xi*cosCPhi + yi*sinCPhi) << 
912                                                << 
913             if (cosPsi >= cosHDPhiIT)  { retur << 
914           }                                    << 
915         }                                      << 
916       }                                        << 
917     }                                          << 
918     else  //    travel || cone surface from it << 
919     {                                          << 
920       sd = kInfinity ;                         << 
921     }                                          << 
922   }                                            << 
923                                                << 
924   // Inner Cone Intersection                   << 
925   // o Space is divided into 3 areas:          << 
926   //   1) Radius greater than real inner cone  << 
927   //      tolerance                            << 
928   //   2) Radius less than inner or imaginary  << 
929   //   3) Within tolerance of real or imaginar << 
930   //      - Extra checks needed for 3's inters << 
931   //        => lots of duplicated code         << 
932                                                << 
933   if (rMinAv != 0.0)                           << 
934   {                                            << 
935     nt1 = t1 - (tanRMin*v.z())*(tanRMin*v.z()) << 
936     nt2 = t2 - tanRMin*v.z()*rin ;             << 
937     nt3 = t3 - rin*rin ;                       << 
938                                                << 
939     if ( nt1 != 0.0 )                          << 
940     {                                          << 
941       if ( nt3 > rin*kRadTolerance*secRMin )   << 
942       {                                        << 
943         // At radius greater than real & imagi << 
944         // -> 2nd root, with zi check          << 
945                                                << 
946         b = nt2/nt1 ;                          << 
947         c = nt3/nt1 ;                          << 
948         d = b*b-c ;                            << 
949         if (d >= 0)   // > 0                   << 
950         {                                      << 
951            if(b>0){sd = c/( -b-std::sqrt(d));} << 
952            else   {sd = -b + std::sqrt(d) ;}   << 
953                                                << 
954           if ( sd >= 0 )   // > 0              << 
955           {                                    << 
956             if ( sd>dRmax ) // Avoid rounding  << 
957             {               // 64 bits systems << 
958               G4double fTerm = sd-std::fmod(sd << 
959               sd = fTerm + DistanceToIn(p+fTer << 
960             }                                  << 
961             zi = p.z() + sd*v.z() ;            << 
962                                                << 
963             if ( std::fabs(zi) <= tolODz )     << 
964             {                                  << 
965               if ( !fPhiFullCone )             << 
966               {                                << 
967                 xi     = p.x() + sd*v.x() ;    << 
968                 yi     = p.y() + sd*v.y() ;    << 
969                 ri     = rMinAv + zi*tanRMin ; << 
970                 cosPsi = (xi*cosCPhi + yi*sinC << 
971                                                << 
972                 if (cosPsi >= cosHDPhiIT)      << 
973                 {                              << 
974                   if ( sd > halfRadTolerance ) << 
975                   else                         << 
976                   {                            << 
977                     // Calculate a normal vect << 
978                                                << 
979                     risec  = std::sqrt(xi*xi + << 
980                     Normal = G4ThreeVector(-xi << 
981                     if ( Normal.dot(v) <= 0 )  << 
982                   }                            << 
983                 }                              << 
984               }                                << 
985               else                             << 
986               {                                << 
987                 if ( sd > halfRadTolerance )   << 
988                 else                              856                 else
989                 {                              << 857           {
990                   // Calculate a normal vector << 858              if ( c <= 0 ) // second >=0
991                                                << 859              {
992                   xi     = p.x() + sd*v.x() ;  << 860                       s = -b + sqrt(d) ;
993                   yi     = p.y() + sd*v.y() ;  << 861              }
994                   risec  = std::sqrt(xi*xi + y << 862                    else  // both negative, travel away
995                   Normal = G4ThreeVector(-xi/r << 863              {
996                   if ( Normal.dot(v) <= 0 )  { << 864                       return kInfinity ;
                                                   >> 865              }
                                                   >> 866           }
                                                   >> 867        }
                                                   >> 868        if (s>0) // If 'forwards'. Check z intersection
                                                   >> 869        {
                                                   >> 870           zi=p.z()+s*v.z();
                                                   >> 871 
                                                   >> 872           if (fabs(zi)<=tolODz)
                                                   >> 873           {
                                                   >> 874 // Z ok. Check phi intersection if reqd
                                                   >> 875 
                                                   >> 876              if ( ! seg )
                                                   >> 877              {
                                                   >> 878                        return s;
                                                   >> 879                    }
                                                   >> 880              else
                                                   >> 881              {
                                                   >> 882                 xi=p.x()+s*v.x();
                                                   >> 883                 yi=p.y()+s*v.y();
                                                   >> 884                 ri=rMaxAv+zi*tanRMax;
                                                   >> 885                 cosPsi=(xi*cosCPhi + yi*sinCPhi)/ri;
                                                   >> 886 
                                                   >> 887                 if (cosPsi>=cosHDPhiOT)
                                                   >> 888                 {
                                                   >> 889                          return s;
                                                   >> 890                       }
                                                   >> 891              }
                                                   >> 892           }             
                                                   >> 893        }                // end if (s>0)
                                                   >> 894     }
                                                   >> 895        }
                                                   >> 896        else
                                                   >> 897        {
                                                   >> 898 // Inside outer cone
                                                   >> 899 // check not inside, and heading through G4Cons (-> 0 to in)
                                                   >> 900 
                                                   >> 901           if (    t3 > (rin+kRadTolerance/2)*(rin+kRadTolerance/2)
                                                   >> 902                && nt2 < 0 
                                                   >> 903                && fabs(p.z()) <= tolIDz )
                                                   >> 904           {
                                                   >> 905 // Inside cones, delta r -ve, inside z extent
                                                   >> 906 
                                                   >> 907              if (seg)
                                                   >> 908              {
                                                   >> 909           cosPsi=(p.x()*cosCPhi+p.y()*sinCPhi)/sqrt(t3);
                                                   >> 910 
                                                   >> 911           if (cosPsi>=cosHDPhiIT)
                                                   >> 912           {
                                                   >> 913              return 0;
                                                   >> 914           }
                                                   >> 915        }
                                                   >> 916        else
                                                   >> 917        {
                                                   >> 918           return 0;
                                                   >> 919        }
                                                   >> 920     }
                                                   >> 921        }
                                                   >> 922     }
                                                   >> 923     else  //  Single root case 
                                                   >> 924     {
                                                   >> 925        if ( fabs(nt2) > kRadTolerance )
                                                   >> 926        {
                                                   >> 927           s = -0.5*nt3/nt2 ;
                                                   >> 928 
                                                   >> 929           if ( s < 0 )  // travel away
                                                   >> 930     {
                                                   >> 931              return kInfinity ;
                                                   >> 932     }
                                                   >> 933           else  // s >= 0,  If 'forwards'. Check z intersection
                                                   >> 934     {
                                                   >> 935        zi=p.z()+s*v.z();
                                                   >> 936 
                                                   >> 937        if (fabs(zi)<=tolODz && nt2 < 0)
                                                   >> 938        {
                                                   >> 939 // Z ok. Check phi intersection if reqd
                                                   >> 940 
                                                   >> 941           if ( ! seg )
                                                   >> 942           {
                                                   >> 943                    return s;
997                 }                                 944                 }
998               }                                << 945           else
999             }                                  << 946           {
1000           }                                   << 947              xi=p.x()+s*v.x();
1001         }                                     << 948              yi=p.y()+s*v.y();
1002       }                                       << 949              ri=rMaxAv+zi*tanRMax;
1003       else  if ( nt3 < -rin*kRadTolerance*sec << 950              cosPsi=(xi*cosCPhi + yi*sinCPhi)/ri;
1004       {                                       << 951 
1005         // Within radius of inner cone (real  << 952              if (cosPsi>=cosHDPhiOT)
1006         // -> Try 2nd root, with checking int << 953              {
1007         // -> If check fails, try 1st root, a << 954                       return s;
1008         //    on real cone                    << 955                    }
1009                                               << 956           }
1010         b = nt2/nt1 ;                         << 957        }             
1011         c = nt3/nt1 ;                         << 958     }                
1012         d = b*b - c ;                         << 959        }
1013                                               << 960        else  //    travel || cone surface from its origin
1014         if ( d >= 0 )  // > 0                 << 961        {
1015         {                                     << 962           s = kInfinity ;
1016           if (b>0) { sd = c/(-b-std::sqrt(d)) << 963        }
1017           else     { sd = -b + std::sqrt(d);  << 964     }
1018           zi = p.z() + sd*v.z() ;             << 965 
1019           ri = rMinAv + zi*tanRMin ;          << 966 
1020                                               << 967 // Inner Cone Intersection
1021           if ( ri > 0 )                       << 968 //
1022           {                                   << 969 // o Space is divided into 3 areas:
1023             if ( (sd >= 0) && (std::fabs(zi)  << 970 //   1) Radius greater than real inner cone & imaginary cone & outside
1024             {                                 << 971 //      tolerance
1025               if ( sd>dRmax ) // Avoid roundi << 972 //   2) Radius less than inner or imaginary cone & outside tolarance
1026               {               // seen on 64 b << 973 //   3) Within tolerance of real or imaginary cones
1027                 G4double fTerm = sd-std::fmod << 974 //      - Extra checks needed for 3's intersections => lots of duplicated code
1028                 sd = fTerm + DistanceToIn(p+f << 975     if (rMinAv)
1029               }                               << 976   {
1030               if ( !fPhiFullCone )            << 977       nt1=t1-(tanRMin*v.z())*(tanRMin*v.z());
1031               {                               << 978       nt2=t2-tanRMin*v.z()*rin;
1032                 xi     = p.x() + sd*v.x() ;   << 979       nt3=t3-rin*rin; 
1033                 yi     = p.y() + sd*v.y() ;   << 980       if (nt1)
1034                 cosPsi = (xi*cosCPhi + yi*sin << 981     {
1035                                               << 982         if (nt3>kRadTolerance/2)
1036                 if (cosPsi >= cosHDPhiOT)     << 983       {
1037                 {                             << 984 // At radius greater than real & imaginary cones
1038                   if ( sd > halfRadTolerance  << 985 // -> 2nd root, with zi check
1039                   else                        << 986           b=nt2/nt1;
1040                   {                           << 987           c=nt3/nt1;
1041                     // Calculate a normal vec << 988           d=b*b-c;
1042                                               << 989           if (d>0)
1043                     risec  = std::sqrt(xi*xi  << 990         {
1044                     Normal = G4ThreeVector(-x << 991             s=-b+sqrt(d);
1045                     if ( Normal.dot(v) <= 0 ) << 992             if (s>0)
1046                   }                           << 993           {
1047                 }                             << 994               zi=p.z()+s*v.z();
1048               }                               << 995               if (fabs(zi)<=tolODz)
1049               else                            << 996             {
1050               {                               << 997                 if (seg)
1051                 if( sd > halfRadTolerance )   << 998               {
1052                 else                          << 999                   xi=p.x()+s*v.x();
1053                 {                             << 1000                   yi=p.y()+s*v.y();
1054                   // Calculate a normal vecto << 1001                   ri=rMinAv+zi*tanRMin;
1055                                               << 1002                   cosPsi=(xi*cosCPhi+
1056                   xi     = p.x() + sd*v.x() ; << 1003                     yi*sinCPhi)/ri;
1057                   yi     = p.y() + sd*v.y() ; << 1004                   if (cosPsi>=cosHDPhiOT)
1058                   risec  = std::sqrt(xi*xi +  << 1005                 { snxt=s; }
1059                   Normal = G4ThreeVector(-xi/ << 1006               }
1060                   if ( Normal.dot(v) <= 0 )   << 1007                 else
1061                 }                             << 1008               {
1062               }                               << 1009                   return s;
1063             }                                 << 1010               }
1064           }                                   << 1011             }
1065           else                                << 1012           }
1066           {                                   << 1013         }
1067             if (b>0) { sd = -b - std::sqrt(d) << 1014           
1068             else     { sd = c/(-b+std::sqrt(d << 1015       }
1069             zi = p.z() + sd*v.z() ;           << 1016         else  if (nt3<-kRadTolerance/2)
1070             ri = rMinAv + zi*tanRMin ;        << 1017       {
1071                                               << 1018 // Within radius of inner cone (real or imaginary)
1072             if ( (sd >= 0) && (ri > 0) && (st << 1019 // -> Try 2nd root, with checking intersection is with real cone
1073             {                                 << 1020 // -> If check fails, try 1st root, also checking intersection is on real cone
1074               if ( sd>dRmax ) // Avoid roundi << 1021           b=nt2/nt1;
1075               {               // seen on 64 b << 1022           c=nt3/nt1;
1076                 G4double fTerm = sd-std::fmod << 1023           d=b*b-c;
1077                 sd = fTerm + DistanceToIn(p+f << 1024           if (d>0)
1078               }                               << 1025         {
1079               if ( !fPhiFullCone )            << 1026             s=-b+sqrt(d);
1080               {                               << 1027             zi=p.z()+s*v.z();
1081                 xi     = p.x() + sd*v.x() ;   << 1028             ri=rMinAv+zi*tanRMin;
1082                 yi     = p.y() + sd*v.y() ;   << 1029             if (ri>=0)
1083                 cosPsi = (xi*cosCPhi + yi*sin << 1030           {
1084                                               << 1031               if (s>0&&fabs(zi)<=tolODz)
1085                 if (cosPsi >= cosHDPhiIT)     << 1032             {
1086                 {                             << 1033                 if (seg)
1087                   if ( sd > halfRadTolerance  << 1034               {
1088                   else                        << 1035                   xi=p.x()+s*v.x();
1089                   {                           << 1036                   yi=p.y()+s*v.y();
1090                     // Calculate a normal vec << 1037                   cosPsi=(xi*cosCPhi+
1091                                               << 1038                     yi*sinCPhi)/ri;
1092                     risec  = std::sqrt(xi*xi  << 1039                   if (cosPsi>=cosHDPhiOT)
1093                     Normal = G4ThreeVector(-x << 1040                 { snxt=s; }
1094                     if ( Normal.dot(v) <= 0 ) << 1041               }
1095                   }                           << 1042                 else
1096                 }                             << 1043               {
1097               }                               << 1044                   return s;
1098               else                            << 1045               }
1099               {                               << 1046             }
1100                 if ( sd > halfRadTolerance )  << 1047           }
1101                 else                          << 1048             else
1102                 {                             << 1049           {
1103                   // Calculate a normal vecto << 1050               s=-b-sqrt(d);
1104                                               << 1051               zi=p.z()+s*v.z();
1105                   xi     = p.x() + sd*v.x() ; << 1052               ri=rMinAv+zi*tanRMin;
1106                   yi     = p.y() + sd*v.y() ; << 1053               if (s>0&&ri>=0&&fabs(zi)<=tolODz)
1107                   risec  = std::sqrt(xi*xi +  << 1054             {
1108                   Normal = G4ThreeVector(-xi/ << 1055                 if (seg)
1109                   if ( Normal.dot(v) <= 0 )   << 1056               {
1110                 }                             << 1057                   xi=p.x()+s*v.x();
1111               }                               << 1058                   yi=p.y()+s*v.y();
1112             }                                 << 1059                   cosPsi=(xi*cosCPhi+
1113           }                                   << 1060                     yi*sinCPhi)/ri;
1114         }                                     << 1061                   if (cosPsi>=cosHDPhiOT)
1115       }                                       << 1062                 { snxt=s; }
1116       else                                    << 1063               }
1117       {                                       << 1064                 else
1118         // Within kRadTol*0.5 of inner cone ( << 1065               {
1119         // ----> Check not travelling through << 1066                   return s;
1120         // ----> if not:                      << 1067               }
1121         //    -2nd root with validity check   << 1068             }
1122                                               << 1069           }
1123         if ( std::fabs(p.z()) <= tolODz )     << 1070         }
1124         {                                     << 1071       }
1125           if ( nt2 > 0 )                      << 1072         else
1126           {                                   << 1073       {
1127             // Inside inner real cone, headin << 1074 // Within kRadTol/2 of inner cone (real OR imaginary)
                                                   >> 1075 // -> Check not travelling through (=>0 to in)
                                                   >> 1076 // -> if not:
                                                   >> 1077 //    -2nd root with validity check
                                                   >> 1078 //     +
                                                   >> 1079           if (fabs(p.z())<=tolODz)
                                                   >> 1080         {
                                                   >> 1081             if (nt2>0)
                                                   >> 1082           {
                                                   >> 1083 // Inside inner real cone, heading outwards, inside z range
                                                   >> 1084               if (seg)
                                                   >> 1085             {
                                                   >> 1086                 cosPsi=(p.x()*cosCPhi+p.y()*sinCPhi)/sqrt(t3);
                                                   >> 1087                 if (cosPsi>=cosHDPhiIT)
                                                   >> 1088               {
                                                   >> 1089                   return 0;
                                                   >> 1090               }
                                                   >> 1091             }
                                                   >> 1092               else
                                                   >> 1093             {
                                                   >> 1094                 return 0;
                                                   >> 1095             }
                                                   >> 1096           }
                                                   >> 1097             else
                                                   >> 1098           {
                                                   >> 1099 // Within z extent, but not travelling through
                                                   >> 1100 // -> 2nd root or kInfinity if 1st root on imaginary cone
                                                   >> 1101 
                                                   >> 1102               b=nt2/nt1;
                                                   >> 1103               c=nt3/nt1;
                                                   >> 1104               d=b*b-c;
                                                   >> 1105               if (d>0)
                                                   >> 1106             {
                                                   >> 1107                 s=-b-sqrt(d);
                                                   >> 1108                 zi=p.z()+s*v.z();
                                                   >> 1109                 ri=rMinAv+zi*tanRMin;
                                                   >> 1110                 if (ri>0)
                                                   >> 1111               {
                                                   >> 1112 // 2nd root
                                                   >> 1113                   s=-b+sqrt(d);
                                                   >> 1114                   zi=p.z()+s*v.z();
                                                   >> 1115                   if (s>0&&fabs(zi)<=tolODz)
                                                   >> 1116                 {
                                                   >> 1117                     if (seg)
                                                   >> 1118                   {
                                                   >> 1119                       xi=p.x()+s*v.x();
                                                   >> 1120                       yi=p.y()+s*v.y();
                                                   >> 1121                       cosPsi=(xi*cosCPhi+
                                                   >> 1122                         yi*sinCPhi)/ri;
                                                   >> 1123                       if (cosPsi>=cosHDPhiOT)
                                                   >> 1124                     { snxt=s; }
                                                   >> 1125                   }
                                                   >> 1126                     else
                                                   >> 1127                   {
                                                   >> 1128                       return s;
                                                   >> 1129                   }
                                                   >> 1130                 }
                                                   >> 1131               }
                                                   >> 1132                 else
                                                   >> 1133               {
                                                   >> 1134                   return kInfinity;
                                                   >> 1135               }
                                                   >> 1136             }
                                                   >> 1137           }
                                                   >> 1138         }
                                                   >> 1139           else
                                                   >> 1140         {
                                                   >> 1141 // 2nd root
                                                   >> 1142             b=nt2/nt1;
                                                   >> 1143             c=nt3/nt1;
                                                   >> 1144             d=b*b-c;
                                                   >> 1145             if (d>0)
                                                   >> 1146           { 
                                                   >> 1147               s=-b+sqrt(d);
                                                   >> 1148               zi=p.z()+s*v.z();
                                                   >> 1149               if (s>0&&fabs(zi)<=tolODz)
                                                   >> 1150             {
                                                   >> 1151                 if (seg)
                                                   >> 1152               {
                                                   >> 1153                   xi=p.x()+s*v.x();
                                                   >> 1154                   yi=p.y()+s*v.y();
                                                   >> 1155                   cosPsi=(xi*cosCPhi+
                                                   >> 1156                     yi*sinCPhi)/ri;
                                                   >> 1157                   if (cosPsi>=cosHDPhiOT)
                                                   >> 1158                 { snxt=s; }
                                                   >> 1159               }
                                                   >> 1160                 else
                                                   >> 1161               {
                                                   >> 1162                   return s;
                                                   >> 1163               }
                                                   >> 1164             }
                                                   >> 1165           }
                                                   >> 1166         }
                                                   >> 1167       }
                                                   >> 1168     }
                                                   >> 1169   }
                                                   >> 1170 
                                                   >> 1171 
                                                   >> 1172 //
                                                   >> 1173 // Phi segment intersection
                                                   >> 1174 //
                                                   >> 1175 // o Tolerant of points inside phi planes by up to kCarTolerance/2
                                                   >> 1176 //
                                                   >> 1177 // o NOTE: Large duplication of code between sphi & ephi checks
                                                   >> 1178 //         -> only diffs: sphi -> ephi, Comp -> -Comp and half-plane
                                                   >> 1179 //            intersection check <=0 -> >=0
                                                   >> 1180 //         -> Should use some form of loop Construct
                                                   >> 1181 //
                                                   >> 1182     if (seg)
                                                   >> 1183   {
                                                   >> 1184 // First phi surface (`S'tarting phi)
                                                   >> 1185       sinSPhi=sin(fSPhi);
                                                   >> 1186       cosSPhi=cos(fSPhi);
                                                   >> 1187       Comp=v.x()*sinSPhi-v.y()*cosSPhi;
                                                   >> 1188                     // Compnent in outwards normal dirn
                                                   >> 1189       if (Comp<0)
                                                   >> 1190     {
                                                   >> 1191         Dist=(p.y()*cosSPhi-p.x()*sinSPhi);
                                                   >> 1192         if (Dist<kCarTolerance/2)
                                                   >> 1193       {
                                                   >> 1194           s=Dist/Comp;
                                                   >> 1195           if (s<snxt)
                                                   >> 1196         {
                                                   >> 1197             if (s<0)
                                                   >> 1198           {
                                                   >> 1199               s=0;
                                                   >> 1200           }
                                                   >> 1201 
                                                   >> 1202             zi=p.z()+s*v.z();
                                                   >> 1203             if (fabs(zi)<=tolODz)
                                                   >> 1204           {
                                                   >> 1205               xi=p.x()+s*v.x();
                                                   >> 1206               yi=p.y()+s*v.y();
                                                   >> 1207               rho2=xi*xi+yi*yi;
                                                   >> 1208               tolORMin2=(rMinOAv+zi*tanRMin)*(rMinOAv+zi*tanRMin);
                                                   >> 1209               tolORMax2=(rMaxOAv+zi*tanRMax)*(rMaxOAv+zi*tanRMax);
                                                   >> 1210 
                                                   >> 1211               if (rho2>=tolORMin2&&rho2<=tolORMax2)
                                                   >> 1212             {
                                                   >> 1213 // z and r intersections good - check intersecting with correct half-plane
                                                   >> 1214                 if ((yi*cosCPhi-xi*sinCPhi)<=0)
                                                   >> 1215               snxt=s;
                                                   >> 1216             }    
                                                   >> 1217           }
                                                   >> 1218         }
                                                   >> 1219       }
                                                   >> 1220     
                                                   >> 1221     }
                                                   >> 1222       
                                                   >> 1223 // Second phi surface (`E'nding phi)
                                                   >> 1224       ePhi=fSPhi+fDPhi;
                                                   >> 1225       sinEPhi=sin(ePhi);
                                                   >> 1226       cosEPhi=cos(ePhi);
                                                   >> 1227       Comp=-(v.x()*sinEPhi-v.y()*cosEPhi);
                                                   >> 1228         // Compnent in outwards normal dirn
                                                   >> 1229       if (Comp<0)
                                                   >> 1230     {
                                                   >> 1231         Dist=-(p.y()*cosEPhi-p.x()*sinEPhi);
                                                   >> 1232         if (Dist<kCarTolerance/2)
                                                   >> 1233       {
                                                   >> 1234           s=Dist/Comp;
                                                   >> 1235           if (s<snxt)
                                                   >> 1236         {
                                                   >> 1237             if (s<0)
                                                   >> 1238           {
                                                   >> 1239               s=0;
                                                   >> 1240           }
                                                   >> 1241 
                                                   >> 1242             zi=p.z()+s*v.z();
                                                   >> 1243             if (fabs(zi)<=tolODz)
                                                   >> 1244           {
                                                   >> 1245               xi=p.x()+s*v.x();
                                                   >> 1246               yi=p.y()+s*v.y();
                                                   >> 1247               rho2=xi*xi+yi*yi;
                                                   >> 1248               tolORMin2=(rMinOAv+zi*tanRMin)*(rMinOAv+zi*tanRMin);
                                                   >> 1249               tolORMax2=(rMaxOAv+zi*tanRMax)*(rMaxOAv+zi*tanRMax);
                                                   >> 1250 
                                                   >> 1251               if (rho2>=tolORMin2&&rho2<=tolORMax2)
                                                   >> 1252             {
                                                   >> 1253 // z and r intersections good - check intersecting with correct half-plane
                                                   >> 1254                 if ((yi*cosCPhi-xi*sinCPhi)>=0)
                                                   >> 1255               snxt=s;
                                                   >> 1256             }    
                                                   >> 1257           }
                                                   >> 1258         }
                                                   >> 1259       }
                                                   >> 1260     }
                                                   >> 1261   }
                                                   >> 1262   
1128                                                  1263 
1129             if ( !fPhiFullCone )              << 1264   
1130             {                                 << 1265     return snxt;
1131               cosPsi = (p.x()*cosCPhi + p.y() << 
1132                                               << 
1133               if (cosPsi >= cosHDPhiIT)  { re << 
1134             }                                 << 
1135             else  { return 0.0; }             << 
1136           }                                   << 
1137           else                                << 
1138           {                                   << 
1139             // Within z extent, but not trave << 
1140             // -> 2nd root or kInfinity if 1s << 
1141                                               << 
1142             b = nt2/nt1 ;                     << 
1143             c = nt3/nt1 ;                     << 
1144             d = b*b - c ;                     << 
1145                                               << 
1146             if ( d >= 0 )   // > 0            << 
1147             {                                 << 
1148               if (b>0) { sd = -b - std::sqrt( << 
1149               else     { sd = c/(-b+std::sqrt << 
1150               zi = p.z() + sd*v.z() ;         << 
1151               ri = rMinAv + zi*tanRMin ;      << 
1152                                               << 
1153               if ( ri > 0 )   // 2nd root     << 
1154               {                               << 
1155                 if (b>0) { sd = c/(-b-std::sq << 
1156                 else     { sd = -b + std::sqr << 
1157                                               << 
1158                 zi = p.z() + sd*v.z() ;       << 
1159                                               << 
1160                 if ( (sd >= 0) && (std::fabs( << 
1161                 {                             << 
1162                   if ( sd>dRmax ) // Avoid ro << 
1163                   {               // seen on  << 
1164                     G4double fTerm = sd-std:: << 
1165                     sd = fTerm + DistanceToIn << 
1166                   }                           << 
1167                   if ( !fPhiFullCone )        << 
1168                   {                           << 
1169                     xi     = p.x() + sd*v.x() << 
1170                     yi     = p.y() + sd*v.y() << 
1171                     ri     = rMinAv + zi*tanR << 
1172                     cosPsi = (xi*cosCPhi + yi << 
1173                                               << 
1174                     if ( cosPsi >= cosHDPhiIT << 
1175                   }                           << 
1176                   else  { return sd; }        << 
1177                 }                             << 
1178               }                               << 
1179               else  { return kInfinity; }     << 
1180             }                                 << 
1181           }                                   << 
1182         }                                     << 
1183         else   // 2nd root                    << 
1184         {                                     << 
1185           b = nt2/nt1 ;                       << 
1186           c = nt3/nt1 ;                       << 
1187           d = b*b - c ;                       << 
1188                                               << 
1189           if ( d > 0 )                        << 
1190           {                                   << 
1191             if (b>0) { sd = c/(-b-std::sqrt(d << 
1192             else     { sd = -b + std::sqrt(d) << 
1193             zi = p.z() + sd*v.z() ;           << 
1194                                               << 
1195             if ( (sd >= 0) && (std::fabs(zi)  << 
1196             {                                 << 
1197               if ( sd>dRmax ) // Avoid roundi << 
1198               {               // seen on 64 b << 
1199                 G4double fTerm = sd-std::fmod << 
1200                 sd = fTerm + DistanceToIn(p+f << 
1201               }                               << 
1202               if ( !fPhiFullCone )            << 
1203               {                               << 
1204                 xi     = p.x() + sd*v.x();    << 
1205                 yi     = p.y() + sd*v.y();    << 
1206                 ri     = rMinAv + zi*tanRMin  << 
1207                 cosPsi = (xi*cosCPhi + yi*sin << 
1208                                               << 
1209                 if (cosPsi >= cosHDPhiIT)  {  << 
1210               }                               << 
1211               else  { return sd; }            << 
1212             }                                 << 
1213           }                                   << 
1214         }                                     << 
1215       }                                       << 
1216     }                                         << 
1217   }                                           << 
1218                                               << 
1219   // Phi segment intersection                 << 
1220   //                                          << 
1221   // o Tolerant of points inside phi planes b << 
1222   //                                          << 
1223   // o NOTE: Large duplication of code betwee << 
1224   //         -> only diffs: sphi -> ephi, Com << 
1225   //            intersection check <=0 -> >=0 << 
1226   //         -> Should use some form of loop  << 
1227                                               << 
1228   if ( !fPhiFullCone )                        << 
1229   {                                           << 
1230     // First phi surface (starting phi)       << 
1231                                               << 
1232     Comp    = v.x()*sinSPhi - v.y()*cosSPhi ; << 
1233                                               << 
1234     if ( Comp < 0 )    // Component in outwar << 
1235     {                                         << 
1236       Dist = (p.y()*cosSPhi - p.x()*sinSPhi)  << 
1237                                               << 
1238       if (Dist < halfCarTolerance)            << 
1239       {                                       << 
1240         sd = Dist/Comp ;                      << 
1241                                               << 
1242         if ( sd < snxt )                      << 
1243         {                                     << 
1244           if ( sd < 0 )  { sd = 0.0; }        << 
1245                                               << 
1246           zi = p.z() + sd*v.z() ;             << 
1247                                               << 
1248           if ( std::fabs(zi) <= tolODz )      << 
1249           {                                   << 
1250             xi        = p.x() + sd*v.x() ;    << 
1251             yi        = p.y() + sd*v.y() ;    << 
1252             rhoi2     = xi*xi + yi*yi ;       << 
1253             tolORMin2 = (rMinOAv + zi*tanRMin << 
1254             tolORMax2 = (rMaxOAv + zi*tanRMax << 
1255                                               << 
1256             if ( (rhoi2 >= tolORMin2) && (rho << 
1257             {                                 << 
1258               // z and r intersections good - << 
1259               // correct half-plane           << 
1260                                               << 
1261               if ((yi*cosCPhi - xi*sinCPhi) < << 
1262             }                                 << 
1263           }                                   << 
1264         }                                     << 
1265       }                                       << 
1266     }                                         << 
1267                                               << 
1268     // Second phi surface (Ending phi)        << 
1269                                               << 
1270     Comp    = -(v.x()*sinEPhi - v.y()*cosEPhi << 
1271                                               << 
1272     if ( Comp < 0 )   // Component in outward << 
1273     {                                         << 
1274       Dist = -(p.y()*cosEPhi - p.x()*sinEPhi) << 
1275       if (Dist < halfCarTolerance)            << 
1276       {                                       << 
1277         sd = Dist/Comp ;                      << 
1278                                               << 
1279         if ( sd < snxt )                      << 
1280         {                                     << 
1281           if ( sd < 0 )  { sd = 0.0; }        << 
1282                                               << 
1283           zi = p.z() + sd*v.z() ;             << 
1284                                               << 
1285           if (std::fabs(zi) <= tolODz)        << 
1286           {                                   << 
1287             xi        = p.x() + sd*v.x() ;    << 
1288             yi        = p.y() + sd*v.y() ;    << 
1289             rhoi2     = xi*xi + yi*yi ;       << 
1290             tolORMin2 = (rMinOAv + zi*tanRMin << 
1291             tolORMax2 = (rMaxOAv + zi*tanRMax << 
1292                                               << 
1293             if ( (rhoi2 >= tolORMin2) && (rho << 
1294             {                                 << 
1295               // z and r intersections good - << 
1296               // correct half-plane           << 
1297                                               << 
1298               if ( (yi*cosCPhi - xi*sinCPhi)  << 
1299             }                                 << 
1300           }                                   << 
1301         }                                     << 
1302       }                                       << 
1303     }                                         << 
1304   }                                           << 
1305   if (snxt < halfCarTolerance)  { snxt = 0.;  << 
1306                                               << 
1307   return snxt ;                               << 
1308 }                                                1266 }
1309                                                  1267 
1310 /////////////////////////////////////////////    1268 //////////////////////////////////////////////////////////////////////////////
1311 //                                               1269 // 
1312 // Calculate distance (<= actual) to closest     1270 // Calculate distance (<= actual) to closest surface of shape from outside
1313 // - Calculate distance to z, radial planes      1271 // - Calculate distance to z, radial planes
1314 // - Only to phi planes if outside phi extent    1272 // - Only to phi planes if outside phi extent
1315 // - Return 0 if point inside                    1273 // - Return 0 if point inside
1316                                                  1274 
1317 G4double G4Cons::DistanceToIn(const G4ThreeVe    1275 G4double G4Cons::DistanceToIn(const G4ThreeVector& p) const
1318 {                                                1276 {
1319   G4double safe=0.0, rho, safeR1, safeR2, saf << 1277     G4double safe,rho,safeR1,safeR2,safeZ;
1320   G4double tanRMin, secRMin, pRMin ;          << 1278     G4double tanRMin,secRMin,pRMin;
1321   G4double tanRMax, secRMax, pRMax ;          << 1279     G4double tanRMax,secRMax,pRMax;
1322                                               << 1280     G4double phiC,cosPhiC,sinPhiC,safePhi,ePhi;
1323   rho   = std::sqrt(p.x()*p.x() + p.y()*p.y() << 1281     G4double cosPsi;
1324   safeZ = std::fabs(p.z()) - fDz ;            << 1282     rho=sqrt(p.x()*p.x()+p.y()*p.y());
1325                                               << 1283     safeZ=fabs(p.z())-fDz;
1326   if ( (fRmin1 != 0.0) || (fRmin2 != 0.0) )   << 1284 
1327   {                                           << 1285     if (fRmin1||fRmin2)
1328     tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;     << 1286   {
1329     secRMin = std::sqrt(1.0 + tanRMin*tanRMin << 1287       tanRMin=(fRmin2-fRmin1)*0.5/fDz;
1330     pRMin   = tanRMin*p.z() + (fRmin1 + fRmin << 1288       secRMin=sqrt(1.0+tanRMin*tanRMin);
1331     safeR1  = (pRMin - rho)/secRMin ;         << 1289       pRMin=tanRMin*p.z()+(fRmin1+fRmin2)*0.5;
1332                                               << 1290       safeR1=(pRMin-rho)/secRMin;
1333     tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;     << 1291 
1334     secRMax = std::sqrt(1.0 + tanRMax*tanRMax << 1292       tanRMax=(fRmax2-fRmax1)*0.5/fDz;
1335     pRMax   = tanRMax*p.z() + (fRmax1 + fRmax << 1293       secRMax=sqrt(1.0+tanRMax*tanRMax);
1336     safeR2  = (rho - pRMax)/secRMax ;         << 1294       pRMax=tanRMax*p.z()+(fRmax1+fRmax2)*0.5;
1337                                               << 1295       safeR2=(rho-pRMax)/secRMax;
1338     if ( safeR1 > safeR2) { safe = safeR1; }  << 1296 
1339     else                  { safe = safeR2; }  << 1297       if (safeR1>safeR2) safe=safeR1;
1340   }                                           << 1298       else safe=safeR2;
1341   else                                        << 1299   }
1342   {                                           << 1300     else
1343     tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;     << 1301   {
1344     secRMax = std::sqrt(1.0 + tanRMax*tanRMax << 1302       tanRMax=(fRmax2-fRmax1)*0.5/fDz;
1345     pRMax   = tanRMax*p.z() + (fRmax1 + fRmax << 1303       secRMax=sqrt(1.0+tanRMax*tanRMax);
1346     safe    = (rho - pRMax)/secRMax ;         << 1304       pRMax=tanRMax*p.z()+(fRmax1+fRmax2)*0.5;
1347   }                                           << 1305       safe=(rho-pRMax)/secRMax;
1348   if ( safeZ > safe )  { safe = safeZ; }      << 1306   }
1349                                               << 1307   
1350   if ( !fPhiFullCone && (rho != 0.0) )        << 1308     if (safeZ>safe) safe=safeZ;
1351   {                                           << 1309 
1352     // Psi=angle from central phi to point    << 1310     if (fDPhi<2.0*M_PI&&rho)
1353                                               << 1311   {
1354     cosPsi = (p.x()*cosCPhi + p.y()*sinCPhi)/ << 1312       phiC=fSPhi+fDPhi*0.5;
1355                                               << 1313       cosPhiC=cos(phiC);
1356     if ( cosPsi < cosHDPhi ) // Point lies ou << 1314       sinPhiC=sin(phiC);
1357     {                                         << 1315 // Psi=angle from central phi to point
1358       if ( (p.y()*cosCPhi - p.x()*sinCPhi) <= << 1316       cosPsi=(p.x()*cosPhiC+p.y()*sinPhiC)/rho;
1359       {                                       << 1317       if (cosPsi<cos(fDPhi*0.5))
1360         safePhi = std::fabs(p.x()*sinSPhi-p.y << 1318     {
1361       }                                       << 1319 // Point lies outside phi range
1362       else                                    << 1320         if ((p.y()*cosPhiC-p.x()*sinPhiC)<=0)
1363       {                                       << 1321       {
1364         safePhi = std::fabs(p.x()*sinEPhi-p.y << 1322           safePhi=fabs(p.x()*sin(fSPhi)-p.y()*cos(fSPhi));
1365       }                                       << 1323       }
1366       if ( safePhi > safe )  { safe = safePhi << 1324         else
1367     }                                         << 1325       {
1368   }                                           << 1326           ePhi=fSPhi+fDPhi;
1369   if ( safe < 0.0 )  { safe = 0.0; }          << 1327           safePhi=fabs(p.x()*sin(ePhi)-p.y()*cos(ePhi));
1370                                               << 1328       }
1371   return safe ;                               << 1329         if (safePhi>safe) safe=safePhi;
                                                   >> 1330     }
                                                   >> 1331   }
                                                   >> 1332     if (safe<0) safe=0;
                                                   >> 1333     return safe;
1372 }                                                1334 }
1373                                                  1335 
1374 /////////////////////////////////////////////    1336 ///////////////////////////////////////////////////////////////
1375 //                                               1337 //
1376 // Calculate distance to surface of shape fro << 1338 // Calculate distance to surface of shape from `inside', allowing for tolerance
1377 // - Only Calc rmax intersection if no valid     1339 // - Only Calc rmax intersection if no valid rmin intersection
1378                                                  1340 
1379 G4double G4Cons::DistanceToOut( const G4Three    1341 G4double G4Cons::DistanceToOut( const G4ThreeVector& p,
1380                                 const G4Three << 1342               const G4ThreeVector& v,
1381                                 const G4bool  << 1343               const G4bool calcNorm,
1382                                       G4bool* << 1344                     G4bool *validNorm,
1383                                       G4Three << 1345                     G4ThreeVector *n) const
1384 {                                                1346 {
1385   ESide side = kNull, sider = kNull, sidephi  << 1347     ESide side = kNull,sider,sidephi;
1386                                               << 
1387   G4double snxt,srd,sphi,pdist ;              << 
1388                                               << 
1389   G4double tanRMax, secRMax, rMaxAv ;  // Dat << 
1390   G4double tanRMin, secRMin, rMinAv ;  // Dat << 
1391                                               << 
1392   G4double t1, t2, t3, rout, rin, nt1, nt2, n << 
1393   G4double b, c, d, sr2, sr3 ;                << 
1394                                               << 
1395   // Vars for intersection within tolerance   << 
1396                                               << 
1397   ESide sidetol = kNull ;                     << 
1398   G4double slentol = kInfinity ;              << 
1399                                               << 
1400   // Vars for phi intersection:               << 
1401                                                  1348 
1402   G4double pDistS, compS, pDistE, compE, sphi << 1349     G4double snxt,sr,sphi,pdist;
1403   G4double zi, ri, deltaRoi2 ;                << 
1404                                                  1350 
1405   // Z plane intersection                     << 1351     G4double tanRMax,secRMax,rMaxAv;  // Data for outer cone
                                                   >> 1352     G4double tanRMin,secRMin,rMinAv;  // Data for inner cone
1406                                                  1353 
1407   if ( v.z() > 0.0 )                          << 1354     G4double t1,t2,t3,rout,rin,nt1,nt2,nt3;
1408   {                                           << 1355     G4double b,c,d,sr2,sr3;
1409     pdist = fDz - p.z() ;                     << 1356     // Vars for intersection within tolerance
1410                                               << 1357     ESide    sidetol;
1411     if (pdist > halfCarTolerance)             << 1358     G4double slentol= kInfinity;
1412     {                                         << 1359 // Vars for phi intersection:
1413       snxt = pdist/v.z() ;                    << 1360     G4double sinSPhi,cosSPhi,ePhi,sinEPhi,cosEPhi;
1414       side = kPZ ;                            << 1361     G4double cPhi,sinCPhi,cosCPhi;
1415     }                                         << 1362     G4double pDistS,compS,pDistE,compE,sphi2,xi,yi,risec,vphi;
1416     else                                      << 1363     G4double zi,ri;
1417     {                                         << 1364 //
1418       if (calcNorm)                           << 1365 // Z plane intersection
1419       {                                       << 1366 //
1420         *n         = G4ThreeVector(0,0,1) ;   << 1367     if (v.z()>0)
1421         *validNorm = true ;                   << 1368     {
1422       }                                       << 1369        pdist=fDz-p.z();
1423       return  snxt = 0.0;                     << 1370 
1424     }                                         << 1371        if (pdist > kCarTolerance*0.5)
1425   }                                           << 1372        {
1426   else if ( v.z() < 0.0 )                     << 1373     snxt=pdist/v.z();
1427   {                                           << 1374     side=kPZ;
1428     pdist = fDz + p.z() ;                     << 1375        }
1429                                               << 1376        else
1430     if ( pdist > halfCarTolerance)            << 1377        {
1431     {                                         << 1378     if (calcNorm)
1432       snxt = -pdist/v.z() ;                   << 1379     {
1433       side = kMZ ;                            << 1380        *n=G4ThreeVector(0,0,1);
                                                   >> 1381        *validNorm=true;
                                                   >> 1382     }
                                                   >> 1383     return snxt=0;
                                                   >> 1384        }
                                                   >> 1385     }
                                                   >> 1386     else if (v.z()<0)
                                                   >> 1387     {
                                                   >> 1388        pdist=fDz+p.z();
                                                   >> 1389 
                                                   >> 1390        if (pdist > kCarTolerance*0.5)
                                                   >> 1391        {
                                                   >> 1392     snxt=-pdist/v.z();
                                                   >> 1393     side=kMZ;
                                                   >> 1394        }
                                                   >> 1395        else
                                                   >> 1396        {
                                                   >> 1397     if (calcNorm)
                                                   >> 1398     {
                                                   >> 1399        *n=G4ThreeVector(0,0,-1);
                                                   >> 1400        *validNorm=true;
                                                   >> 1401     }
                                                   >> 1402     return snxt=0;
                                                   >> 1403        }
1434     }                                            1404     }
1435     else                                         1405     else
1436     {                                            1406     {
1437       if ( calcNorm )                         << 1407        snxt=kInfinity;    // Travel perpendicular to z axis
1438       {                                       << 1408        side=kNull;
1439         *n         = G4ThreeVector(0,0,-1) ;  << 
1440         *validNorm = true ;                   << 
1441       }                                       << 
1442       return snxt = 0.0 ;                     << 
1443     }                                            1409     }
1444   }                                           << 1410 //
1445   else     // Travel perpendicular to z axis  << 1411 // Radial Intersections
1446   {                                           << 1412 //
1447     snxt = kInfinity ;                        << 1413 // Intersection with outer cone (possible return) and
1448     side = kNull ;                            << 1414 //                   inner cone (must also check phi)
1449   }                                           << 1415 //
1450                                               << 1416 // Intersection point (xi,yi,zi) on line x=p.x+t*v.x etc.
1451   // Radial Intersections                     << 1417 //
1452   //                                          << 1418 // Intersects with x^2+y^2=(a*z+b)^2
1453   // Intersection with outer cone (possible r << 1419 //
1454   //                   inner cone (must also  << 1420 // where a=tanRMax or tanRMin
1455   //                                          << 1421 //       b=rMaxAv  or rMinAv
1456   // Intersection point (xi,yi,zi) on line x= << 1422 //
1457   //                                          << 1423 // (vx^2+vy^2-(a*vz)^2)t^2+2t(pxvx+pyvy-a*vz(a*pz+b))+px^2+py^2-(a*pz+b)^2=0;
1458   // Intersects with x^2+y^2=(a*z+b)^2        << 1424 //     t1                        t2                      t3  
1459   //                                          << 1425 //
1460   // where a=tanRMax or tanRMin               << 1426 //  \--------u-------/       \-----------v----------/ \---------w--------/
1461   //       b=rMaxAv  or rMinAv                << 1427 //
1462   //                                          << 1428     tanRMax=(fRmax2-fRmax1)*0.5/fDz;
1463   // (vx^2+vy^2-(a*vz)^2)t^2+2t(pxvx+pyvy-a*v << 1429     secRMax=sqrt(1.0+tanRMax*tanRMax);
1464   //     t1                        t2         << 1430     rMaxAv=(fRmax1+fRmax2)*0.5;
1465   //                                          << 1431 
1466   //  \--------u-------/       \-----------v- << 1432 
1467                                               << 1433     t1=1.0-v.z()*v.z();     // since v normalised
1468   tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;       << 1434     t2=p.x()*v.x()+p.y()*v.y();
1469   secRMax = std::sqrt(1.0 + tanRMax*tanRMax)  << 1435     t3=p.x()*p.x()+p.y()*p.y();
1470   rMaxAv  = (fRmax1 + fRmax2)*0.5 ;           << 1436     rout=tanRMax*p.z()+rMaxAv;
1471                                               << 1437 
1472                                               << 1438     nt1=t1-(tanRMax*v.z())*(tanRMax*v.z());
1473   t1   = 1.0 - v.z()*v.z() ;      // since v  << 1439     nt2=t2-tanRMax*v.z()*rout;
1474   t2   = p.x()*v.x() + p.y()*v.y() ;          << 1440     nt3=t3-rout*rout;
1475   t3   = p.x()*p.x() + p.y()*p.y() ;          << 1441     if (nt1)
1476   rout = tanRMax*p.z() + rMaxAv ;             << 1442     {
1477                                               << 1443 //
1478   nt1 = t1 - (tanRMax*v.z())*(tanRMax*v.z())  << 1444 // Equation quadratic => 2 roots : second root must be leaving
1479   nt2 = t2 - tanRMax*v.z()*rout ;             << 1445 //
1480   nt3 = t3 - rout*rout ;                      << 1446        b=nt2/nt1;
1481                                               << 1447        c=nt3/nt1;
1482   if (v.z() > 0.0)                            << 1448        d=b*b-c;
1483   {                                           << 1449 
1484     deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3 << 1450        if ( d >= 0 )
1485                 - fRmax2*(fRmax2 + kRadTolera << 1451        {
1486   }                                           << 1452 // Check if on outer cone & heading outwards
1487   else if (v.z() < 0.0)                       << 1453 // NOTE: Should use rho-rout>-kRadtolerance/2
1488   {                                           << 1454         
1489     deltaRoi2 = snxt*snxt*t1 + 2*snxt*t2 + t3 << 1455     if (nt3 > -kRadTolerance*0.5 && nt2 >= 0 )
1490                 - fRmax1*(fRmax1 + kRadTolera << 1456     {
1491   }                                           << 1457        if (calcNorm)
1492   else                                        << 1458        {
1493   {                                           << 1459     risec=sqrt(t3)*secRMax;
1494     deltaRoi2 = 1.0;                          << 1460     *validNorm=true;
1495   }                                           << 1461     *n=G4ThreeVector(p.x()/risec,p.y()/risec,-tanRMax/secRMax);
1496                                               << 1462        }
1497   if ( (nt1 != 0.0) && (deltaRoi2 > 0.0) )    << 1463        return snxt=0;
1498   {                                           << 1464     }
1499     // Equation quadratic => 2 roots : second << 1465     else
1500                                               << 1466    {
1501     b = nt2/nt1 ;                             << 1467 // // -*-* ORIG ROOT CODE    
1502     c = nt3/nt1 ;                             << 1468 //          sr=-b+sqrt(d);
1503     d = b*b - c ;                             << 1469 //          sider=kRMax;
1504                                               << 1470 // // -*-* ORIG ROOT CODE    
1505     if ( d >= 0 )                             << 1471 
1506     {                                         << 1472 // Patch 4.4.95 - root above cross-over point
1507       // Check if on outer cone & heading out << 1473 
1508       // NOTE: Should use rho-rout>-kRadToler << 1474        sider=kRMax ;
1509                                               << 1475        sr=-b - sqrt(d); // was +srqrt(d), vmg 28.04.99
1510       if (nt3 > -halfRadTolerance && nt2 >= 0 << 1476        zi=p.z()+sr*v.z();
1511       {                                       << 1477        ri=tanRMax*zi+rMaxAv;
1512         if (calcNorm)                         << 1478           
1513         {                                     << 1479        if (    (ri >= 0) 
1514           risec      = std::sqrt(t3)*secRMax  << 1480                  && (-kRadTolerance/2 <= sr)
1515           *validNorm = true ;                 << 1481      && ( sr <= kRadTolerance/2)  )
1516           *n         = G4ThreeVector(p.x()/ri << 1482        {
1517         }                                     << 1483 // An intersection within the tolerance
1518         return snxt=0 ;                       << 1484 //   we will Store it in case it is good -
1519       }                                       << 1485 // 
1520       else                                    << 1486      slentol = sr;
1521       {                                       << 1487      sidetol= kRMax;
1522         sider = kRMax  ;                      << 1488        }            
1523         if (b>0) { srd = -b - std::sqrt(d);   << 1489        if ( (ri < 0) || (sr < kRadTolerance/2) )
1524         else     { srd = c/(-b+std::sqrt(d))  << 1490        {
1525                                               << 1491 // Safety: if both roots -ve ensure that sr cannot `win' distance to out
1526         zi    = p.z() + srd*v.z() ;           << 1492 
1527         ri    = tanRMax*zi + rMaxAv ;         << 1493     sr2=-b+sqrt(d);
1528                                               << 1494     zi=p.z()+sr2*v.z();
1529         if ((ri >= 0) && (-halfRadTolerance < << 1495     ri=tanRMax*zi+rMaxAv;
1530         {                                     << 1496 
1531           // An intersection within the toler << 1497           if (ri>=0&&sr2>kRadTolerance/2)
1532           //   we will Store it in case it is << 1498     {
1533           //                                  << 1499        sr=sr2;
1534           slentol = srd ;                     << 1500     }
1535           sidetol = kRMax ;                   << 1501     else
1536         }                                     << 1502     {
1537         if ( (ri < 0) || (srd < halfRadTolera << 1503        sr = kInfinity ;
1538         {                                     << 1504 
1539           // Safety: if both roots -ve ensure << 1505        if(    (-kRadTolerance/2 <= sr2)
1540           //         distance to out          << 1506            && ( sr2 <= kRadTolerance/2)  )
1541                                               << 1507        {
1542           if (b>0) { sr2 = c/(-b-std::sqrt(d) << 1508 // An intersection within the tolerance. Storing it in case it is good.
1543           else     { sr2 = -b + std::sqrt(d); << 1509 
1544           zi  = p.z() + sr2*v.z() ;           << 1510           slentol = sr2;
1545           ri  = tanRMax*zi + rMaxAv ;         << 1511           sidetol= kRMax;
1546                                               << 1512        }
1547           if ((ri >= 0) && (sr2 > halfRadTole << 1513     }
1548           {                                   << 1514        }
1549             srd = sr2;                        << 1515     }
1550           }                                   << 1516        }
1551           else                                << 1517        else
1552           {                                   << 1518        {
1553             srd = kInfinity ;                 << 1519 // No intersection with outer cone & not parallel -> already outside, no
1554                                               << 1520 // intersection
1555             if( (-halfRadTolerance <= sr2) && << 1521 
1556             {                                 << 1522     if (calcNorm)
1557               // An intersection within the t << 1523     {
1558               // Storing it in case it is goo << 1524        risec=sqrt(t3)*secRMax;
1559                                               << 1525       *validNorm=true;
1560               slentol = sr2 ;                 << 1526       *n=G4ThreeVector(p.x()/risec,p.y()/risec,-tanRMax/secRMax);
1561               sidetol = kRMax ;               << 1527     }
1562             }                                 << 1528     return snxt=0;
1563           }                                   << 1529        }
1564         }                                     << 1530     }
1565       }                                       << 1531     else if (nt2)
                                                   >> 1532     {
                                                   >> 1533 //
                                                   >> 1534 // Linear case (only one intersection) => point outside outer cone
                                                   >> 1535 //
                                                   >> 1536        if (calcNorm)
                                                   >> 1537        {
                                                   >> 1538     risec=sqrt(t3)*secRMax;
                                                   >> 1539    *validNorm=true;
                                                   >> 1540    *n=G4ThreeVector(p.x()/risec,p.y()/risec,-tanRMax/secRMax);
                                                   >> 1541        }
                                                   >> 1542        return snxt=0;
1566     }                                            1543     }
1567     else                                         1544     else
1568     {                                            1545     {
1569       // No intersection with outer cone & no << 1546 // No intersection -> parallel to outer cone => Z or inner cone intersection
1570       // -> already outside, no intersection  << 
1571                                                  1547 
1572       if ( calcNorm )                         << 1548        sr=kInfinity;
1573       {                                       << 
1574         risec      = std::sqrt(t3)*secRMax;   << 
1575         *validNorm = true;                    << 
1576         *n         = G4ThreeVector(p.x()/rise << 
1577       }                                       << 
1578       return snxt = 0.0 ;                     << 
1579     }                                            1549     }
1580   }                                           << 
1581   else if ( (nt2 != 0.0) && (deltaRoi2 > 0.0) << 
1582   {                                           << 
1583     // Linear case (only one intersection) => << 
1584                                                  1550 
1585     if ( calcNorm )                           << 1551 // Check possible intersection within tolerance
1586     {                                         << 
1587       risec      = std::sqrt(t3)*secRMax;     << 
1588       *validNorm = true;                      << 
1589       *n         = G4ThreeVector(p.x()/risec, << 
1590     }                                         << 
1591     return snxt = 0.0 ;                       << 
1592   }                                           << 
1593   else                                        << 
1594   {                                           << 
1595     // No intersection -> parallel to outer c << 
1596     // => Z or inner cone intersection        << 
1597                                               << 
1598     srd = kInfinity ;                         << 
1599   }                                           << 
1600                                               << 
1601   // Check possible intersection within toler << 
1602                                               << 
1603   if ( slentol <= halfCarTolerance )          << 
1604   {                                           << 
1605     // An intersection within the tolerance w << 
1606     // We must accept it only if the momentum << 
1607     //                                        << 
1608     // G4ThreeVector ptTol ;  // The point of << 
1609     // ptTol= p + slentol*v ;                 << 
1610     // ri=tanRMax*zi+rMaxAv ;                 << 
1611     //                                        << 
1612     // Calculate a normal vector,  as below   << 
1613                                               << 
1614     xi    = p.x() + slentol*v.x();            << 
1615     yi    = p.y() + slentol*v.y();            << 
1616     risec = std::sqrt(xi*xi + yi*yi)*secRMax; << 
1617     G4ThreeVector Normal = G4ThreeVector(xi/r << 
1618                                               << 
1619     if ( Normal.dot(v) > 0 )    // We will le << 
1620     {                                         << 
1621       if ( calcNorm )                         << 
1622       {                                       << 
1623         *n         = Normal.unit() ;          << 
1624         *validNorm = true ;                   << 
1625       }                                       << 
1626       return snxt = 0.0 ;                     << 
1627     }                                         << 
1628     else // On the surface, but not heading o << 
1629     {    //                                   << 
1630       slentol = kInfinity ;                   << 
1631     }                                         << 
1632   }                                           << 
1633                                               << 
1634   // Inner Cone intersection                  << 
1635                                               << 
1636   if ( (fRmin1 != 0.0) || (fRmin2 != 0.0) )   << 
1637   {                                           << 
1638     tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;     << 
1639     nt1     = t1 - (tanRMin*v.z())*(tanRMin*v << 
1640                                                  1552 
1641     if ( nt1 != 0.0 )                         << 1553     if ( slentol <= kCarTolerance/2 )
1642     {                                            1554     {
1643       secRMin = std::sqrt(1.0 + tanRMin*tanRM << 1555 //
1644       rMinAv  = (fRmin1 + fRmin2)*0.5 ;       << 1556 // An intersection within the tolerance was found.  
1645       rin     = tanRMin*p.z() + rMinAv ;      << 1557 // We must accept it only if the momentum points outwards.  
1646       nt2     = t2 - tanRMin*v.z()*rin ;      << 1558 //
1647       nt3     = t3 - rin*rin ;                << 1559 // G4ThreeVector ptTol;  // The point of the intersection  
1648                                               << 1560 // ptTol= p + slentol*v;
1649       // Equation quadratic => 2 roots : firs << 1561 // ri=tanRMax*zi+rMaxAv;
1650                                               << 1562 //
1651       b = nt2/nt1 ;                           << 1563 // Calculate a normal vector,  as below
1652       c = nt3/nt1 ;                           << 1564 
1653       d = b*b - c ;                           << 1565        xi=p.x()+slentol*v.x();
1654                                               << 1566        yi=p.y()+slentol*v.y();
1655       if ( d >= 0.0 )                         << 1567        risec=sqrt(xi*xi+yi*yi)*secRMax;
1656       {                                       << 1568        G4ThreeVector Normal=G4ThreeVector(xi/risec,yi/risec,-tanRMax/secRMax);
1657         // NOTE: should be rho-rin<kRadTolera << 1569 
1658         //       but using squared versions f << 1570        if ( Normal.dot(v) > 0 )
1659                                               << 1571        {
1660         if (nt3 < kRadTolerance*(rin + kRadTo << 1572     // We will leave the Cone immediatelly
1661         {                                     << 1573 
1662           if ( nt2 < 0.0 )                    << 1574     if ( calcNorm ) 
1663           {                                   << 1575     {
1664             if (calcNorm)  { *validNorm = fal << 1576       *n= Normal.unit();
1665             return          snxt      = 0.0;  << 1577       *validNorm=true;
1666           }                                   << 1578     }
1667         }                                     << 1579     return snxt = 0.0;
1668         else                                  << 1580   }
1669         {                                     << 1581         else 
1670           if (b>0) { sr2 = -b - std::sqrt(d); << 1582   { 
1671           else     { sr2 = c/(-b+std::sqrt(d) << 1583     // On the surface, but not heading out
1672           zi  = p.z() + sr2*v.z() ;           << 1584     //  so we ignore this intersection (as it is within tolerance).
1673           ri  = tanRMin*zi + rMinAv ;         << 1585     slentol = kInfinity;
1674                                               << 1586   }
1675           if( (ri>=0.0)&&(-halfRadTolerance<= << 1587     }
1676           {                                   << 1588 
1677             // An intersection within the tol << 1589 
1678             // storing it in case it is good. << 1590 //
1679                                               << 1591 // Inner Cone intersection
1680             slentol = sr2 ;                   << 1592 //
1681             sidetol = kRMax ;                 << 1593     if (fRmin1||fRmin2)
1682           }                                   << 1594   {
1683           if( (ri<0) || (sr2 < halfRadToleran << 1595       tanRMin=(fRmin2-fRmin1)*0.5/fDz;
1684           {                                   << 1596       nt1=t1-(tanRMin*v.z())*(tanRMin*v.z());
1685             if (b>0) { sr3 = c/(-b-std::sqrt( << 1597       if (nt1)
1686             else     { sr3 = -b + std::sqrt(d << 1598     {
1687                                               << 1599         secRMin=sqrt(1.0+tanRMin*tanRMin);
1688             // Safety: if both roots -ve ensu << 1600         rMinAv=(fRmin1+fRmin2)*0.5;
1689             //         distancetoout          << 1601       
1690                                               << 1602         rin=tanRMin*p.z()+rMinAv;
1691             if  ( sr3 > halfRadTolerance )    << 1603         nt2=t2-tanRMin*v.z()*rin;
1692             {                                 << 1604         nt3=t3-rin*rin;
1693               if( sr3 < srd )                 << 1605       
1694               {                               << 1606 //
1695                 zi = p.z() + sr3*v.z() ;      << 1607 // Equation quadratic => 2 roots : first root must be leaving
1696                 ri = tanRMin*zi + rMinAv ;    << 1608 //
1697                                               << 1609         b=nt2/nt1;
1698                 if ( ri >= 0.0 )              << 1610         c=nt3/nt1;
1699                 {                             << 1611         d=b*b-c;
1700                   srd=sr3 ;                   << 1612         if (d>=0)
1701                   sider=kRMin ;               << 1613       {
1702                 }                             << 1614 // NOTE: should be rho-rin<kRadTolerance/2, but using squared versions
1703               }                               << 1615 // for efficiency
1704             }                                 << 1616           if (nt3<kRadTolerance*(rin+kRadTolerance*0.25)) 
1705             else if ( sr3 > -halfRadTolerance << 1617         {
1706             {                                 << 1618             if (nt2<0)
1707               // Intersection in tolerance. S << 1619           {
1708                                               << 1620               if (calcNorm)
1709               slentol = sr3 ;                 << 1621             {
1710               sidetol = kRMin ;               << 1622                 *validNorm=false;
1711             }                                 << 1623             }
1712           }                                   << 1624               return snxt=0;
1713           else if ( (sr2 < srd) && (sr2 > hal << 1625           }
1714           {                                   << 1626         }
1715             srd   = sr2 ;                     << 1627           else
1716             sider = kRMin ;                   << 1628         {
1717           }                                   << 1629 
1718           else if (sr2 > -halfCarTolerance)   << 1630 // // -*-* ORIG ROOT CODE    
1719           {                                   << 1631 //            sr2=-b-sqrt(d);
1720             // Intersection in tolerance. Sto << 1632 //            if (sr2>0&&sr2<sr)
1721                                               << 1633 //          {
1722             slentol = sr2 ;                   << 1634 //              sider=kRMin;
1723             sidetol = kRMin ;                 << 1635 //              sr=sr2;
1724           }                                   << 1636 //          }
1725           if( slentol <= halfCarTolerance  )  << 1637 // -*-* ORIG ROOT CODE
1726           {                                   << 1638 
1727             // An intersection within the tol << 1639 // // Patch 4.4.95 - zi based
1728             // We must accept it only if  the << 1640 //            sr2=-b-sqrt(d);
1729                                               << 1641 //            zi=p.z()+sr2*v.z();
1730             G4ThreeVector Normal ;            << 1642 //            if (fabs(zi)>fDz+kCarTolerance/2)
1731                                               << 1643 //          {
1732             // Calculate a normal vector,  as << 1644 //              sr2=-b+sqrt(d);
1733                                               << 1645 //              zi=p.z()+sr2*v.z();
1734             xi     = p.x() + slentol*v.x() ;  << 1646 //              if (fabs(zi)<fDz+kCarTolerance/2)
1735             yi     = p.y() + slentol*v.y() ;  << 1647 //            {
1736             if( sidetol==kRMax )              << 1648 //                if (sr2<sr&&sr2>=0)
1737             {                                 << 1649 //              {
1738               risec  = std::sqrt(xi*xi + yi*y << 1650 //                  sr=sr2;
1739               Normal = G4ThreeVector(xi/risec << 1651 //                  sider=kRMin;
1740             }                                 << 1652 //              }
1741             else                              << 1653 //            }
1742             {                                 << 1654 //          }
1743               risec  = std::sqrt(xi*xi + yi*y << 1655 //            else
1744               Normal = G4ThreeVector(-xi/rise << 1656 //          {
1745             }                                 << 1657 //              if (sr2<sr&&sr2>=0)
1746             if( Normal.dot(v) > 0 )           << 1658 //            {
1747             {                                 << 1659 //                sr=sr2;
1748               // We will leave the cone immed << 1660 //                sider=kRMin;
1749                                               << 1661 //            }
1750               if( calcNorm )                  << 1662 //          }
1751               {                               << 1663 
1752                 *n         = Normal.unit() ;  << 1664 // Patch 4.4.95 - root above cross-over point
1753                 *validNorm = true ;           << 1665 
1754               }                               << 1666             sr2=-b-sqrt(d);
1755               return snxt = 0.0 ;             << 1667             zi=p.z()+sr2*v.z();
1756             }                                 << 1668             ri=tanRMin*zi+rMinAv;
1757             else                              << 1669             if( (ri>=0) 
1758             {                                 << 1670           && (-kRadTolerance/2 <= sr2)
1759               // On the surface, but not head << 1671           && ( sr2 <= kRadTolerance/2)  )
1760               // intersection (as it is withi << 1672               {
1761                                               << 1673               // An intersection within the tolerance
1762               slentol = kInfinity ;           << 1674               //   storing it in case it is good.
1763             }                                 << 1675           slentol = sr2;
1764           }                                   << 1676           sidetol= kRMax;
1765         }                                     << 1677               }
1766       }                                       << 1678 
1767     }                                         << 1679             if( (ri<0) 
1768   }                                           << 1680           || (sr2<kRadTolerance/2))
1769                                               << 1681           {
1770   // Linear case => point outside inner cone  << 1682               sr3=-b+sqrt(d);
1771   //                                          << 1683 
1772   // Phi Intersection                         << 1684 // Safety: if both roots -ve ensure that sr cannot `win' distancetoout
1773                                               << 1685 
1774   if ( !fPhiFullCone )                        << 1686               if  (sr3>kCarTolerance*0.5)
1775   {                                           << 1687                 {
1776     // add angle calculation with correction  << 1688                   if(sr3<sr)
1777     // of the difference in domain of atan2 a << 1689              {
1778                                               << 1690                zi=p.z()+sr3*v.z();
1779     vphi = std::atan2(v.y(),v.x()) ;          << 1691                ri=tanRMin*zi+rMinAv;
1780                                               << 1692                if (ri>=0)
1781     if ( vphi < fSPhi - halfAngTolerance  )   << 1693                  {
1782     else if ( vphi > fSPhi + fDPhi + halfAngT << 1694                    sr=sr3;
1783                                               << 1695                    sider=kRMin;
1784     if ( (p.x() != 0.0) || (p.y() != 0.0) )   << 1696                  }
1785     {                                         << 1697              } 
1786       // pDist -ve when inside                << 1698                 }
1787                                               << 1699               else if (sr3> -kCarTolerance*0.5)
1788       pDistS = p.x()*sinSPhi - p.y()*cosSPhi  << 1700                 {
1789       pDistE = -p.x()*sinEPhi + p.y()*cosEPhi << 1701             // Intersection in tolerance
1790                                               << 1702             // Store to check if it's good
1791       // Comp -ve when in direction of outwar << 1703             slentol = sr3;
1792                                               << 1704             sidetol= kRMin;
1793       compS = -sinSPhi*v.x() + cosSPhi*v.y()  << 1705                 }
1794       compE = sinEPhi*v.x() - cosEPhi*v.y() ; << 1706           }
1795                                               << 1707             else if (sr2<sr&&sr2>kCarTolerance*0.5)
1796       sidephi = kNull ;                       << 1708           {
1797                                               << 1709               sr=sr2;
1798       if( ( (fDPhi <= pi) && ( (pDistS <= hal << 1710               sider=kRMin;
1799                             && (pDistE <= hal << 1711           }
1800          || ( (fDPhi >  pi) && ((pDistS <=  h << 1712             else if (sr2> -kCarTolerance*0.5)
1801                               || (pDistE <=   << 1713                 {
1802       {                                       << 1714               // Intersection in tolerance
1803         // Inside both phi *full* planes      << 1715               // Store to check if it's good
1804         if ( compS < 0 )                      << 1716               slentol = sr2;
1805         {                                     << 1717               sidetol= kRMin;
1806           sphi = pDistS/compS ;               << 1718                 }
1807           if (sphi >= -halfCarTolerance)      << 1719                
1808           {                                   << 1720 // Patch 4.4.95
1809             xi = p.x() + sphi*v.x() ;         << 1721             
1810             yi = p.y() + sphi*v.y() ;         << 1722 // // Patch 3.4.95
1811                                               << 1723 //            sr2=-b-sqrt(d);
1812             // Check intersecting with correc << 1724 //            zi=p.z()+sr2*v.z();
1813             // (if not -> no intersect)       << 1725 //            if (fabs(zi)>fDz+kCarTolerance/2||sr2<0)
1814             //                                << 1726 //          {
1815             if ( (std::fabs(xi)<=kCarToleranc << 1727 //              sr2=-b+sqrt(d);
1816               && (std::fabs(yi)<=kCarToleranc << 1728 //              zi=p.z()+sr2*v.z();
1817             {                                 << 1729 //              if (fabs(zi)>fDz+kCarTolerance/2||sr2<0)
1818               sidephi= kSPhi;                 << 1730 //            {
1819               if ( ( fSPhi-halfAngTolerance < << 1731 //                sr2=kInfinity;
1820                 && ( fSPhi+fDPhi+halfAngToler << 1732 //            }
1821               {                               << 1733 //          }
1822                 sphi = kInfinity;             << 1734 
1823               }                               << 1735 //              if (sr2<sr)
1824             }                                 << 1736 //            {
1825             else                              << 1737 //                sider=kRMin;
1826             if ( (yi*cosCPhi-xi*sinCPhi)>=0 ) << 1738 //                sr=sr2;
1827             {                                 << 1739 //          }
1828               sphi = kInfinity ;              << 1740         
1829             }                                 << 1741             if( slentol <= kCarTolerance/2  )
1830             else                              << 1742                 {
1831             {                                 << 1743             // An intersection within the
1832               sidephi = kSPhi ;               << 1744             //  tolerance was found. 
1833               if ( pDistS > -halfCarTolerance << 1745             // We must accept it only if 
1834               {                               << 1746             //  the momentum points outwards. 
1835                 sphi = 0.0 ; // Leave by sphi << 1747 
1836               }                               << 1748             G4ThreeVector Normal; 
1837             }                                 << 1749             
1838           }                                   << 1750             // Calculate a normal vector,  as below
1839           else                                << 1751             xi=p.x()+slentol*v.x();
1840           {                                   << 1752             yi=p.y()+slentol*v.y();
1841             sphi = kInfinity ;                << 1753             risec=sqrt(xi*xi+yi*yi)*secRMin;
1842           }                                   << 1754             Normal=G4ThreeVector(xi/risec,yi/risec,-tanRMin/secRMin);
1843         }                                     << 1755             
1844         else                                  << 1756             if( Normal.dot(v) > 0 )
1845         {                                     << 1757               {
1846           sphi = kInfinity ;                  << 1758                 // We will leave the Cone immediatelly
1847         }                                     << 1759                 if(calcNorm) 
1848                                               << 1760             {
1849         if ( compE < 0 )                      << 1761               *n= Normal.unit();
1850         {                                     << 1762               *validNorm=true;
1851           sphi2 = pDistE/compE ;              << 1763             }
1852                                               << 1764                 return snxt = 0.0;
1853           // Only check further if < starting << 1765               }
1854           //                                  << 1766             else 
1855           if ( (sphi2 > -halfCarTolerance) && << 1767               { 
1856           {                                   << 1768                 // On the surface, but not
1857             xi = p.x() + sphi2*v.x() ;        << 1769                 // heading out so we ignore this
1858             yi = p.y() + sphi2*v.y() ;        << 1770                 // intersection (as it is within
1859                                               << 1771                 // tolerance). 
1860             // Check intersecting with correc << 1772                 slentol = kInfinity;
1861                                               << 1773               }
1862             if ( (std::fabs(xi)<=kCarToleranc << 1774             
1863               && (std::fabs(yi)<=kCarToleranc << 1775                 }
1864             {                                 << 1776         }
1865               // Leaving via ending phi       << 1777       }
1866                                               << 1778     }
1867               if( (fSPhi-halfAngTolerance > v << 1779 //
1868                  || (fSPhi+fDPhi+halfAngToler << 1780 // Linear case => point outside inner cone -> outer cone intersect
1869               {                               << 1781 //
1870                 sidephi = kEPhi ;             << 1782   }
1871                 if ( pDistE <= -halfCarTolera << 
1872                 else                          << 
1873               }                               << 
1874             }                                 << 
1875             else // Check intersecting with c << 
1876             if ( yi*cosCPhi-xi*sinCPhi >= 0 ) << 
1877             {                                 << 
1878               // Leaving via ending phi       << 
1879                                               << 
1880               sidephi = kEPhi ;               << 
1881               if ( pDistE <= -halfCarToleranc << 
1882               else                            << 
1883             }                                 << 
1884           }                                   << 
1885         }                                     << 
1886       }                                       << 
1887       else                                    << 
1888       {                                       << 
1889         sphi = kInfinity ;                    << 
1890       }                                       << 
1891     }                                         << 
1892     else                                      << 
1893     {                                         << 
1894       // On z axis + travel not || to z axis  << 
1895       // within phi of shape, Step limited by << 
1896                                                  1783 
1897       if ( (fSPhi-halfAngTolerance <= vphi)   << 1784 //
1898         && (vphi <= fSPhi+fDPhi+halfAngTolera << 1785 // Phi Intersection
1899       {                                       << 1786 //
1900         sphi = kInfinity ;                    << 1787     
1901       }                                       << 1788     if (fDPhi < 2.0*M_PI)
1902       else                                    << 1789   {
1903       {                                       << 1790       sinSPhi=sin(fSPhi);
1904         sidephi = kSPhi  ;   // arbitrary     << 1791       cosSPhi=cos(fSPhi);
1905         sphi    = 0.0 ;                       << 1792 
1906       }                                       << 1793       ePhi=fSPhi+fDPhi;
1907     }                                         << 1794 
1908     if ( sphi < snxt )  // Order intersecttio << 1795       sinEPhi=sin(ePhi);
1909     {                                         << 1796       cosEPhi=cos(ePhi);
1910       snxt = sphi ;                           << 1797       cPhi=fSPhi+fDPhi*0.5;
1911       side = sidephi ;                        << 1798       sinCPhi=sin(cPhi);
1912     }                                         << 1799       cosCPhi=cos(cPhi);
1913   }                                           << 1800 
1914   if ( srd < snxt )  // Order intersections   << 1801 // Check if on z axis (rho not needed later)
1915   {                                           << 1802 
1916     snxt = srd   ;                            << 1803       if (p.x()||p.y())
1917     side = sider ;                            << 1804     {
1918   }                                           << 1805 // pDist -ve when inside
1919   if (calcNorm)                               << 1806 
1920   {                                           << 1807         pDistS=p.x()*sinSPhi-p.y()*cosSPhi;
1921     switch(side)                              << 1808         pDistE=-p.x()*sinEPhi+p.y()*cosEPhi;
1922     {                     // Note: returned v << 1809 
1923       case kRMax:         // (divide by frmax << 1810 // Comp -ve when in direction of outwards normal
1924         xi         = p.x() + snxt*v.x() ;     << 1811 
1925         yi         = p.y() + snxt*v.y() ;     << 1812         compS=-sinSPhi*v.x()+cosSPhi*v.y();
1926         risec      = std::sqrt(xi*xi + yi*yi) << 1813         compE=sinEPhi*v.x()-cosEPhi*v.y();
1927         *n         = G4ThreeVector(xi/risec,y << 1814 
1928         *validNorm = true ;                   << 1815         sidephi=kNull;
1929         break ;                               << 1816 
1930       case kRMin:                             << 1817         if (pDistS <= 0 && pDistE <= 0)
1931         *validNorm = false ;  // Rmin is inco << 1818       {
1932         break ;                               << 1819 // Inside both phi *full* planes
1933       case kSPhi:                             << 1820           if (compS < 0)
1934         if ( fDPhi <= pi )                    << 1821         {
1935         {                                     << 1822             sphi=pDistS/compS;
1936           *n         = G4ThreeVector(sinSPhi, << 1823             xi=p.x()+sphi*v.x();
1937           *validNorm = true ;                 << 1824             yi=p.y()+sphi*v.y();
1938         }                                     << 1825 
1939         else                                  << 1826 // Check intersecting with correct half-plane (if not -> no intersect)
1940         {                                     << 1827             if ((yi*cosCPhi-xi*sinCPhi)>=0)
1941           *validNorm = false ;                << 1828           {
1942         }                                     << 1829               sphi=kInfinity;
1943         break ;                               << 1830           }
1944       case kEPhi:                             << 1831             else
1945         if ( fDPhi <= pi )                    << 1832           {
1946         {                                     << 1833               sidephi=kSPhi;
1947           *n = G4ThreeVector(-sinEPhi, cosEPh << 1834               if (pDistS>-kCarTolerance/2)
1948           *validNorm = true ;                 << 1835             sphi=0;
1949         }                                     << 1836           // Leave by sphi immediately
1950         else                                  << 1837           }
1951         {                                     << 1838         }
1952           *validNorm = false ;                << 1839           else sphi=kInfinity;
1953         }                                     << 1840           
1954         break ;                               << 1841           if (compE < 0)
1955       case kPZ:                               << 1842         {
1956         *n         = G4ThreeVector(0,0,1) ;   << 1843             sphi2=pDistE/compE;
1957         *validNorm = true ;                   << 1844 
1958         break ;                               << 1845 // Only check further if < starting phi intersection
1959       case kMZ:                               << 1846 
1960         *n         = G4ThreeVector(0,0,-1) ;  << 1847             if (sphi2 < sphi)
1961         *validNorm = true ;                   << 1848           {
1962         break ;                               << 1849               xi=p.x()+sphi2*v.x();
1963       default:                                << 1850               yi=p.y()+sphi2*v.y();
1964         G4cout << G4endl ;                    << 1851 // Check intersecting with correct half-plane 
1965         DumpInfo();                           << 1852               if ((yi*cosCPhi-xi*sinCPhi)>=0)
1966         std::ostringstream message;           << 1853             {
1967         G4long oldprc = message.precision(16) << 1854 // Leaving via ending phi
1968         message << "Undefined side for valid  << 1855                 sidephi=kEPhi;
1969                 << G4endl                     << 1856 
1970                 << "Position:"  << G4endl <<  << 1857                 if (pDistE<=-kCarTolerance/2)
1971                 << "p.x() = "   << p.x()/mm < << 1858               {
1972                 << "p.y() = "   << p.y()/mm < << 1859                   sphi=sphi2;
1973                 << "p.z() = "   << p.z()/mm < << 1860               }
1974                 << "pho at z = "   << std::sq << 1861                 else 
1975                 << " mm" << G4endl << G4endl  << 1862               {
1976         if( p.x() != 0. || p.y() != 0.)       << 1863                   sphi=0;
1977         {                                     << 1864               }
1978            message << "point phi = "   << std << 1865             }
1979                    << " degrees" << G4endl << << 1866           }
1980         }                                     << 1867         }
1981         message << "Direction:" << G4endl <<  << 1868           
1982                 << "v.x() = "   << v.x() << G << 1869       }
1983                 << "v.y() = "   << v.y() << G << 1870         else if (pDistS >= 0 && pDistE >= 0)
1984                 << "v.z() = "   << v.z() << G << 1871       {
1985                 << "Proposed distance :" << G << 1872 // Outside both *full* phi planes
1986                 << "snxt = "    << snxt/mm << << 1873                             if (pDistS <= pDistE)
1987         message.precision(oldprc) ;           << 1874           {
1988         G4Exception("G4Cons::DistanceToOut(p, << 1875                               sidephi = kSPhi ;
1989                     JustWarning, message) ;   << 1876           }
1990         break ;                               << 1877                             else
1991     }                                         << 1878           {
1992   }                                           << 1879                               sidephi = kEPhi ;
1993   if (snxt < halfCarTolerance)  { snxt = 0.;  << 1880           }
                                                   >> 1881           if (fDPhi>M_PI)
                                                   >> 1882         {
                                                   >> 1883             if (compS < 0 && compE < 0)
                                                   >> 1884                                     { 
                                                   >> 1885                                         sphi=0;
                                                   >> 1886             }
                                                   >> 1887             else 
                                                   >> 1888                                     {
                                                   >> 1889                                         sphi=kInfinity;
                                                   >> 1890             }
                                                   >> 1891         }
                                                   >> 1892           else
                                                   >> 1893         {
                                                   >> 1894 // if towards both >=0 then once inside (after error) will remain inside
                                                   >> 1895 
                                                   >> 1896             if (compS>=0 && compE>=0)
                                                   >> 1897           {
                                                   >> 1898               sphi=kInfinity;
                                                   >> 1899           }
                                                   >> 1900             else
                                                   >> 1901           {
                                                   >> 1902               sphi=0;
                                                   >> 1903           }
                                                   >> 1904         }
                                                   >> 1905           
                                                   >> 1906       }
                                                   >> 1907         else if (pDistS>0&&pDistE<0)
                                                   >> 1908       {
                                                   >> 1909 // Outside full starting plane, inside full ending plane
                                                   >> 1910           if (fDPhi>M_PI)
                                                   >> 1911         {
                                                   >> 1912             if (compE<0)
                                                   >> 1913           {
                                                   >> 1914               sphi=pDistE/compE;
                                                   >> 1915               xi=p.x()+sphi*v.x();
                                                   >> 1916               yi=p.y()+sphi*v.y();
                                                   >> 1917 // Check intersection in correct half-plane (if not -> not leaving phi extent)
                                                   >> 1918               if ((yi*cosCPhi-xi*sinCPhi)<=0)
                                                   >> 1919             {
                                                   >> 1920                 sphi=kInfinity;
                                                   >> 1921             }
                                                   >> 1922               else
                                                   >> 1923             {
                                                   >> 1924 // Leaving via Ending phi
                                                   >> 1925                                                     sidephi = kEPhi ;
                                                   >> 1926                 if (pDistE>-kCarTolerance/2)
                                                   >> 1927               sphi=0;
                                                   >> 1928             }
                                                   >> 1929           }
                                                   >> 1930             else
                                                   >> 1931           {
                                                   >> 1932               sphi=kInfinity;
                                                   >> 1933           }
                                                   >> 1934         }
                                                   >> 1935           else
                                                   >> 1936         {
                                                   >> 1937             if (compS>=0)
                                                   >> 1938           {
                                                   >> 1939               if (compE<0)
                                                   >> 1940             {
                                                   >> 1941                 
                                                   >> 1942                 sphi=pDistE/compE;
                                                   >> 1943                 xi=p.x()+sphi*v.x();
                                                   >> 1944                 yi=p.y()+sphi*v.y();
                                                   >> 1945 // Check intersection in correct half-plane (if not -> remain in extent)
                                                   >> 1946                 if ((yi*cosCPhi-xi*sinCPhi)<=0)
                                                   >> 1947               {
                                                   >> 1948                   sphi=kInfinity;
                                                   >> 1949               }
                                                   >> 1950                 else
                                                   >> 1951               {
                                                   >> 1952 // otherwise leaving via Ending phi
                                                   >> 1953                   sidephi=kEPhi;
                                                   >> 1954               }
                                                   >> 1955             }
                                                   >> 1956               else sphi=kInfinity;
                                                   >> 1957           }
                                                   >> 1958             else
                                                   >> 1959           {
                                                   >> 1960 // leaving immediately by starting phi
                                                   >> 1961               sidephi=kSPhi;
                                                   >> 1962               sphi=0;
                                                   >> 1963           }
                                                   >> 1964         }
                                                   >> 1965       }
                                                   >> 1966         else
                                                   >> 1967       {
                                                   >> 1968 // Must be pDistS<0&&pDistE>0
                                                   >> 1969 // Inside full starting plane, outside full ending plane
                                                   >> 1970           if (fDPhi>M_PI)
                                                   >> 1971         {
                                                   >> 1972             if (compS<0)
                                                   >> 1973           {
                                                   >> 1974               sphi=pDistS/compS;
                                                   >> 1975               xi=p.x()+sphi*v.x();
                                                   >> 1976               yi=p.y()+sphi*v.y();
                                                   >> 1977 // Check intersection in correct half-plane (if not -> not leaving phi extent)
                                                   >> 1978               if ((yi*cosCPhi-xi*sinCPhi)>=0)
                                                   >> 1979             {
                                                   >> 1980                 sphi=kInfinity;
                                                   >> 1981             }
                                                   >> 1982               else
                                                   >> 1983             {
                                                   >> 1984 // Leaving via Starting phi
                                                   >> 1985                                                     sidephi = kSPhi ;   
                                                   >> 1986                 if (pDistS>-kCarTolerance/2)
                                                   >> 1987               sphi=0;
                                                   >> 1988             }
                                                   >> 1989           }
                                                   >> 1990             else
                                                   >> 1991           {
                                                   >> 1992               sphi=kInfinity;
                                                   >> 1993           }
                                                   >> 1994         }
                                                   >> 1995           else
                                                   >> 1996         {
                                                   >> 1997             if (compE>=0)
                                                   >> 1998           {
                                                   >> 1999               if (compS<0)
                                                   >> 2000             {
                                                   >> 2001                 
                                                   >> 2002                 sphi=pDistS/compS;
                                                   >> 2003                 xi=p.x()+sphi*v.x();
                                                   >> 2004                 yi=p.y()+sphi*v.y();
                                                   >> 2005 // Check intersection in correct half-plane (if not -> remain in extent)
                                                   >> 2006                 if ((yi*cosCPhi-xi*sinCPhi)>=0)
                                                   >> 2007                   {
                                                   >> 2008                 sphi=kInfinity;
                                                   >> 2009                   }
                                                   >> 2010                 else
                                                   >> 2011               {
                                                   >> 2012 // otherwise leaving via Starting phi
                                                   >> 2013                   sidephi=kSPhi;
                                                   >> 2014               }
                                                   >> 2015             }
                                                   >> 2016               else
                                                   >> 2017             {
                                                   >> 2018                 sphi=kInfinity;
                                                   >> 2019             }
                                                   >> 2020           }
                                                   >> 2021             else
                                                   >> 2022           {
                                                   >> 2023 // leaving immediately by ending
                                                   >> 2024               sidephi=kEPhi;
                                                   >> 2025               sphi=0;
                                                   >> 2026           }
                                                   >> 2027         }
                                                   >> 2028       }
                                                   >> 2029         
                                                   >> 2030     }
                                                   >> 2031       else
                                                   >> 2032     {
                                                   >> 2033 // On z axis + travel not || to z axis -> if phi of vector direction
                                                   >> 2034 // within phi of shape, Step limited by rmax, else Step =0
                                                   >> 2035         vphi=atan2(v.y(),v.x());
                                                   >> 2036         if (fSPhi<vphi&&vphi<fSPhi+fDPhi)
                                                   >> 2037       {
                                                   >> 2038           sphi=kInfinity;
                                                   >> 2039       }
                                                   >> 2040         else
                                                   >> 2041       {
                                                   >> 2042                             sidephi = kSPhi ; // arbitrary 
                                                   >> 2043           sphi=0;
                                                   >> 2044       }
                                                   >> 2045     }
                                                   >> 2046       
                                                   >> 2047 // Order intersecttions
                                                   >> 2048       if (sphi<snxt)
                                                   >> 2049     {
                                                   >> 2050         snxt=sphi;
                                                   >> 2051         side=sidephi;
                                                   >> 2052     }
                                                   >> 2053   }
                                                   >> 2054 // Order intersections
                                                   >> 2055     if (sr<snxt)
                                                   >> 2056   {
                                                   >> 2057       snxt=sr;
                                                   >> 2058       side=sider;
                                                   >> 2059   }
                                                   >> 2060 
                                                   >> 2061     if (calcNorm)
                                                   >> 2062   {
                                                   >> 2063       switch(side)
                                                   >> 2064     {
                                                   >> 2065     case kRMax:
                                                   >> 2066           // Note: returned vector not normalised
                                                   >> 2067           // (divide by frmax for unit vector)
                                                   >> 2068         xi=p.x()+snxt*v.x();
                                                   >> 2069         yi=p.y()+snxt*v.y();
                                                   >> 2070         risec=sqrt(xi*xi+yi*yi)*secRMax;
                                                   >> 2071         *n=G4ThreeVector(xi/risec,yi/risec,-tanRMax/secRMax);
                                                   >> 2072         *validNorm=true;
                                                   >> 2073         break;
                                                   >> 2074     case kRMin:
                                                   >> 2075         *validNorm=false; // Rmin is inconvex
                                                   >> 2076         break;
                                                   >> 2077     case kSPhi:
                                                   >> 2078         if (fDPhi<=M_PI)
                                                   >> 2079       {
                                                   >> 2080           *n=G4ThreeVector(sin(fSPhi),-cos(fSPhi),0);
                                                   >> 2081           *validNorm=true;
                                                   >> 2082       }
                                                   >> 2083         else
                                                   >> 2084       {
                                                   >> 2085           *validNorm=false;
                                                   >> 2086       }
                                                   >> 2087         break;
                                                   >> 2088     case kEPhi:
                                                   >> 2089         if (fDPhi<=M_PI)
                                                   >> 2090       {
                                                   >> 2091       *n=G4ThreeVector(-sin(fSPhi+fDPhi),cos(fSPhi+fDPhi),0);
                                                   >> 2092       *validNorm=true;
                                                   >> 2093       }
                                                   >> 2094         else
                                                   >> 2095       {
                                                   >> 2096           *validNorm=false;
                                                   >> 2097       }
                                                   >> 2098         break;
                                                   >> 2099     case kPZ:
                                                   >> 2100         *n=G4ThreeVector(0,0,1);
                                                   >> 2101         *validNorm=true;
                                                   >> 2102         break;
                                                   >> 2103     case kMZ:
                                                   >> 2104         *n=G4ThreeVector(0,0,-1);
                                                   >> 2105         *validNorm=true;
                                                   >> 2106         break;
                                                   >> 2107     default:
                                                   >> 2108         G4Exception("Invalid enum in G4Cons::DistanceToOut");
                                                   >> 2109         break;
                                                   >> 2110     }
                                                   >> 2111   }
1994                                                  2112 
1995   return snxt ;                               << 2113     return snxt;
1996 }                                                2114 }
1997                                                  2115 
1998 /////////////////////////////////////////////    2116 //////////////////////////////////////////////////////////////////
1999 //                                               2117 //
2000 // Calculate distance (<=actual) to closest s    2118 // Calculate distance (<=actual) to closest surface of shape from inside
2001                                                  2119 
2002 G4double G4Cons::DistanceToOut(const G4ThreeV    2120 G4double G4Cons::DistanceToOut(const G4ThreeVector& p) const
2003 {                                                2121 {
2004   G4double safe=0.0, rho, safeR1, safeR2, saf << 2122     G4double safe,rho,safeR1,safeR2,safeZ;
2005   G4double tanRMin, secRMin, pRMin;           << 2123     G4double tanRMin,secRMin,pRMin;
2006   G4double tanRMax, secRMax, pRMax;           << 2124     G4double tanRMax,secRMax,pRMax;
2007                                               << 2125     G4double safePhi,phiC,cosPhiC,sinPhiC,ePhi;
2008 #ifdef G4CSGDEBUG                             << 2126     rho=sqrt(p.x()*p.x()+p.y()*p.y());
2009   if( Inside(p) == kOutside )                 << 2127 
2010   {                                           << 2128     safeZ=fDz-fabs(p.z());
2011     G4int oldprc=G4cout.precision(16) ;       << 2129 
2012     G4cout << G4endl ;                        << 2130     if (fRmin1||fRmin2)
2013     DumpInfo();                               << 2131   {
2014     G4cout << "Position:"  << G4endl << G4end << 2132       tanRMin=(fRmin2-fRmin1)*0.5/fDz;
2015     G4cout << "p.x() = "   << p.x()/mm << " m << 2133       secRMin=sqrt(1.0+tanRMin*tanRMin);
2016     G4cout << "p.y() = "   << p.y()/mm << " m << 2134       pRMin=tanRMin*p.z()+(fRmin1+fRmin2)*0.5;
2017     G4cout << "p.z() = "   << p.z()/mm << " m << 2135       safeR1=(rho-pRMin)/secRMin;
2018     G4cout << "pho at z = "   << std::sqrt( p << 2136   }
2019            << " mm" << G4endl << G4endl ;     << 
2020     if( (p.x() != 0.) || (p.x() != 0.) )      << 
2021     {                                         << 
2022       G4cout << "point phi = "   << std::atan << 
2023              << " degrees" << G4endl << G4end << 
2024     }                                         << 
2025     G4cout.precision(oldprc) ;                << 
2026     G4Exception("G4Cons::DistanceToOut(p)", " << 
2027                 JustWarning, "Point p is outs << 
2028   }                                           << 
2029 #endif                                        << 
2030                                               << 
2031   rho = std::sqrt(p.x()*p.x() + p.y()*p.y())  << 
2032   safeZ = fDz - std::fabs(p.z()) ;            << 
2033                                               << 
2034   if ((fRmin1 != 0.0) || (fRmin2 != 0.0))     << 
2035   {                                           << 
2036     tanRMin = (fRmin2 - fRmin1)*0.5/fDz ;     << 
2037     secRMin = std::sqrt(1.0 + tanRMin*tanRMin << 
2038     pRMin   = tanRMin*p.z() + (fRmin1 + fRmin << 
2039     safeR1  = (rho - pRMin)/secRMin ;         << 
2040   }                                           << 
2041   else                                        << 
2042   {                                           << 
2043     safeR1 = kInfinity ;                      << 
2044   }                                           << 
2045                                               << 
2046   tanRMax = (fRmax2 - fRmax1)*0.5/fDz ;       << 
2047   secRMax = std::sqrt(1.0 + tanRMax*tanRMax)  << 
2048   pRMax   = tanRMax*p.z() + (fRmax1+fRmax2)*0 << 
2049   safeR2  = (pRMax - rho)/secRMax ;           << 
2050                                               << 
2051   if (safeR1 < safeR2)  { safe = safeR1; }    << 
2052   else                  { safe = safeR2; }    << 
2053   if (safeZ < safe)     { safe = safeZ ; }    << 
2054                                               << 
2055   // Check if phi divided, Calc distances clo << 
2056                                               << 
2057   if (!fPhiFullCone)                          << 
2058   {                                           << 
2059     // Above/below central phi of G4Cons?     << 
2060                                               << 
2061     if ( (p.y()*cosCPhi - p.x()*sinCPhi) <= 0 << 
2062     {                                         << 
2063       safePhi = -(p.x()*sinSPhi - p.y()*cosSP << 
2064     }                                         << 
2065     else                                         2137     else
2066     {                                         << 2138   {
2067       safePhi = (p.x()*sinEPhi - p.y()*cosEPh << 2139       safeR1=kInfinity;
2068     }                                         << 2140   }
2069     if (safePhi < safe)  { safe = safePhi; }  << 2141 
2070   }                                           << 2142     tanRMax=(fRmax2-fRmax1)*0.5/fDz;
2071   if ( safe < 0 )  { safe = 0; }              << 2143     secRMax=sqrt(1.0+tanRMax*tanRMax);
2072                                               << 2144     pRMax=tanRMax*p.z()+(fRmax1+fRmax2)*0.5;
2073   return safe ;                               << 2145     safeR2=(pRMax-rho)/secRMax;
                                                   >> 2146 
                                                   >> 2147     if (safeR1<safeR2) safe=safeR1;
                                                   >> 2148     else safe=safeR2;
                                                   >> 2149     if (safeZ<safe) safe=safeZ;
                                                   >> 2150 
                                                   >> 2151 // Check if phi divided, Calc distances closest phi plane
                                                   >> 2152     if (fDPhi<2.0*M_PI)
                                                   >> 2153   {
                                                   >> 2154 // Above/below central phi of G4Cons?
                                                   >> 2155       phiC=fSPhi+fDPhi*0.5;
                                                   >> 2156       cosPhiC=cos(phiC);
                                                   >> 2157       sinPhiC=sin(phiC);
                                                   >> 2158       if ((p.y()*cosPhiC-p.x()*sinPhiC)<=0)
                                                   >> 2159     {
                                                   >> 2160         safePhi=-(p.x()*sin(fSPhi)-p.y()*cos(fSPhi));
                                                   >> 2161     }
                                                   >> 2162       else
                                                   >> 2163     {
                                                   >> 2164         ePhi=fSPhi+fDPhi;
                                                   >> 2165         safePhi=(p.x()*sin(ePhi)-p.y()*cos(ePhi));
                                                   >> 2166     }
                                                   >> 2167       if (safePhi<safe) safe=safePhi;
                                                   >> 2168   }
                                                   >> 2169     if (safe<0) safe=0;
                                                   >> 2170     return safe;  
2074 }                                                2171 }
2075                                                  2172 
2076 ///////////////////////////////////////////// << 2173 ////////////////////////////////////////////////////////////////////////////
2077 //                                               2174 //
2078 // GetEntityType                              << 2175 // Create a List containing the transformed vertices
                                                   >> 2176 // Ordering [0-3] -fDz cross section
                                                   >> 2177 //          [4-7] +fDz cross section such that [0] is below [4],
                                                   >> 2178 //                                             [1] below [5] etc.
                                                   >> 2179 // Note:
                                                   >> 2180 //  Caller has deletion resposibility
                                                   >> 2181 //  Potential improvement: For last slice, use actual ending angle
                                                   >> 2182 //                         to avoid rounding error problems.
2079                                                  2183 
2080 G4GeometryType G4Cons::GetEntityType() const  << 2184 G4ThreeVectorList*
                                                   >> 2185 G4Cons::CreateRotatedVertices(const G4AffineTransform& pTransform) const
2081 {                                                2186 {
2082   return {"G4Cons"};                          << 2187     G4ThreeVectorList *vertices;
2083 }                                             << 2188     G4ThreeVector vertex0,vertex1,vertex2,vertex3;
                                                   >> 2189     G4double meshAngle,meshRMax1,meshRMax2,crossAngle,cosCrossAngle,sinCrossAngle,sAngle;
                                                   >> 2190     G4double rMaxX1,rMaxX2,rMaxY1,rMaxY2,rMinX1,rMinX2,rMinY1,rMinY2;
                                                   >> 2191     G4int crossSection,noCrossSections;
2084                                                  2192 
2085 ///////////////////////////////////////////// << 2193 // Compute no of cross-sections necessary to mesh cone
2086 //                                            << 2194     
2087 // Make a clone of the object                 << 2195     noCrossSections=G4int (fDPhi/kMeshAngleDefault)+1;
2088 //                                            << 2196     if (noCrossSections<kMinMeshSections)
2089 G4VSolid* G4Cons::Clone() const               << 2197   {
2090 {                                             << 2198       noCrossSections=kMinMeshSections;
2091   return new G4Cons(*this);                   << 2199   }
                                                   >> 2200     else if (noCrossSections>kMaxMeshSections)
                                                   >> 2201   {
                                                   >> 2202       noCrossSections=kMaxMeshSections;
                                                   >> 2203   }
                                                   >> 2204   
                                                   >> 2205     meshAngle=fDPhi/(noCrossSections-1);
                                                   >> 2206 
                                                   >> 2207     // G4double RMax = (fRmax2 >= fRmax1) ? fRmax2 : fRmax1 ;
                                                   >> 2208     meshRMax1=fRmax1/cos(meshAngle*0.5);
                                                   >> 2209     meshRMax2=fRmax2/cos(meshAngle*0.5);
                                                   >> 2210 
                                                   >> 2211 // If complete in phi, set start angle such that mesh will be at RMax
                                                   >> 2212 // on the x axis. Will give better extent calculations when not rotated.
                                                   >> 2213     if (fDPhi==M_PI*2.0&&fSPhi==0)
                                                   >> 2214   {
                                                   >> 2215       sAngle=-meshAngle*0.5;
                                                   >> 2216   }
                                                   >> 2217     else
                                                   >> 2218   {
                                                   >> 2219       sAngle=fSPhi;
                                                   >> 2220   }
                                                   >> 2221     
                                                   >> 2222     vertices=new G4ThreeVectorList(noCrossSections*4);
                                                   >> 2223     if (vertices)
                                                   >> 2224   {
                                                   >> 2225       for (crossSection=0;crossSection<noCrossSections;crossSection++)
                                                   >> 2226     {
                                                   >> 2227 // Compute coordinates of cross section at section crossSection
                                                   >> 2228         crossAngle=sAngle+crossSection*meshAngle;
                                                   >> 2229         cosCrossAngle=cos(crossAngle);
                                                   >> 2230         sinCrossAngle=sin(crossAngle);
                                                   >> 2231 
                                                   >> 2232         rMaxX1=meshRMax1*cosCrossAngle;
                                                   >> 2233         rMaxY1=meshRMax1*sinCrossAngle;
                                                   >> 2234         rMaxX2=meshRMax2*cosCrossAngle;
                                                   >> 2235         rMaxY2=meshRMax2*sinCrossAngle;
                                                   >> 2236         
                                                   >> 2237         // G4double RMin = (fRmin2 <= fRmin1) ? fRmin2 : fRmin1 ;
                                                   >> 2238         rMinX1=fRmin1*cosCrossAngle;
                                                   >> 2239         rMinY1=fRmin1*sinCrossAngle;
                                                   >> 2240         rMinX2=fRmin2*cosCrossAngle;
                                                   >> 2241         rMinY2=fRmin2*sinCrossAngle;
                                                   >> 2242         
                                                   >> 2243         vertex0=G4ThreeVector(rMinX1,rMinY1,-fDz);
                                                   >> 2244         vertex1=G4ThreeVector(rMaxX1,rMaxY1,-fDz);
                                                   >> 2245         vertex2=G4ThreeVector(rMaxX2,rMaxY2,+fDz);
                                                   >> 2246         vertex3=G4ThreeVector(rMinX2,rMinY2,+fDz);
                                                   >> 2247 
                                                   >> 2248         vertices->insert(pTransform.TransformPoint(vertex0));
                                                   >> 2249         vertices->insert(pTransform.TransformPoint(vertex1));
                                                   >> 2250         vertices->insert(pTransform.TransformPoint(vertex2));
                                                   >> 2251         vertices->insert(pTransform.TransformPoint(vertex3));
                                                   >> 2252     }
                                                   >> 2253   }
                                                   >> 2254     else
                                                   >> 2255   {
                                                   >> 2256       G4Exception("G4Cons::CreateRotatedVertices Out of memory - Cannot alloc vertices");
                                                   >> 2257   }
                                                   >> 2258     return vertices;
2092 }                                                2259 }
2093                                                  2260 
2094 /////////////////////////////////////////////    2261 //////////////////////////////////////////////////////////////////////////
2095 //                                               2262 //
2096 // Stream object contents to an output stream << 2263 // Methods for visualisation
2097                                                  2264 
2098 std::ostream& G4Cons::StreamInfo(std::ostream << 2265 void G4Cons::DescribeYourselfTo (G4VGraphicsScene& scene) const
2099 {                                                2266 {
2100   G4long oldprc = os.precision(16);           << 2267   scene.AddThis (*this);
2101   os << "------------------------------------ << 
2102      << "    *** Dump for solid - " << GetNam << 
2103      << "    ================================ << 
2104      << " Solid type: G4Cons\n"               << 
2105      << " Parameters: \n"                     << 
2106      << "   inside  -fDz radius: "  << fRmin1 << 
2107      << "   outside -fDz radius: "  << fRmax1 << 
2108      << "   inside  +fDz radius: "  << fRmin2 << 
2109      << "   outside +fDz radius: "  << fRmax2 << 
2110      << "   half length in Z   : "  << fDz/mm << 
2111      << "   starting angle of segment: " << f << 
2112      << "   delta angle of segment   : " << f << 
2113      << "------------------------------------ << 
2114   os.precision(oldprc);                       << 
2115                                               << 
2116   return os;                                  << 
2117 }                                                2268 }
2118                                                  2269 
                                                   >> 2270   // Define the sides of the box into which the G4Cons instance would fit.
2119                                                  2271 
2120                                               << 2272 G4VisExtent G4Cons::GetExtent() const
2121 ///////////////////////////////////////////// << 
2122 //                                            << 
2123 // GetPointOnSurface                          << 
2124                                               << 
2125 G4ThreeVector G4Cons::GetPointOnSurface() con << 
2126 {                                                2273 {
2127   // declare working variables                << 2274     G4double RMax = (fRmax2 >= fRmax1) ? fRmax2 : fRmax1 ;
2128   //                                          << 2275     
2129   G4double rone = (fRmax1-fRmax2)/(2.*fDz);   << 2276     return G4VisExtent (-RMax, RMax, -RMax, RMax, -fDz, fDz);
2130   G4double rtwo = (fRmin1-fRmin2)/(2.*fDz);   << 
2131   G4double qone = (fRmax1 == fRmax2) ? 0. : f << 
2132   G4double qtwo = (fRmin1 == fRmin2) ? 0. : f << 
2133                                               << 
2134   G4double slin   = std::hypot(fRmin1-fRmin2, << 
2135   G4double slout  = std::hypot(fRmax1-fRmax2, << 
2136   G4double Aone   = 0.5*fDPhi*(fRmax2 + fRmax << 
2137   G4double Atwo   = 0.5*fDPhi*(fRmin2 + fRmin << 
2138   G4double Athree = 0.5*fDPhi*(fRmax1*fRmax1- << 
2139   G4double Afour  = 0.5*fDPhi*(fRmax2*fRmax2- << 
2140   G4double Afive  = fDz*(fRmax1-fRmin1+fRmax2 << 
2141                                               << 
2142   G4double phi    = G4RandFlat::shoot(fSPhi,f << 
2143   G4double cosu   = std::cos(phi);            << 
2144   G4double sinu   = std::sin(phi);            << 
2145   G4double rRand1 = GetRadiusInRing(fRmin1, f << 
2146   G4double rRand2 = GetRadiusInRing(fRmin2, f << 
2147                                               << 
2148   if ( (fSPhi == 0.) && fPhiFullCone )  { Afi << 
2149   G4double chose  = G4RandFlat::shoot(0.,Aone << 
2150                                               << 
2151   if( (chose >= 0.) && (chose < Aone) ) // ou << 
2152   {                                           << 
2153     if(fRmax1 != fRmax2)                      << 
2154     {                                         << 
2155       G4double zRand = G4RandFlat::shoot(-1.* << 
2156       return { rone*cosu*(qone-zRand), rone*s << 
2157     }                                         << 
2158     else                                      << 
2159     {                                         << 
2160       return { fRmax1*cosu, fRmax2*sinu, G4Ra << 
2161     }                                         << 
2162   }                                           << 
2163   else if( (chose >= Aone) && (chose < Aone + << 
2164   {                                           << 
2165     if(fRmin1 != fRmin2)                      << 
2166     {                                         << 
2167       G4double zRand = G4RandFlat::shoot(-1.* << 
2168       return { rtwo*cosu*(qtwo-zRand), rtwo*s << 
2169     }                                         << 
2170     else                                      << 
2171     {                                         << 
2172       return { fRmin1*cosu, fRmin2*sinu, G4Ra << 
2173     }                                         << 
2174   }                                           << 
2175   else if( (chose >= Aone + Atwo) && (chose < << 
2176   {                                           << 
2177     return {rRand1*cosu, rRand1*sinu, -1*fDz} << 
2178   }                                           << 
2179   else if( (chose >= Aone + Atwo + Athree)    << 
2180         && (chose < Aone + Atwo + Athree + Af << 
2181   {                                           << 
2182     return { rRand2*cosu, rRand2*sinu, fDz }; << 
2183   }                                           << 
2184   else if( (chose >= Aone + Atwo + Athree + A << 
2185         && (chose < Aone + Atwo + Athree + Af << 
2186   {                                           << 
2187     G4double zRand  = G4RandFlat::shoot(-1.*f << 
2188     rRand1 = G4RandFlat::shoot(fRmin2-((zRand << 
2189                                fRmax2-((zRand << 
2190     return { rRand1*cosSPhi, rRand1*sinSPhi,  << 
2191   }                                           << 
2192   else // SPhi+DPhi section                   << 
2193   {                                           << 
2194     G4double zRand  = G4RandFlat::shoot(-1.*f << 
2195     rRand1 = G4RandFlat::shoot(fRmin2-((zRand << 
2196                                fRmax2-((zRand << 
2197     return { rRand1*cosEPhi, rRand1*sinEPhi,  << 
2198   }                                           << 
2199 }                                                2277 }
2200                                                  2278 
2201 ///////////////////////////////////////////// << 2279 G4Polyhedron* G4Cons::CreatePolyhedron () const
2202 //                                            << 
2203 // Methods for visualisation                  << 
2204                                               << 
2205 void G4Cons::DescribeYourselfTo (G4VGraphicsS << 
2206 {                                                2280 {
2207   scene.AddSolid (*this);                     << 2281     return new G4PolyhedronCons(fRmin1, fRmax1, fRmin2, fRmax2, fDz, fSPhi,
                                                   >> 2282                                 fDPhi);
2208 }                                                2283 }
2209                                                  2284 
2210 G4Polyhedron* G4Cons::CreatePolyhedron () con << 2285 G4NURBS* G4Cons::CreateNURBS () const
2211 {                                                2286 {
2212   return new G4PolyhedronCons(fRmin1,fRmax1,f << 2287     G4double RMax = (fRmax2 >= fRmax1) ? fRmax2 : fRmax1 ;
                                                   >> 2288     
                                                   >> 2289     return new G4NURBSbox (RMax, RMax, fDz);       // Box for now!!!
2213 }                                                2290 }
2214                                                  2291 
2215 #endif                                        << 2292 //
                                                   >> 2293 //
                                                   >> 2294 /////////////////////////////// End of G4Cons.cc file //////////////////////
                                                   >> 2295 
                                                   >> 2296 
                                                   >> 2297 
                                                   >> 2298 
                                                   >> 2299 
                                                   >> 2300 
2216                                                  2301