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


  1 //                                                  1 
  2 // *******************************************    
  3 // * License and Disclaimer                       
  4 // *                                              
  5 // * The  Geant4 software  is  copyright of th    
  6 // * the Geant4 Collaboration.  It is provided    
  7 // * conditions of the Geant4 Software License    
  8 // * LICENSE and available at  http://cern.ch/    
  9 // * include a list of copyright holders.         
 10 // *                                              
 11 // * Neither the authors of this software syst    
 12 // * institutes,nor the agencies providing fin    
 13 // * work  make  any representation or  warran    
 14 // * regarding  this  software system or assum    
 15 // * use.  Please see the license in the file     
 16 // * for the full disclaimer and the limitatio    
 17 // *                                              
 18 // * This  code  implementation is the result     
 19 // * technical work of the GEANT4 collaboratio    
 20 // * By using,  copying,  modifying or  distri    
 21 // * any work based  on the software)  you  ag    
 22 // * use  in  resulting  scientific  publicati    
 23 // * acceptance of all terms of the Geant4 Sof    
 24 // *******************************************    
 25 //                                                
 26 // G4GenericPolycone implementation               
 27 //                                                
 28 // Authors: T.Nikitina, G.Cosmo - CERN            
 29 // -------------------------------------------    
 30                                                   
 31 #include "G4GenericPolycone.hh"                   
 32                                                   
 33 #if !defined(G4GEOM_USE_UGENERICPOLYCONE)         
 34                                                   
 35 #include "G4PolyconeSide.hh"                      
 36 #include "G4PolyPhiFace.hh"                       
 37                                                   
 38 #include "G4GeomTools.hh"                         
 39 #include "G4VoxelLimits.hh"                       
 40 #include "G4AffineTransform.hh"                   
 41 #include "G4BoundingEnvelope.hh"                  
 42                                                   
 43 #include "G4QuickRand.hh"                         
 44                                                   
 45 #include "G4Polyhedron.hh"                        
 46 #include "G4EnclosingCylinder.hh"                 
 47 #include "G4ReduciblePolygon.hh"                  
 48 #include "G4VPVParameterisation.hh"               
 49                                                   
 50 namespace                                         
 51 {                                                 
 52   G4Mutex surface_elementsMutex = G4MUTEX_INIT    
 53 }                                                 
 54                                                   
 55 using namespace CLHEP;                            
 56                                                   
 57 // Constructor (generic parameters)               
 58 //                                                
 59 G4GenericPolycone::G4GenericPolycone( const G4    
 60                               G4double phiStar    
 61                               G4double phiTota    
 62                               G4int    numRZ,     
 63                         const G4double r[],       
 64                         const G4double z[]   )    
 65   : G4VCSGfaceted( name )                         
 66 {                                                 
 67                                                   
 68   auto rz = new G4ReduciblePolygon( r, z, numR    
 69                                                   
 70   Create( phiStart, phiTotal, rz );               
 71                                                   
 72   // Set original_parameters struct for consis    
 73   //                                              
 74   //SetOriginalParameters(rz);                    
 75                                                   
 76   delete rz;                                      
 77 }                                                 
 78                                                   
 79 // Create                                         
 80 //                                                
 81 // Generic create routine, called by each cons    
 82 // conversion of arguments                        
 83 //                                                
 84 void G4GenericPolycone::Create( G4double phiSt    
 85                                 G4double phiTo    
 86                                 G4ReduciblePol    
 87 {                                                 
 88   //                                              
 89   // Perform checks of rz values                  
 90   //                                              
 91   if (rz->Amin() < 0.0)                           
 92   {                                               
 93     std::ostringstream message;                   
 94     message << "Illegal input parameters - " <    
 95             << "        All R values must be >    
 96     G4Exception("G4GenericPolycone::Create()",    
 97                 FatalErrorInArgument, message)    
 98   }                                               
 99                                                   
100   G4double rzArea = rz->Area();                   
101   if (rzArea < -kCarTolerance)                    
102   {                                               
103     rz->ReverseOrder();                           
104   }                                               
105   else if (rzArea < kCarTolerance)                
106   {                                               
107     std::ostringstream message;                   
108     message << "Illegal input parameters - " <    
109             << "        R/Z cross section is z    
110     G4Exception("G4GenericPolycone::Create()",    
111                 FatalErrorInArgument, message)    
112   }                                               
113                                                   
114   if ( (!rz->RemoveDuplicateVertices( kCarTole    
115     || (!rz->RemoveRedundantVertices( kCarTole    
116   {                                               
117     std::ostringstream message;                   
118     message << "Illegal input parameters - " <    
119             << "        Too few unique R/Z val    
120     G4Exception("G4GenericPolycone::Create()",    
121                 FatalErrorInArgument, message)    
122   }                                               
123                                                   
124   if (rz->CrossesItself(1/kInfinity))             
125   {                                               
126     std::ostringstream message;                   
127     message << "Illegal input parameters - " <    
128             << "        R/Z segments cross !";    
129     G4Exception("G4GenericPolycone::Create()",    
130                 FatalErrorInArgument, message)    
131   }                                               
132                                                   
133   numCorner = rz->NumVertices();                  
134                                                   
135   //                                              
136   // Phi opening? Account for some possible ro    
137   // nonsense value as representing no phi ope    
138   //                                              
139   if (phiTotal <= 0 || phiTotal > twopi-1E-10)    
140   {                                               
141     phiIsOpen = false;                            
142     startPhi = 0;                                 
143     endPhi = twopi;                               
144   }                                               
145   else                                            
146   {                                               
147     phiIsOpen = true;                             
148                                                   
149     //                                            
150     // Convert phi into our convention            
151     //                                            
152     startPhi = phiStart;                          
153     while( startPhi < 0 )    // Loop checking,    
154       startPhi += twopi;                          
155                                                   
156     endPhi = phiStart+phiTotal;                   
157     while( endPhi < startPhi )    // Loop chec    
158       endPhi += twopi;                            
159   }                                               
160                                                   
161   //                                              
162   // Allocate corner array.                       
163   //                                              
164   corners = new G4PolyconeSideRZ[numCorner];      
165                                                   
166   //                                              
167   // Copy corners                                 
168   //                                              
169   G4ReduciblePolygonIterator iterRZ(rz);          
170                                                   
171   G4PolyconeSideRZ* next = corners;               
172   iterRZ.Begin();                                 
173   do    // Loop checking, 13.08.2015, G.Cosmo     
174   {                                               
175     next->r = iterRZ.GetA();                      
176     next->z = iterRZ.GetB();                      
177   } while( ++next, iterRZ.Next() );               
178                                                   
179   //                                              
180   // Allocate face pointer array                  
181   //                                              
182   numFace = phiIsOpen ? numCorner+2 : numCorne    
183   faces = new G4VCSGface*[numFace];               
184                                                   
185   //                                              
186   // Construct conical faces                      
187   //                                              
188   // But! Don't construct a face if both point    
189   //                                              
190   G4PolyconeSideRZ *corner = corners,             
191                    *prev = corners + numCorner    
192                    *nextNext;                     
193   G4VCSGface** face = faces;                      
194   do    // Loop checking, 13.08.2015, G.Cosmo     
195   {                                               
196     next = corner+1;                              
197     if (next >= corners+numCorner) next = corn    
198     nextNext = next+1;                            
199     if (nextNext >= corners+numCorner) nextNex    
200                                                   
201     if (corner->r < 1/kInfinity && next->r < 1    
202                                                   
203     //                                            
204     // We must decide here if we can dare decl    
205     // as having a "valid" normal (i.e. allBeh    
206     // is never possible if the face faces "in    
207     //                                            
208     G4bool allBehind;                             
209     if (corner->z > next->z)                      
210     {                                             
211       allBehind = false;                          
212     }                                             
213     else                                          
214     {                                             
215       //                                          
216       // Otherwise, it is only true if the lin    
217       // through the two points of the segment    
218       // split the r/z cross section              
219       //                                          
220       allBehind = !rz->BisectedBy( corner->r,     
221                  next->r, next->z, kCarToleran    
222     }                                             
223                                                   
224     *face++ = new G4PolyconeSide( prev, corner    
225                 startPhi, endPhi-startPhi, phi    
226   } while( prev=corner, corner=next, corner >     
227                                                   
228   if (phiIsOpen)                                  
229   {                                               
230     //                                            
231     // Construct phi open edges                   
232     //                                            
233     *face++ = new G4PolyPhiFace( rz, startPhi,    
234     *face++ = new G4PolyPhiFace( rz, endPhi,      
235   }                                               
236                                                   
237   //                                              
238   // We might have dropped a face or two: reca    
239   //                                              
240   numFace = (G4int)(face-faces);                  
241                                                   
242   //                                              
243   // Make enclosingCylinder                       
244   //                                              
245   enclosingCylinder =                             
246     new G4EnclosingCylinder( rz, phiIsOpen, ph    
247 }                                                 
248                                                   
249 // Fake default constructor - sets only member    
250 //                            for usage restri    
251 //                                                
252 G4GenericPolycone::G4GenericPolycone( __void__    
253   : G4VCSGfaceted(a), startPhi(0.), endPhi(0.)    
254 {                                                 
255 }                                                 
256                                                   
257 // Destructor                                     
258 //                                                
259 G4GenericPolycone::~G4GenericPolycone()           
260 {                                                 
261   delete [] corners;                              
262   delete enclosingCylinder;                       
263   delete fElements;                               
264   delete fpPolyhedron;                            
265   corners = nullptr;                              
266   enclosingCylinder = nullptr;                    
267   fElements = nullptr;                            
268   fpPolyhedron = nullptr;                         
269 }                                                 
270                                                   
271 // Copy constructor                               
272 //                                                
273 G4GenericPolycone::G4GenericPolycone( const G4    
274   : G4VCSGfaceted( source )                       
275 {                                                 
276   CopyStuff( source );                            
277 }                                                 
278                                                   
279 // Assignment operator                            
280 //                                                
281 G4GenericPolycone&                                
282 G4GenericPolycone::operator=( const G4GenericP    
283 {                                                 
284   if (this == &source) return *this;              
285                                                   
286   G4VCSGfaceted::operator=( source );             
287                                                   
288   delete [] corners;                              
289   // if (original_parameters) delete original_    
290                                                   
291   delete enclosingCylinder;                       
292                                                   
293   CopyStuff( source );                            
294                                                   
295   return *this;                                   
296 }                                                 
297                                                   
298 // CopyStuff                                      
299 //                                                
300 void G4GenericPolycone::CopyStuff( const G4Gen    
301 {                                                 
302   //                                              
303   // Simple stuff                                 
304   //                                              
305   startPhi  = source.startPhi;                    
306   endPhi    = source.endPhi;                      
307   phiIsOpen = source.phiIsOpen;                   
308   numCorner = source.numCorner;                   
309                                                   
310   //                                              
311   // The corner array                             
312   //                                              
313   corners = new G4PolyconeSideRZ[numCorner];      
314                                                   
315   G4PolyconeSideRZ  *corn = corners,              
316         *sourceCorn = source.corners;             
317   do    // Loop checking, 13.08.2015, G.Cosmo     
318   {                                               
319     *corn = *sourceCorn;                          
320   } while( ++sourceCorn, ++corn < corners+numC    
321                                                   
322   //                                              
323   // Enclosing cylinder                           
324   //                                              
325   enclosingCylinder = new G4EnclosingCylinder(    
326                                                   
327   //                                              
328   // Surface elements                             
329   //                                              
330   delete fElements;                               
331   fElements = nullptr;                            
332                                                   
333   // Polyhedron                                   
334   //                                              
335   fRebuildPolyhedron = false;                     
336   delete fpPolyhedron;                            
337   fpPolyhedron = nullptr;                         
338 }                                                 
339                                                   
340 // Reset                                          
341 //                                                
342 G4bool G4GenericPolycone::Reset()                 
343 {                                                 
344   std::ostringstream message;                     
345   message << "Solid " << GetName() << " built     
346           << G4endl << "Not applicable to the     
347   G4Exception("G4GenericPolycone::Reset()", "G    
348               JustWarning, message, "Parameter    
349   return true;                                    
350 }                                                 
351                                                   
352 // Inside                                         
353 //                                                
354 // This is an override of G4VCSGfaceted::Insid    
355 // to speed things up by first checking with G    
356 //                                                
357 EInside G4GenericPolycone::Inside( const G4Thr    
358 {                                                 
359   //                                              
360   // Quick test                                   
361   //                                              
362   if (enclosingCylinder->MustBeOutside(p)) ret    
363                                                   
364   //                                              
365   // Long answer                                  
366   //                                              
367   return G4VCSGfaceted::Inside(p);                
368 }                                                 
369                                                   
370 // DistanceToIn                                   
371 //                                                
372 // This is an override of G4VCSGfaceted::Insid    
373 // to speed things up by first checking with G    
374 //                                                
375 G4double G4GenericPolycone::DistanceToIn( cons    
376                                           cons    
377 {                                                 
378   //                                              
379   // Quick test                                   
380   //                                              
381   if (enclosingCylinder->ShouldMiss(p,v))         
382     return kInfinity;                             
383                                                   
384   //                                              
385   // Long answer                                  
386   //                                              
387   return G4VCSGfaceted::DistanceToIn( p, v );     
388 }                                                 
389                                                   
390 // DistanceToIn                                   
391 //                                                
392 G4double G4GenericPolycone::DistanceToIn( cons    
393 {                                                 
394   return G4VCSGfaceted::DistanceToIn(p);          
395 }                                                 
396                                                   
397 // BoundingLimits                                 
398 //                                                
399 // Get bounding box                               
400 //                                                
401 void                                              
402 G4GenericPolycone::BoundingLimits(G4ThreeVecto    
403                                   G4ThreeVecto    
404 {                                                 
405   G4double rmin = kInfinity, rmax = -kInfinity    
406   G4double zmin = kInfinity, zmax = -kInfinity    
407                                                   
408   for (G4int i=0; i<GetNumRZCorner(); ++i)        
409   {                                               
410     G4PolyconeSideRZ corner = GetCorner(i);       
411     if (corner.r < rmin) rmin = corner.r;         
412     if (corner.r > rmax) rmax = corner.r;         
413     if (corner.z < zmin) zmin = corner.z;         
414     if (corner.z > zmax) zmax = corner.z;         
415   }                                               
416                                                   
417   if (IsOpen())                                   
418   {                                               
419     G4TwoVector vmin,vmax;                        
420     G4GeomTools::DiskExtent(rmin,rmax,            
421                             GetSinStartPhi(),G    
422                             GetSinEndPhi(),Get    
423                             vmin,vmax);           
424     pMin.set(vmin.x(),vmin.y(),zmin);             
425     pMax.set(vmax.x(),vmax.y(),zmax);             
426   }                                               
427   else                                            
428   {                                               
429     pMin.set(-rmax,-rmax, zmin);                  
430     pMax.set( rmax, rmax, zmax);                  
431   }                                               
432                                                   
433   // Check correctness of the bounding box        
434   //                                              
435   if (pMin.x() >= pMax.x() || pMin.y() >= pMax    
436   {                                               
437     std::ostringstream message;                   
438     message << "Bad bounding box (min >= max)     
439             << GetName() << " !"                  
440             << "\npMin = " << pMin                
441             << "\npMax = " << pMax;               
442     G4Exception("GenericG4Polycone::BoundingLi    
443                 JustWarning, message);            
444     DumpInfo();                                   
445   }                                               
446 }                                                 
447                                                   
448 // CalculateExtent                                
449 //                                                
450 // Calculate extent under transform and specif    
451 //                                                
452 G4bool                                            
453 G4GenericPolycone::CalculateExtent(const EAxis    
454                                    const G4Vox    
455                                    const G4Aff    
456                                          G4dou    
457 {                                                 
458   G4ThreeVector bmin, bmax;                       
459   G4bool exist;                                   
460                                                   
461   // Check bounding box (bbox)                    
462   //                                              
463   BoundingLimits(bmin,bmax);                      
464   G4BoundingEnvelope bbox(bmin,bmax);             
465 #ifdef G4BBOX_EXTENT                              
466   return bbox.CalculateExtent(pAxis,pVoxelLimi    
467 #endif                                            
468   if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox    
469   {                                               
470     return exist = pMin < pMax;                   
471   }                                               
472                                                   
473   // To find the extent, RZ contour of the pol    
474   // in triangles. The extent is calculated as    
475   // all sub-polycones formed by rotation of t    
476   //                                              
477   G4TwoVectorList contourRZ;                      
478   G4TwoVectorList triangles;                      
479   G4double eminlim = pVoxelLimit.GetMinExtent(    
480   G4double emaxlim = pVoxelLimit.GetMaxExtent(    
481                                                   
482   // get RZ contour, ensure anticlockwise orde    
483   for (G4int i=0; i<GetNumRZCorner(); ++i)        
484   {                                               
485     G4PolyconeSideRZ corner = GetCorner(i);       
486     contourRZ.emplace_back(corner.r,corner.z);    
487   }                                               
488   G4double area = G4GeomTools::PolygonArea(con    
489   if (area < 0.) std::reverse(contourRZ.begin(    
490                                                   
491   // triangulate RZ countour                      
492   if (!G4GeomTools::TriangulatePolygon(contour    
493   {                                               
494     std::ostringstream message;                   
495     message << "Triangulation of RZ contour ha    
496             << GetName() << " !"                  
497             << "\nExtent has been calculated u    
498     G4Exception("G4GenericPolycone::CalculateE    
499                 "GeomMgt1002", JustWarning, me    
500     return bbox.CalculateExtent(pAxis,pVoxelLi    
501   }                                               
502                                                   
503   // set trigonometric values                     
504   const G4int NSTEPS = 24;            // numbe    
505   G4double astep  = twopi/NSTEPS;     // max a    
506                                                   
507   G4double sphi   = GetStartPhi();                
508   G4double ephi   = GetEndPhi();                  
509   G4double dphi   = IsOpen() ? ephi-sphi : two    
510   G4int    ksteps = (dphi <= astep) ? 1 : (G4i    
511   G4double ang    = dphi/ksteps;                  
512                                                   
513   G4double sinHalf = std::sin(0.5*ang);           
514   G4double cosHalf = std::cos(0.5*ang);           
515   G4double sinStep = 2.*sinHalf*cosHalf;          
516   G4double cosStep = 1. - 2.*sinHalf*sinHalf;     
517                                                   
518   G4double sinStart = GetSinStartPhi();           
519   G4double cosStart = GetCosStartPhi();           
520   G4double sinEnd   = GetSinEndPhi();             
521   G4double cosEnd   = GetCosEndPhi();             
522                                                   
523   // define vectors and arrays                    
524   std::vector<const G4ThreeVectorList *> polyg    
525   polygons.resize(ksteps+2);                      
526   G4ThreeVectorList pols[NSTEPS+2];               
527   for (G4int k=0; k<ksteps+2; ++k) pols[k].res    
528   for (G4int k=0; k<ksteps+2; ++k) polygons[k]    
529   G4double r0[6],z0[6]; // contour with origin    
530   G4double r1[6];       // shifted radii of ex    
531                                                   
532   // main loop along triangles                    
533   pMin = kInfinity;                               
534   pMax =-kInfinity;                               
535   G4int ntria = (G4int)triangles.size()/3;        
536   for (G4int i=0; i<ntria; ++i)                   
537   {                                               
538     G4int i3 = i*3;                               
539     for (G4int k=0; k<3; ++k)                     
540     {                                             
541       G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3;    
542       G4int k2 = k*2;                             
543       // set contour with original edges of tr    
544       r0[k2+0] = triangles[e0].x(); z0[k2+0] =    
545       r0[k2+1] = triangles[e1].x(); z0[k2+1] =    
546       // set shifted radii                        
547       r1[k2+0] = r0[k2+0];                        
548       r1[k2+1] = r0[k2+1];                        
549       if (z0[k2+1] - z0[k2+0] <= 0) continue;     
550       r1[k2+0] /= cosHalf;                        
551       r1[k2+1] /= cosHalf;                        
552     }                                             
553                                                   
554     // rotate countour, set sequence of 6-side    
555     G4double sinCur = sinStart*cosHalf + cosSt    
556     G4double cosCur = cosStart*cosHalf - sinSt    
557     for (G4int j=0; j<6; ++j)                     
558     {                                             
559       pols[0][j].set(r0[j]*cosStart,r0[j]*sinS    
560     }                                             
561     for (G4int k=1; k<ksteps+1; ++k)              
562     {                                             
563       for (G4int j=0; j<6; ++j)                   
564       {                                           
565         pols[k][j].set(r1[j]*cosCur,r1[j]*sinC    
566       }                                           
567       G4double sinTmp = sinCur;                   
568       sinCur = sinCur*cosStep + cosCur*sinStep    
569       cosCur = cosCur*cosStep - sinTmp*sinStep    
570     }                                             
571     for (G4int j=0; j<6; ++j)                     
572     {                                             
573       pols[ksteps+1][j].set(r0[j]*cosEnd,r0[j]    
574     }                                             
575                                                   
576     // set sub-envelope and adjust extent         
577     G4double emin,emax;                           
578     G4BoundingEnvelope benv(polygons);            
579     if (!benv.CalculateExtent(pAxis,pVoxelLimi    
580     if (emin < pMin) pMin = emin;                 
581     if (emax > pMax) pMax = emax;                 
582     if (eminlim > pMin && emaxlim < pMax) retu    
583   }                                               
584   return (pMin < pMax);                           
585 }                                                 
586                                                   
587 // GetEntityType                                  
588 //                                                
589 G4GeometryType  G4GenericPolycone::GetEntityTy    
590 {                                                 
591   return {"G4GenericPolycone"};                   
592 }                                                 
593                                                   
594 // Clone                                          
595 //                                                
596 // Make a clone of the object                     
597 //                                                
598 G4VSolid* G4GenericPolycone::Clone() const        
599 {                                                 
600   return new G4GenericPolycone(*this);            
601 }                                                 
602                                                   
603 // StreamInfo                                     
604 //                                                
605 // Stream object contents to an output stream     
606 //                                                
607 std::ostream& G4GenericPolycone::StreamInfo( s    
608 {                                                 
609   G4long oldprc = os.precision(16);               
610   os << "-------------------------------------    
611      << "    *** Dump for solid - " << GetName    
612      << "    =================================    
613      << " Solid type: G4GenericPolycone\n"        
614      << " Parameters: \n"                         
615      << "    starting phi angle : " << startPh    
616      << "    ending phi angle   : " << endPhi/    
617   G4int i=0;                                      
618                                                   
619   os << "    number of RZ points: " << numCorn    
620      << "              RZ values (corners): \n    
621      for (i=0; i<numCorner; i++)                  
622      {                                            
623        os << "                         "          
624           << corners[i].r << ", " << corners[i    
625      }                                            
626   os << "-------------------------------------    
627   os.precision(oldprc);                           
628                                                   
629   return os;                                      
630 }                                                 
631                                                   
632 //////////////////////////////////////////////    
633 //                                                
634 // Return volume                                  
635                                                   
636 G4double G4GenericPolycone::GetCubicVolume()      
637 {                                                 
638   if (fCubicVolume == 0.)                         
639   {                                               
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 }                                                 
653                                                   
654 //////////////////////////////////////////////    
655 //                                                
656 // Return surface area                            
657                                                   
658 G4double G4GenericPolycone::GetSurfaceArea()      
659 {                                                 
660   if (fSurfaceArea == 0.)                         
661   {                                               
662     // phi cut area                               
663     G4int nrz = GetNumRZCorner();                 
664     G4double scut = 0.;                           
665     if (IsOpen())                                 
666     {                                             
667       G4PolyconeSideRZ a = GetCorner(nrz - 1);    
668       for (G4int i=0; i<nrz; ++i)                 
669       {                                           
670         G4PolyconeSideRZ b = GetCorner(i);        
671         scut += a.r*b.z - a.z*b.r;                
672         a = b;                                    
673       }                                           
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                                                   
692 //////////////////////////////////////////////    
693 //                                                
694 // Set vector of surface elements, auxiliary m    
695 // random points on surface                       
696                                                   
697 void G4GenericPolycone::SetSurfaceElements() c    
698 {                                                 
699   fElements = new std::vector<G4GenericPolycon    
700   G4double sarea = 0.;                            
701   G4int nrz = GetNumRZCorner();                   
702                                                   
703   // set lateral surface elements                 
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                                                   
722   // set elements for phi cuts                    
723   if (IsOpen())                                   
724   {                                               
725     G4TwoVectorList contourRZ;                    
726     std::vector<G4int> triangles;                 
727     for (G4int i=0; i<nrz; ++i)                   
728     {                                             
729       G4PolyconeSideRZ corner = GetCorner(i);     
730       contourRZ.emplace_back(corner.r, corner.    
731     }                                             
732     G4GeomTools::TriangulatePolygon(contourRZ,    
733     auto  ntria = (G4int)triangles.size();        
734     for (G4int i=0; i<ntria; i+=3)                
735     {                                             
736       G4GenericPolycone::surface_element selem    
737       selem.i0 = triangles[i];                    
738       selem.i1 = triangles[i+1];                  
739       selem.i2 = triangles[i+2];                  
740       G4PolyconeSideRZ a = GetCorner(selem.i0)    
741       G4PolyconeSideRZ b = GetCorner(selem.i1)    
742       G4PolyconeSideRZ c = GetCorner(selem.i2)    
743       G4double stria =                            
744         std::abs(G4GeomTools::TriangleArea(a.r    
745       sarea += stria;                             
746       selem.area = sarea;                         
747       fElements->push_back(selem); // start ph    
748       sarea += stria;                             
749       selem.area = sarea;                         
750       selem.i0 += nrz;                            
751       fElements->push_back(selem); // end phi     
752     }                                             
753   }                                               
754 }                                                 
755                                                   
756 //////////////////////////////////////////////    
757 //                                                
758 // Generate random point on surface               
759                                                   
760 G4ThreeVector G4GenericPolycone::GetPointOnSur    
761 {                                                 
762   // Set surface elements                         
763   if (fElements == nullptr)                       
764   {                                               
765     G4AutoLock l(&surface_elementsMutex);         
766     SetSurfaceElements();                         
767     l.unlock();                                   
768   }                                               
769                                                   
770   // Select surface element                       
771   G4GenericPolycone::surface_element selem;       
772   selem = fElements->back();                      
773   G4double select = selem.area*G4QuickRand();     
774   auto it = std::lower_bound(fElements->begin(    
775                              [](const G4Generi    
776                              -> G4bool { retur    
777                                                   
778   // Generate random point                        
779   G4double r = 0, z = 0, phi = 0;                 
780   G4double u = G4QuickRand();                     
781   G4double v = G4QuickRand();                     
782   G4int i0 = (*it).i0;                            
783   G4int i1 = (*it).i1;                            
784   G4int i2 = (*it).i2;                            
785   if (i2 < 0) // lateral surface                  
786   {                                               
787     G4PolyconeSideRZ p0 = GetCorner(i0);          
788     G4PolyconeSideRZ p1 = GetCorner(i1);          
789     if (p1.r < p0.r)                              
790     {                                             
791       p0 = GetCorner(i1);                         
792       p1 = GetCorner(i0);                         
793     }                                             
794     if (p1.r - p0.r < kCarTolerance) // cylind    
795     {                                             
796       r = (p1.r - p0.r)*u + p0.r;                 
797       z = (p1.z - p0.z)*u + p0.z;                 
798     }                                             
799     else // conical surface                       
800     {                                             
801       r = std::sqrt(p1.r*p1.r*u + p0.r*p0.r*(1    
802       z = p0.z + (p1.z - p0.z)*(r - p0.r)/(p1.    
803     }                                             
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 }                                                 
832                                                   
833 #endif                                            
834