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 8.0)


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