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 7.1)


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