Geant4 Cross Reference

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


  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 // G4VTwistedFaceted implementation               
 27 //                                                
 28 // Author: 04-Nov-2004 - O.Link (Oliver.Link@c    
 29 // -------------------------------------------    
 30                                                   
 31 #include "G4VTwistedFaceted.hh"                   
 32                                                   
 33 #include "G4PhysicalConstants.hh"                 
 34 #include "G4SystemOfUnits.hh"                     
 35 #include "G4VoxelLimits.hh"                       
 36 #include "G4AffineTransform.hh"                   
 37 #include "G4BoundingEnvelope.hh"                  
 38 #include "G4SolidExtentList.hh"                   
 39 #include "G4ClippablePolygon.hh"                  
 40 #include "G4VPVParameterisation.hh"               
 41 #include "G4GeometryTolerance.hh"                 
 42 #include "meshdefs.hh"                            
 43                                                   
 44 #include "G4VGraphicsScene.hh"                    
 45 #include "G4Polyhedron.hh"                        
 46 #include "G4VisExtent.hh"                         
 47                                                   
 48 #include "Randomize.hh"                           
 49                                                   
 50 #include "G4AutoLock.hh"                          
 51                                                   
 52 namespace                                         
 53 {                                                 
 54   G4Mutex polyhedronMutex = G4MUTEX_INITIALIZE    
 55 }                                                 
 56                                                   
 57                                                   
 58 //============================================    
 59 //* constructors -----------------------------    
 60                                                   
 61 G4VTwistedFaceted::                               
 62 G4VTwistedFaceted( const G4String& pname,         
 63                          G4double  PhiTwist,      
 64                          G4double  pDz,           
 65                          G4double  pTheta, //     
 66                          G4double  pPhi,   //     
 67                          G4double  pDy1,   //     
 68                          G4double  pDx1,   //     
 69                          G4double  pDx2,   //     
 70                          G4double  pDy2,   //     
 71                          G4double  pDx3,   //     
 72                          G4double  pDx4,   //     
 73                          G4double  pAlph ) //     
 74   : G4VSolid(pname),                              
 75     fLowerEndcap(nullptr), fUpperEndcap(nullpt    
 76     fSide90(nullptr), fSide180(nullptr), fSide    
 77 {                                                 
 78                                                   
 79   G4double pDytmp ;                               
 80   G4double fDxUp ;                                
 81   G4double fDxDown ;                              
 82                                                   
 83   fDx1 = pDx1 ;                                   
 84   fDx2 = pDx2 ;                                   
 85   fDx3 = pDx3 ;                                   
 86   fDx4 = pDx4 ;                                   
 87   fDy1 = pDy1 ;                                   
 88   fDy2 = pDy2 ;                                   
 89   fDz  = pDz  ;                                   
 90                                                   
 91   G4double kAngTolerance                          
 92     = G4GeometryTolerance::GetInstance()->GetA    
 93                                                   
 94   // maximum values                               
 95   //                                              
 96   fDxDown = ( fDx1 > fDx2 ? fDx1 : fDx2 ) ;       
 97   fDxUp   = ( fDx3 > fDx4 ? fDx3 : fDx4 ) ;       
 98   fDx     = ( fDxUp > fDxDown ? fDxUp : fDxDow    
 99   fDy     = ( fDy1 > fDy2 ? fDy1 : fDy2 ) ;       
100                                                   
101   // planarity check                              
102   //                                              
103   if ( fDx1 != fDx2 && fDx3 != fDx4 )             
104   {                                               
105     pDytmp = fDy1 * ( fDx3 - fDx4 ) / ( fDx1 -    
106     if ( std::fabs(pDytmp - fDy2) > kCarTolera    
107     {                                             
108       std::ostringstream message;                 
109       message << "Not planar surface in untwis    
110               << GetName() << G4endl              
111               << "fDy2 is " << fDy2 << " but s    
112               << pDytmp << ".";                   
113       G4Exception("G4VTwistedFaceted::G4VTwist    
114                   FatalErrorInArgument, messag    
115     }                                             
116   }                                               
117                                                   
118 #ifdef G4TWISTDEBUG                               
119   if ( fDx1 == fDx2 && fDx3 == fDx4 )             
120   {                                               
121       G4cout << "Trapezoid is a box" << G4endl    
122   }                                               
123                                                   
124 #endif                                            
125                                                   
126   if ( (  fDx1 == fDx2 && fDx3 != fDx4 ) || (     
127   {                                               
128     std::ostringstream message;                   
129     message << "Not planar surface in untwiste    
130             << GetName() << G4endl                
131             << "One endcap is rectangular, the    
132             << "For planarity reasons they hav    
133             << "on both sides.";                  
134     G4Exception("G4VTwistedFaceted::G4VTwisted    
135                 FatalErrorInArgument, message)    
136   }                                               
137                                                   
138   // twist angle                                  
139   //                                              
140   fPhiTwist = PhiTwist ;                          
141                                                   
142   // tilt angle                                   
143   //                                              
144   fAlph = pAlph ;                                 
145   fTAlph = std::tan(fAlph) ;                      
146                                                   
147   fTheta = pTheta ;                               
148   fPhi   = pPhi ;                                 
149                                                   
150   // dx in surface equation                       
151   //                                              
152   fdeltaX = 2 * fDz * std::tan(fTheta) * std::    
153                                                   
154   // dy in surface equation                       
155   //                                              
156   fdeltaY = 2 * fDz * std::tan(fTheta) * std::    
157                                                   
158   if  ( ( fDx1  <= 2*kCarTolerance)               
159          || ( fDx2  <= 2*kCarTolerance)           
160          || ( fDx3  <= 2*kCarTolerance)           
161          || ( fDx4  <= 2*kCarTolerance)           
162          || ( fDy1  <= 2*kCarTolerance)           
163          || ( fDy2  <= 2*kCarTolerance)           
164          || ( fDz   <= 2*kCarTolerance)           
165          || ( std::fabs(fPhiTwist) <= 2*kAngTo    
166          || ( std::fabs(fPhiTwist) >= pi/2 )      
167          || ( std::fabs(fAlph) >= pi/2 )          
168          || fTheta >= pi/2 || fTheta < 0          
169       )                                           
170   {                                               
171     std::ostringstream message;                   
172     message << "Invalid dimensions. Too small,    
173             << GetName() << G4endl                
174             << "fDx 1-4 = " << fDx1/cm << ", "    
175             << fDx3/cm << ", " << fDx4/cm << "    
176             << "fDy 1-2 = " << fDy1/cm << ", "    
177             << " cm" << G4endl                    
178             << "fDz = " << fDz/cm << " cm" <<     
179             << " twistangle " << fPhiTwist/deg    
180             << " phi,theta = " << fPhi/deg <<     
181     G4Exception("G4TwistedTrap::G4VTwistedFace    
182                 "GeomSolids0002", FatalErrorIn    
183   }                                               
184   CreateSurfaces();                               
185 }                                                 
186                                                   
187                                                   
188 //============================================    
189 //* Fake default constructor -----------------    
190                                                   
191 G4VTwistedFaceted::G4VTwistedFaceted( __void__    
192   : G4VSolid(a),                                  
193     fLowerEndcap(nullptr), fUpperEndcap(nullpt    
194     fSide0(nullptr), fSide90(nullptr), fSide18    
195 {                                                 
196 }                                                 
197                                                   
198                                                   
199 //============================================    
200 //* destructor -------------------------------    
201                                                   
202 G4VTwistedFaceted::~G4VTwistedFaceted()           
203 {                                                 
204   delete fLowerEndcap ;                           
205   delete fUpperEndcap ;                           
206                                                   
207   delete fSide0   ;                               
208   delete fSide90  ;                               
209   delete fSide180 ;                               
210   delete fSide270 ;                               
211   delete fpPolyhedron; fpPolyhedron = nullptr;    
212 }                                                 
213                                                   
214                                                   
215 //============================================    
216 //* Copy constructor -------------------------    
217                                                   
218 G4VTwistedFaceted::G4VTwistedFaceted(const G4V    
219   : G4VSolid(rhs),                                
220     fCubicVolume(rhs.fCubicVolume), fSurfaceAr    
221     fTheta(rhs.fTheta), fPhi(rhs.fPhi),           
222     fDy1(rhs.fDy1), fDx1(rhs.fDx1), fDx2(rhs.f    
223     fDx3(rhs.fDx3), fDx4(rhs.fDx4), fDz(rhs.fD    
224     fAlph(rhs.fAlph), fTAlph(rhs.fTAlph), fdel    
225     fdeltaY(rhs.fdeltaY), fPhiTwist(rhs.fPhiTw    
226     fUpperEndcap(nullptr), fSide0(nullptr), fS    
227 {                                                 
228   CreateSurfaces();                               
229 }                                                 
230                                                   
231                                                   
232 //============================================    
233 //* Assignment operator ----------------------    
234                                                   
235 G4VTwistedFaceted& G4VTwistedFaceted::operator    
236 {                                                 
237    // Check assignment to self                    
238    //                                             
239    if (this == &rhs)  { return *this; }           
240                                                   
241    // Copy base class data                        
242    //                                             
243    G4VSolid::operator=(rhs);                      
244                                                   
245    // Copy data                                   
246    //                                             
247    fTheta = rhs.fTheta; fPhi = rhs.fPhi;          
248    fDy1= rhs.fDy1; fDx1= rhs.fDx1; fDx2= rhs.f    
249    fDx3= rhs.fDx3; fDx4= rhs.fDx4; fDz= rhs.fD    
250    fAlph= rhs.fAlph; fTAlph= rhs.fTAlph; fdelt    
251    fdeltaY= rhs.fdeltaY; fPhiTwist= rhs.fPhiTw    
252    fUpperEndcap= nullptr; fSide0= nullptr; fSi    
253    fCubicVolume= rhs.fCubicVolume; fSurfaceAre    
254    fRebuildPolyhedron = false;                    
255    delete fpPolyhedron; fpPolyhedron = nullptr    
256                                                   
257    CreateSurfaces();                              
258                                                   
259    return *this;                                  
260 }                                                 
261                                                   
262                                                   
263 //============================================    
264 //* ComputeDimensions ------------------------    
265                                                   
266 void G4VTwistedFaceted::ComputeDimensions(G4VP    
267                                           cons    
268                                           cons    
269 {                                                 
270   G4Exception("G4VTwistedFaceted::ComputeDimen    
271               "GeomSolids0001", FatalException    
272               "G4VTwistedFaceted does not supp    
273 }                                                 
274                                                   
275                                                   
276 //============================================    
277 //* Extent -----------------------------------    
278                                                   
279 void G4VTwistedFaceted::BoundingLimits(G4Three    
280                                        G4Three    
281 {                                                 
282   G4double cosPhi = std::cos(fPhi);               
283   G4double sinPhi = std::sin(fPhi);               
284   G4double tanTheta = std::tan(fTheta);           
285   G4double tanAlpha = fTAlph;                     
286                                                   
287   G4double xmid1 = fDy1*tanAlpha;                 
288   G4double x1 = std::abs(xmid1 + fDx1);           
289   G4double x2 = std::abs(xmid1 - fDx1);           
290   G4double x3 = std::abs(xmid1 + fDx2);           
291   G4double x4 = std::abs(xmid1 - fDx2);           
292   G4double xmax1 = std::max(std::max(std::max(    
293   G4double rmax1 = std::sqrt(xmax1*xmax1 + fDy    
294                                                   
295   G4double xmid2 = fDy2*tanAlpha;                 
296   G4double x5 = std::abs(xmid2 + fDx3);           
297   G4double x6 = std::abs(xmid2 - fDx3);           
298   G4double x7 = std::abs(xmid2 + fDx4);           
299   G4double x8 = std::abs(xmid2 - fDx4);           
300   G4double xmax2 = std::max(std::max(std::max(    
301   G4double rmax2 = std::sqrt(xmax2*xmax2 + fDy    
302                                                   
303   G4double x0 = fDz*tanTheta*cosPhi;              
304   G4double y0 = fDz*tanTheta*sinPhi;              
305   G4double xmin = std::min(-x0 - rmax1, x0 - r    
306   G4double ymin = std::min(-y0 - rmax1, y0 - r    
307   G4double xmax = std::max(-x0 + rmax1, x0 + r    
308   G4double ymax = std::max(-y0 + rmax1, y0 + r    
309   pMin.set(xmin, ymin,-fDz);                      
310   pMax.set(xmax, ymax, fDz);                      
311 }                                                 
312                                                   
313                                                   
314 //============================================    
315 //* CalculateExtent --------------------------    
316                                                   
317 G4bool                                            
318 G4VTwistedFaceted::CalculateExtent( const EAxi    
319                                     const G4Vo    
320                                     const G4Af    
321                                           G4do    
322                                           G4do    
323 {                                                 
324   G4ThreeVector bmin, bmax;                       
325                                                   
326   // Get bounding box                             
327   BoundingLimits(bmin,bmax);                      
328                                                   
329   // Find extent                                  
330   G4BoundingEnvelope bbox(bmin,bmax);             
331   return bbox.CalculateExtent(pAxis,pVoxelLimi    
332 }                                                 
333                                                   
334                                                   
335 //============================================    
336 //* Inside -----------------------------------    
337                                                   
338 EInside G4VTwistedFaceted::Inside(const G4Thre    
339 {                                                 
340                                                   
341    EInside tmpin = kOutside ;                     
342                                                   
343    G4double phi = p.z()/(2*fDz) * fPhiTwist ;     
344    G4double cphi = std::cos(-phi) ;               
345    G4double sphi = std::sin(-phi) ;               
346                                                   
347    G4double px  = p.x() + fdeltaX * ( -phi/fPh    
348    G4double py  = p.y() + fdeltaY * ( -phi/fPh    
349    G4double pz  = p.z() ;                         
350                                                   
351    G4double posx = px * cphi - py * sphi   ;      
352    G4double posy = px * sphi + py * cphi   ;      
353    G4double posz = pz  ;                          
354                                                   
355    G4double xMin = Xcoef(posy,phi,fTAlph) - 2*    
356    G4double xMax = Xcoef(posy,phi,fTAlph) ;       
357                                                   
358    G4double yMax = GetValueB(phi)/2. ;  // b(p    
359    G4double yMin = -yMax ;                        
360                                                   
361 #ifdef G4TWISTDEBUG                               
362                                                   
363    G4cout << "inside called: p = " << p << G4e    
364    G4cout << "fDx1 = " << fDx1 << G4endl ;        
365    G4cout << "fDx2 = " << fDx2 << G4endl ;        
366    G4cout << "fDx3 = " << fDx3 << G4endl ;        
367    G4cout << "fDx4 = " << fDx4 << G4endl ;        
368                                                   
369    G4cout << "fDy1 = " << fDy1 << G4endl ;        
370    G4cout << "fDy2 = " << fDy2 << G4endl ;        
371                                                   
372    G4cout << "fDz  = " << fDz  << G4endl ;        
373                                                   
374    G4cout << "Tilt angle alpha = " << fAlph <<    
375    G4cout << "phi,theta = " << fPhi << " , " <    
376                                                   
377    G4cout << "Twist angle = " << fPhiTwist <<     
378                                                   
379    G4cout << "posx = " << posx << G4endl ;        
380    G4cout << "posy = " << posy << G4endl ;        
381    G4cout << "xMin = " << xMin << G4endl ;        
382    G4cout << "xMax = " << xMax << G4endl ;        
383    G4cout << "yMin = " << yMin << G4endl ;        
384    G4cout << "yMax = " << yMax << G4endl ;        
385                                                   
386 #endif                                            
387                                                   
388                                                   
389   if ( posx <= xMax - kCarTolerance*0.5           
390     && posx >= xMin + kCarTolerance*0.5 )         
391   {                                               
392     if ( posy <= yMax - kCarTolerance*0.5         
393       && posy >= yMin + kCarTolerance*0.5 )       
394     {                                             
395       if      (std::fabs(posz) <= fDz - kCarTo    
396       else if (std::fabs(posz) <= fDz + kCarTo    
397     }                                             
398     else if ( posy <= yMax + kCarTolerance*0.5    
399            && posy >= yMin - kCarTolerance*0.5    
400     {                                             
401       if (std::fabs(posz) <= fDz + kCarToleran    
402     }                                             
403   }                                               
404   else if ( posx <= xMax + kCarTolerance*0.5      
405          && posx >= xMin - kCarTolerance*0.5 )    
406   {                                               
407     if ( posy <= yMax + kCarTolerance*0.5         
408       && posy >= yMin - kCarTolerance*0.5 )       
409     {                                             
410       if (std::fabs(posz) <= fDz + kCarToleran    
411     }                                             
412   }                                               
413                                                   
414 #ifdef G4TWISTDEBUG                               
415   G4cout << "inside = " << tmpin << G4endl ;      
416 #endif                                            
417                                                   
418   return tmpin;                                   
419                                                   
420 }                                                 
421                                                   
422                                                   
423 //============================================    
424 //* SurfaceNormal ----------------------------    
425                                                   
426 G4ThreeVector G4VTwistedFaceted::SurfaceNormal    
427 {                                                 
428    //                                             
429    // return the normal unit vector to the Hyp    
430    // p on (or nearly on) the surface             
431    //                                             
432    // Which of the three or four surfaces are     
433    //                                             
434                                                   
435                                                   
436    G4double distance = kInfinity;                 
437                                                   
438    G4VTwistSurface* surfaces[6];                  
439                                                   
440    surfaces[0] = fSide0 ;                         
441    surfaces[1] = fSide90 ;                        
442    surfaces[2] = fSide180 ;                       
443    surfaces[3] = fSide270 ;                       
444    surfaces[4] = fLowerEndcap;                    
445    surfaces[5] = fUpperEndcap;                    
446                                                   
447    G4ThreeVector xx;                              
448    G4ThreeVector bestxx;                          
449    G4int i;                                       
450    G4int besti = -1;                              
451    for (i=0; i< 6; i++)                           
452    {                                              
453       G4double tmpdistance = surfaces[i]->Dist    
454       if (tmpdistance < distance)                 
455       {                                           
456          distance = tmpdistance;                  
457          bestxx = xx;                             
458          besti = i;                               
459       }                                           
460    }                                              
461                                                   
462    return surfaces[besti]->GetNormal(bestxx, t    
463 }                                                 
464                                                   
465                                                   
466 //============================================    
467 //* DistanceToIn (p, v) ----------------------    
468                                                   
469 G4double G4VTwistedFaceted::DistanceToIn (cons    
470                                           cons    
471 {                                                 
472                                                   
473    // DistanceToIn (p, v):                        
474    // Calculate distance to surface of shape f    
475    // along with the v, allowing for tolerance    
476    // The function returns kInfinity if no int    
477    // just grazing within tolerance.              
478                                                   
479    //                                             
480    // Calculate DistanceToIn(p,v)                 
481    //                                             
482                                                   
483    EInside currentside = Inside(p);               
484                                                   
485    if (currentside == kInside)                    
486    {                                              
487    }                                              
488    else if (currentside == kSurface)              
489    {                                              
490      // particle is just on a boundary.           
491      // if the particle is entering to the vol    
492      //                                           
493      G4ThreeVector normal = SurfaceNormal(p);     
494      if (normal*v < 0)                            
495      {                                            
496        return 0;                                  
497      }                                            
498    }                                              
499                                                   
500    // now, we can take smallest positive dista    
501                                                   
502    // Initialize                                  
503    //                                             
504    G4double distance = kInfinity;                 
505                                                   
506    // Find intersections and choose nearest on    
507    //                                             
508    G4VTwistSurface *surfaces[6];                  
509                                                   
510    surfaces[0] = fSide0;                          
511    surfaces[1] = fSide90 ;                        
512    surfaces[2] = fSide180 ;                       
513    surfaces[3] = fSide270 ;                       
514    surfaces[4] = fLowerEndcap;                    
515    surfaces[5] = fUpperEndcap;                    
516                                                   
517    G4ThreeVector xx;                              
518    G4ThreeVector bestxx;                          
519    for (const auto & surface : surfaces)          
520    {                                              
521 #ifdef G4TWISTDEBUG                               
522       G4cout << G4endl << "surface " << &surfa    
523 #endif                                            
524       G4double tmpdistance = surface->Distance    
525 #ifdef G4TWISTDEBUG                               
526       G4cout << "Solid DistanceToIn : distance    
527       G4cout << "intersection point = " << xx     
528 #endif                                            
529       if (tmpdistance < distance)                 
530       {                                           
531          distance = tmpdistance;                  
532          bestxx = xx;                             
533       }                                           
534    }                                              
535                                                   
536 #ifdef G4TWISTDEBUG                               
537    G4cout << "best distance = " << distance <<    
538 #endif                                            
539                                                   
540    // timer.Stop();                               
541    return distance;                               
542 }                                                 
543                                                   
544                                                   
545 //============================================    
546 //* DistanceToIn (p) -------------------------    
547                                                   
548 G4double G4VTwistedFaceted::DistanceToIn (cons    
549 {                                                 
550    // DistanceToIn(p):                            
551    // Calculate distance to surface of shape f    
552    // allowing for tolerance                      
553    //                                             
554                                                   
555    //                                             
556    // Calculate DistanceToIn(p)                   
557    //                                             
558                                                   
559    EInside currentside = Inside(p);               
560                                                   
561    switch (currentside)                           
562    {                                              
563       case (kInside) :                            
564       {                                           
565       }                                           
566                                                   
567       case (kSurface) :                           
568       {                                           
569          return 0;                                
570       }                                           
571                                                   
572       case (kOutside) :                           
573       {                                           
574          // Initialize                            
575          //                                       
576          G4double distance = kInfinity;           
577                                                   
578          // Find intersections and choose near    
579          //                                       
580          G4VTwistSurface* surfaces[6];            
581                                                   
582          surfaces[0] = fSide0;                    
583          surfaces[1] = fSide90 ;                  
584          surfaces[2] = fSide180 ;                 
585          surfaces[3] = fSide270 ;                 
586          surfaces[4] = fLowerEndcap;              
587          surfaces[5] = fUpperEndcap;              
588                                                   
589          G4ThreeVector xx;                        
590          G4ThreeVector bestxx;                    
591          for (const auto & surface : surfaces)    
592          {                                        
593             G4double tmpdistance = surface->Di    
594             if (tmpdistance < distance)           
595             {                                     
596                distance = tmpdistance;            
597                bestxx = xx;                       
598             }                                     
599          }                                        
600          return distance;                         
601       }                                           
602                                                   
603       default:                                    
604       {                                           
605          G4Exception("G4VTwistedFaceted::Dista    
606                      FatalException, "Unknown     
607       }                                           
608    } // switch end                                
609                                                   
610    return 0.;                                     
611 }                                                 
612                                                   
613                                                   
614 //============================================    
615 //* DistanceToOut (p, v) ---------------------    
616                                                   
617 G4double                                          
618 G4VTwistedFaceted::DistanceToOut( const G4Thre    
619                                   const G4Thre    
620                                   const G4bool    
621                                         G4bool    
622                                         G4Thre    
623 {                                                 
624    // DistanceToOut (p, v):                       
625    // Calculate distance to surface of shape f    
626    // along with the v, allowing for tolerance    
627    // The function returns kInfinity if no int    
628    // just grazing within tolerance.              
629                                                   
630    //                                             
631    // Calculate DistanceToOut(p,v)                
632    //                                             
633                                                   
634    EInside currentside = Inside(p);               
635                                                   
636    if (currentside == kOutside)                   
637    {                                              
638    }                                              
639    else if (currentside == kSurface)              
640    {                                              
641       // particle is just on a boundary.          
642       // if the particle is exiting from the v    
643       //                                          
644       G4ThreeVector normal = SurfaceNormal(p);    
645       if (normal*v > 0)                           
646       {                                           
647             if (calcNorm)                         
648             {                                     
649                *norm = normal;                    
650                *validNorm = true;                 
651             }                                     
652             // timer.Stop();                      
653             return 0;                             
654       }                                           
655    }                                              
656                                                   
657    // now, we can take smallest positive dista    
658                                                   
659    // Initialize                                  
660    G4double distance = kInfinity;                 
661                                                   
662    // find intersections and choose nearest on    
663    G4VTwistSurface *surfaces[6];                  
664                                                   
665    surfaces[0] = fSide0;                          
666    surfaces[1] = fSide90 ;                        
667    surfaces[2] = fSide180 ;                       
668    surfaces[3] = fSide270 ;                       
669    surfaces[4] = fLowerEndcap;                    
670    surfaces[5] = fUpperEndcap;                    
671                                                   
672    G4int besti = -1;                              
673    G4ThreeVector xx;                              
674    G4ThreeVector bestxx;                          
675    for (auto i=0; i<6 ; ++i)                      
676    {                                              
677       G4double tmpdistance = surfaces[i]->Dist    
678       if (tmpdistance < distance)                 
679       {                                           
680          distance = tmpdistance;                  
681          bestxx = xx;                             
682          besti = i;                               
683       }                                           
684    }                                              
685                                                   
686    if (calcNorm)                                  
687    {                                              
688       if (besti != -1)                            
689       {                                           
690          *norm = (surfaces[besti]->GetNormal(p    
691          *validNorm = surfaces[besti]->IsValid    
692       }                                           
693    }                                              
694                                                   
695    return distance;                               
696 }                                                 
697                                                   
698                                                   
699 //============================================    
700 //* DistanceToOut (p) ------------------------    
701                                                   
702 G4double G4VTwistedFaceted::DistanceToOut( con    
703 {                                                 
704    // DistanceToOut(p):                           
705    // Calculate distance to surface of shape f    
706    // allowing for tolerance                      
707                                                   
708    //                                             
709    // Calculate DistanceToOut(p)                  
710    //                                             
711                                                   
712    EInside currentside = Inside(p);               
713    G4double     retval = kInfinity;               
714                                                   
715    switch (currentside)                           
716    {                                              
717       case (kOutside) :                           
718       {                                           
719 #ifdef G4SPECSDEBUG                               
720         G4int oldprc = G4cout.precision(16) ;     
721         G4cout << G4endl ;                        
722         DumpInfo();                               
723         G4cout << "Position:"  << G4endl << G4    
724         G4cout << "p.x() = "   << p.x()/mm <<     
725         G4cout << "p.y() = "   << p.y()/mm <<     
726         G4cout << "p.z() = "   << p.z()/mm <<     
727         G4cout.precision(oldprc) ;                
728         G4Exception("G4VTwistedFaceted::Distan    
729                     JustWarning, "Point p is o    
730 #endif                                            
731         break;                                    
732       }                                           
733       case (kSurface) :                           
734       {                                           
735         retval = 0;                               
736         break;                                    
737       }                                           
738                                                   
739       case (kInside) :                            
740       {                                           
741         // Initialize                             
742         //                                        
743         G4double distance = kInfinity;            
744                                                   
745         // find intersections and choose neare    
746         //                                        
747         G4VTwistSurface* surfaces[6];             
748                                                   
749         surfaces[0] = fSide0;                     
750         surfaces[1] = fSide90 ;                   
751         surfaces[2] = fSide180 ;                  
752         surfaces[3] = fSide270 ;                  
753         surfaces[4] = fLowerEndcap;               
754         surfaces[5] = fUpperEndcap;               
755                                                   
756         G4ThreeVector xx;                         
757         G4ThreeVector bestxx;                     
758         for (const auto & surface : surfaces)     
759         {                                         
760           G4double tmpdistance = surface->Dist    
761           if (tmpdistance < distance)             
762           {                                       
763             distance = tmpdistance;               
764             bestxx = xx;                          
765           }                                       
766         }                                         
767         retval = distance;                        
768         break;                                    
769       }                                           
770                                                   
771       default :                                   
772       {                                           
773         G4Exception("G4VTwistedFaceted::Distan    
774                     FatalException, "Unknown p    
775         break;                                    
776       }                                           
777    } // switch end                                
778                                                   
779    return retval;                                 
780 }                                                 
781                                                   
782                                                   
783 //============================================    
784 //* StreamInfo -------------------------------    
785                                                   
786 std::ostream& G4VTwistedFaceted::StreamInfo(st    
787 {                                                 
788   //                                              
789   // Stream object contents to an output strea    
790   //                                              
791   G4long oldprc = os.precision(16);               
792   os << "-------------------------------------    
793      << "    *** Dump for solid - " << GetName    
794      << "    =================================    
795      << " Solid type: G4VTwistedFaceted\n"        
796      << " Parameters: \n"                         
797      << "  polar angle theta = "   <<  fTheta/    
798      << "  azimuthal angle phi = "  << fPhi/de    
799      << "  tilt angle  alpha = "   << fAlph/de    
800      << "  TWIST angle = "         << fPhiTwis    
801      << "  Half length along y (lower endcap)     
802      << G4endl                                    
803      << "  Half length along x (lower endcap,     
804      << G4endl                                    
805      << "  Half length along x (lower endcap,     
806      << G4endl                                    
807      << "  Half length along y (upper endcap)     
808      << G4endl                                    
809      << "  Half length along x (upper endcap,     
810      << G4endl                                    
811      << "  Half length along x (upper endcap,     
812      << G4endl                                    
813      << "-------------------------------------    
814   os.precision(oldprc);                           
815                                                   
816   return os;                                      
817 }                                                 
818                                                   
819                                                   
820 //============================================    
821 //* DiscribeYourselfTo -----------------------    
822                                                   
823 void G4VTwistedFaceted::DescribeYourselfTo (G4    
824 {                                                 
825   scene.AddSolid (*this);                         
826 }                                                 
827                                                   
828                                                   
829 //============================================    
830 //* GetExtent --------------------------------    
831                                                   
832 G4VisExtent G4VTwistedFaceted::GetExtent() con    
833 {                                                 
834   G4double maxRad = std::sqrt( fDx*fDx + fDy*f    
835                                                   
836   return { -maxRad, maxRad ,                      
837            -maxRad, maxRad ,                      
838            -fDz, fDz };                           
839 }                                                 
840                                                   
841                                                   
842 //============================================    
843 //* CreateSurfaces ---------------------------    
844                                                   
845 void G4VTwistedFaceted::CreateSurfaces()          
846 {                                                 
847                                                   
848   // create 6 surfaces of TwistedTub.             
849                                                   
850   if ( fDx1 == fDx2 && fDx3 == fDx4 )    // sp    
851   {                                               
852     fSide0   = new G4TwistBoxSide("0deg", fPhi    
853                           fDy1, fDx1, fDx1, fD    
854     fSide180 = new G4TwistBoxSide("180deg", fP    
855                           fDy1, fDx1, fDx1, fD    
856   }                                               
857   else   // default general case                  
858   {                                               
859     fSide0   = new G4TwistTrapAlphaSide("0deg"    
860                       fPhi, fDy1, fDx1, fDx2,     
861     fSide180 = new G4TwistTrapAlphaSide("180de    
862                  fPhi+pi, fDy1, fDx2, fDx1, fD    
863   }                                               
864                                                   
865   // create parallel sides                        
866   //                                              
867   fSide90 = new G4TwistTrapParallelSide("90deg    
868                       fPhi, fDy1, fDx1, fDx2,     
869   fSide270 = new G4TwistTrapParallelSide("270d    
870                  fPhi+pi, fDy1, fDx2, fDx1, fD    
871                                                   
872   // create endcaps                               
873   //                                              
874   fUpperEndcap = new G4TwistTrapFlatSide("Uppe    
875                                     fDz, fAlph    
876   fLowerEndcap = new G4TwistTrapFlatSide("Lowe    
877                                     fDz, fAlph    
878                                                   
879   // Set neighbour surfaces                       
880                                                   
881   fSide0->SetNeighbours(  fSide270 , fLowerEnd    
882   fSide90->SetNeighbours( fSide0   , fLowerEnd    
883   fSide180->SetNeighbours(fSide90  , fLowerEnd    
884   fSide270->SetNeighbours(fSide180 , fLowerEnd    
885   fUpperEndcap->SetNeighbours( fSide180, fSide    
886   fLowerEndcap->SetNeighbours( fSide180, fSide    
887                                                   
888 }                                                 
889                                                   
890 //============================================    
891 //* GetCubicVolume ---------------------------    
892                                                   
893 G4double G4VTwistedFaceted::GetCubicVolume()      
894 {                                                 
895   if(fCubicVolume == 0.)                          
896   {                                               
897     fCubicVolume = ((fDx1 + fDx2 + fDx3 + fDx4    
898                     (fDx4 + fDx3 - fDx2 - fDx1    
899   }                                               
900   return fCubicVolume;                            
901 }                                                 
902                                                   
903 //============================================    
904 //* GetLateralFaceArea -----------------------    
905                                                   
906 G4double                                          
907 G4VTwistedFaceted::GetLateralFaceArea(const G4    
908                                       const G4    
909                                       const G4    
910                                       const G4    
911 {                                                 
912   constexpr G4int NSTEP = 100;                    
913   constexpr G4double dt = 1./NSTEP;               
914                                                   
915   G4double h = 2.*fDz;                            
916   G4double hh = h*h;                              
917   G4double hTanTheta = h*std::tan(fTheta);        
918   G4double x1 = p1.x();                           
919   G4double y1 = p1.y();                           
920   G4double x21 = p2.x() - p1.x();                 
921   G4double y21 = p2.y() - p1.y();                 
922   G4double x31 = p3.x() - p1.x();                 
923   G4double y31 = p3.y() - p1.y();                 
924   G4double x42 = p4.x() - p2.x();                 
925   G4double y42 = p4.y() - p2.y();                 
926   G4double x43 = p4.x() - p3.x();                 
927   G4double y43 = p4.y() - p3.y();                 
928                                                   
929   // check if face is plane (just in case)        
930   G4double lmax = std::max(std::max(std::abs(x    
931                            std::max(std::abs(x    
932   G4double eps = lmax*kCarTolerance;              
933   if (std::abs(fPhiTwist) < kCarTolerance &&      
934       std::abs(x21*y43 - y21*x43) < eps)          
935   {                                               
936     G4double x0 = hTanTheta*std::cos(fPhi);       
937     G4double y0 = hTanTheta*std::sin(fPhi);       
938     G4ThreeVector A(p4.x() - p1.x() + x0, p4.y    
939     G4ThreeVector B(p3.x() - p2.x() + x0, p3.y    
940     return (A.cross(B)).mag()*0.5;                
941   }                                               
942                                                   
943   // twisted face                                 
944   G4double area = 0.;                             
945   for (G4int i = 0; i < NSTEP; ++i)               
946   {                                               
947     G4double t = (i + 0.5)*dt;                    
948     G4double I = x21 + (x42 - x31)*t;             
949     G4double J = y21 + (y42 - y31)*t;             
950     G4double II = I*I;                            
951     G4double JJ = J*J;                            
952     G4double IIJJ = hh*(I*I + J*J);               
953                                                   
954     G4double ang = fPhi + fPhiTwist*(0.5 - t);    
955     G4double A = fPhiTwist*(II + JJ) + x21*y43    
956     G4double B = fPhiTwist*(I*(x1 + x31*t) + J    
957       hTanTheta*(I*std::sin(ang) - J*std::cos(    
958       (I*y31 - J*x31);                            
959                                                   
960     G4double invAA = 1./(A*A);                    
961     G4double sqrtAA = 2.*std::abs(A);             
962     G4double invSqrtAA = 1./sqrtAA;               
963                                                   
964     G4double aa = A*A;                            
965     G4double bb = 2.*A*B;                         
966     G4double cc = IIJJ + B*B;                     
967                                                   
968     G4double R1 = std::sqrt(aa + bb + cc);        
969     G4double R0 = std::sqrt(cc);                  
970     G4double log1 = std::log(std::abs(sqrtAA*R    
971     G4double log0 = std::log(std::abs(sqrtAA*R    
972                                                   
973     area += 0.5*R1 + 0.25*bb*invAA*(R1 - R0) +    
974   }                                               
975   return area*dt;                                 
976 }                                                 
977                                                   
978 //============================================    
979 //* GetSurfaceArea ---------------------------    
980                                                   
981 G4double G4VTwistedFaceted::GetSurfaceArea()      
982 {                                                 
983   if (fSurfaceArea == 0.)                         
984   {                                               
985     G4TwoVector vv[8];                            
986     vv[0] = G4TwoVector(-fDx1 - fDy1*fTAlph,-f    
987     vv[1] = G4TwoVector( fDx1 - fDy1*fTAlph,-f    
988     vv[2] = G4TwoVector(-fDx2 + fDy1*fTAlph, f    
989     vv[3] = G4TwoVector( fDx2 + fDy1*fTAlph, f    
990     vv[4] = G4TwoVector(-fDx3 - fDy2*fTAlph,-f    
991     vv[5] = G4TwoVector( fDx3 - fDy2*fTAlph,-f    
992     vv[6] = G4TwoVector(-fDx4 + fDy2*fTAlph, f    
993     vv[7] = G4TwoVector( fDx4 + fDy2*fTAlph, f    
994     fSurfaceArea = 2.*(fDy1*(fDx1 + fDx2) + fD    
995       GetLateralFaceArea(vv[0], vv[1], vv[4],     
996       GetLateralFaceArea(vv[1], vv[3], vv[5],     
997       GetLateralFaceArea(vv[3], vv[2], vv[7],     
998       GetLateralFaceArea(vv[2], vv[0], vv[6],     
999   }                                               
1000   return fSurfaceArea;                           
1001 }                                                
1002                                                  
1003 //===========================================    
1004 //* GetEntityType ---------------------------    
1005                                                  
1006 G4GeometryType G4VTwistedFaceted::GetEntityTy    
1007 {                                                
1008   return {"G4VTwistedFaceted"};                  
1009 }                                                
1010                                                  
1011                                                  
1012 //===========================================    
1013 //* GetPolyhedron ---------------------------    
1014                                                  
1015 G4Polyhedron* G4VTwistedFaceted::GetPolyhedro    
1016 {                                                
1017   if (fpPolyhedron == nullptr ||                 
1018       fRebuildPolyhedron ||                      
1019       fpPolyhedron->GetNumberOfRotationStepsA    
1020       fpPolyhedron->GetNumberOfRotationSteps(    
1021     {                                            
1022       G4AutoLock l(&polyhedronMutex);            
1023       delete fpPolyhedron;                       
1024       fpPolyhedron = CreatePolyhedron();         
1025       fRebuildPolyhedron = false;                
1026       l.unlock();                                
1027     }                                            
1028                                                  
1029   return fpPolyhedron;                           
1030 }                                                
1031                                                  
1032                                                  
1033 //===========================================    
1034 //* GetPointInSolid -------------------------    
1035                                                  
1036 G4ThreeVector G4VTwistedFaceted::GetPointInSo    
1037 {                                                
1038                                                  
1039                                                  
1040   // this routine is only used for a test        
1041   // can be deleted ...                          
1042                                                  
1043   if ( z == fDz ) z -= 0.1*fDz ;                 
1044   if ( z == -fDz ) z += 0.1*fDz ;                
1045                                                  
1046   G4double phi = z/(2*fDz)*fPhiTwist ;           
1047                                                  
1048   return { fdeltaX * phi/fPhiTwist, fdeltaY *    
1049 }                                                
1050                                                  
1051                                                  
1052 //===========================================    
1053 //* GetPointOnSurface -----------------------    
1054                                                  
1055 G4ThreeVector G4VTwistedFaceted::GetPointOnSu    
1056 {                                                
1057                                                  
1058   G4double phi = G4RandFlat::shoot(-fPhiTwist    
1059   G4double u , umin, umax ;  //  variable for    
1060   G4double y  ;              //  variable for    
1061                                                  
1062   // Compute the areas. Attention: Only corre    
1063   // where the twisting is done along the z-a    
1064   // the computed surface area is more diffic    
1065   // does not affect the tracking through the    
1066                                                  
1067   G4double a1 = fSide0->GetSurfaceArea();        
1068   G4double a2 = fSide90->GetSurfaceArea();       
1069   G4double a3 = fSide180->GetSurfaceArea() ;     
1070   G4double a4 = fSide270->GetSurfaceArea() ;     
1071   G4double a5 = fLowerEndcap->GetSurfaceArea(    
1072   G4double a6 = fUpperEndcap->GetSurfaceArea(    
1073                                                  
1074 #ifdef G4TWISTDEBUG                              
1075   G4cout << "Surface 0   deg = " << a1 << G4e    
1076   G4cout << "Surface 90  deg = " << a2 << G4e    
1077   G4cout << "Surface 180 deg = " << a3 << G4e    
1078   G4cout << "Surface 270 deg = " << a4 << G4e    
1079   G4cout << "Surface Lower   = " << a5 << G4e    
1080   G4cout << "Surface Upper   = " << a6 << G4e    
1081 #endif                                           
1082                                                  
1083   G4double chose = G4RandFlat::shoot(0.,a1 +     
1084                                                  
1085   if(chose < a1)                                 
1086   {                                              
1087     umin = fSide0->GetBoundaryMin(phi) ;         
1088     umax = fSide0->GetBoundaryMax(phi) ;         
1089     u = G4RandFlat::shoot(umin,umax) ;           
1090                                                  
1091     return  fSide0->SurfacePoint(phi, u, true    
1092   }                                              
1093                                                  
1094   else if( (chose >= a1) && (chose < a1 + a2     
1095   {                                              
1096     umin = fSide90->GetBoundaryMin(phi) ;        
1097     umax = fSide90->GetBoundaryMax(phi) ;        
1098                                                  
1099     u = G4RandFlat::shoot(umin,umax) ;           
1100                                                  
1101     return fSide90->SurfacePoint(phi, u, true    
1102   }                                              
1103   else if( (chose >= a1 + a2 ) && (chose < a1    
1104   {                                              
1105     umin = fSide180->GetBoundaryMin(phi) ;       
1106     umax = fSide180->GetBoundaryMax(phi) ;       
1107     u = G4RandFlat::shoot(umin,umax) ;           
1108                                                  
1109     return fSide180->SurfacePoint(phi, u, tru    
1110   }                                              
1111   else if( (chose >= a1 + a2 + a3  ) && (chos    
1112   {                                              
1113     umin = fSide270->GetBoundaryMin(phi) ;       
1114     umax = fSide270->GetBoundaryMax(phi) ;       
1115     u = G4RandFlat::shoot(umin,umax) ;           
1116     return fSide270->SurfacePoint(phi, u, tru    
1117   }                                              
1118   else if( (chose >= a1 + a2 + a3 + a4  ) &&     
1119   {                                              
1120     y = G4RandFlat::shoot(-fDy1,fDy1) ;          
1121     umin = fLowerEndcap->GetBoundaryMin(y) ;     
1122     umax = fLowerEndcap->GetBoundaryMax(y) ;     
1123     u = G4RandFlat::shoot(umin,umax) ;           
1124                                                  
1125     return fLowerEndcap->SurfacePoint(u,y,tru    
1126   }                                              
1127   else                                           
1128   {                                              
1129     y = G4RandFlat::shoot(-fDy2,fDy2) ;          
1130     umin = fUpperEndcap->GetBoundaryMin(y) ;     
1131     umax = fUpperEndcap->GetBoundaryMax(y) ;     
1132     u = G4RandFlat::shoot(umin,umax) ;           
1133                                                  
1134     return fUpperEndcap->SurfacePoint(u,y,tru    
1135                                                  
1136   }                                              
1137 }                                                
1138                                                  
1139                                                  
1140 //===========================================    
1141 //* CreatePolyhedron ------------------------    
1142                                                  
1143 G4Polyhedron* G4VTwistedFaceted::CreatePolyhe    
1144 {                                                
1145   // number of meshes                            
1146   const G4int k =                                
1147   G4int(G4Polyhedron::GetNumberOfRotationStep    
1148         std::abs(fPhiTwist) / twopi) + 2;        
1149   const G4int n = k;                             
1150                                                  
1151   const G4int nnodes = 4*(k-1)*(n-2) + 2*k*k     
1152   const G4int nfaces = 4*(k-1)*(n-1) + 2*(k-1    
1153                                                  
1154   auto  ph = new G4Polyhedron;                   
1155   typedef G4double G4double3[3];                 
1156   typedef G4int G4int4[4];                       
1157   auto xyz = new G4double3[nnodes];  // numbe    
1158   auto faces = new G4int4[nfaces] ;  // numbe    
1159                                                  
1160   fLowerEndcap->GetFacets(k,k,xyz,faces,0) ;     
1161   fUpperEndcap->GetFacets(k,k,xyz,faces,1) ;     
1162   fSide270->GetFacets(k,n,xyz,faces,2) ;         
1163   fSide0->GetFacets(k,n,xyz,faces,3) ;           
1164   fSide90->GetFacets(k,n,xyz,faces,4) ;          
1165   fSide180->GetFacets(k,n,xyz,faces,5) ;         
1166                                                  
1167   ph->createPolyhedron(nnodes,nfaces,xyz,face    
1168                                                  
1169   return ph;                                     
1170 }                                                
1171