Geant4 Cross Reference

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


  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 // G4TwistedTubs implementation                   
 27 //                                                
 28 // 01-Aug-2002 - Kotoyo Hoshina (hoshina@hepbu    
 29 // 13-Nov-2003 - O.Link (Oliver.Link@cern.ch),    
 30 //               from original version in Jupi    
 31 // -------------------------------------------    
 32                                                   
 33 #include "G4TwistedTubs.hh"                       
 34                                                   
 35 #include "G4GeomTools.hh"                         
 36 #include "G4PhysicalConstants.hh"                 
 37 #include "G4SystemOfUnits.hh"                     
 38 #include "G4GeometryTolerance.hh"                 
 39 #include "G4VoxelLimits.hh"                       
 40 #include "G4AffineTransform.hh"                   
 41 #include "G4BoundingEnvelope.hh"                  
 42 #include "G4ClippablePolygon.hh"                  
 43 #include "G4VPVParameterisation.hh"               
 44 #include "meshdefs.hh"                            
 45                                                   
 46 #include "G4VGraphicsScene.hh"                    
 47 #include "G4Polyhedron.hh"                        
 48 #include "G4VisExtent.hh"                         
 49                                                   
 50 #include "Randomize.hh"                           
 51                                                   
 52 #include "G4AutoLock.hh"                          
 53                                                   
 54 namespace                                         
 55 {                                                 
 56   G4Mutex polyhedronMutex = G4MUTEX_INITIALIZE    
 57 }                                                 
 58                                                   
 59                                                   
 60 //============================================    
 61 //* constructors -----------------------------    
 62                                                   
 63 G4TwistedTubs::G4TwistedTubs(const G4String& p    
 64                                    G4double  t    
 65                                    G4double  e    
 66                                    G4double  e    
 67                                    G4double  h    
 68                                    G4double  d    
 69    : G4VSolid(pname), fDPhi(dphi),                
 70      fLowerEndcap(nullptr), fUpperEndcap(nullp    
 71      fFormerTwisted(nullptr), fInnerHype(nullp    
 72 {                                                 
 73    if (endinnerrad < DBL_MIN)                     
 74    {                                              
 75       G4Exception("G4TwistedTubs::G4TwistedTub    
 76                   FatalErrorInArgument, "Inval    
 77    }                                              
 78                                                   
 79    G4double sinhalftwist = std::sin(0.5 * twis    
 80                                                   
 81    G4double endinnerradX = endinnerrad * sinha    
 82    G4double innerrad     = std::sqrt( endinner    
 83                                  - endinnerrad    
 84                                                   
 85    G4double endouterradX = endouterrad * sinha    
 86    G4double outerrad     = std::sqrt( endouter    
 87                                  - endouterrad    
 88                                                   
 89    // temporary treatment!!                       
 90    SetFields(twistedangle, innerrad, outerrad,    
 91    CreateSurfaces();                              
 92 }                                                 
 93                                                   
 94 G4TwistedTubs::G4TwistedTubs(const G4String& p    
 95                                    G4double  t    
 96                                    G4double  e    
 97                                    G4double  e    
 98                                    G4double  h    
 99                                    G4int     n    
100                                    G4double  t    
101    : G4VSolid(pname),                             
102      fLowerEndcap(nullptr), fUpperEndcap(nullp    
103      fFormerTwisted(nullptr), fInnerHype(nullp    
104 {                                                 
105                                                   
106    if (nseg == 0)                                 
107    {                                              
108       std::ostringstream message;                 
109       message << "Invalid number of segments."    
110               << "        nseg = " << nseg;       
111       G4Exception("G4TwistedTubs::G4TwistedTub    
112                   FatalErrorInArgument, messag    
113    }                                              
114    if (totphi == DBL_MIN || endinnerrad < DBL_    
115    {                                              
116       G4Exception("G4TwistedTubs::G4TwistedTub    
117                 FatalErrorInArgument, "Invalid    
118    }                                              
119                                                   
120    G4double sinhalftwist = std::sin(0.5 * twis    
121                                                   
122    G4double endinnerradX = endinnerrad * sinha    
123    G4double innerrad     = std::sqrt( endinner    
124                                  - endinnerrad    
125                                                   
126    G4double endouterradX = endouterrad * sinha    
127    G4double outerrad     = std::sqrt( endouter    
128                                  - endouterrad    
129                                                   
130    // temporary treatment!!                       
131    fDPhi = totphi / nseg;                         
132    SetFields(twistedangle, innerrad, outerrad,    
133    CreateSurfaces();                              
134 }                                                 
135                                                   
136 G4TwistedTubs::G4TwistedTubs(const G4String& p    
137                                    G4double  t    
138                                    G4double  i    
139                                    G4double  o    
140                                    G4double  n    
141                                    G4double  p    
142                                    G4double  d    
143    : G4VSolid(pname), fDPhi(dphi),                
144      fLowerEndcap(nullptr), fUpperEndcap(nullp    
145      fFormerTwisted(nullptr), fInnerHype(nullp    
146 {                                                 
147    if (innerrad < DBL_MIN)                        
148    {                                              
149       G4Exception("G4TwistedTubs::G4TwistedTub    
150                   FatalErrorInArgument, "Inval    
151    }                                              
152                                                   
153    SetFields(twistedangle, innerrad, outerrad,    
154    CreateSurfaces();                              
155 }                                                 
156                                                   
157 G4TwistedTubs::G4TwistedTubs(const G4String& p    
158                                    G4double  t    
159                                    G4double  i    
160                                    G4double  o    
161                                    G4double  n    
162                                    G4double  p    
163                                    G4int     n    
164                                    G4double  t    
165    : G4VSolid(pname),                             
166      fLowerEndcap(nullptr), fUpperEndcap(nullp    
167      fFormerTwisted(nullptr), fInnerHype(nullp    
168 {                                                 
169    if (nseg == 0)                                 
170    {                                              
171       std::ostringstream message;                 
172       message << "Invalid number of segments."    
173               << "        nseg = " << nseg;       
174       G4Exception("G4TwistedTubs::G4TwistedTub    
175                   FatalErrorInArgument, messag    
176    }                                              
177    if (totphi == DBL_MIN || innerrad < DBL_MIN    
178    {                                              
179       G4Exception("G4TwistedTubs::G4TwistedTub    
180                 FatalErrorInArgument, "Invalid    
181    }                                              
182                                                   
183    fDPhi = totphi / nseg;                         
184    SetFields(twistedangle, innerrad, outerrad,    
185    CreateSurfaces();                              
186 }                                                 
187                                                   
188 //============================================    
189 //* Fake default constructor -----------------    
190                                                   
191 G4TwistedTubs::G4TwistedTubs( __void__& a )       
192   : G4VSolid(a),                                  
193     fLowerEndcap(nullptr), fUpperEndcap(nullpt    
194     fLatterTwisted(nullptr), fFormerTwisted(nu    
195     fInnerHype(nullptr), fOuterHype(nullptr)      
196 {                                                 
197 }                                                 
198                                                   
199 //============================================    
200 //* destructor -------------------------------    
201                                                   
202 G4TwistedTubs::~G4TwistedTubs()                   
203 {                                                 
204    delete fLowerEndcap;                           
205    delete fUpperEndcap;                           
206    delete fLatterTwisted;                         
207    delete fFormerTwisted;                         
208    delete fInnerHype;                             
209    delete fOuterHype;                             
210    delete fpPolyhedron; fpPolyhedron = nullptr    
211 }                                                 
212                                                   
213 //============================================    
214 //* Copy constructor -------------------------    
215                                                   
216 G4TwistedTubs::G4TwistedTubs(const G4TwistedTu    
217   : G4VSolid(rhs), fPhiTwist(rhs.fPhiTwist),      
218     fInnerRadius(rhs.fInnerRadius), fOuterRadi    
219     fDPhi(rhs.fDPhi), fZHalfLength(rhs.fZHalfL    
220     fInnerStereo(rhs.fInnerStereo), fOuterSter    
221     fTanInnerStereo(rhs.fTanInnerStereo), fTan    
222     fKappa(rhs.fKappa), fInnerRadius2(rhs.fInn    
223     fOuterRadius2(rhs.fOuterRadius2), fTanInne    
224     fTanOuterStereo2(rhs.fTanOuterStereo2),       
225     fLowerEndcap(nullptr), fUpperEndcap(nullpt    
226     fInnerHype(nullptr), fOuterHype(nullptr),     
227     fCubicVolume(rhs.fCubicVolume), fSurfaceAr    
228 {                                                 
229   for (auto i=0; i<2; ++i)                        
230   {                                               
231     fEndZ[i] = rhs.fEndZ[i];                      
232     fEndInnerRadius[i] = rhs.fEndInnerRadius[i    
233     fEndOuterRadius[i] = rhs.fEndOuterRadius[i    
234     fEndPhi[i] = rhs.fEndPhi[i];                  
235     fEndZ2[i] = rhs.fEndZ2[i];                    
236   }                                               
237   CreateSurfaces();                               
238 }                                                 
239                                                   
240                                                   
241 //============================================    
242 //* Assignment operator ----------------------    
243                                                   
244 G4TwistedTubs& G4TwistedTubs::operator = (cons    
245 {                                                 
246    // Check assignment to self                    
247    //                                             
248    if (this == &rhs)  { return *this; }           
249                                                   
250    // Copy base class data                        
251    //                                             
252    G4VSolid::operator=(rhs);                      
253                                                   
254    // Copy data                                   
255    //                                             
256    fPhiTwist= rhs.fPhiTwist;                      
257    fInnerRadius= rhs.fInnerRadius; fOuterRadiu    
258    fDPhi= rhs.fDPhi; fZHalfLength= rhs.fZHalfL    
259    fInnerStereo= rhs.fInnerStereo; fOuterStere    
260    fTanInnerStereo= rhs.fTanInnerStereo; fTanO    
261    fKappa= rhs.fKappa; fInnerRadius2= rhs.fInn    
262    fOuterRadius2= rhs.fOuterRadius2; fTanInner    
263    fTanOuterStereo2= rhs.fTanOuterStereo2;        
264    fLowerEndcap= fUpperEndcap= fLatterTwisted=    
265    fInnerHype= fOuterHype= nullptr;               
266    fCubicVolume= rhs.fCubicVolume; fSurfaceAre    
267                                                   
268    for (auto i=0; i<2; ++i)                       
269    {                                              
270      fEndZ[i] = rhs.fEndZ[i];                     
271      fEndInnerRadius[i] = rhs.fEndInnerRadius[    
272      fEndOuterRadius[i] = rhs.fEndOuterRadius[    
273      fEndPhi[i] = rhs.fEndPhi[i];                 
274      fEndZ2[i] = rhs.fEndZ2[i];                   
275    }                                              
276                                                   
277    CreateSurfaces();                              
278    fRebuildPolyhedron = false;                    
279    delete fpPolyhedron; fpPolyhedron = nullptr    
280                                                   
281    return *this;                                  
282 }                                                 
283                                                   
284 //============================================    
285 //* ComputeDimensions ------------------------    
286                                                   
287 void G4TwistedTubs::ComputeDimensions(G4VPVPar    
288                                       const G4    
289                                       const G4    
290 {                                                 
291   G4Exception("G4TwistedTubs::ComputeDimension    
292               "GeomSolids0001", FatalException    
293               "G4TwistedTubs does not support     
294 }                                                 
295                                                   
296 //============================================    
297 //* BoundingLimits ---------------------------    
298                                                   
299 void G4TwistedTubs::BoundingLimits(G4ThreeVect    
300                                    G4ThreeVect    
301 {                                                 
302   // Find bounding tube                           
303   G4double rmin = GetInnerRadius();               
304   G4double rmax = GetEndOuterRadius();            
305                                                   
306   G4double zmin = std::min(GetEndZ(0), GetEndZ    
307   G4double zmax = std::max(GetEndZ(0), GetEndZ    
308                                                   
309   G4double dphi = 0.5*GetDPhi();                  
310   G4double sphi = std::min(GetEndPhi(0), GetEn    
311   G4double ephi = std::max(GetEndPhi(0), GetEn    
312   G4double totalphi = ephi - sphi;                
313                                                   
314   // Find bounding box                            
315   if (dphi <= 0 || totalphi >= CLHEP::twopi)      
316   {                                               
317     pMin.set(-rmax,-rmax, zmin);                  
318     pMax.set( rmax, rmax, zmax);                  
319   }                                               
320   else                                            
321   {                                               
322     G4TwoVector vmin,vmax;                        
323     G4GeomTools::DiskExtent(rmin, rmax, sphi,     
324     pMin.set(vmin.x(), vmin.y(), zmin);           
325     pMax.set(vmax.x(), vmax.y(), zmax);           
326   }                                               
327                                                   
328   // Check correctness of the bounding box        
329   //                                              
330   if (pMin.x() >= pMax.x() || pMin.y() >= pMax    
331   {                                               
332     std::ostringstream message;                   
333     message << "Bad bounding box (min >= max)     
334             << GetName() << " !"                  
335             << "\npMin = " << pMin                
336             << "\npMax = " << pMax;               
337     G4Exception("G4TwistedTubs::BoundingLimits    
338                 JustWarning, message);            
339     DumpInfo();                                   
340   }                                               
341 }                                                 
342                                                   
343 //============================================    
344 //* CalculateExtent --------------------------    
345                                                   
346 G4bool                                            
347 G4TwistedTubs::CalculateExtent(const EAxis pAx    
348                                const G4VoxelLi    
349                                const G4AffineT    
350                                      G4double&    
351 {                                                 
352   G4ThreeVector bmin, bmax;                       
353                                                   
354   // Get bounding box                             
355   BoundingLimits(bmin,bmax);                      
356                                                   
357   // Find extent                                  
358   G4BoundingEnvelope bbox(bmin,bmax);             
359   return bbox.CalculateExtent(pAxis,pVoxelLimi    
360 }                                                 
361                                                   
362                                                   
363 //============================================    
364 //* Inside -----------------------------------    
365                                                   
366 EInside G4TwistedTubs::Inside(const G4ThreeVec    
367 {                                                 
368                                                   
369    const G4double halftol                         
370      = 0.5 * G4GeometryTolerance::GetInstance(    
371    // static G4int timerid = -1;                  
372    // G4Timer timer(timerid, "G4TwistedTubs",     
373    // timer.Start();                              
374                                                   
375                                                   
376    EInside  outerhypearea = ((G4TwistTubsHypeS    
377    G4double innerhyperho  = ((G4TwistTubsHypeS    
378    G4double distanceToOut = p.getRho() - inner    
379    EInside       tmpinside;                       
380    if ((outerhypearea == kOutside) || (distanc    
381    {                                              
382       tmpinside = kOutside;                       
383    }                                              
384    else if (outerhypearea == kSurface)            
385    {                                              
386       tmpinside = kSurface;                       
387    }                                              
388    else                                           
389    {                                              
390       if (distanceToOut <= halftol)               
391       {                                           
392          tmpinside = kSurface;                    
393       }                                           
394       else                                        
395       {                                           
396          tmpinside = kInside;                     
397       }                                           
398    }                                              
399                                                   
400    return tmpinside;                              
401 }                                                 
402                                                   
403 //============================================    
404 //* SurfaceNormal ----------------------------    
405                                                   
406 G4ThreeVector G4TwistedTubs::SurfaceNormal(con    
407 {                                                 
408    //                                             
409    // return the normal unit vector to the Hyp    
410    // p on (or nearly on) the surface             
411    //                                             
412    // Which of the three or four surfaces are     
413    //                                             
414                                                   
415                                                   
416    G4double      distance = kInfinity;            
417                                                   
418    G4VTwistSurface *surfaces[6];                  
419    surfaces[0] = fLatterTwisted;                  
420    surfaces[1] = fFormerTwisted;                  
421    surfaces[2] = fInnerHype;                      
422    surfaces[3] = fOuterHype;                      
423    surfaces[4] = fLowerEndcap;                    
424    surfaces[5] = fUpperEndcap;                    
425                                                   
426    G4ThreeVector xx;                              
427    G4ThreeVector bestxx;                          
428    G4int besti = -1;                              
429    for (auto i=0; i<6; ++i)                       
430    {                                              
431       G4double tmpdistance = surfaces[i]->Dist    
432       if (tmpdistance < distance)                 
433       {                                           
434          distance = tmpdistance;                  
435          bestxx = xx;                             
436          besti = i;                               
437       }                                           
438    }                                              
439                                                   
440   return surfaces[besti]->GetNormal(bestxx, tr    
441 }                                                 
442                                                   
443 //============================================    
444 //* DistanceToIn (p, v) ----------------------    
445                                                   
446 G4double G4TwistedTubs::DistanceToIn (const G4    
447                                       const G4    
448 {                                                 
449                                                   
450    // DistanceToIn (p, v):                        
451    // Calculate distance to surface of shape f    
452    // along with the v, allowing for tolerance    
453    // The function returns kInfinity if no int    
454    // just grazing within tolerance.              
455                                                   
456    //                                             
457    // Calculate DistanceToIn(p,v)                 
458    //                                             
459                                                   
460    EInside currentside = Inside(p);               
461                                                   
462    if (currentside == kInside)                    
463    {                                              
464    }                                              
465    else                                           
466    {                                              
467      if (currentside == kSurface)                 
468      {                                            
469        // particle is just on a boundary.         
470        // If the particle is entering to the v    
471        //                                         
472        G4ThreeVector normal = SurfaceNormal(p)    
473        if (normal*v < 0)                          
474        {                                          
475          return 0;                                
476        }                                          
477      }                                            
478    }                                              
479                                                   
480    // now, we can take smallest positive dista    
481                                                   
482    // Initialize                                  
483    //                                             
484    G4double      distance = kInfinity;            
485                                                   
486    // find intersections and choose nearest on    
487    //                                             
488    G4VTwistSurface* surfaces[6];                  
489    surfaces[0] = fLowerEndcap;                    
490    surfaces[1] = fUpperEndcap;                    
491    surfaces[2] = fLatterTwisted;                  
492    surfaces[3] = fFormerTwisted;                  
493    surfaces[4] = fInnerHype;                      
494    surfaces[5] = fOuterHype;                      
495                                                   
496    G4ThreeVector xx;                              
497    G4ThreeVector bestxx;                          
498    for (const auto & surface : surfaces)          
499    {                                              
500       G4double tmpdistance = surface->Distance    
501       if (tmpdistance < distance)                 
502       {                                           
503          distance = tmpdistance;                  
504          bestxx = xx;                             
505       }                                           
506    }                                              
507    return distance;                               
508 }                                                 
509                                                   
510 //============================================    
511 //* DistanceToIn (p) -------------------------    
512                                                   
513 G4double G4TwistedTubs::DistanceToIn (const G4    
514 {                                                 
515    // DistanceToIn(p):                            
516    // Calculate distance to surface of shape f    
517    // allowing for tolerance                      
518                                                   
519    //                                             
520    // Calculate DistanceToIn(p)                   
521    //                                             
522                                                   
523    EInside currentside = Inside(p);               
524                                                   
525    switch (currentside)                           
526    {                                              
527       case (kInside) :                            
528       {}                                          
529       case (kSurface) :                           
530       {                                           
531          return 0;                                
532       }                                           
533       case (kOutside) :                           
534       {                                           
535          // Initialize                            
536          G4double distance = kInfinity;           
537                                                   
538          // find intersections and choose near    
539          G4VTwistSurface *surfaces[6];            
540          surfaces[0] = fLowerEndcap;              
541          surfaces[1] = fUpperEndcap;              
542          surfaces[2] = fLatterTwisted;            
543          surfaces[3] = fFormerTwisted;            
544          surfaces[4] = fInnerHype;                
545          surfaces[5] = fOuterHype;                
546                                                   
547          G4ThreeVector xx;                        
548          G4ThreeVector bestxx;                    
549          for (const auto & surface : surfaces)    
550          {                                        
551             G4double tmpdistance = surface->Di    
552             if (tmpdistance < distance)           
553             {                                     
554                distance = tmpdistance;            
555                bestxx = xx;                       
556             }                                     
557          }                                        
558          return distance;                         
559       }                                           
560       default :                                   
561       {                                           
562          G4Exception("G4TwistedTubs::DistanceT    
563                      FatalException, "Unknown     
564       }                                           
565    } // switch end                                
566                                                   
567    return kInfinity;                              
568 }                                                 
569                                                   
570 //============================================    
571 //* DistanceToOut (p, v) ---------------------    
572                                                   
573 G4double G4TwistedTubs::DistanceToOut( const G    
574                                        const G    
575                                        const G    
576                                        G4bool     
577                                        G4Three    
578 {                                                 
579    // DistanceToOut (p, v):                       
580    // Calculate distance to surface of shape f    
581    // along with the v, allowing for tolerance    
582    // The function returns kInfinity if no int    
583    // just grazing within tolerance.              
584                                                   
585    //                                             
586    // Calculate DistanceToOut(p,v)                
587    //                                             
588                                                   
589    EInside currentside = Inside(p);               
590    if (currentside == kOutside)                   
591    {                                              
592    }                                              
593    else                                           
594    {                                              
595      if (currentside == kSurface)                 
596      {                                            
597        // particle is just on a boundary.         
598        // If the particle is exiting from the     
599        //                                         
600        G4ThreeVector normal = SurfaceNormal(p)    
601        if (normal*v > 0)                          
602        {                                          
603          if (calcNorm)                            
604          {                                        
605            *norm = normal;                        
606            *validNorm = true;                     
607          }                                        
608          return 0;                                
609        }                                          
610      }                                            
611    }                                              
612                                                   
613    // now, we can take smallest positive dista    
614                                                   
615    // Initialize                                  
616    //                                             
617    G4double distance = kInfinity;                 
618                                                   
619    // find intersections and choose nearest on    
620    //                                             
621    G4VTwistSurface* surfaces[6];                  
622    surfaces[0] = fLatterTwisted;                  
623    surfaces[1] = fFormerTwisted;                  
624    surfaces[2] = fInnerHype;                      
625    surfaces[3] = fOuterHype;                      
626    surfaces[4] = fLowerEndcap;                    
627    surfaces[5] = fUpperEndcap;                    
628                                                   
629    G4int besti = -1;                              
630    G4ThreeVector xx;                              
631    G4ThreeVector bestxx;                          
632    for (auto i=0; i<6; ++i)                       
633    {                                              
634       G4double tmpdistance = surfaces[i]->Dist    
635       if (tmpdistance < distance)                 
636       {                                           
637          distance = tmpdistance;                  
638          bestxx = xx;                             
639          besti = i;                               
640       }                                           
641    }                                              
642                                                   
643    if (calcNorm)                                  
644    {                                              
645       if (besti != -1)                            
646       {                                           
647          *norm = (surfaces[besti]->GetNormal(p    
648          *validNorm = surfaces[besti]->IsValid    
649       }                                           
650    }                                              
651                                                   
652    return distance;                               
653 }                                                 
654                                                   
655                                                   
656 //============================================    
657 //* DistanceToOut (p) ------------------------    
658                                                   
659 G4double G4TwistedTubs::DistanceToOut( const G    
660 {                                                 
661    // DistanceToOut(p):                           
662    // Calculate distance to surface of shape f    
663    // allowing for tolerance                      
664                                                   
665    //                                             
666    // Calculate DistanceToOut(p)                  
667    //                                             
668                                                   
669    EInside currentside = Inside(p);               
670                                                   
671    switch (currentside)                           
672    {                                              
673       case (kOutside) :                           
674       {                                           
675       }                                           
676       case (kSurface) :                           
677       {                                           
678          return 0;                                
679       }                                           
680       case (kInside) :                            
681       {                                           
682          // Initialize                            
683          G4double      distance = kInfinity;      
684                                                   
685          // find intersections and choose near    
686          G4VTwistSurface* surfaces[6];            
687          surfaces[0] = fLatterTwisted;            
688          surfaces[1] = fFormerTwisted;            
689          surfaces[2] = fInnerHype;                
690          surfaces[3] = fOuterHype;                
691          surfaces[4] = fLowerEndcap;              
692          surfaces[5] = fUpperEndcap;              
693                                                   
694          G4ThreeVector xx;                        
695          G4ThreeVector bestxx;                    
696          for (const auto & surface : surfaces)    
697          {                                        
698             G4double tmpdistance = surface->Di    
699             if (tmpdistance < distance)           
700             {                                     
701                distance = tmpdistance;            
702                bestxx = xx;                       
703             }                                     
704          }                                        
705          return distance;                         
706       }                                           
707       default :                                   
708       {                                           
709          G4Exception("G4TwistedTubs::DistanceT    
710                      FatalException, "Unknown     
711       }                                           
712    } // switch end                                
713                                                   
714    return 0.;                                     
715 }                                                 
716                                                   
717 //============================================    
718 //* StreamInfo -------------------------------    
719                                                   
720 std::ostream& G4TwistedTubs::StreamInfo(std::o    
721 {                                                 
722   //                                              
723   // Stream object contents to an output strea    
724   //                                              
725   G4long oldprc = os.precision(16);               
726   os << "-------------------------------------    
727      << "    *** Dump for solid - " << GetName    
728      << "    =================================    
729      << " Solid type: G4TwistedTubs\n"            
730      << " Parameters: \n"                         
731      << "    -ve end Z              : " << fEn    
732      << "    +ve end Z              : " << fEn    
733      << "    inner end radius(-ve z): " << fEn    
734      << "    inner end radius(+ve z): " << fEn    
735      << "    outer end radius(-ve z): " << fEn    
736      << "    outer end radius(+ve z): " << fEn    
737      << "    inner radius (z=0)     : " << fIn    
738      << "    outer radius (z=0)     : " << fOu    
739      << "    twisted angle          : " << fPh    
740      << "    inner stereo angle     : " << fIn    
741      << "    outer stereo angle     : " << fOu    
742      << "    phi-width of a piece   : " << fDP    
743      << "-------------------------------------    
744   os.precision(oldprc);                           
745                                                   
746   return os;                                      
747 }                                                 
748                                                   
749                                                   
750 //============================================    
751 //* DiscribeYourselfTo -----------------------    
752                                                   
753 void G4TwistedTubs::DescribeYourselfTo (G4VGra    
754 {                                                 
755   scene.AddSolid (*this);                         
756 }                                                 
757                                                   
758 //============================================    
759 //* GetExtent --------------------------------    
760                                                   
761 G4VisExtent G4TwistedTubs::GetExtent() const      
762 {                                                 
763   // Define the sides of the box into which th    
764   //                                              
765   G4ThreeVector pmin,pmax;                        
766   BoundingLimits(pmin,pmax);                      
767   return { pmin.x(),pmax.x(),                     
768            pmin.y(),pmax.y(),                     
769            pmin.z(),pmax.z() };                   
770 }                                                 
771                                                   
772 //============================================    
773 //* CreatePolyhedron -------------------------    
774                                                   
775 G4Polyhedron* G4TwistedTubs::CreatePolyhedron     
776 {                                                 
777   // number of meshes                             
778   //                                              
779   G4double absPhiTwist = std::abs(fPhiTwist);     
780   G4double dA = std::max(fDPhi,absPhiTwist);      
781   const G4int k =                                 
782     G4int(G4Polyhedron::GetNumberOfRotationSte    
783   const G4int n =                                 
784     G4int(G4Polyhedron::GetNumberOfRotationSte    
785                                                   
786   const G4int nnodes = 4*(k-1)*(n-2) + 2*k*k ;    
787   const G4int nfaces = 4*(k-1)*(n-1) + 2*(k-1)    
788                                                   
789   auto ph = new G4Polyhedron;                     
790   typedef G4double G4double3[3];                  
791   typedef G4int G4int4[4];                        
792   auto xyz = new G4double3[nnodes];  // number    
793   auto faces = new G4int4[nfaces] ;  // number    
794   fLowerEndcap->GetFacets(k,k,xyz,faces,0) ;      
795   fUpperEndcap->GetFacets(k,k,xyz,faces,1) ;      
796   fInnerHype->GetFacets(k,n,xyz,faces,2) ;        
797   fFormerTwisted->GetFacets(k,n,xyz,faces,3) ;    
798   fOuterHype->GetFacets(k,n,xyz,faces,4) ;        
799   fLatterTwisted->GetFacets(k,n,xyz,faces,5) ;    
800                                                   
801   ph->createPolyhedron(nnodes,nfaces,xyz,faces    
802                                                   
803   delete[] xyz;                                   
804   delete[] faces;                                 
805                                                   
806   return ph;                                      
807 }                                                 
808                                                   
809 //============================================    
810 //* GetPolyhedron ----------------------------    
811                                                   
812 G4Polyhedron* G4TwistedTubs::GetPolyhedron ()     
813 {                                                 
814   if (fpPolyhedron == nullptr ||                  
815       fRebuildPolyhedron ||                       
816       fpPolyhedron->GetNumberOfRotationStepsAt    
817       fpPolyhedron->GetNumberOfRotationSteps()    
818   {                                               
819     G4AutoLock l(&polyhedronMutex);               
820     delete fpPolyhedron;                          
821     fpPolyhedron = CreatePolyhedron();            
822     fRebuildPolyhedron = false;                   
823     l.unlock();                                   
824   }                                               
825   return fpPolyhedron;                            
826 }                                                 
827                                                   
828 //============================================    
829 //* CreateSurfaces ---------------------------    
830                                                   
831 void G4TwistedTubs::CreateSurfaces()              
832 {                                                 
833    // create 6 surfaces of TwistedTub             
834                                                   
835    G4ThreeVector x0(0, 0, fEndZ[0]);              
836    G4ThreeVector n (0, 0, -1);                    
837                                                   
838    fLowerEndcap = new G4TwistTubsFlatSide("Low    
839                                     fEndInnerR    
840                                     fDPhi, fEn    
841                                                   
842    fUpperEndcap = new G4TwistTubsFlatSide("Upp    
843                                     fEndInnerR    
844                                     fDPhi, fEn    
845                                                   
846    G4RotationMatrix    rotHalfDPhi;               
847    rotHalfDPhi.rotateZ(0.5*fDPhi);                
848                                                   
849    fLatterTwisted = new G4TwistTubsSide("Latte    
850                                          fEndI    
851                                          fDPhi    
852                                          fInne    
853                                          1 ) ;    
854    fFormerTwisted = new G4TwistTubsSide("Forme    
855                                          fEndI    
856                                          fDPhi    
857                                          fInne    
858                                          -1 )     
859                                                   
860    fInnerHype = new G4TwistTubsHypeSide("Inner    
861                                         fEndIn    
862                                         fDPhi,    
863                                         fInner    
864                                         fTanIn    
865    fOuterHype = new G4TwistTubsHypeSide("Outer    
866                                         fEndIn    
867                                         fDPhi,    
868                                         fInner    
869                                         fTanIn    
870                                                   
871                                                   
872    // set neighbour surfaces                      
873    //                                             
874    fLowerEndcap->SetNeighbours(fInnerHype, fLa    
875                                fOuterHype, fFo    
876    fUpperEndcap->SetNeighbours(fInnerHype, fLa    
877                                fOuterHype, fFo    
878    fLatterTwisted->SetNeighbours(fInnerHype, f    
879                                  fOuterHype, f    
880    fFormerTwisted->SetNeighbours(fInnerHype, f    
881                                  fOuterHype, f    
882    fInnerHype->SetNeighbours(fLatterTwisted, f    
883                              fFormerTwisted, f    
884    fOuterHype->SetNeighbours(fLatterTwisted, f    
885                              fFormerTwisted, f    
886 }                                                 
887                                                   
888                                                   
889 //============================================    
890 //* GetEntityType ----------------------------    
891                                                   
892 G4GeometryType G4TwistedTubs::GetEntityType()     
893 {                                                 
894   return {"G4TwistedTubs"};                       
895 }                                                 
896                                                   
897 //============================================    
898 //* Clone ------------------------------------    
899                                                   
900 G4VSolid* G4TwistedTubs::Clone() const            
901 {                                                 
902   return new G4TwistedTubs(*this);                
903 }                                                 
904                                                   
905 //============================================    
906 //* GetCubicVolume ---------------------------    
907                                                   
908 G4double G4TwistedTubs::GetCubicVolume()          
909 {                                                 
910   if (fCubicVolume == 0.)                         
911   {                                               
912     G4double DPhi  = GetDPhi();                   
913     G4double Z0    = GetEndZ(0);                  
914     G4double Z1    = GetEndZ(1);                  
915     G4double Ain   = GetInnerRadius();            
916     G4double Aout  = GetOuterRadius();            
917     G4double R0in  = GetEndInnerRadius(0);        
918     G4double R1in  = GetEndInnerRadius(1);        
919     G4double R0out = GetEndOuterRadius(0);        
920     G4double R1out = GetEndOuterRadius(1);        
921                                                   
922     // V_hyperboloid = pi*h*(2*a*a + R*R)/3       
923     fCubicVolume = (2.*(Z1 - Z0)*(Aout + Ain)*    
924                     + Z1*(R1out + R1in)*(R1out    
925                     - Z0*(R0out + R0in)*(R0out    
926   }                                               
927   return fCubicVolume;                            
928 }                                                 
929                                                   
930 //============================================    
931 //* GetLateralArea ---------------------------    
932                                                   
933 G4double                                          
934 G4TwistedTubs::GetLateralArea(G4double a, G4do    
935 {                                                 
936   if (z == 0) return 0.;                          
937   G4double h = std::abs(z);                       
938   G4double area = h*a;                            
939   if (std::abs(a - r) > kCarTolerance)            
940   {                                               
941     G4double aa = a*a;                            
942     G4double hh = h*h;                            
943     G4double rr = r*r;                            
944     G4double cc = aa*hh/(rr - aa);                
945     G4double k  = std::sqrt(aa + cc)/cc;          
946     G4double kh = k*h;                            
947     area = 0.5*a*(h*std::sqrt(1. + kh*kh) + st    
948   }                                               
949   return GetDPhi()*area;                          
950 }                                                 
951                                                   
952 //============================================    
953 //* GetPhiCutArea ----------------------------    
954                                                   
955 G4double                                          
956 G4TwistedTubs::GetPhiCutArea(G4double a, G4dou    
957 {                                                 
958   if (GetDPhi() >= CLHEP::twopi || r <= 0 || z    
959   G4double h = std::abs(z);                       
960   G4double area = h*a;                            
961   if (GetPhiTwist() > kCarTolerance)              
962   {                                               
963     G4double sinw = std::sin(0.5*GetPhiTwist()    
964     G4double p = sinw*r/h;                        
965     G4double q = sinw*r/a;                        
966     G4double pp = p*p;                            
967     G4double qq = q*q;                            
968     G4double pq = p*q;                            
969     G4double sqroot = std::sqrt(pp + qq + 1);     
970     area = (pq*sqroot +                           
971             0.5*p*(pp + 3.)*std::atanh(q/sqroo    
972             0.5*q*(qq + 3.)*std::atanh(p/sqroo    
973             std::atan(sqroot/(pq)) - CLHEP::ha    
974   }                                               
975   return area;                                    
976 }                                                 
977                                                   
978 //============================================    
979 //* GetSurfaceArea ---------------------------    
980                                                   
981 G4double G4TwistedTubs::GetSurfaceArea()          
982 {                                                 
983   if (fSurfaceArea == 0.)                         
984   {                                               
985     G4double dphi = GetDPhi();                    
986     G4double Ainn = GetInnerRadius();             
987     G4double Aout = GetOuterRadius();             
988     G4double Rinn0 = GetEndInnerRadius(0);        
989     G4double Rout0 = GetEndOuterRadius(0);        
990     G4double Rinn1 = GetEndInnerRadius(1);        
991     G4double Rout1 = GetEndOuterRadius(1);        
992     G4double z0 = GetEndZ(0);                     
993     G4double z1 = GetEndZ(1);                     
994                                                   
995     G4double base0 = 0.5*dphi*(Rout0*Rout0 - R    
996     G4double inner0 = GetLateralArea(Ainn, Rin    
997     G4double outer0 = GetLateralArea(Aout, Rou    
998     G4double cut0 =                               
999       GetPhiCutArea(Aout, Rout0, z0) - GetPhiC    
1000                                                  
1001     G4double base1 = base0;                      
1002     G4double inner1 = inner0;                    
1003     G4double outer1 = outer0;                    
1004     G4double cut1 = cut0;                        
1005     if (std::abs(z0) != std::abs(z1))            
1006     {                                            
1007       base1 = 0.5*dphi*(Rout1*Rout1 - Rinn1*R    
1008       inner1 = GetLateralArea(Ainn, Rinn1, z1    
1009       outer1 = GetLateralArea(Aout, Rout1, z1    
1010       cut1 =                                     
1011       GetPhiCutArea(Aout, Rout1, z1) - GetPhi    
1012     }                                            
1013     fSurfaceArea = base0 + base1 +               
1014       ((z0*z1 < 0) ?                             
1015       (inner0 + inner1 + outer0 + outer1 + 2.    
1016       std::abs(inner0 - inner1 + outer0 - out    
1017   }                                              
1018   return fSurfaceArea;                           
1019 }                                                
1020                                                  
1021 //===========================================    
1022 //* GetPointOnSurface -----------------------    
1023                                                  
1024 G4ThreeVector G4TwistedTubs::GetPointOnSurfac    
1025 {                                                
1026                                                  
1027   G4double z = G4RandFlat::shoot(fEndZ[0],fEn    
1028   G4double phi , phimin, phimax ;                
1029   G4double x   , xmin,   xmax ;                  
1030   G4double r   , rmin,   rmax ;                  
1031                                                  
1032   G4double a1 = fOuterHype->GetSurfaceArea()     
1033   G4double a2 = fInnerHype->GetSurfaceArea()     
1034   G4double a3 = fLatterTwisted->GetSurfaceAre    
1035   G4double a4 = fFormerTwisted->GetSurfaceAre    
1036   G4double a5 = fLowerEndcap->GetSurfaceArea(    
1037   G4double a6 = fUpperEndcap->GetSurfaceArea(    
1038                                                  
1039   G4double chose = G4RandFlat::shoot(0.,a1 +     
1040                                                  
1041   if(chose < a1)                                 
1042   {                                              
1043                                                  
1044     phimin = fOuterHype->GetBoundaryMin(z) ;     
1045     phimax = fOuterHype->GetBoundaryMax(z) ;     
1046     phi = G4RandFlat::shoot(phimin,phimax) ;     
1047                                                  
1048     return fOuterHype->SurfacePoint(phi,z,tru    
1049                                                  
1050   }                                              
1051   else if ( (chose >= a1) && (chose < a1 + a2    
1052   {                                              
1053                                                  
1054     phimin = fInnerHype->GetBoundaryMin(z) ;     
1055     phimax = fInnerHype->GetBoundaryMax(z) ;     
1056     phi = G4RandFlat::shoot(phimin,phimax) ;     
1057                                                  
1058     return fInnerHype->SurfacePoint(phi,z,tru    
1059                                                  
1060   }                                              
1061   else if ( (chose >= a1 + a2 ) && (chose < a    
1062   {                                              
1063                                                  
1064     xmin = fLatterTwisted->GetBoundaryMin(z)     
1065     xmax = fLatterTwisted->GetBoundaryMax(z)     
1066     x = G4RandFlat::shoot(xmin,xmax) ;           
1067                                                  
1068     return fLatterTwisted->SurfacePoint(x,z,t    
1069                                                  
1070   }                                              
1071   else if ( (chose >= a1 + a2 + a3  ) && (cho    
1072   {                                              
1073                                                  
1074     xmin = fFormerTwisted->GetBoundaryMin(z)     
1075     xmax = fFormerTwisted->GetBoundaryMax(z)     
1076     x = G4RandFlat::shoot(xmin,xmax) ;           
1077                                                  
1078     return fFormerTwisted->SurfacePoint(x,z,t    
1079    }                                             
1080   else if( (chose >= a1 + a2 + a3 + a4  )&&(c    
1081   {                                              
1082     rmin = GetEndInnerRadius(0) ;                
1083     rmax = GetEndOuterRadius(0) ;                
1084     r = std::sqrt(G4RandFlat::shoot()*(sqr(rm    
1085                                                  
1086     phimin = fLowerEndcap->GetBoundaryMin(r)     
1087     phimax = fLowerEndcap->GetBoundaryMax(r)     
1088     phi    = G4RandFlat::shoot(phimin,phimax)    
1089                                                  
1090     return fLowerEndcap->SurfacePoint(phi,r,t    
1091   }                                              
1092   else                                           
1093   {                                              
1094     rmin = GetEndInnerRadius(1) ;                
1095     rmax = GetEndOuterRadius(1) ;                
1096     r = rmin + (rmax-rmin)*std::sqrt(G4RandFl    
1097                                                  
1098     phimin = fUpperEndcap->GetBoundaryMin(r)     
1099     phimax = fUpperEndcap->GetBoundaryMax(r)     
1100     phi    = G4RandFlat::shoot(phimin,phimax)    
1101                                                  
1102     return fUpperEndcap->SurfacePoint(phi,r,t    
1103   }                                              
1104 }                                                
1105