Geant4 Cross Reference

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


  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 // G4GenericPolycone implementation                26 // G4GenericPolycone implementation
 27 //                                                 27 //
 28 // Authors: T.Nikitina, G.Cosmo - CERN             28 // Authors: T.Nikitina, G.Cosmo - CERN
 29 // -------------------------------------------     29 // --------------------------------------------------------------------
 30                                                    30 
 31 #include "G4GenericPolycone.hh"                    31 #include "G4GenericPolycone.hh"
 32                                                    32 
 33 #if !defined(G4GEOM_USE_UGENERICPOLYCONE)          33 #if !defined(G4GEOM_USE_UGENERICPOLYCONE)
 34                                                    34 
 35 #include "G4PolyconeSide.hh"                       35 #include "G4PolyconeSide.hh"
 36 #include "G4PolyPhiFace.hh"                        36 #include "G4PolyPhiFace.hh"
 37                                                    37 
 38 #include "G4GeomTools.hh"                          38 #include "G4GeomTools.hh"
 39 #include "G4VoxelLimits.hh"                        39 #include "G4VoxelLimits.hh"
 40 #include "G4AffineTransform.hh"                    40 #include "G4AffineTransform.hh"
 41 #include "G4BoundingEnvelope.hh"                   41 #include "G4BoundingEnvelope.hh"
 42                                                    42 
 43 #include "G4QuickRand.hh"                      <<  43 #include "Randomize.hh"
 44                                                    44 
 45 #include "G4Polyhedron.hh"                         45 #include "G4Polyhedron.hh"
 46 #include "G4EnclosingCylinder.hh"                  46 #include "G4EnclosingCylinder.hh"
 47 #include "G4ReduciblePolygon.hh"                   47 #include "G4ReduciblePolygon.hh"
 48 #include "G4VPVParameterisation.hh"                48 #include "G4VPVParameterisation.hh"
 49                                                    49 
 50 namespace                                      << 
 51 {                                              << 
 52   G4Mutex surface_elementsMutex = G4MUTEX_INIT << 
 53 }                                              << 
 54                                                << 
 55 using namespace CLHEP;                             50 using namespace CLHEP;
 56                                                    51 
 57 // Constructor (generic parameters)                52 // Constructor (generic parameters)
 58 //                                                 53 //
 59 G4GenericPolycone::G4GenericPolycone( const G4 <<  54 G4GenericPolycone::G4GenericPolycone( const G4String& name, 
 60                               G4double phiStar     55                               G4double phiStart,
 61                               G4double phiTota     56                               G4double phiTotal,
 62                               G4int    numRZ,      57                               G4int    numRZ,
 63                         const G4double r[],        58                         const G4double r[],
 64                         const G4double z[]   )     59                         const G4double z[]   )
 65   : G4VCSGfaceted( name )                          60   : G4VCSGfaceted( name )
 66 {                                              <<  61 { 
 67                                                <<  62   
 68   auto rz = new G4ReduciblePolygon( r, z, numR <<  63   G4ReduciblePolygon *rz = new G4ReduciblePolygon( r, z, numRZ );
 69                                                <<  64   
 70   Create( phiStart, phiTotal, rz );                65   Create( phiStart, phiTotal, rz );
 71                                                <<  66   
 72   // Set original_parameters struct for consis     67   // Set original_parameters struct for consistency
 73   //                                               68   //
 74   //SetOriginalParameters(rz);                     69   //SetOriginalParameters(rz);
 75                                                    70 
 76   delete rz;                                       71   delete rz;
 77 }                                                  72 }
 78                                                    73 
 79 // Create                                          74 // Create
 80 //                                                 75 //
 81 // Generic create routine, called by each cons     76 // Generic create routine, called by each constructor after
 82 // conversion of arguments                         77 // conversion of arguments
 83 //                                                 78 //
 84 void G4GenericPolycone::Create( G4double phiSt     79 void G4GenericPolycone::Create( G4double phiStart,
 85                                 G4double phiTo <<  80                          G4double phiTotal,
 86                                 G4ReduciblePol <<  81                          G4ReduciblePolygon *rz    )
 87 {                                                  82 {
 88   //                                               83   //
 89   // Perform checks of rz values                   84   // Perform checks of rz values
 90   //                                               85   //
 91   if (rz->Amin() < 0.0)                            86   if (rz->Amin() < 0.0)
 92   {                                                87   {
 93     std::ostringstream message;                    88     std::ostringstream message;
 94     message << "Illegal input parameters - " <     89     message << "Illegal input parameters - " << GetName() << G4endl
 95             << "        All R values must be >     90             << "        All R values must be >= 0 !";
 96     G4Exception("G4GenericPolycone::Create()",     91     G4Exception("G4GenericPolycone::Create()", "GeomSolids0002",
 97                 FatalErrorInArgument, message)     92                 FatalErrorInArgument, message);
 98   }                                                93   }
 99                                                <<  94     
100   G4double rzArea = rz->Area();                    95   G4double rzArea = rz->Area();
101   if (rzArea < -kCarTolerance)                     96   if (rzArea < -kCarTolerance)
102   {                                                97   {
103     rz->ReverseOrder();                            98     rz->ReverseOrder();
104   }                                                99   }
105   else if (rzArea < kCarTolerance)                100   else if (rzArea < kCarTolerance)
106   {                                               101   {
107     std::ostringstream message;                   102     std::ostringstream message;
108     message << "Illegal input parameters - " <    103     message << "Illegal input parameters - " << GetName() << G4endl
109             << "        R/Z cross section is z    104             << "        R/Z cross section is zero or near zero: " << rzArea;
110     G4Exception("G4GenericPolycone::Create()",    105     G4Exception("G4GenericPolycone::Create()", "GeomSolids0002",
111                 FatalErrorInArgument, message)    106                 FatalErrorInArgument, message);
112   }                                               107   }
113                                                << 108     
114   if ( (!rz->RemoveDuplicateVertices( kCarTole    109   if ( (!rz->RemoveDuplicateVertices( kCarTolerance ))
115     || (!rz->RemoveRedundantVertices( kCarTole << 110     || (!rz->RemoveRedundantVertices( kCarTolerance ))     ) 
116   {                                               111   {
117     std::ostringstream message;                   112     std::ostringstream message;
118     message << "Illegal input parameters - " <    113     message << "Illegal input parameters - " << GetName() << G4endl
119             << "        Too few unique R/Z val    114             << "        Too few unique R/Z values !";
120     G4Exception("G4GenericPolycone::Create()",    115     G4Exception("G4GenericPolycone::Create()", "GeomSolids0002",
121                 FatalErrorInArgument, message)    116                 FatalErrorInArgument, message);
122   }                                               117   }
123                                                   118 
124   if (rz->CrossesItself(1/kInfinity))          << 119   if (rz->CrossesItself(1/kInfinity)) 
125   {                                               120   {
126     std::ostringstream message;                   121     std::ostringstream message;
127     message << "Illegal input parameters - " <    122     message << "Illegal input parameters - " << GetName() << G4endl
128             << "        R/Z segments cross !";    123             << "        R/Z segments cross !";
129     G4Exception("G4GenericPolycone::Create()",    124     G4Exception("G4GenericPolycone::Create()", "GeomSolids0002",
130                 FatalErrorInArgument, message)    125                 FatalErrorInArgument, message);
131   }                                               126   }
132                                                   127 
133   numCorner = rz->NumVertices();                  128   numCorner = rz->NumVertices();
134                                                   129 
135   //                                              130   //
136   // Phi opening? Account for some possible ro    131   // Phi opening? Account for some possible roundoff, and interpret
137   // nonsense value as representing no phi ope    132   // nonsense value as representing no phi opening
138   //                                              133   //
139   if (phiTotal <= 0 || phiTotal > twopi-1E-10)    134   if (phiTotal <= 0 || phiTotal > twopi-1E-10)
140   {                                               135   {
141     phiIsOpen = false;                            136     phiIsOpen = false;
142     startPhi = 0;                                 137     startPhi = 0;
143     endPhi = twopi;                               138     endPhi = twopi;
144   }                                               139   }
145   else                                            140   else
146   {                                               141   {
147     phiIsOpen = true;                             142     phiIsOpen = true;
148                                                << 143     
149     //                                            144     //
150     // Convert phi into our convention            145     // Convert phi into our convention
151     //                                            146     //
152     startPhi = phiStart;                          147     startPhi = phiStart;
153     while( startPhi < 0 )    // Loop checking,    148     while( startPhi < 0 )    // Loop checking, 13.08.2015, G.Cosmo
154       startPhi += twopi;                          149       startPhi += twopi;
155                                                << 150     
156     endPhi = phiStart+phiTotal;                   151     endPhi = phiStart+phiTotal;
157     while( endPhi < startPhi )    // Loop chec    152     while( endPhi < startPhi )    // Loop checking, 13.08.2015, G.Cosmo
158       endPhi += twopi;                            153       endPhi += twopi;
159   }                                               154   }
160                                                << 155   
161   //                                              156   //
162   // Allocate corner array.                    << 157   // Allocate corner array. 
163   //                                              158   //
164   corners = new G4PolyconeSideRZ[numCorner];      159   corners = new G4PolyconeSideRZ[numCorner];
165                                                   160 
166   //                                              161   //
167   // Copy corners                                 162   // Copy corners
168   //                                              163   //
169   G4ReduciblePolygonIterator iterRZ(rz);          164   G4ReduciblePolygonIterator iterRZ(rz);
170                                                << 165   
171   G4PolyconeSideRZ* next = corners;               166   G4PolyconeSideRZ* next = corners;
172   iterRZ.Begin();                                 167   iterRZ.Begin();
173   do    // Loop checking, 13.08.2015, G.Cosmo     168   do    // Loop checking, 13.08.2015, G.Cosmo
174   {                                               169   {
175     next->r = iterRZ.GetA();                      170     next->r = iterRZ.GetA();
176     next->z = iterRZ.GetB();                      171     next->z = iterRZ.GetB();
177   } while( ++next, iterRZ.Next() );               172   } while( ++next, iterRZ.Next() );
178                                                << 173   
179   //                                              174   //
180   // Allocate face pointer array                  175   // Allocate face pointer array
181   //                                              176   //
182   numFace = phiIsOpen ? numCorner+2 : numCorne    177   numFace = phiIsOpen ? numCorner+2 : numCorner;
183   faces = new G4VCSGface*[numFace];               178   faces = new G4VCSGface*[numFace];
184                                                << 179   
185   //                                              180   //
186   // Construct conical faces                      181   // Construct conical faces
187   //                                              182   //
188   // But! Don't construct a face if both point    183   // But! Don't construct a face if both points are at zero radius!
189   //                                              184   //
190   G4PolyconeSideRZ *corner = corners,             185   G4PolyconeSideRZ *corner = corners,
191                    *prev = corners + numCorner    186                    *prev = corners + numCorner-1,
192                    *nextNext;                     187                    *nextNext;
193   G4VCSGface** face = faces;                      188   G4VCSGface** face = faces;
194   do    // Loop checking, 13.08.2015, G.Cosmo     189   do    // Loop checking, 13.08.2015, G.Cosmo
195   {                                               190   {
196     next = corner+1;                              191     next = corner+1;
197     if (next >= corners+numCorner) next = corn    192     if (next >= corners+numCorner) next = corners;
198     nextNext = next+1;                            193     nextNext = next+1;
199     if (nextNext >= corners+numCorner) nextNex    194     if (nextNext >= corners+numCorner) nextNext = corners;
200                                                << 195     
201     if (corner->r < 1/kInfinity && next->r < 1    196     if (corner->r < 1/kInfinity && next->r < 1/kInfinity) continue;
202                                                << 197     
203     //                                            198     //
204     // We must decide here if we can dare decl    199     // We must decide here if we can dare declare one of our faces
205     // as having a "valid" normal (i.e. allBeh    200     // as having a "valid" normal (i.e. allBehind = true). This
206     // is never possible if the face faces "in    201     // is never possible if the face faces "inward" in r.
207     //                                            202     //
208     G4bool allBehind;                             203     G4bool allBehind;
209     if (corner->z > next->z)                      204     if (corner->z > next->z)
210     {                                             205     {
211       allBehind = false;                          206       allBehind = false;
212     }                                             207     }
213     else                                          208     else
214     {                                             209     {
215       //                                          210       //
216       // Otherwise, it is only true if the lin    211       // Otherwise, it is only true if the line passing
217       // through the two points of the segment    212       // through the two points of the segment do not
218       // split the r/z cross section              213       // split the r/z cross section
219       //                                          214       //
220       allBehind = !rz->BisectedBy( corner->r,     215       allBehind = !rz->BisectedBy( corner->r, corner->z,
221                  next->r, next->z, kCarToleran    216                  next->r, next->z, kCarTolerance );
222     }                                             217     }
223                                                << 218     
224     *face++ = new G4PolyconeSide( prev, corner    219     *face++ = new G4PolyconeSide( prev, corner, next, nextNext,
225                 startPhi, endPhi-startPhi, phi    220                 startPhi, endPhi-startPhi, phiIsOpen, allBehind );
226   } while( prev=corner, corner=next, corner >     221   } while( prev=corner, corner=next, corner > corners );
227                                                << 222   
228   if (phiIsOpen)                                  223   if (phiIsOpen)
229   {                                               224   {
230     //                                            225     //
231     // Construct phi open edges                   226     // Construct phi open edges
232     //                                            227     //
233     *face++ = new G4PolyPhiFace( rz, startPhi,    228     *face++ = new G4PolyPhiFace( rz, startPhi, 0, endPhi  );
234     *face++ = new G4PolyPhiFace( rz, endPhi,      229     *face++ = new G4PolyPhiFace( rz, endPhi,   0, startPhi );
235   }                                               230   }
236                                                << 231   
237   //                                              232   //
238   // We might have dropped a face or two: reca    233   // We might have dropped a face or two: recalculate numFace
239   //                                              234   //
240   numFace = (G4int)(face-faces);               << 235   numFace = face-faces;
241                                                << 236   
242   //                                              237   //
243   // Make enclosingCylinder                       238   // Make enclosingCylinder
244   //                                              239   //
245   enclosingCylinder =                             240   enclosingCylinder =
246     new G4EnclosingCylinder( rz, phiIsOpen, ph    241     new G4EnclosingCylinder( rz, phiIsOpen, phiStart, phiTotal );
247 }                                                 242 }
248                                                   243 
249 // Fake default constructor - sets only member    244 // Fake default constructor - sets only member data and allocates memory
250 //                            for usage restri    245 //                            for usage restricted to object persistency.
251 //                                                246 //
252 G4GenericPolycone::G4GenericPolycone( __void__    247 G4GenericPolycone::G4GenericPolycone( __void__& a )
253   : G4VCSGfaceted(a), startPhi(0.), endPhi(0.)    248   : G4VCSGfaceted(a), startPhi(0.), endPhi(0.), numCorner(0)
254 {                                                 249 {
255 }                                                 250 }
256                                                   251 
257 // Destructor                                     252 // Destructor
258 //                                                253 //
259 G4GenericPolycone::~G4GenericPolycone()           254 G4GenericPolycone::~G4GenericPolycone()
260 {                                                 255 {
261   delete [] corners;                              256   delete [] corners;
262   delete enclosingCylinder;                       257   delete enclosingCylinder;
263   delete fElements;                            << 
264   delete fpPolyhedron;                         << 
265   corners = nullptr;                           << 
266   enclosingCylinder = nullptr;                 << 
267   fElements = nullptr;                         << 
268   fpPolyhedron = nullptr;                      << 
269 }                                                 258 }
270                                                   259 
271 // Copy constructor                               260 // Copy constructor
272 //                                                261 //
273 G4GenericPolycone::G4GenericPolycone( const G4    262 G4GenericPolycone::G4GenericPolycone( const G4GenericPolycone& source )
274   : G4VCSGfaceted( source )                       263   : G4VCSGfaceted( source )
275 {                                                 264 {
276   CopyStuff( source );                            265   CopyStuff( source );
277 }                                                 266 }
278                                                   267 
279 // Assignment operator                            268 // Assignment operator
280 //                                                269 //
281 G4GenericPolycone&                                270 G4GenericPolycone&
282 G4GenericPolycone::operator=( const G4GenericP    271 G4GenericPolycone::operator=( const G4GenericPolycone& source )
283 {                                                 272 {
284   if (this == &source) return *this;              273   if (this == &source) return *this;
285                                                << 274   
286   G4VCSGfaceted::operator=( source );             275   G4VCSGfaceted::operator=( source );
287                                                << 276   
288   delete [] corners;                              277   delete [] corners;
289   // if (original_parameters) delete original_    278   // if (original_parameters) delete original_parameters;
290                                                << 279   
291   delete enclosingCylinder;                       280   delete enclosingCylinder;
292                                                << 281   
293   CopyStuff( source );                            282   CopyStuff( source );
294                                                << 283   
295   return *this;                                   284   return *this;
296 }                                                 285 }
297                                                   286 
298 // CopyStuff                                      287 // CopyStuff
299 //                                                288 //
300 void G4GenericPolycone::CopyStuff( const G4Gen    289 void G4GenericPolycone::CopyStuff( const G4GenericPolycone& source )
301 {                                                 290 {
302   //                                              291   //
303   // Simple stuff                                 292   // Simple stuff
304   //                                              293   //
305   startPhi  = source.startPhi;                    294   startPhi  = source.startPhi;
306   endPhi    = source.endPhi;                      295   endPhi    = source.endPhi;
307   phiIsOpen = source.phiIsOpen;                   296   phiIsOpen = source.phiIsOpen;
308   numCorner = source.numCorner;                   297   numCorner = source.numCorner;
309                                                   298 
310   //                                              299   //
311   // The corner array                             300   // The corner array
312   //                                              301   //
313   corners = new G4PolyconeSideRZ[numCorner];      302   corners = new G4PolyconeSideRZ[numCorner];
314                                                << 303   
315   G4PolyconeSideRZ  *corn = corners,              304   G4PolyconeSideRZ  *corn = corners,
316         *sourceCorn = source.corners;             305         *sourceCorn = source.corners;
317   do    // Loop checking, 13.08.2015, G.Cosmo     306   do    // Loop checking, 13.08.2015, G.Cosmo
318   {                                               307   {
319     *corn = *sourceCorn;                          308     *corn = *sourceCorn;
320   } while( ++sourceCorn, ++corn < corners+numC    309   } while( ++sourceCorn, ++corn < corners+numCorner );
321                                                << 310   
322   //                                              311   //
323   // Enclosing cylinder                           312   // Enclosing cylinder
324   //                                              313   //
325   enclosingCylinder = new G4EnclosingCylinder(    314   enclosingCylinder = new G4EnclosingCylinder( *source.enclosingCylinder );
326                                                   315 
327   //                                           << 
328   // Surface elements                          << 
329   //                                           << 
330   delete fElements;                            << 
331   fElements = nullptr;                         << 
332                                                << 
333   // Polyhedron                                << 
334   //                                           << 
335   fRebuildPolyhedron = false;                     316   fRebuildPolyhedron = false;
336   delete fpPolyhedron;                         << 
337   fpPolyhedron = nullptr;                         317   fpPolyhedron = nullptr;
338 }                                                 318 }
339                                                   319 
340 // Reset                                          320 // Reset
341 //                                                321 //
342 G4bool G4GenericPolycone::Reset()                 322 G4bool G4GenericPolycone::Reset()
343 {                                                 323 {
344   std::ostringstream message;                     324   std::ostringstream message;
345   message << "Solid " << GetName() << " built     325   message << "Solid " << GetName() << " built using generic construct."
346           << G4endl << "Not applicable to the     326           << G4endl << "Not applicable to the generic construct !";
347   G4Exception("G4GenericPolycone::Reset()", "G    327   G4Exception("G4GenericPolycone::Reset()", "GeomSolids1001",
348               JustWarning, message, "Parameter    328               JustWarning, message, "Parameters NOT resetted.");
349   return true;                                    329   return true;
350 }                                                 330 }
351                                                   331 
352 // Inside                                         332 // Inside
353 //                                                333 //
354 // This is an override of G4VCSGfaceted::Insid    334 // This is an override of G4VCSGfaceted::Inside, created in order
355 // to speed things up by first checking with G    335 // to speed things up by first checking with G4EnclosingCylinder.
356 //                                                336 //
357 EInside G4GenericPolycone::Inside( const G4Thr    337 EInside G4GenericPolycone::Inside( const G4ThreeVector& p ) const
358 {                                                 338 {
359   //                                              339   //
360   // Quick test                                   340   // Quick test
361   //                                              341   //
362   if (enclosingCylinder->MustBeOutside(p)) ret    342   if (enclosingCylinder->MustBeOutside(p)) return kOutside;
363                                                   343 
364   //                                              344   //
365   // Long answer                                  345   // Long answer
366   //                                              346   //
367   return G4VCSGfaceted::Inside(p);                347   return G4VCSGfaceted::Inside(p);
368 }                                                 348 }
369                                                   349 
370 // DistanceToIn                                   350 // DistanceToIn
371 //                                                351 //
372 // This is an override of G4VCSGfaceted::Insid    352 // This is an override of G4VCSGfaceted::Inside, created in order
373 // to speed things up by first checking with G    353 // to speed things up by first checking with G4EnclosingCylinder.
374 //                                                354 //
375 G4double G4GenericPolycone::DistanceToIn( cons    355 G4double G4GenericPolycone::DistanceToIn( const G4ThreeVector& p,
376                                           cons    356                                           const G4ThreeVector& v ) const
377 {                                                 357 {
378   //                                              358   //
379   // Quick test                                   359   // Quick test
380   //                                              360   //
381   if (enclosingCylinder->ShouldMiss(p,v))         361   if (enclosingCylinder->ShouldMiss(p,v))
382     return kInfinity;                             362     return kInfinity;
383                                                << 363   
384   //                                              364   //
385   // Long answer                                  365   // Long answer
386   //                                              366   //
387   return G4VCSGfaceted::DistanceToIn( p, v );     367   return G4VCSGfaceted::DistanceToIn( p, v );
388 }                                                 368 }
389                                                   369 
390 // DistanceToIn                                   370 // DistanceToIn
391 //                                                371 //
392 G4double G4GenericPolycone::DistanceToIn( cons    372 G4double G4GenericPolycone::DistanceToIn( const G4ThreeVector& p ) const
393 {                                                 373 {
394   return G4VCSGfaceted::DistanceToIn(p);          374   return G4VCSGfaceted::DistanceToIn(p);
395 }                                                 375 }
396                                                   376 
397 // BoundingLimits                                 377 // BoundingLimits
398 //                                                378 //
399 // Get bounding box                               379 // Get bounding box
400 //                                                380 //
401 void                                              381 void
402 G4GenericPolycone::BoundingLimits(G4ThreeVecto    382 G4GenericPolycone::BoundingLimits(G4ThreeVector& pMin,
403                                   G4ThreeVecto    383                                   G4ThreeVector& pMax) const
404 {                                                 384 {
405   G4double rmin = kInfinity, rmax = -kInfinity    385   G4double rmin = kInfinity, rmax = -kInfinity;
406   G4double zmin = kInfinity, zmax = -kInfinity    386   G4double zmin = kInfinity, zmax = -kInfinity;
407                                                   387 
408   for (G4int i=0; i<GetNumRZCorner(); ++i)        388   for (G4int i=0; i<GetNumRZCorner(); ++i)
409   {                                               389   {
410     G4PolyconeSideRZ corner = GetCorner(i);       390     G4PolyconeSideRZ corner = GetCorner(i);
411     if (corner.r < rmin) rmin = corner.r;         391     if (corner.r < rmin) rmin = corner.r;
412     if (corner.r > rmax) rmax = corner.r;         392     if (corner.r > rmax) rmax = corner.r;
413     if (corner.z < zmin) zmin = corner.z;         393     if (corner.z < zmin) zmin = corner.z;
414     if (corner.z > zmax) zmax = corner.z;         394     if (corner.z > zmax) zmax = corner.z;
415   }                                               395   }
416                                                   396 
417   if (IsOpen())                                   397   if (IsOpen())
418   {                                               398   {
419     G4TwoVector vmin,vmax;                        399     G4TwoVector vmin,vmax;
420     G4GeomTools::DiskExtent(rmin,rmax,            400     G4GeomTools::DiskExtent(rmin,rmax,
421                             GetSinStartPhi(),G    401                             GetSinStartPhi(),GetCosStartPhi(),
422                             GetSinEndPhi(),Get    402                             GetSinEndPhi(),GetCosEndPhi(),
423                             vmin,vmax);           403                             vmin,vmax);
424     pMin.set(vmin.x(),vmin.y(),zmin);             404     pMin.set(vmin.x(),vmin.y(),zmin);
425     pMax.set(vmax.x(),vmax.y(),zmax);             405     pMax.set(vmax.x(),vmax.y(),zmax);
426   }                                               406   }
427   else                                            407   else
428   {                                               408   {
429     pMin.set(-rmax,-rmax, zmin);                  409     pMin.set(-rmax,-rmax, zmin);
430     pMax.set( rmax, rmax, zmax);                  410     pMax.set( rmax, rmax, zmax);
431   }                                               411   }
432                                                   412 
433   // Check correctness of the bounding box        413   // Check correctness of the bounding box
434   //                                              414   //
435   if (pMin.x() >= pMax.x() || pMin.y() >= pMax    415   if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
436   {                                               416   {
437     std::ostringstream message;                   417     std::ostringstream message;
438     message << "Bad bounding box (min >= max)     418     message << "Bad bounding box (min >= max) for solid: "
439             << GetName() << " !"                  419             << GetName() << " !"
440             << "\npMin = " << pMin                420             << "\npMin = " << pMin
441             << "\npMax = " << pMax;               421             << "\npMax = " << pMax;
442     G4Exception("GenericG4Polycone::BoundingLi    422     G4Exception("GenericG4Polycone::BoundingLimits()", "GeomMgt0001",
443                 JustWarning, message);            423                 JustWarning, message);
444     DumpInfo();                                   424     DumpInfo();
445   }                                               425   }
446 }                                                 426 }
447                                                   427 
448 // CalculateExtent                                428 // CalculateExtent
449 //                                                429 //
450 // Calculate extent under transform and specif    430 // Calculate extent under transform and specified limit
451 //                                                431 //
452 G4bool                                            432 G4bool
453 G4GenericPolycone::CalculateExtent(const EAxis    433 G4GenericPolycone::CalculateExtent(const EAxis pAxis,
454                                    const G4Vox    434                                    const G4VoxelLimits& pVoxelLimit,
455                                    const G4Aff    435                                    const G4AffineTransform& pTransform,
456                                          G4dou    436                                          G4double& pMin, G4double& pMax) const
457 {                                                 437 {
458   G4ThreeVector bmin, bmax;                       438   G4ThreeVector bmin, bmax;
459   G4bool exist;                                   439   G4bool exist;
460                                                   440 
461   // Check bounding box (bbox)                    441   // Check bounding box (bbox)
462   //                                              442   //
463   BoundingLimits(bmin,bmax);                      443   BoundingLimits(bmin,bmax);
464   G4BoundingEnvelope bbox(bmin,bmax);             444   G4BoundingEnvelope bbox(bmin,bmax);
465 #ifdef G4BBOX_EXTENT                              445 #ifdef G4BBOX_EXTENT
466   return bbox.CalculateExtent(pAxis,pVoxelLimi    446   return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
467 #endif                                            447 #endif
468   if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox    448   if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
469   {                                               449   {
470     return exist = pMin < pMax;                << 450     return exist = (pMin < pMax) ? true : false;
471   }                                               451   }
472                                                   452 
473   // To find the extent, RZ contour of the pol    453   // To find the extent, RZ contour of the polycone is subdivided
474   // in triangles. The extent is calculated as    454   // in triangles. The extent is calculated as cumulative extent of
475   // all sub-polycones formed by rotation of t    455   // all sub-polycones formed by rotation of triangles around Z
476   //                                              456   //
477   G4TwoVectorList contourRZ;                      457   G4TwoVectorList contourRZ;
478   G4TwoVectorList triangles;                      458   G4TwoVectorList triangles;
479   G4double eminlim = pVoxelLimit.GetMinExtent(    459   G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
480   G4double emaxlim = pVoxelLimit.GetMaxExtent(    460   G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
481                                                   461 
482   // get RZ contour, ensure anticlockwise orde    462   // get RZ contour, ensure anticlockwise order of corners
483   for (G4int i=0; i<GetNumRZCorner(); ++i)        463   for (G4int i=0; i<GetNumRZCorner(); ++i)
484   {                                               464   {
485     G4PolyconeSideRZ corner = GetCorner(i);       465     G4PolyconeSideRZ corner = GetCorner(i);
486     contourRZ.emplace_back(corner.r,corner.z); << 466     contourRZ.push_back(G4TwoVector(corner.r,corner.z));
487   }                                               467   }
488   G4double area = G4GeomTools::PolygonArea(con    468   G4double area = G4GeomTools::PolygonArea(contourRZ);
489   if (area < 0.) std::reverse(contourRZ.begin(    469   if (area < 0.) std::reverse(contourRZ.begin(),contourRZ.end());
490                                                   470 
491   // triangulate RZ countour                      471   // triangulate RZ countour
492   if (!G4GeomTools::TriangulatePolygon(contour    472   if (!G4GeomTools::TriangulatePolygon(contourRZ,triangles))
493   {                                               473   {
494     std::ostringstream message;                   474     std::ostringstream message;
495     message << "Triangulation of RZ contour ha    475     message << "Triangulation of RZ contour has failed for solid: "
496             << GetName() << " !"                  476             << GetName() << " !"
497             << "\nExtent has been calculated u    477             << "\nExtent has been calculated using boundary box";
498     G4Exception("G4GenericPolycone::CalculateE    478     G4Exception("G4GenericPolycone::CalculateExtent()",
499                 "GeomMgt1002", JustWarning, me    479                 "GeomMgt1002", JustWarning, message);
500     return bbox.CalculateExtent(pAxis,pVoxelLi    480     return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
501   }                                               481   }
502                                                   482 
503   // set trigonometric values                     483   // set trigonometric values
504   const G4int NSTEPS = 24;            // numbe    484   const G4int NSTEPS = 24;            // number of steps for whole circle
505   G4double astep  = twopi/NSTEPS;     // max a    485   G4double astep  = twopi/NSTEPS;     // max angle for one step
506                                                   486 
507   G4double sphi   = GetStartPhi();                487   G4double sphi   = GetStartPhi();
508   G4double ephi   = GetEndPhi();                  488   G4double ephi   = GetEndPhi();
509   G4double dphi   = IsOpen() ? ephi-sphi : two    489   G4double dphi   = IsOpen() ? ephi-sphi : twopi;
510   G4int    ksteps = (dphi <= astep) ? 1 : (G4i    490   G4int    ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
511   G4double ang    = dphi/ksteps;                  491   G4double ang    = dphi/ksteps;
512                                                   492 
513   G4double sinHalf = std::sin(0.5*ang);           493   G4double sinHalf = std::sin(0.5*ang);
514   G4double cosHalf = std::cos(0.5*ang);           494   G4double cosHalf = std::cos(0.5*ang);
515   G4double sinStep = 2.*sinHalf*cosHalf;          495   G4double sinStep = 2.*sinHalf*cosHalf;
516   G4double cosStep = 1. - 2.*sinHalf*sinHalf;     496   G4double cosStep = 1. - 2.*sinHalf*sinHalf;
517                                                   497 
518   G4double sinStart = GetSinStartPhi();           498   G4double sinStart = GetSinStartPhi();
519   G4double cosStart = GetCosStartPhi();           499   G4double cosStart = GetCosStartPhi();
520   G4double sinEnd   = GetSinEndPhi();             500   G4double sinEnd   = GetSinEndPhi();
521   G4double cosEnd   = GetCosEndPhi();             501   G4double cosEnd   = GetCosEndPhi();
522                                                   502 
523   // define vectors and arrays                    503   // define vectors and arrays
524   std::vector<const G4ThreeVectorList *> polyg    504   std::vector<const G4ThreeVectorList *> polygons;
525   polygons.resize(ksteps+2);                      505   polygons.resize(ksteps+2);
526   G4ThreeVectorList pols[NSTEPS+2];               506   G4ThreeVectorList pols[NSTEPS+2];
527   for (G4int k=0; k<ksteps+2; ++k) pols[k].res    507   for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(6);
528   for (G4int k=0; k<ksteps+2; ++k) polygons[k]    508   for (G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
529   G4double r0[6],z0[6]; // contour with origin    509   G4double r0[6],z0[6]; // contour with original edges of triangle
530   G4double r1[6];       // shifted radii of ex    510   G4double r1[6];       // shifted radii of external edges of triangle
531                                                   511 
532   // main loop along triangles                    512   // main loop along triangles
533   pMin = kInfinity;                               513   pMin = kInfinity;
534   pMax =-kInfinity;                               514   pMax =-kInfinity;
535   G4int ntria = (G4int)triangles.size()/3;     << 515   G4int ntria = triangles.size()/3;
536   for (G4int i=0; i<ntria; ++i)                   516   for (G4int i=0; i<ntria; ++i)
537   {                                               517   {
538     G4int i3 = i*3;                               518     G4int i3 = i*3;
539     for (G4int k=0; k<3; ++k)                     519     for (G4int k=0; k<3; ++k)
540     {                                             520     {
541       G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3;    521       G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3;
542       G4int k2 = k*2;                             522       G4int k2 = k*2;
543       // set contour with original edges of tr    523       // set contour with original edges of triangle
544       r0[k2+0] = triangles[e0].x(); z0[k2+0] =    524       r0[k2+0] = triangles[e0].x(); z0[k2+0] = triangles[e0].y();
545       r0[k2+1] = triangles[e1].x(); z0[k2+1] =    525       r0[k2+1] = triangles[e1].x(); z0[k2+1] = triangles[e1].y();
546       // set shifted radii                        526       // set shifted radii
547       r1[k2+0] = r0[k2+0];                        527       r1[k2+0] = r0[k2+0];
548       r1[k2+1] = r0[k2+1];                        528       r1[k2+1] = r0[k2+1];
549       if (z0[k2+1] - z0[k2+0] <= 0) continue;     529       if (z0[k2+1] - z0[k2+0] <= 0) continue;
550       r1[k2+0] /= cosHalf;                        530       r1[k2+0] /= cosHalf;
551       r1[k2+1] /= cosHalf;                        531       r1[k2+1] /= cosHalf;
552     }                                             532     }
553                                                   533 
554     // rotate countour, set sequence of 6-side    534     // rotate countour, set sequence of 6-sided polygons
555     G4double sinCur = sinStart*cosHalf + cosSt    535     G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
556     G4double cosCur = cosStart*cosHalf - sinSt    536     G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
557     for (G4int j=0; j<6; ++j)                     537     for (G4int j=0; j<6; ++j)
558     {                                             538     {
559       pols[0][j].set(r0[j]*cosStart,r0[j]*sinS    539       pols[0][j].set(r0[j]*cosStart,r0[j]*sinStart,z0[j]);
560     }                                             540     }
561     for (G4int k=1; k<ksteps+1; ++k)              541     for (G4int k=1; k<ksteps+1; ++k)
562     {                                             542     {
563       for (G4int j=0; j<6; ++j)                   543       for (G4int j=0; j<6; ++j)
564       {                                           544       {
565         pols[k][j].set(r1[j]*cosCur,r1[j]*sinC    545         pols[k][j].set(r1[j]*cosCur,r1[j]*sinCur,z0[j]);
566       }                                           546       }
567       G4double sinTmp = sinCur;                   547       G4double sinTmp = sinCur;
568       sinCur = sinCur*cosStep + cosCur*sinStep    548       sinCur = sinCur*cosStep + cosCur*sinStep;
569       cosCur = cosCur*cosStep - sinTmp*sinStep    549       cosCur = cosCur*cosStep - sinTmp*sinStep;
570     }                                             550     }
571     for (G4int j=0; j<6; ++j)                     551     for (G4int j=0; j<6; ++j)
572     {                                             552     {
573       pols[ksteps+1][j].set(r0[j]*cosEnd,r0[j]    553       pols[ksteps+1][j].set(r0[j]*cosEnd,r0[j]*sinEnd,z0[j]);
574     }                                             554     }
575                                                   555 
576     // set sub-envelope and adjust extent         556     // set sub-envelope and adjust extent
577     G4double emin,emax;                           557     G4double emin,emax;
578     G4BoundingEnvelope benv(polygons);            558     G4BoundingEnvelope benv(polygons);
579     if (!benv.CalculateExtent(pAxis,pVoxelLimi    559     if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
580     if (emin < pMin) pMin = emin;                 560     if (emin < pMin) pMin = emin;
581     if (emax > pMax) pMax = emax;                 561     if (emax > pMax) pMax = emax;
582     if (eminlim > pMin && emaxlim < pMax) retu    562     if (eminlim > pMin && emaxlim < pMax) return true; // max possible extent
583   }                                               563   }
584   return (pMin < pMax);                           564   return (pMin < pMax);
585 }                                                 565 }
586                                                   566 
587 // GetEntityType                                  567 // GetEntityType
588 //                                                568 //
589 G4GeometryType  G4GenericPolycone::GetEntityTy    569 G4GeometryType  G4GenericPolycone::GetEntityType() const
590 {                                                 570 {
591   return {"G4GenericPolycone"};                << 571   return G4String("G4GenericPolycone");
592 }                                                 572 }
593                                                   573 
594 // Clone                                          574 // Clone
595 //                                                575 //
596 // Make a clone of the object                     576 // Make a clone of the object
597 //                                                577 //
598 G4VSolid* G4GenericPolycone::Clone() const        578 G4VSolid* G4GenericPolycone::Clone() const
599 {                                                 579 {
600   return new G4GenericPolycone(*this);            580   return new G4GenericPolycone(*this);
601 }                                                 581 }
602                                                   582 
603 // StreamInfo                                     583 // StreamInfo
604 //                                                584 //
605 // Stream object contents to an output stream     585 // Stream object contents to an output stream
606 //                                                586 //
607 std::ostream& G4GenericPolycone::StreamInfo( s    587 std::ostream& G4GenericPolycone::StreamInfo( std::ostream& os ) const
608 {                                                 588 {
609   G4long oldprc = os.precision(16);            << 589   G4int oldprc = os.precision(16);
610   os << "-------------------------------------    590   os << "-----------------------------------------------------------\n"
611      << "    *** Dump for solid - " << GetName    591      << "    *** Dump for solid - " << GetName() << " ***\n"
612      << "    =================================    592      << "    ===================================================\n"
613      << " Solid type: G4GenericPolycone\n"        593      << " Solid type: G4GenericPolycone\n"
614      << " Parameters: \n"                         594      << " Parameters: \n"
615      << "    starting phi angle : " << startPh    595      << "    starting phi angle : " << startPhi/degree << " degrees \n"
616      << "    ending phi angle   : " << endPhi/    596      << "    ending phi angle   : " << endPhi/degree << " degrees \n";
617   G4int i=0;                                      597   G4int i=0;
618                                                << 598  
619   os << "    number of RZ points: " << numCorn    599   os << "    number of RZ points: " << numCorner << "\n"
620      << "              RZ values (corners): \n    600      << "              RZ values (corners): \n";
621      for (i=0; i<numCorner; i++)                  601      for (i=0; i<numCorner; i++)
622      {                                            602      {
623        os << "                         "          603        os << "                         "
624           << corners[i].r << ", " << corners[i    604           << corners[i].r << ", " << corners[i].z << "\n";
625      }                                            605      }
626   os << "-------------------------------------    606   os << "-----------------------------------------------------------\n";
627   os.precision(oldprc);                           607   os.precision(oldprc);
628                                                   608 
629   return os;                                      609   return os;
630 }                                                 610 }
631                                                   611 
632 ////////////////////////////////////////////// << 612 // GetPointOnSurface
633 //                                                613 //
634 // Return volume                               << 614 G4ThreeVector G4GenericPolycone::GetPointOnSurface() const
635                                                << 
636 G4double G4GenericPolycone::GetCubicVolume()   << 
637 {                                                 615 {
638   if (fCubicVolume == 0.)                      << 616   return GetPointOnSurfaceGeneric();  
639   {                                            << 617 
640     G4double total = 0.;                       << 
641     G4int nrz = GetNumRZCorner();              << 
642     G4PolyconeSideRZ a = GetCorner(nrz - 1);   << 
643     for (G4int i=0; i<nrz; ++i)                << 
644     {                                          << 
645       G4PolyconeSideRZ b = GetCorner(i);       << 
646       total += (b.r*b.r + b.r*a.r + a.r*a.r)*( << 
647       a = b;                                   << 
648     }                                          << 
649     fCubicVolume = std::abs(total)*(GetEndPhi( << 
650   }                                            << 
651   return fCubicVolume;                         << 
652 }                                                 618 }
653                                                   619 
654 ////////////////////////////////////////////// << 620 // CreatePolyhedron
655 //                                                621 //
656 // Return surface area                         << 622 G4Polyhedron* G4GenericPolycone::CreatePolyhedron() const
657                                                << 623 { 
658 G4double G4GenericPolycone::GetSurfaceArea()   << 624     // The following code prepares for:
659 {                                              << 625     // HepPolyhedron::createPolyhedron(int Nnodes, int Nfaces,
660   if (fSurfaceArea == 0.)                      << 626     //                                  const double xyz[][3],
661   {                                            << 627     //                                  const int faces_vec[][4])
662     // phi cut area                            << 628     // Here is an extract from the header file HepPolyhedron.h:
663     G4int nrz = GetNumRZCorner();              << 629     /**
664     G4double scut = 0.;                        << 630      * Creates user defined polyhedron.
665     if (IsOpen())                              << 631      * This function allows to the user to define arbitrary polyhedron.
                                                   >> 632      * The faces of the polyhedron should be either triangles or planar
                                                   >> 633      * quadrilateral. Nodes of a face are defined by indexes pointing to
                                                   >> 634      * the elements in the xyz array. Numeration of the elements in the
                                                   >> 635      * array starts from 1 (like in fortran). The indexes can be positive
                                                   >> 636      * or negative. Negative sign means that the corresponding edge is
                                                   >> 637      * invisible. The normal of the face should be directed to exterior
                                                   >> 638      * of the polyhedron. 
                                                   >> 639      * 
                                                   >> 640      * @param  Nnodes number of nodes
                                                   >> 641      * @param  Nfaces number of faces
                                                   >> 642      * @param  xyz    nodes
                                                   >> 643      * @param  faces_vec  faces (quadrilaterals or triangles)
                                                   >> 644      * @return status of the operation - is non-zero in case of problem
                                                   >> 645      */
                                                   >> 646     const G4int numSide =
                                                   >> 647           G4int(G4Polyhedron::GetNumberOfRotationSteps()
                                                   >> 648                 * (endPhi - startPhi) / twopi) + 1;
                                                   >> 649     G4int nNodes;
                                                   >> 650     G4int nFaces;
                                                   >> 651     typedef G4double double3[3];
                                                   >> 652     double3* xyz;
                                                   >> 653     typedef G4int int4[4];
                                                   >> 654     int4* faces_vec;
                                                   >> 655     if (phiIsOpen)
666     {                                             656     {
667       G4PolyconeSideRZ a = GetCorner(nrz - 1); << 657       // Triangulate open ends. Simple ear-chopping algorithm...
668       for (G4int i=0; i<nrz; ++i)              << 658       // I'm not sure how robust this algorithm is (J.Allison).
                                                   >> 659       //
                                                   >> 660       std::vector<G4bool> chopped(numCorner, false);
                                                   >> 661       std::vector<G4int*> triQuads;
                                                   >> 662       G4int remaining = numCorner;
                                                   >> 663       G4int iStarter = 0;
                                                   >> 664       while (remaining >= 3)    // Loop checking, 13.08.2015, G.Cosmo
669       {                                           665       {
670         G4PolyconeSideRZ b = GetCorner(i);     << 666         // Find unchopped corners...
671         scut += a.r*b.z - a.z*b.r;             << 667         //
672         a = b;                                 << 668         G4int A = -1, B = -1, C = -1;
                                                   >> 669         G4int iStepper = iStarter;
                                                   >> 670         do    // Loop checking, 13.08.2015, G.Cosmo
                                                   >> 671         {
                                                   >> 672           if (A < 0)      { A = iStepper; }
                                                   >> 673           else if (B < 0) { B = iStepper; }
                                                   >> 674           else if (C < 0) { C = iStepper; }
                                                   >> 675           do    // Loop checking, 13.08.2015, G.Cosmo
                                                   >> 676           {
                                                   >> 677             if (++iStepper >= numCorner) { iStepper = 0; }
                                                   >> 678           }
                                                   >> 679           while (chopped[iStepper]);
                                                   >> 680         }
                                                   >> 681         while (C < 0 && iStepper != iStarter);
                                                   >> 682 
                                                   >> 683         // Check triangle at B is pointing outward (an "ear").
                                                   >> 684         // Sign of z cross product determines...
                                                   >> 685         //
                                                   >> 686         G4double BAr = corners[A].r - corners[B].r;
                                                   >> 687         G4double BAz = corners[A].z - corners[B].z;
                                                   >> 688         G4double BCr = corners[C].r - corners[B].r;
                                                   >> 689         G4double BCz = corners[C].z - corners[B].z;
                                                   >> 690         if (BAr * BCz - BAz * BCr < kCarTolerance)
                                                   >> 691         {
                                                   >> 692           G4int* tq = new G4int[3];
                                                   >> 693           tq[0] = A + 1;
                                                   >> 694           tq[1] = B + 1;
                                                   >> 695           tq[2] = C + 1;
                                                   >> 696           triQuads.push_back(tq);
                                                   >> 697           chopped[B] = true;
                                                   >> 698           --remaining;
                                                   >> 699         }
                                                   >> 700         else
                                                   >> 701         {
                                                   >> 702           do    // Loop checking, 13.08.2015, G.Cosmo
                                                   >> 703           {
                                                   >> 704             if (++iStarter >= numCorner) { iStarter = 0; }
                                                   >> 705           }
                                                   >> 706           while (chopped[iStarter]);
                                                   >> 707         }
                                                   >> 708       }
                                                   >> 709       // Transfer to faces...
                                                   >> 710       //
                                                   >> 711       nNodes = (numSide + 1) * numCorner;
                                                   >> 712       nFaces = numSide * numCorner + 2 * triQuads.size();
                                                   >> 713       faces_vec = new int4[nFaces];
                                                   >> 714       G4int iface = 0;
                                                   >> 715       G4int addition = numCorner * numSide;
                                                   >> 716       G4int d = numCorner - 1;
                                                   >> 717       for (G4int iEnd = 0; iEnd < 2; ++iEnd)
                                                   >> 718       {
                                                   >> 719         for (size_t i = 0; i < triQuads.size(); ++i)
                                                   >> 720         {
                                                   >> 721           // Negative for soft/auxiliary/normally invisible edges...
                                                   >> 722           //
                                                   >> 723           G4int a, b, c;
                                                   >> 724           if (iEnd == 0)
                                                   >> 725           {
                                                   >> 726             a = triQuads[i][0];
                                                   >> 727             b = triQuads[i][1];
                                                   >> 728             c = triQuads[i][2];
                                                   >> 729           }
                                                   >> 730           else
                                                   >> 731           {
                                                   >> 732             a = triQuads[i][0] + addition;
                                                   >> 733             b = triQuads[i][2] + addition;
                                                   >> 734             c = triQuads[i][1] + addition;
                                                   >> 735           }
                                                   >> 736           G4int ab = std::abs(b - a);
                                                   >> 737           G4int bc = std::abs(c - b);
                                                   >> 738           G4int ca = std::abs(a - c);
                                                   >> 739           faces_vec[iface][0] = (ab == 1 || ab == d)? a: -a;
                                                   >> 740           faces_vec[iface][1] = (bc == 1 || bc == d)? b: -b;
                                                   >> 741           faces_vec[iface][2] = (ca == 1 || ca == d)? c: -c;
                                                   >> 742           faces_vec[iface][3] = 0;
                                                   >> 743           ++iface;
                                                   >> 744         }
673       }                                           745       }
674       scut = std::abs(scut);                   << 
675     }                                          << 
676     // lateral surface area                    << 
677     G4double slat = 0;                         << 
678     G4PolyconeSideRZ a = GetCorner(nrz - 1);   << 
679     for (G4int i=0; i<nrz; ++i)                << 
680     {                                          << 
681       G4PolyconeSideRZ b = GetCorner(i);       << 
682       G4double h = std::sqrt((b.r - a.r)*(b.r  << 
683       slat += (b.r + a.r)*h;                   << 
684       a = b;                                   << 
685     }                                          << 
686     slat *= (GetEndPhi() - GetStartPhi())/2.;  << 
687     fSurfaceArea = scut + slat;                << 
688   }                                            << 
689   return fSurfaceArea;                         << 
690 }                                              << 
691                                                   746 
692 ////////////////////////////////////////////// << 747       // Continue with sides...
693 //                                             << 
694 // Set vector of surface elements, auxiliary m << 
695 // random points on surface                    << 
696                                                   748 
697 void G4GenericPolycone::SetSurfaceElements() c << 749       xyz = new double3[nNodes];
698 {                                              << 750       const G4double dPhi = (endPhi - startPhi) / numSide;
699   fElements = new std::vector<G4GenericPolycon << 751       G4double phi = startPhi;
700   G4double sarea = 0.;                         << 752       G4int ixyz = 0;
701   G4int nrz = GetNumRZCorner();                << 753       for (G4int iSide = 0; iSide < numSide; ++iSide)
                                                   >> 754       {
                                                   >> 755         for (G4int iCorner = 0; iCorner < numCorner; ++iCorner)
                                                   >> 756         {
                                                   >> 757           xyz[ixyz][0] = corners[iCorner].r * std::cos(phi);
                                                   >> 758           xyz[ixyz][1] = corners[iCorner].r * std::sin(phi);
                                                   >> 759           xyz[ixyz][2] = corners[iCorner].z;
                                                   >> 760           if (iSide == 0)   // startPhi
                                                   >> 761           {
                                                   >> 762             if (iCorner < numCorner - 1)
                                                   >> 763             {
                                                   >> 764               faces_vec[iface][0] = ixyz + 1;
                                                   >> 765               faces_vec[iface][1] = -(ixyz + numCorner + 1);
                                                   >> 766               faces_vec[iface][2] = ixyz + numCorner + 2;
                                                   >> 767               faces_vec[iface][3] = ixyz + 2;
                                                   >> 768             }
                                                   >> 769             else
                                                   >> 770             {
                                                   >> 771               faces_vec[iface][0] = ixyz + 1;
                                                   >> 772               faces_vec[iface][1] = -(ixyz + numCorner + 1);
                                                   >> 773               faces_vec[iface][2] = ixyz + 2;
                                                   >> 774               faces_vec[iface][3] = ixyz - numCorner + 2;
                                                   >> 775             }
                                                   >> 776           }
                                                   >> 777           else if (iSide == numSide - 1)   // endPhi
                                                   >> 778           {
                                                   >> 779             if (iCorner < numCorner - 1)
                                                   >> 780               {
                                                   >> 781                 faces_vec[iface][0] = ixyz + 1;
                                                   >> 782                 faces_vec[iface][1] = ixyz + numCorner + 1;
                                                   >> 783                 faces_vec[iface][2] = ixyz + numCorner + 2;
                                                   >> 784                 faces_vec[iface][3] = -(ixyz + 2);
                                                   >> 785               }
                                                   >> 786             else
                                                   >> 787               {
                                                   >> 788                 faces_vec[iface][0] = ixyz + 1;
                                                   >> 789                 faces_vec[iface][1] = ixyz + numCorner + 1;
                                                   >> 790                 faces_vec[iface][2] = ixyz + 2;
                                                   >> 791                 faces_vec[iface][3] = -(ixyz - numCorner + 2);
                                                   >> 792               }
                                                   >> 793           }
                                                   >> 794           else
                                                   >> 795           {
                                                   >> 796             if (iCorner < numCorner - 1)
                                                   >> 797               {
                                                   >> 798                 faces_vec[iface][0] = ixyz + 1;
                                                   >> 799                 faces_vec[iface][1] = -(ixyz + numCorner + 1);
                                                   >> 800                 faces_vec[iface][2] = ixyz + numCorner + 2;
                                                   >> 801                 faces_vec[iface][3] = -(ixyz + 2);
                                                   >> 802               }
                                                   >> 803               else
                                                   >> 804               {
                                                   >> 805                 faces_vec[iface][0] = ixyz + 1;
                                                   >> 806                 faces_vec[iface][1] = -(ixyz + numCorner + 1);
                                                   >> 807                 faces_vec[iface][2] = ixyz + 2;
                                                   >> 808                 faces_vec[iface][3] = -(ixyz - numCorner + 2);
                                                   >> 809               }
                                                   >> 810             }
                                                   >> 811             ++iface;
                                                   >> 812             ++ixyz;
                                                   >> 813         }
                                                   >> 814         phi += dPhi;
                                                   >> 815       }
702                                                   816 
703   // set lateral surface elements              << 817       // Last corners...
704   G4double dphi = GetEndPhi() - GetStartPhi(); << 
705   G4int ia = nrz - 1;                          << 
706   for (G4int ib=0; ib<nrz; ++ib)               << 
707   {                                            << 
708     G4PolyconeSideRZ a = GetCorner(ia);        << 
709     G4PolyconeSideRZ b = GetCorner(ib);        << 
710     G4GenericPolycone::surface_element selem;  << 
711     selem.i0 = ia;                             << 
712     selem.i1 = ib;                             << 
713     selem.i2 = -1;                             << 
714     ia = ib;                                   << 
715     if (a.r == 0. && b.r == 0.) continue;      << 
716     G4double h = std::sqrt((b.r - a.r)*(b.r -  << 
717     sarea += 0.5*dphi*(b.r + a.r)*h;           << 
718     selem.area = sarea;                        << 
719     fElements->push_back(selem);               << 
720   }                                            << 
721                                                   818 
722   // set elements for phi cuts                 << 819       for (G4int iCorner = 0; iCorner < numCorner; ++iCorner)
723   if (IsOpen())                                << 820       {
724   {                                            << 821         xyz[ixyz][0] = corners[iCorner].r * std::cos(phi);
725     G4TwoVectorList contourRZ;                 << 822         xyz[ixyz][1] = corners[iCorner].r * std::sin(phi);
726     std::vector<G4int> triangles;              << 823         xyz[ixyz][2] = corners[iCorner].z;
727     for (G4int i=0; i<nrz; ++i)                << 824         ++ixyz;
728     {                                          << 825       }
729       G4PolyconeSideRZ corner = GetCorner(i);  << 
730       contourRZ.emplace_back(corner.r, corner. << 
731     }                                             826     }
732     G4GeomTools::TriangulatePolygon(contourRZ, << 827     else  // !phiIsOpen - i.e., a complete 360 degrees.
733     auto  ntria = (G4int)triangles.size();     << 
734     for (G4int i=0; i<ntria; i+=3)             << 
735     {                                             828     {
736       G4GenericPolycone::surface_element selem << 829       nNodes = numSide * numCorner;
737       selem.i0 = triangles[i];                 << 830       nFaces = numSide * numCorner;;
738       selem.i1 = triangles[i+1];               << 831       xyz = new double3[nNodes];
739       selem.i2 = triangles[i+2];               << 832       faces_vec = new int4[nFaces];
740       G4PolyconeSideRZ a = GetCorner(selem.i0) << 833       const G4double dPhi = (endPhi - startPhi) / numSide;
741       G4PolyconeSideRZ b = GetCorner(selem.i1) << 834       G4double phi = startPhi;
742       G4PolyconeSideRZ c = GetCorner(selem.i2) << 835       G4int ixyz = 0, iface = 0;
743       G4double stria =                         << 836       for (G4int iSide = 0; iSide < numSide; ++iSide)
744         std::abs(G4GeomTools::TriangleArea(a.r << 837       {
745       sarea += stria;                          << 838         for (G4int iCorner = 0; iCorner < numCorner; ++iCorner)
746       selem.area = sarea;                      << 839         {
747       fElements->push_back(selem); // start ph << 840           xyz[ixyz][0] = corners[iCorner].r * std::cos(phi);
748       sarea += stria;                          << 841           xyz[ixyz][1] = corners[iCorner].r * std::sin(phi);
749       selem.area = sarea;                      << 842           xyz[ixyz][2] = corners[iCorner].z;
750       selem.i0 += nrz;                         << 843 
751       fElements->push_back(selem); // end phi  << 844           if (iSide < numSide - 1)
752     }                                          << 845           {
753   }                                            << 846             if (iCorner < numCorner - 1)
754 }                                              << 847             {
755                                                << 848               faces_vec[iface][0] = ixyz + 1;
756 ////////////////////////////////////////////// << 849               faces_vec[iface][1] = -(ixyz + numCorner + 1);
757 //                                             << 850               faces_vec[iface][2] = ixyz + numCorner + 2;
758 // Generate random point on surface            << 851               faces_vec[iface][3] = -(ixyz + 2);
759                                                << 852             }
760 G4ThreeVector G4GenericPolycone::GetPointOnSur << 853             else
761 {                                              << 854             {
762   // Set surface elements                      << 855               faces_vec[iface][0] = ixyz + 1;
763   if (fElements == nullptr)                    << 856               faces_vec[iface][1] = -(ixyz + numCorner + 1);
764   {                                            << 857               faces_vec[iface][2] = ixyz + 2;
765     G4AutoLock l(&surface_elementsMutex);      << 858               faces_vec[iface][3] = -(ixyz - numCorner + 2);
766     SetSurfaceElements();                      << 859             }
767     l.unlock();                                << 860           }
768   }                                            << 861           else   // Last side joins ends...
769                                                << 862           {
770   // Select surface element                    << 863             if (iCorner < numCorner - 1)
771   G4GenericPolycone::surface_element selem;    << 864             {
772   selem = fElements->back();                   << 865               faces_vec[iface][0] = ixyz + 1;
773   G4double select = selem.area*G4QuickRand();  << 866               faces_vec[iface][1] = -(ixyz + numCorner - nFaces + 1);
774   auto it = std::lower_bound(fElements->begin( << 867               faces_vec[iface][2] = ixyz + numCorner - nFaces + 2;
775                              [](const G4Generi << 868               faces_vec[iface][3] = -(ixyz + 2);
776                              -> G4bool { retur << 869             }
777                                                << 870             else
778   // Generate random point                     << 871             {
779   G4double r = 0, z = 0, phi = 0;              << 872               faces_vec[iface][0] = ixyz + 1;
780   G4double u = G4QuickRand();                  << 873               faces_vec[iface][1] = -(ixyz - nFaces + numCorner + 1);
781   G4double v = G4QuickRand();                  << 874               faces_vec[iface][2] = ixyz - nFaces + 2;
782   G4int i0 = (*it).i0;                         << 875               faces_vec[iface][3] = -(ixyz - numCorner + 2);
783   G4int i1 = (*it).i1;                         << 876             }
784   G4int i2 = (*it).i2;                         << 877           }
785   if (i2 < 0) // lateral surface               << 878           ++ixyz;
786   {                                            << 879           ++iface;
787     G4PolyconeSideRZ p0 = GetCorner(i0);       << 880         }
788     G4PolyconeSideRZ p1 = GetCorner(i1);       << 881         phi += dPhi;
789     if (p1.r < p0.r)                           << 882       }
790     {                                          << 
791       p0 = GetCorner(i1);                      << 
792       p1 = GetCorner(i0);                      << 
793     }                                             883     }
794     if (p1.r - p0.r < kCarTolerance) // cylind << 884     G4Polyhedron* polyhedron = new G4Polyhedron;
795     {                                          << 885     G4int prob = polyhedron->createPolyhedron(nNodes, nFaces, xyz, faces_vec);
796       r = (p1.r - p0.r)*u + p0.r;              << 886     delete [] faces_vec;
797       z = (p1.z - p0.z)*u + p0.z;              << 887     delete [] xyz;
                                                   >> 888     if (prob)
                                                   >> 889     {
                                                   >> 890       std::ostringstream message;
                                                   >> 891       message << "Problem creating G4Polyhedron for: " << GetName();
                                                   >> 892       G4Exception("G4GenericPolycone::CreatePolyhedron()", "GeomSolids1002",
                                                   >> 893                   JustWarning, message);
                                                   >> 894       delete polyhedron;
                                                   >> 895       return nullptr;
798     }                                             896     }
799     else // conical surface                    << 897     else
800     {                                             898     {
801       r = std::sqrt(p1.r*p1.r*u + p0.r*p0.r*(1 << 899       return polyhedron;
802       z = p0.z + (p1.z - p0.z)*(r - p0.r)/(p1. << 
803     }                                             900     }
804     phi = (GetEndPhi() - GetStartPhi())*v + Ge << 
805   }                                            << 
806   else // phi cut                              << 
807   {                                            << 
808     G4int nrz = GetNumRZCorner();              << 
809     phi = (i0 < nrz) ? GetStartPhi() : GetEndP << 
810     if (i0 >= nrz) { i0 -= nrz; }              << 
811     G4PolyconeSideRZ p0 = GetCorner(i0);       << 
812     G4PolyconeSideRZ p1 = GetCorner(i1);       << 
813     G4PolyconeSideRZ p2 = GetCorner(i2);       << 
814     if (u + v > 1.) { u = 1. - u; v = 1. - v;  << 
815     r = (p1.r - p0.r)*u +  (p2.r - p0.r)*v + p << 
816     z = (p1.z - p0.z)*u +  (p2.z - p0.z)*v + p << 
817   }                                            << 
818   return {r*std::cos(phi), r*std::sin(phi), z} << 
819 }                                              << 
820                                                << 
821 ////////////////////////////////////////////// << 
822 //                                             << 
823 // CreatePolyhedron                            << 
824                                                << 
825 G4Polyhedron* G4GenericPolycone::CreatePolyhed << 
826 {                                              << 
827   std::vector<G4TwoVector> rz(numCorner);      << 
828   for (G4int i = 0; i < numCorner; ++i)        << 
829     rz[i].set(corners[i].r, corners[i].z);     << 
830   return new G4PolyhedronPcon(startPhi, endPhi << 
831 }                                                 901 }
832                                                   902 
833 #endif                                            903 #endif
834                                                   904