Geant4 Cross Reference

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


  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 // Implementation of G4Polycone, a CSG polycon    
 27 //                                                
 28 // Author: David C. Williams (davidw@scipp.ucs    
 29 // -------------------------------------------    
 30                                                   
 31 #include "G4Polycone.hh"                          
 32                                                   
 33 #if !defined(G4GEOM_USE_UPOLYCONE)                
 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 "G4EnclosingCylinder.hh"                 
 46 #include "G4ReduciblePolygon.hh"                  
 47 #include "G4VPVParameterisation.hh"               
 48                                                   
 49 namespace                                         
 50 {                                                 
 51   G4Mutex surface_elementsMutex = G4MUTEX_INIT    
 52 }                                                 
 53                                                   
 54 using namespace CLHEP;                            
 55                                                   
 56 // Constructor (GEANT3 style parameters)          
 57 //                                                
 58 G4Polycone::G4Polycone( const G4String& name,     
 59                               G4double phiStar    
 60                               G4double phiTota    
 61                               G4int numZPlanes    
 62                         const G4double zPlane[    
 63                         const G4double rInner[    
 64                         const G4double rOuter[    
 65   : G4VCSGfaceted( name )                         
 66 {                                                 
 67   //                                              
 68   // Some historical ugliness                     
 69   //                                              
 70   original_parameters = new G4PolyconeHistoric    
 71                                                   
 72   original_parameters->Start_angle = phiStart;    
 73   original_parameters->Opening_angle = phiTota    
 74   original_parameters->Num_z_planes = numZPlan    
 75   original_parameters->Z_values = new G4double    
 76   original_parameters->Rmin = new G4double[num    
 77   original_parameters->Rmax = new G4double[num    
 78                                                   
 79   for (G4int i=0; i<numZPlanes; ++i)              
 80   {                                               
 81     if(rInner[i]>rOuter[i])                       
 82     {                                             
 83       DumpInfo();                                 
 84       std::ostringstream message;                 
 85       message << "Cannot create a Polycone wit    
 86               << G4endl                           
 87               << "        rInner > rOuter for     
 88               << "        rMin[" << i << "] =     
 89               << " -- rMax[" << i << "] = " <<    
 90       G4Exception("G4Polycone::G4Polycone()",     
 91                   FatalErrorInArgument, messag    
 92     }                                             
 93     if (( i < numZPlanes-1) && ( zPlane[i] ==     
 94     {                                             
 95       if( (rInner[i]   > rOuter[i+1])             
 96         ||(rInner[i+1] > rOuter[i])   )           
 97       {                                           
 98         DumpInfo();                               
 99         std::ostringstream message;               
100         message << "Cannot create a Polycone w    
101                 << G4endl                         
102                 << "        Segments are not c    
103                 << "        rMin[" << i << "]     
104                 << " -- rMax[" << i+1 << "] =     
105                 << "        rMin[" << i+1 << "    
106                 << " -- rMax[" << i << "] = "     
107         G4Exception("G4Polycone::G4Polycone()"    
108                     FatalErrorInArgument, mess    
109       }                                           
110     }                                             
111     original_parameters->Z_values[i] = zPlane[    
112     original_parameters->Rmin[i] = rInner[i];     
113     original_parameters->Rmax[i] = rOuter[i];     
114   }                                               
115                                                   
116   //                                              
117   // Build RZ polygon using special PCON/PGON     
118   //                                              
119   auto rz = new G4ReduciblePolygon( rInner, rO    
120                                                   
121   //                                              
122   // Do the real work                             
123   //                                              
124   Create( phiStart, phiTotal, rz );               
125                                                   
126   delete rz;                                      
127 }                                                 
128                                                   
129 // Constructor (generic parameters)               
130 //                                                
131 G4Polycone::G4Polycone( const G4String& name,     
132                               G4double phiStar    
133                               G4double phiTota    
134                               G4int    numRZ,     
135                         const G4double r[],       
136                         const G4double z[]   )    
137   : G4VCSGfaceted( name )                         
138 {                                                 
139                                                   
140   auto rz = new G4ReduciblePolygon( r, z, numR    
141                                                   
142   Create( phiStart, phiTotal, rz );               
143                                                   
144   // Set original_parameters struct for consis    
145   //                                              
146                                                   
147   G4bool convertible = SetOriginalParameters(r    
148                                                   
149   if(!convertible)                                
150   {                                               
151     std::ostringstream message;                   
152     message << "Polycone " << GetName() << "ca    
153             << "to Polycone with (Rmin,Rmaz,Z)    
154     G4Exception("G4Polycone::G4Polycone()", "G    
155                 FatalException, message, "Use     
156   }                                               
157   else                                            
158   {                                               
159     G4cout << "INFO: Converting polycone " <<     
160            << "to optimized polycone with (Rmi    
161            << G4endl;                             
162   }                                               
163   delete rz;                                      
164 }                                                 
165                                                   
166 // Create                                         
167 //                                                
168 // Generic create routine, called by each cons    
169 // conversion of arguments                        
170 //                                                
171 void G4Polycone::Create( G4double phiStart,       
172                          G4double phiTotal,       
173                          G4ReduciblePolygon* r    
174 {                                                 
175   //                                              
176   // Perform checks of rz values                  
177   //                                              
178   if (rz->Amin() < 0.0)                           
179   {                                               
180     std::ostringstream message;                   
181     message << "Illegal input parameters - " <    
182             << "        All R values must be >    
183     G4Exception("G4Polycone::Create()", "GeomS    
184                 FatalErrorInArgument, message)    
185   }                                               
186                                                   
187   G4double rzArea = rz->Area();                   
188   if (rzArea < -kCarTolerance)                    
189   {                                               
190     rz->ReverseOrder();                           
191   }                                               
192   else if (rzArea < kCarTolerance)                
193   {                                               
194     std::ostringstream message;                   
195     message << "Illegal input parameters - " <    
196             << "        R/Z cross section is z    
197     G4Exception("G4Polycone::Create()", "GeomS    
198                 FatalErrorInArgument, message)    
199   }                                               
200                                                   
201   if ( (!rz->RemoveDuplicateVertices( kCarTole    
202     || (!rz->RemoveRedundantVertices( kCarTole    
203   {                                               
204     std::ostringstream message;                   
205     message << "Illegal input parameters - " <    
206             << "        Too few unique R/Z val    
207     G4Exception("G4Polycone::Create()", "GeomS    
208                 FatalErrorInArgument, message)    
209   }                                               
210                                                   
211   if (rz->CrossesItself(1/kInfinity))             
212   {                                               
213     std::ostringstream message;                   
214     message << "Illegal input parameters - " <    
215             << "        R/Z segments cross !";    
216     G4Exception("G4Polycone::Create()", "GeomS    
217                 FatalErrorInArgument, message)    
218   }                                               
219                                                   
220   numCorner = rz->NumVertices();                  
221                                                   
222   startPhi = phiStart;                            
223   while( startPhi < 0. )    // Loop checking,     
224     startPhi += twopi;                            
225   //                                              
226   // Phi opening? Account for some possible ro    
227   // nonsense value as representing no phi ope    
228   //                                              
229   if ( (phiTotal <= 0) || (phiTotal > twopi*(1    
230   {                                               
231     phiIsOpen = false;                            
232     startPhi = 0.;                                
233     endPhi = twopi;                               
234   }                                               
235   else                                            
236   {                                               
237     phiIsOpen = true;                             
238     endPhi = startPhi + phiTotal;                 
239   }                                               
240                                                   
241   //                                              
242   // Allocate corner array.                       
243   //                                              
244   corners = new G4PolyconeSideRZ[numCorner];      
245                                                   
246   //                                              
247   // Copy corners                                 
248   //                                              
249   G4ReduciblePolygonIterator iterRZ(rz);          
250                                                   
251   G4PolyconeSideRZ *next = corners;               
252   iterRZ.Begin();                                 
253   do    // Loop checking, 13.08.2015, G.Cosmo     
254   {                                               
255     next->r = iterRZ.GetA();                      
256     next->z = iterRZ.GetB();                      
257   } while( ++next, iterRZ.Next() );               
258                                                   
259   //                                              
260   // Allocate face pointer array                  
261   //                                              
262   numFace = phiIsOpen ? numCorner+2 : numCorne    
263   faces = new G4VCSGface*[numFace];               
264                                                   
265   //                                              
266   // Construct conical faces                      
267   //                                              
268   // But! Don't construct a face if both point    
269   //                                              
270   G4PolyconeSideRZ* corner = corners,             
271                   * prev = corners + numCorner    
272                   * nextNext;                     
273   G4VCSGface  **face = faces;                     
274   do    // Loop checking, 13.08.2015, G.Cosmo     
275   {                                               
276     next = corner+1;                              
277     if (next >= corners+numCorner) next = corn    
278     nextNext = next+1;                            
279     if (nextNext >= corners+numCorner) nextNex    
280                                                   
281     if (corner->r < 1/kInfinity && next->r < 1    
282                                                   
283     //                                            
284     // We must decide here if we can dare decl    
285     // as having a "valid" normal (i.e. allBeh    
286     // is never possible if the face faces "in    
287     //                                            
288     G4bool allBehind;                             
289     if (corner->z > next->z)                      
290     {                                             
291       allBehind = false;                          
292     }                                             
293     else                                          
294     {                                             
295       //                                          
296       // Otherwise, it is only true if the lin    
297       // through the two points of the segment    
298       // split the r/z cross section              
299       //                                          
300       allBehind = !rz->BisectedBy( corner->r,     
301                  next->r, next->z, kCarToleran    
302     }                                             
303                                                   
304     *face++ = new G4PolyconeSide( prev, corner    
305                 startPhi, endPhi-startPhi, phi    
306   } while( prev=corner, corner=next, corner >     
307                                                   
308   if (phiIsOpen)                                  
309   {                                               
310     //                                            
311     // Construct phi open edges                   
312     //                                            
313     *face++ = new G4PolyPhiFace( rz, startPhi,    
314     *face++ = new G4PolyPhiFace( rz, endPhi,      
315   }                                               
316                                                   
317   //                                              
318   // We might have dropped a face or two: reca    
319   //                                              
320   numFace = (G4int)(face-faces);                  
321                                                   
322   //                                              
323   // Make enclosingCylinder                       
324   //                                              
325   enclosingCylinder =                             
326     new G4EnclosingCylinder( rz, phiIsOpen, ph    
327 }                                                 
328                                                   
329 // Fake default constructor - sets only member    
330 //                            for usage restri    
331 //                                                
332 G4Polycone::G4Polycone( __void__& a )             
333   : G4VCSGfaceted(a), startPhi(0.),  endPhi(0.    
334 {                                                 
335 }                                                 
336                                                   
337                                                   
338 //                                                
339 // Destructor                                     
340 //                                                
341 G4Polycone::~G4Polycone()                         
342 {                                                 
343   delete [] corners;                              
344   delete original_parameters;                     
345   delete enclosingCylinder;                       
346   delete fElements;                               
347   delete fpPolyhedron;                            
348   corners = nullptr;                              
349   original_parameters = nullptr;                  
350   enclosingCylinder = nullptr;                    
351   fElements = nullptr;                            
352   fpPolyhedron = nullptr;                         
353 }                                                 
354                                                   
355 // Copy constructor                               
356 //                                                
357 G4Polycone::G4Polycone( const G4Polycone& sour    
358   : G4VCSGfaceted( source )                       
359 {                                                 
360   CopyStuff( source );                            
361 }                                                 
362                                                   
363 // Assignment operator                            
364 //                                                
365 G4Polycone &G4Polycone::operator=( const G4Pol    
366 {                                                 
367   if (this == &source) return *this;              
368                                                   
369   G4VCSGfaceted::operator=( source );             
370                                                   
371   delete [] corners;                              
372   delete original_parameters;                     
373                                                   
374   delete enclosingCylinder;                       
375                                                   
376   CopyStuff( source );                            
377                                                   
378   return *this;                                   
379 }                                                 
380                                                   
381 // CopyStuff                                      
382 //                                                
383 void G4Polycone::CopyStuff( const G4Polycone&     
384 {                                                 
385   //                                              
386   // Simple stuff                                 
387   //                                              
388   startPhi  = source.startPhi;                    
389   endPhi    = source.endPhi;                      
390   phiIsOpen = source.phiIsOpen;                   
391   numCorner = source.numCorner;                   
392                                                   
393   //                                              
394   // The corner array                             
395   //                                              
396   corners = new G4PolyconeSideRZ[numCorner];      
397                                                   
398   G4PolyconeSideRZ* corn = corners,               
399                   * sourceCorn = source.corner    
400   do    // Loop checking, 13.08.2015, G.Cosmo     
401   {                                               
402     *corn = *sourceCorn;                          
403   } while( ++sourceCorn, ++corn < corners+numC    
404                                                   
405   //                                              
406   // Original parameters                          
407   //                                              
408   if (source.original_parameters != nullptr)      
409   {                                               
410     original_parameters =                         
411       new G4PolyconeHistorical( *source.origin    
412   }                                               
413                                                   
414   //                                              
415   // Enclosing cylinder                           
416   //                                              
417   enclosingCylinder = new G4EnclosingCylinder(    
418                                                   
419   //                                              
420   // Surface elements                             
421   //                                              
422   delete fElements;                               
423   fElements = nullptr;                            
424                                                   
425   //                                              
426   // Polyhedron                                   
427   //                                              
428   fRebuildPolyhedron = false;                     
429   delete fpPolyhedron;                            
430   fpPolyhedron = nullptr;                         
431 }                                                 
432                                                   
433 // Reset                                          
434 //                                                
435 G4bool G4Polycone::Reset()                        
436 {                                                 
437   //                                              
438   // Clear old setup                              
439   //                                              
440   G4VCSGfaceted::DeleteStuff();                   
441   delete [] corners;                              
442   delete enclosingCylinder;                       
443   delete fElements;                               
444   corners = nullptr;                              
445   fElements = nullptr;                            
446   enclosingCylinder = nullptr;                    
447                                                   
448   //                                              
449   // Rebuild polycone                             
450   //                                              
451   auto rz = new G4ReduciblePolygon( original_p    
452                                     original_p    
453                                     original_p    
454                                     original_p    
455   Create( original_parameters->Start_angle,       
456           original_parameters->Opening_angle,     
457   delete rz;                                      
458                                                   
459   return false;                                   
460 }                                                 
461                                                   
462 // Inside                                         
463 //                                                
464 // This is an override of G4VCSGfaceted::Insid    
465 // to speed things up by first checking with G    
466 //                                                
467 EInside G4Polycone::Inside( const G4ThreeVecto    
468 {                                                 
469   //                                              
470   // Quick test                                   
471   //                                              
472   if (enclosingCylinder->MustBeOutside(p)) ret    
473                                                   
474   //                                              
475   // Long answer                                  
476   //                                              
477   return G4VCSGfaceted::Inside(p);                
478 }                                                 
479                                                   
480 // DistanceToIn                                   
481 //                                                
482 // This is an override of G4VCSGfaceted::Insid    
483 // to speed things up by first checking with G    
484 //                                                
485 G4double G4Polycone::DistanceToIn( const G4Thr    
486                                    const G4Thr    
487 {                                                 
488   //                                              
489   // Quick test                                   
490   //                                              
491   if (enclosingCylinder->ShouldMiss(p,v))         
492     return kInfinity;                             
493                                                   
494   //                                              
495   // Long answer                                  
496   //                                              
497   return G4VCSGfaceted::DistanceToIn( p, v );     
498 }                                                 
499                                                   
500 // DistanceToIn                                   
501 //                                                
502 G4double G4Polycone::DistanceToIn( const G4Thr    
503 {                                                 
504   return G4VCSGfaceted::DistanceToIn(p);          
505 }                                                 
506                                                   
507 // Get bounding box                               
508 //                                                
509 void G4Polycone::BoundingLimits(G4ThreeVector&    
510                                 G4ThreeVector&    
511 {                                                 
512   G4double rmin = kInfinity, rmax = -kInfinity    
513   G4double zmin = kInfinity, zmax = -kInfinity    
514                                                   
515   for (G4int i=0; i<GetNumRZCorner(); ++i)        
516   {                                               
517     G4PolyconeSideRZ corner = GetCorner(i);       
518     if (corner.r < rmin) rmin = corner.r;         
519     if (corner.r > rmax) rmax = corner.r;         
520     if (corner.z < zmin) zmin = corner.z;         
521     if (corner.z > zmax) zmax = corner.z;         
522   }                                               
523                                                   
524   if (IsOpen())                                   
525   {                                               
526     G4TwoVector vmin,vmax;                        
527     G4GeomTools::DiskExtent(rmin,rmax,            
528                             GetSinStartPhi(),G    
529                             GetSinEndPhi(),Get    
530                             vmin,vmax);           
531     pMin.set(vmin.x(),vmin.y(),zmin);             
532     pMax.set(vmax.x(),vmax.y(),zmax);             
533   }                                               
534   else                                            
535   {                                               
536     pMin.set(-rmax,-rmax, zmin);                  
537     pMax.set( rmax, rmax, zmax);                  
538   }                                               
539                                                   
540   // Check correctness of the bounding box        
541   //                                              
542   if (pMin.x() >= pMax.x() || pMin.y() >= pMax    
543   {                                               
544     std::ostringstream message;                   
545     message << "Bad bounding box (min >= max)     
546             << GetName() << " !"                  
547             << "\npMin = " << pMin                
548             << "\npMax = " << pMax;               
549     G4Exception("G4Polycone::BoundingLimits()"    
550                 JustWarning, message);            
551     DumpInfo();                                   
552   }                                               
553 }                                                 
554                                                   
555 // Calculate extent under transform and specif    
556 //                                                
557 G4bool G4Polycone::CalculateExtent(const EAxis    
558                                    const G4Vox    
559                                    const G4Aff    
560                                          G4dou    
561 {                                                 
562   G4ThreeVector bmin, bmax;                       
563   G4bool exist;                                   
564                                                   
565   // Check bounding box (bbox)                    
566   //                                              
567   BoundingLimits(bmin,bmax);                      
568   G4BoundingEnvelope bbox(bmin,bmax);             
569 #ifdef G4BBOX_EXTENT                              
570   return bbox.CalculateExtent(pAxis,pVoxelLimi    
571 #endif                                            
572   if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox    
573   {                                               
574     return exist = pMin < pMax;                   
575   }                                               
576                                                   
577   // To find the extent, RZ contour of the pol    
578   // in triangles. The extent is calculated as    
579   // all sub-polycones formed by rotation of t    
580   //                                              
581   G4TwoVectorList contourRZ;                      
582   G4TwoVectorList triangles;                      
583   std::vector<G4int> iout;                        
584   G4double eminlim = pVoxelLimit.GetMinExtent(    
585   G4double emaxlim = pVoxelLimit.GetMaxExtent(    
586                                                   
587   // get RZ contour, ensure anticlockwise orde    
588   for (G4int i=0; i<GetNumRZCorner(); ++i)        
589   {                                               
590     G4PolyconeSideRZ corner = GetCorner(i);       
591     contourRZ.emplace_back(corner.r,corner.z);    
592   }                                               
593   G4GeomTools::RemoveRedundantVertices(contour    
594   G4double area = G4GeomTools::PolygonArea(con    
595   if (area < 0.) std::reverse(contourRZ.begin(    
596                                                   
597   // triangulate RZ countour                      
598   if (!G4GeomTools::TriangulatePolygon(contour    
599   {                                               
600     std::ostringstream message;                   
601     message << "Triangulation of RZ contour ha    
602             << GetName() << " !"                  
603             << "\nExtent has been calculated u    
604     G4Exception("G4Polycone::CalculateExtent()    
605                 "GeomMgt1002", JustWarning, me    
606     return bbox.CalculateExtent(pAxis,pVoxelLi    
607   }                                               
608                                                   
609   // set trigonometric values                     
610   const G4int NSTEPS = 24;            // numbe    
611   G4double astep  = twopi/NSTEPS;     // max a    
612                                                   
613   G4double sphi   = GetStartPhi();                
614   G4double ephi   = GetEndPhi();                  
615   G4double dphi   = IsOpen() ? ephi-sphi : two    
616   G4int    ksteps = (dphi <= astep) ? 1 : (G4i    
617   G4double ang    = dphi/ksteps;                  
618                                                   
619   G4double sinHalf = std::sin(0.5*ang);           
620   G4double cosHalf = std::cos(0.5*ang);           
621   G4double sinStep = 2.*sinHalf*cosHalf;          
622   G4double cosStep = 1. - 2.*sinHalf*sinHalf;     
623                                                   
624   G4double sinStart = GetSinStartPhi();           
625   G4double cosStart = GetCosStartPhi();           
626   G4double sinEnd   = GetSinEndPhi();             
627   G4double cosEnd   = GetCosEndPhi();             
628                                                   
629   // define vectors and arrays                    
630   std::vector<const G4ThreeVectorList *> polyg    
631   polygons.resize(ksteps+2);                      
632   G4ThreeVectorList pols[NSTEPS+2];               
633   for (G4int k=0; k<ksteps+2; ++k) pols[k].res    
634   for (G4int k=0; k<ksteps+2; ++k) polygons[k]    
635   G4double r0[6],z0[6]; // contour with origin    
636   G4double r1[6];       // shifted radii of ex    
637                                                   
638   // main loop along triangles                    
639   pMin = kInfinity;                               
640   pMax =-kInfinity;                               
641   G4int ntria = (G4int)triangles.size()/3;        
642   for (G4int i=0; i<ntria; ++i)                   
643   {                                               
644     G4int i3 = i*3;                               
645     for (G4int k=0; k<3; ++k)                     
646     {                                             
647       G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3;    
648       G4int k2 = k*2;                             
649       // set contour with original edges of tr    
650       r0[k2+0] = triangles[e0].x(); z0[k2+0] =    
651       r0[k2+1] = triangles[e1].x(); z0[k2+1] =    
652       // set shifted radii                        
653       r1[k2+0] = r0[k2+0];                        
654       r1[k2+1] = r0[k2+1];                        
655       if (z0[k2+1] - z0[k2+0] <= 0) continue;     
656       r1[k2+0] /= cosHalf;                        
657       r1[k2+1] /= cosHalf;                        
658     }                                             
659                                                   
660     // rotate countour, set sequence of 6-side    
661     G4double sinCur = sinStart*cosHalf + cosSt    
662     G4double cosCur = cosStart*cosHalf - sinSt    
663     for (G4int j=0; j<6; ++j) pols[0][j].set(r    
664     for (G4int k=1; k<ksteps+1; ++k)              
665     {                                             
666       for (G4int j=0; j<6; ++j) pols[k][j].set    
667       G4double sinTmp = sinCur;                   
668       sinCur = sinCur*cosStep + cosCur*sinStep    
669       cosCur = cosCur*cosStep - sinTmp*sinStep    
670     }                                             
671     for (G4int j=0; j<6; ++j) pols[ksteps+1][j    
672                                                   
673     // set sub-envelope and adjust extent         
674     G4double emin,emax;                           
675     G4BoundingEnvelope benv(polygons);            
676     if (!benv.CalculateExtent(pAxis,pVoxelLimi    
677     if (emin < pMin) pMin = emin;                 
678     if (emax > pMax) pMax = emax;                 
679     if (eminlim > pMin && emaxlim < pMax) retu    
680   }                                               
681   return (pMin < pMax);                           
682 }                                                 
683                                                   
684 // ComputeDimensions                              
685 //                                                
686 void G4Polycone::ComputeDimensions(       G4VP    
687                                     const G4in    
688                                     const G4VP    
689 {                                                 
690   p->ComputeDimensions(*this,n,pRep);             
691 }                                                 
692                                                   
693 // GetEntityType                                  
694 //                                                
695 G4GeometryType  G4Polycone::GetEntityType() co    
696 {                                                 
697   return {"G4Polycone"};                          
698 }                                                 
699                                                   
700 // Make a clone of the object                     
701 //                                                
702 G4VSolid* G4Polycone::Clone() const               
703 {                                                 
704   return new G4Polycone(*this);                   
705 }                                                 
706                                                   
707 //                                                
708 // Stream object contents to an output stream     
709 //                                                
710 std::ostream& G4Polycone::StreamInfo( std::ost    
711 {                                                 
712   G4long oldprc = os.precision(16);               
713   os << "-------------------------------------    
714      << "    *** Dump for solid - " << GetName    
715      << "    =================================    
716      << " Solid type: G4Polycone\n"               
717      << " Parameters: \n"                         
718      << "    starting phi angle : " << startPh    
719      << "    ending phi angle   : " << endPhi/    
720   G4int i=0;                                      
721                                                   
722     G4int numPlanes = original_parameters->Num    
723     os << "    number of Z planes: " << numPla    
724        << "              Z values: \n";           
725     for (i=0; i<numPlanes; ++i)                   
726     {                                             
727       os << "              Z plane " << i << "    
728          << original_parameters->Z_values[i] <    
729     }                                             
730     os << "              Tangent distances to     
731     for (i=0; i<numPlanes; ++i)                   
732     {                                             
733       os << "              Z plane " << i << "    
734          << original_parameters->Rmin[i] << "\    
735     }                                             
736     os << "              Tangent distances to     
737     for (i=0; i<numPlanes; ++i)                   
738     {                                             
739       os << "              Z plane " << i << "    
740          << original_parameters->Rmax[i] << "\    
741     }                                             
742                                                   
743   os << "    number of RZ points: " << numCorn    
744      << "              RZ values (corners): \n    
745      for (i=0; i<numCorner; ++i)                  
746      {                                            
747        os << "                         "          
748           << corners[i].r << ", " << corners[i    
749      }                                            
750   os << "-------------------------------------    
751   os.precision(oldprc);                           
752                                                   
753   return os;                                      
754 }                                                 
755                                                   
756 //////////////////////////////////////////////    
757 //                                                
758 // Return volume                                  
759                                                   
760 G4double G4Polycone::GetCubicVolume()             
761 {                                                 
762   if (fCubicVolume == 0.)                         
763   {                                               
764     G4double total = 0.;                          
765     G4int nrz = GetNumRZCorner();                 
766     G4PolyconeSideRZ a = GetCorner(nrz - 1);      
767     for (G4int i=0; i<nrz; ++i)                   
768     {                                             
769       G4PolyconeSideRZ b = GetCorner(i);          
770       total += (b.r*b.r + b.r*a.r + a.r*a.r)*(    
771       a = b;                                      
772     }                                             
773     fCubicVolume = std::abs(total)*(GetEndPhi(    
774   }                                               
775   return fCubicVolume;                            
776 }                                                 
777                                                   
778 //////////////////////////////////////////////    
779 //                                                
780 // Return surface area                            
781                                                   
782 G4double G4Polycone::GetSurfaceArea()             
783 {                                                 
784   if (fSurfaceArea == 0.)                         
785   {                                               
786     // phi cut area                               
787     G4int nrz = GetNumRZCorner();                 
788     G4double scut = 0.;                           
789     if (IsOpen())                                 
790     {                                             
791       G4PolyconeSideRZ a = GetCorner(nrz - 1);    
792       for (G4int i=0; i<nrz; ++i)                 
793       {                                           
794         G4PolyconeSideRZ b = GetCorner(i);        
795         scut += a.r*b.z - a.z*b.r;                
796         a = b;                                    
797       }                                           
798       scut = std::abs(scut);                      
799     }                                             
800     // lateral surface area                       
801     G4double slat = 0;                            
802     G4PolyconeSideRZ a = GetCorner(nrz - 1);      
803     for (G4int i=0; i<nrz; ++i)                   
804     {                                             
805       G4PolyconeSideRZ b = GetCorner(i);          
806       G4double h = std::sqrt((b.r - a.r)*(b.r     
807       slat += (b.r + a.r)*h;                      
808       a = b;                                      
809     }                                             
810     slat *= (GetEndPhi() - GetStartPhi())/2.;     
811     fSurfaceArea = scut + slat;                   
812   }                                               
813   return fSurfaceArea;                            
814 }                                                 
815                                                   
816 //////////////////////////////////////////////    
817 //                                                
818 // Set vector of surface elements, auxiliary m    
819 // random points on surface                       
820                                                   
821 void G4Polycone::SetSurfaceElements() const       
822 {                                                 
823   fElements = new std::vector<G4Polycone::surf    
824   G4double total = 0.;                            
825   G4int nrz = GetNumRZCorner();                   
826                                                   
827   // set lateral surface elements                 
828   G4double dphi = GetEndPhi() - GetStartPhi();    
829   G4int ia = nrz - 1;                             
830   for (G4int ib=0; ib<nrz; ++ib)                  
831   {                                               
832     G4PolyconeSideRZ a = GetCorner(ia);           
833     G4PolyconeSideRZ b = GetCorner(ib);           
834     G4Polycone::surface_element selem;            
835     selem.i0 = ia;                                
836     selem.i1 = ib;                                
837     selem.i2 = -1;                                
838     ia = ib;                                      
839     if (a.r == 0. && b.r == 0.) continue;         
840     G4double h = std::sqrt((b.r - a.r)*(b.r -     
841     total += 0.5*dphi*(b.r + a.r)*h;              
842     selem.area = total;                           
843     fElements->push_back(selem);                  
844   }                                               
845                                                   
846   // set elements for phi cuts                    
847   if (IsOpen())                                   
848   {                                               
849     G4TwoVectorList contourRZ;                    
850     std::vector<G4int> triangles;                 
851     for (G4int i=0; i<nrz; ++i)                   
852     {                                             
853       G4PolyconeSideRZ corner = GetCorner(i);     
854       contourRZ.emplace_back(corner.r, corner.    
855     }                                             
856     G4GeomTools::TriangulatePolygon(contourRZ,    
857     auto ntria = (G4int)triangles.size();         
858     for (G4int i=0; i<ntria; i+=3)                
859     {                                             
860       G4Polycone::surface_element selem;          
861       selem.i0 = triangles[i];                    
862       selem.i1 = triangles[i+1];                  
863       selem.i2 = triangles[i+2];                  
864       G4PolyconeSideRZ a = GetCorner(selem.i0)    
865       G4PolyconeSideRZ b = GetCorner(selem.i1)    
866       G4PolyconeSideRZ c = GetCorner(selem.i2)    
867       G4double stria =                            
868         std::abs(G4GeomTools::TriangleArea(a.r    
869       total += stria;                             
870       selem.area = total;                         
871       fElements->push_back(selem); // start ph    
872       total += stria;                             
873       selem.area = total;                         
874       selem.i0 += nrz;                            
875       fElements->push_back(selem); // end phi     
876     }                                             
877   }                                               
878 }                                                 
879                                                   
880 //////////////////////////////////////////////    
881 //                                                
882 // Generate random point on surface               
883                                                   
884 G4ThreeVector G4Polycone::GetPointOnSurface()     
885 {                                                 
886   // Set surface elements                         
887   if (fElements == nullptr)                       
888   {                                               
889     G4AutoLock l(&surface_elementsMutex);         
890     SetSurfaceElements();                         
891     l.unlock();                                   
892   }                                               
893                                                   
894   // Select surface element                       
895   G4Polycone::surface_element selem;              
896   selem = fElements->back();                      
897   G4double select = selem.area*G4QuickRand();     
898   auto it = std::lower_bound(fElements->begin(    
899                              [](const G4Polyco    
900                              -> G4bool { retur    
901                                                   
902   // Generate random point                        
903   G4double r = 0, z = 0, phi = 0;                 
904   G4double u = G4QuickRand();                     
905   G4double v = G4QuickRand();                     
906   G4int i0 = (*it).i0;                            
907   G4int i1 = (*it).i1;                            
908   G4int i2 = (*it).i2;                            
909   if (i2 < 0) // lateral surface                  
910   {                                               
911     G4PolyconeSideRZ p0 = GetCorner(i0);          
912     G4PolyconeSideRZ p1 = GetCorner(i1);          
913     if (p1.r < p0.r)                              
914     {                                             
915       p0 = GetCorner(i1);                         
916       p1 = GetCorner(i0);                         
917     }                                             
918     if (p1.r - p0.r < kCarTolerance) // cylind    
919     {                                             
920       r = (p1.r - p0.r)*u + p0.r;                 
921       z = (p1.z - p0.z)*u + p0.z;                 
922     }                                             
923     else // conical surface                       
924     {                                             
925       r = std::sqrt(p1.r*p1.r*u + p0.r*p0.r*(1    
926       z = p0.z + (p1.z - p0.z)*(r - p0.r)/(p1.    
927     }                                             
928     phi = (GetEndPhi() - GetStartPhi())*v + Ge    
929   }                                               
930   else // phi cut                                 
931   {                                               
932     G4int nrz = GetNumRZCorner();                 
933     phi = (i0 < nrz) ? GetStartPhi() : GetEndP    
934     if (i0 >= nrz) { i0 -= nrz; }                 
935     G4PolyconeSideRZ p0 = GetCorner(i0);          
936     G4PolyconeSideRZ p1 = GetCorner(i1);          
937     G4PolyconeSideRZ p2 = GetCorner(i2);          
938     if (u + v > 1.) { u = 1. - u; v = 1. - v;     
939     r = (p1.r - p0.r)*u +  (p2.r - p0.r)*v + p    
940     z = (p1.z - p0.z)*u +  (p2.z - p0.z)*v + p    
941   }                                               
942   return { r*std::cos(phi), r*std::sin(phi), z    
943 }                                                 
944                                                   
945 //////////////////////////////////////////////    
946 //                                                
947 // CreatePolyhedron                               
948                                                   
949 G4Polyhedron* G4Polycone::CreatePolyhedron() c    
950 {                                                 
951   std::vector<G4TwoVector> rz(numCorner);         
952   for (G4int i = 0; i < numCorner; ++i)           
953     rz[i].set(corners[i].r, corners[i].z);        
954   return new G4PolyhedronPcon(startPhi, endPhi    
955 }                                                 
956                                                   
957 // SetOriginalParameters                          
958 //                                                
959 G4bool  G4Polycone::SetOriginalParameters(G4Re    
960 {                                                 
961   G4int numPlanes = numCorner;                    
962   G4bool isConvertible = true;                    
963   G4double Zmax=rz->Bmax();                       
964   rz->StartWithZMin();                            
965                                                   
966   // Prepare vectors for storage                  
967   //                                              
968   std::vector<G4double> Z;                        
969   std::vector<G4double> Rmin;                     
970   std::vector<G4double> Rmax;                     
971                                                   
972   G4int countPlanes=1;                            
973   G4int icurr=0;                                  
974   G4int icurl=0;                                  
975                                                   
976   // first plane Z=Z[0]                           
977   //                                              
978   Z.push_back(corners[0].z);                      
979   G4double Zprev=Z[0];                            
980   if (Zprev == corners[1].z)                      
981   {                                               
982     Rmin.push_back(corners[0].r);                 
983     Rmax.push_back (corners[1].r);icurr=1;        
984   }                                               
985   else if (Zprev == corners[numPlanes-1].z)       
986   {                                               
987     Rmin.push_back(corners[numPlanes-1].r);       
988     Rmax.push_back (corners[0].r);                
989     icurl=numPlanes-1;                            
990   }                                               
991   else                                            
992   {                                               
993     Rmin.push_back(corners[0].r);                 
994     Rmax.push_back (corners[0].r);                
995   }                                               
996                                                   
997   // next planes until last                       
998   //                                              
999   G4int inextr=0, inextl=0;                       
1000   for (G4int i=0; i < numPlanes-2; ++i)          
1001   {                                              
1002     inextr=1+icurr;                              
1003     inextl=(icurl <= 0)? numPlanes-1 : icurl-    
1004                                                  
1005     if((corners[inextr].z >= Zmax) & (corners    
1006                                                  
1007     G4double Zleft = corners[inextl].z;          
1008     G4double Zright = corners[inextr].z;         
1009     if(Zright > Zleft)  // Next plane will be    
1010     {                                            
1011       Z.push_back(Zleft);                        
1012       countPlanes++;                             
1013       G4double difZr=corners[inextr].z - corn    
1014       G4double difZl=corners[inextl].z - corn    
1015                                                  
1016       if(std::fabs(difZl) < kCarTolerance)       
1017       {                                          
1018         if(std::fabs(difZr) < kCarTolerance)     
1019         {                                        
1020           Rmin.push_back(corners[inextl].r);     
1021           Rmax.push_back(corners[icurr].r);      
1022         }                                        
1023         else                                     
1024         {                                        
1025           Rmin.push_back(corners[inextl].r);     
1026           Rmax.push_back(corners[icurr].r + (    
1027                                 *(corners[ine    
1028         }                                        
1029       }                                          
1030       else if (difZl >= kCarTolerance)           
1031       {                                          
1032         if(std::fabs(difZr) < kCarTolerance)     
1033         {                                        
1034           Rmin.push_back(corners[icurl].r);      
1035           Rmax.push_back(corners[icurr].r);      
1036         }                                        
1037         else                                     
1038         {                                        
1039           Rmin.push_back(corners[icurl].r);      
1040           Rmax.push_back(corners[icurr].r + (    
1041                                 *(corners[ine    
1042         }                                        
1043       }                                          
1044       else                                       
1045       {                                          
1046         isConvertible=false; break;              
1047       }                                          
1048       icurl=(icurl == 0)? numPlanes-1 : icurl    
1049     }                                            
1050     else if(std::fabs(Zright-Zleft)<kCarToler    
1051     {                                            
1052       Z.push_back(Zleft);                        
1053       ++countPlanes;                             
1054       ++icurr;                                   
1055                                                  
1056       icurl=(icurl == 0)? numPlanes-1 : icurl    
1057                                                  
1058       Rmin.push_back(corners[inextl].r);         
1059       Rmax.push_back(corners[inextr].r);         
1060     }                                            
1061     else  // Zright<Zleft                        
1062     {                                            
1063       Z.push_back(Zright);                       
1064       ++countPlanes;                             
1065                                                  
1066       G4double difZr=corners[inextr].z - corn    
1067       G4double difZl=corners[inextl].z - corn    
1068       if(std::fabs(difZr) < kCarTolerance)       
1069       {                                          
1070         if(std::fabs(difZl) < kCarTolerance)     
1071         {                                        
1072           Rmax.push_back(corners[inextr].r);     
1073           Rmin.push_back(corners[icurr].r);      
1074         }                                        
1075         else                                     
1076         {                                        
1077           Rmin.push_back(corners[icurl].r + (    
1078                                 *(corners[ine    
1079           Rmax.push_back(corners[inextr].r);     
1080         }                                        
1081         ++icurr;                                 
1082       }           // plate                       
1083       else if (difZr >= kCarTolerance)           
1084       {                                          
1085         if(std::fabs(difZl) < kCarTolerance)     
1086         {                                        
1087           Rmax.push_back(corners[inextr].r);     
1088           Rmin.push_back (corners[icurr].r);     
1089         }                                        
1090         else                                     
1091         {                                        
1092           Rmax.push_back(corners[inextr].r);     
1093           Rmin.push_back (corners[icurl].r+(Z    
1094                                   * (corners[    
1095         }                                        
1096         ++icurr;                                 
1097       }                                          
1098       else                                       
1099       {                                          
1100         isConvertible=false; break;              
1101       }                                          
1102     }                                            
1103   }   // end for loop                            
1104                                                  
1105   // last plane Z=Zmax                           
1106   //                                             
1107   Z.push_back(Zmax);                             
1108   ++countPlanes;                                 
1109   inextr=1+icurr;                                
1110   inextl=(icurl <= 0)? numPlanes-1 : icurl-1;    
1111                                                  
1112   Rmax.push_back(corners[inextr].r);             
1113   Rmin.push_back(corners[inextl].r);             
1114                                                  
1115   // Set original parameters Rmin,Rmax,Z         
1116   //                                             
1117   if(isConvertible)                              
1118   {                                              
1119    original_parameters = new G4PolyconeHistor    
1120    original_parameters->Z_values = new G4doub    
1121    original_parameters->Rmin = new G4double[c    
1122    original_parameters->Rmax = new G4double[c    
1123                                                  
1124    for(G4int j=0; j < countPlanes; ++j)          
1125    {                                             
1126      original_parameters->Z_values[j] = Z[j];    
1127      original_parameters->Rmax[j] = Rmax[j];     
1128      original_parameters->Rmin[j] = Rmin[j];     
1129    }                                             
1130    original_parameters->Start_angle = startPh    
1131    original_parameters->Opening_angle = endPh    
1132    original_parameters->Num_z_planes = countP    
1133                                                  
1134   }                                              
1135   else  // Set parameters(r,z) with Rmin==0 a    
1136   {                                              
1137 #ifdef G4SPECSDEBUG                              
1138     std::ostringstream message;                  
1139     message << "Polycone " << GetName() << G4    
1140             << "cannot be converted to Polyco    
1141     G4Exception("G4Polycone::SetOriginalParam    
1142                 JustWarning, message);           
1143 #endif                                           
1144     original_parameters = new G4PolyconeHisto    
1145     original_parameters->Z_values = new G4dou    
1146     original_parameters->Rmin = new G4double[    
1147     original_parameters->Rmax = new G4double[    
1148                                                  
1149     for(G4int j=0; j < numPlanes; ++j)           
1150     {                                            
1151       original_parameters->Z_values[j] = corn    
1152       original_parameters->Rmax[j] = corners[    
1153       original_parameters->Rmin[j] = 0.0;        
1154     }                                            
1155     original_parameters->Start_angle = startP    
1156     original_parameters->Opening_angle = endP    
1157     original_parameters->Num_z_planes = numPl    
1158   }                                              
1159   return isConvertible;                          
1160 }                                                
1161                                                  
1162 #endif                                           
1163