Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/solids/specific/src/G4Ellipsoid.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/G4Ellipsoid.cc (Version 11.3.0) and /geometry/solids/specific/src/G4Ellipsoid.cc (Version 11.0.p3,)


** Warning: Cannot open xref database.

  1 //                                                  1 
  2 // *******************************************    
  3 // * License and Disclaimer                       
  4 // *                                              
  5 // * The  Geant4 software  is  copyright of th    
  6 // * the Geant4 Collaboration.  It is provided    
  7 // * conditions of the Geant4 Software License    
  8 // * LICENSE and available at  http://cern.ch/    
  9 // * include a list of copyright holders.         
 10 // *                                              
 11 // * Neither the authors of this software syst    
 12 // * institutes,nor the agencies providing fin    
 13 // * work  make  any representation or  warran    
 14 // * regarding  this  software system or assum    
 15 // * use.  Please see the license in the file     
 16 // * for the full disclaimer and the limitatio    
 17 // *                                              
 18 // * This  code  implementation is the result     
 19 // * technical work of the GEANT4 collaboratio    
 20 // * By using,  copying,  modifying or  distri    
 21 // * any work based  on the software)  you  ag    
 22 // * use  in  resulting  scientific  publicati    
 23 // * acceptance of all terms of the Geant4 Sof    
 24 // *******************************************    
 25 //                                                
 26 // class G4Ellipsoid                              
 27 //                                                
 28 // Implementation of G4Ellipsoid class            
 29 //                                                
 30 // 10.11.99 G.Horton-Smith: first writing, bas    
 31 // 25.02.05 G.Guerrieri: Revised                  
 32 // 15.12.19 E.Tcherniaev: Complete revision       
 33 // -------------------------------------------    
 34                                                   
 35 #include "G4Ellipsoid.hh"                         
 36                                                   
 37 #if !(defined(G4GEOM_USE_UELLIPSOID) && define    
 38                                                   
 39 #include "globals.hh"                             
 40                                                   
 41 #include "G4VoxelLimits.hh"                       
 42 #include "G4AffineTransform.hh"                   
 43 #include "G4GeometryTolerance.hh"                 
 44 #include "G4BoundingEnvelope.hh"                  
 45 #include "G4RandomTools.hh"                       
 46 #include "G4QuickRand.hh"                         
 47                                                   
 48 #include "G4VPVParameterisation.hh"               
 49                                                   
 50 #include "G4VGraphicsScene.hh"                    
 51 #include "G4VisExtent.hh"                         
 52                                                   
 53 #include "G4AutoLock.hh"                          
 54                                                   
 55 namespace                                         
 56 {                                                 
 57   G4Mutex polyhedronMutex  = G4MUTEX_INITIALIZ    
 58   G4Mutex lateralareaMutex = G4MUTEX_INITIALIZ    
 59 }                                                 
 60                                                   
 61 using namespace CLHEP;                            
 62                                                   
 63 //////////////////////////////////////////////    
 64 //                                                
 65 // Constructor                                    
 66                                                   
 67 G4Ellipsoid::G4Ellipsoid(const G4String& name,    
 68                                G4double xSemiA    
 69                                G4double ySemiA    
 70                                G4double zSemiA    
 71                                G4double zBotto    
 72                                G4double zTopCu    
 73   : G4VSolid(name), fDx(xSemiAxis), fDy(ySemiA    
 74     fZBottomCut(zBottomCut), fZTopCut(zTopCut)    
 75 {                                                 
 76   CheckParameters();                              
 77 }                                                 
 78                                                   
 79 //////////////////////////////////////////////    
 80 //                                                
 81 // Fake default constructor - sets only member    
 82 //                            for usage restri    
 83                                                   
 84 G4Ellipsoid::G4Ellipsoid( __void__& a )           
 85   : G4VSolid(a), fDx(0.), fDy(0.), fDz(0.), fZ    
 86 {                                                 
 87 }                                                 
 88                                                   
 89 //////////////////////////////////////////////    
 90 //                                                
 91 // Destructor                                     
 92                                                   
 93 G4Ellipsoid::~G4Ellipsoid()                       
 94 {                                                 
 95   delete fpPolyhedron; fpPolyhedron = nullptr;    
 96 }                                                 
 97                                                   
 98 //////////////////////////////////////////////    
 99 //                                                
100 // Copy constructor                               
101                                                   
102 G4Ellipsoid::G4Ellipsoid(const G4Ellipsoid& rh    
103   : G4VSolid(rhs),                                
104    fDx(rhs.fDx), fDy(rhs.fDy), fDz(rhs.fDz),      
105    fZBottomCut(rhs.fZBottomCut), fZTopCut(rhs.    
106    halfTolerance(rhs.halfTolerance),              
107    fXmax(rhs.fXmax), fYmax(rhs.fYmax),            
108    fRsph(rhs.fRsph), fR(rhs.fR),                  
109    fSx(rhs.fSx), fSy(rhs.fSy), fSz(rhs.fSz),      
110    fZMidCut(rhs.fZMidCut), fZDimCut(rhs.fZDimC    
111    fQ1(rhs.fQ1), fQ2(rhs.fQ2),                    
112    fCubicVolume(rhs.fCubicVolume),                
113    fSurfaceArea(rhs.fSurfaceArea),                
114    fLateralArea(rhs.fLateralArea)                 
115 {                                                 
116 }                                                 
117                                                   
118 //////////////////////////////////////////////    
119 //                                                
120 // Assignment operator                            
121                                                   
122 G4Ellipsoid& G4Ellipsoid::operator = (const G4    
123 {                                                 
124    // Check assignment to self                    
125    //                                             
126    if (this == &rhs)  { return *this; }           
127                                                   
128    // Copy base class data                        
129    //                                             
130    G4VSolid::operator=(rhs);                      
131                                                   
132    // Copy data                                   
133    //                                             
134    fDx = rhs.fDx;                                 
135    fDy = rhs.fDy;                                 
136    fDz = rhs.fDz;                                 
137    fZBottomCut = rhs.fZBottomCut;                 
138    fZTopCut = rhs.fZTopCut;                       
139                                                   
140    halfTolerance = rhs.halfTolerance;             
141    fXmax = rhs.fXmax;                             
142    fYmax = rhs.fYmax;                             
143    fRsph = rhs.fRsph;                             
144    fR = rhs.fR;                                   
145    fSx = rhs.fSx;                                 
146    fSy = rhs.fSy;                                 
147    fSz = rhs.fSz;                                 
148    fZMidCut = rhs.fZMidCut;                       
149    fZDimCut = rhs.fZDimCut;                       
150    fQ1 = rhs.fQ1;                                 
151    fQ2 = rhs.fQ2;                                 
152                                                   
153    fCubicVolume = rhs.fCubicVolume;               
154    fSurfaceArea = rhs.fSurfaceArea;               
155    fLateralArea = rhs.fLateralArea;               
156                                                   
157    fRebuildPolyhedron = false;                    
158    delete fpPolyhedron; fpPolyhedron = nullptr    
159                                                   
160    return *this;                                  
161 }                                                 
162                                                   
163 //////////////////////////////////////////////    
164 //                                                
165 // Check parameters and make precalculation       
166                                                   
167 void G4Ellipsoid::CheckParameters()               
168 {                                                 
169   halfTolerance = 0.5 * kCarTolerance; // half    
170   G4double dmin = 2. * kCarTolerance;             
171                                                   
172   // Check dimensions                             
173   //                                              
174   if (fDx < dmin || fDy < dmin || fDz < dmin)     
175   {                                               
176     std::ostringstream message;                   
177     message << "Invalid (too small or negative    
178             << GetName()  << "\n"                 
179             << "  semi-axis x: " << fDx << "\n    
180             << "  semi-axis y: " << fDy << "\n    
181             << "  semi-axis z: " << fDz;          
182     G4Exception("G4Ellipsoid::CheckParameters(    
183                 FatalException, message);         
184   }                                               
185   G4double A = fDx;                               
186   G4double B = fDy;                               
187   G4double C = fDz;                               
188                                                   
189   // Check cuts                                   
190   //                                              
191   if (fZBottomCut == 0. && fZTopCut == 0.)        
192   {                                               
193     fZBottomCut = -C;                             
194     fZTopCut = C;                                 
195   }                                               
196   if (fZBottomCut >= C || fZTopCut <= -C || fZ    
197   {                                               
198     std::ostringstream message;                   
199     message << "Invalid Z cuts for Solid: "       
200             << GetName() << "\n"                  
201             << "  bottom cut: " << fZBottomCut    
202             << "  top cut: " << fZTopCut;         
203     G4Exception("G4Ellipsoid::CheckParameters(    
204                 FatalException, message);         
205                                                   
206   }                                               
207   fZBottomCut = std::max(fZBottomCut, -C);        
208   fZTopCut = std::min(fZTopCut, C);               
209                                                   
210   // Set extent in x and y                        
211   fXmax = A;                                      
212   fYmax = B;                                      
213   if (fZBottomCut > 0.)                           
214   {                                               
215     G4double ratio = fZBottomCut / C;             
216     G4double scale = std::sqrt((1. - ratio) *     
217     fXmax *= scale;                               
218     fYmax *= scale;                               
219   }                                               
220   if (fZTopCut < 0.)                              
221   {                                               
222     G4double ratio  = fZTopCut / C;               
223     G4double scale  = std::sqrt((1. - ratio) *    
224     fXmax *= scale;                               
225     fYmax *= scale;                               
226   }                                               
227                                                   
228   // Set scale factors                            
229   fRsph = std::max(std::max(A, B), C); // boun    
230   fR    = std::min(std::min(A, B), C); // radi    
231   fSx   = fR / A; // X scale factor               
232   fSy   = fR / B; // Y scale factor               
233   fSz   = fR / C; // Z scale factor               
234                                                   
235   // Scaled cuts                                  
236   fZMidCut = 0.5 * (fZTopCut + fZBottomCut) *     
237   fZDimCut = 0.5 * (fZTopCut - fZBottomCut) *     
238                                                   
239   // Coefficients for approximation of distanc    
240   fQ1 = 0.5 / fR;                                 
241   fQ2 = 0.5 * fR + halfTolerance * halfToleran    
242                                                   
243   fCubicVolume = 0.; // volume                    
244   fSurfaceArea = 0.; // surface area              
245   fLateralArea = 0.; // lateral surface area      
246 }                                                 
247                                                   
248 //////////////////////////////////////////////    
249 //                                                
250 // Dispatch to parameterisation for replicatio    
251 // computation & modification                     
252                                                   
253 void G4Ellipsoid::ComputeDimensions(G4VPVParam    
254                                     const G4in    
255                                     const G4VP    
256 {                                                 
257   p->ComputeDimensions(*this,n,pRep);             
258 }                                                 
259                                                   
260 //////////////////////////////////////////////    
261 //                                                
262 // Get bounding box                               
263                                                   
264 void G4Ellipsoid::BoundingLimits(G4ThreeVector    
265                                  G4ThreeVector    
266 {                                                 
267   pMin.set(-fXmax,-fYmax, fZBottomCut);           
268   pMax.set( fXmax, fYmax, fZTopCut);              
269 }                                                 
270                                                   
271 //////////////////////////////////////////////    
272 //                                                
273 // Calculate extent under transform and specif    
274                                                   
275 G4bool                                            
276 G4Ellipsoid::CalculateExtent(const EAxis pAxis    
277                              const G4VoxelLimi    
278                              const G4AffineTra    
279                                    G4double& p    
280 {                                                 
281   G4ThreeVector bmin, bmax;                       
282                                                   
283   // Get bounding box                             
284   BoundingLimits(bmin,bmax);                      
285                                                   
286   // Find extent                                  
287   G4BoundingEnvelope bbox(bmin,bmax);             
288   return bbox.CalculateExtent(pAxis,pVoxelLimi    
289 }                                                 
290                                                   
291 //////////////////////////////////////////////    
292 //                                                
293 // Return position of point: inside/outside/on    
294                                                   
295 EInside G4Ellipsoid::Inside(const G4ThreeVecto    
296 {                                                 
297   G4double x     = p.x() * fSx;                   
298   G4double y     = p.y() * fSy;                   
299   G4double z     = p.z() * fSz;                   
300   G4double rr    = x * x + y * y + z * z;         
301   G4double distZ = std::abs(z - fZMidCut) - fZ    
302   G4double distR = fQ1 * rr - fQ2;                
303   G4double dist  = std::max(distZ, distR);        
304                                                   
305   if (dist > halfTolerance) return kOutside;      
306   return (dist > -halfTolerance) ? kSurface :     
307 }                                                 
308                                                   
309 //////////////////////////////////////////////    
310 //                                                
311 // Return unit normal to surface at p             
312                                                   
313 G4ThreeVector G4Ellipsoid::SurfaceNormal( cons    
314 {                                                 
315   G4ThreeVector norm(0., 0., 0.);                 
316   G4int nsurf = 0;                                
317                                                   
318   // Check cuts                                   
319   G4double x = p.x() * fSx;                       
320   G4double y = p.y() * fSy;                       
321   G4double z = p.z() * fSz;                       
322   G4double distZ = std::abs(z - fZMidCut) - fZ    
323   if (std::abs(distZ) <= halfTolerance)           
324   {                                               
325     norm.setZ(std::copysign(1., z - fZMidCut))    
326     ++nsurf;                                      
327   }                                               
328                                                   
329   // Check lateral surface                        
330   G4double distR = fQ1*(x*x + y*y + z*z) - fQ2    
331   if (std::abs(distR) <= halfTolerance)           
332   {                                               
333     // normal = (p.x/a^2, p.y/b^2, p.z/c^2)       
334     norm += G4ThreeVector(x*fSx, y*fSy, z*fSz)    
335     ++nsurf;                                      
336   }                                               
337                                                   
338   // Return normal                                
339   if (nsurf == 1) return norm;                    
340   else if (nsurf > 1) return norm.unit(); // e    
341   else                                            
342   {                                               
343 #ifdef G4SPECSDEBUG                               
344     std::ostringstream message;                   
345     G4long oldprc = message.precision(16);        
346     message << "Point p is not on surface (!?)    
347             << GetName() << "\n";                 
348     message << "Position:\n";                     
349     message << "   p.x() = " << p.x()/mm << "     
350     message << "   p.y() = " << p.y()/mm << "     
351     message << "   p.z() = " << p.z()/mm << "     
352     G4cout.precision(oldprc);                     
353     G4Exception("G4Ellipsoid::SurfaceNormal(p)    
354                 JustWarning, message );           
355     DumpInfo();                                   
356 #endif                                            
357     return ApproxSurfaceNormal(p);                
358   }                                               
359 }                                                 
360                                                   
361 //////////////////////////////////////////////    
362 //                                                
363 // Find surface nearest to point and return co    
364 // This method normally should not be called.     
365                                                   
366 G4ThreeVector G4Ellipsoid::ApproxSurfaceNormal    
367 {                                                 
368   G4double x  = p.x() * fSx;                      
369   G4double y  = p.y() * fSy;                      
370   G4double z  = p.z() * fSz;                      
371   G4double rr = x * x + y * y + z * z;            
372   G4double distZ = std::abs(z - fZMidCut) - fZ    
373   G4double distR = std::sqrt(rr) - fR;            
374   if  (distR > distZ && rr > 0.) // distR > di    
375     return G4ThreeVector(x*fSx, y*fSy, z*fSz).    
376   else                                            
377     return { 0., 0., std::copysign(1., z - fZM    
378 }                                                 
379                                                   
380 //////////////////////////////////////////////    
381 //                                                
382 // Calculate distance to shape from outside al    
383                                                   
384 G4double G4Ellipsoid::DistanceToIn(const G4Thr    
385                                    const G4Thr    
386 {                                                 
387   G4double offset = 0.;                           
388   G4ThreeVector pcur = p;                         
389                                                   
390   // Check if point is flying away, relative t    
391   //                                              
392   G4double safex = std::abs(p.x()) - fXmax;       
393   G4double safey = std::abs(p.y()) - fYmax;       
394   G4double safet = p.z() - fZTopCut;              
395   G4double safeb = fZBottomCut - p.z();           
396                                                   
397   if (safex >= -halfTolerance && p.x() * v.x()    
398   if (safey >= -halfTolerance && p.y() * v.y()    
399   if (safet >= -halfTolerance && v.z() >= 0.)     
400   if (safeb >= -halfTolerance && v.z() <= 0.)     
401                                                   
402   // Relocate point, if required                  
403   //                                              
404   G4double safe = std::max(std::max(std::max(s    
405   if (safe > 32. * fRsph)                         
406   {                                               
407     offset = (1. - 1.e-08) * safe - 2. * fRsph    
408     pcur += offset * v;                           
409     G4double dist = DistanceToIn(pcur, v);        
410     return (dist == kInfinity) ? kInfinity : d    
411   }                                               
412                                                   
413   // Scale ellipsoid to sphere                    
414   //                                              
415   G4double px = pcur.x() * fSx;                   
416   G4double py = pcur.y() * fSy;                   
417   G4double pz = pcur.z() * fSz;                   
418   G4double vx = v.x() * fSx;                      
419   G4double vy = v.y() * fSy;                      
420   G4double vz = v.z() * fSz;                      
421                                                   
422   // Check if point is leaving the solid          
423   //                                              
424   G4double dzcut = fZDimCut;                      
425   G4double pzcut = pz - fZMidCut;                 
426   G4double distZ = std::abs(pzcut) - dzcut;       
427   if (distZ >= -halfTolerance && pzcut * vz >=    
428                                                   
429   G4double rr = px * px + py * py + pz * pz;      
430   G4double pv = px * vx + py * vy + pz * vz;      
431   G4double distR = fQ1 * rr - fQ2;                
432   if (distR >= -halfTolerance && pv >= 0.) ret    
433                                                   
434   G4double A = vx * vx + vy * vy + vz * vz;       
435   G4double B = pv;                                
436   G4double C = rr - fR * fR;                      
437   G4double D = B * B - A * C;                     
438   // scratch^2 = R^2 - (R - halfTolerance)^2 =    
439   G4double EPS = A * A * fR * kCarTolerance; /    
440   if (D <= EPS) return kInfinity; // no inters    
441                                                   
442   // Find intersection with Z planes              
443   //                                              
444   G4double invz  = (vz == 0) ? DBL_MAX : -1./v    
445   G4double dz    = std::copysign(dzcut, invz);    
446   G4double tzmin = (pzcut - dz) * invz;           
447   G4double tzmax = (pzcut + dz) * invz;           
448                                                   
449   // Find intersection with lateral surface       
450   //                                              
451   G4double tmp = -B - std::copysign(std::sqrt(    
452   G4double t1 = tmp / A;                          
453   G4double t2 = C / tmp;                          
454   G4double trmin = std::min(t1, t2);              
455   G4double trmax = std::max(t1, t2);              
456                                                   
457   // Return distance                              
458   //                                              
459   G4double tmin = std::max(tzmin, trmin);         
460   G4double tmax = std::min(tzmax, trmax);         
461                                                   
462   if (tmax - tmin <= halfTolerance) return kIn    
463   return (tmin < halfTolerance) ? offset : tmi    
464 }                                                 
465                                                   
466 //////////////////////////////////////////////    
467 //                                                
468 // Estimate distance to surface from outside      
469                                                   
470 G4double G4Ellipsoid::DistanceToIn(const G4Thr    
471 {                                                 
472   G4double px = p.x();                            
473   G4double py = p.y();                            
474   G4double pz = p.z();                            
475                                                   
476   // Safety distance to bounding box              
477   G4double distX = std::abs(px) - fXmax;          
478   G4double distY = std::abs(py) - fYmax;          
479   G4double distZ = std::max(pz - fZTopCut, fZB    
480   G4double distB = std::max(std::max(distX, di    
481                                                   
482   // Safety distance to lateral surface           
483   G4double x = px * fSx;                          
484   G4double y = py * fSy;                          
485   G4double z = pz * fSz;                          
486   G4double distR = std::sqrt(x*x + y*y + z*z)     
487                                                   
488   // Return safety to in                          
489   G4double dist = std::max(distB, distR);         
490   return (dist < 0.) ? 0. : dist;                 
491 }                                                 
492                                                   
493 //////////////////////////////////////////////    
494 //                                                
495 // Calculate distance to surface from inside a    
496                                                   
497 G4double G4Ellipsoid::DistanceToOut(const G4Th    
498                                     const G4Th    
499                                     const G4bo    
500                                           G4bo    
501                                           G4Th    
502 {                                                 
503   // Check if point flying away relative to Z     
504   //                                              
505   G4double pz = p.z() * fSz;                      
506   G4double vz = v.z() * fSz;                      
507   G4double dzcut = fZDimCut;                      
508   G4double pzcut = pz - fZMidCut;                 
509   G4double distZ = std::abs(pzcut) - dzcut;       
510   if (distZ >= -halfTolerance && pzcut * vz >     
511   {                                               
512     if (calcNorm)                                 
513     {                                             
514       *validNorm = true;                          
515       n->set(0., 0., std::copysign(1., pzcut))    
516     }                                             
517     return 0.;                                    
518   }                                               
519                                                   
520   // Check if point is flying away relative to    
521   //                                              
522   G4double px = p.x() * fSx;                      
523   G4double py = p.y() * fSy;                      
524   G4double vx = v.x() * fSx;                      
525   G4double vy = v.y() * fSy;                      
526   G4double rr = px * px + py * py + pz * pz;      
527   G4double pv = px * vx + py * vy + pz * vz;      
528   G4double distR = fQ1 * rr - fQ2;                
529   if (distR >= -halfTolerance && pv > 0.)         
530   {                                               
531     if (calcNorm)                                 
532     {                                             
533       *validNorm = true;                          
534       *n = G4ThreeVector(px*fSx, py*fSy, pz*fS    
535     }                                             
536     return 0.;                                    
537   }                                               
538                                                   
539   // Just in case check if point is outside (n    
540   //                                              
541   if (std::max(distZ, distR) > halfTolerance)     
542   {                                               
543 #ifdef G4SPECSDEBUG                               
544     std::ostringstream message;                   
545     G4long oldprc = message.precision(16);        
546     message << "Point p is outside (!?) of sol    
547             << GetName() << G4endl;               
548     message << "Position:  " << p << G4endl;;     
549     message << "Direction: " << v;                
550     G4cout.precision(oldprc);                     
551     G4Exception("G4Ellipsoid::DistanceToOut(p,    
552                 JustWarning, message );           
553     DumpInfo();                                   
554 #endif                                            
555     if (calcNorm)                                 
556     {                                             
557       *validNorm = true;                          
558       *n = ApproxSurfaceNormal(p);                
559     }                                             
560     return 0.;                                    
561   }                                               
562                                                   
563   // Set coefficients of quadratic equation: A    
564   //                                              
565   G4double A  = vx * vx + vy * vy + vz * vz;      
566   G4double B  = pv;                               
567   G4double C  = rr - fR * fR;                     
568   G4double D  = B * B - A * C;                    
569   // It is expected that the point is located     
570   // max term in the expression for discrimina    
571   // max calculation error can be derived as f    
572   // A * (1 + 2e) * R^2 * (1 + 2e) = A * R^2 +    
573   G4double EPS = 4. * A * fR * fR * DBL_EPSILO    
574                                                   
575   if (D <= EPS) // no intersection                
576   {                                               
577     if (calcNorm)                                 
578     {                                             
579       *validNorm = true;                          
580       *n = G4ThreeVector(px*fSx, py*fSy, pz*fS    
581     }                                             
582     return 0.;                                    
583   }                                               
584                                                   
585   // Find intersection with Z cuts                
586   //                                              
587   G4double tzmax = (vz == 0.) ? DBL_MAX : (std    
588                                                   
589   // Find intersection with lateral surface       
590   //                                              
591   G4double tmp = -B - std::copysign(std::sqrt(    
592   G4double trmax = (tmp < 0.) ? C/tmp : tmp/A;    
593                                                   
594   // Find distance and set normal, if required    
595   //                                              
596   G4double tmax = std::min(tzmax, trmax);         
597   //if (tmax < halfTolerance) tmax = 0.;          
598                                                   
599   if (calcNorm)                                   
600   {                                               
601     *validNorm = true;                            
602     if (tmax == tzmax)                            
603     {                                             
604       G4double pznew = pz + tmax * vz;            
605       n->set(0., 0., (pznew > fZMidCut) ? 1. :    
606     }                                             
607     else                                          
608     {                                             
609       G4double nx = (px + tmax * vx) * fSx;       
610       G4double ny = (py + tmax * vy) * fSy;       
611       G4double nz = (pz + tmax * vz) * fSz;       
612       *n = G4ThreeVector(nx, ny, nz).unit();      
613     }                                             
614   }                                               
615   return tmax;                                    
616 }                                                 
617                                                   
618 //////////////////////////////////////////////    
619 //                                                
620 // Estimate distance to surface from inside       
621                                                   
622 G4double G4Ellipsoid::DistanceToOut(const G4Th    
623 {                                                 
624   // Safety distance in z direction               
625   G4double distZ = std::min(fZTopCut - p.z(),     
626                                                   
627   // Safety distance to lateral surface           
628   G4double x = p.x() * fSx;                       
629   G4double y = p.y() * fSy;                       
630   G4double z = p.z() * fSz;                       
631   G4double distR = fR - std::sqrt(x*x + y*y +     
632                                                   
633   // Return safety to out                         
634   G4double dist = std::min(distZ, distR);         
635   return (dist < 0.) ? 0. : dist;                 
636 }                                                 
637                                                   
638 //////////////////////////////////////////////    
639 //                                                
640 // Return entity type                             
641                                                   
642 G4GeometryType G4Ellipsoid::GetEntityType() co    
643 {                                                 
644   return {"G4Ellipsoid"};                         
645 }                                                 
646                                                   
647 //////////////////////////////////////////////    
648 //                                                
649 // Make a clone of the object                     
650                                                   
651 G4VSolid* G4Ellipsoid::Clone() const              
652 {                                                 
653   return new G4Ellipsoid(*this);                  
654 }                                                 
655                                                   
656 //////////////////////////////////////////////    
657 //                                                
658 // Stream object contents to output stream        
659                                                   
660 std::ostream& G4Ellipsoid::StreamInfo( std::os    
661 {                                                 
662   G4long oldprc = os.precision(16);               
663   os << "-------------------------------------    
664      << "    *** Dump for solid - " << GetName    
665      << "    =================================    
666      << " Solid type: " << GetEntityType() <<     
667      << " Parameters: \n"                         
668      << "    semi-axis x: " << GetDx()/mm << "    
669      << "    semi-axis y: " << GetDy()/mm << "    
670      << "    semi-axis z: " << GetDz()/mm << "    
671      << "    lower cut in z: " << GetZBottomCu    
672      << "    upper cut in z: " << GetZTopCut()    
673      << "-------------------------------------    
674   os.precision(oldprc);                           
675   return os;                                      
676 }                                                 
677                                                   
678 //////////////////////////////////////////////    
679 //                                                
680 // Return volume                                  
681                                                   
682 G4double G4Ellipsoid::GetCubicVolume()            
683 {                                                 
684   if (fCubicVolume == 0.)                         
685   {                                               
686     G4double piAB_3 = CLHEP::pi * fDx * fDy /     
687     fCubicVolume = 4. * piAB_3 * fDz;             
688     if (fZBottomCut > -fDz)                       
689     {                                             
690       G4double hbot = 1. + fZBottomCut / fDz;     
691       fCubicVolume -= piAB_3 * hbot * hbot * (    
692     }                                             
693     if (fZTopCut < fDz)                           
694     {                                             
695       G4double htop = 1. - fZTopCut / fDz;        
696       fCubicVolume -= piAB_3 * htop * htop * (    
697     }                                             
698   }                                               
699   return fCubicVolume;                            
700 }                                                 
701                                                   
702 //////////////////////////////////////////////    
703 //                                                
704 // Calculate area of lateral surface              
705                                                   
706 G4double G4Ellipsoid::LateralSurfaceArea() con    
707 {                                                 
708   constexpr G4int NPHI = 1000.;                   
709   constexpr G4double dPhi = CLHEP::halfpi/NPHI    
710   constexpr G4double eps = 4.*DBL_EPSILON;        
711                                                   
712   G4double aa = fDx*fDx;                          
713   G4double bb = fDy*fDy;                          
714   G4double cc = fDz*fDz;                          
715   G4double ab = fDx*fDy;                          
716   G4double cc_aa = cc/aa;                         
717   G4double cc_bb = cc/bb;                         
718   G4double zmax = std::min(fZTopCut, fDz);        
719   G4double zmin = std::max(fZBottomCut,-fDz);     
720   G4double zmax_c = zmax/fDz;                     
721   G4double zmin_c = zmin/fDz;                     
722   G4double area = 0.;                             
723                                                   
724   if (aa == bb) // spheroid, use analytical ex    
725   {                                               
726     G4double k = fDz/fDx;                         
727     G4double kk = k*k;                            
728     if (kk < 1. - eps)                            
729     {                                             
730       G4double invk = fDx/fDz;                    
731       G4double root = std::sqrt(1. - kk);         
732       G4double tmax = zmax_c*root;                
733       G4double tmin = zmin_c*root;                
734       area = CLHEP::pi*ab*                        
735         ((zmax_c*std::sqrt(kk + tmax*tmax) - z    
736          (std::asinh(tmax*invk) - std::asinh(t    
737     }                                             
738     else if (kk > 1. + eps)                       
739     {                                             
740       G4double invk = fDx/fDz;                    
741       G4double root = std::sqrt(kk - 1.);         
742       G4double tmax = zmax_c*root;                
743       G4double tmin = zmin_c*root;                
744       area = CLHEP::pi*ab*                        
745         ((zmax_c*std::sqrt(kk - tmax*tmax) - z    
746          (std::asin(tmax*invk) - std::asin(tmi    
747     }                                             
748     else                                          
749     {                                             
750       area = CLHEP::twopi*fDx*(zmax - zmin);      
751     }                                             
752     return area;                                  
753   }                                               
754                                                   
755   // ellipsoid, integration along phi             
756   for (G4int i = 0; i < NPHI; ++i)                
757   {                                               
758     G4double sinPhi = std::sin(dPhi*(i + 0.5))    
759     G4double kk = cc_aa + (cc_bb - cc_aa)*sinP    
760     if (kk < 1. - eps)                            
761     {                                             
762       G4double root = std::sqrt(1. - kk);         
763       G4double tmax = zmax_c*root;                
764       G4double tmin = zmin_c*root;                
765       G4double invk = 1./std::sqrt(kk);           
766       area += 2.*ab*dPhi*                         
767         ((zmax_c*std::sqrt(kk + tmax*tmax) - z    
768          (std::asinh(tmax*invk) - std::asinh(t    
769     }                                             
770     else if (kk > 1. + eps)                       
771     {                                             
772       G4double root = std::sqrt(kk - 1.);         
773       G4double tmax = zmax_c*root;                
774       G4double tmin = zmin_c*root;                
775       G4double invk = 1./std::sqrt(kk);           
776       area += 2.*ab*dPhi*                         
777         ((zmax_c*std::sqrt(kk - tmax*tmax) - z    
778          (std::asin(tmax*invk) - std::asin(tmi    
779     }                                             
780     else                                          
781     {                                             
782       area += 4.*ab*dPhi*(zmax_c - zmin_c);       
783     }                                             
784   }                                               
785   return area;                                    
786 }                                                 
787                                                   
788 //////////////////////////////////////////////    
789 //                                                
790 // Return surface area                            
791                                                   
792 G4double G4Ellipsoid::GetSurfaceArea()            
793 {                                                 
794   if (fSurfaceArea == 0.)                         
795   {                                               
796     G4double piAB = CLHEP::pi * fDx * fDy;        
797     fSurfaceArea = LateralSurfaceArea();          
798     if (fZBottomCut > -fDz)                       
799     {                                             
800       G4double hbot = 1. + fZBottomCut / fDz;     
801       fSurfaceArea += piAB * hbot * (2. - hbot    
802     }                                             
803     if (fZTopCut < fDz)                           
804     {                                             
805       G4double htop = 1. - fZTopCut / fDz;        
806       fSurfaceArea += piAB * htop * (2. - htop    
807     }                                             
808   }                                               
809   return fSurfaceArea;                            
810 }                                                 
811                                                   
812 //////////////////////////////////////////////    
813 //                                                
814 // Return random point on surface                 
815                                                   
816 G4ThreeVector G4Ellipsoid::GetPointOnSurface()    
817 {                                                 
818   G4double A    = GetDx();                        
819   G4double B    = GetDy();                        
820   G4double C    = GetDz();                        
821   G4double Zbot = GetZBottomCut();                
822   G4double Ztop = GetZTopCut();                   
823                                                   
824   // Calculate cut areas                          
825   G4double Hbot = 1. + Zbot / C;                  
826   G4double Htop = 1. - Ztop / C;                  
827   G4double piAB = CLHEP::pi * A * B;              
828   G4double Sbot = piAB * Hbot * (2. - Hbot);      
829   G4double Stop = piAB * Htop * (2. - Htop);      
830                                                   
831   // Get area of lateral surface                  
832   if (fLateralArea == 0.)                         
833   {                                               
834     G4AutoLock l(&lateralareaMutex);              
835     fLateralArea = LateralSurfaceArea();          
836     l.unlock();                                   
837   }                                               
838   G4double Slat = fLateralArea;                   
839                                                   
840   // Select surface (0 - bottom cut, 1 - later    
841   G4double select = (Sbot + Slat + Stop) * G4Q    
842   G4int k = 0;                                    
843   if (select > Sbot) k = 1;                       
844   if (select > Sbot + Slat) k = 2;                
845                                                   
846   // Pick random point on selected surface (re    
847   G4ThreeVector p;                                
848   switch (k)                                      
849   {                                               
850     case 0: // bootom z-cut                       
851     {                                             
852       G4double scale = std::sqrt(Hbot * (2. -     
853       G4TwoVector rho = G4RandomPointInEllipse    
854       p.set(rho.x(), rho.y(), Zbot);              
855       break;                                      
856     }                                             
857     case 1: // lateral surface                    
858     {                                             
859       G4double x, y, z;                           
860       G4double mu_max = std::max(std::max(A *     
861       for (G4int i = 0; i < 1000; ++i)            
862       {                                           
863         // generate random point on unit spher    
864         z = (Zbot + (Ztop - Zbot) * G4QuickRan    
865         G4double rho = std::sqrt((1. + z) * (1    
866         G4double phi = CLHEP::twopi * G4QuickR    
867         x = rho * std::cos(phi);                  
868         y = rho * std::sin(phi);                  
869         // check  acceptance                      
870         G4double xbc = x * B * C;                 
871         G4double yac = y * A * C;                 
872         G4double zab = z * A * B;                 
873         G4double mu  = std::sqrt(xbc * xbc + y    
874         if (mu_max * G4QuickRand() <= mu) brea    
875       }                                           
876       p.set(A * x, B * y, C * z);                 
877       break;                                      
878     }                                             
879     case 2: // top z-cut                          
880     {                                             
881       G4double scale  = std::sqrt(Htop * (2. -    
882       G4TwoVector rho = G4RandomPointInEllipse    
883       p.set(rho.x(), rho.y(), Ztop);              
884       break;                                      
885     }                                             
886   }                                               
887   return p;                                       
888 }                                                 
889                                                   
890 //////////////////////////////////////////////    
891 //                                                
892 // Methods for visualisation                      
893                                                   
894 void G4Ellipsoid::DescribeYourselfTo (G4VGraph    
895 {                                                 
896   scene.AddSolid(*this);                          
897 }                                                 
898                                                   
899 //////////////////////////////////////////////    
900 //                                                
901 // Return vis extent                              
902                                                   
903 G4VisExtent G4Ellipsoid::GetExtent() const        
904 {                                                 
905   return { -fXmax, fXmax, -fYmax, fYmax, fZBot    
906 }                                                 
907                                                   
908 //////////////////////////////////////////////    
909 //                                                
910 // Create polyhedron                              
911                                                   
912 G4Polyhedron* G4Ellipsoid::CreatePolyhedron ()    
913 {                                                 
914   return new G4PolyhedronEllipsoid(fDx, fDy, f    
915 }                                                 
916                                                   
917 //////////////////////////////////////////////    
918 //                                                
919 // Return pointer to polyhedron                   
920                                                   
921 G4Polyhedron* G4Ellipsoid::GetPolyhedron () co    
922 {                                                 
923   if (fpPolyhedron == nullptr ||                  
924       fRebuildPolyhedron ||                       
925       fpPolyhedron->GetNumberOfRotationStepsAt    
926       fpPolyhedron->GetNumberOfRotationSteps()    
927     {                                             
928       G4AutoLock l(&polyhedronMutex);             
929       delete fpPolyhedron;                        
930       fpPolyhedron = CreatePolyhedron();          
931       fRebuildPolyhedron = false;                 
932       l.unlock();                                 
933     }                                             
934   return fpPolyhedron;                            
935 }                                                 
936                                                   
937 #endif // !defined(G4GEOM_USE_UELLIPSOID) || !    
938