Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/solids/specific/src/G4Paraboloid.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/specific/src/G4Paraboloid.cc (Version 11.3.0) and /geometry/solids/specific/src/G4Paraboloid.cc (Version 10.4.p1)


  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 // $Id: G4Paraboloid.cc 104316 2017-05-24 13:04:23Z gcosmo $
                                                   >>  27 //
                                                   >>  28 // class G4Paraboloid
                                                   >>  29 //
 26 // Implementation for G4Paraboloid class           30 // Implementation for G4Paraboloid class
 27 //                                                 31 //
 28 // Author : Lukas Lindroos (CERN), July 2007       32 // Author : Lukas Lindroos (CERN), July 2007
 29 // Revised: Tatiana Nikitina (CERN)                33 // Revised: Tatiana Nikitina (CERN)
 30 // -------------------------------------------     34 // --------------------------------------------------------------------
 31                                                    35 
 32 #include "globals.hh"                              36 #include "globals.hh"
 33                                                    37 
 34 #include "G4Paraboloid.hh"                         38 #include "G4Paraboloid.hh"
 35                                                    39 
 36 #if !(defined(G4GEOM_USE_UPARABOLOID) && defin     40 #if !(defined(G4GEOM_USE_UPARABOLOID) && defined(G4GEOM_USE_SYS_USOLIDS))
 37                                                    41 
 38 #include "G4VoxelLimits.hh"                        42 #include "G4VoxelLimits.hh"
 39 #include "G4AffineTransform.hh"                    43 #include "G4AffineTransform.hh"
 40 #include "G4BoundingEnvelope.hh"                   44 #include "G4BoundingEnvelope.hh"
 41                                                    45 
 42 #include "meshdefs.hh"                             46 #include "meshdefs.hh"
 43                                                    47 
 44 #include "Randomize.hh"                            48 #include "Randomize.hh"
 45                                                    49 
 46 #include "G4VGraphicsScene.hh"                     50 #include "G4VGraphicsScene.hh"
 47 #include "G4VisExtent.hh"                          51 #include "G4VisExtent.hh"
 48                                                    52 
 49 #include "G4AutoLock.hh"                           53 #include "G4AutoLock.hh"
 50                                                    54 
 51 namespace                                          55 namespace
 52 {                                                  56 {
 53   G4Mutex polyhedronMutex = G4MUTEX_INITIALIZE     57   G4Mutex polyhedronMutex = G4MUTEX_INITIALIZER;
 54 }                                                  58 }
 55                                                    59 
 56 using namespace CLHEP;                             60 using namespace CLHEP;
 57                                                    61 
 58 //////////////////////////////////////////////     62 ///////////////////////////////////////////////////////////////////////////////
 59 //                                                 63 //
 60 // constructor - check parameters                  64 // constructor - check parameters
 61 //                                             <<  65 
 62 G4Paraboloid::G4Paraboloid(const G4String& pNa     66 G4Paraboloid::G4Paraboloid(const G4String& pName,
 63                                  G4double pDz,     67                                  G4double pDz,
 64                                  G4double pR1,     68                                  G4double pR1,
 65                                  G4double pR2)     69                                  G4double pR2)
 66  : G4VSolid(pName)                             <<  70  : G4VSolid(pName), fRebuildPolyhedron(false), fpPolyhedron(0),
                                                   >>  71    fSurfaceArea(0.), fCubicVolume(0.) 
                                                   >>  72 
 67 {                                                  73 {
 68   if( (pDz <= 0.) || (pR2 <= pR1) || (pR1 < 0.     74   if( (pDz <= 0.) || (pR2 <= pR1) || (pR1 < 0.) )
 69   {                                                75   {
 70     std::ostringstream message;                    76     std::ostringstream message;
 71     message << "Invalid dimensions. Negative I     77     message << "Invalid dimensions. Negative Input Values or R1>=R2 - "
 72             << GetName();                          78             << GetName();
 73     G4Exception("G4Paraboloid::G4Paraboloid()"     79     G4Exception("G4Paraboloid::G4Paraboloid()", "GeomSolids0002", 
 74                 FatalErrorInArgument, message,     80                 FatalErrorInArgument, message,
 75                 "Z half-length must be larger      81                 "Z half-length must be larger than zero or R1>=R2.");
 76   }                                                82   }
 77                                                    83 
 78   r1 = pR1;                                        84   r1 = pR1;
 79   r2 = pR2;                                        85   r2 = pR2;
 80   dz = pDz;                                        86   dz = pDz;
 81                                                    87 
 82   // r1^2 = k1 * (-dz) + k2                        88   // r1^2 = k1 * (-dz) + k2
 83   // r2^2 = k1 * ( dz) + k2                        89   // r2^2 = k1 * ( dz) + k2
 84   // => r1^2 + r2^2 = k2 + k2 => k2 = (r2^2 +      90   // => r1^2 + r2^2 = k2 + k2 => k2 = (r2^2 + r1^2) / 2
 85   // and r2^2 - r1^2 = k1 * dz - k1 * (-dz) =>     91   // and r2^2 - r1^2 = k1 * dz - k1 * (-dz) => k1 = (r2^2 - r1^2) / 2 / dz
 86                                                    92 
 87   k1 = (r2 * r2 - r1 * r1) / 2 / dz;               93   k1 = (r2 * r2 - r1 * r1) / 2 / dz;
 88   k2 = (r2 * r2 + r1 * r1) / 2;                    94   k2 = (r2 * r2 + r1 * r1) / 2;
 89 }                                                  95 }
 90                                                    96 
 91 //////////////////////////////////////////////     97 ///////////////////////////////////////////////////////////////////////////////
 92 //                                                 98 //
 93 // Fake default constructor - sets only member     99 // Fake default constructor - sets only member data and allocates memory
 94 //                            for usage restri    100 //                            for usage restricted to object persistency.
 95 //                                                101 //
 96 G4Paraboloid::G4Paraboloid( __void__& a )         102 G4Paraboloid::G4Paraboloid( __void__& a )
 97   : G4VSolid(a), dz(0.), r1(0.), r2(0.), k1(0. << 103   : G4VSolid(a), fRebuildPolyhedron(false), fpPolyhedron(0),
                                                   >> 104     fSurfaceArea(0.), fCubicVolume(0.),
                                                   >> 105     dz(0.), r1(0.), r2(0.), k1(0.), k2(0.)
 98 {                                                 106 {
 99 }                                                 107 }
100                                                   108 
101 //////////////////////////////////////////////    109 ///////////////////////////////////////////////////////////////////////////////
102 //                                                110 //
103 // Destructor                                     111 // Destructor
104 //                                             << 112 
105 G4Paraboloid::~G4Paraboloid()                     113 G4Paraboloid::~G4Paraboloid()
106 {                                                 114 {
107   delete fpPolyhedron; fpPolyhedron = nullptr; << 115   delete fpPolyhedron; fpPolyhedron = 0;
108 }                                                 116 }
109                                                   117 
110 //////////////////////////////////////////////    118 ///////////////////////////////////////////////////////////////////////////////
111 //                                                119 //
112 // Copy constructor                               120 // Copy constructor
113 //                                             << 121 
114 G4Paraboloid::G4Paraboloid(const G4Paraboloid&    122 G4Paraboloid::G4Paraboloid(const G4Paraboloid& rhs)
115   : G4VSolid(rhs),                             << 123   : G4VSolid(rhs), fRebuildPolyhedron(false), fpPolyhedron(0),
116     fSurfaceArea(rhs.fSurfaceArea), fCubicVolu    124     fSurfaceArea(rhs.fSurfaceArea), fCubicVolume(rhs.fCubicVolume),
117     dz(rhs.dz), r1(rhs.r1), r2(rhs.r2), k1(rhs    125     dz(rhs.dz), r1(rhs.r1), r2(rhs.r2), k1(rhs.k1), k2(rhs.k2)
118 {                                                 126 {
119 }                                                 127 }
120                                                   128 
                                                   >> 129 
121 //////////////////////////////////////////////    130 ///////////////////////////////////////////////////////////////////////////////
122 //                                                131 //
123 // Assignment operator                            132 // Assignment operator
124 //                                             << 133 
125 G4Paraboloid& G4Paraboloid::operator = (const     134 G4Paraboloid& G4Paraboloid::operator = (const G4Paraboloid& rhs) 
126 {                                                 135 {
127    // Check assignment to self                    136    // Check assignment to self
128    //                                             137    //
129    if (this == &rhs)  { return *this; }           138    if (this == &rhs)  { return *this; }
130                                                   139 
131    // Copy base class data                        140    // Copy base class data
132    //                                             141    //
133    G4VSolid::operator=(rhs);                      142    G4VSolid::operator=(rhs);
134                                                   143 
135    // Copy data                                   144    // Copy data
136    //                                             145    //
137    fSurfaceArea = rhs.fSurfaceArea; fCubicVolu    146    fSurfaceArea = rhs.fSurfaceArea; fCubicVolume = rhs.fCubicVolume;
138    dz = rhs.dz; r1 = rhs.r1; r2 = rhs.r2; k1 =    147    dz = rhs.dz; r1 = rhs.r1; r2 = rhs.r2; k1 = rhs.k1; k2 = rhs.k2;
139    fRebuildPolyhedron = false;                    148    fRebuildPolyhedron = false;
140    delete fpPolyhedron; fpPolyhedron = nullptr << 149    delete fpPolyhedron; fpPolyhedron = 0;
141                                                   150 
142    return *this;                                  151    return *this;
143 }                                                 152 }
144                                                   153 
                                                   >> 154 /////////////////////////////////////////////////////////////////////////
                                                   >> 155 //
                                                   >> 156 // Dispatch to parameterisation for replication mechanism dimension
                                                   >> 157 // computation & modification.
                                                   >> 158 
                                                   >> 159 //void ComputeDimensions(       G4VPVParamerisation p,
                                                   >> 160 //                        const G4Int               n,
                                                   >> 161 //                        const G4VPhysicalVolume*  pRep )
                                                   >> 162 //{
                                                   >> 163 //  p->ComputeDimensions(*this,n,pRep) ;
                                                   >> 164 //}
                                                   >> 165 
145 //////////////////////////////////////////////    166 ///////////////////////////////////////////////////////////////////////////////
146 //                                                167 //
147 // Get bounding box                               168 // Get bounding box
148 //                                             << 169 
149 void G4Paraboloid::BoundingLimits(G4ThreeVecto    170 void G4Paraboloid::BoundingLimits(G4ThreeVector& pMin,
150                                   G4ThreeVecto    171                                   G4ThreeVector& pMax) const
151 {                                                 172 {
152   pMin.set(-r2,-r2,-dz);                          173   pMin.set(-r2,-r2,-dz);
153   pMax.set( r2, r2, dz);                          174   pMax.set( r2, r2, dz);
154                                                   175 
155   // Check correctness of the bounding box        176   // Check correctness of the bounding box
156   //                                              177   //
157   if (pMin.x() >= pMax.x() || pMin.y() >= pMax    178   if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
158   {                                               179   {
159     std::ostringstream message;                   180     std::ostringstream message;
160     message << "Bad bounding box (min >= max)     181     message << "Bad bounding box (min >= max) for solid: "
161             << GetName() << " !"                  182             << GetName() << " !"
162             << "\npMin = " << pMin                183             << "\npMin = " << pMin
163             << "\npMax = " << pMax;               184             << "\npMax = " << pMax;
164     G4Exception("G4Paraboloid::BoundingLimits(    185     G4Exception("G4Paraboloid::BoundingLimits()", "GeomMgt0001",
165                 JustWarning, message);            186                 JustWarning, message);
166     DumpInfo();                                   187     DumpInfo();
167   }                                               188   }
168 }                                                 189 }
169                                                   190 
170 //////////////////////////////////////////////    191 ///////////////////////////////////////////////////////////////////////////////
171 //                                                192 //
172 // Calculate extent under transform and specif    193 // Calculate extent under transform and specified limit
173 //                                             << 194 
174 G4bool                                            195 G4bool
175 G4Paraboloid::CalculateExtent(const EAxis pAxi    196 G4Paraboloid::CalculateExtent(const EAxis pAxis,
176                               const G4VoxelLim << 197                              const G4VoxelLimits& pVoxelLimit,
177                               const G4AffineTr << 198                              const G4AffineTransform& pTransform,
178                                     G4double&  << 199                                    G4double& pMin, G4double& pMax) const
179 {                                                 200 {
180   G4ThreeVector bmin, bmax;                       201   G4ThreeVector bmin, bmax;
181                                                   202 
182   // Get bounding box                             203   // Get bounding box
183   BoundingLimits(bmin,bmax);                      204   BoundingLimits(bmin,bmax);
184                                                   205 
185   // Find extent                                  206   // Find extent
186   G4BoundingEnvelope bbox(bmin,bmax);             207   G4BoundingEnvelope bbox(bmin,bmax);
187   return bbox.CalculateExtent(pAxis,pVoxelLimi    208   return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
188 }                                                 209 }
189                                                   210 
190 //////////////////////////////////////////////    211 ///////////////////////////////////////////////////////////////////////////////
191 //                                                212 //
192 // Return whether point inside/outside/on surf    213 // Return whether point inside/outside/on surface
193 //                                             << 214 
194 EInside G4Paraboloid::Inside(const G4ThreeVect    215 EInside G4Paraboloid::Inside(const G4ThreeVector& p) const
195 {                                                 216 {
196   // First check is  the point is above or bel    217   // First check is  the point is above or below the solid.
197   //                                              218   //
198   if(std::fabs(p.z()) > dz + 0.5 * kCarToleran    219   if(std::fabs(p.z()) > dz + 0.5 * kCarTolerance) { return kOutside; }
199                                                   220 
200   G4double rho2 = p.perp2(),                      221   G4double rho2 = p.perp2(),
201            rhoSurfTimesTol2  = (k1 * p.z() + k    222            rhoSurfTimesTol2  = (k1 * p.z() + k2) * sqr(kCarTolerance),
202            A = rho2 - ((k1 *p.z() + k2) + 0.25    223            A = rho2 - ((k1 *p.z() + k2) + 0.25 * kCarTolerance * kCarTolerance);
203                                                   224  
204   if(A < 0 && sqr(A) > rhoSurfTimesTol2)          225   if(A < 0 && sqr(A) > rhoSurfTimesTol2)
205   {                                               226   {
206     // Actually checking rho < radius of parab    227     // Actually checking rho < radius of paraboloid at z = p.z().
207     // We're either inside or in lower/upper c    228     // We're either inside or in lower/upper cutoff area.
208                                                   229    
209     if(std::fabs(p.z()) > dz - 0.5 * kCarToler    230     if(std::fabs(p.z()) > dz - 0.5 * kCarTolerance)
210     {                                             231     {
211       // We're in the upper/lower cutoff area,    232       // We're in the upper/lower cutoff area, sides have a paraboloid shape
212       // maybe further checks should be made t    233       // maybe further checks should be made to make these nicer
213                                                   234 
214       return kSurface;                            235       return kSurface;
215     }                                             236     }
216     else                                          237     else
217     {                                             238     {
218       return kInside;                             239       return kInside;
219     }                                             240     }
220   }                                               241   }
221   else if(A <= 0 || sqr(A) < rhoSurfTimesTol2)    242   else if(A <= 0 || sqr(A) < rhoSurfTimesTol2)
222   {                                               243   {
223     // We're in the parabolic surface.            244     // We're in the parabolic surface.
224                                                   245 
225     return kSurface;                              246     return kSurface;
226   }                                               247   }
227   else                                            248   else
228   {                                               249   {
229     return kOutside;                              250     return kOutside;
230   }                                               251   }
231 }                                                 252 }
232                                                   253 
233 //////////////////////////////////////////////    254 ///////////////////////////////////////////////////////////////////////////////
234 //                                                255 //
235 // SurfaceNormal                               << 256 
236 //                                             << 
237 G4ThreeVector G4Paraboloid::SurfaceNormal( con    257 G4ThreeVector G4Paraboloid::SurfaceNormal( const G4ThreeVector& p) const
238 {                                                 258 {
239   G4ThreeVector n(0, 0, 0);                       259   G4ThreeVector n(0, 0, 0);
240   if(std::fabs(p.z()) > dz + 0.5 * kCarToleran    260   if(std::fabs(p.z()) > dz + 0.5 * kCarTolerance)
241   {                                               261   {
242     // If above or below just return normal ve    262     // If above or below just return normal vector for the cutoff plane.
243                                                   263 
244     n = G4ThreeVector(0, 0, p.z()/std::fabs(p.    264     n = G4ThreeVector(0, 0, p.z()/std::fabs(p.z()));
245   }                                               265   }
246   else if(std::fabs(p.z()) > dz - 0.5 * kCarTo    266   else if(std::fabs(p.z()) > dz - 0.5 * kCarTolerance)
247   {                                               267   {
248     // This means we're somewhere in the plane    268     // This means we're somewhere in the plane z = dz or z = -dz.
249     // (As far as the program is concerned any    269     // (As far as the program is concerned anyway.
250                                                   270 
251     if(p.z() < 0) // Are we in upper or lower     271     if(p.z() < 0) // Are we in upper or lower plane?
252     {                                             272     {
253       if(p.perp2() > sqr(r1 + 0.5 * kCarTolera    273       if(p.perp2() > sqr(r1 + 0.5 * kCarTolerance))
254       {                                           274       {
255         n = G4ThreeVector(p.x(), p.y(), -k1 /     275         n = G4ThreeVector(p.x(), p.y(), -k1 / 2).unit();
256       }                                           276       }
257       else if(r1 < 0.5 * kCarTolerance            277       else if(r1 < 0.5 * kCarTolerance
258            || p.perp2() > sqr(r1 - 0.5 * kCarT    278            || p.perp2() > sqr(r1 - 0.5 * kCarTolerance))
259       {                                           279       {
260         n = G4ThreeVector(p.x(), p.y(), 0.).un    280         n = G4ThreeVector(p.x(), p.y(), 0.).unit()
261           + G4ThreeVector(0., 0., -1.).unit();    281           + G4ThreeVector(0., 0., -1.).unit();
262         n = n.unit();                             282         n = n.unit();
263       }                                           283       }
264       else                                        284       else
265       {                                           285       {
266         n = G4ThreeVector(0., 0., -1.);           286         n = G4ThreeVector(0., 0., -1.);
267       }                                           287       }
268     }                                             288     }
269     else                                          289     else
270     {                                             290     {
271       if(p.perp2() > sqr(r2 + 0.5 * kCarTolera    291       if(p.perp2() > sqr(r2 + 0.5 * kCarTolerance))
272       {                                           292       {
273         n = G4ThreeVector(p.x(), p.y(), 0.).un    293         n = G4ThreeVector(p.x(), p.y(), 0.).unit();
274       }                                           294       }
275       else if(r2 < 0.5 * kCarTolerance            295       else if(r2 < 0.5 * kCarTolerance
276            || p.perp2() > sqr(r2 - 0.5 * kCarT    296            || p.perp2() > sqr(r2 - 0.5 * kCarTolerance))
277       {                                           297       {
278         n = G4ThreeVector(p.x(), p.y(), 0.).un    298         n = G4ThreeVector(p.x(), p.y(), 0.).unit()
279           + G4ThreeVector(0., 0., 1.).unit();     299           + G4ThreeVector(0., 0., 1.).unit();
280         n = n.unit();                             300         n = n.unit();
281       }                                           301       }
282       else                                        302       else
283       {                                           303       {
284         n = G4ThreeVector(0., 0., 1.);            304         n = G4ThreeVector(0., 0., 1.);
285       }                                           305       }
286     }                                             306     }
287   }                                               307   }
288   else                                            308   else
289   {                                               309   {
290     G4double rho2 = p.perp2();                    310     G4double rho2 = p.perp2();
291     G4double rhoSurfTimesTol2  = (k1 * p.z() +    311     G4double rhoSurfTimesTol2  = (k1 * p.z() + k2) * sqr(kCarTolerance);
292     G4double A = rho2 - ((k1 *p.z() + k2)         312     G4double A = rho2 - ((k1 *p.z() + k2)
293                + 0.25 * kCarTolerance * kCarTo    313                + 0.25 * kCarTolerance * kCarTolerance);
294                                                   314 
295     if(A < 0 && sqr(A) > rhoSurfTimesTol2)        315     if(A < 0 && sqr(A) > rhoSurfTimesTol2)
296     {                                             316     {
297       // Actually checking rho < radius of par    317       // Actually checking rho < radius of paraboloid at z = p.z().
298       // We're inside.                            318       // We're inside.
299                                                   319 
300       if(p.mag2() != 0) { n = p.unit(); }         320       if(p.mag2() != 0) { n = p.unit(); }
301     }                                             321     }
302     else if(A <= 0 || sqr(A) < rhoSurfTimesTol    322     else if(A <= 0 || sqr(A) < rhoSurfTimesTol2)
303     {                                             323     {
304       // We're in the parabolic surface.          324       // We're in the parabolic surface.
305                                                   325 
306       n = G4ThreeVector(p.x(), p.y(), - k1 / 2    326       n = G4ThreeVector(p.x(), p.y(), - k1 / 2).unit();
307     }                                             327     }
308     else                                          328     else
309     {                                             329     {
310       n = G4ThreeVector(p.x(), p.y(), - k1 / 2    330       n = G4ThreeVector(p.x(), p.y(), - k1 / 2).unit();
311     }                                             331     }
312   }                                               332   }
313                                                   333 
314   if(n.mag2() == 0)                               334   if(n.mag2() == 0)
315   {                                               335   {
316     std::ostringstream message;                   336     std::ostringstream message;
317     message << "No normal defined for this poi    337     message << "No normal defined for this point p." << G4endl
318             << "          p = " << 1 / mm * p     338             << "          p = " << 1 / mm * p << " mm";
319     G4Exception("G4Paraboloid::SurfaceNormal(p    339     G4Exception("G4Paraboloid::SurfaceNormal(p)", "GeomSolids1002",
320                 JustWarning, message);            340                 JustWarning, message);
321   }                                               341   }
322   return n;                                       342   return n;
323 }                                                 343 }
324                                                   344 
325 //////////////////////////////////////////////    345 ///////////////////////////////////////////////////////////////////////////////
326 //                                                346 //
327 // Calculate distance to shape from outside, a    347 // Calculate distance to shape from outside, along normalised vector
328 // - return kInfinity if no intersection          348 // - return kInfinity if no intersection
329 //                                                349 //
330 //                                             << 350 
331 G4double G4Paraboloid::DistanceToIn( const G4T    351 G4double G4Paraboloid::DistanceToIn( const G4ThreeVector& p,
332                                      const G4T << 352                                     const G4ThreeVector& v  ) const
333 {                                                 353 {
334   G4double rho2 = p.perp2(), paraRho2 = std::f    354   G4double rho2 = p.perp2(), paraRho2 = std::fabs(k1 * p.z() + k2);
335   G4double tol2 = kCarTolerance*kCarTolerance;    355   G4double tol2 = kCarTolerance*kCarTolerance;
336   G4double tolh = 0.5*kCarTolerance;              356   G4double tolh = 0.5*kCarTolerance;
337                                                   357 
338   if((r2 != 0.0) && p.z() > - tolh + dz)       << 358   if(r2 && p.z() > - tolh + dz) 
339   {                                               359   {
340     // If the points is above check for inters    360     // If the points is above check for intersection with upper edge.
341                                                   361 
342     if(v.z() < 0)                                 362     if(v.z() < 0)
343     {                                             363     {
344       G4double intersection = (dz - p.z()) / v    364       G4double intersection = (dz - p.z()) / v.z(); // With plane z = dz.
345       if(sqr(p.x() + v.x()*intersection)          365       if(sqr(p.x() + v.x()*intersection)
346        + sqr(p.y() + v.y()*intersection) < sqr    366        + sqr(p.y() + v.y()*intersection) < sqr(r2 + 0.5 * kCarTolerance))
347       {                                           367       {
348         if(p.z() < tolh + dz)                     368         if(p.z() < tolh + dz)
349           { return 0; }                           369           { return 0; }
350         else                                      370         else
351           { return intersection; }                371           { return intersection; }
352       }                                           372       }
353     }                                             373     }
354     else  // Direction away, no possibility of    374     else  // Direction away, no possibility of intersection
355     {                                             375     {
356       return kInfinity;                           376       return kInfinity;
357     }                                             377     }
358   }                                               378   }
359   else if((r1 != 0.0) && p.z() < tolh - dz)    << 379   else if(r1 && p.z() < tolh - dz)
360   {                                               380   {
361     // If the points is belove check for inter    381     // If the points is belove check for intersection with lower edge.
362                                                   382 
363     if(v.z() > 0)                                 383     if(v.z() > 0)
364     {                                             384     {
365       G4double intersection = (-dz - p.z()) /     385       G4double intersection = (-dz - p.z()) / v.z(); // With plane z = -dz.
366       if(sqr(p.x() + v.x()*intersection)          386       if(sqr(p.x() + v.x()*intersection)
367        + sqr(p.y() + v.y()*intersection) < sqr    387        + sqr(p.y() + v.y()*intersection) < sqr(r1 + 0.5 * kCarTolerance))
368       {                                           388       {
369         if(p.z() > -tolh - dz)                    389         if(p.z() > -tolh - dz)
370         {                                         390         {
371           return 0;                               391           return 0;
372         }                                         392         }
373         else                                      393         else
374         {                                         394         {
375           return intersection;                    395           return intersection;
376         }                                         396         }
377       }                                           397       }
378     }                                             398     }
379     else  // Direction away, no possibility of    399     else  // Direction away, no possibility of intersection
380     {                                             400     {
381       return kInfinity;                           401       return kInfinity;
382     }                                             402     }
383   }                                               403   }
384                                                   404 
385   G4double A = k1 / 2 * v.z() - p.x() * v.x()     405   G4double A = k1 / 2 * v.z() - p.x() * v.x() - p.y() * v.y(),
386            vRho2 = v.perp2(), intersection,       406            vRho2 = v.perp2(), intersection,
387            B = (k1 * p.z() + k2 - rho2) * vRho    407            B = (k1 * p.z() + k2 - rho2) * vRho2;
388                                                   408 
389   if ( ( (rho2 > paraRho2) && (sqr(rho2-paraRh    409   if ( ( (rho2 > paraRho2) && (sqr(rho2-paraRho2-0.25*tol2) > tol2*paraRho2) )
390     || (p.z() < - dz+kCarTolerance)               410     || (p.z() < - dz+kCarTolerance)
391     || (p.z() > dz-kCarTolerance) ) // Make su    411     || (p.z() > dz-kCarTolerance) ) // Make sure it's safely outside.
392   {                                               412   {
393     // Is there a problem with squaring rho tw    413     // Is there a problem with squaring rho twice?
394                                                   414 
395     if(vRho2<tol2) // Needs to be treated sepe    415     if(vRho2<tol2) // Needs to be treated seperately.
396     {                                             416     {
397       intersection = ((rho2 - k2)/k1 - p.z())/    417       intersection = ((rho2 - k2)/k1 - p.z())/v.z();
398       if(intersection < 0) { return kInfinity;    418       if(intersection < 0) { return kInfinity; }
399       else if(std::fabs(p.z() + v.z() * inters    419       else if(std::fabs(p.z() + v.z() * intersection) <= dz)
400       {                                           420       {
401         return intersection;                      421         return intersection;
402       }                                           422       }
403       else                                        423       else
404       {                                           424       {
405         return kInfinity;                         425         return kInfinity;
406       }                                           426       }
407     }                                             427     }
408     else if(A*A + B < 0) // No real intersecti    428     else if(A*A + B < 0) // No real intersections.
409     {                                             429     {
410       return kInfinity;                           430       return kInfinity;
411     }                                             431     }
412     else                                          432     else
413     {                                             433     {
414       intersection = (A - std::sqrt(B + sqr(A)    434       intersection = (A - std::sqrt(B + sqr(A))) / vRho2;
415       if(intersection < 0)                        435       if(intersection < 0)
416       {                                           436       {
417         return kInfinity;                         437         return kInfinity;
418       }                                           438       }
419       else if(std::fabs(p.z() + intersection *    439       else if(std::fabs(p.z() + intersection * v.z()) < dz + tolh)
420       {                                           440       {
421         return intersection;                      441         return intersection;
422       }                                           442       }
423       else                                        443       else
424       {                                           444       {
425         return kInfinity;                         445         return kInfinity;
426       }                                           446       }
427     }                                             447     }
428   }                                               448   }
429   else if(sqr(rho2 - paraRho2 - .25 * tol2) <=    449   else if(sqr(rho2 - paraRho2 - .25 * tol2) <= tol2 * paraRho2)
430   {                                               450   {
431     // If this is true we're somewhere in the     451     // If this is true we're somewhere in the border.
432                                                   452 
433     G4ThreeVector normal(p.x(), p.y(), -k1/2);    453     G4ThreeVector normal(p.x(), p.y(), -k1/2);
434     if(normal.dot(v) <= 0)                        454     if(normal.dot(v) <= 0)
435       { return 0; }                               455       { return 0; }
436     else                                          456     else
437       { return kInfinity; }                       457       { return kInfinity; }
438   }                                               458   }
439   else                                            459   else
440   {                                               460   {
441     std::ostringstream message;                   461     std::ostringstream message;
442     if(Inside(p) == kInside)                      462     if(Inside(p) == kInside)
443     {                                             463     {
444       message << "Point p is inside! - " << Ge    464       message << "Point p is inside! - " << GetName() << G4endl;
445     }                                             465     }
446     else                                          466     else
447     {                                             467     {
448       message << "Likely a problem in this fun    468       message << "Likely a problem in this function, for solid: " << GetName()
449               << G4endl;                          469               << G4endl;
450     }                                             470     }
451     message << "          p = " << p * (1/mm)     471     message << "          p = " << p * (1/mm) << " mm" << G4endl
452             << "          v = " << v * (1/mm)     472             << "          v = " << v * (1/mm) << " mm";
453     G4Exception("G4Paraboloid::DistanceToIn(p,    473     G4Exception("G4Paraboloid::DistanceToIn(p,v)", "GeomSolids1002",
454                 JustWarning, message);            474                 JustWarning, message);
455     return 0;                                     475     return 0;
456   }                                               476   }
457 }                                                 477 }
458                                                   478 
459 //////////////////////////////////////////////    479 ///////////////////////////////////////////////////////////////////////////////
460 //                                                480 //
461 // Calculate distance (<= actual) to closest s    481 // Calculate distance (<= actual) to closest surface of shape from outside
462 // - Return zero if point inside               << 482 // - Return 0 if point inside
463 //                                             << 483 
464 G4double G4Paraboloid::DistanceToIn(const G4Th    484 G4double G4Paraboloid::DistanceToIn(const G4ThreeVector& p) const
465 {                                                 485 {
466   G4double safz = -dz+std::fabs(p.z());           486   G4double safz = -dz+std::fabs(p.z());
467   if(safz<0.) { safz=0.; }                     << 487   if(safz<0) { safz=0; }
468   G4double safr = kInfinity;                      488   G4double safr = kInfinity;
469                                                   489 
470   G4double rho = p.x()*p.x()+p.y()*p.y();         490   G4double rho = p.x()*p.x()+p.y()*p.y();
471   G4double paraRho = (p.z()-k2)/k1;               491   G4double paraRho = (p.z()-k2)/k1;
472   G4double sqrho = std::sqrt(rho);                492   G4double sqrho = std::sqrt(rho);
473                                                   493 
474   if(paraRho<0.)                               << 494   if(paraRho<0)
475   {                                               495   {
476     safr=sqrho-r2;                                496     safr=sqrho-r2;
477     if(safr>safz) { safz=safr; }                  497     if(safr>safz) { safz=safr; }
478     return safz;                                  498     return safz;
479   }                                               499   }
480                                                   500 
481   G4double sqprho = std::sqrt(paraRho);           501   G4double sqprho = std::sqrt(paraRho);
482   G4double dRho = sqrho-sqprho;                   502   G4double dRho = sqrho-sqprho;
483   if(dRho<0.) { return safz; }                 << 503   if(dRho<0) { return safz; }
484                                                   504 
485   G4double talf = -2.*k1*sqprho;                  505   G4double talf = -2.*k1*sqprho;
486   G4double tmp  = 1+talf*talf;                    506   G4double tmp  = 1+talf*talf;
487   if(tmp<0.) { return safz; }                     507   if(tmp<0.) { return safz; }
488                                                   508 
489   G4double salf = talf/std::sqrt(tmp);            509   G4double salf = talf/std::sqrt(tmp);
490   safr = std::fabs(dRho*salf);                    510   safr = std::fabs(dRho*salf);
491   if(safr>safz) { safz=safr; }                    511   if(safr>safz) { safz=safr; }
492                                                   512 
493   return safz;                                    513   return safz;
494 }                                                 514 }
495                                                   515 
496 //////////////////////////////////////////////    516 ///////////////////////////////////////////////////////////////////////////////
497 //                                                517 //
498 // Calculate distance to surface of shape from    518 // Calculate distance to surface of shape from 'inside'
499 //                                             << 519 
500 G4double G4Paraboloid::DistanceToOut(const G4T    520 G4double G4Paraboloid::DistanceToOut(const G4ThreeVector& p,
501                                     const G4Th    521                                     const G4ThreeVector& v,
502                                     const G4bo    522                                     const G4bool calcNorm,
503                                           G4bo << 523                                           G4bool *validNorm,
504                                           G4Th << 524                                           G4ThreeVector *n  ) const
505 {                                                 525 {
506   G4double rho2 = p.perp2(), paraRho2 = std::f    526   G4double rho2 = p.perp2(), paraRho2 = std::fabs(k1 * p.z() + k2);
507   G4double vRho2 = v.perp2(), intersection;       527   G4double vRho2 = v.perp2(), intersection;
508   G4double tol2 = kCarTolerance*kCarTolerance;    528   G4double tol2 = kCarTolerance*kCarTolerance;
509   G4double tolh = 0.5*kCarTolerance;              529   G4double tolh = 0.5*kCarTolerance;
510                                                   530 
511   if(calcNorm) { *validNorm = false; }            531   if(calcNorm) { *validNorm = false; }
512                                                   532 
513   // We have that the particle p follows the l    533   // We have that the particle p follows the line x = p + s * v
514   // meaning x = p.x() + s * v.x(), y = p.y()     534   // meaning x = p.x() + s * v.x(), y = p.y() + s * v.y() and
515   // z = p.z() + s * v.z()                        535   // z = p.z() + s * v.z()
516   // The equation for all points on the surfac    536   // The equation for all points on the surface (surface expanded for
517   // to include all z) x^2 + y^2 = k1 * z + k2    537   // to include all z) x^2 + y^2 = k1 * z + k2 => .. =>
518   // => s = (A +- std::sqrt(A^2 + B)) / vRho2     538   // => s = (A +- std::sqrt(A^2 + B)) / vRho2
519   // where:                                       539   // where:
520   //                                              540   //
521   G4double A = k1 / 2 * v.z() - p.x() * v.x()     541   G4double A = k1 / 2 * v.z() - p.x() * v.x() - p.y() * v.y();
522   //                                              542   //
523   // and:                                         543   // and:
524   //                                              544   //
525   G4double B = (-rho2 + paraRho2) * vRho2;        545   G4double B = (-rho2 + paraRho2) * vRho2;
526                                                   546 
527   if ( rho2 < paraRho2 && sqr(rho2 - paraRho2     547   if ( rho2 < paraRho2 && sqr(rho2 - paraRho2 - 0.25 * tol2) > tol2 * paraRho2
528     && std::fabs(p.z()) < dz - kCarTolerance)     548     && std::fabs(p.z()) < dz - kCarTolerance)
529   {                                               549   {
530     // Make sure it's safely inside.              550     // Make sure it's safely inside.
531                                                   551 
532     if(v.z() > 0)                                 552     if(v.z() > 0)
533     {                                             553     {
534       // It's heading upwards, check where it     554       // It's heading upwards, check where it colides with the plane z = dz.
535       // When it does, is that in the surface     555       // When it does, is that in the surface of the paraboloid.
536       // z = p.z() + variable * v.z() for all     556       // z = p.z() + variable * v.z() for all points the particle can go.
537       // => variable = (z - p.z()) / v.z() so     557       // => variable = (z - p.z()) / v.z() so intersection must be:
538                                                   558 
539       intersection = (dz - p.z()) / v.z();        559       intersection = (dz - p.z()) / v.z();
540       G4ThreeVector ip = p + intersection * v;    560       G4ThreeVector ip = p + intersection * v; // Point of intersection.
541                                                   561 
542       if(ip.perp2() < sqr(r2 + kCarTolerance))    562       if(ip.perp2() < sqr(r2 + kCarTolerance))
543       {                                           563       {
544         if(calcNorm)                              564         if(calcNorm)
545         {                                         565         {
546           *n = G4ThreeVector(0, 0, 1);            566           *n = G4ThreeVector(0, 0, 1);
547           if(r2 < tolh || ip.perp2() > sqr(r2     567           if(r2 < tolh || ip.perp2() > sqr(r2 - tolh))
548           {                                       568           {
549             *n += G4ThreeVector(ip.x(), ip.y()    569             *n += G4ThreeVector(ip.x(), ip.y(), - k1 / 2).unit();
550             *n = n->unit();                       570             *n = n->unit();
551           }                                       571           }
552           *validNorm = true;                      572           *validNorm = true;
553         }                                         573         }
554         return intersection;                      574         return intersection;
555       }                                           575       }
556     }                                             576     }
557     else if(v.z() < 0)                            577     else if(v.z() < 0)
558     {                                             578     {
559       // It's heading downwards, check were it    579       // It's heading downwards, check were it colides with the plane z = -dz.
560       // When it does, is that in the surface     580       // When it does, is that in the surface of the paraboloid.
561       // z = p.z() + variable * v.z() for all     581       // z = p.z() + variable * v.z() for all points the particle can go.
562       // => variable = (z - p.z()) / v.z() so     582       // => variable = (z - p.z()) / v.z() so intersection must be:
563                                                   583 
564       intersection = (-dz - p.z()) / v.z();       584       intersection = (-dz - p.z()) / v.z();
565       G4ThreeVector ip = p + intersection * v;    585       G4ThreeVector ip = p + intersection * v; // Point of intersection.
566                                                   586 
567       if(ip.perp2() < sqr(r1 + tolh))             587       if(ip.perp2() < sqr(r1 + tolh))
568       {                                           588       {
569         if(calcNorm)                              589         if(calcNorm)
570         {                                         590         {
571           *n = G4ThreeVector(0, 0, -1);           591           *n = G4ThreeVector(0, 0, -1);
572           if(r1 < tolh || ip.perp2() > sqr(r1     592           if(r1 < tolh || ip.perp2() > sqr(r1 - tolh))
573           {                                       593           {
574             *n += G4ThreeVector(ip.x(), ip.y()    594             *n += G4ThreeVector(ip.x(), ip.y(), - k1 / 2).unit();
575             *n = n->unit();                       595             *n = n->unit();
576           }                                       596           }
577           *validNorm = true;                      597           *validNorm = true;
578         }                                         598         }
579         return intersection;                      599         return intersection;
580       }                                           600       }
581     }                                             601     }
582                                                   602 
583     // Now check for collisions with paraboloi    603     // Now check for collisions with paraboloid surface.
584                                                   604 
585     if(vRho2 == 0) // Needs to be treated sepe    605     if(vRho2 == 0) // Needs to be treated seperately.
586     {                                             606     {
587       intersection = ((rho2 - k2)/k1 - p.z())/    607       intersection = ((rho2 - k2)/k1 - p.z())/v.z();
588       if(calcNorm)                                608       if(calcNorm)
589       {                                           609       {
590         G4ThreeVector intersectionP = p + v *     610         G4ThreeVector intersectionP = p + v * intersection;
591         *n = G4ThreeVector(intersectionP.x(),     611         *n = G4ThreeVector(intersectionP.x(), intersectionP.y(), -k1/2);
592         *n = n->unit();                           612         *n = n->unit();
593                                                   613 
594         *validNorm = true;                        614         *validNorm = true;
595       }                                           615       }
596       return intersection;                        616       return intersection;
597     }                                             617     }
598     else if( ((A <= 0) && (B >= sqr(A) * (sqr(    618     else if( ((A <= 0) && (B >= sqr(A) * (sqr(vRho2) - 1))) || (A >= 0))
599     {                                             619     {
600       // intersection = (A + std::sqrt(B + sqr    620       // intersection = (A + std::sqrt(B + sqr(A))) / vRho2;
601       // The above calculation has a precision    621       // The above calculation has a precision problem:
602       // known problem of solving quadratic eq    622       // known problem of solving quadratic equation with small A  
603                                                   623 
604       A = A/vRho2;                                624       A = A/vRho2;
605       B = (k1 * p.z() + k2 - rho2)/vRho2;         625       B = (k1 * p.z() + k2 - rho2)/vRho2;
606       intersection = B/(-A + std::sqrt(B + sqr    626       intersection = B/(-A + std::sqrt(B + sqr(A)));
607       if(calcNorm)                                627       if(calcNorm)
608       {                                           628       {
609         G4ThreeVector intersectionP = p + v *     629         G4ThreeVector intersectionP = p + v * intersection;
610         *n = G4ThreeVector(intersectionP.x(),     630         *n = G4ThreeVector(intersectionP.x(), intersectionP.y(), -k1/2);
611         *n = n->unit();                           631         *n = n->unit();
612         *validNorm = true;                        632         *validNorm = true;
613       }                                           633       }
614       return intersection;                        634       return intersection;
615     }                                             635     }
616     std::ostringstream message;                   636     std::ostringstream message;
617     message << "There is no intersection betwe    637     message << "There is no intersection between given line and solid!"
618             << G4endl                             638             << G4endl
619             << "          p = " << p << G4endl    639             << "          p = " << p << G4endl
620             << "          v = " << v;             640             << "          v = " << v;
621     G4Exception("G4Paraboloid::DistanceToOut(p    641     G4Exception("G4Paraboloid::DistanceToOut(p,v,...)", "GeomSolids1002",
622                 JustWarning, message);            642                 JustWarning, message);
623                                                   643 
624     return kInfinity;                             644     return kInfinity;
625   }                                               645   }
626   else if ( (rho2 < paraRho2 + kCarTolerance      646   else if ( (rho2 < paraRho2 + kCarTolerance
627          || sqr(rho2 - paraRho2 - 0.25 * tol2)    647          || sqr(rho2 - paraRho2 - 0.25 * tol2) < tol2 * paraRho2 )
628          && std::fabs(p.z()) < dz + tolh)         648          && std::fabs(p.z()) < dz + tolh) 
629   {                                               649   {
630     // If this is true we're somewhere in the     650     // If this is true we're somewhere in the border.
631                                                   651     
632     G4ThreeVector normal = G4ThreeVector (p.x(    652     G4ThreeVector normal = G4ThreeVector (p.x(), p.y(), -k1/2);
633                                                   653 
634     if(std::fabs(p.z()) > dz - tolh)              654     if(std::fabs(p.z()) > dz - tolh)
635     {                                             655     {
636       // We're in the lower or upper edge         656       // We're in the lower or upper edge
637       //                                          657       //
638       if( ((v.z() > 0) && (p.z() > 0)) || ((v.    658       if( ((v.z() > 0) && (p.z() > 0)) || ((v.z() < 0) && (p.z() < 0)) )
639       {             // If we're heading out of    659       {             // If we're heading out of the object that is treated here
640         if(calcNorm)                              660         if(calcNorm)
641         {                                         661         {
642           *validNorm = true;                      662           *validNorm = true;
643           if(p.z() > 0)                           663           if(p.z() > 0)
644             { *n = G4ThreeVector(0, 0, 1); }      664             { *n = G4ThreeVector(0, 0, 1); }
645           else                                    665           else
646             { *n = G4ThreeVector(0, 0, -1); }     666             { *n = G4ThreeVector(0, 0, -1); }
647         }                                         667         }
648         return 0;                                 668         return 0;
649       }                                           669       }
650                                                   670 
651       if(v.z() == 0)                              671       if(v.z() == 0)
652       {                                           672       {
653         // Case where we're moving inside the     673         // Case where we're moving inside the surface needs to be
654         // treated separately.                    674         // treated separately.
655         // Distance until it goes out through     675         // Distance until it goes out through a side is returned.
656                                                   676 
657         G4double r = (p.z() > 0)? r2 : r1;        677         G4double r = (p.z() > 0)? r2 : r1;
658         G4double pDotV = p.dot(v);                678         G4double pDotV = p.dot(v);
659         A = vRho2 * ( sqr(r) - sqr(p.x()) - sq    679         A = vRho2 * ( sqr(r) - sqr(p.x()) - sqr(p.y()));
660         intersection = (-pDotV + std::sqrt(A +    680         intersection = (-pDotV + std::sqrt(A + sqr(pDotV))) / vRho2;
661                                                   681 
662         if(calcNorm)                              682         if(calcNorm)
663         {                                         683         {
664           *validNorm = true;                      684           *validNorm = true;
665                                                   685 
666           *n = (G4ThreeVector(0, 0, p.z()/std:    686           *n = (G4ThreeVector(0, 0, p.z()/std::fabs(p.z()))
667               + G4ThreeVector(p.x() + v.x() *     687               + G4ThreeVector(p.x() + v.x() * intersection, p.y() + v.y()
668               * intersection, -k1/2).unit()).u    688               * intersection, -k1/2).unit()).unit();
669         }                                         689         }
670         return intersection;                      690         return intersection;
671       }                                           691       }
672     }                                             692     }
673     //                                            693     //
674     // Problem in the Logic :: Following condi    694     // Problem in the Logic :: Following condition for point on upper surface 
675     //                         and Vz<0  will     695     //                         and Vz<0  will return 0 (Problem #1015), but
676     //                         it has to retur    696     //                         it has to return intersection with parabolic
677     //                         surface or with    697     //                         surface or with lower plane surface (z = -dz)
678     // The logic has to be  :: If not found in    698     // The logic has to be  :: If not found intersection until now,
679     // do not exit but continue to search for     699     // do not exit but continue to search for possible intersection.
680     // Only for point situated on both borders    700     // Only for point situated on both borders (Z and parabolic)
681     // this condition has to be taken into acc    701     // this condition has to be taken into account and done later
682     //                                            702     //
683     //                                            703     //
684     // else if(normal.dot(v) >= 0)                704     // else if(normal.dot(v) >= 0)
685     // {                                          705     // {
686     //   if(calcNorm)                             706     //   if(calcNorm)
687     //   {                                        707     //   {
688     //     *validNorm = true;                     708     //     *validNorm = true;
689     //     *n = normal.unit();                    709     //     *n = normal.unit();
690     //   }                                        710     //   }
691     //   return 0;                                711     //   return 0;
692     // }                                          712     // }
693                                                   713 
694     if(v.z() > 0)                                 714     if(v.z() > 0)
695     {                                             715     {
696       // Check for collision with upper edge.     716       // Check for collision with upper edge.
697                                                   717 
698       intersection = (dz - p.z()) / v.z();        718       intersection = (dz - p.z()) / v.z();
699       G4ThreeVector ip = p + intersection * v;    719       G4ThreeVector ip = p + intersection * v;
700                                                   720 
701       if(ip.perp2() < sqr(r2 - tolh))             721       if(ip.perp2() < sqr(r2 - tolh))
702       {                                           722       {
703         if(calcNorm)                              723         if(calcNorm)
704         {                                         724         {
705           *validNorm = true;                      725           *validNorm = true;
706           *n = G4ThreeVector(0, 0, 1);            726           *n = G4ThreeVector(0, 0, 1);
707         }                                         727         }
708         return intersection;                      728         return intersection;
709       }                                           729       }
710       else if(ip.perp2() < sqr(r2 + tolh))        730       else if(ip.perp2() < sqr(r2 + tolh))
711       {                                           731       {
712         if(calcNorm)                              732         if(calcNorm)
713         {                                         733         {
714           *validNorm = true;                      734           *validNorm = true;
715           *n = G4ThreeVector(0, 0, 1)             735           *n = G4ThreeVector(0, 0, 1)
716              + G4ThreeVector(ip.x(), ip.y(), -    736              + G4ThreeVector(ip.x(), ip.y(), - k1 / 2).unit();
717           *n = n->unit();                         737           *n = n->unit();
718         }                                         738         }
719         return intersection;                      739         return intersection;
720       }                                           740       }
721     }                                             741     }
722     if( v.z() < 0)                                742     if( v.z() < 0)
723     {                                             743     {
724       // Check for collision with lower edge.     744       // Check for collision with lower edge.
725                                                   745 
726       intersection = (-dz - p.z()) / v.z();       746       intersection = (-dz - p.z()) / v.z();
727       G4ThreeVector ip = p + intersection * v;    747       G4ThreeVector ip = p + intersection * v;
728                                                   748 
729       if(ip.perp2() < sqr(r1 - tolh))             749       if(ip.perp2() < sqr(r1 - tolh))
730       {                                           750       {
731         if(calcNorm)                              751         if(calcNorm)
732         {                                         752         {
733           *validNorm = true;                      753           *validNorm = true;
734           *n = G4ThreeVector(0, 0, -1);           754           *n = G4ThreeVector(0, 0, -1);
735         }                                         755         }
736         return intersection;                      756         return intersection;
737       }                                           757       }
738       else if(ip.perp2() < sqr(r1 + tolh))        758       else if(ip.perp2() < sqr(r1 + tolh))
739       {                                           759       {
740         if(calcNorm)                              760         if(calcNorm)
741         {                                         761         {
742           *validNorm = true;                      762           *validNorm = true;
743           *n = G4ThreeVector(0, 0, -1)            763           *n = G4ThreeVector(0, 0, -1)
744              + G4ThreeVector(ip.x(), ip.y(), -    764              + G4ThreeVector(ip.x(), ip.y(), - k1 / 2).unit();
745           *n = n->unit();                         765           *n = n->unit();
746         }                                         766         }
747         return intersection;                      767         return intersection;
748       }                                           768       }
749     }                                             769     }
750                                                   770 
751     // Note: comparison with zero below would     771     // Note: comparison with zero below would not be correct !
752     //                                            772     //
753     if(std::fabs(vRho2) > tol2) // precision e    773     if(std::fabs(vRho2) > tol2) // precision error in the calculation of
754     {                           // intersectio    774     {                           // intersection = (A+std::sqrt(B+sqr(A)))/vRho2
755       A = A/vRho2;                                775       A = A/vRho2;
756       B = (k1 * p.z() + k2 - rho2);               776       B = (k1 * p.z() + k2 - rho2);
757       if(std::fabs(B)>kCarTolerance)              777       if(std::fabs(B)>kCarTolerance)
758       {                                           778       {
759         B = (B)/vRho2;                            779         B = (B)/vRho2;
760         intersection = B/(-A + std::sqrt(B + s    780         intersection = B/(-A + std::sqrt(B + sqr(A)));
761       }                                           781       }
762       else                      // Point is On    782       else                      // Point is On both borders: Z and parabolic
763       {                         // solution de    783       {                         // solution depends on normal.dot(v) sign
764         if(normal.dot(v) >= 0)                    784         if(normal.dot(v) >= 0)
765         {                                         785         {
766           if(calcNorm)                            786           if(calcNorm)
767           {                                       787           {
768             *validNorm = true;                    788             *validNorm = true;
769             *n = normal.unit();                   789             *n = normal.unit();
770           }                                       790           }
771           return 0;                               791           return 0;
772         }                                         792         }
773         intersection = 2.*A;                      793         intersection = 2.*A;
774       }                                           794       }
775     }                                             795     }
776     else                                          796     else
777     {                                             797     {
778       intersection = ((rho2 - k2) / k1 - p.z()    798       intersection = ((rho2 - k2) / k1 - p.z()) / v.z();
779     }                                             799     }
780                                                   800 
781     if(calcNorm)                                  801     if(calcNorm)
782     {                                             802     {
783       *validNorm = true;                          803       *validNorm = true;
784       *n = G4ThreeVector(p.x() + intersection     804       *n = G4ThreeVector(p.x() + intersection * v.x(), p.y()
785          + intersection * v.y(), - k1 / 2);       805          + intersection * v.y(), - k1 / 2);
786       *n = n->unit();                             806       *n = n->unit();
787     }                                             807     }
788     return intersection;                          808     return intersection;
789   }                                               809   }
790   else                                            810   else
791   {                                               811   {
792 #ifdef G4SPECSDEBUG                               812 #ifdef G4SPECSDEBUG
793     if(kOutside == Inside(p))                     813     if(kOutside == Inside(p))
794     {                                             814     {
795       G4Exception("G4Paraboloid::DistanceToOut    815       G4Exception("G4Paraboloid::DistanceToOut(p,v,...)", "GeomSolids1002",
796                   JustWarning, "Point p is out    816                   JustWarning, "Point p is outside!");
797     }                                             817     }
798     else                                          818     else
799       G4Exception("G4Paraboloid::DistanceToOut    819       G4Exception("G4Paraboloid::DistanceToOut(p,v,...)", "GeomSolids1002",
800                   JustWarning, "There's an err    820                   JustWarning, "There's an error in this functions code.");
801 #endif                                            821 #endif
802     return kInfinity;                             822     return kInfinity;
803   }                                               823   }
804   return 0;                                       824   return 0;
805 }                                                 825 } 
806                                                   826 
807 //////////////////////////////////////////////    827 ///////////////////////////////////////////////////////////////////////////////
808 //                                                828 //
809 // Calculate distance (<=actual) to closest su    829 // Calculate distance (<=actual) to closest surface of shape from inside
810 //                                             << 830 
811 G4double G4Paraboloid::DistanceToOut(const G4T    831 G4double G4Paraboloid::DistanceToOut(const G4ThreeVector& p) const
812 {                                                 832 {
813   G4double safe=0.0,rho,safeR,safeZ ;             833   G4double safe=0.0,rho,safeR,safeZ ;
814   G4double tanRMax,secRMax,pRMax ;                834   G4double tanRMax,secRMax,pRMax ;
815                                                   835 
816 #ifdef G4SPECSDEBUG                               836 #ifdef G4SPECSDEBUG
817   if( Inside(p) == kOutside )                     837   if( Inside(p) == kOutside )
818   {                                               838   {
819      G4cout << G4endl ;                           839      G4cout << G4endl ;
820      DumpInfo();                                  840      DumpInfo();
821      std::ostringstream message;                  841      std::ostringstream message;
822      G4long oldprc = message.precision(16);    << 842      G4int oldprc = message.precision(16);
823      message << "Point p is outside !?" << G4e    843      message << "Point p is outside !?" << G4endl
824              << "Position:" << G4endl             844              << "Position:" << G4endl
825              << "   p.x() = "   << p.x()/mm <<    845              << "   p.x() = "   << p.x()/mm << " mm" << G4endl
826              << "   p.y() = "   << p.y()/mm <<    846              << "   p.y() = "   << p.y()/mm << " mm" << G4endl
827              << "   p.z() = "   << p.z()/mm <<    847              << "   p.z() = "   << p.z()/mm << " mm";
828      message.precision(oldprc) ;                  848      message.precision(oldprc) ;
829      G4Exception("G4Paraboloid::DistanceToOut(    849      G4Exception("G4Paraboloid::DistanceToOut(p)", "GeomSolids1002",
830                  JustWarning, message);           850                  JustWarning, message);
831   }                                               851   }
832 #endif                                            852 #endif
833                                                   853 
834   rho = p.perp();                                 854   rho = p.perp();
835   safeZ = dz - std::fabs(p.z()) ;                 855   safeZ = dz - std::fabs(p.z()) ;
836                                                   856 
837   tanRMax = (r2 - r1)*0.5/dz ;                    857   tanRMax = (r2 - r1)*0.5/dz ;
838   secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;    858   secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
839   pRMax   = tanRMax*p.z() + (r1+r2)*0.5 ;         859   pRMax   = tanRMax*p.z() + (r1+r2)*0.5 ;
840   safeR  = (pRMax - rho)/secRMax ;                860   safeR  = (pRMax - rho)/secRMax ;
841                                                   861 
842   if (safeZ < safeR) { safe = safeZ; }            862   if (safeZ < safeR) { safe = safeZ; }
843   else { safe = safeR; }                          863   else { safe = safeR; }
844   if ( safe < 0.5 * kCarTolerance ) { safe = 0    864   if ( safe < 0.5 * kCarTolerance ) { safe = 0; }
845   return safe ;                                   865   return safe ;
846 }                                                 866 }
847                                                   867 
848 //////////////////////////////////////////////    868 //////////////////////////////////////////////////////////////////////////
849 //                                                869 //
850 // G4EntityType                                   870 // G4EntityType
851 //                                             << 871 
852 G4GeometryType G4Paraboloid::GetEntityType() c    872 G4GeometryType G4Paraboloid::GetEntityType() const
853 {                                                 873 {
854   return {"G4Paraboloid"};                     << 874   return G4String("G4Paraboloid");
855 }                                                 875 }
856                                                   876 
857 //////////////////////////////////////////////    877 //////////////////////////////////////////////////////////////////////////
858 //                                                878 //
859 // Make a clone of the object                     879 // Make a clone of the object
860 //                                             << 880 
861 G4VSolid* G4Paraboloid::Clone() const             881 G4VSolid* G4Paraboloid::Clone() const
862 {                                                 882 {
863   return new G4Paraboloid(*this);                 883   return new G4Paraboloid(*this);
864 }                                                 884 }
865                                                   885 
866 //////////////////////////////////////////////    886 //////////////////////////////////////////////////////////////////////////
867 //                                                887 //
868 // Stream object contents to an output stream     888 // Stream object contents to an output stream
869 //                                             << 889 
870 std::ostream& G4Paraboloid::StreamInfo( std::o    890 std::ostream& G4Paraboloid::StreamInfo( std::ostream& os ) const
871 {                                                 891 {
872   G4long oldprc = os.precision(16);            << 892   G4int oldprc = os.precision(16);
873   os << "-------------------------------------    893   os << "-----------------------------------------------------------\n"
874      << "    *** Dump for solid - " << GetName    894      << "    *** Dump for solid - " << GetName() << " ***\n"
875      << "    =================================    895      << "    ===================================================\n"
876      << " Solid type: G4Paraboloid\n"             896      << " Solid type: G4Paraboloid\n"
877      << " Parameters: \n"                         897      << " Parameters: \n"
878      << "    z half-axis:   " << dz/mm << " mm    898      << "    z half-axis:   " << dz/mm << " mm \n"
879      << "    radius at -dz: " << r1/mm << " mm    899      << "    radius at -dz: " << r1/mm << " mm \n"
880      << "    radius at dz:  " << r2/mm << " mm    900      << "    radius at dz:  " << r2/mm << " mm \n"
881      << "-------------------------------------    901      << "-----------------------------------------------------------\n";
882   os.precision(oldprc);                           902   os.precision(oldprc);
883                                                   903 
884   return os;                                      904   return os;
885 }                                                 905 }
886                                                   906 
887 //////////////////////////////////////////////    907 ////////////////////////////////////////////////////////////////////
888 //                                                908 //
889 // GetPointOnSurface                              909 // GetPointOnSurface
890 //                                             << 910 
891 G4ThreeVector G4Paraboloid::GetPointOnSurface(    911 G4ThreeVector G4Paraboloid::GetPointOnSurface() const
892 {                                                 912 {
893   G4double A = (fSurfaceArea == 0)? CalculateS    913   G4double A = (fSurfaceArea == 0)? CalculateSurfaceArea(): fSurfaceArea;
894   G4double z = G4RandFlat::shoot(0.,1.);          914   G4double z = G4RandFlat::shoot(0.,1.);
895   G4double phi = G4RandFlat::shoot(0., twopi);    915   G4double phi = G4RandFlat::shoot(0., twopi);
896   if(pi*(sqr(r1) + sqr(r2))/A >= z)               916   if(pi*(sqr(r1) + sqr(r2))/A >= z)
897   {                                               917   {
898     G4double rho;                                 918     G4double rho;
899     if(pi * sqr(r1) / A > z)                      919     if(pi * sqr(r1) / A > z)
900     {                                             920     {
901       rho = r1 * std::sqrt(G4RandFlat::shoot(0    921       rho = r1 * std::sqrt(G4RandFlat::shoot(0., 1.));
902       return { rho * std::cos(phi), rho * std: << 922       return G4ThreeVector(rho * std::cos(phi), rho * std::sin(phi), -dz);
903     }                                             923     }
904     else                                          924     else
905     {                                             925     {
906       rho = r2 * std::sqrt(G4RandFlat::shoot(0    926       rho = r2 * std::sqrt(G4RandFlat::shoot(0., 1));
907       return { rho * std::cos(phi), rho * std: << 927       return G4ThreeVector(rho * std::cos(phi), rho * std::sin(phi), dz);
908     }                                             928     }
909   }                                               929   }
910   else                                            930   else
911   {                                               931   {
912     z = G4RandFlat::shoot(0., 1.)*2*dz - dz;      932     z = G4RandFlat::shoot(0., 1.)*2*dz - dz;
913     return { std::sqrt(z*k1 + k2)*std::cos(phi << 933     return G4ThreeVector(std::sqrt(z*k1 + k2)*std::cos(phi),
914              std::sqrt(z*k1 + k2)*std::sin(phi << 934                          std::sqrt(z*k1 + k2)*std::sin(phi), z);
915   }                                               935   }
916 }                                                 936 }
917                                                   937 
918 //////////////////////////////////////////////    938 /////////////////////////////////////////////////////////////////////////////
919 //                                                939 //
920 // Methods for visualisation                      940 // Methods for visualisation
921 //                                             << 941 
922 void G4Paraboloid::DescribeYourselfTo (G4VGrap    942 void G4Paraboloid::DescribeYourselfTo (G4VGraphicsScene& scene) const
923 {                                                 943 {
924   scene.AddSolid(*this);                          944   scene.AddSolid(*this);
925 }                                                 945 }
926                                                   946 
927 G4Polyhedron* G4Paraboloid::CreatePolyhedron (    947 G4Polyhedron* G4Paraboloid::CreatePolyhedron () const
928 {                                                 948 {
929   return new G4PolyhedronParaboloid(r1, r2, dz    949   return new G4PolyhedronParaboloid(r1, r2, dz, 0., twopi);
930 }                                                 950 }
931                                                   951 
                                                   >> 952 
932 G4Polyhedron* G4Paraboloid::GetPolyhedron () c    953 G4Polyhedron* G4Paraboloid::GetPolyhedron () const
933 {                                                 954 {
934   if (fpPolyhedron == nullptr ||               << 955   if (!fpPolyhedron ||
935       fRebuildPolyhedron ||                       956       fRebuildPolyhedron ||
936       fpPolyhedron->GetNumberOfRotationStepsAt    957       fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
937       fpPolyhedron->GetNumberOfRotationSteps()    958       fpPolyhedron->GetNumberOfRotationSteps())
938   {                                               959   {
939     G4AutoLock l(&polyhedronMutex);               960     G4AutoLock l(&polyhedronMutex);
940     delete fpPolyhedron;                          961     delete fpPolyhedron;
941     fpPolyhedron = CreatePolyhedron();            962     fpPolyhedron = CreatePolyhedron();
942     fRebuildPolyhedron = false;                   963     fRebuildPolyhedron = false;
943     l.unlock();                                   964     l.unlock();
944   }                                               965   }
945   return fpPolyhedron;                            966   return fpPolyhedron;
946 }                                                 967 }
947                                                   968 
948 #endif // !defined(G4GEOM_USE_UPARABOLOID) ||     969 #endif // !defined(G4GEOM_USE_UPARABOLOID) || !defined(G4GEOM_USE_SYS_USOLIDS)
949                                                   970