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


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