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.6.p4)


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