Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/solids/specific/src/G4TessellatedSolid.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/G4TessellatedSolid.cc (Version 11.3.0) and /geometry/solids/specific/src/G4TessellatedSolid.cc (Version 6.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 // * subject to DEFCON 705 IPR conditions.        
 21 // * By using,  copying,  modifying or  distri    
 22 // * any work based  on the software)  you  ag    
 23 // * use  in  resulting  scientific  publicati    
 24 // * acceptance of all terms of the Geant4 Sof    
 25 // *******************************************    
 26 //                                                
 27 // G4TessellatedSolid implementation              
 28 //                                                
 29 // 31.10.2004, P R Truscott, QinetiQ Ltd, UK -    
 30 // 17.09.2007, P R Truscott, QinetiQ Ltd & Ric    
 31 //                    Updated extensively prio    
 32 //                    concaved tessellated sur    
 33 //                    of Richard Holmberg.  Th    
 34 //                    to determine with inside    
 35 //                    random rays from the poi    
 36 //                    are predefined rather th    
 37 //                    number generator at run-    
 38 // 12.10.2012, M Gayer, CERN, complete rewrite    
 39 //                    requirements more than 5    
 40 //                    tens or more depending o    
 41 //                    to voxelization of surfa    
 42 //                    Speedup factor of thousa    
 43 //                    facets in hundreds of th    
 44 // 23.10.2016, E Tcherniaev, reimplemented Cal    
 45 //                    use of G4BoundingEnvelop    
 46 // -------------------------------------------    
 47                                                   
 48 #include "G4TessellatedSolid.hh"                  
 49                                                   
 50 #if !defined(G4GEOM_USE_UTESSELLATEDSOLID)        
 51                                                   
 52 #include <algorithm>                              
 53 #include <fstream>                                
 54 #include <iomanip>                                
 55 #include <iostream>                               
 56 #include <list>                                   
 57 #include <random>                                 
 58 #include <stack>                                  
 59                                                   
 60 #include "geomdefs.hh"                            
 61 #include "Randomize.hh"                           
 62 #include "G4SystemOfUnits.hh"                     
 63 #include "G4PhysicalConstants.hh"                 
 64 #include "G4GeometryTolerance.hh"                 
 65 #include "G4VoxelLimits.hh"                       
 66 #include "G4AffineTransform.hh"                   
 67 #include "G4BoundingEnvelope.hh"                  
 68                                                   
 69 #include "G4VGraphicsScene.hh"                    
 70 #include "G4VisExtent.hh"                         
 71                                                   
 72 #include "G4AutoLock.hh"                          
 73                                                   
 74 namespace                                         
 75 {                                                 
 76   G4Mutex polyhedronMutex = G4MUTEX_INITIALIZE    
 77 }                                                 
 78                                                   
 79 using namespace std;                              
 80                                                   
 81 //////////////////////////////////////////////    
 82 //                                                
 83 // Standard contructor has blank name and defi    
 84 //                                                
 85 G4TessellatedSolid::G4TessellatedSolid () : G4    
 86 {                                                 
 87   Initialize();                                   
 88 }                                                 
 89                                                   
 90 //////////////////////////////////////////////    
 91 //                                                
 92 // Alternative constructor. Simple define name    
 93 // to detine.                                     
 94 //                                                
 95 G4TessellatedSolid::G4TessellatedSolid (const     
 96   : G4VSolid(name)                                
 97 {                                                 
 98   Initialize();                                   
 99 }                                                 
100                                                   
101 //////////////////////////////////////////////    
102 //                                                
103 // Fake default constructor - sets only member    
104 //                            for usage restri    
105 //                                                
106 G4TessellatedSolid::G4TessellatedSolid( __void    
107 {                                                 
108   Initialize();                                   
109   fMinExtent.set(0,0,0);                          
110   fMaxExtent.set(0,0,0);                          
111 }                                                 
112                                                   
113                                                   
114 //////////////////////////////////////////////    
115 G4TessellatedSolid::~G4TessellatedSolid()         
116 {                                                 
117   DeleteObjects();                                
118 }                                                 
119                                                   
120 //////////////////////////////////////////////    
121 //                                                
122 // Copy constructor.                              
123 //                                                
124 G4TessellatedSolid::G4TessellatedSolid (const     
125   : G4VSolid(ts)                                  
126 {                                                 
127   Initialize();                                   
128                                                   
129   CopyObjects(ts);                                
130 }                                                 
131                                                   
132 //////////////////////////////////////////////    
133 //                                                
134 // Assignment operator.                           
135 //                                                
136 G4TessellatedSolid&                               
137 G4TessellatedSolid::operator= (const G4Tessell    
138 {                                                 
139   if (&ts == this) return *this;                  
140                                                   
141   // Copy base class data                         
142   G4VSolid::operator=(ts);                        
143                                                   
144   DeleteObjects ();                               
145                                                   
146   Initialize();                                   
147                                                   
148   CopyObjects (ts);                               
149                                                   
150   return *this;                                   
151 }                                                 
152                                                   
153 //////////////////////////////////////////////    
154 //                                                
155 void G4TessellatedSolid::Initialize()             
156 {                                                 
157   kCarToleranceHalf = 0.5*kCarTolerance;          
158                                                   
159   fRebuildPolyhedron = false; fpPolyhedron = n    
160   fCubicVolume = 0.; fSurfaceArea = 0.;           
161                                                   
162   fGeometryType = "G4TessellatedSolid";           
163   fSolidClosed  = false;                          
164                                                   
165   fMinExtent.set(kInfinity,kInfinity,kInfinity    
166   fMaxExtent.set(-kInfinity,-kInfinity,-kInfin    
167                                                   
168   SetRandomVectors();                             
169 }                                                 
170                                                   
171 //////////////////////////////////////////////    
172 //                                                
173 void G4TessellatedSolid::DeleteObjects()          
174 {                                                 
175   std::size_t size = fFacets.size();              
176   for (std::size_t i = 0; i < size; ++i)  { de    
177   fFacets.clear();                                
178   delete fpPolyhedron; fpPolyhedron = nullptr;    
179 }                                                 
180                                                   
181 //////////////////////////////////////////////    
182 //                                                
183 void G4TessellatedSolid::CopyObjects (const G4    
184 {                                                 
185   G4ThreeVector reductionRatio;                   
186   G4int fmaxVoxels = fVoxels.GetMaxVoxels(redu    
187   if (fmaxVoxels < 0)                             
188     fVoxels.SetMaxVoxels(reductionRatio);         
189   else                                            
190     fVoxels.SetMaxVoxels(fmaxVoxels);             
191                                                   
192   G4int n = ts.GetNumberOfFacets();               
193   for (G4int i = 0; i < n; ++i)                   
194   {                                               
195     G4VFacet *facetClone = (ts.GetFacet(i))->G    
196     AddFacet(facetClone);                         
197   }                                               
198   if (ts.GetSolidClosed()) SetSolidClosed(true    
199 }                                                 
200                                                   
201 //////////////////////////////////////////////    
202 //                                                
203 // Add a facet to the facet list.                 
204 // Note that you can add, but you cannot delet    
205 //                                                
206 G4bool G4TessellatedSolid::AddFacet (G4VFacet*    
207 {                                                 
208   // Add the facet to the vector.                 
209   //                                              
210   if (fSolidClosed)                               
211   {                                               
212     G4Exception("G4TessellatedSolid::AddFacet(    
213                 JustWarning, "Attempt to add f    
214     return false;                                 
215   }                                               
216   else if (aFacet->IsDefined())                   
217   {                                               
218     set<G4VertexInfo,G4VertexComparator>::iter    
219       = fFacetList.begin(), end = fFacetList.e    
220     G4ThreeVector p = aFacet->GetCircumcentre(    
221     G4VertexInfo value;                           
222     value.id = (G4int)fFacetList.size();          
223     value.mag2 = p.x() + p.y() + p.z();           
224                                                   
225     G4bool found = false;                         
226     if (!OutsideOfExtent(p, kCarTolerance))       
227     {                                             
228       G4double kCarTolerance3 = 3 * kCarTolera    
229       pos = fFacetList.lower_bound(value);        
230                                                   
231       it = pos;                                   
232       while (!found && it != end)    // Loop c    
233       {                                           
234         G4int id = (*it).id;                      
235         G4VFacet *facet = fFacets[id];            
236         G4ThreeVector q = facet->GetCircumcent    
237         if ((found = (facet == aFacet))) break    
238         G4double dif = q.x() + q.y() + q.z() -    
239         if (dif > kCarTolerance3) break;          
240         it++;                                     
241       }                                           
242                                                   
243       if (fFacets.size() > 1)                     
244       {                                           
245         it = pos;                                 
246         while (!found && it != begin)    // Lo    
247         {                                         
248           --it;                                   
249           G4int id = (*it).id;                    
250           G4VFacet *facet = fFacets[id];          
251           G4ThreeVector q = facet->GetCircumce    
252           found = (facet == aFacet);              
253           if (found) break;                       
254           G4double dif = value.mag2 - (q.x() +    
255           if (dif > kCarTolerance3) break;        
256         }                                         
257       }                                           
258     }                                             
259                                                   
260     if (!found)                                   
261     {                                             
262       fFacets.push_back(aFacet);                  
263       fFacetList.insert(value);                   
264     }                                             
265     return true;                                  
266   }                                               
267   else                                            
268   {                                               
269     G4Exception("G4TessellatedSolid::AddFacet(    
270                 JustWarning, "Attempt to add f    
271     aFacet->StreamInfo(G4cout);                   
272     return false;                                 
273   }                                               
274 }                                                 
275                                                   
276 //////////////////////////////////////////////    
277 //                                                
278 G4int G4TessellatedSolid::SetAllUsingStack(con    
279                                            con    
280                                            G4b    
281 {                                                 
282   vector<G4int> xyz = voxel;                      
283   stack<vector<G4int> > pos;                      
284   pos.push(xyz);                                  
285   G4int filled = 0;                               
286                                                   
287   vector<G4int> candidates;                       
288                                                   
289   while (!pos.empty())    // Loop checking, 13    
290   {                                               
291     xyz = pos.top();                              
292     pos.pop();                                    
293     G4int index = fVoxels.GetVoxelsIndex(xyz);    
294     if (!checked[index])                          
295     {                                             
296       checked.SetBitNumber(index, true);          
297                                                   
298       if (fVoxels.IsEmpty(index))                 
299       {                                           
300         ++filled;                                 
301                                                   
302         fInsides.SetBitNumber(index, status);     
303                                                   
304         for (auto i = 0; i <= 2; ++i)             
305         {                                         
306           if (xyz[i] < max[i] - 1)                
307           {                                       
308             xyz[i]++;                             
309             pos.push(xyz);                        
310             xyz[i]--;                             
311           }                                       
312                                                   
313           if (xyz[i] > 0)                         
314           {                                       
315             xyz[i]--;                             
316             pos.push(xyz);                        
317             xyz[i]++;                             
318           }                                       
319         }                                         
320       }                                           
321     }                                             
322   }                                               
323   return filled;                                  
324 }                                                 
325                                                   
326 //////////////////////////////////////////////    
327 //                                                
328 void G4TessellatedSolid::PrecalculateInsides()    
329 {                                                 
330   vector<G4int> voxel(3), maxVoxels(3);           
331   for (auto i = 0; i <= 2; ++i)                   
332     maxVoxels[i] = (G4int)fVoxels.GetBoundary(    
333   G4int size = maxVoxels[0] * maxVoxels[1] * m    
334                                                   
335   G4SurfBits checked(size-1);                     
336   fInsides.Clear();                               
337   fInsides.ResetBitNumber(size-1);                
338                                                   
339   G4ThreeVector point;                            
340   for (voxel[2] = 0; voxel[2] < maxVoxels[2] -    
341   {                                               
342     for (voxel[1] = 0; voxel[1] < maxVoxels[1]    
343     {                                             
344       for (voxel[0] = 0; voxel[0] < maxVoxels[    
345       {                                           
346         G4int index = fVoxels.GetVoxelsIndex(v    
347         if (!checked[index] && fVoxels.IsEmpty    
348         {                                         
349           for (auto i = 0; i <= 2; ++i)           
350           {                                       
351             point[i] = fVoxels.GetBoundary(i)[    
352           }                                       
353           auto inside = (G4bool) (InsideNoVoxe    
354           SetAllUsingStack(voxel, maxVoxels, i    
355         }                                         
356         else checked.SetBitNumber(index);         
357       }                                           
358     }                                             
359   }                                               
360 }                                                 
361                                                   
362 //////////////////////////////////////////////    
363 //                                                
364 void G4TessellatedSolid::Voxelize ()              
365 {                                                 
366 #ifdef G4SPECSDEBUG                               
367   G4cout << "Voxelizing..." << G4endl;            
368 #endif                                            
369   fVoxels.Voxelize(fFacets);                      
370                                                   
371   if (fVoxels.Empty().GetNbits() != 0u)           
372   {                                               
373 #ifdef G4SPECSDEBUG                               
374     G4cout << "Precalculating Insides..." << G    
375 #endif                                            
376     PrecalculateInsides();                        
377   }                                               
378 }                                                 
379                                                   
380 //////////////////////////////////////////////    
381 //                                                
382 // Compute extremeFacets, i.e. find those face    
383 // planes that bound the volume.                  
384 // Note that this is going to reject concaved     
385 // note that if the vertex is on the facet, di    
386 // returns true. So will this work??  Need non    
387 // "G4bool inside = displacement < 0.0;"          
388 // or                                             
389 // "G4bool inside = displacement <= -0.5*kCarT    
390 // (Notes from PT 13/08/2007).                    
391 //                                                
392 void G4TessellatedSolid::SetExtremeFacets()       
393 {                                                 
394   // Copy vertices to local array                 
395   std::size_t vsize = fVertexList.size();         
396   std::vector<G4ThreeVector> vertices(vsize);     
397   for (std::size_t i = 0; i < vsize; ++i) { ve    
398                                                   
399   // Shuffle vertices                             
400   std::mt19937 gen(12345678);                     
401   std::shuffle(vertices.begin(), vertices.end(    
402                                                   
403   // Select six extreme vertices in different     
404   G4ThreeVector points[6];                        
405   for (auto & point : points) { point = vertic    
406   for (std::size_t i=1; i < vsize; ++i)           
407   {                                               
408     if (vertices[i].x() < points[0].x()) point    
409     if (vertices[i].x() > points[1].x()) point    
410     if (vertices[i].y() < points[2].y()) point    
411     if (vertices[i].y() > points[3].y()) point    
412     if (vertices[i].z() < points[4].z()) point    
413     if (vertices[i].z() > points[5].z()) point    
414   }                                               
415                                                   
416   // Find extreme facets                          
417   std::size_t size = fFacets.size();              
418   for (std::size_t j = 0; j < size; ++j)          
419   {                                               
420     G4VFacet &facet = *fFacets[j];                
421                                                   
422     // Check extreme vertices                     
423     if (!facet.IsInside(points[0])) continue;     
424     if (!facet.IsInside(points[1])) continue;     
425     if (!facet.IsInside(points[2])) continue;     
426     if (!facet.IsInside(points[3])) continue;     
427     if (!facet.IsInside(points[4])) continue;     
428     if (!facet.IsInside(points[5])) continue;     
429                                                   
430     // Check vertices                             
431     G4bool isExtreme = true;                      
432     for (std::size_t i=0; i < vsize; ++i)         
433     {                                             
434       if (!facet.IsInside(vertices[i]))           
435       {                                           
436         isExtreme = false;                        
437         break;                                    
438       }                                           
439     }                                             
440     if (isExtreme) fExtremeFacets.insert(&face    
441   }                                               
442 }                                                 
443                                                   
444 //////////////////////////////////////////////    
445 //                                                
446 void G4TessellatedSolid::CreateVertexList()       
447 {                                                 
448   // The algorithm:                               
449   // we will have additional vertexListSorted,    
450   // sorted by magnitude of vertice vector.       
451   // New candidate for fVertexList - we will d    
452   // item which would be within its magnitude     
453   // We will go trough until we will reach > +    
454   // Comparison (q-p).mag() < 0.5*kCarToleranc    
455   // They can be just stored in std::vector, w    
456   // on binary search.                            
457                                                   
458   set<G4VertexInfo,G4VertexComparator> vertexL    
459   set<G4VertexInfo,G4VertexComparator>::iterat    
460      = vertexListSorted.begin(), end = vertexL    
461   G4ThreeVector p;                                
462   G4VertexInfo value;                             
463                                                   
464   fVertexList.clear();                            
465   std::size_t size = fFacets.size();              
466                                                   
467   G4double kCarTolerance24 = kCarTolerance * k    
468   G4double kCarTolerance3 = 3 * kCarTolerance;    
469   vector<G4int> newIndex(100);                    
470                                                   
471   for (std::size_t k = 0; k < size; ++k)          
472   {                                               
473     G4VFacet &facet = *fFacets[k];                
474     G4int max = facet.GetNumberOfVertices();      
475                                                   
476     for (G4int i = 0; i < max; ++i)               
477     {                                             
478       p = facet.GetVertex(i);                     
479       value.id = (G4int)fVertexList.size();       
480       value.mag2 = p.x() + p.y() + p.z();         
481                                                   
482       G4bool found = false;                       
483       G4int id = 0;                               
484       if (!OutsideOfExtent(p, kCarTolerance))     
485       {                                           
486         pos = vertexListSorted.lower_bound(val    
487         it = pos;                                 
488         while (it != end)    // Loop checking,    
489         {                                         
490           id = (*it).id;                          
491           G4ThreeVector q = fVertexList[id];      
492           G4double dif = (q-p).mag2();            
493           found = (dif < kCarTolerance24);        
494           if (found) break;                       
495           dif = q.x() + q.y() + q.z() - value.    
496           if (dif > kCarTolerance3) break;        
497           ++it;                                   
498         }                                         
499                                                   
500         if (!found && (fVertexList.size() > 1)    
501         {                                         
502           it = pos;                               
503           while (it != begin)    // Loop check    
504           {                                       
505             --it;                                 
506             id = (*it).id;                        
507             G4ThreeVector q = fVertexList[id];    
508             G4double dif = (q-p).mag2();          
509             found = (dif < kCarTolerance24);      
510             if (found) break;                     
511             dif = value.mag2 - (q.x() + q.y()     
512             if (dif > kCarTolerance3) break;      
513           }                                       
514         }                                         
515       }                                           
516                                                   
517       if (!found)                                 
518       {                                           
519 #ifdef G4SPECSDEBUG                               
520         G4cout << p.x() << ":" << p.y() << ":"    
521         G4cout << "Adding new vertex #" << i <    
522                << " id " << value.id << G4endl    
523         G4cout << "===" << G4endl;                
524 #endif                                            
525         fVertexList.push_back(p);                 
526         vertexListSorted.insert(value);           
527         begin = vertexListSorted.begin();         
528         end = vertexListSorted.end();             
529         newIndex[i] = value.id;                   
530         //                                        
531         // Now update the maximum x, y and z l    
532         //                                        
533         if (value.id == 0) fMinExtent = fMaxEx    
534         else                                      
535         {                                         
536           if (p.x() > fMaxExtent.x()) fMaxExte    
537           else if (p.x() < fMinExtent.x()) fMi    
538           if (p.y() > fMaxExtent.y()) fMaxExte    
539           else if (p.y() < fMinExtent.y()) fMi    
540           if (p.z() > fMaxExtent.z()) fMaxExte    
541           else if (p.z() < fMinExtent.z()) fMi    
542         }                                         
543       }                                           
544       else                                        
545       {                                           
546 #ifdef G4SPECSDEBUG                               
547         G4cout << p.x() << ":" << p.y() << ":"    
548         G4cout << "Vertex #" << i << " of face    
549                << " found, redirecting to " <<    
550         G4cout << "===" << G4endl;                
551 #endif                                            
552         newIndex[i] = id;                         
553       }                                           
554     }                                             
555     // only now it is possible to change verti    
556     //                                            
557     facet.SetVertices(&fVertexList);              
558     for (G4int i = 0; i < max; ++i)               
559       facet.SetVertexIndex(i,newIndex[i]);        
560   }                                               
561   vector<G4ThreeVector>(fVertexList).swap(fVer    
562                                                   
563 #ifdef G4SPECSDEBUG                               
564   G4double previousValue = 0.;                    
565   for (auto res=vertexListSorted.cbegin(); res    
566   {                                               
567     G4int id = (*res).id;                         
568     G4ThreeVector vec = fVertexList[id];          
569     G4double mvalue = vec.x() + vec.y() + vec.    
570     if (previousValue && (previousValue - 1e-9    
571       G4cout << "Error in CreateVertexList: pr    
572              <<  " is smaller than mvalue " <<    
573     previousValue = mvalue;                       
574   }                                               
575 #endif                                            
576 }                                                 
577                                                   
578 //////////////////////////////////////////////    
579 //                                                
580 void G4TessellatedSolid::DisplayAllocatedMemor    
581 {                                                 
582   G4int without = AllocatedMemoryWithoutVoxels    
583   G4int with = AllocatedMemory();                 
584   G4double ratio = (G4double) with / without;     
585   G4cout << "G4TessellatedSolid - Allocated me    
586          << without << "; with " << with << ";    
587 }                                                 
588                                                   
589 //////////////////////////////////////////////    
590 //                                                
591 void G4TessellatedSolid::SetSolidClosed (const    
592 {                                                 
593   if (t)                                          
594   {                                               
595 #ifdef G4SPECSDEBUG                               
596     G4cout << "Creating vertex list..." << G4e    
597 #endif                                            
598     CreateVertexList();                           
599                                                   
600 #ifdef G4SPECSDEBUG                               
601     G4cout << "Setting extreme facets..." << G    
602 #endif                                            
603     SetExtremeFacets();                           
604                                                   
605 #ifdef G4SPECSDEBUG                               
606     G4cout << "Voxelizing..." << G4endl;          
607 #endif                                            
608     Voxelize();                                   
609                                                   
610 #ifdef G4SPECSDEBUG                               
611     DisplayAllocatedMemory();                     
612 #endif                                            
613                                                   
614 #ifdef G4SPECSDEBUG                               
615     G4cout << "Checking Structure..." << G4end    
616 #endif                                            
617     G4int irep = CheckStructure();                
618     if (irep != 0)                                
619     {                                             
620       if ((irep & 1) != 0)                        
621       {                                           
622          std::ostringstream message;              
623          message << "Defects in solid: " << Ge    
624                  << " - negative cubic volume,    
625          G4Exception("G4TessellatedSolid::SetS    
626                      "GeomSolids1001", JustWar    
627       }                                           
628       if ((irep & 2) != 0)                        
629       {                                           
630          std::ostringstream message;              
631          message << "Defects in solid: " << Ge    
632                  << " - some facets have wrong    
633          G4Exception("G4TessellatedSolid::SetS    
634                      "GeomSolids1001", JustWar    
635       }                                           
636       if ((irep & 4) != 0)                        
637       {                                           
638          std::ostringstream message;              
639          message << "Defects in solid: " << Ge    
640                  << " - there are holes in the    
641          G4Exception("G4TessellatedSolid::SetS    
642                      "GeomSolids1001", JustWar    
643       }                                           
644     }                                             
645   }                                               
646   fSolidClosed = t;                               
647 }                                                 
648                                                   
649 //////////////////////////////////////////////    
650 //                                                
651 // GetSolidClosed                                 
652 //                                                
653 // Used to determine whether the solid is clos    
654 //                                                
655 G4bool G4TessellatedSolid::GetSolidClosed () c    
656 {                                                 
657   return fSolidClosed;                            
658 }                                                 
659                                                   
660 //////////////////////////////////////////////    
661 //                                                
662 // CheckStructure                                 
663 //                                                
664 // Checks structure of the solid. Return value    
665 // defect indicators, if any (0 means no defec    
666 //   1 - cubic volume is negative, wrong orien    
667 //   2 - some facets have wrong orientation       
668 //   4 - holes in the surface                     
669 //                                                
670 G4int G4TessellatedSolid::CheckStructure() con    
671 {                                                 
672   G4int nedge = 0;                                
673   std::size_t nface = fFacets.size();             
674                                                   
675   // Calculate volume                             
676   //                                              
677   G4double volume = 0.;                           
678   for (std::size_t i = 0; i < nface; ++i)         
679   {                                               
680     G4VFacet& facet = *fFacets[i];                
681     nedge += facet.GetNumberOfVertices();         
682     volume += facet.GetArea()*(facet.GetVertex    
683   }                                               
684   auto  ivolume = static_cast<G4int>(volume <=    
685                                                   
686   // Create sorted vector of edges                
687   //                                              
688   std::vector<int64_t> iedge(nedge);              
689   G4int kk = 0;                                   
690   for (std::size_t i = 0; i < nface; ++i)         
691   {                                               
692     G4VFacet& facet = *fFacets[i];                
693     G4int nnode = facet.GetNumberOfVertices();    
694     for (G4int k = 0; k < nnode; ++k)             
695     {                                             
696       int64_t i1 = facet.GetVertexIndex((k ==     
697       int64_t i2 = facet.GetVertexIndex(k);       
698       auto  inverse = static_cast<int64_t>(i2     
699       if (inverse != 0) std::swap(i1, i2);        
700       iedge[kk++] = i1*1000000000 + i2*2 + inv    
701     }                                             
702   }                                               
703   std::sort(iedge.begin(), iedge.end());          
704                                                   
705   // Check edges, correct structure should con    
706   // with different orientation                   
707   //                                              
708   G4int iorder = 0;                               
709   G4int ihole = 0;                                
710   G4int i = 0;                                    
711   while (i < nedge - 1)                           
712   {                                               
713     if (iedge[i + 1] - iedge[i] == 1) // paire    
714     {                                             
715       i += 2;                                     
716     }                                             
717     else if (iedge[i + 1] == iedge[i]) // pair    
718     {                                             
719       iorder = 2;                                 
720       i += 2;                                     
721     }                                             
722     else // unpaired edge                         
723     {                                             
724       ihole = 4;                                  
725       i++;                                        
726     }                                             
727   }                                               
728   return ivolume + iorder + ihole;                
729 }                                                 
730                                                   
731 //////////////////////////////////////////////    
732 //                                                
733 // operator+=                                     
734 //                                                
735 // This operator allows the user to add two te    
736 // that the solid on the left then includes al    
737 // on the right.  Note that copies of the face    
738 // using the original facet set of the solid o    
739 //                                                
740 G4TessellatedSolid&                               
741 G4TessellatedSolid::operator+=(const G4Tessell    
742 {                                                 
743   G4int size = right.GetNumberOfFacets();         
744   for (G4int i = 0; i < size; ++i)                
745     AddFacet(right.GetFacet(i)->GetClone());      
746                                                   
747   return *this;                                   
748 }                                                 
749                                                   
750 //////////////////////////////////////////////    
751 //                                                
752 // GetNumberOfFacets                              
753 //                                                
754 G4int G4TessellatedSolid::GetNumberOfFacets()     
755 {                                                 
756   return (G4int)fFacets.size();                   
757 }                                                 
758                                                   
759 //////////////////////////////////////////////    
760 //                                                
761 EInside G4TessellatedSolid::InsideVoxels(const    
762 {                                                 
763   //                                              
764   // First the simple test - check if we're ou    
765   // of the tessellated solid.                    
766   //                                              
767   if (OutsideOfExtent(p, kCarTolerance))          
768     return kOutside;                              
769                                                   
770   vector<G4int> startingVoxel(3);                 
771   fVoxels.GetVoxel(startingVoxel, p);             
772                                                   
773   const G4double dirTolerance = 1.0E-14;          
774                                                   
775   const vector<G4int> &startingCandidates =       
776     fVoxels.GetCandidates(startingVoxel);         
777   std::size_t limit = startingCandidates.size(    
778   if (limit == 0 && (fInsides.GetNbits() != 0u    
779   {                                               
780     G4int index = fVoxels.GetPointIndex(p);       
781     EInside location = fInsides[index] ? kInsi    
782     return location;                              
783   }                                               
784                                                   
785   G4double minDist = kInfinity;                   
786                                                   
787   for(std::size_t i = 0; i < limit; ++i)          
788   {                                               
789     G4int candidate = startingCandidates[i];      
790     G4VFacet &facet = *fFacets[candidate];        
791     G4double dist = facet.Distance(p,minDist);    
792     if (dist < minDist) minDist = dist;           
793     if (dist <= kCarToleranceHalf)                
794       return kSurface;                            
795   }                                               
796                                                   
797   // The following is something of an adaptati    
798   // Rickard Holmberg augmented with informati    
799   // "Geometric Tools for Computer Graphics,"     
800   // we're trying to determine whether we're i    
801   // a few rays and determining if the first s    
802   // vector between 0 to pi/2 (out-going) or p    
803   // We should also avoid rays which are nearl    
804   // tessellated surface, and therefore produc    
805   // For the moment, this is a bit over-engine    
806   //                                              
807   G4double distOut          = kInfinity;          
808   G4double distIn           = kInfinity;          
809   G4double distO            = 0.0;                
810   G4double distI            = 0.0;                
811   G4double distFromSurfaceO = 0.0;                
812   G4double distFromSurfaceI = 0.0;                
813   G4ThreeVector normalO, normalI;                 
814   G4bool crossingO          = false;              
815   G4bool crossingI          = false;              
816   EInside location          = kOutside;           
817   G4int sm                  = 0;                  
818                                                   
819   G4bool nearParallel = false;                    
820   do    // Loop checking, 13.08.2015, G.Cosmo     
821   {                                               
822     // We loop until we find direction where t    
823     // to the surface of any facet since this     
824     // case is that the angles should be suffi    
825     // are 20 random directions to select from    
826     //                                            
827     distOut = distIn = kInfinity;                 
828     const G4ThreeVector& v = fRandir[sm];         
829     ++sm;                                         
830     //                                            
831     // This code could be voxelized by the sam    
832     // DistanceToOut(). We will traverse throu    
833     // intersect only for those, which would b    
834     // checked before.                            
835     //                                            
836     G4ThreeVector currentPoint = p;               
837     G4ThreeVector direction = v.unit();           
838     // G4SurfBits exclusion(fVoxels.GetBitsPer    
839     vector<G4int> curVoxel(3);                    
840     curVoxel = startingVoxel;                     
841     G4double shiftBonus = kCarTolerance;          
842                                                   
843     G4bool crossed = false;                       
844     G4bool started = true;                        
845                                                   
846     do    // Loop checking, 13.08.2015, G.Cosm    
847     {                                             
848       const vector<G4int> &candidates =           
849         started ? startingCandidates : fVoxels    
850       started = false;                            
851       if (auto candidatesCount = (G4int)candid    
852       {                                           
853         for (G4int i = 0 ; i < candidatesCount    
854         {                                         
855           G4int candidate = candidates[i];        
856           // bits.SetBitNumber(candidate);        
857           G4VFacet& facet = *fFacets[candidate    
858                                                   
859           crossingO = facet.Intersect(p,v,true    
860           crossingI = facet.Intersect(p,v,fals    
861                                                   
862           if (crossingO || crossingI)             
863           {                                       
864             crossed = true;                       
865                                                   
866             nearParallel = (crossingO             
867                      && std::fabs(normalO.dot(    
868                      || (crossingI && std::fab    
869             if (!nearParallel)                    
870             {                                     
871               if (crossingO && distO > 0.0 &&     
872                 distOut = distO;                  
873               if (crossingI && distI > 0.0 &&     
874                 distIn  = distI;                  
875             }                                     
876             else break;                           
877           }                                       
878         }                                         
879         if (nearParallel) break;                  
880       }                                           
881       else                                        
882       {                                           
883         if (!crossed)                             
884         {                                         
885           G4int index = fVoxels.GetVoxelsIndex    
886           G4bool inside = fInsides[index];        
887           location = inside ? kInside : kOutsi    
888           return location;                        
889         }                                         
890       }                                           
891                                                   
892       G4double shift=fVoxels.DistanceToNext(cu    
893       if (shift == kInfinity) break;              
894                                                   
895       currentPoint += direction * (shift + shi    
896     }                                             
897     while (fVoxels.UpdateCurrentVoxel(currentP    
898                                                   
899   }                                               
900   while (nearParallel && sm != fMaxTries);        
901   //                                              
902   // Here we loop through the facets to find o    
903   // between the ray and that facet.  The test    
904   // the ray is entering the facet or exiting.    
905   //                                              
906 #ifdef G4VERBOSE                                  
907   if (sm == fMaxTries)                            
908   {                                               
909     //                                            
910     // We've run out of random vector directio    
911     // low (nTries <= 0.5*maxTries) then this     
912     // something wrong with geometry.             
913     //                                            
914     std::ostringstream message;                   
915     G4long oldprc = message.precision(16);        
916     message << "Cannot determine whether point    
917       << G4endl                                   
918       << "Solid name       = " << GetName()  <    
919       << "Geometry Type    = " << fGeometryTyp    
920       << "Number of facets = " << fFacets.size    
921       << "Position:"  << G4endl << G4endl         
922       << "p.x() = "   << p.x()/mm << " mm" <<     
923       << "p.y() = "   << p.y()/mm << " mm" <<     
924       << "p.z() = "   << p.z()/mm << " mm";       
925     message.precision(oldprc);                    
926     G4Exception("G4TessellatedSolid::Inside()"    
927                 "GeomSolids1002", JustWarning,    
928   }                                               
929 #endif                                            
930                                                   
931   // In the next if-then-elseif G4String the l    
932   // (1) You don't hit anything so cannot be i    
933   //     constructed correctly!                   
934   // (2) Distance to inside (ie. nearest facet    
935   //     shorter than distance to outside (nea    
936   //     facet) - on condition of safety dista    
937   // (3) Distance to outside is shorter than d    
938   //     we're inside.                            
939   //                                              
940   if (distIn == kInfinity && distOut == kInfin    
941     location = kOutside;                          
942   else if (distIn <= distOut - kCarToleranceHa    
943     location = kOutside;                          
944   else if (distOut <= distIn - kCarToleranceHa    
945     location = kInside;                           
946                                                   
947   return location;                                
948 }                                                 
949                                                   
950 //////////////////////////////////////////////    
951 //                                                
952 EInside G4TessellatedSolid::InsideNoVoxels (co    
953 {                                                 
954   //                                              
955   // First the simple test - check if we're ou    
956   // of the tessellated solid.                    
957   //                                              
958   if (OutsideOfExtent(p, kCarTolerance))          
959     return kOutside;                              
960                                                   
961   const G4double dirTolerance = 1.0E-14;          
962                                                   
963   G4double minDist = kInfinity;                   
964   //                                              
965   // Check if we are close to a surface           
966   //                                              
967   std::size_t size = fFacets.size();              
968   for (std::size_t i = 0; i < size; ++i)          
969   {                                               
970     G4VFacet& facet = *fFacets[i];                
971     G4double dist = facet.Distance(p,minDist);    
972     if (dist < minDist) minDist = dist;           
973     if (dist <= kCarToleranceHalf)                
974     {                                             
975       return kSurface;                            
976     }                                             
977   }                                               
978   //                                              
979   // The following is something of an adaptati    
980   // Rickard Holmberg augmented with informati    
981   // "Geometric Tools for Computer Graphics,"     
982   // trying to determine whether we're inside     
983   // rays and determining if the first surface    
984   // between 0 to pi/2 (out-going) or pi/2 to     
985   // avoid rays which are nearly within the pl    
986   // and therefore produce rays randomly. For     
987   // over-engineered (belt-braces-and-ducttape    
988   //                                              
989 #if G4SPECSDEBUG                                  
990   G4int nTry                = 7;                  
991 #else                                             
992   G4int nTry                = 3;                  
993 #endif                                            
994   G4double distOut          = kInfinity;          
995   G4double distIn           = kInfinity;          
996   G4double distO            = 0.0;                
997   G4double distI            = 0.0;                
998   G4double distFromSurfaceO = 0.0;                
999   G4double distFromSurfaceI = 0.0;                
1000   G4ThreeVector normalO(0.0,0.0,0.0);            
1001   G4ThreeVector normalI(0.0,0.0,0.0);            
1002   G4bool crossingO          = false;             
1003   G4bool crossingI          = false;             
1004   EInside location          = kOutside;          
1005   EInside locationprime     = kOutside;          
1006   G4int sm = 0;                                  
1007                                                  
1008   for (G4int i=0; i<nTry; ++i)                   
1009   {                                              
1010     G4bool nearParallel = false;                 
1011     do    // Loop checking, 13.08.2015, G.Cos    
1012     {                                            
1013       //                                         
1014       // We loop until we find direction wher    
1015       // to the surface of any facet since th    
1016       // case is that the angles should be su    
1017       // are 20 random directions to select f    
1018       //                                         
1019       distOut = distIn = kInfinity;              
1020       G4ThreeVector v = fRandir[sm];             
1021       sm++;                                      
1022       auto f = fFacets.cbegin();                 
1023                                                  
1024       do    // Loop checking, 13.08.2015, G.C    
1025       {                                          
1026         //                                       
1027         // Here we loop through the facets to    
1028         // intersection between the ray and t    
1029         // separately whether the ray is ente    
1030         //                                       
1031         crossingO = ((*f)->Intersect(p,v,true    
1032         crossingI = ((*f)->Intersect(p,v,fals    
1033         if (crossingO || crossingI)              
1034         {                                        
1035           nearParallel = (crossingO && std::f    
1036                       || (crossingI && std::f    
1037           if (!nearParallel)                     
1038           {                                      
1039             if (crossingO && distO > 0.0 && d    
1040             if (crossingI && distI > 0.0 && d    
1041           }                                      
1042         }                                        
1043       } while (!nearParallel && ++f != fFacet    
1044     } while (nearParallel && sm != fMaxTries)    
1045                                                  
1046 #ifdef G4VERBOSE                                 
1047     if (sm == fMaxTries)                         
1048     {                                            
1049       //                                         
1050       // We've run out of random vector direc    
1051       // sufficiently low (nTries <= 0.5*maxT    
1052       // that there is something wrong with g    
1053       //                                         
1054       std::ostringstream message;                
1055       G4long oldprc = message.precision(16);     
1056       message << "Cannot determine whether po    
1057         << G4endl                                
1058         << "Solid name       = " << GetName()    
1059         << "Geometry Type    = " << fGeometry    
1060         << "Number of facets = " << fFacets.s    
1061         << "Position:"  << G4endl << G4endl      
1062         << "p.x() = "   << p.x()/mm << " mm"     
1063         << "p.y() = "   << p.y()/mm << " mm"     
1064         << "p.z() = "   << p.z()/mm << " mm";    
1065       message.precision(oldprc);                 
1066       G4Exception("G4TessellatedSolid::Inside    
1067         "GeomSolids1002", JustWarning, messag    
1068     }                                            
1069 #endif                                           
1070     //                                           
1071     // In the next if-then-elseif G4String th    
1072     // (1) You don't hit anything so cannot b    
1073     //     constructed correctly!                
1074     // (2) Distance to inside (ie. nearest fa    
1075     //     shorter than distance to outside (    
1076     //     facet) - on condition of safety di    
1077     // (3) Distance to outside is shorter tha    
1078     // we're inside.                             
1079     //                                           
1080     if (distIn == kInfinity && distOut == kIn    
1081       locationprime = kOutside;                  
1082     else if (distIn <= distOut - kCarToleranc    
1083       locationprime = kOutside;                  
1084     else if (distOut <= distIn - kCarToleranc    
1085       locationprime = kInside;                   
1086                                                  
1087     if (i == 0) location = locationprime;        
1088   }                                              
1089                                                  
1090   return location;                               
1091 }                                                
1092                                                  
1093 /////////////////////////////////////////////    
1094 //                                               
1095 // Return index of the facet closest to the p    
1096 // be located on the surface. Return -1 if no    
1097 //                                               
1098 G4int G4TessellatedSolid::GetFacetIndex (cons    
1099 {                                                
1100   G4int index = -1;                              
1101                                                  
1102   if (fVoxels.GetCountOfVoxels() > 1)            
1103   {                                              
1104     vector<G4int> curVoxel(3);                   
1105     fVoxels.GetVoxel(curVoxel, p);               
1106     const vector<G4int> &candidates = fVoxels    
1107     if (auto limit = (G4int)candidates.size()    
1108     {                                            
1109       G4double minDist = kInfinity;              
1110       for(G4int i = 0 ; i < limit ; ++i)         
1111       {                                          
1112         G4int candidate = candidates[i];         
1113         G4VFacet& facet = *fFacets[candidate]    
1114         G4double dist = facet.Distance(p, min    
1115         if (dist <= kCarToleranceHalf) return    
1116         if (dist < minDist)                      
1117   {                                              
1118     minDist = dist;                              
1119     index = candidate;                           
1120   }                                              
1121       }                                          
1122     }                                            
1123   }                                              
1124   else                                           
1125   {                                              
1126     G4double minDist = kInfinity;                
1127     std::size_t size = fFacets.size();           
1128     for (std::size_t i = 0; i < size; ++i)       
1129     {                                            
1130       G4VFacet& facet = *fFacets[i];             
1131       G4double dist = facet.Distance(p, minDi    
1132       if (dist < minDist)                        
1133       {                                          
1134         minDist  = dist;                         
1135         index = (G4int)i;                        
1136       }                                          
1137     }                                            
1138   }                                              
1139   return index;                                  
1140 }                                                
1141                                                  
1142 /////////////////////////////////////////////    
1143 //                                               
1144 // Return the outwards pointing unit normal o    
1145 // surface closest to the point at offset p.     
1146 //                                               
1147 G4bool G4TessellatedSolid::Normal (const G4Th    
1148                                          G4Th    
1149 {                                                
1150   G4double minDist;                              
1151   G4VFacet* facet = nullptr;                     
1152                                                  
1153   if (fVoxels.GetCountOfVoxels() > 1)            
1154   {                                              
1155     vector<G4int> curVoxel(3);                   
1156     fVoxels.GetVoxel(curVoxel, p);               
1157     const vector<G4int> &candidates = fVoxels    
1158     // fVoxels.GetCandidatesVoxelArray(p, can    
1159                                                  
1160     if (auto limit = (G4int)candidates.size()    
1161     {                                            
1162       minDist = kInfinity;                       
1163       for(G4int i = 0 ; i < limit ; ++i)         
1164       {                                          
1165         G4int candidate = candidates[i];         
1166         G4VFacet &fct = *fFacets[candidate];     
1167         G4double dist = fct.Distance(p,minDis    
1168         if (dist < minDist) minDist = dist;      
1169         if (dist <= kCarToleranceHalf)           
1170         {                                        
1171           aNormal = fct.GetSurfaceNormal();      
1172           return true;                           
1173         }                                        
1174       }                                          
1175     }                                            
1176     minDist = MinDistanceFacet(p, true, facet    
1177   }                                              
1178   else                                           
1179   {                                              
1180     minDist = kInfinity;                         
1181     std::size_t size = fFacets.size();           
1182     for (std::size_t i = 0; i < size; ++i)       
1183     {                                            
1184       G4VFacet& f = *fFacets[i];                 
1185       G4double dist = f.Distance(p, minDist);    
1186       if (dist < minDist)                        
1187       {                                          
1188         minDist  = dist;                         
1189         facet = &f;                              
1190       }                                          
1191     }                                            
1192   }                                              
1193                                                  
1194   if (minDist != kInfinity)                      
1195   {                                              
1196     if (facet != nullptr)  { aNormal = facet-    
1197     return minDist <= kCarToleranceHalf;         
1198   }                                              
1199   else                                           
1200   {                                              
1201 #ifdef G4VERBOSE                                 
1202     std::ostringstream message;                  
1203     message << "Point p is not on surface !?"    
1204       << "          No facets found for point    
1205       << "          Returning approximated va    
1206                                                  
1207     G4Exception("G4TessellatedSolid::SurfaceN    
1208                 "GeomSolids1002", JustWarning    
1209 #endif                                           
1210     aNormal = (p.z() > 0 ? G4ThreeVector(0,0,    
1211     return false;                                
1212   }                                              
1213 }                                                
1214                                                  
1215 /////////////////////////////////////////////    
1216 //                                               
1217 // G4double DistanceToIn(const G4ThreeVector&    
1218 //                                               
1219 // Return the distance along the normalised v    
1220 // from the point at offset p. If there is no    
1221 // kInfinity. The first intersection resultin    
1222 // surface/volume is discarded. Hence, this i    
1223 // surface of shape.                             
1224 //                                               
1225 G4double                                         
1226 G4TessellatedSolid::DistanceToInNoVoxels (con    
1227                                           con    
1228                                                  
1229 {                                                
1230   G4double minDist         = kInfinity;          
1231   G4double dist            = 0.0;                
1232   G4double distFromSurface = 0.0;                
1233   G4ThreeVector normal;                          
1234                                                  
1235 #if G4SPECSDEBUG                                 
1236   if (Inside(p) == kInside )                     
1237   {                                              
1238     std::ostringstream message;                  
1239     G4int oldprc = message.precision(16) ;       
1240     message << "Point p is already inside!?"     
1241       << "Position:"  << G4endl << G4endl        
1242       << "   p.x() = "   << p.x()/mm << " mm"    
1243       << "   p.y() = "   << p.y()/mm << " mm"    
1244       << "   p.z() = "   << p.z()/mm << " mm"    
1245       << "DistanceToOut(p) == " << DistanceTo    
1246     message.precision(oldprc) ;                  
1247     G4Exception("G4TriangularFacet::DistanceT    
1248                 "GeomSolids1002", JustWarning    
1249   }                                              
1250 #endif                                           
1251                                                  
1252   std::size_t size = fFacets.size();             
1253   for (std::size_t i = 0; i < size; ++i)         
1254   {                                              
1255     G4VFacet& facet = *fFacets[i];               
1256     if (facet.Intersect(p,v,false,dist,distFr    
1257     {                                            
1258       //                                         
1259       // set minDist to the new distance to c    
1260       // is in positive direction and point i    
1261       // within 0.5*kCarTolerance of the surf    
1262       // zero and leave member function immed    
1263       // proposed by & credit to Akira Okumur    
1264       //                                         
1265       if (distFromSurface > kCarToleranceHalf    
1266       {                                          
1267         minDist  = dist;                         
1268       }                                          
1269       else                                       
1270       {                                          
1271         if (-kCarToleranceHalf <= dist && dis    
1272         {                                        
1273           return 0.0;                            
1274         }                                        
1275         else                                     
1276         {                                        
1277           if  (distFromSurface > -kCarToleran    
1278             && distFromSurface <  kCarToleran    
1279           {                                      
1280             minDist = dist;                      
1281           }                                      
1282         }                                        
1283       }                                          
1284     }                                            
1285   }                                              
1286   return minDist;                                
1287 }                                                
1288                                                  
1289 /////////////////////////////////////////////    
1290 //                                               
1291 G4double                                         
1292 G4TessellatedSolid::DistanceToOutNoVoxels (co    
1293                                            co    
1294                                                  
1295                                                  
1296                                                  
1297 {                                                
1298   G4double minDist         = kInfinity;          
1299   G4double dist            = 0.0;                
1300   G4double distFromSurface = 0.0;                
1301   G4ThreeVector normal, minNormal;               
1302                                                  
1303 #if G4SPECSDEBUG                                 
1304   if ( Inside(p) == kOutside )                   
1305   {                                              
1306     std::ostringstream message;                  
1307     G4int oldprc = message.precision(16) ;       
1308     message << "Point p is already outside!?"    
1309       << "Position:"  << G4endl << G4endl        
1310       << "   p.x() = "   << p.x()/mm << " mm"    
1311       << "   p.y() = "   << p.y()/mm << " mm"    
1312       << "   p.z() = "   << p.z()/mm << " mm"    
1313       << "DistanceToIn(p) == " << DistanceToI    
1314     message.precision(oldprc) ;                  
1315     G4Exception("G4TriangularFacet::DistanceT    
1316                 "GeomSolids1002", JustWarning    
1317   }                                              
1318 #endif                                           
1319                                                  
1320   G4bool isExtreme = false;                      
1321   std::size_t size = fFacets.size();             
1322   for (std::size_t i = 0; i < size; ++i)         
1323   {                                              
1324     G4VFacet& facet = *fFacets[i];               
1325     if (facet.Intersect(p,v,true,dist,distFro    
1326     {                                            
1327       if (distFromSurface > 0.0 && distFromSu    
1328         && facet.Distance(p,kCarTolerance) <=    
1329       {                                          
1330         // We are on a surface. Return zero.     
1331         aConvex = (fExtremeFacets.find(&facet    
1332         // Normal(p, aNormalVector);             
1333         // aNormalVector = facet.GetSurfaceNo    
1334         aNormalVector = normal;                  
1335         return 0.0;                              
1336       }                                          
1337       if (dist >= 0.0 && dist < minDist)         
1338       {                                          
1339         minDist   = dist;                        
1340         minNormal = normal;                      
1341         isExtreme = (fExtremeFacets.find(&fac    
1342       }                                          
1343     }                                            
1344   }                                              
1345   if (minDist < kInfinity)                       
1346   {                                              
1347     aNormalVector = minNormal;                   
1348     aConvex = isExtreme;                         
1349     return minDist;                              
1350   }                                              
1351   else                                           
1352   {                                              
1353     // No intersection found                     
1354     aConvex = false;                             
1355     Normal(p, aNormalVector);                    
1356     return 0.0;                                  
1357   }                                              
1358 }                                                
1359                                                  
1360 /////////////////////////////////////////////    
1361 //                                               
1362 void G4TessellatedSolid::                        
1363 DistanceToOutCandidates(const std::vector<G4i    
1364                         const G4ThreeVector&     
1365                         const G4ThreeVector&     
1366                               G4double& minDi    
1367                               G4int& minCandi    
1368 {                                                
1369   auto candidatesCount = (G4int)candidates.si    
1370   G4double dist            = 0.0;                
1371   G4double distFromSurface = 0.0;                
1372   G4ThreeVector normal;                          
1373                                                  
1374   for (G4int i = 0 ; i < candidatesCount; ++i    
1375   {                                              
1376     G4int candidate = candidates[i];             
1377     G4VFacet& facet = *fFacets[candidate];       
1378     if (facet.Intersect(aPoint,direction,true    
1379     {                                            
1380       if (distFromSurface > 0.0 && distFromSu    
1381        && facet.Distance(aPoint,kCarTolerance    
1382       {                                          
1383         // We are on a surface                   
1384         //                                       
1385         minDist = 0.0;                           
1386         minNormal = normal;                      
1387         minCandidate = candidate;                
1388         break;                                   
1389       }                                          
1390       if (dist >= 0.0 && dist < minDist)         
1391       {                                          
1392         minDist = dist;                          
1393         minNormal = normal;                      
1394         minCandidate = candidate;                
1395       }                                          
1396     }                                            
1397   }                                              
1398 }                                                
1399                                                  
1400 /////////////////////////////////////////////    
1401 //                                               
1402 G4double                                         
1403 G4TessellatedSolid::DistanceToOutCore(const G    
1404                                       const G    
1405                                             G    
1406                                             G    
1407                                             G    
1408 {                                                
1409   G4double minDistance;                          
1410                                                  
1411   if (fVoxels.GetCountOfVoxels() > 1)            
1412   {                                              
1413     minDistance = kInfinity;                     
1414                                                  
1415     G4ThreeVector currentPoint = aPoint;         
1416     G4ThreeVector direction = aDirection.unit    
1417     G4double totalShift = 0.;                    
1418     vector<G4int> curVoxel(3);                   
1419     if (!fVoxels.Contains(aPoint)) return 0.;    
1420                                                  
1421     fVoxels.GetVoxel(curVoxel, currentPoint);    
1422                                                  
1423     G4double shiftBonus = kCarTolerance;         
1424                                                  
1425     const vector<G4int>* old = nullptr;          
1426                                                  
1427     G4int minCandidate = -1;                     
1428     do    // Loop checking, 13.08.2015, G.Cos    
1429     {                                            
1430       const vector<G4int>& candidates = fVoxe    
1431       if (old == &candidates)                    
1432         ++old;                                   
1433       if (old != &candidates && !candidates.e    
1434       {                                          
1435         DistanceToOutCandidates(candidates, a    
1436                                 aNormalVector    
1437         if (minDistance <= totalShift) break;    
1438       }                                          
1439                                                  
1440       G4double shift=fVoxels.DistanceToNext(c    
1441       if (shift == kInfinity) break;             
1442                                                  
1443       totalShift += shift;                       
1444       if (minDistance <= totalShift) break;      
1445                                                  
1446       currentPoint += direction * (shift + sh    
1447                                                  
1448       old = &candidates;                         
1449     }                                            
1450     while (fVoxels.UpdateCurrentVoxel(current    
1451                                                  
1452     if (minCandidate < 0)                        
1453     {                                            
1454       // No intersection found                   
1455       minDistance = 0.;                          
1456       aConvex = false;                           
1457       Normal(aPoint, aNormalVector);             
1458     }                                            
1459     else                                         
1460     {                                            
1461       aConvex = (fExtremeFacets.find(fFacets[    
1462               != fExtremeFacets.end());          
1463     }                                            
1464   }                                              
1465   else                                           
1466   {                                              
1467     minDistance = DistanceToOutNoVoxels(aPoin    
1468                                         aConv    
1469   }                                              
1470   return minDistance;                            
1471 }                                                
1472                                                  
1473 /////////////////////////////////////////////    
1474 //                                               
1475 G4double G4TessellatedSolid::                    
1476 DistanceToInCandidates(const std::vector<G4in    
1477                        const G4ThreeVector& a    
1478                        const G4ThreeVector& d    
1479 {                                                
1480   auto candidatesCount = (G4int)candidates.si    
1481   G4double dist            = 0.0;                
1482   G4double distFromSurface = 0.0;                
1483   G4ThreeVector normal;                          
1484                                                  
1485   G4double minDistance = kInfinity;              
1486   for (G4int i = 0 ; i < candidatesCount; ++i    
1487   {                                              
1488     G4int candidate = candidates[i];             
1489     G4VFacet& facet = *fFacets[candidate];       
1490     if (facet.Intersect(aPoint,direction,fals    
1491     {                                            
1492       //                                         
1493       // Set minDist to the new distance to c    
1494       // in positive direction and point is n    
1495       // within 0.5*kCarTolerance of the surf    
1496       // zero and leave member function immed    
1497       // proposed by & credit to Akira Okumur    
1498       //                                         
1499       if ( (distFromSurface > kCarToleranceHa    
1500         && (dist >= 0.0) && (dist < minDistan    
1501       {                                          
1502         minDistance  = dist;                     
1503       }                                          
1504       else                                       
1505       {                                          
1506         if (-kCarToleranceHalf <= dist && dis    
1507         {                                        
1508          return 0.0;                             
1509         }                                        
1510         else if  (distFromSurface > -kCarTole    
1511                && distFromSurface <  kCarTole    
1512         {                                        
1513           minDistance = dist;                    
1514         }                                        
1515       }                                          
1516     }                                            
1517   }                                              
1518   return minDistance;                            
1519 }                                                
1520                                                  
1521 /////////////////////////////////////////////    
1522 //                                               
1523 G4double                                         
1524 G4TessellatedSolid::DistanceToInCore(const G4    
1525                                      const G4    
1526                                            G4    
1527 {                                                
1528   G4double minDistance;                          
1529                                                  
1530   if (fVoxels.GetCountOfVoxels() > 1)            
1531   {                                              
1532     minDistance = kInfinity;                     
1533     G4ThreeVector currentPoint = aPoint;         
1534     G4ThreeVector direction = aDirection.unit    
1535     G4double shift = fVoxels.DistanceToFirst(    
1536     if (shift == kInfinity) return shift;        
1537     G4double shiftBonus = kCarTolerance;         
1538     if (shift != 0.0)                            
1539       currentPoint += direction * (shift + sh    
1540     // if (!fVoxels.Contains(currentPoint))      
1541     G4double totalShift = shift;                 
1542                                                  
1543     // G4SurfBits exclusion; // (1/*fVoxels.G    
1544     vector<G4int> curVoxel(3);                   
1545                                                  
1546     fVoxels.GetVoxel(curVoxel, currentPoint);    
1547     do    // Loop checking, 13.08.2015, G.Cos    
1548     {                                            
1549       const vector<G4int>& candidates = fVoxe    
1550       if (!candidates.empty())                   
1551       {                                          
1552         G4double distance=DistanceToInCandida    
1553         if (minDistance > distance) minDistan    
1554         if (distance < totalShift) break;        
1555       }                                          
1556                                                  
1557       shift = fVoxels.DistanceToNext(currentP    
1558       if (shift == kInfinity /*|| shift == 0*    
1559                                                  
1560       totalShift += shift;                       
1561       if (minDistance < totalShift) break;       
1562                                                  
1563       currentPoint += direction * (shift + sh    
1564     }                                            
1565     while (fVoxels.UpdateCurrentVoxel(current    
1566   }                                              
1567   else                                           
1568   {                                              
1569     minDistance = DistanceToInNoVoxels(aPoint    
1570   }                                              
1571                                                  
1572   return minDistance;                            
1573 }                                                
1574                                                  
1575 /////////////////////////////////////////////    
1576 //                                               
1577 G4bool                                           
1578 G4TessellatedSolid::CompareSortedVoxel(const     
1579                                        const     
1580 {                                                
1581   return l.second < r.second;                    
1582 }                                                
1583                                                  
1584 /////////////////////////////////////////////    
1585 //                                               
1586 G4double                                         
1587 G4TessellatedSolid::MinDistanceFacet(const G4    
1588                                            G4    
1589                                            G4    
1590 {                                                
1591   G4double minDist = kInfinity;                  
1592                                                  
1593   G4int size = fVoxels.GetVoxelBoxesSize();      
1594   vector<pair<G4int, G4double> > voxelsSorted    
1595                                                  
1596   pair<G4int, G4double> info;                    
1597                                                  
1598   for (G4int i = 0; i < size; ++i)               
1599   {                                              
1600     const G4VoxelBox& voxelBox = fVoxels.GetV    
1601                                                  
1602     G4ThreeVector pointShifted = p - voxelBox    
1603     G4double safety = fVoxels.MinDistanceToBo    
1604     info.first = i;                              
1605     info.second = safety;                        
1606     voxelsSorted[i] = info;                      
1607   }                                              
1608                                                  
1609   std::sort(voxelsSorted.begin(), voxelsSorte    
1610             &G4TessellatedSolid::CompareSorte    
1611                                                  
1612   for (G4int i = 0; i < size; ++i)               
1613   {                                              
1614     const pair<G4int,G4double>& inf = voxelsS    
1615     G4double dist = inf.second;                  
1616     if (dist > minDist) break;                   
1617                                                  
1618     const vector<G4int>& candidates = fVoxels    
1619     auto csize = (G4int)candidates.size();       
1620     for (G4int j = 0; j < csize; ++j)            
1621     {                                            
1622       G4int candidate = candidates[j];           
1623       G4VFacet& facet = *fFacets[candidate];     
1624       dist = simple ? facet.Distance(p,minDis    
1625                     : facet.Distance(p,minDis    
1626       if (dist < minDist)                        
1627       {                                          
1628         minDist  = dist;                         
1629         minFacet = &facet;                       
1630       }                                          
1631     }                                            
1632   }                                              
1633   return minDist;                                
1634 }                                                
1635                                                  
1636 /////////////////////////////////////////////    
1637 //                                               
1638 G4double G4TessellatedSolid::SafetyFromOutsid    
1639                                                  
1640 {                                                
1641 #if G4SPECSDEBUG                                 
1642   if ( Inside(p) == kInside )                    
1643   {                                              
1644     std::ostringstream message;                  
1645     G4int oldprc = message.precision(16) ;       
1646     message << "Point p is already inside!?"     
1647       << "Position:"  << G4endl << G4endl        
1648       << "p.x() = "   << p.x()/mm << " mm" <<    
1649       << "p.y() = "   << p.y()/mm << " mm" <<    
1650       << "p.z() = "   << p.z()/mm << " mm" <<    
1651       << "DistanceToOut(p) == " << DistanceTo    
1652     message.precision(oldprc) ;                  
1653     G4Exception("G4TriangularFacet::DistanceT    
1654                 "GeomSolids1002", JustWarning    
1655   }                                              
1656 #endif                                           
1657                                                  
1658   G4double minDist;                              
1659                                                  
1660   if (fVoxels.GetCountOfVoxels() > 1)            
1661   {                                              
1662     if (!aAccurate)                              
1663       return fVoxels.DistanceToBoundingBox(p)    
1664                                                  
1665     if (!OutsideOfExtent(p, kCarTolerance))      
1666     {                                            
1667       vector<G4int> startingVoxel(3);            
1668       fVoxels.GetVoxel(startingVoxel, p);        
1669       const vector<G4int> &candidates = fVoxe    
1670       if (candidates.empty() && (fInsides.Get    
1671       {                                          
1672         G4int index = fVoxels.GetPointIndex(p    
1673         if (fInsides[index]) return 0.;          
1674       }                                          
1675     }                                            
1676                                                  
1677     G4VFacet* facet;                             
1678     minDist = MinDistanceFacet(p, true, facet    
1679   }                                              
1680   else                                           
1681   {                                              
1682     minDist = kInfinity;                         
1683     std::size_t size = fFacets.size();           
1684     for (std::size_t i = 0; i < size; ++i)       
1685     {                                            
1686       G4VFacet& facet = *fFacets[i];             
1687       G4double dist = facet.Distance(p,minDis    
1688       if (dist < minDist) minDist = dist;        
1689     }                                            
1690   }                                              
1691   return minDist;                                
1692 }                                                
1693                                                  
1694 /////////////////////////////////////////////    
1695 //                                               
1696 G4double                                         
1697 G4TessellatedSolid::SafetyFromInside (const G    
1698 {                                                
1699 #if G4SPECSDEBUG                                 
1700   if ( Inside(p) == kOutside )                   
1701   {                                              
1702     std::ostringstream message;                  
1703     G4int oldprc = message.precision(16) ;       
1704     message << "Point p is already outside!?"    
1705       << "Position:"  << G4endl << G4endl        
1706       << "p.x() = "   << p.x()/mm << " mm" <<    
1707       << "p.y() = "   << p.y()/mm << " mm" <<    
1708       << "p.z() = "   << p.z()/mm << " mm" <<    
1709       << "DistanceToIn(p) == " << DistanceToI    
1710     message.precision(oldprc) ;                  
1711     G4Exception("G4TriangularFacet::DistanceT    
1712                 "GeomSolids1002", JustWarning    
1713   }                                              
1714 #endif                                           
1715                                                  
1716   G4double minDist;                              
1717                                                  
1718   if (OutsideOfExtent(p, kCarTolerance)) retu    
1719                                                  
1720   if (fVoxels.GetCountOfVoxels() > 1)            
1721   {                                              
1722     G4VFacet* facet;                             
1723     minDist = MinDistanceFacet(p, true, facet    
1724   }                                              
1725   else                                           
1726   {                                              
1727     minDist = kInfinity;                         
1728     G4double dist = 0.0;                         
1729     std::size_t size = fFacets.size();           
1730     for (std::size_t i = 0; i < size; ++i)       
1731     {                                            
1732       G4VFacet& facet = *fFacets[i];             
1733       dist = facet.Distance(p,minDist);          
1734       if (dist < minDist) minDist  = dist;       
1735     }                                            
1736   }                                              
1737   return minDist;                                
1738 }                                                
1739                                                  
1740 /////////////////////////////////////////////    
1741 //                                               
1742 // G4GeometryType GetEntityType() const;         
1743 //                                               
1744 // Provide identification of the class of an     
1745 //                                               
1746 G4GeometryType G4TessellatedSolid::GetEntityT    
1747 {                                                
1748   return fGeometryType;                          
1749 }                                                
1750                                                  
1751 /////////////////////////////////////////////    
1752 //                                               
1753 // IsFaceted                                     
1754 //                                               
1755 G4bool G4TessellatedSolid::IsFaceted () const    
1756 {                                                
1757   return true;                                   
1758 }                                                
1759                                                  
1760 /////////////////////////////////////////////    
1761 //                                               
1762 std::ostream &G4TessellatedSolid::StreamInfo(    
1763 {                                                
1764   os << G4endl;                                  
1765   os << "Solid name       = " << GetName()       
1766   os << "Geometry Type    = " << fGeometryTyp    
1767   os << "Number of facets = " << fFacets.size    
1768                                                  
1769   std::size_t size = fFacets.size();             
1770   for (std::size_t i = 0; i < size; ++i)         
1771   {                                              
1772     os << "FACET #          = " << i + 1 << G    
1773     G4VFacet &facet = *fFacets[i];               
1774     facet.StreamInfo(os);                        
1775   }                                              
1776   os << G4endl;                                  
1777                                                  
1778   return os;                                     
1779 }                                                
1780                                                  
1781 /////////////////////////////////////////////    
1782 //                                               
1783 // Make a clone of the object                    
1784 //                                               
1785 G4VSolid* G4TessellatedSolid::Clone() const      
1786 {                                                
1787   return new G4TessellatedSolid(*this);          
1788 }                                                
1789                                                  
1790 /////////////////////////////////////////////    
1791 //                                               
1792 // EInside G4TessellatedSolid::Inside (const     
1793 //                                               
1794 // This method must return:                      
1795 //    * kOutside if the point at offset p is     
1796 //      boundaries plus kCarTolerance/2,         
1797 //    * kSurface if the point is <= kCarToler    
1798 //    * kInside otherwise.                       
1799 //                                               
1800 EInside G4TessellatedSolid::Inside (const G4T    
1801 {                                                
1802   EInside location;                              
1803                                                  
1804   if (fVoxels.GetCountOfVoxels() > 1)            
1805   {                                              
1806     location = InsideVoxels(aPoint);             
1807   }                                              
1808   else                                           
1809   {                                              
1810     location = InsideNoVoxels(aPoint);           
1811   }                                              
1812   return location;                               
1813 }                                                
1814                                                  
1815 /////////////////////////////////////////////    
1816 //                                               
1817 G4ThreeVector G4TessellatedSolid::SurfaceNorm    
1818 {                                                
1819   G4ThreeVector n;                               
1820   Normal(p, n);                                  
1821   return n;                                      
1822 }                                                
1823                                                  
1824 /////////////////////////////////////////////    
1825 //                                               
1826 // G4double DistanceToIn(const G4ThreeVector&    
1827 //                                               
1828 // Calculate distance to nearest surface of s    
1829 // distance can be an underestimate.             
1830 //                                               
1831 G4double G4TessellatedSolid::DistanceToIn(con    
1832 {                                                
1833   return SafetyFromOutside(p, false);            
1834 }                                                
1835                                                  
1836 /////////////////////////////////////////////    
1837 //                                               
1838 G4double G4TessellatedSolid::DistanceToIn(con    
1839                                           con    
1840 {                                                
1841   G4double dist = DistanceToInCore(p,v,kInfin    
1842 #ifdef G4SPECSDEBUG                              
1843   if (dist < kInfinity)                          
1844   {                                              
1845     if (Inside(p + dist*v) != kSurface)          
1846     {                                            
1847       std::ostringstream message;                
1848       message << "Invalid response from facet    
1849               << G4endl                          
1850               << "at point: " << p <<  "and d    
1851       G4Exception("G4TessellatedSolid::Distan    
1852                   "GeomSolids1002", JustWarni    
1853     }                                            
1854   }                                              
1855 #endif                                           
1856   return dist;                                   
1857 }                                                
1858                                                  
1859 /////////////////////////////////////////////    
1860 //                                               
1861 // G4double DistanceToOut(const G4ThreeVector    
1862 //                                               
1863 // Calculate distance to nearest surface of s    
1864 // point. The distance can be an underestimat    
1865 //                                               
1866 G4double G4TessellatedSolid::DistanceToOut(co    
1867 {                                                
1868   return SafetyFromInside(p, false);             
1869 }                                                
1870                                                  
1871 /////////////////////////////////////////////    
1872 //                                               
1873 // G4double DistanceToOut(const G4ThreeVector    
1874 //                        const G4bool calcNo    
1875 //                        G4bool *validNorm=0    
1876 //                                               
1877 // Return distance along the normalised vecto    
1878 // point at an offset p inside or on the surf    
1879 // shape. Intersections with surfaces, when t    
1880 // than kCarTolerance/2 from a surface, must     
1881 //     If calcNorm is true, then it must also    
1882 //     * true, if the solid lies entirely beh    
1883 //        surface. Then it must set n to the     
1884 //        (the Magnitude of the vector is not    
1885 //     * false, if the solid does not lie ent    
1886 //       exiting surface.                        
1887 // If calcNorm is false, then validNorm and n    
1888 //                                               
1889 G4double G4TessellatedSolid::DistanceToOut(co    
1890                                            co    
1891                                            co    
1892                                                  
1893                                                  
1894 {                                                
1895   G4ThreeVector n;                               
1896   G4bool valid;                                  
1897                                                  
1898   G4double dist = DistanceToOutCore(p, v, n,     
1899   if (calcNorm)                                  
1900   {                                              
1901     *norm = n;                                   
1902     *validNorm = valid;                          
1903   }                                              
1904 #ifdef G4SPECSDEBUG                              
1905   if (dist < kInfinity)                          
1906   {                                              
1907     if (Inside(p + dist*v) != kSurface)          
1908     {                                            
1909       std::ostringstream message;                
1910       message << "Invalid response from facet    
1911               << G4endl                          
1912               << "at point: " << p <<  "and d    
1913       G4Exception("G4TessellatedSolid::Distan    
1914                   "GeomSolids1002", JustWarni    
1915     }                                            
1916   }                                              
1917 #endif                                           
1918   return dist;                                   
1919 }                                                
1920                                                  
1921 /////////////////////////////////////////////    
1922 //                                               
1923 void G4TessellatedSolid::DescribeYourselfTo (    
1924 {                                                
1925   scene.AddSolid (*this);                        
1926 }                                                
1927                                                  
1928 /////////////////////////////////////////////    
1929 //                                               
1930 G4Polyhedron* G4TessellatedSolid::CreatePolyh    
1931 {                                                
1932   auto nVertices = (G4int)fVertexList.size();    
1933   auto nFacets = (G4int)fFacets.size();          
1934   auto polyhedron = new G4Polyhedron(nVertice    
1935   for (auto i = 0; i < nVertices; ++i)           
1936   {                                              
1937     polyhedron->SetVertex(i+1, fVertexList[i]    
1938   }                                              
1939                                                  
1940   for (auto i = 0; i < nFacets; ++i)             
1941   {                                              
1942     G4VFacet* facet = fFacets[i];                
1943     G4int v[4] = {0};                            
1944     G4int n = facet->GetNumberOfVertices();      
1945     if (n > 4) n = 4;                            
1946     for (auto j = 0; j < n; ++j)                 
1947     {                                            
1948       v[j] = facet->GetVertexIndex(j) + 1;       
1949     }                                            
1950     polyhedron->SetFacet(i+1, v[0], v[1], v[2    
1951   }                                              
1952   polyhedron->SetReferences();                   
1953                                                  
1954   return polyhedron;                             
1955 }                                                
1956                                                  
1957 /////////////////////////////////////////////    
1958 //                                               
1959 // GetPolyhedron                                 
1960 //                                               
1961 G4Polyhedron* G4TessellatedSolid::GetPolyhedr    
1962 {                                                
1963   if (fpPolyhedron == nullptr ||                 
1964       fRebuildPolyhedron ||                      
1965       fpPolyhedron->GetNumberOfRotationStepsA    
1966       fpPolyhedron->GetNumberOfRotationSteps(    
1967   {                                              
1968     G4AutoLock l(&polyhedronMutex);              
1969     delete fpPolyhedron;                         
1970     fpPolyhedron = CreatePolyhedron();           
1971     fRebuildPolyhedron = false;                  
1972     l.unlock();                                  
1973   }                                              
1974   return fpPolyhedron;                           
1975 }                                                
1976                                                  
1977 /////////////////////////////////////////////    
1978 //                                               
1979 // Get bounding box                              
1980 //                                               
1981 void G4TessellatedSolid::BoundingLimits(G4Thr    
1982                                         G4Thr    
1983 {                                                
1984   pMin = fMinExtent;                             
1985   pMax = fMaxExtent;                             
1986                                                  
1987   // Check correctness of the bounding box       
1988   //                                             
1989   if (pMin.x() >= pMax.x() || pMin.y() >= pMa    
1990   {                                              
1991     std::ostringstream message;                  
1992     message << "Bad bounding box (min >= max)    
1993             << GetName() << " !"                 
1994             << "\npMin = " << pMin               
1995             << "\npMax = " << pMax;              
1996     G4Exception("G4TessellatedSolid::Bounding    
1997                 "GeomMgt0001", JustWarning, m    
1998     DumpInfo();                                  
1999   }                                              
2000 }                                                
2001                                                  
2002 /////////////////////////////////////////////    
2003 //                                               
2004 // Calculate extent under transform and speci    
2005 //                                               
2006 G4bool                                           
2007 G4TessellatedSolid::CalculateExtent(const EAx    
2008                                     const G4V    
2009                                     const G4A    
2010                                           G4d    
2011 {                                                
2012   G4ThreeVector bmin, bmax;                      
2013                                                  
2014   // Check bounding box (bbox)                   
2015   //                                             
2016   BoundingLimits(bmin,bmax);                     
2017   G4BoundingEnvelope bbox(bmin,bmax);            
2018                                                  
2019   // Use simple bounding-box to help in the c    
2020   //                                             
2021   return bbox.CalculateExtent(pAxis,pVoxelLim    
2022                                                  
2023 #if 0                                            
2024   // Precise extent computation (disabled by     
2025   //                                             
2026   if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVo    
2027   {                                              
2028     return (pMin < pMax) ? true : false;         
2029   }                                              
2030                                                  
2031   // The extent is calculated as cumulative e    
2032   // formed by facets and the center of the b    
2033   //                                             
2034   G4double eminlim = pVoxelLimit.GetMinExtent    
2035   G4double emaxlim = pVoxelLimit.GetMaxExtent    
2036                                                  
2037   G4ThreeVectorList base;                        
2038   G4ThreeVectorList apex(1);                     
2039   std::vector<const G4ThreeVectorList *> pyra    
2040   pyramid[0] = &base;                            
2041   pyramid[1] = &apex;                            
2042   apex[0] = (bmin+bmax)*0.5;                     
2043                                                  
2044   // main loop along facets                      
2045   pMin =  kInfinity;                             
2046   pMax = -kInfinity;                             
2047   for (G4int i=0; i<GetNumberOfFacets(); ++i)    
2048   {                                              
2049     G4VFacet* facet = GetFacet(i);               
2050     if (std::abs((facet->GetSurfaceNormal()).    
2051         < kCarToleranceHalf) continue;           
2052                                                  
2053     G4int nv = facet->GetNumberOfVertices();     
2054     base.resize(nv);                             
2055     for (G4int k=0; k<nv; ++k) { base[k] = fa    
2056                                                  
2057     G4double emin,emax;                          
2058     G4BoundingEnvelope benv(pyramid);            
2059     if (!benv.CalculateExtent(pAxis,pVoxelLim    
2060     if (emin < pMin) pMin = emin;                
2061     if (emax > pMax) pMax = emax;                
2062     if (eminlim > pMin && emaxlim < pMax) bre    
2063   }                                              
2064   return (pMin < pMax);                          
2065 #endif                                           
2066 }                                                
2067                                                  
2068 /////////////////////////////////////////////    
2069 //                                               
2070 G4double G4TessellatedSolid::GetMinXExtent ()    
2071 {                                                
2072   return fMinExtent.x();                         
2073 }                                                
2074                                                  
2075 /////////////////////////////////////////////    
2076 //                                               
2077 G4double G4TessellatedSolid::GetMaxXExtent ()    
2078 {                                                
2079   return fMaxExtent.x();                         
2080 }                                                
2081                                                  
2082 /////////////////////////////////////////////    
2083 //                                               
2084 G4double G4TessellatedSolid::GetMinYExtent ()    
2085 {                                                
2086   return fMinExtent.y();                         
2087 }                                                
2088                                                  
2089 /////////////////////////////////////////////    
2090 //                                               
2091 G4double G4TessellatedSolid::GetMaxYExtent ()    
2092 {                                                
2093   return fMaxExtent.y();                         
2094 }                                                
2095                                                  
2096 /////////////////////////////////////////////    
2097 //                                               
2098 G4double G4TessellatedSolid::GetMinZExtent ()    
2099 {                                                
2100   return fMinExtent.z();                         
2101 }                                                
2102                                                  
2103 /////////////////////////////////////////////    
2104 //                                               
2105 G4double G4TessellatedSolid::GetMaxZExtent ()    
2106 {                                                
2107   return fMaxExtent.z();                         
2108 }                                                
2109                                                  
2110 /////////////////////////////////////////////    
2111 //                                               
2112 G4VisExtent G4TessellatedSolid::GetExtent ()     
2113 {                                                
2114   return { fMinExtent.x(), fMaxExtent.x(),       
2115            fMinExtent.y(), fMaxExtent.y(),       
2116            fMinExtent.z(), fMaxExtent.z() };     
2117 }                                                
2118                                                  
2119 /////////////////////////////////////////////    
2120 //                                               
2121 G4double G4TessellatedSolid::GetCubicVolume (    
2122 {                                                
2123   if (fCubicVolume != 0.) return fCubicVolume    
2124                                                  
2125   // For explanation of the following algorit    
2126   // https://en.wikipedia.org/wiki/Polyhedron    
2127   // http://wwwf.imperial.ac.uk/~rn/centroid.    
2128                                                  
2129   std::size_t size = fFacets.size();             
2130   for (std::size_t i = 0; i < size; ++i)         
2131   {                                              
2132     G4VFacet &facet = *fFacets[i];               
2133     G4double area = facet.GetArea();             
2134     G4ThreeVector unit_normal = facet.GetSurf    
2135     fCubicVolume += area * (facet.GetVertex(0    
2136   }                                              
2137   fCubicVolume /= 3.;                            
2138   return fCubicVolume;                           
2139 }                                                
2140                                                  
2141 /////////////////////////////////////////////    
2142 //                                               
2143 G4double G4TessellatedSolid::GetSurfaceArea (    
2144 {                                                
2145   if (fSurfaceArea != 0.) return fSurfaceArea    
2146                                                  
2147   std::size_t size = fFacets.size();             
2148   for (std::size_t i = 0; i < size; ++i)         
2149   {                                              
2150     G4VFacet &facet = *fFacets[i];               
2151     fSurfaceArea += facet.GetArea();             
2152   }                                              
2153   return fSurfaceArea;                           
2154 }                                                
2155                                                  
2156 /////////////////////////////////////////////    
2157 //                                               
2158 G4ThreeVector G4TessellatedSolid::GetPointOnS    
2159 {                                                
2160   // Select randomly a facet and return a ran    
2161                                                  
2162   auto i = (G4int) G4RandFlat::shoot(0., fFac    
2163   return fFacets[i]->GetPointOnFace();           
2164 }                                                
2165                                                  
2166 /////////////////////////////////////////////    
2167 //                                               
2168 // SetRandomVectorSet                            
2169 //                                               
2170 // This is a set of predefined random vectors    
2171 // in terms!) used to generate rays from a us    
2172 // function Inside uses these to determine wh    
2173 // outside of the tessellated solid.  All vec    
2174 //                                               
2175 void G4TessellatedSolid::SetRandomVectors ()     
2176 {                                                
2177   fRandir.resize(20);                            
2178   fRandir[0]  =                                  
2179     G4ThreeVector(-0.9577428892113370, 0.2732    
2180   fRandir[1]  =                                  
2181     G4ThreeVector(-0.8331264504940770,-0.5162    
2182   fRandir[2]  =                                  
2183     G4ThreeVector(-0.1516671651108820, 0.9666    
2184   fRandir[3]  =                                  
2185     G4ThreeVector( 0.6570250350323190,-0.6944    
2186   fRandir[4]  =                                  
2187     G4ThreeVector(-0.4820456281280320,-0.6331    
2188   fRandir[5]  =                                  
2189     G4ThreeVector( 0.7629032554236800 , 0.101    
2190   fRandir[6]  =                                  
2191     G4ThreeVector( 0.7689540409061150, 0.5034    
2192   fRandir[7]  =                                  
2193     G4ThreeVector( 0.5765188359255740, 0.5997    
2194   fRandir[8]  =                                  
2195     G4ThreeVector( 0.6660632777862070,-0.6362    
2196   fRandir[9]  =                                  
2197     G4ThreeVector( 0.3824415020414780, 0.6541    
2198   fRandir[10] =                                  
2199     G4ThreeVector(-0.5107726564526760, 0.6020    
2200   fRandir[11] =                                  
2201     G4ThreeVector( 0.7459135439578050, 0.6618    
2202   fRandir[12] =                                  
2203     G4ThreeVector( 0.1536405855311580, 0.8117    
2204   fRandir[13] =                                  
2205     G4ThreeVector( 0.0744395301705579,-0.8707    
2206   fRandir[14] =                                  
2207     G4ThreeVector(-0.1665874645185400, 0.6018    
2208   fRandir[15] =                                  
2209     G4ThreeVector( 0.7766902003633100, 0.6014    
2210   fRandir[16] =                                  
2211     G4ThreeVector(-0.8710128685847430,-0.1434    
2212   fRandir[17] =                                  
2213     G4ThreeVector( 0.8901082092766820,-0.4388    
2214   fRandir[18] =                                  
2215     G4ThreeVector(-0.6430417431544370,-0.3295    
2216   fRandir[19] =                                  
2217     G4ThreeVector( 0.6331124368380410, 0.6306    
2218                                                  
2219   fMaxTries = 20;                                
2220 }                                                
2221                                                  
2222 /////////////////////////////////////////////    
2223 //                                               
2224 G4int G4TessellatedSolid::AllocatedMemoryWith    
2225 {                                                
2226   G4int base = sizeof(*this);                    
2227   base += fVertexList.capacity() * sizeof(G4T    
2228   base += fRandir.capacity() * sizeof(G4Three    
2229                                                  
2230   std::size_t limit = fFacets.size();            
2231   for (std::size_t i = 0; i < limit; ++i)        
2232   {                                              
2233     G4VFacet& facet = *fFacets[i];               
2234     base += facet.AllocatedMemory();             
2235   }                                              
2236                                                  
2237   for (const auto & fExtremeFacet : fExtremeF    
2238   {                                              
2239     G4VFacet &facet = *fExtremeFacet;            
2240     base += facet.AllocatedMemory();             
2241   }                                              
2242   return base;                                   
2243 }                                                
2244                                                  
2245 /////////////////////////////////////////////    
2246 //                                               
2247 G4int G4TessellatedSolid::AllocatedMemory()      
2248 {                                                
2249   G4int size = AllocatedMemoryWithoutVoxels()    
2250   G4int sizeInsides = fInsides.GetNbytes();      
2251   G4int sizeVoxels = fVoxels.AllocatedMemory(    
2252   size += sizeInsides + sizeVoxels;              
2253   return size;                                   
2254 }                                                
2255                                                  
2256 #endif                                           
2257