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