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 9.4.p3)


  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: G4Ellipsoid.cc,v 1.30 2010-10-20 08:54:18 gcosmo Exp $
                                                   >>  27 // GEANT4 tag $Name: not supported by cvs2svn $
                                                   >>  28 //
 26 // class G4Ellipsoid                               29 // class G4Ellipsoid
 27 //                                                 30 //
 28 // Implementation of G4Ellipsoid class         <<  31 // Implementation for G4Ellipsoid class
                                                   >>  32 //
                                                   >>  33 // History:
                                                   >>  34 //
                                                   >>  35 // 10.11.99 G.Horton-Smith  -- first writing, based on G4Sphere class
                                                   >>  36 // 25.02.05 G.Guerrieri -- Modified for future Geant4 release
 29 //                                                 37 //
 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 // -------------------------------------------     38 // --------------------------------------------------------------------
 34                                                    39 
 35 #include "G4Ellipsoid.hh"                      << 
 36                                                << 
 37 #if !(defined(G4GEOM_USE_UELLIPSOID) && define << 
 38                                                << 
 39 #include "globals.hh"                              40 #include "globals.hh"
 40                                                    41 
                                                   >>  42 #include "G4Ellipsoid.hh"
                                                   >>  43 
 41 #include "G4VoxelLimits.hh"                        44 #include "G4VoxelLimits.hh"
 42 #include "G4AffineTransform.hh"                    45 #include "G4AffineTransform.hh"
 43 #include "G4GeometryTolerance.hh"                  46 #include "G4GeometryTolerance.hh"
 44 #include "G4BoundingEnvelope.hh"               << 
 45 #include "G4RandomTools.hh"                    << 
 46 #include "G4QuickRand.hh"                      << 
 47                                                    47 
 48 #include "G4VPVParameterisation.hh"            <<  48 #include "meshdefs.hh"
                                                   >>  49 
                                                   >>  50 #include "Randomize.hh"
 49                                                    51 
 50 #include "G4VGraphicsScene.hh"                     52 #include "G4VGraphicsScene.hh"
                                                   >>  53 #include "G4Polyhedron.hh"
                                                   >>  54 #include "G4NURBS.hh"
                                                   >>  55 #include "G4NURBSbox.hh"
 51 #include "G4VisExtent.hh"                          56 #include "G4VisExtent.hh"
 52                                                    57 
 53 #include "G4AutoLock.hh"                       << 
 54                                                << 
 55 namespace                                      << 
 56 {                                              << 
 57   G4Mutex polyhedronMutex  = G4MUTEX_INITIALIZ << 
 58   G4Mutex lateralareaMutex = G4MUTEX_INITIALIZ << 
 59 }                                              << 
 60                                                << 
 61 using namespace CLHEP;                             58 using namespace CLHEP;
 62                                                    59 
 63 ////////////////////////////////////////////// <<  60 ///////////////////////////////////////////////////////////////////////////////
 64 //                                                 61 //
 65 // Constructor                                 <<  62 // constructor - check parameters, convert angles so 0<sphi+dpshi<=2_PI
                                                   >>  63 //             - note if pDPhi>2PI then reset to 2PI
 66                                                    64 
 67 G4Ellipsoid::G4Ellipsoid(const G4String& name, <<  65 G4Ellipsoid::G4Ellipsoid(const G4String& pName,
 68                                G4double xSemiA <<  66                                G4double pxSemiAxis,
 69                                G4double ySemiA <<  67                                G4double pySemiAxis,
 70                                G4double zSemiA <<  68                                G4double pzSemiAxis,
 71                                G4double zBotto <<  69                                G4double pzBottomCut,
 72                                G4double zTopCu <<  70                                G4double pzTopCut)
 73   : G4VSolid(name), fDx(xSemiAxis), fDy(ySemiA <<  71   : G4VSolid(pName), fpPolyhedron(0), fCubicVolume(0.), fSurfaceArea(0.),
 74     fZBottomCut(zBottomCut), fZTopCut(zTopCut) <<  72     zBottomCut(0.), zTopCut(0.)
 75 {                                                  73 {
 76   CheckParameters();                           <<  74   // note: for users that want to use the full ellipsoid it is useful
                                                   >>  75   // to include a default for the cuts 
                                                   >>  76 
                                                   >>  77   kRadTolerance = G4GeometryTolerance::GetInstance()->GetRadialTolerance();
                                                   >>  78 
                                                   >>  79   // Check Semi-Axis
                                                   >>  80   if ( (pxSemiAxis<=0.) || (pySemiAxis<=0.) || (pzSemiAxis<=0.) )
                                                   >>  81   {
                                                   >>  82      G4cerr << "ERROR - G4Ellipsoid::G4Ellipsoid(): " << GetName() << G4endl
                                                   >>  83            << "         Invalid semi-axis !"
                                                   >>  84            << G4endl;
                                                   >>  85      G4Exception("G4Ellipsoid::G4Ellipsoid()", "InvalidSetup",
                                                   >>  86                  FatalException, "Invalid semi-axis.");
                                                   >>  87   }
                                                   >>  88   SetSemiAxis(pxSemiAxis, pySemiAxis, pzSemiAxis);
                                                   >>  89 
                                                   >>  90   if ( pzBottomCut == 0 && pzTopCut == 0 )
                                                   >>  91   {
                                                   >>  92      SetZCuts(-pzSemiAxis, pzSemiAxis);
                                                   >>  93   }
                                                   >>  94   else if ( (pzBottomCut < pzSemiAxis) && (pzTopCut > -pzSemiAxis)
                                                   >>  95          && (pzBottomCut < pzTopCut) )
                                                   >>  96   {
                                                   >>  97      SetZCuts(pzBottomCut, pzTopCut);
                                                   >>  98   }
                                                   >>  99   else
                                                   >> 100   {
                                                   >> 101      G4cerr << "ERROR - G4Ellipsoid::G4Ellipsoid(): " << GetName() << G4endl
                                                   >> 102            << "         Invalid z-coordinate for cutting plane !"
                                                   >> 103            << G4endl;
                                                   >> 104      G4Exception("G4Ellipsoid::G4Ellipsoid()", "InvalidSetup",
                                                   >> 105                  FatalException, "Invalid z-coordinate for cutting plane.");
                                                   >> 106   }
 77 }                                                 107 }
 78                                                   108 
 79 ////////////////////////////////////////////// << 109 ///////////////////////////////////////////////////////////////////////////////
 80 //                                                110 //
 81 // Fake default constructor - sets only member    111 // Fake default constructor - sets only member data and allocates memory
 82 //                            for usage restri << 112 //                            for usage restricted to object persistency.
 83                                                << 113 //
 84 G4Ellipsoid::G4Ellipsoid( __void__& a )           114 G4Ellipsoid::G4Ellipsoid( __void__& a )
 85   : G4VSolid(a), fDx(0.), fDy(0.), fDz(0.), fZ << 115   : G4VSolid(a), fpPolyhedron(0), kRadTolerance(0.), fCubicVolume(0.),
                                                   >> 116     fSurfaceArea(0.), xSemiAxis(0.), ySemiAxis(0.), zSemiAxis(0.),
                                                   >> 117     semiAxisMax(0.), zBottomCut(0.), zTopCut(0.)
 86 {                                                 118 {
 87 }                                                 119 }
 88                                                   120 
 89 ////////////////////////////////////////////// << 121 ///////////////////////////////////////////////////////////////////////////////
 90 //                                                122 //
 91 // Destructor                                     123 // Destructor
 92                                                   124 
 93 G4Ellipsoid::~G4Ellipsoid()                       125 G4Ellipsoid::~G4Ellipsoid()
 94 {                                                 126 {
 95   delete fpPolyhedron; fpPolyhedron = nullptr; << 
 96 }                                                 127 }
 97                                                   128 
 98 ////////////////////////////////////////////// << 129 ///////////////////////////////////////////////////////////////////////////////
 99 //                                                130 //
100 // Copy constructor                               131 // Copy constructor
101                                                   132 
102 G4Ellipsoid::G4Ellipsoid(const G4Ellipsoid& rh    133 G4Ellipsoid::G4Ellipsoid(const G4Ellipsoid& rhs)
103   : G4VSolid(rhs),                                134   : G4VSolid(rhs),
104    fDx(rhs.fDx), fDy(rhs.fDy), fDz(rhs.fDz),   << 135     fpPolyhedron(0), kRadTolerance(rhs.kRadTolerance),
105    fZBottomCut(rhs.fZBottomCut), fZTopCut(rhs. << 136     fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
106    halfTolerance(rhs.halfTolerance),           << 137     xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.ySemiAxis),
107    fXmax(rhs.fXmax), fYmax(rhs.fYmax),         << 138     zSemiAxis(rhs.zSemiAxis), semiAxisMax(rhs.semiAxisMax),
108    fRsph(rhs.fRsph), fR(rhs.fR),               << 139     zBottomCut(rhs.zBottomCut), zTopCut(rhs.zTopCut)
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 {                                                 140 {
116 }                                                 141 }
117                                                   142 
118 ////////////////////////////////////////////// << 143 ///////////////////////////////////////////////////////////////////////////////
119 //                                                144 //
120 // Assignment operator                            145 // Assignment operator
121                                                   146 
122 G4Ellipsoid& G4Ellipsoid::operator = (const G4 << 147 G4Ellipsoid& G4Ellipsoid::operator = (const G4Ellipsoid& rhs) 
123 {                                                 148 {
124    // Check assignment to self                    149    // Check assignment to self
125    //                                             150    //
126    if (this == &rhs)  { return *this; }           151    if (this == &rhs)  { return *this; }
127                                                   152 
128    // Copy base class data                        153    // Copy base class data
129    //                                             154    //
130    G4VSolid::operator=(rhs);                      155    G4VSolid::operator=(rhs);
131                                                   156 
132    // Copy data                                   157    // Copy data
133    //                                             158    //
134    fDx = rhs.fDx;                              << 159    fpPolyhedron = 0; kRadTolerance = rhs.kRadTolerance;
135    fDy = rhs.fDy;                              << 160    fCubicVolume = rhs.fCubicVolume; fSurfaceArea = rhs.fSurfaceArea;
136    fDz = rhs.fDz;                              << 161    xSemiAxis = rhs.xSemiAxis; ySemiAxis = rhs.ySemiAxis;
137    fZBottomCut = rhs.fZBottomCut;              << 162    zSemiAxis = rhs.zSemiAxis; semiAxisMax = rhs.semiAxisMax;
138    fZTopCut = rhs.fZTopCut;                    << 163    zBottomCut = rhs.zBottomCut; zTopCut = rhs.zTopCut;
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                                                   164 
160    return *this;                                  165    return *this;
161 }                                                 166 }
162                                                   167 
163 ////////////////////////////////////////////// << 168 ///////////////////////////////////////////////////////////////////////////////
164 //                                                169 //
165 // Check parameters and make precalculation    << 170 // Calculate extent under transform and specified limit
166                                                   171 
167 void G4Ellipsoid::CheckParameters()            << 172 G4bool
                                                   >> 173 G4Ellipsoid::CalculateExtent(const EAxis pAxis,
                                                   >> 174                              const G4VoxelLimits& pVoxelLimit,
                                                   >> 175                              const G4AffineTransform& pTransform,
                                                   >> 176                                    G4double& pMin, G4double& pMax) const
168 {                                                 177 {
169   halfTolerance = 0.5 * kCarTolerance; // half << 178   if (!pTransform.IsRotated())
170   G4double dmin = 2. * kCarTolerance;          << 
171                                                << 
172   // Check dimensions                          << 
173   //                                           << 
174   if (fDx < dmin || fDy < dmin || fDz < dmin)  << 
175   {                                               179   {
176     std::ostringstream message;                << 180     // Special case handling for unrotated solid ellipsoid
177     message << "Invalid (too small or negative << 181     // Compute x/y/z mins and maxs for bounding box respecting limits,
178             << GetName()  << "\n"              << 182     // with early returns if outside limits. Then switch() on pAxis,
179             << "  semi-axis x: " << fDx << "\n << 183     // and compute exact x and y limit for x/y case
180             << "  semi-axis y: " << fDy << "\n << 184 
181             << "  semi-axis z: " << fDz;       << 185     G4double xoffset,xMin,xMax;
182     G4Exception("G4Ellipsoid::CheckParameters( << 186     G4double yoffset,yMin,yMax;
183                 FatalException, message);      << 187     G4double zoffset,zMin,zMax;
184   }                                            << 188 
185   G4double A = fDx;                            << 189     G4double maxDiff,newMin,newMax;
186   G4double B = fDy;                            << 190     G4double xoff,yoff;
187   G4double C = fDz;                            << 191 
                                                   >> 192     xoffset=pTransform.NetTranslation().x();
                                                   >> 193     xMin=xoffset - xSemiAxis;
                                                   >> 194     xMax=xoffset + xSemiAxis;
                                                   >> 195     if (pVoxelLimit.IsXLimited())
                                                   >> 196     {
                                                   >> 197       if ( (xMin>pVoxelLimit.GetMaxXExtent()+kCarTolerance)
                                                   >> 198         || (xMax<pVoxelLimit.GetMinXExtent()-kCarTolerance) )
                                                   >> 199       {
                                                   >> 200         return false;
                                                   >> 201       }
                                                   >> 202       else
                                                   >> 203       {
                                                   >> 204         if (xMin<pVoxelLimit.GetMinXExtent())
                                                   >> 205         {
                                                   >> 206           xMin=pVoxelLimit.GetMinXExtent();
                                                   >> 207         }
                                                   >> 208         if (xMax>pVoxelLimit.GetMaxXExtent())
                                                   >> 209         {
                                                   >> 210           xMax=pVoxelLimit.GetMaxXExtent();
                                                   >> 211         }
                                                   >> 212       }
                                                   >> 213     }
188                                                   214 
189   // Check cuts                                << 215     yoffset=pTransform.NetTranslation().y();
190   //                                           << 216     yMin=yoffset - ySemiAxis;
191   if (fZBottomCut == 0. && fZTopCut == 0.)     << 217     yMax=yoffset + ySemiAxis;
192   {                                            << 218     if (pVoxelLimit.IsYLimited())
193     fZBottomCut = -C;                          << 219     {
194     fZTopCut = C;                              << 220       if ( (yMin>pVoxelLimit.GetMaxYExtent()+kCarTolerance)
195   }                                            << 221         || (yMax<pVoxelLimit.GetMinYExtent()-kCarTolerance) )
196   if (fZBottomCut >= C || fZTopCut <= -C || fZ << 222       {
197   {                                            << 223         return false;
198     std::ostringstream message;                << 224       }
199     message << "Invalid Z cuts for Solid: "    << 225       else
200             << GetName() << "\n"               << 226       {
201             << "  bottom cut: " << fZBottomCut << 227         if (yMin<pVoxelLimit.GetMinYExtent())
202             << "  top cut: " << fZTopCut;      << 228         {
203     G4Exception("G4Ellipsoid::CheckParameters( << 229           yMin=pVoxelLimit.GetMinYExtent();
204                 FatalException, message);      << 230         }
                                                   >> 231         if (yMax>pVoxelLimit.GetMaxYExtent())
                                                   >> 232         {
                                                   >> 233           yMax=pVoxelLimit.GetMaxYExtent();
                                                   >> 234         }
                                                   >> 235       }
                                                   >> 236     }
205                                                   237 
206   }                                            << 238     zoffset=pTransform.NetTranslation().z();
207   fZBottomCut = std::max(fZBottomCut, -C);     << 239     zMin=zoffset + (-zSemiAxis > zBottomCut ? -zSemiAxis : zBottomCut);
208   fZTopCut = std::min(fZTopCut, C);            << 240     zMax=zoffset + ( zSemiAxis < zTopCut ? zSemiAxis : zTopCut);
                                                   >> 241     if (pVoxelLimit.IsZLimited())
                                                   >> 242     {
                                                   >> 243       if ( (zMin>pVoxelLimit.GetMaxZExtent()+kCarTolerance)
                                                   >> 244         || (zMax<pVoxelLimit.GetMinZExtent()-kCarTolerance) )
                                                   >> 245       {
                                                   >> 246         return false;
                                                   >> 247       }
                                                   >> 248       else
                                                   >> 249       {
                                                   >> 250         if (zMin<pVoxelLimit.GetMinZExtent())
                                                   >> 251         {
                                                   >> 252           zMin=pVoxelLimit.GetMinZExtent();
                                                   >> 253         }
                                                   >> 254         if (zMax>pVoxelLimit.GetMaxZExtent())
                                                   >> 255         {
                                                   >> 256           zMax=pVoxelLimit.GetMaxZExtent();
                                                   >> 257         }
                                                   >> 258       }
                                                   >> 259     }
209                                                   260 
210   // Set extent in x and y                     << 261     // if here, then known to cut bounding box around ellipsoid
211   fXmax = A;                                   << 262     //
212   fYmax = B;                                   << 263     xoff = (xoffset < xMin) ? (xMin-xoffset)
213   if (fZBottomCut > 0.)                        << 264          : (xoffset > xMax) ? (xoffset-xMax) : 0.0;
214   {                                            << 265     yoff = (yoffset < yMin) ? (yMin-yoffset)
215     G4double ratio = fZBottomCut / C;          << 266          : (yoffset > yMax) ? (yoffset-yMax) : 0.0;
216     G4double scale = std::sqrt((1. - ratio) *  << 267 
217     fXmax *= scale;                            << 268     // detailed calculations
218     fYmax *= scale;                            << 269     // NOTE: does not use X or Y offsets to adjust Z range,
                                                   >> 270     // and does not use Z offset to adjust X or Y range,
                                                   >> 271     // which is consistent with G4Sphere::CalculateExtent behavior
                                                   >> 272     //
                                                   >> 273     switch (pAxis)
                                                   >> 274     {
                                                   >> 275       case kXAxis:
                                                   >> 276         if (yoff==0.)
                                                   >> 277         {
                                                   >> 278           // YZ limits cross max/min x => no change
                                                   >> 279           //
                                                   >> 280           pMin=xMin;
                                                   >> 281           pMax=xMax;
                                                   >> 282         }
                                                   >> 283         else
                                                   >> 284         {
                                                   >> 285           // YZ limits don't cross max/min x => compute max delta x,
                                                   >> 286           // hence new mins/maxs
                                                   >> 287           //
                                                   >> 288           maxDiff= 1.0-sqr(yoff/ySemiAxis);
                                                   >> 289           if (maxDiff < 0.0) { return false; }
                                                   >> 290           maxDiff= xSemiAxis * std::sqrt(maxDiff);
                                                   >> 291           newMin=xoffset-maxDiff;
                                                   >> 292           newMax=xoffset+maxDiff;
                                                   >> 293           pMin=(newMin<xMin) ? xMin : newMin;
                                                   >> 294           pMax=(newMax>xMax) ? xMax : newMax;
                                                   >> 295         }
                                                   >> 296         break;
                                                   >> 297       case kYAxis:
                                                   >> 298         if (xoff==0.)
                                                   >> 299         {
                                                   >> 300           // XZ limits cross max/min y => no change
                                                   >> 301           //
                                                   >> 302           pMin=yMin;
                                                   >> 303           pMax=yMax;
                                                   >> 304         }
                                                   >> 305         else
                                                   >> 306         {
                                                   >> 307           // XZ limits don't cross max/min y => compute max delta y,
                                                   >> 308           // hence new mins/maxs
                                                   >> 309           //
                                                   >> 310           maxDiff= 1.0-sqr(xoff/xSemiAxis);
                                                   >> 311           if (maxDiff < 0.0) { return false; }
                                                   >> 312           maxDiff= ySemiAxis * std::sqrt(maxDiff);
                                                   >> 313           newMin=yoffset-maxDiff;
                                                   >> 314           newMax=yoffset+maxDiff;
                                                   >> 315           pMin=(newMin<yMin) ? yMin : newMin;
                                                   >> 316           pMax=(newMax>yMax) ? yMax : newMax;
                                                   >> 317         }
                                                   >> 318         break;
                                                   >> 319       case kZAxis:
                                                   >> 320         pMin=zMin;
                                                   >> 321         pMax=zMax;
                                                   >> 322         break;
                                                   >> 323       default:
                                                   >> 324         break;
                                                   >> 325     }
                                                   >> 326   
                                                   >> 327     pMin-=kCarTolerance;
                                                   >> 328     pMax+=kCarTolerance;
                                                   >> 329     return true;
219   }                                               330   }
220   if (fZTopCut < 0.)                           << 331   else  // not rotated
221   {                                               332   {
222     G4double ratio  = fZTopCut / C;            << 333     G4int i,j,noEntries,noBetweenSections;
223     G4double scale  = std::sqrt((1. - ratio) * << 334     G4bool existsAfterClip=false;
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                                                   335 
239   // Coefficients for approximation of distanc << 336     // Calculate rotated vertex coordinates
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                                                   337 
253 void G4Ellipsoid::ComputeDimensions(G4VPVParam << 338     G4int noPolygonVertices=0;
254                                     const G4in << 339     G4ThreeVectorList* vertices =
255                                     const G4VP << 340       CreateRotatedVertices(pTransform,noPolygonVertices);
256 {                                              << 341 
257   p->ComputeDimensions(*this,n,pRep);          << 342     pMin=+kInfinity;
258 }                                              << 343     pMax=-kInfinity;
                                                   >> 344 
                                                   >> 345     noEntries=vertices->size(); // noPolygonVertices*noPhiCrossSections
                                                   >> 346     noBetweenSections=noEntries-noPolygonVertices;
                                                   >> 347     
                                                   >> 348     G4ThreeVectorList ThetaPolygon;
                                                   >> 349     for (i=0;i<noEntries;i+=noPolygonVertices)
                                                   >> 350     {
                                                   >> 351       for(j=0;j<(noPolygonVertices/2)-1;j++)
                                                   >> 352       {
                                                   >> 353         ThetaPolygon.push_back((*vertices)[i+j]);  
                                                   >> 354         ThetaPolygon.push_back((*vertices)[i+j+1]);  
                                                   >> 355         ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-2-j]);
                                                   >> 356         ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-1-j]);
                                                   >> 357         CalculateClippedPolygonExtent(ThetaPolygon,pVoxelLimit,pAxis,pMin,pMax);
                                                   >> 358         ThetaPolygon.clear();
                                                   >> 359       }
                                                   >> 360     }
                                                   >> 361     for (i=0;i<noBetweenSections;i+=noPolygonVertices)
                                                   >> 362     {
                                                   >> 363       for(j=0;j<noPolygonVertices-1;j++)
                                                   >> 364       {
                                                   >> 365         ThetaPolygon.push_back((*vertices)[i+j]);  
                                                   >> 366         ThetaPolygon.push_back((*vertices)[i+j+1]);  
                                                   >> 367         ThetaPolygon.push_back((*vertices)[i+noPolygonVertices+j+1]);
                                                   >> 368         ThetaPolygon.push_back((*vertices)[i+noPolygonVertices+j]);
                                                   >> 369         CalculateClippedPolygonExtent(ThetaPolygon,pVoxelLimit,pAxis,pMin,pMax);
                                                   >> 370         ThetaPolygon.clear();
                                                   >> 371       }
                                                   >> 372       ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-1]);
                                                   >> 373       ThetaPolygon.push_back((*vertices)[i]);
                                                   >> 374       ThetaPolygon.push_back((*vertices)[i+noPolygonVertices]);
                                                   >> 375       ThetaPolygon.push_back((*vertices)[i+2*noPolygonVertices-1]);
                                                   >> 376       CalculateClippedPolygonExtent(ThetaPolygon,pVoxelLimit,pAxis,pMin,pMax);
                                                   >> 377       ThetaPolygon.clear();
                                                   >> 378     }
                                                   >> 379     if ( (pMin!=kInfinity) || (pMax!=-kInfinity) )
                                                   >> 380     {
                                                   >> 381       existsAfterClip=true;
                                                   >> 382     
                                                   >> 383       // Add 2*tolerance to avoid precision troubles
                                                   >> 384       //
                                                   >> 385       pMin-=kCarTolerance;
                                                   >> 386       pMax+=kCarTolerance;
259                                                   387 
260 ////////////////////////////////////////////// << 388     }
261 //                                             << 389     else
262 // Get bounding box                            << 390     {
                                                   >> 391       // Check for case where completely enveloping clipping volume
                                                   >> 392       // If point inside then we are confident that the solid completely
                                                   >> 393       // envelopes the clipping volume. Hence set min/max extents according
                                                   >> 394       // to clipping volume extents along the specified axis.
                                                   >> 395       //
                                                   >> 396       G4ThreeVector
                                                   >> 397       clipCentre((pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
                                                   >> 398                  (pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
                                                   >> 399                  (pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5);
263                                                   400 
264 void G4Ellipsoid::BoundingLimits(G4ThreeVector << 401       if (Inside(pTransform.Inverse().TransformPoint(clipCentre))!=kOutside)
265                                  G4ThreeVector << 402       {
266 {                                              << 403         existsAfterClip=true;
267   pMin.set(-fXmax,-fYmax, fZBottomCut);        << 404         pMin=pVoxelLimit.GetMinExtent(pAxis);
268   pMax.set( fXmax, fYmax, fZTopCut);           << 405         pMax=pVoxelLimit.GetMaxExtent(pAxis);
                                                   >> 406       }
                                                   >> 407     }
                                                   >> 408     delete vertices;
                                                   >> 409     return existsAfterClip;
                                                   >> 410   }
269 }                                                 411 }
270                                                   412 
271 ////////////////////////////////////////////// << 413 ///////////////////////////////////////////////////////////////////////////////
272 //                                                414 //
273 // Calculate extent under transform and specif << 415 // Return whether point inside/outside/on surface
                                                   >> 416 // Split into radius, phi, theta checks
                                                   >> 417 // Each check modifies `in', or returns as approprate
274                                                   418 
275 G4bool                                         << 419 EInside G4Ellipsoid::Inside(const G4ThreeVector& p) const
276 G4Ellipsoid::CalculateExtent(const EAxis pAxis << 
277                              const G4VoxelLimi << 
278                              const G4AffineTra << 
279                                    G4double& p << 
280 {                                                 420 {
281   G4ThreeVector bmin, bmax;                    << 421   G4double rad2oo,  // outside surface outer tolerance
                                                   >> 422            rad2oi;  // outside surface inner tolerance
                                                   >> 423   EInside in;
282                                                   424 
283   // Get bounding box                          << 425   static const G4double halfRadTolerance=kRadTolerance*0.5;
284   BoundingLimits(bmin,bmax);                   << 
285                                                   426 
286   // Find extent                               << 427   // check this side of z cut first, because that's fast
287   G4BoundingEnvelope bbox(bmin,bmax);          << 428   //
288   return bbox.CalculateExtent(pAxis,pVoxelLimi << 429   if (p.z() < zBottomCut-halfRadTolerance) { return in=kOutside; }
289 }                                              << 430   if (p.z() > zTopCut+halfRadTolerance)    { return in=kOutside; }
290                                                   431 
291 ////////////////////////////////////////////// << 432   rad2oo= sqr(p.x()/(xSemiAxis+halfRadTolerance))
292 //                                             << 433         + sqr(p.y()/(ySemiAxis+halfRadTolerance))
293 // Return position of point: inside/outside/on << 434         + sqr(p.z()/(zSemiAxis+halfRadTolerance));
                                                   >> 435 
                                                   >> 436   if (rad2oo > 1.0)  { return in=kOutside; }
                                                   >> 437     
                                                   >> 438   rad2oi= sqr(p.x()*(1.0+halfRadTolerance/xSemiAxis)/xSemiAxis)
                                                   >> 439       + sqr(p.y()*(1.0+halfRadTolerance/ySemiAxis)/ySemiAxis)
                                                   >> 440       + sqr(p.z()*(1.0+halfRadTolerance/zSemiAxis)/zSemiAxis);
294                                                   441 
295 EInside G4Ellipsoid::Inside(const G4ThreeVecto << 442   // Check radial surfaces
296 {                                              << 443   //  sets `in' (already checked for rad2oo > 1.0)
297   G4double x     = p.x() * fSx;                << 444   //
298   G4double y     = p.y() * fSy;                << 445   if (rad2oi < 1.0)
299   G4double z     = p.z() * fSz;                << 446   {
300   G4double rr    = x * x + y * y + z * z;      << 447     in = ( (p.z() < zBottomCut+halfRadTolerance)
301   G4double distZ = std::abs(z - fZMidCut) - fZ << 448         || (p.z() > zTopCut-halfRadTolerance) ) ? kSurface : kInside;
302   G4double distR = fQ1 * rr - fQ2;             << 449     if ( rad2oi > 1.0-halfRadTolerance )  { in=kSurface; }
303   G4double dist  = std::max(distZ, distR);     << 450   }
                                                   >> 451   else 
                                                   >> 452   {
                                                   >> 453     in = kSurface;
                                                   >> 454   }
                                                   >> 455   return in;
304                                                   456 
305   if (dist > halfTolerance) return kOutside;   << 
306   return (dist > -halfTolerance) ? kSurface :  << 
307 }                                                 457 }
308                                                   458 
309 ////////////////////////////////////////////// << 459 ///////////////////////////////////////////////////////////////////////////////
310 //                                                460 //
311 // Return unit normal to surface at p          << 461 // Return unit normal of surface closest to p not protected against p=0
312                                                   462 
313 G4ThreeVector G4Ellipsoid::SurfaceNormal( cons    463 G4ThreeVector G4Ellipsoid::SurfaceNormal( const G4ThreeVector& p) const
314 {                                                 464 {
315   G4ThreeVector norm(0., 0., 0.);              << 465   G4double distR, distZBottom, distZTop;
316   G4int nsurf = 0;                             << 
317                                                   466 
318   // Check cuts                                << 467   // normal vector with special magnitude:  parallel to normal, units 1/length
319   G4double x = p.x() * fSx;                    << 468   // norm*p == 1.0 if on surface, >1.0 if outside, <1.0 if inside
320   G4double y = p.y() * fSy;                    << 469   //
321   G4double z = p.z() * fSz;                    << 470   G4ThreeVector norm(p.x()/(xSemiAxis*xSemiAxis),
322   G4double distZ = std::abs(z - fZMidCut) - fZ << 471                      p.y()/(ySemiAxis*ySemiAxis),
323   if (std::abs(distZ) <= halfTolerance)        << 472                      p.z()/(zSemiAxis*zSemiAxis));
324   {                                            << 473   G4double radius = 1.0/norm.mag();
325     norm.setZ(std::copysign(1., z - fZMidCut)) << 
326     ++nsurf;                                   << 
327   }                                            << 
328                                                   474 
329   // Check lateral surface                     << 475   // approximate distance to curved surface
330   G4double distR = fQ1*(x*x + y*y + z*z) - fQ2 << 476   //
331   if (std::abs(distR) <= halfTolerance)        << 477   distR = std::fabs( (p*norm - 1.0) * radius ) / 2.0;
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                                                   478 
338   // Return normal                             << 479   // Distance to z-cut plane
339   if (nsurf == 1) return norm;                 << 480   //
340   else if (nsurf > 1) return norm.unit(); // e << 481   distZBottom = std::fabs( p.z() - zBottomCut );
341   else                                         << 482   distZTop = std::fabs( p.z() - zTopCut );
                                                   >> 483 
                                                   >> 484   if ( (distZBottom < distR) || (distZTop < distR) )
342   {                                               485   {
343 #ifdef G4SPECSDEBUG                            << 486     return G4ThreeVector(0.,0.,(distZBottom < distZTop) ? -1.0 : 1.0);
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   }                                               487   }
                                                   >> 488   return ( norm *= radius );
359 }                                                 489 }
360                                                   490 
361 ////////////////////////////////////////////// << 491 ///////////////////////////////////////////////////////////////////////////////
362 //                                                492 //
363 // Find surface nearest to point and return co << 493 // Calculate distance to shape from outside, along normalised vector
364 // This method normally should not be called.  << 494 // - return kInfinity if no intersection, or intersection distance <= tolerance
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 //                                                495 //
382 // Calculate distance to shape from outside al << 
383                                                   496 
384 G4double G4Ellipsoid::DistanceToIn(const G4Thr << 497 G4double G4Ellipsoid::DistanceToIn( const G4ThreeVector& p,
385                                    const G4Thr << 498                                     const G4ThreeVector& v  ) const
386 {                                                 499 {
387   G4double offset = 0.;                        << 500   static const G4double halfCarTolerance=kCarTolerance*0.5;
388   G4ThreeVector pcur = p;                      << 501   static const G4double halfRadTolerance=kRadTolerance*0.5;
389                                                   502 
390   // Check if point is flying away, relative t << 503   G4double distMin = std::min(xSemiAxis,ySemiAxis);
391   //                                           << 504   const G4double dRmax = 100.*std::min(distMin,zSemiAxis);
392   G4double safex = std::abs(p.x()) - fXmax;    << 505   distMin= kInfinity;
393   G4double safey = std::abs(p.y()) - fYmax;    << 
394   G4double safet = p.z() - fZTopCut;           << 
395   G4double safeb = fZBottomCut - p.z();        << 
396                                                   506 
397   if (safex >= -halfTolerance && p.x() * v.x() << 507   // check to see if Z plane is relevant
398   if (safey >= -halfTolerance && p.y() * v.y() << 508   if (p.z() <= zBottomCut+halfCarTolerance)
399   if (safet >= -halfTolerance && v.z() >= 0.)  << 509   {
400   if (safeb >= -halfTolerance && v.z() <= 0.)  << 510     if (v.z() <= 0.0) { return distMin; }
                                                   >> 511     G4double distZ = (zBottomCut - p.z()) / v.z();
401                                                   512 
402   // Relocate point, if required               << 513     if ( (distZ > -halfRadTolerance) && (Inside(p+distZ*v) != kOutside) )
403   //                                           << 514     {
404   G4double safe = std::max(std::max(std::max(s << 515       // early exit since can't intercept curved surface if we reach here
405   if (safe > 32. * fRsph)                      << 516       if ( std::fabs(distZ) < halfRadTolerance ) { distZ=0.; }
                                                   >> 517       return distMin= distZ;
                                                   >> 518     }
                                                   >> 519   }
                                                   >> 520   if (p.z() >= zTopCut-halfCarTolerance)
406   {                                               521   {
407     offset = (1. - 1.e-08) * safe - 2. * fRsph << 522     if (v.z() >= 0.0) { return distMin;}
408     pcur += offset * v;                        << 523     G4double distZ = (zTopCut - p.z()) / v.z();
409     G4double dist = DistanceToIn(pcur, v);     << 524     if ( (distZ > -halfRadTolerance) && (Inside(p+distZ*v) != kOutside) )
410     return (dist == kInfinity) ? kInfinity : d << 525     {
                                                   >> 526       // early exit since can't intercept curved surface if we reach here
                                                   >> 527       if ( std::fabs(distZ) < halfRadTolerance ) { distZ=0.; }
                                                   >> 528       return distMin= distZ;
                                                   >> 529     }
411   }                                               530   }
                                                   >> 531   // if fZCut1 <= p.z() <= fZCut2, then must hit curved surface
412                                                   532 
413   // Scale ellipsoid to sphere                 << 533   // now check curved surface intercept
414   //                                           << 534   G4double A,B,C;
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                                                   535 
422   // Check if point is leaving the solid       << 536   A= sqr(v.x()/xSemiAxis) + sqr(v.y()/ySemiAxis) + sqr(v.z()/zSemiAxis);
423   //                                           << 537   C= sqr(p.x()/xSemiAxis) + sqr(p.y()/ySemiAxis) + sqr(p.z()/zSemiAxis) - 1.0;
424   G4double dzcut = fZDimCut;                   << 538   B= 2.0 * ( p.x()*v.x()/(xSemiAxis*xSemiAxis)
425   G4double pzcut = pz - fZMidCut;              << 539            + p.y()*v.y()/(ySemiAxis*ySemiAxis)
426   G4double distZ = std::abs(pzcut) - dzcut;    << 540            + p.z()*v.z()/(zSemiAxis*zSemiAxis) );
427   if (distZ >= -halfTolerance && pzcut * vz >= << 541 
                                                   >> 542   C= B*B - 4.0*A*C;
                                                   >> 543   if (C > 0.0)
                                                   >> 544   {    
                                                   >> 545     G4double distR= (-B - std::sqrt(C)) / (2.0*A);
                                                   >> 546     G4double intZ = p.z()+distR*v.z();
                                                   >> 547     if ( (distR > halfRadTolerance)
                                                   >> 548       && (intZ >= zBottomCut-halfRadTolerance)
                                                   >> 549       && (intZ <= zTopCut+halfRadTolerance) )
                                                   >> 550     { 
                                                   >> 551       distMin = distR;
                                                   >> 552     }
                                                   >> 553     else if( (distR >- halfRadTolerance)
                                                   >> 554       && (intZ >= zBottomCut-halfRadTolerance)
                                                   >> 555       && (intZ <= zTopCut+halfRadTolerance) )
                                                   >> 556     {
                                                   >> 557       // p is on the curved surface, DistanceToIn returns 0 or kInfinity:
                                                   >> 558       // DistanceToIn returns 0, if second root is positive (means going inside)
                                                   >> 559       // If second root is negative, DistanceToIn returns kInfinity (outside)
                                                   >> 560       //
                                                   >> 561       distR = (-B + std::sqrt(C) ) / (2.0*A);
                                                   >> 562       if(distR>0.) { distMin=0.; }
                                                   >> 563     }
                                                   >> 564     else
                                                   >> 565     {
                                                   >> 566       distR= (-B + std::sqrt(C)) / (2.0*A);
                                                   >> 567       intZ = p.z()+distR*v.z();
                                                   >> 568       if ( (distR > halfRadTolerance)
                                                   >> 569         && (intZ >= zBottomCut-halfRadTolerance)
                                                   >> 570         && (intZ <= zTopCut+halfRadTolerance) )
                                                   >> 571       {
                                                   >> 572         G4ThreeVector norm=SurfaceNormal(p);
                                                   >> 573         if (norm.dot(v)<0.) { distMin = distR; }
                                                   >> 574       }
                                                   >> 575     }
                                                   >> 576     if ( (distMin!=kInfinity) && (distMin>dRmax) ) 
                                                   >> 577     {                    // Avoid rounding errors due to precision issues on
                                                   >> 578                          // 64 bits systems. Split long distances and recompute
                                                   >> 579       G4double fTerm = distMin-std::fmod(distMin,dRmax);
                                                   >> 580       distMin = fTerm + DistanceToIn(p+fTerm*v,v);
                                                   >> 581     }
                                                   >> 582   }
                                                   >> 583   
                                                   >> 584   if (std::fabs(distMin)<halfRadTolerance) { distMin=0.; }
                                                   >> 585   return distMin;
                                                   >> 586 } 
428                                                   587 
429   G4double rr = px * px + py * py + pz * pz;   << 588 ///////////////////////////////////////////////////////////////////////////////
430   G4double pv = px * vx + py * vy + pz * vz;   << 589 //
431   G4double distR = fQ1 * rr - fQ2;             << 590 // Calculate distance (<= actual) to closest surface of shape from outside
432   if (distR >= -halfTolerance && pv >= 0.) ret << 591 // - Return 0 if point inside
433                                                   592 
434   G4double A = vx * vx + vy * vy + vz * vz;    << 593 G4double G4Ellipsoid::DistanceToIn(const G4ThreeVector& p) const
435   G4double B = pv;                             << 594 {
436   G4double C = rr - fR * fR;                   << 595   G4double distR, distZ;
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                                                   596 
442   // Find intersection with Z planes           << 597   // normal vector:  parallel to normal, magnitude 1/(characteristic radius)
443   //                                              598   //
444   G4double invz  = (vz == 0) ? DBL_MAX : -1./v << 599   G4ThreeVector norm(p.x()/(xSemiAxis*xSemiAxis),
445   G4double dz    = std::copysign(dzcut, invz); << 600                      p.y()/(ySemiAxis*ySemiAxis),
446   G4double tzmin = (pzcut - dz) * invz;        << 601                      p.z()/(zSemiAxis*zSemiAxis));
447   G4double tzmax = (pzcut + dz) * invz;        << 602   G4double radius= 1.0/norm.mag();
448                                                   603 
449   // Find intersection with lateral surface    << 604   // approximate distance to curved surface ( <= actual distance )
450   //                                              605   //
451   G4double tmp = -B - std::copysign(std::sqrt( << 606   distR= (p*norm - 1.0) * radius / 2.0;
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                                                   607 
457   // Return distance                           << 608   // Distance to z-cut plane
458   //                                              609   //
459   G4double tmin = std::max(tzmin, trmin);      << 610   distZ= zBottomCut - p.z();
460   G4double tmax = std::min(tzmax, trmax);      << 611   if (distZ < 0.0)
461                                                << 612   {
462   if (tmax - tmin <= halfTolerance) return kIn << 613     distZ = p.z() - zTopCut;
463   return (tmin < halfTolerance) ? offset : tmi << 614   }
464 }                                              << 
465                                                << 
466 ////////////////////////////////////////////// << 
467 //                                             << 
468 // Estimate distance to surface from outside   << 
469                                                   615 
470 G4double G4Ellipsoid::DistanceToIn(const G4Thr << 616   // Distance to closest surface from outside
471 {                                              << 617   //
472   G4double px = p.x();                         << 618   if (distZ < 0.0)
473   G4double py = p.y();                         << 619   {
474   G4double pz = p.z();                         << 620     return (distR < 0.0) ? 0.0 : distR;
475                                                << 621   }
476   // Safety distance to bounding box           << 622   else if (distR < 0.0)
477   G4double distX = std::abs(px) - fXmax;       << 623   {
478   G4double distY = std::abs(py) - fYmax;       << 624     return distZ;
479   G4double distZ = std::max(pz - fZTopCut, fZB << 625   }
480   G4double distB = std::max(std::max(distX, di << 626   else
481                                                << 627   {
482   // Safety distance to lateral surface        << 628     return (distZ < distR) ? distZ : distR;
483   G4double x = px * fSx;                       << 629   }
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 }                                                 630 }
492                                                   631 
493 ////////////////////////////////////////////// << 632 ///////////////////////////////////////////////////////////////////////////////
494 //                                                633 //
495 // Calculate distance to surface from inside a << 634 // Calculate distance to surface of shape from `inside', allowing for tolerance
496                                                   635 
497 G4double G4Ellipsoid::DistanceToOut(const G4Th    636 G4double G4Ellipsoid::DistanceToOut(const G4ThreeVector& p,
498                                     const G4Th    637                                     const G4ThreeVector& v,
499                                     const G4bo    638                                     const G4bool calcNorm,
500                                           G4bo << 639                                           G4bool *validNorm,
501                                           G4Th << 640                                           G4ThreeVector *n  ) const
502 {                                                 641 {
503   // Check if point flying away relative to Z  << 642   G4double distMin;
                                                   >> 643   enum surface_e {kPlaneSurf, kCurvedSurf, kNoSurf} surface;
                                                   >> 644   
                                                   >> 645   distMin= kInfinity;
                                                   >> 646   surface= kNoSurf;
                                                   >> 647 
                                                   >> 648   // check to see if Z plane is relevant
504   //                                              649   //
505   G4double pz = p.z() * fSz;                   << 650   if (v.z() < 0.0)
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   {                                               651   {
512     if (calcNorm)                              << 652     G4double distZ = (zBottomCut - p.z()) / v.z();
                                                   >> 653     if (distZ < 0.0)
513     {                                             654     {
514       *validNorm = true;                       << 655       distZ= 0.0;
515       n->set(0., 0., std::copysign(1., pzcut)) << 656       if (!calcNorm) {return 0.0;}
516     }                                             657     }
517     return 0.;                                 << 658     distMin= distZ;
                                                   >> 659     surface= kPlaneSurf;
518   }                                               660   }
519                                                << 661   if (v.z() > 0.0)
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   {                                               662   {
531     if (calcNorm)                              << 663     G4double distZ = (zTopCut - p.z()) / v.z();
                                                   >> 664     if (distZ < 0.0)
532     {                                             665     {
533       *validNorm = true;                       << 666       distZ= 0.0;
534       *n = G4ThreeVector(px*fSx, py*fSy, pz*fS << 667       if (!calcNorm) {return 0.0;}
535     }                                             668     }
536     return 0.;                                 << 669     distMin= distZ;
                                                   >> 670     surface= kPlaneSurf;
537   }                                               671   }
538                                                   672 
539   // Just in case check if point is outside (n << 673   // normal vector:  parallel to normal, magnitude 1/(characteristic radius)
                                                   >> 674   //
                                                   >> 675   G4ThreeVector nearnorm(p.x()/(xSemiAxis*xSemiAxis),
                                                   >> 676                          p.y()/(ySemiAxis*ySemiAxis),
                                                   >> 677                          p.z()/(zSemiAxis*zSemiAxis));
                                                   >> 678   
                                                   >> 679   // now check curved surface intercept
540   //                                              680   //
541   if (std::max(distZ, distR) > halfTolerance)  << 681   G4double A,B,C;
                                                   >> 682   
                                                   >> 683   A= sqr(v.x()/xSemiAxis) + sqr(v.y()/ySemiAxis) + sqr(v.z()/zSemiAxis);
                                                   >> 684   C= (p * nearnorm) - 1.0;
                                                   >> 685   B= 2.0 * (v * nearnorm);
                                                   >> 686 
                                                   >> 687   C= B*B - 4.0*A*C;
                                                   >> 688   if (C > 0.0)
542   {                                               689   {
543 #ifdef G4SPECSDEBUG                            << 690     G4double distR= (-B + std::sqrt(C) ) / (2.0*A);
544     std::ostringstream message;                << 691     if (distR < 0.0)
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     {                                             692     {
557       *validNorm = true;                       << 693       distR= 0.0;
558       *n = ApproxSurfaceNormal(p);             << 694       if (!calcNorm) {return 0.0;}
                                                   >> 695     }
                                                   >> 696     if (distR < distMin)
                                                   >> 697     {
                                                   >> 698       distMin= distR;
                                                   >> 699       surface= kCurvedSurf;
559     }                                             700     }
560     return 0.;                                 << 
561   }                                               701   }
562                                                   702 
563   // Set coefficients of quadratic equation: A << 703   // set normal if requested
564   //                                              704   //
565   G4double A  = vx * vx + vy * vy + vz * vz;   << 705   if (calcNorm)
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   {                                               706   {
577     if (calcNorm)                              << 707     if (surface == kNoSurf)
                                                   >> 708     {
                                                   >> 709       *validNorm = false;
                                                   >> 710     }
                                                   >> 711     else
578     {                                             712     {
579       *validNorm = true;                          713       *validNorm = true;
580       *n = G4ThreeVector(px*fSx, py*fSy, pz*fS << 714       switch (surface)
                                                   >> 715       {
                                                   >> 716         case kPlaneSurf:
                                                   >> 717           *n= G4ThreeVector(0.,0.,(v.z() > 0.0 ? 1. : -1.));
                                                   >> 718           break;
                                                   >> 719         case kCurvedSurf:
                                                   >> 720         {
                                                   >> 721           G4ThreeVector pexit= p + distMin*v;
                                                   >> 722           G4ThreeVector truenorm(pexit.x()/(xSemiAxis*xSemiAxis),
                                                   >> 723                                  pexit.y()/(ySemiAxis*ySemiAxis),
                                                   >> 724                                  pexit.z()/(zSemiAxis*zSemiAxis));
                                                   >> 725           truenorm *= 1.0/truenorm.mag();
                                                   >> 726           *n= truenorm;
                                                   >> 727         } break;
                                                   >> 728         default:           // Should never reach this case ...
                                                   >> 729           G4int oldprc = G4cout.precision(16);
                                                   >> 730           G4cout << G4endl;
                                                   >> 731           DumpInfo();
                                                   >> 732           G4cout << "Position:"  << G4endl << G4endl;
                                                   >> 733           G4cout << "p.x() = "   << p.x()/mm << " mm" << G4endl;
                                                   >> 734           G4cout << "p.y() = "   << p.y()/mm << " mm" << G4endl;
                                                   >> 735           G4cout << "p.z() = "   << p.z()/mm << " mm" << G4endl << G4endl;
                                                   >> 736           G4cout << "Direction:" << G4endl << G4endl;
                                                   >> 737           G4cout << "v.x() = "   << v.x() << G4endl;
                                                   >> 738           G4cout << "v.y() = "   << v.y() << G4endl;
                                                   >> 739           G4cout << "v.z() = "   << v.z() << G4endl << G4endl;
                                                   >> 740           G4cout << "Proposed distance :" << G4endl << G4endl;
                                                   >> 741           G4cout << "distMin = "    << distMin/mm << " mm" << G4endl << G4endl;
                                                   >> 742           G4cout.precision(oldprc);
                                                   >> 743           G4Exception("G4Ellipsoid::DistanceToOut(p,v,..)",
                                                   >> 744                       "Notification", JustWarning,
                                                   >> 745                       "Undefined side for valid surface normal to solid.");
                                                   >> 746           break;
                                                   >> 747       }
581     }                                             748     }
582     return 0.;                                 << 
583   }                                               749   }
                                                   >> 750    
                                                   >> 751   return distMin;
                                                   >> 752 }
                                                   >> 753 
                                                   >> 754 ///////////////////////////////////////////////////////////////////////////////
                                                   >> 755 //
                                                   >> 756 // Calculate distance (<=actual) to closest surface of shape from inside
                                                   >> 757 
                                                   >> 758 G4double G4Ellipsoid::DistanceToOut(const G4ThreeVector& p) const
                                                   >> 759 {
                                                   >> 760   G4double distR, distZ;
                                                   >> 761 
                                                   >> 762 #ifdef G4SPECSDEBUG
                                                   >> 763   if( Inside(p) == kOutside )
                                                   >> 764   {
                                                   >> 765      G4int oldprc = G4cout.precision(16) ;
                                                   >> 766      G4cout << G4endl ;
                                                   >> 767      DumpInfo();
                                                   >> 768      G4cout << "Position:"  << G4endl << G4endl ;
                                                   >> 769      G4cout << "p.x() = "   << p.x()/mm << " mm" << G4endl ;
                                                   >> 770      G4cout << "p.y() = "   << p.y()/mm << " mm" << G4endl ;
                                                   >> 771      G4cout << "p.z() = "   << p.z()/mm << " mm" << G4endl << G4endl ;
                                                   >> 772      G4cout.precision(oldprc) ;
                                                   >> 773      G4Exception("G4Ellipsoid::DistanceToOut(p)", "Notification", JustWarning, 
                                                   >> 774                  "Point p is outside !?" );
                                                   >> 775   }
                                                   >> 776 #endif
584                                                   777 
585   // Find intersection with Z cuts             << 778   // Normal vector:  parallel to normal, magnitude 1/(characteristic radius)
586   //                                              779   //
587   G4double tzmax = (vz == 0.) ? DBL_MAX : (std << 780   G4ThreeVector norm(p.x()/(xSemiAxis*xSemiAxis),
                                                   >> 781                      p.y()/(ySemiAxis*ySemiAxis),
                                                   >> 782                      p.z()/(zSemiAxis*zSemiAxis));
588                                                   783 
589   // Find intersection with lateral surface    << 784   // the following is a safe inlined "radius= min(1.0/norm.mag(),p.mag())
590   //                                              785   //
591   G4double tmp = -B - std::copysign(std::sqrt( << 786   G4double radius= p.mag();
592   G4double trmax = (tmp < 0.) ? C/tmp : tmp/A; << 787   G4double tmp= norm.mag();
                                                   >> 788   if ( (tmp > 0.0) && (1.0 < radius*tmp) ) {radius = 1.0/tmp;}
593                                                   789 
594   // Find distance and set normal, if required << 790   // Approximate distance to curved surface ( <= actual distance )
595   //                                              791   //
596   G4double tmax = std::min(tzmax, trmax);      << 792   distR = (1.0 - p*norm) * radius / 2.0;
597   //if (tmax < halfTolerance) tmax = 0.;       << 793     
                                                   >> 794   // Distance to z-cut plane
                                                   >> 795   //
                                                   >> 796   distZ = p.z() - zBottomCut;
                                                   >> 797   if (distZ < 0.0) {distZ= zTopCut - p.z();}
598                                                   798 
599   if (calcNorm)                                << 799   // Distance to closest surface from inside
                                                   >> 800   //
                                                   >> 801   if ( (distZ < 0.0) || (distR < 0.0) )
600   {                                               802   {
601     *validNorm = true;                         << 803     return 0.0;
602     if (tmax == tzmax)                         << 804   }
603     {                                          << 805   else
604       G4double pznew = pz + tmax * vz;         << 806   {
605       n->set(0., 0., (pznew > fZMidCut) ? 1. : << 807     return (distZ < distR) ? distZ : distR;
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   }                                               808   }
615   return tmax;                                 << 
616 }                                                 809 }
617                                                   810 
618 ////////////////////////////////////////////// << 811 ///////////////////////////////////////////////////////////////////////////////
619 //                                                812 //
620 // Estimate distance to surface from inside    << 813 // Create a List containing the transformed vertices
                                                   >> 814 // Ordering [0-3] -fDz cross section
                                                   >> 815 //          [4-7] +fDz cross section such that [0] is below [4],
                                                   >> 816 //                                             [1] below [5] etc.
                                                   >> 817 // Note:
                                                   >> 818 //  Caller has deletion resposibility
                                                   >> 819 //  Potential improvement: For last slice, use actual ending angle
                                                   >> 820 //                         to avoid rounding error problems.
                                                   >> 821 
                                                   >> 822 G4ThreeVectorList*
                                                   >> 823 G4Ellipsoid::CreateRotatedVertices(const G4AffineTransform& pTransform,
                                                   >> 824                                          G4int& noPolygonVertices) const
                                                   >> 825 {
                                                   >> 826   G4ThreeVectorList *vertices;
                                                   >> 827   G4ThreeVector vertex;
                                                   >> 828   G4double meshAnglePhi, meshRMaxFactor,
                                                   >> 829            crossAnglePhi, coscrossAnglePhi, sincrossAnglePhi, sAnglePhi;
                                                   >> 830   G4double meshTheta, crossTheta, startTheta;
                                                   >> 831   G4double rMaxX, rMaxY, rMaxZ, rMaxMax, rx, ry, rz;
                                                   >> 832   G4int crossSectionPhi, noPhiCrossSections, crossSectionTheta, noThetaSections;
621                                                   833 
622 G4double G4Ellipsoid::DistanceToOut(const G4Th << 834   // Phi cross sections
623 {                                              << 835   //
624   // Safety distance in z direction            << 836   noPhiCrossSections=G4int (twopi/kMeshAngleDefault)+1;  // = 9!
625   G4double distZ = std::min(fZTopCut - p.z(),  << 837     
                                                   >> 838 /*
                                                   >> 839   if (noPhiCrossSections<kMinMeshSections)        // <3
                                                   >> 840   {
                                                   >> 841     noPhiCrossSections=kMinMeshSections;
                                                   >> 842   }
                                                   >> 843   else if (noPhiCrossSections>kMaxMeshSections)   // >37
                                                   >> 844   {
                                                   >> 845     noPhiCrossSections=kMaxMeshSections;
                                                   >> 846   }
                                                   >> 847 */
                                                   >> 848   meshAnglePhi=twopi/(noPhiCrossSections-1);
                                                   >> 849     
                                                   >> 850   // Set start angle such that mesh will be at fRMax
                                                   >> 851   // on the x axis. Will give better extent calculations when not rotated.
                                                   >> 852     
                                                   >> 853   sAnglePhi = -meshAnglePhi*0.5;
                                                   >> 854 
                                                   >> 855   // Theta cross sections
                                                   >> 856     
                                                   >> 857   noThetaSections = G4int(pi/kMeshAngleDefault)+3;  //  = 7!
626                                                   858 
627   // Safety distance to lateral surface        << 859 /*
628   G4double x = p.x() * fSx;                    << 860   if (noThetaSections<kMinMeshSections)       // <3
629   G4double y = p.y() * fSy;                    << 861   {
630   G4double z = p.z() * fSz;                    << 862     noThetaSections=kMinMeshSections;
631   G4double distR = fR - std::sqrt(x*x + y*y +  << 863   }
632                                                << 864   else if (noThetaSections>kMaxMeshSections)  // >37
633   // Return safety to out                      << 865   {
634   G4double dist = std::min(distZ, distR);      << 866     noThetaSections=kMaxMeshSections;
635   return (dist < 0.) ? 0. : dist;              << 867   }
                                                   >> 868 */
                                                   >> 869   meshTheta= pi/(noThetaSections-2);
                                                   >> 870     
                                                   >> 871   // Set start angle such that mesh will be at fRMax
                                                   >> 872   // on the z axis. Will give better extent calculations when not rotated.
                                                   >> 873     
                                                   >> 874   startTheta = -meshTheta*0.5;
                                                   >> 875 
                                                   >> 876   meshRMaxFactor =  1.0/std::cos(0.5*
                                                   >> 877                     std::sqrt(meshAnglePhi*meshAnglePhi+meshTheta*meshTheta));
                                                   >> 878   rMaxMax= (xSemiAxis > ySemiAxis ? xSemiAxis : ySemiAxis);
                                                   >> 879   if (zSemiAxis > rMaxMax) rMaxMax= zSemiAxis;
                                                   >> 880   rMaxX= xSemiAxis + rMaxMax*(meshRMaxFactor-1.0);
                                                   >> 881   rMaxY= ySemiAxis + rMaxMax*(meshRMaxFactor-1.0);
                                                   >> 882   rMaxZ= zSemiAxis + rMaxMax*(meshRMaxFactor-1.0);
                                                   >> 883   G4double* cosCrossTheta = new G4double[noThetaSections];
                                                   >> 884   G4double* sinCrossTheta = new G4double[noThetaSections];    
                                                   >> 885   vertices=new G4ThreeVectorList(noPhiCrossSections*noThetaSections);
                                                   >> 886   if (vertices && cosCrossTheta && sinCrossTheta)
                                                   >> 887   {
                                                   >> 888     for (crossSectionTheta=0; crossSectionTheta<noThetaSections;
                                                   >> 889          crossSectionTheta++)
                                                   >> 890     {
                                                   >> 891       // Compute sine and cosine table (for historical reasons)
                                                   >> 892       //
                                                   >> 893       crossTheta=startTheta+crossSectionTheta*meshTheta;
                                                   >> 894       cosCrossTheta[crossSectionTheta]=std::cos(crossTheta);
                                                   >> 895       sinCrossTheta[crossSectionTheta]=std::sin(crossTheta);
                                                   >> 896     }
                                                   >> 897     for (crossSectionPhi=0; crossSectionPhi<noPhiCrossSections;
                                                   >> 898          crossSectionPhi++)
                                                   >> 899     {
                                                   >> 900       crossAnglePhi=sAnglePhi+crossSectionPhi*meshAnglePhi;
                                                   >> 901       coscrossAnglePhi=std::cos(crossAnglePhi);
                                                   >> 902       sincrossAnglePhi=std::sin(crossAnglePhi);
                                                   >> 903       for (crossSectionTheta=0; crossSectionTheta<noThetaSections;
                                                   >> 904            crossSectionTheta++)
                                                   >> 905       {
                                                   >> 906         // Compute coordinates of cross section at section crossSectionPhi
                                                   >> 907         //
                                                   >> 908         rx= sinCrossTheta[crossSectionTheta]*coscrossAnglePhi*rMaxX;
                                                   >> 909         ry= sinCrossTheta[crossSectionTheta]*sincrossAnglePhi*rMaxY;
                                                   >> 910         rz= cosCrossTheta[crossSectionTheta]*rMaxZ;
                                                   >> 911         if (rz < zBottomCut)
                                                   >> 912           { rz= zBottomCut; }
                                                   >> 913         if (rz > zTopCut)
                                                   >> 914           { rz= zTopCut; }
                                                   >> 915         vertex= G4ThreeVector(rx,ry,rz);
                                                   >> 916         vertices->push_back(pTransform.TransformPoint(vertex));
                                                   >> 917       }    // Theta forward     
                                                   >> 918     }    // Phi
                                                   >> 919     noPolygonVertices = noThetaSections ;
                                                   >> 920   }
                                                   >> 921   else
                                                   >> 922   {
                                                   >> 923     DumpInfo();
                                                   >> 924     G4Exception("G4Ellipsoid::CreateRotatedVertices()",
                                                   >> 925                 "FatalError", FatalException,
                                                   >> 926                 "Error in allocation of vertices. Out of memory !");
                                                   >> 927   }
                                                   >> 928 
                                                   >> 929   delete[] cosCrossTheta;
                                                   >> 930   delete[] sinCrossTheta;
                                                   >> 931 
                                                   >> 932   return vertices;
636 }                                                 933 }
637                                                   934 
638 //////////////////////////////////////////////    935 //////////////////////////////////////////////////////////////////////////
639 //                                                936 //
640 // Return entity type                          << 937 // G4EntityType
641                                                   938 
642 G4GeometryType G4Ellipsoid::GetEntityType() co    939 G4GeometryType G4Ellipsoid::GetEntityType() const
643 {                                                 940 {
644   return {"G4Ellipsoid"};                      << 941   return G4String("G4Ellipsoid");
645 }                                                 942 }
646                                                   943 
647 //////////////////////////////////////////////    944 //////////////////////////////////////////////////////////////////////////
648 //                                                945 //
649 // Make a clone of the object                     946 // Make a clone of the object
650                                                   947 
651 G4VSolid* G4Ellipsoid::Clone() const              948 G4VSolid* G4Ellipsoid::Clone() const
652 {                                                 949 {
653   return new G4Ellipsoid(*this);                  950   return new G4Ellipsoid(*this);
654 }                                                 951 }
655                                                   952 
656 //////////////////////////////////////////////    953 //////////////////////////////////////////////////////////////////////////
657 //                                                954 //
658 // Stream object contents to output stream     << 955 // Stream object contents to an output stream
659                                                   956 
660 std::ostream& G4Ellipsoid::StreamInfo( std::os    957 std::ostream& G4Ellipsoid::StreamInfo( std::ostream& os ) const
661 {                                                 958 {
662   G4long oldprc = os.precision(16);            << 
663   os << "-------------------------------------    959   os << "-----------------------------------------------------------\n"
664      << "    *** Dump for solid - " << GetName    960      << "    *** Dump for solid - " << GetName() << " ***\n"
665      << "    =================================    961      << "    ===================================================\n"
666      << " Solid type: " << GetEntityType() <<  << 962      << " Solid type: G4Ellipsoid\n"
667      << " Parameters: \n"                         963      << " Parameters: \n"
668      << "    semi-axis x: " << GetDx()/mm << " << 964 
669      << "    semi-axis y: " << GetDy()/mm << " << 965      << "    semi-axis x: " << xSemiAxis/mm << " mm \n"
670      << "    semi-axis z: " << GetDz()/mm << " << 966      << "    semi-axis y: " << ySemiAxis/mm << " mm \n"
671      << "    lower cut in z: " << GetZBottomCu << 967      << "    semi-axis z: " << zSemiAxis/mm << " mm \n"
672      << "    upper cut in z: " << GetZTopCut() << 968      << "    max semi-axis: " << semiAxisMax/mm << " mm \n"
                                                   >> 969      << "    lower cut plane level z: " << zBottomCut/mm << " mm \n"
                                                   >> 970      << "    upper cut plane level z: " << zTopCut/mm << " mm \n"
673      << "-------------------------------------    971      << "-----------------------------------------------------------\n";
674   os.precision(oldprc);                        << 972 
675   return os;                                      973   return os;
676 }                                                 974 }
677                                                   975 
678 ////////////////////////////////////////////// << 976 ////////////////////////////////////////////////////////////////////
679 //                                                977 //
680 // Return volume                               << 978 // GetPointOnSurface
681                                                   979 
682 G4double G4Ellipsoid::GetCubicVolume()         << 980 G4ThreeVector G4Ellipsoid::GetPointOnSurface() const
683 {                                                 981 {
684   if (fCubicVolume == 0.)                      << 982   G4double aTop, aBottom, aCurved, chose, xRand, yRand, zRand, phi;
                                                   >> 983   G4double cosphi, sinphi, costheta, sintheta, alpha, beta, max1, max2, max3;
                                                   >> 984 
                                                   >> 985   max1  = xSemiAxis > ySemiAxis ? xSemiAxis : ySemiAxis;
                                                   >> 986   max1  = max1 > zSemiAxis ? max1 : zSemiAxis;
                                                   >> 987   if (max1 == xSemiAxis)      { max2 = ySemiAxis; max3 = zSemiAxis; }
                                                   >> 988   else if (max1 == ySemiAxis) { max2 = xSemiAxis; max3 = zSemiAxis; }
                                                   >> 989   else                        { max2 = xSemiAxis; max3 = ySemiAxis; }
                                                   >> 990 
                                                   >> 991   phi   = RandFlat::shoot(0.,twopi);
                                                   >> 992   
                                                   >> 993   cosphi = std::cos(phi);   sinphi = std::sin(phi);
                                                   >> 994   costheta = RandFlat::shoot(zBottomCut,zTopCut)/zSemiAxis;
                                                   >> 995   sintheta = std::sqrt(1.-sqr(costheta));
                                                   >> 996   
                                                   >> 997   alpha = 1.-sqr(max2/max1); beta  = 1.-sqr(max3/max1);
                                                   >> 998   
                                                   >> 999   aTop    = pi*xSemiAxis*ySemiAxis*(1 - sqr(zTopCut/zSemiAxis));
                                                   >> 1000   aBottom = pi*xSemiAxis*ySemiAxis*(1 - sqr(zBottomCut/zSemiAxis));
                                                   >> 1001   
                                                   >> 1002   // approximation
                                                   >> 1003   // from:" http://www.citr.auckland.ac.nz/techreports/2004/CITR-TR-139.pdf"
                                                   >> 1004   aCurved = 4.*pi*max1*max2*(1.-1./6.*(alpha+beta)-
                                                   >> 1005                             1./120.*(3.*sqr(alpha)+2.*alpha*beta+3.*sqr(beta)));
                                                   >> 1006 
                                                   >> 1007   aCurved *= 0.5*(1.2*zTopCut/zSemiAxis - 1.2*zBottomCut/zSemiAxis);
                                                   >> 1008   
                                                   >> 1009   if( ( zTopCut >= zSemiAxis && zBottomCut <= -1.*zSemiAxis )
                                                   >> 1010    || ( zTopCut == 0 && zBottomCut ==0 ) )
685   {                                               1011   {
686     G4double piAB_3 = CLHEP::pi * fDx * fDy /  << 1012     aTop = 0; aBottom = 0;
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   }                                               1013   }
699   return fCubicVolume;                         << 1014   
700 }                                              << 1015   chose = RandFlat::shoot(0.,aTop + aBottom + aCurved); 
701                                                << 1016   
702 ////////////////////////////////////////////// << 1017   if(chose < aCurved)
703 //                                             << 1018   { 
704 // Calculate area of lateral surface           << 1019     xRand = xSemiAxis*sintheta*cosphi;
705                                                << 1020     yRand = ySemiAxis*sintheta*sinphi;
706 G4double G4Ellipsoid::LateralSurfaceArea() con << 1021     zRand = zSemiAxis*costheta;
707 {                                              << 1022     return G4ThreeVector (xRand,yRand,zRand); 
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   }                                               1023   }
754                                                << 1024   else if(chose >= aCurved && chose < aCurved + aTop)
755   // ellipsoid, integration along phi          << 
756   for (G4int i = 0; i < NPHI; ++i)             << 
757   {                                               1025   {
758     G4double sinPhi = std::sin(dPhi*(i + 0.5)) << 1026     xRand = RandFlat::shoot(-1.,1.)*xSemiAxis
759     G4double kk = cc_aa + (cc_bb - cc_aa)*sinP << 1027           * std::sqrt(1-sqr(zTopCut/zSemiAxis));
760     if (kk < 1. - eps)                         << 1028     yRand = RandFlat::shoot(-1.,1.)*ySemiAxis
761     {                                          << 1029           * std::sqrt(1.-sqr(zTopCut/zSemiAxis)-sqr(xRand/xSemiAxis));
762       G4double root = std::sqrt(1. - kk);      << 1030     zRand = zTopCut;
763       G4double tmax = zmax_c*root;             << 1031     return G4ThreeVector (xRand,yRand,zRand);
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   }                                               1032   }
785   return area;                                 << 1033   else
786 }                                              << 
787                                                << 
788 ////////////////////////////////////////////// << 
789 //                                             << 
790 // Return surface area                         << 
791                                                << 
792 G4double G4Ellipsoid::GetSurfaceArea()         << 
793 {                                              << 
794   if (fSurfaceArea == 0.)                      << 
795   {                                               1034   {
796     G4double piAB = CLHEP::pi * fDx * fDy;     << 1035     xRand = RandFlat::shoot(-1.,1.)*xSemiAxis
797     fSurfaceArea = LateralSurfaceArea();       << 1036           * std::sqrt(1-sqr(zBottomCut/zSemiAxis));
798     if (fZBottomCut > -fDz)                    << 1037     yRand = RandFlat::shoot(-1.,1.)*ySemiAxis
799     {                                          << 1038           * std::sqrt(1.-sqr(zBottomCut/zSemiAxis)-sqr(xRand/xSemiAxis)); 
800       G4double hbot = 1. + fZBottomCut / fDz;  << 1039     zRand = zBottomCut;
801       fSurfaceArea += piAB * hbot * (2. - hbot << 1040     return G4ThreeVector (xRand,yRand,zRand);
802     }                                          << 
803     if (fZTopCut < fDz)                        << 
804     {                                          << 
805       G4double htop = 1. - fZTopCut / fDz;     << 
806       fSurfaceArea += piAB * htop * (2. - htop << 
807     }                                          << 
808   }                                               1041   }
809   return fSurfaceArea;                         << 
810 }                                                 1042 }
811                                                   1043 
812 ////////////////////////////////////////////// << 1044 /////////////////////////////////////////////////////////////////////////////
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 //                                                1045 //
892 // Methods for visualisation                      1046 // Methods for visualisation
893                                                   1047 
894 void G4Ellipsoid::DescribeYourselfTo (G4VGraph    1048 void G4Ellipsoid::DescribeYourselfTo (G4VGraphicsScene& scene) const
895 {                                                 1049 {
896   scene.AddSolid(*this);                          1050   scene.AddSolid(*this);
897 }                                                 1051 }
898                                                   1052 
899 ////////////////////////////////////////////// << 
900 //                                             << 
901 // Return vis extent                           << 
902                                                << 
903 G4VisExtent G4Ellipsoid::GetExtent() const        1053 G4VisExtent G4Ellipsoid::GetExtent() const
904 {                                                 1054 {
905   return { -fXmax, fXmax, -fYmax, fYmax, fZBot << 1055   // Define the sides of the box into which the G4Ellipsoid instance would fit.
                                                   >> 1056   //
                                                   >> 1057   return G4VisExtent (-semiAxisMax, semiAxisMax,
                                                   >> 1058                       -semiAxisMax, semiAxisMax,
                                                   >> 1059                       -semiAxisMax, semiAxisMax);
906 }                                                 1060 }
907                                                   1061 
908 ////////////////////////////////////////////// << 1062 G4NURBS* G4Ellipsoid::CreateNURBS () const
909 //                                             << 1063 {
910 // Create polyhedron                           << 1064   // Box for now!!!
                                                   >> 1065   //
                                                   >> 1066   return new G4NURBSbox(semiAxisMax, semiAxisMax, semiAxisMax);
                                                   >> 1067 }
911                                                   1068 
912 G4Polyhedron* G4Ellipsoid::CreatePolyhedron ()    1069 G4Polyhedron* G4Ellipsoid::CreatePolyhedron () const
913 {                                                 1070 {
914   return new G4PolyhedronEllipsoid(fDx, fDy, f << 1071   return new G4PolyhedronEllipsoid(xSemiAxis, ySemiAxis, zSemiAxis,
                                                   >> 1072                                    zBottomCut, zTopCut);
915 }                                                 1073 }
916                                                   1074 
917 ////////////////////////////////////////////// << 
918 //                                             << 
919 // Return pointer to polyhedron                << 
920                                                << 
921 G4Polyhedron* G4Ellipsoid::GetPolyhedron () co    1075 G4Polyhedron* G4Ellipsoid::GetPolyhedron () const
922 {                                                 1076 {
923   if (fpPolyhedron == nullptr ||               << 1077   if (!fpPolyhedron ||
924       fRebuildPolyhedron ||                    << 
925       fpPolyhedron->GetNumberOfRotationStepsAt    1078       fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
926       fpPolyhedron->GetNumberOfRotationSteps()    1079       fpPolyhedron->GetNumberOfRotationSteps())
927     {                                             1080     {
928       G4AutoLock l(&polyhedronMutex);          << 
929       delete fpPolyhedron;                        1081       delete fpPolyhedron;
930       fpPolyhedron = CreatePolyhedron();          1082       fpPolyhedron = CreatePolyhedron();
931       fRebuildPolyhedron = false;              << 
932       l.unlock();                              << 
933     }                                             1083     }
934   return fpPolyhedron;                            1084   return fpPolyhedron;
935 }                                                 1085 }
936                                                << 
937 #endif // !defined(G4GEOM_USE_UELLIPSOID) || ! << 
938                                                   1086