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


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