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 10.5.p1)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
                                                   >>  26 //
 26 // class G4Ellipsoid                               27 // class G4Ellipsoid
 27 //                                                 28 //
 28 // Implementation of G4Ellipsoid class         <<  29 // Implementation for G4Ellipsoid class
                                                   >>  30 //
                                                   >>  31 // History:
 29 //                                                 32 //
 30 // 10.11.99 G.Horton-Smith: first writing, bas     33 // 10.11.99 G.Horton-Smith: first writing, based on G4Sphere class
 31 // 25.02.05 G.Guerrieri: Revised               <<  34 // 25.02.05 G.Guerrieri: Modified for future Geant4 release
 32 // 15.12.19 E.Tcherniaev: Complete revision    <<  35 // 26.10.16 E.Tcherniaev: reimplemented CalculateExtent() using
                                                   >>  36 //                        G4BoundingEnvelope, removed CreateRotatedVertices()
                                                   >>  37 //
 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"                   47 #include "G4BoundingEnvelope.hh"
 45 #include "G4RandomTools.hh"                    <<  48 
 46 #include "G4QuickRand.hh"                      <<  49 #include "meshdefs.hh"
                                                   >>  50 #include "Randomize.hh"
 47                                                    51 
 48 #include "G4VPVParameterisation.hh"                52 #include "G4VPVParameterisation.hh"
 49                                                    53 
 50 #include "G4VGraphicsScene.hh"                     54 #include "G4VGraphicsScene.hh"
 51 #include "G4VisExtent.hh"                          55 #include "G4VisExtent.hh"
 52                                                    56 
 53 #include "G4AutoLock.hh"                           57 #include "G4AutoLock.hh"
 54                                                    58 
 55 namespace                                          59 namespace
 56 {                                                  60 {
 57   G4Mutex polyhedronMutex  = G4MUTEX_INITIALIZ <<  61   G4Mutex polyhedronMutex = G4MUTEX_INITIALIZER;
 58   G4Mutex lateralareaMutex = G4MUTEX_INITIALIZ << 
 59 }                                                  62 }
 60                                                    63 
 61 using namespace CLHEP;                             64 using namespace CLHEP;
 62                                                    65 
 63 ////////////////////////////////////////////// <<  66 ///////////////////////////////////////////////////////////////////////////////
 64 //                                                 67 //
 65 // Constructor                                 <<  68 // constructor - check parameters, convert angles so 0<sphi+dpshi<=2_PI
                                                   >>  69 //             - note if pDPhi>2PI then reset to 2PI
 66                                                    70 
 67 G4Ellipsoid::G4Ellipsoid(const G4String& name, <<  71 G4Ellipsoid::G4Ellipsoid(const G4String& pName,
 68                                G4double xSemiA <<  72                                G4double pxSemiAxis,
 69                                G4double ySemiA <<  73                                G4double pySemiAxis,
 70                                G4double zSemiA <<  74                                G4double pzSemiAxis,
 71                                G4double zBotto <<  75                                G4double pzBottomCut,
 72                                G4double zTopCu <<  76                                G4double pzTopCut)
 73   : G4VSolid(name), fDx(xSemiAxis), fDy(ySemiA <<  77   : G4VSolid(pName), fRebuildPolyhedron(false), fpPolyhedron(0),
 74     fZBottomCut(zBottomCut), fZTopCut(zTopCut) <<  78     fCubicVolume(0.), fSurfaceArea(0.), zBottomCut(0.), zTopCut(0.)
 75 {                                                  79 {
 76   CheckParameters();                           <<  80   // note: for users that want to use the full ellipsoid it is useful
                                                   >>  81   // to include a default for the cuts 
                                                   >>  82 
                                                   >>  83   kRadTolerance = G4GeometryTolerance::GetInstance()->GetRadialTolerance();
                                                   >>  84 
                                                   >>  85   halfCarTolerance = kCarTolerance*0.5;
                                                   >>  86   halfRadTolerance = kRadTolerance*0.5;
                                                   >>  87 
                                                   >>  88   // Check Semi-Axis
                                                   >>  89   if ( (pxSemiAxis<=0.) || (pySemiAxis<=0.) || (pzSemiAxis<=0.) )
                                                   >>  90   {
                                                   >>  91      std::ostringstream message;
                                                   >>  92      message << "Invalid semi-axis - " << GetName();
                                                   >>  93      G4Exception("G4Ellipsoid::G4Ellipsoid()", "GeomSolids0002",
                                                   >>  94                  FatalErrorInArgument, message);
                                                   >>  95   }
                                                   >>  96   SetSemiAxis(pxSemiAxis, pySemiAxis, pzSemiAxis);
                                                   >>  97 
                                                   >>  98   if ( pzBottomCut == 0 && pzTopCut == 0 )
                                                   >>  99   {
                                                   >> 100      SetZCuts(-pzSemiAxis, pzSemiAxis);
                                                   >> 101   }
                                                   >> 102   else if ( (pzBottomCut < pzSemiAxis) && (pzTopCut > -pzSemiAxis)
                                                   >> 103          && (pzBottomCut < pzTopCut) )
                                                   >> 104   {
                                                   >> 105      SetZCuts(pzBottomCut, pzTopCut);
                                                   >> 106   }
                                                   >> 107   else
                                                   >> 108   {
                                                   >> 109      std::ostringstream message;
                                                   >> 110      message << "Invalid z-coordinate for cutting plane - " << GetName();
                                                   >> 111      G4Exception("G4Ellipsoid::G4Ellipsoid()", "GeomSolids0002",
                                                   >> 112                  FatalErrorInArgument, message);
                                                   >> 113   }
 77 }                                                 114 }
 78                                                   115 
 79 ////////////////////////////////////////////// << 116 ///////////////////////////////////////////////////////////////////////////////
 80 //                                                117 //
 81 // Fake default constructor - sets only member    118 // Fake default constructor - sets only member data and allocates memory
 82 //                            for usage restri << 119 //                            for usage restricted to object persistency.
 83                                                << 120 //
 84 G4Ellipsoid::G4Ellipsoid( __void__& a )           121 G4Ellipsoid::G4Ellipsoid( __void__& a )
 85   : G4VSolid(a), fDx(0.), fDy(0.), fDz(0.), fZ << 122   : G4VSolid(a), fRebuildPolyhedron(false), fpPolyhedron(0), kRadTolerance(0.),
                                                   >> 123     halfCarTolerance(0.), halfRadTolerance(0.), fCubicVolume(0.),
                                                   >> 124     fSurfaceArea(0.), xSemiAxis(0.), ySemiAxis(0.), zSemiAxis(0.),
                                                   >> 125     semiAxisMax(0.), zBottomCut(0.), zTopCut(0.)
 86 {                                                 126 {
 87 }                                                 127 }
 88                                                   128 
 89 ////////////////////////////////////////////// << 129 ///////////////////////////////////////////////////////////////////////////////
 90 //                                                130 //
 91 // Destructor                                     131 // Destructor
 92                                                   132 
 93 G4Ellipsoid::~G4Ellipsoid()                       133 G4Ellipsoid::~G4Ellipsoid()
 94 {                                                 134 {
 95   delete fpPolyhedron; fpPolyhedron = nullptr; << 135   delete fpPolyhedron; fpPolyhedron = 0;
 96 }                                                 136 }
 97                                                   137 
 98 ////////////////////////////////////////////// << 138 ///////////////////////////////////////////////////////////////////////////////
 99 //                                                139 //
100 // Copy constructor                               140 // Copy constructor
101                                                   141 
102 G4Ellipsoid::G4Ellipsoid(const G4Ellipsoid& rh    142 G4Ellipsoid::G4Ellipsoid(const G4Ellipsoid& rhs)
103   : G4VSolid(rhs),                                143   : G4VSolid(rhs),
104    fDx(rhs.fDx), fDy(rhs.fDy), fDz(rhs.fDz),   << 144     fRebuildPolyhedron(false), fpPolyhedron(0),
105    fZBottomCut(rhs.fZBottomCut), fZTopCut(rhs. << 145     kRadTolerance(rhs.kRadTolerance),
106    halfTolerance(rhs.halfTolerance),           << 146     halfCarTolerance(rhs.halfCarTolerance),
107    fXmax(rhs.fXmax), fYmax(rhs.fYmax),         << 147     halfRadTolerance(rhs.halfRadTolerance),
108    fRsph(rhs.fRsph), fR(rhs.fR),               << 148     fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
109    fSx(rhs.fSx), fSy(rhs.fSy), fSz(rhs.fSz),   << 149     xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.ySemiAxis),
110    fZMidCut(rhs.fZMidCut), fZDimCut(rhs.fZDimC << 150     zSemiAxis(rhs.zSemiAxis), semiAxisMax(rhs.semiAxisMax),
111    fQ1(rhs.fQ1), fQ2(rhs.fQ2),                 << 151     zBottomCut(rhs.zBottomCut), zTopCut(rhs.zTopCut)
112    fCubicVolume(rhs.fCubicVolume),             << 
113    fSurfaceArea(rhs.fSurfaceArea),             << 
114    fLateralArea(rhs.fLateralArea)              << 
115 {                                                 152 {
116 }                                                 153 }
117                                                   154 
118 ////////////////////////////////////////////// << 155 ///////////////////////////////////////////////////////////////////////////////
119 //                                                156 //
120 // Assignment operator                            157 // Assignment operator
121                                                   158 
122 G4Ellipsoid& G4Ellipsoid::operator = (const G4 << 159 G4Ellipsoid& G4Ellipsoid::operator = (const G4Ellipsoid& rhs) 
123 {                                                 160 {
124    // Check assignment to self                    161    // Check assignment to self
125    //                                             162    //
126    if (this == &rhs)  { return *this; }           163    if (this == &rhs)  { return *this; }
127                                                   164 
128    // Copy base class data                        165    // Copy base class data
129    //                                             166    //
130    G4VSolid::operator=(rhs);                      167    G4VSolid::operator=(rhs);
131                                                   168 
132    // Copy data                                   169    // Copy data
133    //                                             170    //
134    fDx = rhs.fDx;                              << 171    kRadTolerance = rhs.kRadTolerance;
135    fDy = rhs.fDy;                              << 172    halfCarTolerance = rhs.halfCarTolerance;
136    fDz = rhs.fDz;                              << 173    halfRadTolerance = rhs.halfRadTolerance;
137    fZBottomCut = rhs.fZBottomCut;              << 174    fCubicVolume = rhs.fCubicVolume; fSurfaceArea = rhs.fSurfaceArea;
138    fZTopCut = rhs.fZTopCut;                    << 175    xSemiAxis = rhs.xSemiAxis; ySemiAxis = rhs.ySemiAxis;
139                                                << 176    zSemiAxis = rhs.zSemiAxis; semiAxisMax = rhs.semiAxisMax;
140    halfTolerance = rhs.halfTolerance;          << 177    zBottomCut = rhs.zBottomCut; zTopCut = rhs.zTopCut;
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;                    178    fRebuildPolyhedron = false;
158    delete fpPolyhedron; fpPolyhedron = nullptr << 179    delete fpPolyhedron; fpPolyhedron = 0;
159                                                   180 
160    return *this;                                  181    return *this;
161 }                                                 182 }
162                                                   183 
163 ////////////////////////////////////////////// << 184 ////////////////////////////////////////////////////////////////////////
164 //                                             << 
165 // Check parameters and make precalculation    << 
166                                                << 
167 void G4Ellipsoid::CheckParameters()            << 
168 {                                              << 
169   halfTolerance = 0.5 * kCarTolerance; // half << 
170   G4double dmin = 2. * kCarTolerance;          << 
171                                                << 
172   // Check dimensions                          << 
173   //                                           << 
174   if (fDx < dmin || fDy < dmin || fDz < dmin)  << 
175   {                                            << 
176     std::ostringstream message;                << 
177     message << "Invalid (too small or negative << 
178             << GetName()  << "\n"              << 
179             << "  semi-axis x: " << fDx << "\n << 
180             << "  semi-axis y: " << fDy << "\n << 
181             << "  semi-axis z: " << fDz;       << 
182     G4Exception("G4Ellipsoid::CheckParameters( << 
183                 FatalException, message);      << 
184   }                                            << 
185   G4double A = fDx;                            << 
186   G4double B = fDy;                            << 
187   G4double C = fDz;                            << 
188                                                << 
189   // Check cuts                                << 
190   //                                           << 
191   if (fZBottomCut == 0. && fZTopCut == 0.)     << 
192   {                                            << 
193     fZBottomCut = -C;                          << 
194     fZTopCut = C;                              << 
195   }                                            << 
196   if (fZBottomCut >= C || fZTopCut <= -C || fZ << 
197   {                                            << 
198     std::ostringstream message;                << 
199     message << "Invalid Z cuts for Solid: "    << 
200             << GetName() << "\n"               << 
201             << "  bottom cut: " << fZBottomCut << 
202             << "  top cut: " << fZTopCut;      << 
203     G4Exception("G4Ellipsoid::CheckParameters( << 
204                 FatalException, message);      << 
205                                                << 
206   }                                            << 
207   fZBottomCut = std::max(fZBottomCut, -C);     << 
208   fZTopCut = std::min(fZTopCut, C);            << 
209                                                << 
210   // Set extent in x and y                     << 
211   fXmax = A;                                   << 
212   fYmax = B;                                   << 
213   if (fZBottomCut > 0.)                        << 
214   {                                            << 
215     G4double ratio = fZBottomCut / C;          << 
216     G4double scale = std::sqrt((1. - ratio) *  << 
217     fXmax *= scale;                            << 
218     fYmax *= scale;                            << 
219   }                                            << 
220   if (fZTopCut < 0.)                           << 
221   {                                            << 
222     G4double ratio  = fZTopCut / C;            << 
223     G4double scale  = std::sqrt((1. - ratio) * << 
224     fXmax *= scale;                            << 
225     fYmax *= scale;                            << 
226   }                                            << 
227                                                << 
228   // Set scale factors                         << 
229   fRsph = std::max(std::max(A, B), C); // boun << 
230   fR    = std::min(std::min(A, B), C); // radi << 
231   fSx   = fR / A; // X scale factor            << 
232   fSy   = fR / B; // Y scale factor            << 
233   fSz   = fR / C; // Z scale factor            << 
234                                                << 
235   // Scaled cuts                               << 
236   fZMidCut = 0.5 * (fZTopCut + fZBottomCut) *  << 
237   fZDimCut = 0.5 * (fZTopCut - fZBottomCut) *  << 
238                                                << 
239   // Coefficients for approximation of distanc << 
240   fQ1 = 0.5 / fR;                              << 
241   fQ2 = 0.5 * fR + halfTolerance * halfToleran << 
242                                                << 
243   fCubicVolume = 0.; // volume                 << 
244   fSurfaceArea = 0.; // surface area           << 
245   fLateralArea = 0.; // lateral surface area   << 
246 }                                              << 
247                                                << 
248 ////////////////////////////////////////////// << 
249 //                                                185 //
250 // Dispatch to parameterisation for replicatio    186 // Dispatch to parameterisation for replication mechanism dimension
251 // computation & modification                  << 187 // computation & modification.
252                                                   188 
253 void G4Ellipsoid::ComputeDimensions(G4VPVParam    189 void G4Ellipsoid::ComputeDimensions(G4VPVParameterisation* p,
254                                     const G4in    190                                     const G4int n,
255                                     const G4VP    191                                     const G4VPhysicalVolume* pRep)
256 {                                                 192 {
257   p->ComputeDimensions(*this,n,pRep);             193   p->ComputeDimensions(*this,n,pRep);
258 }                                                 194 }
259                                                   195 
260 ////////////////////////////////////////////// << 196 ///////////////////////////////////////////////////////////////////////////////
261 //                                                197 //
262 // Get bounding box                               198 // Get bounding box
263                                                   199 
264 void G4Ellipsoid::BoundingLimits(G4ThreeVector << 200 void G4Ellipsoid::BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const
265                                  G4ThreeVector << 
266 {                                                 201 {
267   pMin.set(-fXmax,-fYmax, fZBottomCut);        << 202   G4double dx = GetSemiAxisMax(0);
268   pMax.set( fXmax, fYmax, fZTopCut);           << 203   G4double dy = GetSemiAxisMax(1);
                                                   >> 204   G4double dz = GetSemiAxisMax(2);
                                                   >> 205   G4double zmin = std::max(-dz,GetZBottomCut());
                                                   >> 206   G4double zmax = std::min( dz,GetZTopCut());
                                                   >> 207   pMin.set(-dx,-dy,zmin);
                                                   >> 208   pMax.set( dx, dy,zmax);
                                                   >> 209 
                                                   >> 210   // Check correctness of the bounding box
                                                   >> 211   //
                                                   >> 212   if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
                                                   >> 213   {
                                                   >> 214     std::ostringstream message;
                                                   >> 215     message << "Bad bounding box (min >= max) for solid: "
                                                   >> 216             << GetName() << " !"
                                                   >> 217             << "\npMin = " << pMin
                                                   >> 218             << "\npMax = " << pMax;
                                                   >> 219     G4Exception("G4Ellipsoid::BoundingLimits()", "GeomMgt0001",
                                                   >> 220                 JustWarning, message);
                                                   >> 221     DumpInfo();
                                                   >> 222   }
269 }                                                 223 }
270                                                   224 
271 ////////////////////////////////////////////// << 225 ///////////////////////////////////////////////////////////////////////////////
272 //                                                226 //
273 // Calculate extent under transform and specif << 227 // Calculate extent under transform and specified limit
274                                                   228 
275 G4bool                                            229 G4bool
276 G4Ellipsoid::CalculateExtent(const EAxis pAxis    230 G4Ellipsoid::CalculateExtent(const EAxis pAxis,
277                              const G4VoxelLimi    231                              const G4VoxelLimits& pVoxelLimit,
278                              const G4AffineTra    232                              const G4AffineTransform& pTransform,
279                                    G4double& p    233                                    G4double& pMin, G4double& pMax) const
280 {                                                 234 {
281   G4ThreeVector bmin, bmax;                       235   G4ThreeVector bmin, bmax;
282                                                   236 
283   // Get bounding box                             237   // Get bounding box
284   BoundingLimits(bmin,bmax);                      238   BoundingLimits(bmin,bmax);
285                                                   239 
286   // Find extent                                  240   // Find extent
287   G4BoundingEnvelope bbox(bmin,bmax);             241   G4BoundingEnvelope bbox(bmin,bmax);
288   return bbox.CalculateExtent(pAxis,pVoxelLimi    242   return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
289 }                                                 243 }
290                                                   244 
291 ////////////////////////////////////////////// << 245 ///////////////////////////////////////////////////////////////////////////////
292 //                                                246 //
293 // Return position of point: inside/outside/on << 247 // Return whether point inside/outside/on surface
                                                   >> 248 // Split into radius, phi, theta checks
                                                   >> 249 // Each check modifies `in', or returns as approprate
294                                                   250 
295 EInside G4Ellipsoid::Inside(const G4ThreeVecto    251 EInside G4Ellipsoid::Inside(const G4ThreeVector& p) const
296 {                                                 252 {
297   G4double x     = p.x() * fSx;                << 253   G4double rad2oo,  // outside surface outer tolerance
298   G4double y     = p.y() * fSy;                << 254            rad2oi;  // outside surface inner tolerance
299   G4double z     = p.z() * fSz;                << 255   EInside in;
300   G4double rr    = x * x + y * y + z * z;      << 
301   G4double distZ = std::abs(z - fZMidCut) - fZ << 
302   G4double distR = fQ1 * rr - fQ2;             << 
303   G4double dist  = std::max(distZ, distR);     << 
304                                                   256 
305   if (dist > halfTolerance) return kOutside;   << 257   // check this side of z cut first, because that's fast
306   return (dist > -halfTolerance) ? kSurface :  << 258   //
307 }                                              << 259   if (p.z() < zBottomCut-halfRadTolerance) { return in=kOutside; }
                                                   >> 260   if (p.z() > zTopCut+halfRadTolerance)    { return in=kOutside; }
308                                                   261 
309 ////////////////////////////////////////////// << 262   rad2oo= sqr(p.x()/(xSemiAxis+halfRadTolerance))
310 //                                             << 263         + sqr(p.y()/(ySemiAxis+halfRadTolerance))
311 // Return unit normal to surface at p          << 264         + sqr(p.z()/(zSemiAxis+halfRadTolerance));
312                                                   265 
313 G4ThreeVector G4Ellipsoid::SurfaceNormal( cons << 266   if (rad2oo > 1.0)  { return in=kOutside; }
314 {                                              << 267     
315   G4ThreeVector norm(0., 0., 0.);              << 268   rad2oi= sqr(p.x()*(1.0+halfRadTolerance/xSemiAxis)/xSemiAxis)
316   G4int nsurf = 0;                             << 269       + sqr(p.y()*(1.0+halfRadTolerance/ySemiAxis)/ySemiAxis)
                                                   >> 270       + sqr(p.z()*(1.0+halfRadTolerance/zSemiAxis)/zSemiAxis);
317                                                   271 
318   // Check cuts                                << 272   // Check radial surfaces
319   G4double x = p.x() * fSx;                    << 273   //  sets `in' (already checked for rad2oo > 1.0)
320   G4double y = p.y() * fSy;                    << 274   //
321   G4double z = p.z() * fSz;                    << 275   if (rad2oi < 1.0)
322   G4double distZ = std::abs(z - fZMidCut) - fZ << 
323   if (std::abs(distZ) <= halfTolerance)        << 
324   {                                               276   {
325     norm.setZ(std::copysign(1., z - fZMidCut)) << 277     in = ( (p.z() < zBottomCut+halfRadTolerance)
326     ++nsurf;                                   << 278         || (p.z() > zTopCut-halfRadTolerance) ) ? kSurface : kInside;
                                                   >> 279     if ( rad2oi > 1.0-halfRadTolerance )  { in=kSurface; }
327   }                                               280   }
328                                                << 281   else 
329   // Check lateral surface                     << 
330   G4double distR = fQ1*(x*x + y*y + z*z) - fQ2 << 
331   if (std::abs(distR) <= halfTolerance)        << 
332   {                                               282   {
333     // normal = (p.x/a^2, p.y/b^2, p.z/c^2)    << 283     in = kSurface;
334     norm += G4ThreeVector(x*fSx, y*fSy, z*fSz) << 
335     ++nsurf;                                   << 
336   }                                               284   }
                                                   >> 285   return in;
337                                                   286 
338   // Return normal                             << 
339   if (nsurf == 1) return norm;                 << 
340   else if (nsurf > 1) return norm.unit(); // e << 
341   else                                         << 
342   {                                            << 
343 #ifdef G4SPECSDEBUG                            << 
344     std::ostringstream message;                << 
345     G4long oldprc = message.precision(16);     << 
346     message << "Point p is not on surface (!?) << 
347             << GetName() << "\n";              << 
348     message << "Position:\n";                  << 
349     message << "   p.x() = " << p.x()/mm << "  << 
350     message << "   p.y() = " << p.y()/mm << "  << 
351     message << "   p.z() = " << p.z()/mm << "  << 
352     G4cout.precision(oldprc);                  << 
353     G4Exception("G4Ellipsoid::SurfaceNormal(p) << 
354                 JustWarning, message );        << 
355     DumpInfo();                                << 
356 #endif                                         << 
357     return ApproxSurfaceNormal(p);             << 
358   }                                            << 
359 }                                                 287 }
360                                                   288 
361 ////////////////////////////////////////////// << 289 ///////////////////////////////////////////////////////////////////////////////
362 //                                                290 //
363 // Find surface nearest to point and return co << 291 // Return unit normal of surface closest to p not protected against p=0
364 // This method normally should not be called.  << 
365                                                   292 
366 G4ThreeVector G4Ellipsoid::ApproxSurfaceNormal << 293 G4ThreeVector G4Ellipsoid::SurfaceNormal( const G4ThreeVector& p) const
367 {                                                 294 {
368   G4double x  = p.x() * fSx;                   << 295   G4double distR, distZBottom, distZTop;
369   G4double y  = p.y() * fSy;                   << 296 
370   G4double z  = p.z() * fSz;                   << 297   // normal vector with special magnitude:  parallel to normal, units 1/length
371   G4double rr = x * x + y * y + z * z;         << 298   // norm*p == 1.0 if on surface, >1.0 if outside, <1.0 if inside
372   G4double distZ = std::abs(z - fZMidCut) - fZ << 299   //
373   G4double distR = std::sqrt(rr) - fR;         << 300   G4ThreeVector norm(p.x()/(xSemiAxis*xSemiAxis),
374   if  (distR > distZ && rr > 0.) // distR > di << 301                      p.y()/(ySemiAxis*ySemiAxis),
375     return G4ThreeVector(x*fSx, y*fSy, z*fSz). << 302                      p.z()/(zSemiAxis*zSemiAxis));
376   else                                         << 303   G4double radius = 1.0/norm.mag();
377     return { 0., 0., std::copysign(1., z - fZM << 304 
                                                   >> 305   // approximate distance to curved surface
                                                   >> 306   //
                                                   >> 307   distR = std::fabs( (p*norm - 1.0) * radius ) / 2.0;
                                                   >> 308 
                                                   >> 309   // Distance to z-cut plane
                                                   >> 310   //
                                                   >> 311   distZBottom = std::fabs( p.z() - zBottomCut );
                                                   >> 312   distZTop = std::fabs( p.z() - zTopCut );
                                                   >> 313 
                                                   >> 314   if ( (distZBottom < distR) || (distZTop < distR) )
                                                   >> 315   {
                                                   >> 316     return G4ThreeVector(0.,0.,(distZBottom < distZTop) ? -1.0 : 1.0);
                                                   >> 317   }
                                                   >> 318   return ( norm *= radius );
378 }                                                 319 }
379                                                   320 
380 ////////////////////////////////////////////// << 321 ///////////////////////////////////////////////////////////////////////////////
                                                   >> 322 //
                                                   >> 323 // Calculate distance to shape from outside, along normalised vector
                                                   >> 324 // - return kInfinity if no intersection, or intersection distance <= tolerance
381 //                                                325 //
382 // Calculate distance to shape from outside al << 
383                                                   326 
384 G4double G4Ellipsoid::DistanceToIn(const G4Thr << 327 G4double G4Ellipsoid::DistanceToIn( const G4ThreeVector& p,
385                                    const G4Thr << 328                                     const G4ThreeVector& v  ) const
386 {                                                 329 {
387   G4double offset = 0.;                        << 330   G4double distMin = std::min(xSemiAxis,ySemiAxis);
388   G4ThreeVector pcur = p;                      << 331   const G4double dRmax = 100.*std::min(distMin,zSemiAxis);
                                                   >> 332   distMin= kInfinity;
389                                                   333 
390   // Check if point is flying away, relative t << 334   // check to see if Z plane is relevant
391   //                                           << 335   if (p.z() <= zBottomCut+halfCarTolerance)
392   G4double safex = std::abs(p.x()) - fXmax;    << 336   {
393   G4double safey = std::abs(p.y()) - fYmax;    << 337     if (v.z() <= 0.0) { return distMin; }
394   G4double safet = p.z() - fZTopCut;           << 338     G4double distZ = (zBottomCut - p.z()) / v.z();
395   G4double safeb = fZBottomCut - p.z();        << 
396                                                << 
397   if (safex >= -halfTolerance && p.x() * v.x() << 
398   if (safey >= -halfTolerance && p.y() * v.y() << 
399   if (safet >= -halfTolerance && v.z() >= 0.)  << 
400   if (safeb >= -halfTolerance && v.z() <= 0.)  << 
401                                                   339 
402   // Relocate point, if required               << 340     if ( (distZ > -halfRadTolerance) && (Inside(p+distZ*v) != kOutside) )
403   //                                           << 341     {
404   G4double safe = std::max(std::max(std::max(s << 342       // early exit since can't intercept curved surface if we reach here
405   if (safe > 32. * fRsph)                      << 343       if ( std::fabs(distZ) < halfRadTolerance ) { distZ=0.; }
                                                   >> 344       return distMin= distZ;
                                                   >> 345     }
                                                   >> 346   }
                                                   >> 347   if (p.z() >= zTopCut-halfCarTolerance)
406   {                                               348   {
407     offset = (1. - 1.e-08) * safe - 2. * fRsph << 349     if (v.z() >= 0.0) { return distMin;}
408     pcur += offset * v;                        << 350     G4double distZ = (zTopCut - p.z()) / v.z();
409     G4double dist = DistanceToIn(pcur, v);     << 351     if ( (distZ > -halfRadTolerance) && (Inside(p+distZ*v) != kOutside) )
410     return (dist == kInfinity) ? kInfinity : d << 352     {
                                                   >> 353       // early exit since can't intercept curved surface if we reach here
                                                   >> 354       if ( std::fabs(distZ) < halfRadTolerance ) { distZ=0.; }
                                                   >> 355       return distMin= distZ;
                                                   >> 356     }
411   }                                               357   }
                                                   >> 358   // if fZCut1 <= p.z() <= fZCut2, then must hit curved surface
412                                                   359 
413   // Scale ellipsoid to sphere                 << 360   // now check curved surface intercept
414   //                                           << 361   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                                                   362 
422   // Check if point is leaving the solid       << 363   A= sqr(v.x()/xSemiAxis) + sqr(v.y()/ySemiAxis) + sqr(v.z()/zSemiAxis);
423   //                                           << 364   C= sqr(p.x()/xSemiAxis) + sqr(p.y()/ySemiAxis) + sqr(p.z()/zSemiAxis) - 1.0;
424   G4double dzcut = fZDimCut;                   << 365   B= 2.0 * ( p.x()*v.x()/(xSemiAxis*xSemiAxis)
425   G4double pzcut = pz - fZMidCut;              << 366            + p.y()*v.y()/(ySemiAxis*ySemiAxis)
426   G4double distZ = std::abs(pzcut) - dzcut;    << 367            + p.z()*v.z()/(zSemiAxis*zSemiAxis) );
427   if (distZ >= -halfTolerance && pzcut * vz >= << 
428                                                   368 
429   G4double rr = px * px + py * py + pz * pz;   << 369   C= B*B - 4.0*A*C;
430   G4double pv = px * vx + py * vy + pz * vz;   << 370   if (C > 0.0)
431   G4double distR = fQ1 * rr - fQ2;             << 371   {    
432   if (distR >= -halfTolerance && pv >= 0.) ret << 372     G4double distR= (-B - std::sqrt(C)) / (2.0*A);
                                                   >> 373     G4double intZ = p.z()+distR*v.z();
                                                   >> 374     if ( (distR > halfRadTolerance)
                                                   >> 375       && (intZ >= zBottomCut-halfRadTolerance)
                                                   >> 376       && (intZ <= zTopCut+halfRadTolerance) )
                                                   >> 377     { 
                                                   >> 378       distMin = distR;
                                                   >> 379     }
                                                   >> 380     else if( (distR >- halfRadTolerance)
                                                   >> 381             && (intZ >= zBottomCut-halfRadTolerance)
                                                   >> 382             && (intZ <= zTopCut+halfRadTolerance) )
                                                   >> 383     {
                                                   >> 384       // p is on the curved surface, DistanceToIn returns 0 or kInfinity:
                                                   >> 385       // DistanceToIn returns 0, if second root is positive (means going inside)
                                                   >> 386       // If second root is negative, DistanceToIn returns kInfinity (outside)
                                                   >> 387       //
                                                   >> 388       distR = (-B + std::sqrt(C) ) / (2.0*A);
                                                   >> 389       if(distR>0.) { distMin=0.; }
                                                   >> 390     }
                                                   >> 391     else
                                                   >> 392     {
                                                   >> 393       distR= (-B + std::sqrt(C)) / (2.0*A);
                                                   >> 394       intZ = p.z()+distR*v.z();
                                                   >> 395       if ( (distR > halfRadTolerance)
                                                   >> 396         && (intZ >= zBottomCut-halfRadTolerance)
                                                   >> 397         && (intZ <= zTopCut+halfRadTolerance) )
                                                   >> 398       {
                                                   >> 399         G4ThreeVector norm=SurfaceNormal(p);
                                                   >> 400         if (norm.dot(v)<0.) { distMin = distR; }
                                                   >> 401       }
                                                   >> 402     }
                                                   >> 403     if ( (distMin!=kInfinity) && (distMin>dRmax) ) 
                                                   >> 404     {                    // Avoid rounding errors due to precision issues on
                                                   >> 405                          // 64 bits systems. Split long distances and recompute
                                                   >> 406       G4double fTerm = distMin-std::fmod(distMin,dRmax);
                                                   >> 407       distMin = fTerm + DistanceToIn(p+fTerm*v,v);
                                                   >> 408     }
                                                   >> 409   }
                                                   >> 410   
                                                   >> 411   if (std::fabs(distMin)<halfRadTolerance) { distMin=0.; }
                                                   >> 412   return distMin;
                                                   >> 413 } 
433                                                   414 
434   G4double A = vx * vx + vy * vy + vz * vz;    << 415 ///////////////////////////////////////////////////////////////////////////////
435   G4double B = pv;                             << 416 //
436   G4double C = rr - fR * fR;                   << 417 // Calculate distance (<= actual) to closest surface of shape from outside
437   G4double D = B * B - A * C;                  << 418 // - Return 0 if point inside
438   // scratch^2 = R^2 - (R - halfTolerance)^2 = << 
439   G4double EPS = A * A * fR * kCarTolerance; / << 
440   if (D <= EPS) return kInfinity; // no inters << 
441                                                   419 
442   // Find intersection with Z planes           << 420 G4double G4Ellipsoid::DistanceToIn(const G4ThreeVector& p) const
443   //                                           << 421 {
444   G4double invz  = (vz == 0) ? DBL_MAX : -1./v << 422   G4double distR, distZ;
445   G4double dz    = std::copysign(dzcut, invz); << 
446   G4double tzmin = (pzcut - dz) * invz;        << 
447   G4double tzmax = (pzcut + dz) * invz;        << 
448                                                   423 
449   // Find intersection with lateral surface    << 424   // normal vector:  parallel to normal, magnitude 1/(characteristic radius)
450   //                                              425   //
451   G4double tmp = -B - std::copysign(std::sqrt( << 426   G4ThreeVector norm(p.x()/(xSemiAxis*xSemiAxis),
452   G4double t1 = tmp / A;                       << 427                      p.y()/(ySemiAxis*ySemiAxis),
453   G4double t2 = C / tmp;                       << 428                      p.z()/(zSemiAxis*zSemiAxis));
454   G4double trmin = std::min(t1, t2);           << 429   G4double radius= 1.0/norm.mag();
455   G4double trmax = std::max(t1, t2);           << 
456                                                   430 
457   // Return distance                           << 431   // approximate distance to curved surface ( <= actual distance )
458   //                                              432   //
459   G4double tmin = std::max(tzmin, trmin);      << 433   distR= (p*norm - 1.0) * radius / 2.0;
460   G4double tmax = std::min(tzmax, trmax);      << 
461                                                << 
462   if (tmax - tmin <= halfTolerance) return kIn << 
463   return (tmin < halfTolerance) ? offset : tmi << 
464 }                                              << 
465                                                   434 
466 ////////////////////////////////////////////// << 435   // Distance to z-cut plane
467 //                                             << 436   //
468 // Estimate distance to surface from outside   << 437   distZ= zBottomCut - p.z();
                                                   >> 438   if (distZ < 0.0)
                                                   >> 439   {
                                                   >> 440     distZ = p.z() - zTopCut;
                                                   >> 441   }
469                                                   442 
470 G4double G4Ellipsoid::DistanceToIn(const G4Thr << 443   // Distance to closest surface from outside
471 {                                              << 444   //
472   G4double px = p.x();                         << 445   if (distZ < 0.0)
473   G4double py = p.y();                         << 446   {
474   G4double pz = p.z();                         << 447     return (distR < 0.0) ? 0.0 : distR;
475                                                << 448   }
476   // Safety distance to bounding box           << 449   else if (distR < 0.0)
477   G4double distX = std::abs(px) - fXmax;       << 450   {
478   G4double distY = std::abs(py) - fYmax;       << 451     return distZ;
479   G4double distZ = std::max(pz - fZTopCut, fZB << 452   }
480   G4double distB = std::max(std::max(distX, di << 453   else
481                                                << 454   {
482   // Safety distance to lateral surface        << 455     return (distZ < distR) ? distZ : distR;
483   G4double x = px * fSx;                       << 456   }
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 }                                                 457 }
492                                                   458 
493 ////////////////////////////////////////////// << 459 ///////////////////////////////////////////////////////////////////////////////
494 //                                                460 //
495 // Calculate distance to surface from inside a << 461 // Calculate distance to surface of shape from `inside', allowing for tolerance
496                                                   462 
497 G4double G4Ellipsoid::DistanceToOut(const G4Th    463 G4double G4Ellipsoid::DistanceToOut(const G4ThreeVector& p,
498                                     const G4Th    464                                     const G4ThreeVector& v,
499                                     const G4bo    465                                     const G4bool calcNorm,
500                                           G4bo << 466                                           G4bool *validNorm,
501                                           G4Th << 467                                           G4ThreeVector *n  ) const
502 {                                                 468 {
503   // Check if point flying away relative to Z  << 469   G4double distMin;
504   //                                           << 470   enum surface_e {kPlaneSurf, kCurvedSurf, kNoSurf} surface;
505   G4double pz = p.z() * fSz;                   << 471   
506   G4double vz = v.z() * fSz;                   << 472   distMin= kInfinity;
507   G4double dzcut = fZDimCut;                   << 473   surface= kNoSurf;
508   G4double pzcut = pz - fZMidCut;              << 
509   G4double distZ = std::abs(pzcut) - dzcut;    << 
510   if (distZ >= -halfTolerance && pzcut * vz >  << 
511   {                                            << 
512     if (calcNorm)                              << 
513     {                                          << 
514       *validNorm = true;                       << 
515       n->set(0., 0., std::copysign(1., pzcut)) << 
516     }                                          << 
517     return 0.;                                 << 
518   }                                            << 
519                                                   474 
520   // Check if point is flying away relative to << 475   // check to see if Z plane is relevant
521   //                                              476   //
522   G4double px = p.x() * fSx;                   << 477   if (v.z() < 0.0)
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   {                                               478   {
531     if (calcNorm)                              << 479     G4double distZ = (zBottomCut - p.z()) / v.z();
                                                   >> 480     if (distZ < 0.0)
532     {                                             481     {
533       *validNorm = true;                       << 482       distZ= 0.0;
534       *n = G4ThreeVector(px*fSx, py*fSy, pz*fS << 483       if (!calcNorm) {return 0.0;}
535     }                                             484     }
536     return 0.;                                 << 485     distMin= distZ;
                                                   >> 486     surface= kPlaneSurf;
537   }                                               487   }
538                                                << 488   if (v.z() > 0.0)
539   // Just in case check if point is outside (n << 
540   //                                           << 
541   if (std::max(distZ, distR) > halfTolerance)  << 
542   {                                               489   {
543 #ifdef G4SPECSDEBUG                            << 490     G4double distZ = (zTopCut - p.z()) / v.z();
544     std::ostringstream message;                << 491     if (distZ < 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     {                                             492     {
557       *validNorm = true;                       << 493       distZ= 0.0;
558       *n = ApproxSurfaceNormal(p);             << 494       if (!calcNorm) {return 0.0;}
559     }                                             495     }
560     return 0.;                                 << 496     distMin= distZ;
                                                   >> 497     surface= kPlaneSurf;
561   }                                               498   }
562                                                   499 
563   // Set coefficients of quadratic equation: A << 500   // normal vector:  parallel to normal, magnitude 1/(characteristic radius)
                                                   >> 501   //
                                                   >> 502   G4ThreeVector nearnorm(p.x()/(xSemiAxis*xSemiAxis),
                                                   >> 503                          p.y()/(ySemiAxis*ySemiAxis),
                                                   >> 504                          p.z()/(zSemiAxis*zSemiAxis));
                                                   >> 505   
                                                   >> 506   // now check curved surface intercept
564   //                                              507   //
565   G4double A  = vx * vx + vy * vy + vz * vz;   << 508   G4double A,B,C;
566   G4double B  = pv;                            << 509   
567   G4double C  = rr - fR * fR;                  << 510   A= sqr(v.x()/xSemiAxis) + sqr(v.y()/ySemiAxis) + sqr(v.z()/zSemiAxis);
568   G4double D  = B * B - A * C;                 << 511   C= (p * nearnorm) - 1.0;
569   // It is expected that the point is located  << 512   B= 2.0 * (v * nearnorm);
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                                                   513 
575   if (D <= EPS) // no intersection             << 514   C= B*B - 4.0*A*C;
                                                   >> 515   if (C > 0.0)
576   {                                               516   {
577     if (calcNorm)                              << 517     G4double distR= (-B + std::sqrt(C) ) / (2.0*A);
                                                   >> 518     if (distR < 0.0)
578     {                                             519     {
579       *validNorm = true;                       << 520       distR= 0.0;
580       *n = G4ThreeVector(px*fSx, py*fSy, pz*fS << 521       if (!calcNorm) {return 0.0;}
                                                   >> 522     }
                                                   >> 523     if (distR < distMin)
                                                   >> 524     {
                                                   >> 525       distMin= distR;
                                                   >> 526       surface= kCurvedSurf;
581     }                                             527     }
582     return 0.;                                 << 
583   }                                               528   }
584                                                   529 
585   // Find intersection with Z cuts             << 530   // set normal if requested
586   //                                           << 
587   G4double tzmax = (vz == 0.) ? DBL_MAX : (std << 
588                                                << 
589   // Find intersection with lateral surface    << 
590   //                                              531   //
591   G4double tmp = -B - std::copysign(std::sqrt( << 
592   G4double trmax = (tmp < 0.) ? C/tmp : tmp/A; << 
593                                                << 
594   // Find distance and set normal, if required << 
595   //                                           << 
596   G4double tmax = std::min(tzmax, trmax);      << 
597   //if (tmax < halfTolerance) tmax = 0.;       << 
598                                                << 
599   if (calcNorm)                                   532   if (calcNorm)
600   {                                               533   {
601     *validNorm = true;                         << 534     if (surface == kNoSurf)
602     if (tmax == tzmax)                         << 
603     {                                             535     {
604       G4double pznew = pz + tmax * vz;         << 536       *validNorm = false;
605       n->set(0., 0., (pznew > fZMidCut) ? 1. : << 
606     }                                             537     }
607     else                                          538     else
608     {                                             539     {
609       G4double nx = (px + tmax * vx) * fSx;    << 540       *validNorm = true;
610       G4double ny = (py + tmax * vy) * fSy;    << 541       switch (surface)
611       G4double nz = (pz + tmax * vz) * fSz;    << 542       {
612       *n = G4ThreeVector(nx, ny, nz).unit();   << 543         case kPlaneSurf:
                                                   >> 544           *n= G4ThreeVector(0.,0.,(v.z() > 0.0 ? 1. : -1.));
                                                   >> 545           break;
                                                   >> 546         case kCurvedSurf:
                                                   >> 547         {
                                                   >> 548           G4ThreeVector pexit= p + distMin*v;
                                                   >> 549           G4ThreeVector truenorm(pexit.x()/(xSemiAxis*xSemiAxis),
                                                   >> 550                                  pexit.y()/(ySemiAxis*ySemiAxis),
                                                   >> 551                                  pexit.z()/(zSemiAxis*zSemiAxis));
                                                   >> 552           truenorm *= 1.0/truenorm.mag();
                                                   >> 553           *n= truenorm;
                                                   >> 554         } break;
                                                   >> 555         default:           // Should never reach this case ...
                                                   >> 556           DumpInfo();
                                                   >> 557           std::ostringstream message;
                                                   >> 558           G4int oldprc = message.precision(16);
                                                   >> 559           message << "Undefined side for valid surface normal to solid."
                                                   >> 560                   << G4endl
                                                   >> 561                   << "Position:"  << G4endl
                                                   >> 562                   << "   p.x() = "   << p.x()/mm << " mm" << G4endl
                                                   >> 563                   << "   p.y() = "   << p.y()/mm << " mm" << G4endl
                                                   >> 564                   << "   p.z() = "   << p.z()/mm << " mm" << G4endl
                                                   >> 565                   << "Direction:" << G4endl << G4endl
                                                   >> 566                   << "   v.x() = "   << v.x() << G4endl
                                                   >> 567                   << "   v.y() = "   << v.y() << G4endl
                                                   >> 568                   << "   v.z() = "   << v.z() << G4endl
                                                   >> 569                   << "Proposed distance :" << G4endl
                                                   >> 570                   << "   distMin = "    << distMin/mm << " mm";
                                                   >> 571           message.precision(oldprc);
                                                   >> 572           G4Exception("G4Ellipsoid::DistanceToOut(p,v,..)",
                                                   >> 573                       "GeomSolids1002", JustWarning, message);
                                                   >> 574           break;
                                                   >> 575       }
613     }                                             576     }
614   }                                               577   }
615   return tmax;                                 << 578    
                                                   >> 579   return distMin;
616 }                                                 580 }
617                                                   581 
618 ////////////////////////////////////////////// << 582 ///////////////////////////////////////////////////////////////////////////////
619 //                                                583 //
620 // Estimate distance to surface from inside    << 584 // Calculate distance (<=actual) to closest surface of shape from inside
621                                                   585 
622 G4double G4Ellipsoid::DistanceToOut(const G4Th    586 G4double G4Ellipsoid::DistanceToOut(const G4ThreeVector& p) const
623 {                                                 587 {
624   // Safety distance in z direction            << 588   G4double distR, distZ;
625   G4double distZ = std::min(fZTopCut - p.z(),  << 
626                                                   589 
627   // Safety distance to lateral surface        << 590 #ifdef G4SPECSDEBUG
628   G4double x = p.x() * fSx;                    << 591   if( Inside(p) == kOutside )
629   G4double y = p.y() * fSy;                    << 592   {
630   G4double z = p.z() * fSz;                    << 593      DumpInfo();
631   G4double distR = fR - std::sqrt(x*x + y*y +  << 594      std::ostringstream message;
632                                                << 595      G4int oldprc = message.precision(16);
633   // Return safety to out                      << 596      message << "Point p is outside !?" << G4endl
634   G4double dist = std::min(distZ, distR);      << 597              << "Position:"  << G4endl
635   return (dist < 0.) ? 0. : dist;              << 598              << "   p.x() = "   << p.x()/mm << " mm" << G4endl
                                                   >> 599              << "   p.y() = "   << p.y()/mm << " mm" << G4endl
                                                   >> 600              << "   p.z() = "   << p.z()/mm << " mm";
                                                   >> 601      message.precision(oldprc) ;
                                                   >> 602      G4Exception("G4Ellipsoid::DistanceToOut(p)", "GeomSolids1002",
                                                   >> 603                  JustWarning, message);
                                                   >> 604   }
                                                   >> 605 #endif
                                                   >> 606 
                                                   >> 607   // Normal vector:  parallel to normal, magnitude 1/(characteristic radius)
                                                   >> 608   //
                                                   >> 609   G4ThreeVector norm(p.x()/(xSemiAxis*xSemiAxis),
                                                   >> 610                      p.y()/(ySemiAxis*ySemiAxis),
                                                   >> 611                      p.z()/(zSemiAxis*zSemiAxis));
                                                   >> 612 
                                                   >> 613   // the following is a safe inlined "radius= min(1.0/norm.mag(),p.mag())
                                                   >> 614   //
                                                   >> 615   G4double radius= p.mag();
                                                   >> 616   G4double tmp= norm.mag();
                                                   >> 617   if ( (tmp > 0.0) && (1.0 < radius*tmp) ) {radius = 1.0/tmp;}
                                                   >> 618 
                                                   >> 619   // Approximate distance to curved surface ( <= actual distance )
                                                   >> 620   //
                                                   >> 621   distR = (1.0 - p*norm) * radius / 2.0;
                                                   >> 622     
                                                   >> 623   // Distance to z-cut plane
                                                   >> 624   //
                                                   >> 625   distZ = p.z() - zBottomCut;
                                                   >> 626   if (distZ < 0.0) {distZ= zTopCut - p.z();}
                                                   >> 627 
                                                   >> 628   // Distance to closest surface from inside
                                                   >> 629   //
                                                   >> 630   if ( (distZ < 0.0) || (distR < 0.0) )
                                                   >> 631   {
                                                   >> 632     return 0.0;
                                                   >> 633   }
                                                   >> 634   else
                                                   >> 635   {
                                                   >> 636     return (distZ < distR) ? distZ : distR;
                                                   >> 637   }
636 }                                                 638 }
637                                                   639 
638 //////////////////////////////////////////////    640 //////////////////////////////////////////////////////////////////////////
639 //                                                641 //
640 // Return entity type                          << 642 // G4EntityType
641                                                   643 
642 G4GeometryType G4Ellipsoid::GetEntityType() co    644 G4GeometryType G4Ellipsoid::GetEntityType() const
643 {                                                 645 {
644   return {"G4Ellipsoid"};                      << 646   return G4String("G4Ellipsoid");
645 }                                                 647 }
646                                                   648 
647 //////////////////////////////////////////////    649 //////////////////////////////////////////////////////////////////////////
648 //                                                650 //
649 // Make a clone of the object                     651 // Make a clone of the object
650                                                   652 
651 G4VSolid* G4Ellipsoid::Clone() const              653 G4VSolid* G4Ellipsoid::Clone() const
652 {                                                 654 {
653   return new G4Ellipsoid(*this);                  655   return new G4Ellipsoid(*this);
654 }                                                 656 }
655                                                   657 
656 //////////////////////////////////////////////    658 //////////////////////////////////////////////////////////////////////////
657 //                                                659 //
658 // Stream object contents to output stream     << 660 // Stream object contents to an output stream
659                                                   661 
660 std::ostream& G4Ellipsoid::StreamInfo( std::os    662 std::ostream& G4Ellipsoid::StreamInfo( std::ostream& os ) const
661 {                                                 663 {
662   G4long oldprc = os.precision(16);            << 664   G4int oldprc = os.precision(16);
663   os << "-------------------------------------    665   os << "-----------------------------------------------------------\n"
664      << "    *** Dump for solid - " << GetName    666      << "    *** Dump for solid - " << GetName() << " ***\n"
665      << "    =================================    667      << "    ===================================================\n"
666      << " Solid type: " << GetEntityType() <<  << 668      << " Solid type: G4Ellipsoid\n"
667      << " Parameters: \n"                         669      << " Parameters: \n"
668      << "    semi-axis x: " << GetDx()/mm << " << 670 
669      << "    semi-axis y: " << GetDy()/mm << " << 671      << "    semi-axis x: " << xSemiAxis/mm << " mm \n"
670      << "    semi-axis z: " << GetDz()/mm << " << 672      << "    semi-axis y: " << ySemiAxis/mm << " mm \n"
671      << "    lower cut in z: " << GetZBottomCu << 673      << "    semi-axis z: " << zSemiAxis/mm << " mm \n"
672      << "    upper cut in z: " << GetZTopCut() << 674      << "    max semi-axis: " << semiAxisMax/mm << " mm \n"
                                                   >> 675      << "    lower cut plane level z: " << zBottomCut/mm << " mm \n"
                                                   >> 676      << "    upper cut plane level z: " << zTopCut/mm << " mm \n"
673      << "-------------------------------------    677      << "-----------------------------------------------------------\n";
674   os.precision(oldprc);                           678   os.precision(oldprc);
675   return os;                                   << 
676 }                                              << 
677                                                << 
678 ////////////////////////////////////////////// << 
679 //                                             << 
680 // Return volume                               << 
681                                                   679 
682 G4double G4Ellipsoid::GetCubicVolume()         << 680   return os;
683 {                                              << 
684   if (fCubicVolume == 0.)                      << 
685   {                                            << 
686     G4double piAB_3 = CLHEP::pi * fDx * fDy /  << 
687     fCubicVolume = 4. * piAB_3 * fDz;          << 
688     if (fZBottomCut > -fDz)                    << 
689     {                                          << 
690       G4double hbot = 1. + fZBottomCut / fDz;  << 
691       fCubicVolume -= piAB_3 * hbot * hbot * ( << 
692     }                                          << 
693     if (fZTopCut < fDz)                        << 
694     {                                          << 
695       G4double htop = 1. - fZTopCut / fDz;     << 
696       fCubicVolume -= piAB_3 * htop * htop * ( << 
697     }                                          << 
698   }                                            << 
699   return fCubicVolume;                         << 
700 }                                                 681 }
701                                                   682 
702 ////////////////////////////////////////////// << 683 ////////////////////////////////////////////////////////////////////
703 //                                                684 //
704 // Calculate area of lateral surface           << 685 // GetPointOnSurface
705                                                   686 
706 G4double G4Ellipsoid::LateralSurfaceArea() con << 687 G4ThreeVector G4Ellipsoid::GetPointOnSurface() const
707 {                                                 688 {
708   constexpr G4int NPHI = 1000.;                << 689   G4double aTop, aBottom, aCurved, chose, xRand, yRand, zRand, phi;
709   constexpr G4double dPhi = CLHEP::halfpi/NPHI << 690   G4double cosphi, sinphi, costheta, sintheta, alpha, beta, max1, max2, max3;
710   constexpr G4double eps = 4.*DBL_EPSILON;     << 
711                                                << 
712   G4double aa = fDx*fDx;                       << 
713   G4double bb = fDy*fDy;                       << 
714   G4double cc = fDz*fDz;                       << 
715   G4double ab = fDx*fDy;                       << 
716   G4double cc_aa = cc/aa;                      << 
717   G4double cc_bb = cc/bb;                      << 
718   G4double zmax = std::min(fZTopCut, fDz);     << 
719   G4double zmin = std::max(fZBottomCut,-fDz);  << 
720   G4double zmax_c = zmax/fDz;                  << 
721   G4double zmin_c = zmin/fDz;                  << 
722   G4double area = 0.;                          << 
723                                                << 
724   if (aa == bb) // spheroid, use analytical ex << 
725   {                                            << 
726     G4double k = fDz/fDx;                      << 
727     G4double kk = k*k;                         << 
728     if (kk < 1. - eps)                         << 
729     {                                          << 
730       G4double invk = fDx/fDz;                 << 
731       G4double root = std::sqrt(1. - kk);      << 
732       G4double tmax = zmax_c*root;             << 
733       G4double tmin = zmin_c*root;             << 
734       area = CLHEP::pi*ab*                     << 
735         ((zmax_c*std::sqrt(kk + tmax*tmax) - z << 
736          (std::asinh(tmax*invk) - std::asinh(t << 
737     }                                          << 
738     else if (kk > 1. + eps)                    << 
739     {                                          << 
740       G4double invk = fDx/fDz;                 << 
741       G4double root = std::sqrt(kk - 1.);      << 
742       G4double tmax = zmax_c*root;             << 
743       G4double tmin = zmin_c*root;             << 
744       area = CLHEP::pi*ab*                     << 
745         ((zmax_c*std::sqrt(kk - tmax*tmax) - z << 
746          (std::asin(tmax*invk) - std::asin(tmi << 
747     }                                          << 
748     else                                       << 
749     {                                          << 
750       area = CLHEP::twopi*fDx*(zmax - zmin);   << 
751     }                                          << 
752     return area;                               << 
753   }                                            << 
754                                                   691 
755   // ellipsoid, integration along phi          << 692   max1  = xSemiAxis > ySemiAxis ? xSemiAxis : ySemiAxis;
756   for (G4int i = 0; i < NPHI; ++i)             << 693   max1  = max1 > zSemiAxis ? max1 : zSemiAxis;
757   {                                            << 694   if (max1 == xSemiAxis)      { max2 = ySemiAxis; max3 = zSemiAxis; }
758     G4double sinPhi = std::sin(dPhi*(i + 0.5)) << 695   else if (max1 == ySemiAxis) { max2 = xSemiAxis; max3 = zSemiAxis; }
759     G4double kk = cc_aa + (cc_bb - cc_aa)*sinP << 696   else                        { max2 = xSemiAxis; max3 = ySemiAxis; }
760     if (kk < 1. - eps)                         << 697 
761     {                                          << 698   phi   = G4RandFlat::shoot(0.,twopi);
762       G4double root = std::sqrt(1. - kk);      << 699   
763       G4double tmax = zmax_c*root;             << 700   cosphi = std::cos(phi);   sinphi = std::sin(phi);
764       G4double tmin = zmin_c*root;             << 701   costheta = G4RandFlat::shoot(zBottomCut,zTopCut)/zSemiAxis;
765       G4double invk = 1./std::sqrt(kk);        << 702   sintheta = std::sqrt(1.-sqr(costheta));
766       area += 2.*ab*dPhi*                      << 703   
767         ((zmax_c*std::sqrt(kk + tmax*tmax) - z << 704   alpha = 1.-sqr(max2/max1); beta  = 1.-sqr(max3/max1);
768          (std::asinh(tmax*invk) - std::asinh(t << 705   
769     }                                          << 706   aTop    = pi*xSemiAxis*ySemiAxis*(1 - sqr(zTopCut/zSemiAxis));
770     else if (kk > 1. + eps)                    << 707   aBottom = pi*xSemiAxis*ySemiAxis*(1 - sqr(zBottomCut/zSemiAxis));
771     {                                          << 708   
772       G4double root = std::sqrt(kk - 1.);      << 709   // approximation
773       G4double tmax = zmax_c*root;             << 710   // from:" http://www.citr.auckland.ac.nz/techreports/2004/CITR-TR-139.pdf"
774       G4double tmin = zmin_c*root;             << 711   aCurved = 4.*pi*max1*max2*(1.-1./6.*(alpha+beta)-
775       G4double invk = 1./std::sqrt(kk);        << 712                             1./120.*(3.*sqr(alpha)+2.*alpha*beta+3.*sqr(beta)));
776       area += 2.*ab*dPhi*                      << 713 
777         ((zmax_c*std::sqrt(kk - tmax*tmax) - z << 714   aCurved *= 0.5*(1.2*zTopCut/zSemiAxis - 1.2*zBottomCut/zSemiAxis);
778          (std::asin(tmax*invk) - std::asin(tmi << 715   
779     }                                          << 716   if( ( zTopCut >= zSemiAxis && zBottomCut <= -1.*zSemiAxis )
780     else                                       << 717    || ( zTopCut == 0 && zBottomCut ==0 ) )
781     {                                          << 718   {
782       area += 4.*ab*dPhi*(zmax_c - zmin_c);    << 719     aTop = 0; aBottom = 0;
783     }                                          << 720   }
                                                   >> 721   
                                                   >> 722   chose = G4RandFlat::shoot(0.,aTop + aBottom + aCurved); 
                                                   >> 723   
                                                   >> 724   if(chose < aCurved)
                                                   >> 725   { 
                                                   >> 726     xRand = xSemiAxis*sintheta*cosphi;
                                                   >> 727     yRand = ySemiAxis*sintheta*sinphi;
                                                   >> 728     zRand = zSemiAxis*costheta;
                                                   >> 729     return G4ThreeVector (xRand,yRand,zRand); 
                                                   >> 730   }
                                                   >> 731   else if(chose >= aCurved && chose < aCurved + aTop)
                                                   >> 732   {
                                                   >> 733     xRand = G4RandFlat::shoot(-1.,1.)*xSemiAxis
                                                   >> 734           * std::sqrt(1-sqr(zTopCut/zSemiAxis));
                                                   >> 735     yRand = G4RandFlat::shoot(-1.,1.)*ySemiAxis
                                                   >> 736           * std::sqrt(1.-sqr(zTopCut/zSemiAxis)-sqr(xRand/xSemiAxis));
                                                   >> 737     zRand = zTopCut;
                                                   >> 738     return G4ThreeVector (xRand,yRand,zRand);
784   }                                               739   }
785   return area;                                 << 740   else
786 }                                              << 
787                                                << 
788 ////////////////////////////////////////////// << 
789 //                                             << 
790 // Return surface area                         << 
791                                                << 
792 G4double G4Ellipsoid::GetSurfaceArea()         << 
793 {                                              << 
794   if (fSurfaceArea == 0.)                      << 
795   {                                               741   {
796     G4double piAB = CLHEP::pi * fDx * fDy;     << 742     xRand = G4RandFlat::shoot(-1.,1.)*xSemiAxis
797     fSurfaceArea = LateralSurfaceArea();       << 743           * std::sqrt(1-sqr(zBottomCut/zSemiAxis));
798     if (fZBottomCut > -fDz)                    << 744     yRand = G4RandFlat::shoot(-1.,1.)*ySemiAxis
799     {                                          << 745           * std::sqrt(1.-sqr(zBottomCut/zSemiAxis)-sqr(xRand/xSemiAxis)); 
800       G4double hbot = 1. + fZBottomCut / fDz;  << 746     zRand = zBottomCut;
801       fSurfaceArea += piAB * hbot * (2. - hbot << 747     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   }                                               748   }
809   return fSurfaceArea;                         << 
810 }                                                 749 }
811                                                   750 
812 ////////////////////////////////////////////// << 751 /////////////////////////////////////////////////////////////////////////////
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 //                                                752 //
892 // Methods for visualisation                      753 // Methods for visualisation
893                                                   754 
894 void G4Ellipsoid::DescribeYourselfTo (G4VGraph    755 void G4Ellipsoid::DescribeYourselfTo (G4VGraphicsScene& scene) const
895 {                                                 756 {
896   scene.AddSolid(*this);                          757   scene.AddSolid(*this);
897 }                                                 758 }
898                                                   759 
899 ////////////////////////////////////////////// << 
900 //                                             << 
901 // Return vis extent                           << 
902                                                << 
903 G4VisExtent G4Ellipsoid::GetExtent() const        760 G4VisExtent G4Ellipsoid::GetExtent() const
904 {                                                 761 {
905   return { -fXmax, fXmax, -fYmax, fYmax, fZBot << 762   // Define the sides of the box into which the G4Ellipsoid instance would fit.
                                                   >> 763   //
                                                   >> 764   return G4VisExtent (-semiAxisMax, semiAxisMax,
                                                   >> 765                       -semiAxisMax, semiAxisMax,
                                                   >> 766                       -semiAxisMax, semiAxisMax);
906 }                                                 767 }
907                                                   768 
908 ////////////////////////////////////////////// << 
909 //                                             << 
910 // Create polyhedron                           << 
911                                                << 
912 G4Polyhedron* G4Ellipsoid::CreatePolyhedron ()    769 G4Polyhedron* G4Ellipsoid::CreatePolyhedron () const
913 {                                                 770 {
914   return new G4PolyhedronEllipsoid(fDx, fDy, f << 771   return new G4PolyhedronEllipsoid(xSemiAxis, ySemiAxis, zSemiAxis,
                                                   >> 772                                    zBottomCut, zTopCut);
915 }                                                 773 }
916                                                   774 
917 ////////////////////////////////////////////// << 
918 //                                             << 
919 // Return pointer to polyhedron                << 
920                                                << 
921 G4Polyhedron* G4Ellipsoid::GetPolyhedron () co    775 G4Polyhedron* G4Ellipsoid::GetPolyhedron () const
922 {                                                 776 {
923   if (fpPolyhedron == nullptr ||               << 777   if (!fpPolyhedron ||
924       fRebuildPolyhedron ||                       778       fRebuildPolyhedron ||
925       fpPolyhedron->GetNumberOfRotationStepsAt    779       fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
926       fpPolyhedron->GetNumberOfRotationSteps()    780       fpPolyhedron->GetNumberOfRotationSteps())
927     {                                             781     {
928       G4AutoLock l(&polyhedronMutex);             782       G4AutoLock l(&polyhedronMutex);
929       delete fpPolyhedron;                        783       delete fpPolyhedron;
930       fpPolyhedron = CreatePolyhedron();          784       fpPolyhedron = CreatePolyhedron();
931       fRebuildPolyhedron = false;                 785       fRebuildPolyhedron = false;
932       l.unlock();                                 786       l.unlock();
933     }                                             787     }
934   return fpPolyhedron;                            788   return fpPolyhedron;
935 }                                                 789 }
936                                                << 
937 #endif // !defined(G4GEOM_USE_UELLIPSOID) || ! << 
938                                                   790