Geant4 Cross Reference

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


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
                                                   >>  26 // $Id: G4EllipticalCone.cc 83572 2014-09-01 15:23:27Z gcosmo $
                                                   >>  27 //
 26 // Implementation of G4EllipticalCone class        28 // Implementation of G4EllipticalCone class
 27 //                                                 29 //
 28 // This code implements an Elliptical Cone giv     30 // This code implements an Elliptical Cone given explicitly by the
 29 // equation:                                       31 // equation:
 30 //   x^2/a^2 + y^2/b^2 = (z-h)^2                   32 //   x^2/a^2 + y^2/b^2 = (z-h)^2
 31 // and specified by the parameters (a,b,h) and     33 // and specified by the parameters (a,b,h) and a cut parallel to the
 32 // xy plane above z = 0.                           34 // xy plane above z = 0.
 33 //                                                 35 //
 34 // Author: Dionysios Anninos                       36 // Author: Dionysios Anninos
 35 // Revised: Evgueni Tcherniaev                 <<  37 //
 36 // -------------------------------------------     38 // --------------------------------------------------------------------
 37                                                    39 
 38 #if !(defined(G4GEOM_USE_UELLIPTICALCONE) && d << 
 39                                                << 
 40 #include "globals.hh"                              40 #include "globals.hh"
 41                                                    41 
 42 #include "G4EllipticalCone.hh"                     42 #include "G4EllipticalCone.hh"
 43                                                    43 
 44 #include "G4RandomTools.hh"                    << 
 45 #include "G4GeomTools.hh"                      << 
 46 #include "G4ClippablePolygon.hh"                   44 #include "G4ClippablePolygon.hh"
                                                   >>  45 #include "G4SolidExtentList.hh"
 47 #include "G4VoxelLimits.hh"                        46 #include "G4VoxelLimits.hh"
 48 #include "G4AffineTransform.hh"                    47 #include "G4AffineTransform.hh"
 49 #include "G4BoundingEnvelope.hh"               << 
 50 #include "G4GeometryTolerance.hh"                  48 #include "G4GeometryTolerance.hh"
 51                                                    49 
 52 #include "meshdefs.hh"                             50 #include "meshdefs.hh"
 53                                                    51 
 54 #include "Randomize.hh"                            52 #include "Randomize.hh"
 55                                                    53 
 56 #include "G4VGraphicsScene.hh"                     54 #include "G4VGraphicsScene.hh"
 57 #include "G4VisExtent.hh"                          55 #include "G4VisExtent.hh"
 58                                                    56 
 59 #include "G4AutoLock.hh"                           57 #include "G4AutoLock.hh"
 60                                                    58 
 61 namespace                                          59 namespace
 62 {                                                  60 {
 63   G4Mutex polyhedronMutex = G4MUTEX_INITIALIZE     61   G4Mutex polyhedronMutex = G4MUTEX_INITIALIZER;
 64 }                                                  62 }
 65                                                    63 
 66 using namespace CLHEP;                             64 using namespace CLHEP;
 67                                                    65 
 68 ////////////////////////////////////////////// <<  66 //////////////////////////////////////////////////////////////////////
 69 //                                                 67 //
 70 // Constructor - check parameters                  68 // Constructor - check parameters
 71                                                <<  69 //
 72 G4EllipticalCone::G4EllipticalCone(const G4Str     70 G4EllipticalCone::G4EllipticalCone(const G4String& pName,
 73                                          G4dou     71                                          G4double  pxSemiAxis,
 74                                          G4dou     72                                          G4double  pySemiAxis,
 75                                          G4dou     73                                          G4double  pzMax,
 76                                          G4dou     74                                          G4double  pzTopCut)
 77   : G4VSolid(pName), zTopCut(0.)               <<  75   : G4VSolid(pName), fRebuildPolyhedron(false), fpPolyhedron(0),
                                                   >>  76     fCubicVolume(0.), fSurfaceArea(0.), zTopCut(0.)
 78 {                                                  77 {
                                                   >>  78 
                                                   >>  79   kRadTolerance = G4GeometryTolerance::GetInstance()->GetRadialTolerance();
                                                   >>  80 
                                                   >>  81   halfRadTol = 0.5*kRadTolerance;
 79   halfCarTol = 0.5*kCarTolerance;                  82   halfCarTol = 0.5*kCarTolerance;
 80                                                    83 
 81   // Check Semi-Axis & Z-cut                       84   // Check Semi-Axis & Z-cut
 82   //                                               85   //
 83   if ( (pxSemiAxis <= 0.) || (pySemiAxis <= 0.     86   if ( (pxSemiAxis <= 0.) || (pySemiAxis <= 0.) || (pzMax <= 0.) )
 84   {                                                87   {
 85      std::ostringstream message;                   88      std::ostringstream message;
 86      message << "Invalid semi-axis or height f <<  89      message << "Invalid semi-axis or height - " << GetName();
 87              << "\n   X semi-axis, Y semi-axis << 
 88              << pxSemiAxis << ", " << pySemiAx << 
 89      G4Exception("G4EllipticalCone::G4Elliptic     90      G4Exception("G4EllipticalCone::G4EllipticalCone()", "GeomSolids0002",
 90                  FatalErrorInArgument, message     91                  FatalErrorInArgument, message);
 91    }                                           <<  92   }
 92                                                << 
 93   if ( pzTopCut <= 0 )                             93   if ( pzTopCut <= 0 )
 94   {                                                94   {
 95      std::ostringstream message;                   95      std::ostringstream message;
 96      message << "Invalid z-coordinate for cutt <<  96      message << "Invalid z-coordinate for cutting plane - " << GetName();
 97              << "\n   Z top cut = " << pzTopCu <<  97      G4Exception("G4EllipticalCone::G4EllipticalCone()", "InvalidSetup",
 98      G4Exception("G4EllipticalCone::G4Elliptic << 
 99                  FatalErrorInArgument, message     98                  FatalErrorInArgument, message);
100   }                                                99   }
101                                                   100 
102   SetSemiAxis( pxSemiAxis, pySemiAxis, pzMax )    101   SetSemiAxis( pxSemiAxis, pySemiAxis, pzMax );
103   SetZCut(pzTopCut);                              102   SetZCut(pzTopCut);
104 }                                                 103 }
105                                                   104 
106 ////////////////////////////////////////////// << 105 ///////////////////////////////////////////////////////////////////////////////
107 //                                                106 //
108 // Fake default constructor - sets only member    107 // Fake default constructor - sets only member data and allocates memory
109 //                            for usage restri    108 //                            for usage restricted to object persistency.
110                                                << 109 //
111 G4EllipticalCone::G4EllipticalCone( __void__&     110 G4EllipticalCone::G4EllipticalCone( __void__& a )
112   : G4VSolid(a), halfCarTol(0.),               << 111   : G4VSolid(a), fRebuildPolyhedron(false), fpPolyhedron(0),
113     xSemiAxis(0.), ySemiAxis(0.), zheight(0.), << 112     kRadTolerance(0.), halfRadTol(0.), halfCarTol(0.), fCubicVolume(0.),
114     cosAxisMin(0.), invXX(0.), invYY(0.)       << 113     fSurfaceArea(0.), xSemiAxis(0.), ySemiAxis(0.), zheight(0.),
                                                   >> 114     semiAxisMax(0.), zTopCut(0.)
115 {                                                 115 {
116 }                                                 116 }
117                                                   117 
118 ////////////////////////////////////////////// << 118 ///////////////////////////////////////////////////////////////////////////////
119 //                                                119 //
120 // Destructor                                     120 // Destructor
121                                                << 121 //
122 G4EllipticalCone::~G4EllipticalCone()             122 G4EllipticalCone::~G4EllipticalCone()
123 {                                                 123 {
124   delete fpPolyhedron; fpPolyhedron = nullptr; << 124   delete fpPolyhedron; fpPolyhedron = 0;
125 }                                                 125 }
126                                                   126 
127 ////////////////////////////////////////////// << 127 ///////////////////////////////////////////////////////////////////////////////
128 //                                                128 //
129 // Copy constructor                               129 // Copy constructor
130                                                << 130 //
131 G4EllipticalCone::G4EllipticalCone(const G4Ell    131 G4EllipticalCone::G4EllipticalCone(const G4EllipticalCone& rhs)
132   : G4VSolid(rhs), halfCarTol(rhs.halfCarTol), << 132   : G4VSolid(rhs),
                                                   >> 133     fRebuildPolyhedron(false), fpPolyhedron(0),
                                                   >> 134     kRadTolerance(rhs.kRadTolerance),
                                                   >> 135     halfRadTol(rhs.halfRadTol), halfCarTol(rhs.halfCarTol), 
133     fCubicVolume(rhs.fCubicVolume), fSurfaceAr    136     fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
134     xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.yS << 137     xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.ySemiAxis), zheight(rhs.zheight),
135     zheight(rhs.zheight), zTopCut(rhs.zTopCut) << 138     semiAxisMax(rhs.semiAxisMax), zTopCut(rhs.zTopCut)
136     cosAxisMin(rhs.cosAxisMin), invXX(rhs.invX << 
137 {                                                 139 {
138 }                                                 140 }
139                                                   141 
140 ////////////////////////////////////////////// << 142 ///////////////////////////////////////////////////////////////////////////////
141 //                                                143 //
142 // Assignment operator                            144 // Assignment operator
143                                                << 145 //
144 G4EllipticalCone& G4EllipticalCone::operator =    146 G4EllipticalCone& G4EllipticalCone::operator = (const G4EllipticalCone& rhs) 
145 {                                                 147 {
146    // Check assignment to self                    148    // Check assignment to self
147    //                                             149    //
148    if (this == &rhs)  { return *this; }           150    if (this == &rhs)  { return *this; }
149                                                   151 
150    // Copy base class data                        152    // Copy base class data
151    //                                             153    //
152    G4VSolid::operator=(rhs);                      154    G4VSolid::operator=(rhs);
153                                                   155 
154    // Copy data                                   156    // Copy data
155    //                                             157    //
156    halfCarTol = rhs.halfCarTol;                << 158    kRadTolerance = rhs.kRadTolerance;
                                                   >> 159    halfRadTol = rhs.halfRadTol; halfCarTol = rhs.halfCarTol;
157    fCubicVolume = rhs.fCubicVolume; fSurfaceAr    160    fCubicVolume = rhs.fCubicVolume; fSurfaceArea = rhs.fSurfaceArea;
158    xSemiAxis = rhs.xSemiAxis; ySemiAxis = rhs.    161    xSemiAxis = rhs.xSemiAxis; ySemiAxis = rhs.ySemiAxis;
159    zheight = rhs.zheight; zTopCut = rhs.zTopCu << 162    zheight = rhs.zheight; semiAxisMax = rhs.semiAxisMax; zTopCut = rhs.zTopCut;
160    cosAxisMin = rhs.cosAxisMin; invXX = rhs.in << 
161                                                << 
162    fRebuildPolyhedron = false;                    163    fRebuildPolyhedron = false;
163    delete fpPolyhedron; fpPolyhedron = nullptr << 164    delete fpPolyhedron; fpPolyhedron = 0;
164                                                   165 
165    return *this;                                  166    return *this;
166 }                                                 167 }
167                                                   168 
168 ////////////////////////////////////////////// << 169 ///////////////////////////////////////////////////////////////////////////////
169 //                                                170 //
170 // Get bounding box                            << 171 // Calculate extent under transform and specified limit
171                                                << 172 //
172 void G4EllipticalCone::BoundingLimits(G4ThreeV << 173 G4bool
173                                       G4ThreeV << 174 G4EllipticalCone::CalculateExtent( const EAxis axis,
                                                   >> 175                                    const G4VoxelLimits &voxelLimit,
                                                   >> 176                                    const G4AffineTransform &transform,
                                                   >> 177                                          G4double &min, G4double &max ) const
174 {                                                 178 {
175   G4double zcut   = GetZTopCut();              << 179   G4SolidExtentList  extentList( axis, voxelLimit );
176   G4double height = GetZMax();                 << 180   
177   G4double xmax   = GetSemiAxisX()*(height+zcu << 181   //
178   G4double ymax   = GetSemiAxisY()*(height+zcu << 182   // We are going to divide up our elliptical face into small pieces
179   pMin.set(-xmax,-ymax,-zcut);                 << 183   //
180   pMax.set( xmax, ymax, zcut);                 << 184   
181                                                << 185   //
182   // Check correctness of the bounding box     << 186   // Choose phi size of our segment(s) based on constants as
183   //                                           << 187   // defined in meshdefs.hh
184   if (pMin.x() >= pMax.x() || pMin.y() >= pMax << 188   //
185   {                                            << 189   G4int numPhi = kMaxMeshSections;
186     std::ostringstream message;                << 190   G4double sigPhi = twopi/numPhi;
187     message << "Bad bounding box (min >= max)  << 191   
188             << GetName() << " !"               << 192   //
189             << "\npMin = " << pMin             << 193   // We have to be careful to keep our segments completely outside
190             << "\npMax = " << pMax;            << 194   // of the elliptical surface. To do so we imagine we have
191     G4Exception("G4EllipticalCone::BoundingLim << 195   // a simple (unit radius) circular cross section (as in G4Tubs) 
192                 JustWarning, message);         << 196   // and then "stretch" the dimensions as necessary to fit the ellipse.
193     DumpInfo();                                << 197   //
194   }                                            << 198   G4double rFudge = 1.0/std::cos(0.5*sigPhi);
195 }                                              << 199   G4double dxFudgeBot = xSemiAxis*2.*zheight*rFudge,
                                                   >> 200            dyFudgeBot = ySemiAxis*2.*zheight*rFudge;
                                                   >> 201   G4double dxFudgeTop = xSemiAxis*(zheight-zTopCut)*rFudge,
                                                   >> 202            dyFudgeTop = ySemiAxis*(zheight-zTopCut)*rFudge;
                                                   >> 203   
                                                   >> 204   //
                                                   >> 205   // As we work around the elliptical surface, we build
                                                   >> 206   // a "phi" segment on the way, and keep track of two
                                                   >> 207   // additional polygons for the two ends.
                                                   >> 208   //
                                                   >> 209   G4ClippablePolygon endPoly1, endPoly2, phiPoly;
                                                   >> 210   
                                                   >> 211   G4double phi = 0, 
                                                   >> 212            cosPhi = std::cos(phi),
                                                   >> 213            sinPhi = std::sin(phi);
                                                   >> 214   G4ThreeVector v0( dxFudgeTop*cosPhi, dyFudgeTop*sinPhi, +zTopCut ),
                                                   >> 215                 v1( dxFudgeBot*cosPhi, dyFudgeBot*sinPhi, -zTopCut ),
                                                   >> 216                 w0, w1;
                                                   >> 217   transform.ApplyPointTransform( v0 );
                                                   >> 218   transform.ApplyPointTransform( v1 );
                                                   >> 219   do
                                                   >> 220   {
                                                   >> 221     phi += sigPhi;
                                                   >> 222     if (numPhi == 1) phi = 0;  // Try to avoid roundoff
                                                   >> 223     cosPhi = std::cos(phi), 
                                                   >> 224     sinPhi = std::sin(phi);
                                                   >> 225     
                                                   >> 226     w0 = G4ThreeVector( dxFudgeTop*cosPhi, dyFudgeTop*sinPhi, +zTopCut );
                                                   >> 227     w1 = G4ThreeVector( dxFudgeBot*cosPhi, dyFudgeBot*sinPhi, -zTopCut );
                                                   >> 228     transform.ApplyPointTransform( w0 );
                                                   >> 229     transform.ApplyPointTransform( w1 );
                                                   >> 230     
                                                   >> 231     //
                                                   >> 232     // Add a point to our z ends
                                                   >> 233     //
                                                   >> 234     endPoly1.AddVertexInOrder( v0 );
                                                   >> 235     endPoly2.AddVertexInOrder( v1 );
                                                   >> 236     
                                                   >> 237     //
                                                   >> 238     // Build phi polygon
                                                   >> 239     //
                                                   >> 240     phiPoly.ClearAllVertices();
                                                   >> 241     
                                                   >> 242     phiPoly.AddVertexInOrder( v0 );
                                                   >> 243     phiPoly.AddVertexInOrder( v1 );
                                                   >> 244     phiPoly.AddVertexInOrder( w1 );
                                                   >> 245     phiPoly.AddVertexInOrder( w0 );
                                                   >> 246     
                                                   >> 247     if (phiPoly.PartialClip( voxelLimit, axis ))
                                                   >> 248     {
                                                   >> 249       //
                                                   >> 250       // Get unit normal
                                                   >> 251       //
                                                   >> 252       phiPoly.SetNormal( (v1-v0).cross(w0-v0).unit() );
                                                   >> 253       
                                                   >> 254       extentList.AddSurface( phiPoly );
                                                   >> 255     }
196                                                   256 
197 ////////////////////////////////////////////// << 257     //
198 //                                             << 258     // Next vertex
199 // Calculate extent under transform and specif << 259     //    
                                                   >> 260     v0 = w0;
                                                   >> 261     v1 = w1;
                                                   >> 262   } while( --numPhi > 0 );
200                                                   263 
201 G4bool                                         << 264   //
202 G4EllipticalCone::CalculateExtent(const EAxis  << 265   // Process the end pieces
203                                   const G4Voxe << 266   //
204                                   const G4Affi << 267   if (endPoly1.PartialClip( voxelLimit, axis ))
205                                         G4doub << 
206 {                                              << 
207   G4ThreeVector bmin,bmax;                     << 
208   G4bool exist;                                << 
209                                                << 
210   // Check bounding box (bbox)                 << 
211   //                                           << 
212   BoundingLimits(bmin,bmax);                   << 
213   G4BoundingEnvelope bbox(bmin,bmax);          << 
214 #ifdef G4BBOX_EXTENT                           << 
215   return bbox.CalculateExtent(pAxis,pVoxelLimi << 
216 #endif                                         << 
217   if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox << 
218   {                                               268   {
219     return exist = pMin < pMax;                << 269     static const G4ThreeVector normal(0,0,+1);
                                                   >> 270     endPoly1.SetNormal( transform.TransformAxis(normal) );
                                                   >> 271     extentList.AddSurface( endPoly1 );
220   }                                               272   }
221                                                << 273   
222   // Set bounding envelope (benv) and calculat << 274   if (endPoly2.PartialClip( voxelLimit, axis ))
                                                   >> 275   {
                                                   >> 276     static const G4ThreeVector normal(0,0,-1);
                                                   >> 277     endPoly2.SetNormal( transform.TransformAxis(normal) );
                                                   >> 278     extentList.AddSurface( endPoly2 );
                                                   >> 279   }
                                                   >> 280   
                                                   >> 281   //
                                                   >> 282   // Return min/max value
223   //                                              283   //
224   static const G4int NSTEPS = 48; // number of << 284   return extentList.GetExtent( min, max );
225   static const G4double ang = twopi/NSTEPS;    << 
226   static const G4double sinHalf = std::sin(0.5 << 
227   static const G4double cosHalf = std::cos(0.5 << 
228   static const G4double sinStep = 2.*sinHalf*c << 
229   static const G4double cosStep = 1. - 2.*sinH << 
230   G4double zcut   = bmax.z();                  << 
231   G4double height = GetZMax();                 << 
232   G4double sxmin  = GetSemiAxisX()*(height-zcu << 
233   G4double symin  = GetSemiAxisY()*(height-zcu << 
234   G4double sxmax  = bmax.x()/cosHalf;          << 
235   G4double symax  = bmax.y()/cosHalf;          << 
236                                                << 
237   G4double sinCur = sinHalf;                   << 
238   G4double cosCur = cosHalf;                   << 
239   G4ThreeVectorList baseA(NSTEPS),baseB(NSTEPS << 
240   for (G4int k=0; k<NSTEPS; ++k)               << 
241   {                                            << 
242     baseA[k].set(sxmax*cosCur,symax*sinCur,-zc << 
243     baseB[k].set(sxmin*cosCur,symin*sinCur, zc << 
244                                                << 
245     G4double sinTmp = sinCur;                  << 
246     sinCur = sinCur*cosStep + cosCur*sinStep;  << 
247     cosCur = cosCur*cosStep - sinTmp*sinStep;  << 
248   }                                            << 
249                                                << 
250   std::vector<const G4ThreeVectorList *> polyg << 
251   polygons[0] = &baseA;                        << 
252   polygons[1] = &baseB;                        << 
253   G4BoundingEnvelope benv(bmin,bmax,polygons); << 
254   exist = benv.CalculateExtent(pAxis,pVoxelLim << 
255   return exist;                                << 
256 }                                                 285 }
257                                                   286 
258 ////////////////////////////////////////////// << 287 ////////////////////////////////////////////////////////////////////////
                                                   >> 288 //
                                                   >> 289 // Return whether point inside/outside/on surface
                                                   >> 290 // Split into radius, phi, theta checks
                                                   >> 291 // Each check modifies `in', or returns as approprate
259 //                                                292 //
260 // Determine where is point: inside, outside o << 
261                                                << 
262 EInside G4EllipticalCone::Inside(const G4Three    293 EInside G4EllipticalCone::Inside(const G4ThreeVector& p) const
263 {                                                 294 {
264   G4double hp = std::sqrt(p.x()*p.x()*invXX +  << 295   G4double rad2oo,  // outside surface outer tolerance
265   G4double ds = (hp - zheight)*cosAxisMin;     << 296            rad2oi;  // outside surface inner tolerance
266   G4double dz = std::abs(p.z()) - zTopCut;     << 297   
267   G4double dist = std::max(ds,dz);             << 298   EInside in;
                                                   >> 299 
                                                   >> 300   // check this side of z cut first, because that's fast
                                                   >> 301   //
268                                                   302 
269   if (dist > halfCarTol) return kOutside;      << 303   if ( (p.z() < -zTopCut - halfCarTol)
270   return (dist > -halfCarTol) ? kSurface : kIn << 304     || (p.z() > zTopCut + halfCarTol ) )
                                                   >> 305   {
                                                   >> 306     return in = kOutside; 
                                                   >> 307   }
                                                   >> 308 
                                                   >> 309   rad2oo= sqr(p.x()/( xSemiAxis + halfRadTol ))
                                                   >> 310         + sqr(p.y()/( ySemiAxis + halfRadTol ));
                                                   >> 311 
                                                   >> 312   if ( rad2oo > sqr( zheight-p.z() ) )
                                                   >> 313   {
                                                   >> 314     return in = kOutside; 
                                                   >> 315   }
                                                   >> 316 
                                                   >> 317   //  rad2oi= sqr( p.x()*(1.0 + 0.5*kRadTolerance/(xSemiAxis*xSemiAxis)) )
                                                   >> 318   //      + sqr( p.y()*(1.0 + 0.5*kRadTolerance/(ySemiAxis*ySemiAxis)) );
                                                   >> 319   rad2oi = sqr(p.x()/( xSemiAxis - halfRadTol ))
                                                   >> 320         + sqr(p.y()/( ySemiAxis - halfRadTol ));
                                                   >> 321      
                                                   >> 322   if (rad2oi < sqr( zheight-p.z() ) )
                                                   >> 323   {
                                                   >> 324     in = ( ( p.z() < -zTopCut + halfRadTol )
                                                   >> 325         || ( p.z() >  zTopCut - halfRadTol ) ) ? kSurface : kInside;
                                                   >> 326   }
                                                   >> 327   else 
                                                   >> 328   {
                                                   >> 329     in = kSurface;
                                                   >> 330   }
                                                   >> 331 
                                                   >> 332   return in;
271 }                                                 333 }
272                                                   334 
273 //////////////////////////////////////////////    335 /////////////////////////////////////////////////////////////////////////
274 //                                                336 //
275 // Return unit normal at surface closest to p  << 337 // Return unit normal of surface closest to p not protected against p=0
276                                                << 338 //
277 G4ThreeVector G4EllipticalCone::SurfaceNormal(    339 G4ThreeVector G4EllipticalCone::SurfaceNormal( const G4ThreeVector& p) const
278 {                                                 340 {
279   G4ThreeVector norm(0,0,0);                   << 
280   G4int nsurf = 0;  // number of surfaces wher << 
281                                                   341 
282   G4double hp = std::sqrt(p.x()*p.x()*invXX +  << 342   G4double rx = sqr(p.x()/xSemiAxis), 
283   G4double ds = (hp - zheight)*cosAxisMin;     << 343            ry = sqr(p.y()/ySemiAxis);
284   if (std::abs(ds) <= halfCarTol)              << 344 
                                                   >> 345   G4double rds = std::sqrt(rx + ry); 
                                                   >> 346 
                                                   >> 347   G4ThreeVector norm;
                                                   >> 348 
                                                   >> 349   if( (p.z() < -zTopCut) && ((rx+ry) < sqr(zTopCut + zheight)) )
285   {                                               350   {
286     norm = G4ThreeVector(p.x()*invXX, p.y()*in << 351     return G4ThreeVector( 0., 0., -1. ); 
287     G4double mag = norm.mag();                 << 
288     if (mag == 0) return {0,0,1}; // apex      << 
289     norm *= (1/mag);                           << 
290     ++nsurf;                                   << 
291   }                                               352   }
292   G4double dz = std::abs(p.z()) - zTopCut;     << 353 
293   if (std::abs(dz) <= halfCarTol)              << 354   if( (p.z() > (zheight > zTopCut ? zheight : zTopCut)) &&
                                                   >> 355       ((rx+ry) < sqr(zheight-zTopCut)) )
294   {                                               356   {
295     norm += G4ThreeVector(0., 0.,(p.z() < 0) ? << 357     return G4ThreeVector( 0., 0., 1. );
296     ++nsurf;                                   << 
297   }                                               358   }
298                                                   359 
299   if      (nsurf == 1) return norm;            << 360   if( p.z() > rds + 2.*zTopCut - zheight ) 
300   else if (nsurf >  1) return norm.unit(); //  << 
301   else                                         << 
302   {                                               361   {
303     // Point is not on the surface             << 362     if ( p.z() > zTopCut )
304     //                                         << 363     {
305 #ifdef G4CSGDEBUG                              << 364       if( p.x() == 0. ) 
306     std::ostringstream message;                << 365       {
307     G4long oldprc = message.precision(16);     << 366         norm = G4ThreeVector( 0., p.y() < 0. ? -1. : 1., 1. ); 
308     message << "Point p is not on surface (!?) << 367         return norm /= norm.mag();
309             << GetName() << G4endl;            << 368       } 
310     message << "Position:\n";                  << 369       if( p.y() == 0. )
311     message << "   p.x() = " << p.x()/mm << "  << 370       {
312     message << "   p.y() = " << p.y()/mm << "  << 371         norm = G4ThreeVector( p.x() < 0. ? -1. : 1., 0., 1. ); 
313     message << "   p.z() = " << p.z()/mm << "  << 372         return norm /= norm.mag();
314     G4cout.precision(oldprc);                  << 373       } 
315     G4Exception("G4EllipticalCone::SurfaceNorm << 374       
316                 JustWarning, message );        << 375       G4double k =  std::fabs(p.x()/p.y());
317     DumpInfo();                                << 376       G4double c2 = sqr(zheight-zTopCut)/(1./sqr(xSemiAxis)+sqr(k/ySemiAxis));
318 #endif                                         << 377       G4double x  = std::sqrt(c2);
319     return ApproxSurfaceNormal(p);             << 378       G4double y  = k*x;
                                                   >> 379         
                                                   >> 380       x /= sqr(xSemiAxis);
                                                   >> 381       y /= sqr(ySemiAxis);
                                                   >> 382       
                                                   >> 383       norm = G4ThreeVector( p.x() < 0. ? -x : x, 
                                                   >> 384                             p.y() < 0. ? -y : y,
                                                   >> 385                             - ( zheight - zTopCut ) );
                                                   >> 386       norm /= norm.mag();
                                                   >> 387       norm += G4ThreeVector( 0., 0., 1. );
                                                   >> 388       return norm /= norm.mag();      
                                                   >> 389     }
                                                   >> 390     
                                                   >> 391     return G4ThreeVector( 0., 0., 1. );    
320   }                                               392   }
321 }                                              << 393   
                                                   >> 394   if( p.z() < rds - 2.*zTopCut - zheight )
                                                   >> 395   {
                                                   >> 396     if( p.x() == 0. ) 
                                                   >> 397     {
                                                   >> 398       norm = G4ThreeVector( 0., p.y() < 0. ? -1. : 1., -1. ); 
                                                   >> 399       return norm /= norm.mag();
                                                   >> 400     } 
                                                   >> 401     if( p.y() == 0. )
                                                   >> 402     {
                                                   >> 403       norm = G4ThreeVector( p.x() < 0. ? -1. : 1., 0., -1. ); 
                                                   >> 404       return norm /= norm.mag();
                                                   >> 405     } 
                                                   >> 406     
                                                   >> 407     G4double k =  std::fabs(p.x()/p.y());
                                                   >> 408     G4double c2 = sqr(zheight+zTopCut)/(1./sqr(xSemiAxis)+sqr(k/ySemiAxis));
                                                   >> 409     G4double x  = std::sqrt(c2);
                                                   >> 410     G4double y  = k*x;
                                                   >> 411     
                                                   >> 412     x /= sqr(xSemiAxis);
                                                   >> 413     y /= sqr(ySemiAxis);
                                                   >> 414     
                                                   >> 415     norm = G4ThreeVector( p.x() < 0. ? -x : x, 
                                                   >> 416                           p.y() < 0. ? -y : y,
                                                   >> 417                           - ( zheight - zTopCut ) );
                                                   >> 418     norm /= norm.mag();
                                                   >> 419     norm += G4ThreeVector( 0., 0., -1. );
                                                   >> 420     return norm /= norm.mag();      
                                                   >> 421   }
                                                   >> 422     
                                                   >> 423   norm  = G4ThreeVector(p.x()/sqr(xSemiAxis), p.y()/sqr(ySemiAxis), rds);
                                                   >> 424    
                                                   >> 425   G4double k = std::tan(pi/8.);
                                                   >> 426   G4double c = -zTopCut - k*(zTopCut + zheight);
322                                                   427 
323 ////////////////////////////////////////////// << 428   if( p.z() < -k*rds + c )
324 //                                             << 429     return G4ThreeVector (0.,0.,-1.);
325 // Find surface nearest to point and return co << 430 
326 // The algorithm is similar to the algorithm u << 431   return norm /= norm.mag();
327 // This method normally should not be called.  << 
328                                                << 
329 G4ThreeVector                                  << 
330 G4EllipticalCone::ApproxSurfaceNormal(const G4 << 
331 {                                              << 
332   G4double hp = std::sqrt(p.x()*p.x()*invXX +  << 
333   G4double ds = (hp - zheight)*cosAxisMin;     << 
334   G4double dz = std::abs(p.z()) - zTopCut;     << 
335   if (ds > dz && std::abs(hp - p.z()) > halfCa << 
336     return G4ThreeVector(p.x()*invXX, p.y()*in << 
337   else                                         << 
338     return { 0., 0., (G4double)((p.z() < 0) ?  << 
339 }                                                 432 }
340                                                   433 
341 ////////////////////////////////////////////// << 434 //////////////////////////////////////////////////////////////////////////
342 //                                                435 //
343 // Calculate distance to shape from outside, a    436 // Calculate distance to shape from outside, along normalised vector
344 // return kInfinity if no intersection, or int    437 // return kInfinity if no intersection, or intersection distance <= tolerance
345                                                << 438 //
346 G4double G4EllipticalCone::DistanceToIn( const    439 G4double G4EllipticalCone::DistanceToIn( const G4ThreeVector& p,
347                                          const    440                                          const G4ThreeVector& v  ) const
348 {                                                 441 {
349   G4double distMin = kInfinity;                   442   G4double distMin = kInfinity;
350                                                   443 
351   // code from EllipticalTube                     444   // code from EllipticalTube
352                                                   445 
353   G4double sigz = p.z()+zTopCut;                  446   G4double sigz = p.z()+zTopCut;
354                                                   447 
355   //                                              448   //
356   // Check z = -dz planer surface                 449   // Check z = -dz planer surface
357   //                                              450   //
358                                                   451 
359   if (sigz < halfCarTol)                          452   if (sigz < halfCarTol)
360   {                                               453   {
361     //                                            454     //
362     // We are "behind" the shape in z, and so     455     // We are "behind" the shape in z, and so can
363     // potentially hit the rear face. Correct     456     // potentially hit the rear face. Correct direction?
364     //                                            457     //
365     if (v.z() <= 0)                               458     if (v.z() <= 0)
366     {                                             459     {
367       //                                          460       //
368       // As long as we are far enough away, we    461       // As long as we are far enough away, we know we
369       // can't intersect                          462       // can't intersect
370       //                                          463       //
371       if (sigz < 0) return kInfinity;             464       if (sigz < 0) return kInfinity;
372                                                   465       
373       //                                          466       //
374       // Otherwise, we don't intersect unless     467       // Otherwise, we don't intersect unless we are
375       // on the surface of the ellipse            468       // on the surface of the ellipse
376       //                                          469       //
377                                                   470 
378       if ( sqr(p.x()/( xSemiAxis - halfCarTol     471       if ( sqr(p.x()/( xSemiAxis - halfCarTol ))
379          + sqr(p.y()/( ySemiAxis - halfCarTol  << 472          + sqr(p.y()/( ySemiAxis - halfCarTol )) <= sqr( zheight+zTopCut ) )
380         return kInfinity;                         473         return kInfinity;
381                                                   474 
382     }                                             475     }
383     else                                          476     else
384     {                                             477     {
385       //                                          478       //
386       // How far?                                 479       // How far?
387       //                                          480       //
388       G4double q = -sigz/v.z();                   481       G4double q = -sigz/v.z();
389                                                   482       
390       //                                          483       //
391       // Where does that place us?                484       // Where does that place us?
392       //                                          485       //
393       G4double xi = p.x() + q*v.x(),              486       G4double xi = p.x() + q*v.x(),
394                yi = p.y() + q*v.y();              487                yi = p.y() + q*v.y();
395                                                   488       
396       //                                          489       //
397       // Is this on the surface (within ellips    490       // Is this on the surface (within ellipse)?
398       //                                          491       //
399       if ( sqr(xi/xSemiAxis) + sqr(yi/ySemiAxi    492       if ( sqr(xi/xSemiAxis) + sqr(yi/ySemiAxis) <= sqr( zheight + zTopCut ) )
400       {                                           493       {
401         //                                        494         //
402         // Yup. Return q, unless we are on the    495         // Yup. Return q, unless we are on the surface
403         //                                        496         //
404         return (sigz < -halfCarTol) ? q : 0;      497         return (sigz < -halfCarTol) ? q : 0;
405       }                                           498       }
406       else if (xi/(xSemiAxis*xSemiAxis)*v.x()     499       else if (xi/(xSemiAxis*xSemiAxis)*v.x()
407              + yi/(ySemiAxis*ySemiAxis)*v.y()     500              + yi/(ySemiAxis*ySemiAxis)*v.y() >= 0)
408       {                                           501       {
409         //                                        502         //
410         // Else, if we are traveling outwards,    503         // Else, if we are traveling outwards, we know
411         // we must miss                           504         // we must miss
412         //                                        505         //
413         //        return kInfinity;               506         //        return kInfinity;
414       }                                           507       }
415     }                                             508     }
416   }                                               509   }
417                                                   510 
418   //                                              511   //
419   // Check z = +dz planer surface                 512   // Check z = +dz planer surface
420   //                                              513   //
421   sigz = p.z() - zTopCut;                         514   sigz = p.z() - zTopCut;
422                                                   515   
423   if (sigz > -halfCarTol)                         516   if (sigz > -halfCarTol)
424   {                                               517   {
425     if (v.z() >= 0)                               518     if (v.z() >= 0)
426     {                                             519     {
427                                                   520 
428       if (sigz > 0) return kInfinity;             521       if (sigz > 0) return kInfinity;
429                                                   522 
430       if ( sqr(p.x()/( xSemiAxis - halfCarTol     523       if ( sqr(p.x()/( xSemiAxis - halfCarTol ))
431          + sqr(p.y()/( ySemiAxis - halfCarTol     524          + sqr(p.y()/( ySemiAxis - halfCarTol )) <= sqr( zheight-zTopCut ) )
432         return kInfinity;                         525         return kInfinity;
433                                                   526 
434     }                                             527     }
435     else {                                        528     else {
436       G4double q = -sigz/v.z();                   529       G4double q = -sigz/v.z();
437                                                   530 
438       G4double xi = p.x() + q*v.x(),              531       G4double xi = p.x() + q*v.x(),
439                yi = p.y() + q*v.y();              532                yi = p.y() + q*v.y();
440                                                   533 
441       if ( sqr(xi/xSemiAxis) + sqr(yi/ySemiAxi    534       if ( sqr(xi/xSemiAxis) + sqr(yi/ySemiAxis) <= sqr( zheight - zTopCut ) )
442       {                                           535       {
443         return (sigz > -halfCarTol) ? q : 0;      536         return (sigz > -halfCarTol) ? q : 0;
444       }                                           537       }
445       else if (xi/(xSemiAxis*xSemiAxis)*v.x()     538       else if (xi/(xSemiAxis*xSemiAxis)*v.x()
446              + yi/(ySemiAxis*ySemiAxis)*v.y()     539              + yi/(ySemiAxis*ySemiAxis)*v.y() >= 0)
447       {                                           540       {
448         //        return kInfinity;               541         //        return kInfinity;
449       }                                           542       }
450     }                                             543     }
451   }                                               544   }
452                                                   545 
453                                                   546 
454 #if 0                                             547 #if 0
455                                                   548 
456   // check to see if Z plane is relevant          549   // check to see if Z plane is relevant
457   //                                              550   //
458   if (p.z() < -zTopCut - halfCarTol)           << 551   if (p.z() < -zTopCut - 0.5*kCarTolerance)
459   {                                               552   {
460     if (v.z() <= 0.0)                             553     if (v.z() <= 0.0)
461       return distMin;                             554       return distMin; 
462                                                   555 
463     G4double lambda = (-zTopCut - p.z())/v.z()    556     G4double lambda = (-zTopCut - p.z())/v.z();
464                                                   557     
465     if ( sqr((lambda*v.x()+p.x())/xSemiAxis) +    558     if ( sqr((lambda*v.x()+p.x())/xSemiAxis) + 
466          sqr((lambda*v.y()+p.y())/ySemiAxis) <    559          sqr((lambda*v.y()+p.y())/ySemiAxis) <=
467          sqr(zTopCut + zheight + halfCarTol) ) << 560          sqr(zTopCut + zheight + 0.5*kRadTolerance) ) 
468     {                                             561     { 
469       return distMin = std::fabs(lambda);         562       return distMin = std::fabs(lambda);    
470     }                                             563     }
471   }                                               564   }
472                                                   565 
473   if (p.z() > zTopCut + halfCarTol)            << 566   if (p.z() > zTopCut+0.5*kCarTolerance) 
474   {                                               567   {
475     if (v.z() >= 0.0)                             568     if (v.z() >= 0.0)
476       { return distMin; }                         569       { return distMin; }
477                                                   570 
478     G4double lambda  = (zTopCut - p.z()) / v.z    571     G4double lambda  = (zTopCut - p.z()) / v.z();
479                                                   572 
480     if ( sqr((lambda*v.x() + p.x())/xSemiAxis)    573     if ( sqr((lambda*v.x() + p.x())/xSemiAxis) + 
481          sqr((lambda*v.y() + p.y())/ySemiAxis)    574          sqr((lambda*v.y() + p.y())/ySemiAxis) <=
482          sqr(zheight - zTopCut + halfCarTol) ) << 575          sqr(zheight - zTopCut + 0.5*kRadTolerance) )
483       {                                           576       {
484         return distMin = std::fabs(lambda);       577         return distMin = std::fabs(lambda);
485       }                                           578       }
486   }                                               579   }
487                                                   580   
488   if (p.z() > zTopCut - halfCarTol                581   if (p.z() > zTopCut - halfCarTol
489    && p.z() < zTopCut + halfCarTol )              582    && p.z() < zTopCut + halfCarTol )
490   {                                               583   {
491     if (v.z() > 0.)                               584     if (v.z() > 0.) 
492       { return kInfinity; }                       585       { return kInfinity; }
493                                                   586 
494     return distMin = 0.;                          587     return distMin = 0.;
495   }                                               588   }
496                                                   589   
497   if (p.z() < -zTopCut + halfCarTol               590   if (p.z() < -zTopCut + halfCarTol
498    && p.z() > -zTopCut - halfCarTol)              591    && p.z() > -zTopCut - halfCarTol)
499   {                                               592   {
500     if (v.z() < 0.)                               593     if (v.z() < 0.)
501       { return distMin = kInfinity; }             594       { return distMin = kInfinity; }
502                                                   595     
503     return distMin = 0.;                          596     return distMin = 0.;
504   }                                               597   }
505                                                   598   
506 #endif                                            599 #endif
507                                                   600 
508   // if we are here then it either intersects     601   // if we are here then it either intersects or grazes the curved surface 
509   // or it does not intersect at all              602   // or it does not intersect at all
510   //                                              603   //
511   G4double A = sqr(v.x()/xSemiAxis) + sqr(v.y(    604   G4double A = sqr(v.x()/xSemiAxis) + sqr(v.y()/ySemiAxis) - sqr(v.z());
512   G4double B = 2*(v.x()*p.x()/sqr(xSemiAxis) +    605   G4double B = 2*(v.x()*p.x()/sqr(xSemiAxis) + 
513                   v.y()*p.y()/sqr(ySemiAxis) +    606                   v.y()*p.y()/sqr(ySemiAxis) + v.z()*(zheight-p.z()));
514   G4double C = sqr(p.x()/xSemiAxis) + sqr(p.y(    607   G4double C = sqr(p.x()/xSemiAxis) + sqr(p.y()/ySemiAxis) - 
515                sqr(zheight - p.z());              608                sqr(zheight - p.z());
516                                                   609  
517   G4double discr = B*B - 4.*A*C;                  610   G4double discr = B*B - 4.*A*C;
518                                                   611    
519   // if the discriminant is negative it never     612   // if the discriminant is negative it never hits the curved object
520   //                                              613   //
521   if ( discr < -halfCarTol )                      614   if ( discr < -halfCarTol )
522     { return distMin; }                           615     { return distMin; }
523                                                   616   
524   // case below is when it hits or grazes the     617   // case below is when it hits or grazes the surface
525   //                                              618   //
526   if ( (discr >= -halfCarTol ) && (discr < hal << 619   if ( (discr >= - halfCarTol ) && (discr < halfCarTol ) )
527   {                                               620   {
528     return distMin = std::fabs(-B/(2.*A));        621     return distMin = std::fabs(-B/(2.*A)); 
529   }                                               622   }
530                                                   623   
531   G4double plus  = (-B+std::sqrt(discr))/(2.*A    624   G4double plus  = (-B+std::sqrt(discr))/(2.*A);
532   G4double minus = (-B-std::sqrt(discr))/(2.*A    625   G4double minus = (-B-std::sqrt(discr))/(2.*A);
533                                                   626  
534   // Special case::Point on Surface, Check nor    627   // Special case::Point on Surface, Check norm.dot(v)
535                                                   628 
536   if ( ( std::fabs(plus) < halfCarTol )||( std    629   if ( ( std::fabs(plus) < halfCarTol )||( std::fabs(minus) < halfCarTol ) )
537   {                                               630   {
538     G4ThreeVector truenorm(p.x()/(xSemiAxis*xS    631     G4ThreeVector truenorm(p.x()/(xSemiAxis*xSemiAxis),
539                            p.y()/(ySemiAxis*yS    632                            p.y()/(ySemiAxis*ySemiAxis),
540                            -( p.z() - zheight     633                            -( p.z() - zheight ));
541     if ( truenorm*v >= 0)  //  going outside t    634     if ( truenorm*v >= 0)  //  going outside the solid from surface
542     {                                             635     {
543       return kInfinity;                           636       return kInfinity;
544     }                                             637     }
545     else                                          638     else
546     {                                             639     {
547       return 0;                                   640       return 0;
548     }                                             641     }
549   }                                               642   }
550                                                   643 
551   // G4double lambda = std::fabs(plus) < std::    644   // G4double lambda = std::fabs(plus) < std::fabs(minus) ? plus : minus;  
552   G4double lambda = 0;                            645   G4double lambda = 0;
553                                                   646 
554   if ( minus > halfCarTol && minus < distMin )    647   if ( minus > halfCarTol && minus < distMin ) 
555   {                                               648   {
556     lambda = minus ;                              649     lambda = minus ;
557     // check normal vector   n * v < 0            650     // check normal vector   n * v < 0
558     G4ThreeVector pin = p + lambda*v;             651     G4ThreeVector pin = p + lambda*v;
559     if(std::fabs(pin.z())< zTopCut + halfCarTo << 652     if(std::fabs(pin.z())<zTopCut+0.5*kCarTolerance)
560     {                                             653     {
561       G4ThreeVector truenorm(pin.x()/(xSemiAxi    654       G4ThreeVector truenorm(pin.x()/(xSemiAxis*xSemiAxis),
562                              pin.y()/(ySemiAxi    655                              pin.y()/(ySemiAxis*ySemiAxis),
563                              - ( pin.z() - zhe    656                              - ( pin.z() - zheight ));
564       if ( truenorm*v < 0)                        657       if ( truenorm*v < 0)
565       {   // yes, going inside the solid          658       {   // yes, going inside the solid
566         distMin = lambda;                         659         distMin = lambda;
567       }                                           660       }
568     }                                             661     }
569   }                                               662   }
570   if ( plus > halfCarTol  && plus < distMin )     663   if ( plus > halfCarTol  && plus < distMin )
571   {                                               664   {
572     lambda = plus ;                               665     lambda = plus ;
573     // check normal vector   n * v < 0            666     // check normal vector   n * v < 0
574     G4ThreeVector pin = p + lambda*v;             667     G4ThreeVector pin = p + lambda*v;
575     if(std::fabs(pin.z()) < zTopCut + halfCarT << 668     if(std::fabs(pin.z())<zTopCut+0.5*kCarTolerance)
576     {                                             669     {
577       G4ThreeVector truenorm(pin.x()/(xSemiAxi    670       G4ThreeVector truenorm(pin.x()/(xSemiAxis*xSemiAxis),
578                              pin.y()/(ySemiAxi    671                              pin.y()/(ySemiAxis*ySemiAxis),
579                              - ( pin.z() - zhe    672                              - ( pin.z() - zheight ) );
580       if ( truenorm*v < 0)                        673       if ( truenorm*v < 0)
581       {   // yes, going inside the solid          674       {   // yes, going inside the solid
582         distMin = lambda;                         675         distMin = lambda;
583       }                                           676       }
584     }                                             677     }
585   }                                               678   }
586   if (distMin < halfCarTol) distMin=0.;           679   if (distMin < halfCarTol) distMin=0.;
587   return distMin ;                                680   return distMin ;
588 }                                                 681 }
589                                                   682 
590 ////////////////////////////////////////////// << 683 //////////////////////////////////////////////////////////////////////////
591 //                                                684 //
592 // Calculate distance (<= actual) to closest s    685 // Calculate distance (<= actual) to closest surface of shape from outside
593 // Return 0 if point inside                       686 // Return 0 if point inside
594                                                << 687 //
595 G4double G4EllipticalCone::DistanceToIn(const     688 G4double G4EllipticalCone::DistanceToIn(const G4ThreeVector& p) const
596 {                                                 689 {
597   G4double hp = std::sqrt(p.x()*p.x()*invXX +  << 690   G4double distR, distR2, distZ, maxDim;
598   G4double ds = (hp - zheight)*cosAxisMin;     << 691   G4double distRad;  
599   G4double dz = std::abs(p.z()) - zTopCut;     << 692 
600   G4double dist = std::max(ds,dz);             << 693   // check if the point lies either below z=-zTopCut in bottom elliptical
601   return (dist > 0) ? dist : 0.;               << 694   // region or on top within cut elliptical region
                                                   >> 695   //
                                                   >> 696   if( (p.z() <= -zTopCut) && (sqr(p.x()/xSemiAxis) + sqr(p.y()/ySemiAxis)
                                                   >> 697                            <= sqr(zTopCut + zheight + 0.5*kCarTolerance )) )
                                                   >> 698   {  
                                                   >> 699     //return distZ = std::fabs(zTopCut - p.z());
                                                   >> 700      return distZ = std::fabs(zTopCut + p.z());
                                                   >> 701   } 
                                                   >> 702   
                                                   >> 703   if( (p.z() >= zTopCut) && (sqr(p.x()/xSemiAxis)+sqr(p.y()/ySemiAxis)
                                                   >> 704                           <= sqr(zheight - zTopCut + kCarTolerance/2.0 )) )
                                                   >> 705   {
                                                   >> 706     return distZ = std::fabs(p.z() - zTopCut);
                                                   >> 707   } 
                                                   >> 708   
                                                   >> 709   // below we use the following approximation: we take the largest of the
                                                   >> 710   // axes and find the shortest distance to the circular (cut) cone of that
                                                   >> 711   // radius.  
                                                   >> 712   //
                                                   >> 713   maxDim = xSemiAxis >= ySemiAxis ? xSemiAxis:ySemiAxis;
                                                   >> 714   distRad = std::sqrt(p.x()*p.x()+p.y()*p.y());
                                                   >> 715 
                                                   >> 716   if( p.z() > maxDim*distRad + zTopCut*(1.+maxDim)-sqr(maxDim)*zheight )
                                                   >> 717   {
                                                   >> 718     distR2 = sqr(p.z() - zTopCut) + sqr(distRad - maxDim*(zheight - zTopCut));
                                                   >> 719     return std::sqrt( distR2 );
                                                   >> 720   } 
                                                   >> 721 
                                                   >> 722   if( distRad > maxDim*( zheight - p.z() ) )
                                                   >> 723   {
                                                   >> 724     if( p.z() > maxDim*distRad - (zTopCut*(1.+maxDim)+sqr(maxDim)*zheight) )
                                                   >> 725     {
                                                   >> 726       G4double zVal = (p.z()-maxDim*(distRad-maxDim*zheight))/(1.+sqr(maxDim));
                                                   >> 727       G4double rVal = maxDim*(zheight - zVal);
                                                   >> 728       return distR  = std::sqrt(sqr(p.z() - zVal) + sqr(distRad - rVal));
                                                   >> 729     }
                                                   >> 730   }
                                                   >> 731 
                                                   >> 732   if( distRad <= maxDim*(zheight - p.z()) )
                                                   >> 733   {
                                                   >> 734     distR2 = sqr(distRad - maxDim*(zheight + zTopCut)) + sqr(p.z() + zTopCut);
                                                   >> 735     return std::sqrt( distR2 );    
                                                   >> 736   }   
                                                   >> 737   
                                                   >> 738   return distR = 0;
602 }                                                 739 }
603                                                   740 
604 ////////////////////////////////////////////// << 741 /////////////////////////////////////////////////////////////////////////
605 //                                                742 //
606 // Calculate distance to surface of shape from    743 // Calculate distance to surface of shape from `inside',
607 // allowing for tolerance                         744 // allowing for tolerance
608                                                << 745 //
609 G4double G4EllipticalCone::DistanceToOut(const    746 G4double G4EllipticalCone::DistanceToOut(const G4ThreeVector& p,
610                                          const    747                                          const G4ThreeVector& v,
611                                          const    748                                          const G4bool calcNorm,
612                                                << 749                                                G4bool *validNorm,
613                                                << 750                                                G4ThreeVector *n  ) const
614 {                                                 751 {
615   G4double distMin, lambda;                       752   G4double distMin, lambda;
616   enum surface_e {kPlaneSurf, kCurvedSurf, kNo    753   enum surface_e {kPlaneSurf, kCurvedSurf, kNoSurf} surface;
617                                                   754   
618   distMin = kInfinity;                            755   distMin = kInfinity;
619   surface = kNoSurf;                              756   surface = kNoSurf;
620                                                   757 
621   if (v.z() < 0.0)                                758   if (v.z() < 0.0)
622   {                                               759   {
623     lambda = (-p.z() - zTopCut)/v.z();            760     lambda = (-p.z() - zTopCut)/v.z();
624                                                   761 
625     if ( (sqr((p.x() + lambda*v.x())/xSemiAxis    762     if ( (sqr((p.x() + lambda*v.x())/xSemiAxis) + 
626           sqr((p.y() + lambda*v.y())/ySemiAxis    763           sqr((p.y() + lambda*v.y())/ySemiAxis)) < 
627           sqr(zheight + zTopCut + halfCarTol)  << 764           sqr(zheight + zTopCut + 0.5*kCarTolerance) )
628     {                                             765     {
629       distMin = std::fabs(lambda);                766       distMin = std::fabs(lambda);
630                                                   767 
631       if (!calcNorm) { return distMin; }          768       if (!calcNorm) { return distMin; }
632     }                                             769     } 
633     distMin = std::fabs(lambda);                  770     distMin = std::fabs(lambda);
634     surface = kPlaneSurf;                         771     surface = kPlaneSurf;
635   }                                               772   }
636                                                   773 
637   if (v.z() > 0.0)                                774   if (v.z() > 0.0)
638   {                                               775   {
639     lambda = (zTopCut - p.z()) / v.z();           776     lambda = (zTopCut - p.z()) / v.z();
640                                                   777 
641     if ( (sqr((p.x() + lambda*v.x())/xSemiAxis    778     if ( (sqr((p.x() + lambda*v.x())/xSemiAxis)
642         + sqr((p.y() + lambda*v.y())/ySemiAxis    779         + sqr((p.y() + lambda*v.y())/ySemiAxis) )
643        < (sqr(zheight - zTopCut + halfCarTol)) << 780        < (sqr(zheight - zTopCut + 0.5*kCarTolerance)) )
644     {                                             781     {
645       distMin = std::fabs(lambda);                782       distMin = std::fabs(lambda);
646       if (!calcNorm) { return distMin; }          783       if (!calcNorm) { return distMin; }
647     }                                             784     }
648     distMin = std::fabs(lambda);                  785     distMin = std::fabs(lambda);
649     surface = kPlaneSurf;                         786     surface = kPlaneSurf;
650   }                                               787   }
651                                                   788   
652   // if we are here then it either intersects     789   // if we are here then it either intersects or grazes the 
653   // curved surface...                            790   // curved surface...
654   //                                              791   //
655   G4double A = sqr(v.x()/xSemiAxis) + sqr(v.y(    792   G4double A = sqr(v.x()/xSemiAxis) + sqr(v.y()/ySemiAxis) - sqr(v.z());
656   G4double B = 2.*(v.x()*p.x()/sqr(xSemiAxis)     793   G4double B = 2.*(v.x()*p.x()/sqr(xSemiAxis) +  
657                    v.y()*p.y()/sqr(ySemiAxis)     794                    v.y()*p.y()/sqr(ySemiAxis) + v.z()*(zheight-p.z()));
658   G4double C = sqr(p.x()/xSemiAxis) + sqr(p.y(    795   G4double C = sqr(p.x()/xSemiAxis) + sqr(p.y()/ySemiAxis)
659              - sqr(zheight - p.z());              796              - sqr(zheight - p.z());
660                                                   797  
661   G4double discr = B*B - 4.*A*C;                  798   G4double discr = B*B - 4.*A*C;
662                                                   799   
663   if ( discr >= - halfCarTol && discr < halfCa << 800   if ( discr >= - 0.5*kCarTolerance && discr < 0.5*kCarTolerance )
664   {                                               801   { 
665     if(!calcNorm) { return distMin = std::fabs    802     if(!calcNorm) { return distMin = std::fabs(-B/(2.*A)); }
666   }                                               803   }
667                                                   804 
668   else if ( discr > halfCarTol )               << 805   else if ( discr > 0.5*kCarTolerance )
669   {                                               806   {
670     G4double plus  = (-B+std::sqrt(discr))/(2.    807     G4double plus  = (-B+std::sqrt(discr))/(2.*A);
671     G4double minus = (-B-std::sqrt(discr))/(2.    808     G4double minus = (-B-std::sqrt(discr))/(2.*A);
672                                                   809 
673     if ( plus > halfCarTol && minus > halfCarT << 810     if ( plus > 0.5*kCarTolerance && minus > 0.5*kCarTolerance )
674     {                                             811     {
675       // take the shorter distance                812       // take the shorter distance
676       //                                          813       //
677       lambda   = std::fabs(plus) < std::fabs(m    814       lambda   = std::fabs(plus) < std::fabs(minus) ? plus : minus;
678     }                                             815     }
679     else                                          816     else
680     {                                             817     {
681       // at least one solution is close to zer    818       // at least one solution is close to zero or negative
682       // so, take small positive solution or z    819       // so, take small positive solution or zero 
683       //                                          820       //
684       lambda   = plus > -halfCarTol ? plus : 0 << 821       lambda   = plus > -0.5*kCarTolerance ? plus : 0;
685     }                                             822     }
686                                                   823 
687     if ( std::fabs(lambda) < distMin )            824     if ( std::fabs(lambda) < distMin )
688     {                                             825     {
689       if( std::fabs(lambda) > halfCarTol)      << 826       if( std::fabs(lambda) > 0.5*kCarTolerance)
690       {                                           827       {
691         distMin  = std::fabs(lambda);             828         distMin  = std::fabs(lambda);
692         surface  = kCurvedSurf;                   829         surface  = kCurvedSurf;
693       }                                           830       }
694       else  // Point is On the Surface, Check     831       else  // Point is On the Surface, Check Normal
695       {                                           832       {
696         G4ThreeVector truenorm(p.x()/(xSemiAxi    833         G4ThreeVector truenorm(p.x()/(xSemiAxis*xSemiAxis),
697                                p.y()/(ySemiAxi    834                                p.y()/(ySemiAxis*ySemiAxis),
698                                -( p.z() - zhei    835                                -( p.z() - zheight ));
699         if( truenorm.dot(v) > 0 )                 836         if( truenorm.dot(v) > 0 )
700         {                                         837         {
701           distMin  = 0.0;                         838           distMin  = 0.0;
702           surface  = kCurvedSurf;                 839           surface  = kCurvedSurf;
703         }                                         840         }
704       }                                           841       } 
705     }                                             842     }
706   }                                               843   }
707                                                   844 
708   // set normal if requested                      845   // set normal if requested
709   //                                              846   //
710   if (calcNorm)                                   847   if (calcNorm)
711   {                                               848   {
712     if (surface == kNoSurf)                       849     if (surface == kNoSurf)
713     {                                             850     {
714       *validNorm = false;                         851       *validNorm = false;
715     }                                             852     }
716     else                                          853     else
717     {                                             854     {
718       *validNorm = true;                          855       *validNorm = true;
719       switch (surface)                            856       switch (surface)
720       {                                           857       {
721         case kPlaneSurf:                          858         case kPlaneSurf:
722         {                                         859         {
723           *n = G4ThreeVector(0.,0.,(v.z() > 0.    860           *n = G4ThreeVector(0.,0.,(v.z() > 0.0 ? 1. : -1.));
724         }                                         861         }
725         break;                                    862         break;
726                                                   863 
727         case kCurvedSurf:                         864         case kCurvedSurf:
728         {                                         865         {
729           G4ThreeVector pexit = p + distMin*v;    866           G4ThreeVector pexit = p + distMin*v;
730           G4ThreeVector truenorm( pexit.x()/(x    867           G4ThreeVector truenorm( pexit.x()/(xSemiAxis*xSemiAxis),
731                                   pexit.y()/(y    868                                   pexit.y()/(ySemiAxis*ySemiAxis),
732                                   -( pexit.z()    869                                   -( pexit.z() - zheight ) );
733           truenorm /= truenorm.mag();             870           truenorm /= truenorm.mag();
734           *n= truenorm;                           871           *n= truenorm;
735         }                                         872         } 
736         break;                                    873         break;
737                                                   874 
738         default:            // Should never re    875         default:            // Should never reach this case ...
739           DumpInfo();                             876           DumpInfo();
740           std::ostringstream message;             877           std::ostringstream message;
741           G4long oldprc = message.precision(16 << 878           G4int oldprc = message.precision(16);
742           message << "Undefined side for valid    879           message << "Undefined side for valid surface normal to solid."
743                   << G4endl                       880                   << G4endl
744                   << "Position:"  << G4endl       881                   << "Position:"  << G4endl
745                   << "   p.x() = "   << p.x()/    882                   << "   p.x() = "   << p.x()/mm << " mm" << G4endl
746                   << "   p.y() = "   << p.y()/    883                   << "   p.y() = "   << p.y()/mm << " mm" << G4endl
747                   << "   p.z() = "   << p.z()/    884                   << "   p.z() = "   << p.z()/mm << " mm" << G4endl
748                   << "Direction:" << G4endl       885                   << "Direction:" << G4endl
749                   << "   v.x() = "   << v.x()     886                   << "   v.x() = "   << v.x() << G4endl
750                   << "   v.y() = "   << v.y()     887                   << "   v.y() = "   << v.y() << G4endl
751                   << "   v.z() = "   << v.z()     888                   << "   v.z() = "   << v.z() << G4endl
752                   << "Proposed distance :" <<     889                   << "Proposed distance :" << G4endl
753                   << "   distMin = "    << dis    890                   << "   distMin = "    << distMin/mm << " mm";
754           message.precision(oldprc);              891           message.precision(oldprc);
755           G4Exception("G4EllipticalCone::Dista    892           G4Exception("G4EllipticalCone::DistanceToOut(p,v,..)",
756                       "GeomSolids1002", JustWa    893                       "GeomSolids1002", JustWarning, message);
757           break;                                  894           break;
758       }                                           895       }
759     }                                             896     }
760   }                                               897   }
761                                                   898 
762   if (distMin < halfCarTol) { distMin=0; }     << 899   if (distMin<0.5*kCarTolerance) { distMin=0; }
763                                                   900 
764   return distMin;                                 901   return distMin;
765 }                                                 902 }
766                                                   903 
767 //////////////////////////////////////////////    904 /////////////////////////////////////////////////////////////////////////
768 //                                                905 //
769 // Calculate distance (<=actual) to closest su    906 // Calculate distance (<=actual) to closest surface of shape from inside
770                                                << 907 //
771 G4double G4EllipticalCone::DistanceToOut(const    908 G4double G4EllipticalCone::DistanceToOut(const G4ThreeVector& p) const
772 {                                                 909 {
                                                   >> 910   G4double rds,roo,roo1, distR, distZ, distMin=0.;
                                                   >> 911   G4double minAxis = xSemiAxis < ySemiAxis ? xSemiAxis : ySemiAxis;
                                                   >> 912 
773 #ifdef G4SPECSDEBUG                               913 #ifdef G4SPECSDEBUG
774   if( Inside(p) == kOutside )                     914   if( Inside(p) == kOutside )
775   {                                               915   {
                                                   >> 916      DumpInfo();
776      std::ostringstream message;                  917      std::ostringstream message;
777      G4long oldprc = message.precision(16);    << 918      G4int oldprc = message.precision(16);
778      message << "Point p is outside (!?) of so << 919      message << "Point p is outside !?" << G4endl
779              << "Position:\n"                  << 920              << "Position:"  << G4endl
780              << "   p.x() = "  << p.x()/mm <<  << 921              << "   p.x() = "   << p.x()/mm << " mm" << G4endl
781              << "   p.y() = "  << p.y()/mm <<  << 922              << "   p.y() = "   << p.y()/mm << " mm" << G4endl
782              << "   p.z() = "  << p.z()/mm <<  << 923              << "   p.z() = "   << p.z()/mm << " mm";
783      message.precision(oldprc) ;                  924      message.precision(oldprc) ;
784      G4Exception("G4Ellipsoid::DistanceToOut(p    925      G4Exception("G4Ellipsoid::DistanceToOut(p)", "GeomSolids1002",
785                  JustWarning, message);           926                  JustWarning, message);
786      DumpInfo();                               << 
787   }                                               927   }
788 #endif                                            928 #endif
789   G4double hp = std::sqrt(p.x()*p.x()*invXX +  << 929     
790   G4double ds = (zheight - hp)*cosAxisMin;     << 930   // since we have made the above warning, below we are working assuming p
791   G4double dz = zTopCut - std::abs(p.z());     << 931   // is inside check how close it is to the circular cone with radius equal
792   G4double dist = std::min(ds,dz);             << 932   // to the smaller of the axes
793   return (dist > 0) ? dist : 0.;               << 933   //
                                                   >> 934   if( sqr(p.x()/minAxis)+sqr(p.y()/minAxis) < sqr(zheight - p.z()) )
                                                   >> 935   {
                                                   >> 936     rds     = std::sqrt(sqr(p.x()) + sqr(p.y()));
                                                   >> 937     roo     = minAxis*(zheight-p.z()); // radius of cone at z= p.z()
                                                   >> 938     roo1    = minAxis*(zheight-zTopCut); // radius of cone at z=+zTopCut
                                                   >> 939 
                                                   >> 940     distZ=zTopCut - std::fabs(p.z()) ;
                                                   >> 941     distR=(roo-rds)/(std::sqrt(1+sqr(minAxis)));
                                                   >> 942 
                                                   >> 943     if(rds>roo1)
                                                   >> 944     {
                                                   >> 945       distMin=(zTopCut-p.z())*(roo-rds)/(roo-roo1);
                                                   >> 946       distMin=std::min(distMin,distR);
                                                   >> 947     }      
                                                   >> 948     distMin=std::min(distR,distZ);
                                                   >> 949   }
                                                   >> 950 
                                                   >> 951   return distMin;
794 }                                                 952 }
795                                                   953 
796 ////////////////////////////////////////////// << 954 //////////////////////////////////////////////////////////////////////////
797 //                                                955 //
798 // GetEntityType                                  956 // GetEntityType
799                                                << 957 //
800 G4GeometryType G4EllipticalCone::GetEntityType    958 G4GeometryType G4EllipticalCone::GetEntityType() const
801 {                                                 959 {
802   return {"G4EllipticalCone"};                 << 960   return G4String("G4EllipticalCone");
803 }                                                 961 }
804                                                   962 
805 ////////////////////////////////////////////// << 963 //////////////////////////////////////////////////////////////////////////
806 //                                                964 //
807 // Make a clone of the object                     965 // Make a clone of the object
808                                                << 966 //
809 G4VSolid* G4EllipticalCone::Clone() const         967 G4VSolid* G4EllipticalCone::Clone() const
810 {                                                 968 {
811   return new G4EllipticalCone(*this);             969   return new G4EllipticalCone(*this);
812 }                                                 970 }
813                                                   971 
814 ////////////////////////////////////////////// << 972 //////////////////////////////////////////////////////////////////////////
815 //                                                973 //
816 // Stream object contents to an output stream     974 // Stream object contents to an output stream
817                                                << 975 //
818 std::ostream& G4EllipticalCone::StreamInfo( st    976 std::ostream& G4EllipticalCone::StreamInfo( std::ostream& os ) const
819 {                                                 977 {
820   G4long oldprc = os.precision(16);            << 978   G4int oldprc = os.precision(16);
821   os << "-------------------------------------    979   os << "-----------------------------------------------------------\n"
822      << "    *** Dump for solid - " << GetName    980      << "    *** Dump for solid - " << GetName() << " ***\n"
823      << "    =================================    981      << "    ===================================================\n"
824      << " Solid type: G4EllipticalCone\n"         982      << " Solid type: G4EllipticalCone\n"
825      << " Parameters: \n"                         983      << " Parameters: \n"
826                                                   984 
827      << "    semi-axis x: " << xSemiAxis/mm <<    985      << "    semi-axis x: " << xSemiAxis/mm << " mm \n"
828      << "    semi-axis y: " << ySemiAxis/mm <<    986      << "    semi-axis y: " << ySemiAxis/mm << " mm \n"
829      << "    height    z: " << zheight/mm << "    987      << "    height    z: " << zheight/mm << " mm \n"
830      << "    half length in  z: " << zTopCut/m    988      << "    half length in  z: " << zTopCut/mm << " mm \n"
831      << "-------------------------------------    989      << "-----------------------------------------------------------\n";
832   os.precision(oldprc);                           990   os.precision(oldprc);
833                                                   991 
834   return os;                                      992   return os;
835 }                                                 993 }
836                                                   994 
837 //////////////////////////////////////////////    995 /////////////////////////////////////////////////////////////////////////
838 //                                                996 //
839 // Return random point on the surface of the s << 997 // GetPointOnSurface
840                                                << 998 //
                                                   >> 999 // returns quasi-uniformly distributed point on surface of elliptical cone
                                                   >> 1000 //
841 G4ThreeVector G4EllipticalCone::GetPointOnSurf    1001 G4ThreeVector G4EllipticalCone::GetPointOnSurface() const
842 {                                                 1002 {
843   G4double x0 = xSemiAxis*zheight; // x semi a << 
844   G4double y0 = ySemiAxis*zheight; // y semi a << 
845   G4double s0 = G4GeomTools::EllipticConeLater << 
846   G4double kmin = (zTopCut >= zheight ) ? 0. : << 
847   G4double kmax = (zTopCut >= zheight ) ? 2. : << 
848                                                << 
849   // Set areas (base at -Z, side surface, base << 
850   //                                           << 
851   G4double szmin =  pi*x0*y0*kmax*kmax;        << 
852   G4double szmax =  pi*x0*y0*kmin*kmin;        << 
853   G4double sside =  s0*(kmax*kmax - kmin*kmin) << 
854   G4double ssurf[3] = { szmin, sside, szmax }; << 
855   for (auto i=1; i<3; ++i) { ssurf[i] += ssurf << 
856                                                   1003 
857   // Select surface                            << 1004   G4double phi, sinphi, cosphi, aOne, aTwo, aThree,
858   //                                           << 1005            chose, zRand, rRand1, rRand2;
859   G4double select = ssurf[2]*G4UniformRand();  << 1006   
860   G4int k = 2;                                 << 1007   G4double rOne = std::sqrt(sqr(xSemiAxis)
861   if (select <= ssurf[1]) k = 1;               << 1008                 + sqr(ySemiAxis))*(zheight - zTopCut);
862   if (select <= ssurf[0]) k = 0;               << 1009   G4double rTwo = std::sqrt(sqr(xSemiAxis)
                                                   >> 1010                 + sqr(ySemiAxis))*(zheight + zTopCut);
                                                   >> 1011   
                                                   >> 1012   aOne   = pi*(rOne + rTwo)*std::sqrt(sqr(rOne - rTwo)+sqr(2.*zTopCut));
                                                   >> 1013   aTwo   = pi*xSemiAxis*ySemiAxis*sqr(zheight+zTopCut);
                                                   >> 1014   aThree = pi*xSemiAxis*ySemiAxis*sqr(zheight-zTopCut);  
                                                   >> 1015 
                                                   >> 1016   phi = RandFlat::shoot(0.,twopi);
                                                   >> 1017   cosphi = std::cos(phi);
                                                   >> 1018   sinphi = std::sin(phi);
                                                   >> 1019   
                                                   >> 1020   if(zTopCut >= zheight) aThree = 0.;
863                                                   1021 
864   // Pick random point on selected surface     << 1022   chose = RandFlat::shoot(0.,aOne+aTwo+aThree);
865   //                                           << 1023   if((chose>=0.) && (chose<aOne))
866   G4ThreeVector p;                             << 
867   switch(k)                                    << 
868   {                                               1024   {
869     case 0: // base at -Z, uniform distributio << 1025     zRand = RandFlat::shoot(-zTopCut,zTopCut);
870     {                                          << 1026     return G4ThreeVector(xSemiAxis*(zheight-zRand)*cosphi,
871       G4double zh = zheight + zTopCut;         << 1027                          ySemiAxis*(zheight-zRand)*sinphi,zRand);    
872       G4TwoVector rho = G4RandomPointInEllipse << 1028   }
873       p.set(rho.x(),rho.y(),-zTopCut);         << 1029   else if((chose>=aOne) && (chose<aOne+aTwo))
874       break;                                   << 1030   {
875     }                                          << 1031     do
876     case 1: // side surface, uniform distribut << 
877     {                                             1032     {
878       G4double zh = G4RandomRadiusInRing(zheig << 1033       rRand1 = RandFlat::shoot(0.,1.) ;
879       G4double a = x0;                         << 1034       rRand2 = RandFlat::shoot(0.,1.) ;
880       G4double b = y0;                         << 1035     } while ( rRand2 >= rRand1  ) ;
881                                                   1036 
882       G4double hh = zheight*zheight;           << 1037     //    rRand2 = RandFlat::shoot(0.,std::sqrt(1.-sqr(rRand1)));
883       G4double aa = a*a;                       << 1038     return G4ThreeVector(rRand1*xSemiAxis*(zheight+zTopCut)*cosphi,
884       G4double bb = b*b;                       << 1039                          rRand1*ySemiAxis*(zheight+zTopCut)*sinphi, -zTopCut);
885       G4double R  = std::max(a,b);             << 
886       G4double mu_max = R*std::sqrt(hh + R*R); << 
887                                                   1040 
888       G4double x,y;                            << 
889       for (auto i=0; i<1000; ++i)              << 
890       {                                        << 
891   G4double phi = CLHEP::twopi*G4UniformRand(); << 
892         x = std::cos(phi);                     << 
893         y = std::sin(phi);                     << 
894         G4double xx = x*x;                     << 
895         G4double yy = y*y;                     << 
896         G4double E = hh + aa*xx + bb*yy;       << 
897         G4double F = (aa-bb)*x*y;              << 
898         G4double G = aa*yy + bb*xx;            << 
899         G4double mu = std::sqrt(E*G - F*F);    << 
900         if (mu_max*G4UniformRand() <= mu) brea << 
901       }                                        << 
902       p.set(zh*xSemiAxis*x,zh*ySemiAxis*y,zhei << 
903       break;                                   << 
904     }                                          << 
905     case 2: // base at +Z, uniform distributio << 
906     {                                          << 
907       G4double zh = zheight - zTopCut;         << 
908       G4TwoVector rho = G4RandomPointInEllipse << 
909       p.set(rho.x(),rho.y(),zTopCut);          << 
910       break;                                   << 
911     }                                          << 
912   }                                               1041   }
913   return p;                                    << 1042   // else
914 }                                              << 1043   //
915                                                << 
916 ////////////////////////////////////////////// << 
917 //                                             << 
918 // Get cubic volume                            << 
919                                                   1044 
920 G4double G4EllipticalCone::GetCubicVolume()    << 1045   do
921 {                                              << 
922   if (fCubicVolume == 0.0)                     << 
923   {                                               1046   {
924     G4double x0 = xSemiAxis*zheight; // x semi << 1047     rRand1 = RandFlat::shoot(0.,1.) ;
925     G4double y0 = ySemiAxis*zheight; // y semi << 1048     rRand2 = RandFlat::shoot(0.,1.) ;
926     G4double v0 = CLHEP::pi*x0*y0*zheight/3.;  << 1049   } while ( rRand2 >= rRand1  ) ;
927     G4double kmin = (zTopCut >= zheight ) ? 0. << 
928     G4double kmax = (zTopCut >= zheight ) ? 2. << 
929     fCubicVolume = (kmax - kmin)*(kmax*kmax +  << 
930   }                                            << 
931   return fCubicVolume;                         << 
932 }                                              << 
933                                                   1050 
934 ////////////////////////////////////////////// << 1051   return G4ThreeVector(rRand1*xSemiAxis*(zheight-zTopCut)*cosphi,
935 //                                             << 1052                        rRand1*ySemiAxis*(zheight-zTopCut)*sinphi, zTopCut);
936 // Get surface area                            << 
937                                                << 
938 G4double G4EllipticalCone::GetSurfaceArea()    << 
939 {                                              << 
940   if (fSurfaceArea == 0.0)                     << 
941   {                                            << 
942     G4double x0 = xSemiAxis*zheight; // x semi << 
943     G4double y0 = ySemiAxis*zheight; // y semi << 
944     G4double s0 = G4GeomTools::EllipticConeLat << 
945     G4double kmin = (zTopCut >= zheight ) ? 0. << 
946     G4double kmax = (zTopCut >= zheight ) ? 2. << 
947     fSurfaceArea = (kmax - kmin)*(kmax + kmin) << 
948                  + CLHEP::pi*x0*y0*(kmin*kmin  << 
949   }                                            << 
950   return fSurfaceArea;                         << 
951 }                                                 1053 }
952                                                   1054 
953 ////////////////////////////////////////////// << 
954 //                                                1055 //
955 // Methods for visualisation                      1056 // Methods for visualisation
                                                   >> 1057 //
956                                                   1058 
957 void G4EllipticalCone::DescribeYourselfTo (G4V    1059 void G4EllipticalCone::DescribeYourselfTo (G4VGraphicsScene& scene) const
958 {                                                 1060 {
959   scene.AddSolid(*this);                          1061   scene.AddSolid(*this);
960 }                                                 1062 }
961                                                   1063 
962 G4VisExtent G4EllipticalCone::GetExtent() cons    1064 G4VisExtent G4EllipticalCone::GetExtent() const
963 {                                                 1065 {
964   // Define the sides of the box into which th    1066   // Define the sides of the box into which the solid instance would fit.
965   //                                              1067   //
966   G4ThreeVector pmin,pmax;                     << 1068   G4double maxDim;
967   BoundingLimits(pmin,pmax);                   << 1069   maxDim = xSemiAxis > ySemiAxis ? xSemiAxis : ySemiAxis;
968   return { pmin.x(), pmax.x(), pmin.y(), pmax. << 1070   maxDim = maxDim > zTopCut ? maxDim : zTopCut;
                                                   >> 1071   
                                                   >> 1072   return G4VisExtent (-maxDim, maxDim,
                                                   >> 1073                       -maxDim, maxDim,
                                                   >> 1074                       -maxDim, maxDim);
969 }                                                 1075 }
970                                                   1076 
971 G4Polyhedron* G4EllipticalCone::CreatePolyhedr    1077 G4Polyhedron* G4EllipticalCone::CreatePolyhedron () const
972 {                                                 1078 {
973   return new G4PolyhedronEllipticalCone(xSemiA    1079   return new G4PolyhedronEllipticalCone(xSemiAxis, ySemiAxis, zheight, zTopCut);
974 }                                                 1080 }
975                                                   1081 
976 G4Polyhedron* G4EllipticalCone::GetPolyhedron     1082 G4Polyhedron* G4EllipticalCone::GetPolyhedron () const
977 {                                                 1083 {
978   if ( (fpPolyhedron == nullptr)               << 1084   if ( (!fpPolyhedron)
979     || fRebuildPolyhedron                         1085     || fRebuildPolyhedron
980     || (fpPolyhedron->GetNumberOfRotationSteps    1086     || (fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
981         fpPolyhedron->GetNumberOfRotationSteps    1087         fpPolyhedron->GetNumberOfRotationSteps()) )
982     {                                             1088     {
983       G4AutoLock l(&polyhedronMutex);             1089       G4AutoLock l(&polyhedronMutex);
984       delete fpPolyhedron;                        1090       delete fpPolyhedron;
985       fpPolyhedron = CreatePolyhedron();          1091       fpPolyhedron = CreatePolyhedron();
986       fRebuildPolyhedron = false;                 1092       fRebuildPolyhedron = false;
987       l.unlock();                                 1093       l.unlock();
988     }                                             1094     }
989   return fpPolyhedron;                            1095   return fpPolyhedron;
990 }                                                 1096 }
991                                                << 
992 #endif // !defined(G4GEOM_USE_UELLIPTICALCONE) << 
993                                                   1097