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


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration and of QinetiQ Ltd,   *
 20 // * subject to DEFCON 705 IPR conditions.         20 // * subject to DEFCON 705 IPR conditions.                            *
 21 // * By using,  copying,  modifying or  distri     21 // * By using,  copying,  modifying or  distributing the software (or *
 22 // * any work based  on the software)  you  ag     22 // * any work based  on the software)  you  agree  to acknowledge its *
 23 // * use  in  resulting  scientific  publicati     23 // * use  in  resulting  scientific  publications,  and indicate your *
 24 // * acceptance of all terms of the Geant4 Sof     24 // * acceptance of all terms of the Geant4 Software license.          *
 25 // *******************************************     25 // ********************************************************************
 26 //                                                 26 //
 27 // G4TessellatedSolid implementation           <<  27 // $Id: G4TessellatedSolid.cc,v 1.27 2010-11-02 11:29:07 gcosmo Exp $
                                                   >>  28 // GEANT4 tag $Name: not supported by cvs2svn $
 28 //                                                 29 //
 29 // 31.10.2004, P R Truscott, QinetiQ Ltd, UK - <<  30 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 30 // 17.09.2007, P R Truscott, QinetiQ Ltd & Ric <<  31 //
                                                   >>  32 // MODULE:              G4TessellatedSolid.cc
                                                   >>  33 //
                                                   >>  34 // Date:                15/06/2005
                                                   >>  35 // Author:              P R Truscott
                                                   >>  36 // Organisation:        QinetiQ Ltd, UK
                                                   >>  37 // Customer:            UK Ministry of Defence : RAO CRP TD Electronic Systems
                                                   >>  38 // Contract:            C/MAT/N03517
                                                   >>  39 //
                                                   >>  40 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                                                   >>  41 //
                                                   >>  42 // CHANGE HISTORY
                                                   >>  43 // --------------
                                                   >>  44 // 22 August 2011,    I Hrivnacova, Orsay, fix in DistanceToOut(p) and
                                                   >>  45 //                    DistanceToIn(p) to exactly compute distance from facet
                                                   >>  46 //                    avoiding use of 'outgoing' flag shortcut variant.
                                                   >>  47 //
                                                   >>  48 // 04 August 2011,    T Nikitina, CERN, added SetReferences() to
                                                   >>  49 //                    CreatePolyhedron() for Visualization of Boolean Operations  
                                                   >>  50 //
                                                   >>  51 // 12 April 2010,     P R Truscott, QinetiQ, bug fixes to treat optical
                                                   >>  52 //                    photon transport, in particular internal reflection
                                                   >>  53 //                    at surface.
                                                   >>  54 //
                                                   >>  55 // 14 November 2007,  P R Truscott, QinetiQ & Stan Seibert, U Texas
                                                   >>  56 //                    Bug fixes to CalculateExtent
                                                   >>  57 //
                                                   >>  58 // 17 September 2007, P R Truscott, QinetiQ Ltd & Richard Holmberg
 31 //                    Updated extensively prio     59 //                    Updated extensively prior to this date to deal with
 32 //                    concaved tessellated sur     60 //                    concaved tessellated surfaces, based on the algorithm
 33 //                    of Richard Holmberg.  Th     61 //                    of Richard Holmberg.  This had been slightly modified
 34 //                    to determine with inside     62 //                    to determine with inside the geometry by projecting
 35 //                    random rays from the poi     63 //                    random rays from the point provided.  Now random rays
 36 //                    are predefined rather th     64 //                    are predefined rather than making use of random
 37 //                    number generator at run-     65 //                    number generator at run-time.
 38 // 12.10.2012, M Gayer, CERN, complete rewrite <<  66 //
 39 //                    requirements more than 5 <<  67 // 22 November 2005, F Lei
 40 //                    tens or more depending o <<  68 //  - Changed ::DescribeYourselfTo(), line 464
 41 //                    to voxelization of surfa <<  69 //  - added GetPolyHedron()
 42 //                    Speedup factor of thousa <<  70 // 
 43 //                    facets in hundreds of th <<  71 // 31 October 2004, P R Truscott, QinetiQ Ltd, UK
 44 // 23.10.2016, E Tcherniaev, reimplemented Cal <<  72 //  - Created.
 45 //                    use of G4BoundingEnvelop <<  73 //
 46 // ------------------------------------------- <<  74 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 47                                                    75 
 48 #include "G4TessellatedSolid.hh"                   76 #include "G4TessellatedSolid.hh"
 49                                                <<  77 #include "G4PolyhedronArbitrary.hh"
 50 #if !defined(G4GEOM_USE_UTESSELLATEDSOLID)     <<  78 #include "globals.hh"
 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"                            79 #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                                                    80 
 79 using namespace std;                           <<  81 #include <iostream>
 80                                                    82 
 81 //////////////////////////////////////////////     83 ///////////////////////////////////////////////////////////////////////////////
 82 //                                                 84 //
 83 // Standard contructor has blank name and defi <<  85 // Standard contructor has blank name and defines no facets.
 84 //                                                 86 //
 85 G4TessellatedSolid::G4TessellatedSolid () : G4 <<  87 G4TessellatedSolid::G4TessellatedSolid ()
                                                   >>  88   : G4VSolid("dummy"), fpPolyhedron(0), cubicVolume(0.), surfaceArea(0.)
 86 {                                                  89 {
 87   Initialize();                                <<  90   dirTolerance = 1.0E-14;
                                                   >>  91   
                                                   >>  92   geometryType = "G4TessellatedSolid";
                                                   >>  93   facets.clear();
                                                   >>  94   solidClosed  = false;
                                                   >>  95   
                                                   >>  96   xMinExtent =  kInfinity;
                                                   >>  97   xMaxExtent = -kInfinity;
                                                   >>  98   yMinExtent =  kInfinity;
                                                   >>  99   yMaxExtent = -kInfinity;
                                                   >> 100   zMinExtent =  kInfinity;
                                                   >> 101   zMaxExtent = -kInfinity;
                                                   >> 102 
                                                   >> 103   SetRandomVectorSet();
 88 }                                                 104 }
 89                                                   105 
 90 //////////////////////////////////////////////    106 ///////////////////////////////////////////////////////////////////////////////
 91 //                                                107 //
 92 // Alternative constructor. Simple define name << 108 // Alternative constructor. Simple define name and geometry type - no facets
 93 // to detine.                                     109 // to detine.
 94 //                                                110 //
 95 G4TessellatedSolid::G4TessellatedSolid (const  << 111 G4TessellatedSolid::G4TessellatedSolid (const G4String &name)
 96   : G4VSolid(name)                             << 112   : G4VSolid(name), fpPolyhedron(0), cubicVolume(0.), surfaceArea(0.)
 97 {                                                 113 {
 98   Initialize();                                << 114   dirTolerance = 1.0E-14;
                                                   >> 115   
                                                   >> 116   geometryType = "G4TessellatedSolid";
                                                   >> 117   facets.clear();
                                                   >> 118   solidClosed  = false;
                                                   >> 119   
                                                   >> 120   xMinExtent =  kInfinity;
                                                   >> 121   xMaxExtent = -kInfinity;
                                                   >> 122   yMinExtent =  kInfinity;
                                                   >> 123   yMaxExtent = -kInfinity;
                                                   >> 124   zMinExtent =  kInfinity;
                                                   >> 125   zMaxExtent = -kInfinity;
                                                   >> 126 
                                                   >> 127   SetRandomVectorSet();
 99 }                                                 128 }
100                                                   129 
101 //////////////////////////////////////////////    130 ///////////////////////////////////////////////////////////////////////////////
102 //                                                131 //
103 // Fake default constructor - sets only member    132 // Fake default constructor - sets only member data and allocates memory
104 //                            for usage restri    133 //                            for usage restricted to object persistency.
105 //                                                134 //
106 G4TessellatedSolid::G4TessellatedSolid( __void << 135 G4TessellatedSolid::G4TessellatedSolid( __void__& a )
107 {                                              << 136   : G4VSolid(a), fpPolyhedron(0), facets(0),
108   Initialize();                                << 137     geometryType("G4TessellatedSolid"), cubicVolume(0.), surfaceArea(0.),
109   fMinExtent.set(0,0,0);                       << 138     vertexList(), xMinExtent(0.), xMaxExtent(0.),
110   fMaxExtent.set(0,0,0);                       << 139     yMinExtent(0.), yMaxExtent(0.), zMinExtent(0.), zMaxExtent(0.),
111 }                                              << 140     solidClosed(false), dirTolerance(1.0E-14)
112                                                << 
113                                                << 
114 ////////////////////////////////////////////// << 
115 G4TessellatedSolid::~G4TessellatedSolid()      << 
116 {                                                 141 {
117   DeleteObjects();                             << 142   SetRandomVectorSet();
118 }                                                 143 }
119                                                   144 
120 //////////////////////////////////////////////    145 ///////////////////////////////////////////////////////////////////////////////
121 //                                                146 //
122 // Copy constructor.                           << 147 // Destructor.
123 //                                                148 //
124 G4TessellatedSolid::G4TessellatedSolid (const  << 149 G4TessellatedSolid::~G4TessellatedSolid ()
125   : G4VSolid(ts)                               << 
126 {                                                 150 {
127   Initialize();                                << 151   DeleteObjects ();
128                                                << 
129   CopyObjects(ts);                             << 
130 }                                                 152 }
131                                                   153 
132 //////////////////////////////////////////////    154 ///////////////////////////////////////////////////////////////////////////////
133 //                                                155 //
134 // Assignment operator.                        << 156 // Define copy constructor.
135 //                                                157 //
136 G4TessellatedSolid&                            << 158 G4TessellatedSolid::G4TessellatedSolid (const G4TessellatedSolid &s)
137 G4TessellatedSolid::operator= (const G4Tessell << 159   : G4VSolid(s), fpPolyhedron(0)
138 {                                                 160 {
139   if (&ts == this) return *this;               << 161   dirTolerance = 1.0E-14;
140                                                << 162   
141   // Copy base class data                      << 163   geometryType = "G4TessellatedSolid";
142   G4VSolid::operator=(ts);                     << 164   facets.clear();
                                                   >> 165   solidClosed  = false;
143                                                   166 
144   DeleteObjects ();                            << 167   cubicVolume = s.cubicVolume;  
                                                   >> 168   surfaceArea = s.surfaceArea;  
145                                                   169 
146   Initialize();                                << 170   xMinExtent =  kInfinity;
                                                   >> 171   xMaxExtent = -kInfinity;
                                                   >> 172   yMinExtent =  kInfinity;
                                                   >> 173   yMaxExtent = -kInfinity;
                                                   >> 174   zMinExtent =  kInfinity;
                                                   >> 175   zMaxExtent = -kInfinity;
147                                                   176 
148   CopyObjects (ts);                            << 177   SetRandomVectorSet();
149                                                   178 
150   return *this;                                << 179   CopyObjects (s);
151 }                                                 180 }
152                                                   181 
153 //////////////////////////////////////////////    182 ///////////////////////////////////////////////////////////////////////////////
154 //                                                183 //
155 void G4TessellatedSolid::Initialize()          << 184 // Define assignment operator.
                                                   >> 185 //
                                                   >> 186 const G4TessellatedSolid &
                                                   >> 187 G4TessellatedSolid::operator= (const G4TessellatedSolid &s)
156 {                                                 188 {
157   kCarToleranceHalf = 0.5*kCarTolerance;       << 189   if (&s == this) { return *this; }
158                                                << 190   
159   fRebuildPolyhedron = false; fpPolyhedron = n << 191   // Copy base class data
160   fCubicVolume = 0.; fSurfaceArea = 0.;        << 192   //
161                                                << 193   G4VSolid::operator=(s);
162   fGeometryType = "G4TessellatedSolid";        << 
163   fSolidClosed  = false;                       << 
164                                                   194 
165   fMinExtent.set(kInfinity,kInfinity,kInfinity << 195   // Copy data
166   fMaxExtent.set(-kInfinity,-kInfinity,-kInfin << 196   //
                                                   >> 197   cubicVolume = s.cubicVolume;  
                                                   >> 198   surfaceArea = s.surfaceArea;
                                                   >> 199   fpPolyhedron = 0; 
167                                                   200 
168   SetRandomVectors();                          << 201   DeleteObjects ();
                                                   >> 202   CopyObjects (s);
                                                   >> 203   
                                                   >> 204   return *this;
169 }                                                 205 }
170                                                   206 
171 //////////////////////////////////////////////    207 ///////////////////////////////////////////////////////////////////////////////
172 //                                                208 //
173 void G4TessellatedSolid::DeleteObjects()       << 209 void G4TessellatedSolid::DeleteObjects ()
174 {                                                 210 {
175   std::size_t size = fFacets.size();           << 211   for (std::vector<G4VFacet *>::iterator f=facets.begin(); f!=facets.end(); f++)
176   for (std::size_t i = 0; i < size; ++i)  { de << 212   {
177   fFacets.clear();                             << 213     delete *f;
178   delete fpPolyhedron; fpPolyhedron = nullptr; << 214   }
                                                   >> 215   facets.clear();
179 }                                                 216 }
180                                                   217 
181 //////////////////////////////////////////////    218 ///////////////////////////////////////////////////////////////////////////////
182 //                                                219 //
183 void G4TessellatedSolid::CopyObjects (const G4 << 220 void G4TessellatedSolid::CopyObjects (const G4TessellatedSolid &s)
184 {                                                 221 {
185   G4ThreeVector reductionRatio;                << 222   size_t n = s.GetNumberOfFacets();
186   G4int fmaxVoxels = fVoxels.GetMaxVoxels(redu << 223   for (size_t i=0; i<n; i++)
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   {                                               224   {
195     G4VFacet *facetClone = (ts.GetFacet(i))->G << 225     G4VFacet *facetClone = (s.GetFacet(i))->GetClone();
196     AddFacet(facetClone);                         226     AddFacet(facetClone);
197   }                                               227   }
198   if (ts.GetSolidClosed()) SetSolidClosed(true << 228   
                                                   >> 229   if ( s.GetSolidClosed() )  { SetSolidClosed(true); }
199 }                                                 230 }
200                                                   231 
201 //////////////////////////////////////////////    232 ///////////////////////////////////////////////////////////////////////////////
202 //                                                233 //
203 // Add a facet to the facet list.              << 234 // Add a facet to the facet list.  Note that you can add, but you cannot
204 // Note that you can add, but you cannot delet << 235 // delete.
205 //                                                236 //
206 G4bool G4TessellatedSolid::AddFacet (G4VFacet* << 237 G4bool G4TessellatedSolid::AddFacet (G4VFacet *aFacet)
207 {                                                 238 {
208   // Add the facet to the vector.                 239   // Add the facet to the vector.
209   //                                           << 240 
210   if (fSolidClosed)                            << 241   if (solidClosed)
211   {                                               242   {
212     G4Exception("G4TessellatedSolid::AddFacet(    243     G4Exception("G4TessellatedSolid::AddFacet()", "GeomSolids1002",
213                 JustWarning, "Attempt to add f    244                 JustWarning, "Attempt to add facets when solid is closed.");
214     return false;                                 245     return false;
215   }                                               246   }
216   else if (aFacet->IsDefined())                   247   else if (aFacet->IsDefined())
217   {                                               248   {
218     set<G4VertexInfo,G4VertexComparator>::iter << 249     if (facets.size() == 0)
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     {                                             250     {
228       G4double kCarTolerance3 = 3 * kCarTolera << 251       facets.push_back(aFacet);
229       pos = fFacetList.lower_bound(value);     << 252     }
230                                                << 253     else
231       it = pos;                                << 254     {
232       while (!found && it != end)    // Loop c << 255       G4bool found = false;
                                                   >> 256       FacetI it    = facets.begin();
                                                   >> 257       do
                                                   >> 258       {
                                                   >> 259         found = (**it == *aFacet);
                                                   >> 260       } while (!found && ++it!=facets.end());
                                                   >> 261     
                                                   >> 262       if (found)
233       {                                           263       {
234         G4int id = (*it).id;                   << 264         delete *it;
235         G4VFacet *facet = fFacets[id];         << 265         facets.erase(it);
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       }                                           266       }
242                                                << 267       else
243       if (fFacets.size() > 1)                  << 
244       {                                           268       {
245         it = pos;                              << 269         facets.push_back(aFacet);
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       }                                           270       }
258     }                                             271     }
259                                                << 272     
260     if (!found)                                << 
261     {                                          << 
262       fFacets.push_back(aFacet);               << 
263       fFacetList.insert(value);                << 
264     }                                          << 
265     return true;                                  273     return true;
266   }                                               274   }
267   else                                            275   else
268   {                                               276   {
269     G4Exception("G4TessellatedSolid::AddFacet(    277     G4Exception("G4TessellatedSolid::AddFacet()", "GeomSolids1002",
270                 JustWarning, "Attempt to add f << 278                 JustWarning, "Attempt to add facet not properly defined.");    
271     aFacet->StreamInfo(G4cout);                   279     aFacet->StreamInfo(G4cout);
272     return false;                                 280     return false;
273   }                                               281   }
274 }                                                 282 }
275                                                   283 
276 //////////////////////////////////////////////    284 ///////////////////////////////////////////////////////////////////////////////
277 //                                                285 //
278 G4int G4TessellatedSolid::SetAllUsingStack(con << 286 void G4TessellatedSolid::SetSolidClosed (const G4bool t)
279                                            con << 287 {
280                                            G4b << 288   if (t)
281 {                                              << 289   {
282   vector<G4int> xyz = voxel;                   << 290     vertexList.clear();
283   stack<vector<G4int> > pos;                   << 291     for (FacetCI it=facets.begin(); it!=facets.end(); it++)
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     {                                             292     {
296       checked.SetBitNumber(index, true);       << 293       size_t m = vertexList.size();
297                                                << 294       G4ThreeVector p(0.0,0.0,0.0);
298       if (fVoxels.IsEmpty(index))              << 295       for (size_t i=0; i<(*it)->GetNumberOfVertices(); i++)
299       {                                        << 296       {
300         ++filled;                              << 297         p            = (*it)->GetVertex(i);
301                                                << 298         G4bool found = false;
302         fInsides.SetBitNumber(index, status);  << 299         size_t j     = 0;
303                                                << 300         while (j < m && !found)
304         for (auto i = 0; i <= 2; ++i)          << 
305         {                                         301         {
306           if (xyz[i] < max[i] - 1)             << 302           G4ThreeVector q = vertexList[j];
307           {                                    << 303           found = (q-p).mag() < 0.5*kCarTolerance;
308             xyz[i]++;                          << 304           if (!found) j++;
309             pos.push(xyz);                     << 305         }
310             xyz[i]--;                          << 306     
311           }                                    << 307         if (!found)
312                                                << 308         {
313           if (xyz[i] > 0)                      << 309           vertexList.push_back(p);
314           {                                    << 310           (*it)->SetVertexIndex(i,vertexList.size()-1);
315             xyz[i]--;                          << 311         }
316             pos.push(xyz);                     << 312         else
317             xyz[i]++;                          << 313         {
318           }                                    << 314           (*it)->SetVertexIndex(i,j);
319         }                                         315         }
320       }                                           316       }
321     }                                             317     }
322   }                                            << 318     //
323   return filled;                               << 319     // Now update the maximum x, y and z limits of the volume.
324 }                                              << 320     //
325                                                << 321     for (size_t i=0; i<vertexList.size(); i++)
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     {                                             322     {
344       for (voxel[0] = 0; voxel[0] < maxVoxels[ << 323       G4ThreeVector p = vertexList[i];
                                                   >> 324       G4double x      = p.x();
                                                   >> 325       G4double y      = p.y();
                                                   >> 326       G4double z      = p.z();
                                                   >> 327     
                                                   >> 328       if (i > 0)
                                                   >> 329       {
                                                   >> 330         if (x > xMaxExtent) xMaxExtent = x;
                                                   >> 331         if (x < xMinExtent) xMinExtent = x;
                                                   >> 332         if (y > yMaxExtent) yMaxExtent = y;
                                                   >> 333         if (y < yMinExtent) yMinExtent = y;
                                                   >> 334         if (z > zMaxExtent) zMaxExtent = z;
                                                   >> 335         if (z < zMinExtent) zMinExtent = z;
                                                   >> 336       }
                                                   >> 337       else
345       {                                           338       {
346         G4int index = fVoxels.GetVoxelsIndex(v << 339         xMaxExtent = x;
347         if (!checked[index] && fVoxels.IsEmpty << 340         xMinExtent = x;
348         {                                      << 341         yMaxExtent = y;
349           for (auto i = 0; i <= 2; ++i)        << 342         yMinExtent = y;
350           {                                    << 343         zMaxExtent = z;
351             point[i] = fVoxels.GetBoundary(i)[ << 344         zMinExtent = z;    
352           }                                    << 
353           auto inside = (G4bool) (InsideNoVoxe << 
354           SetAllUsingStack(voxel, maxVoxels, i << 
355         }                                      << 
356         else checked.SetBitNumber(index);      << 
357       }                                           345       }
358     }                                             346     }
359   }                                            << 
360 }                                              << 
361                                                << 
362 ////////////////////////////////////////////// << 
363 //                                                347 //
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 //                                                348 //
382 // Compute extremeFacets, i.e. find those face    349 // Compute extremeFacets, i.e. find those facets that have surface
383 // planes that bound the volume.                  350 // planes that bound the volume.
384 // Note that this is going to reject concaved  << 351 // Note that this is going to reject concaved surfaces as being extreme.  Also
385 // note that if the vertex is on the facet, di    352 // note that if the vertex is on the facet, displacement is zero, so IsInside
386 // returns true. So will this work??  Need non << 353 // returns true.  So will this work??  Need non-equality
387 // "G4bool inside = displacement < 0.0;"          354 // "G4bool inside = displacement < 0.0;"
388 // or                                             355 // or
389 // "G4bool inside = displacement <= -0.5*kCarT << 356 // "G4bool inside = displacement <= -0.5*kCarTolerance" 
390 // (Notes from PT 13/08/2007).                    357 // (Notes from PT 13/08/2007).
391 //                                                358 //
392 void G4TessellatedSolid::SetExtremeFacets()    << 359     for (FacetCI it=facets.begin(); it!=facets.end(); it++)
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     {                                             360     {
434       if (!facet.IsInside(vertices[i]))        << 361       G4bool isExtreme = true;
                                                   >> 362       for (size_t i=0; i<vertexList.size(); i++)
435       {                                           363       {
436         isExtreme = false;                     << 364         if (!(*it)->IsInside(vertexList[i]))
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         {                                         365         {
490           id = (*it).id;                       << 366           isExtreme = false;
491           G4ThreeVector q = fVertexList[id];   << 367           break;
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         }                                         368         }
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       }                                           369       }
                                                   >> 370       if (isExtreme)
                                                   >> 371         extremeFacets.insert(*it);
554     }                                             372     }
555     // only now it is possible to change verti << 373     solidClosed = true;
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   }                                               374   }
575 #endif                                         << 375   else
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   {                                               376   {
595 #ifdef G4SPECSDEBUG                            << 377     solidClosed = false;
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   }                                               378   }
646   fSolidClosed = t;                            << 
647 }                                                 379 }
648                                                   380 
649 //////////////////////////////////////////////    381 ///////////////////////////////////////////////////////////////////////////////
650 //                                                382 //
651 // GetSolidClosed                                 383 // GetSolidClosed
652 //                                                384 //
653 // Used to determine whether the solid is clos << 385 // Used to determine whether the solid is closed to adding further facets.
654 //                                                386 //
655 G4bool G4TessellatedSolid::GetSolidClosed () c    387 G4bool G4TessellatedSolid::GetSolidClosed () const
656 {                                              << 388   {return solidClosed;}
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                                                   389 
731 //////////////////////////////////////////////    390 ///////////////////////////////////////////////////////////////////////////////
732 //                                                391 //
733 // operator+=                                     392 // operator+=
734 //                                                393 //
735 // This operator allows the user to add two te    394 // This operator allows the user to add two tessellated solids together, so
736 // that the solid on the left then includes al    395 // that the solid on the left then includes all of the facets in the solid
737 // on the right.  Note that copies of the face    396 // on the right.  Note that copies of the facets are generated, rather than
738 // using the original facet set of the solid o    397 // using the original facet set of the solid on the right.
739 //                                                398 //
740 G4TessellatedSolid&                            << 399 const G4TessellatedSolid &G4TessellatedSolid::operator+=
741 G4TessellatedSolid::operator+=(const G4Tessell << 400   (const G4TessellatedSolid &right)
742 {                                                 401 {
743   G4int size = right.GetNumberOfFacets();      << 402   for (size_t i=0; i<right.GetNumberOfFacets(); i++)
744   for (G4int i = 0; i < size; ++i)             << 
745     AddFacet(right.GetFacet(i)->GetClone());      403     AddFacet(right.GetFacet(i)->GetClone());
746                                                << 
747   return *this;                                   404   return *this;
748 }                                                 405 }
749                                                   406 
750 //////////////////////////////////////////////    407 ///////////////////////////////////////////////////////////////////////////////
751 //                                                408 //
752 // GetNumberOfFacets                           << 409 // GetFacet
                                                   >> 410 //
                                                   >> 411 // Access pointer to facet in solid, indexed by integer i.
753 //                                                412 //
754 G4int G4TessellatedSolid::GetNumberOfFacets()  << 413 G4VFacet *G4TessellatedSolid::GetFacet (size_t i) const
755 {                                                 414 {
756   return (G4int)fFacets.size();                << 415   return facets[i];
757 }                                                 416 }
758                                                   417 
759 //////////////////////////////////////////////    418 ///////////////////////////////////////////////////////////////////////////////
760 //                                                419 //
761 EInside G4TessellatedSolid::InsideVoxels(const << 420 // GetNumberOfFacets
                                                   >> 421 //
                                                   >> 422 size_t G4TessellatedSolid::GetNumberOfFacets () const
762 {                                                 423 {
763   //                                           << 424   return facets.size();
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 }                                                 425 }
949                                                   426 
950 //////////////////////////////////////////////    427 ///////////////////////////////////////////////////////////////////////////////
951 //                                                428 //
952 EInside G4TessellatedSolid::InsideNoVoxels (co << 429 // EInside G4TessellatedSolid::Inside (const G4ThreeVector &p) const
                                                   >> 430 //
                                                   >> 431 // This method must return:
                                                   >> 432 //    * kOutside if the point at offset p is outside the shape
                                                   >> 433 //      boundaries plus kCarTolerance/2,
                                                   >> 434 //    * kSurface if the point is <= kCarTolerance/2 from a surface, or
                                                   >> 435 //    * kInside otherwise.
                                                   >> 436 //
                                                   >> 437 EInside G4TessellatedSolid::Inside (const G4ThreeVector &p) const
953 {                                                 438 {
954   //                                           << 439 //
955   // First the simple test - check if we're ou << 440 // First the simple test - check if we're outside of the X-Y-Z extremes
956   // of the tessellated solid.                 << 441 // of the tessellated solid.
957   //                                           << 442 //
958   if (OutsideOfExtent(p, kCarTolerance))       << 443   if ( p.x() < xMinExtent - kCarTolerance ||
                                                   >> 444        p.x() > xMaxExtent + kCarTolerance ||
                                                   >> 445        p.y() < yMinExtent - kCarTolerance ||
                                                   >> 446        p.y() > yMaxExtent + kCarTolerance ||
                                                   >> 447        p.z() < zMinExtent - kCarTolerance ||
                                                   >> 448        p.z() > zMaxExtent + kCarTolerance )
                                                   >> 449   {
959     return kOutside;                              450     return kOutside;
960                                                << 451   }  
961   const G4double dirTolerance = 1.0E-14;       << 
962                                                   452 
963   G4double minDist = kInfinity;                   453   G4double minDist = kInfinity;
964   //                                           << 454 //
965   // Check if we are close to a surface        << 455 //
966   //                                           << 456 // Check if we are close to a surface
967   std::size_t size = fFacets.size();           << 457 //
968   for (std::size_t i = 0; i < size; ++i)       << 458   for (FacetCI f=facets.begin(); f!=facets.end(); f++)
969   {                                               459   {
970     G4VFacet& facet = *fFacets[i];             << 460     G4double dist = (*f)->Distance(p,minDist);
971     G4double dist = facet.Distance(p,minDist); << 
972     if (dist < minDist) minDist = dist;           461     if (dist < minDist) minDist = dist;
973     if (dist <= kCarToleranceHalf)             << 462     if (dist <= 0.5*kCarTolerance)
974     {                                             463     {
975       return kSurface;                            464       return kSurface;
976     }                                             465     }
977   }                                               466   }
978   //                                           << 467 //
979   // The following is something of an adaptati << 468 //
980   // Rickard Holmberg augmented with informati << 469 // The following is something of an adaptation of the method implemented by
981   // "Geometric Tools for Computer Graphics,"  << 470 // Rickard Holmberg augmented with information from Schneider & Eberly,
982   // trying to determine whether we're inside  << 471 // "Geometric Tools for Computer Graphics," pp700-701, 2003.  In essence, we're
983   // rays and determining if the first surface << 472 // trying to determine whether we're inside the volume by projecting a few rays
984   // between 0 to pi/2 (out-going) or pi/2 to  << 473 // and determining if the first surface crossed is has a normal vector between
985   // avoid rays which are nearly within the pl << 474 // 0 to pi/2 (out-going) or pi/2 to pi (in-going).  We should also avoid rays
986   // and therefore produce rays randomly. For  << 475 // which are nearly within the plane of the tessellated surface, and therefore
987   // over-engineered (belt-braces-and-ducttape << 476 // produce rays randomly.  For the moment, this is a bit over-engineered
988   //                                           << 477 // (belt-braces-and-ducttape).
                                                   >> 478 //
989 #if G4SPECSDEBUG                                  479 #if G4SPECSDEBUG
990   G4int nTry                = 7;                  480   G4int nTry                = 7;
991 #else                                             481 #else
992   G4int nTry                = 3;                  482   G4int nTry                = 3;
993 #endif                                            483 #endif
994   G4double distOut          = kInfinity;          484   G4double distOut          = kInfinity;
995   G4double distIn           = kInfinity;          485   G4double distIn           = kInfinity;
996   G4double distO            = 0.0;                486   G4double distO            = 0.0;
997   G4double distI            = 0.0;                487   G4double distI            = 0.0;
998   G4double distFromSurfaceO = 0.0;                488   G4double distFromSurfaceO = 0.0;
999   G4double distFromSurfaceI = 0.0;                489   G4double distFromSurfaceI = 0.0;
1000   G4ThreeVector normalO(0.0,0.0,0.0);            490   G4ThreeVector normalO(0.0,0.0,0.0);
1001   G4ThreeVector normalI(0.0,0.0,0.0);            491   G4ThreeVector normalI(0.0,0.0,0.0);
1002   G4bool crossingO          = false;             492   G4bool crossingO          = false;
1003   G4bool crossingI          = false;             493   G4bool crossingI          = false;
1004   EInside location          = kOutside;          494   EInside location          = kOutside;
1005   EInside locationprime     = kOutside;          495   EInside locationprime     = kOutside;
1006   G4int sm = 0;                               << 496   G4int m                   = 0;
1007                                                  497 
1008   for (G4int i=0; i<nTry; ++i)                << 498   for (G4int i=0; i<nTry; i++)
1009   {                                              499   {
1010     G4bool nearParallel = false;                 500     G4bool nearParallel = false;
1011     do    // Loop checking, 13.08.2015, G.Cos << 501     do
1012     {                                            502     {
1013       //                                      << 503 //
1014       // We loop until we find direction wher << 504 //
1015       // to the surface of any facet since th << 505 // We loop until we find direction where the vector is not nearly parallel
1016       // case is that the angles should be su << 506 // to the surface of any facet since this causes ambiguities.  The usual
1017       // are 20 random directions to select f << 507 // case is that the angles should be sufficiently different, but there are 20
1018       //                                      << 508 // random directions to select from - hopefully sufficient.
1019       distOut = distIn = kInfinity;           << 509 //
1020       G4ThreeVector v = fRandir[sm];          << 510       distOut          = kInfinity;
1021       sm++;                                   << 511       distIn           = kInfinity;
1022       auto f = fFacets.cbegin();              << 512       G4ThreeVector v  = randir[m];
1023                                               << 513       m++;
1024       do    // Loop checking, 13.08.2015, G.C << 514       FacetCI f = facets.begin();
                                                   >> 515       do
1025       {                                          516       {
1026         //                                    << 517 //
1027         // Here we loop through the facets to << 518 //
1028         // intersection between the ray and t << 519 // Here we loop through the facets to find out if there is an intersection
1029         // separately whether the ray is ente << 520 // between the ray and that facet.  The test if performed separately whether
1030         //                                    << 521 // the ray is entering the facet or exiting.
1031         crossingO = ((*f)->Intersect(p,v,true << 522 //
1032         crossingI = ((*f)->Intersect(p,v,fals << 523         crossingO =  ((*f)->Intersect(p,v,true,distO,distFromSurfaceO,normalO));
                                                   >> 524         crossingI =  ((*f)->Intersect(p,v,false,distI,distFromSurfaceI,normalI));
1033         if (crossingO || crossingI)              525         if (crossingO || crossingI)
1034         {                                        526         {
1035           nearParallel = (crossingO && std::f << 527           nearParallel = (crossingO && std::fabs(normalO.dot(v))<dirTolerance) ||
1036                       || (crossingI && std::f << 528                          (crossingI && std::fabs(normalI.dot(v))<dirTolerance);
1037           if (!nearParallel)                     529           if (!nearParallel)
1038           {                                      530           {
1039             if (crossingO && distO > 0.0 && d    531             if (crossingO && distO > 0.0 && distO < distOut) distOut = distO;
1040             if (crossingI && distI > 0.0 && d    532             if (crossingI && distI > 0.0 && distI < distIn)  distIn  = distI;
1041           }                                      533           }
1042         }                                        534         }
1043       } while (!nearParallel && ++f != fFacet << 535       } while (!nearParallel && ++f!=facets.end());
1044     } while (nearParallel && sm != fMaxTries) << 536     } while (nearParallel && m!=maxTries);
1045                                                  537 
1046 #ifdef G4VERBOSE                                 538 #ifdef G4VERBOSE
1047     if (sm == fMaxTries)                      << 539     if (m == maxTries)
1048     {                                            540     {
1049       //                                      << 541 //
1050       // We've run out of random vector direc << 542 //
1051       // sufficiently low (nTries <= 0.5*maxT << 543 // We've run out of random vector directions.  If nTries is set sufficiently
1052       // that there is something wrong with g << 544 // low (nTries <= 0.5*maxTries) then this would indicate that there is
1053       //                                      << 545 // something wrong with geometry.
                                                   >> 546 //
1054       std::ostringstream message;                547       std::ostringstream message;
1055       G4long oldprc = message.precision(16);  << 548       G4int oldprc = message.precision(16);
1056       message << "Cannot determine whether po    549       message << "Cannot determine whether point is inside or outside volume!"
1057         << G4endl                             << 550               << G4endl
1058         << "Solid name       = " << GetName() << 551               << "Solid name       = " << GetName()  << G4endl
1059         << "Geometry Type    = " << fGeometry << 552               << "Geometry Type    = " << geometryType  << G4endl
1060         << "Number of facets = " << fFacets.s << 553               << "Number of facets = " << facets.size() << G4endl
1061         << "Position:"  << G4endl << G4endl   << 554               << "Position:"  << G4endl << G4endl
1062         << "p.x() = "   << p.x()/mm << " mm"  << 555               << "p.x() = "   << p.x()/mm << " mm" << G4endl
1063         << "p.y() = "   << p.y()/mm << " mm"  << 556               << "p.y() = "   << p.y()/mm << " mm" << G4endl
1064         << "p.z() = "   << p.z()/mm << " mm"; << 557               << "p.z() = "   << p.z()/mm << " mm";
1065       message.precision(oldprc);                 558       message.precision(oldprc);
1066       G4Exception("G4TessellatedSolid::Inside    559       G4Exception("G4TessellatedSolid::Inside()",
1067         "GeomSolids1002", JustWarning, messag << 560                   "GeomSolids1002", JustWarning, message);
1068     }                                            561     }
1069 #endif                                           562 #endif
1070     //                                        << 563 //
1071     // In the next if-then-elseif G4String th << 564 //
1072     // (1) You don't hit anything so cannot b << 565 // In the next if-then-elseif string the logic is as follows:
1073     //     constructed correctly!             << 566 // (1) You don't hit anything so cannot be inside volume, provided volume
1074     // (2) Distance to inside (ie. nearest fa << 567 //     constructed correctly!
1075     //     shorter than distance to outside ( << 568 // (2) Distance to inside (ie. nearest facet such that you enter facet) is
1076     //     facet) - on condition of safety di << 569 //     shorter than distance to outside (nearest facet such that you exit
1077     // (3) Distance to outside is shorter tha << 570 //     facet) - on condition of safety distance - therefore we're outside.
1078     // we're inside.                          << 571 // (3) Distance to outside is shorter than distance to inside therefore we're
1079     //                                        << 572 //     inside.
                                                   >> 573 //
1080     if (distIn == kInfinity && distOut == kIn    574     if (distIn == kInfinity && distOut == kInfinity)
1081       locationprime = kOutside;                  575       locationprime = kOutside;
1082     else if (distIn <= distOut - kCarToleranc << 576     else if (distIn <= distOut - kCarTolerance*0.5)
1083       locationprime = kOutside;                  577       locationprime = kOutside;
1084     else if (distOut <= distIn - kCarToleranc << 578     else if (distOut <= distIn - kCarTolerance*0.5)
1085       locationprime = kInside;                   579       locationprime = kInside;
1086                                                  580 
1087     if (i == 0) location = locationprime;     << 581     if (i == 0)  { location = locationprime; }
1088   }                                           << 582 #ifdef G4VERBOSE
1089                                               << 583     else if (locationprime != location)
1090   return location;                            << 584     {
1091 }                                             << 
1092                                               << 
1093 ///////////////////////////////////////////// << 
1094 //                                               585 //
1095 // Return index of the facet closest to the p << 
1096 // be located on the surface. Return -1 if no << 
1097 //                                               586 //
1098 G4int G4TessellatedSolid::GetFacetIndex (cons << 587 // Different ray directions result in different answer.  Seems like the
1099 {                                             << 588 // geometry is not constructed correctly.
1100   G4int index = -1;                           << 589 //
1101                                               << 590       std::ostringstream message;
1102   if (fVoxels.GetCountOfVoxels() > 1)         << 591       G4int oldprc = message.precision(16);
1103   {                                           << 592       message << "Cannot determine whether point is inside or outside volume!"
1104     vector<G4int> curVoxel(3);                << 593               << G4endl
1105     fVoxels.GetVoxel(curVoxel, p);            << 594               << "Solid name       = " << GetName()  << G4endl
1106     const vector<G4int> &candidates = fVoxels << 595               << "Geometry Type    = " << geometryType  << G4endl
1107     if (auto limit = (G4int)candidates.size() << 596               << "Number of facets = " << facets.size() << G4endl
1108     {                                         << 597               << "Position:"  << G4endl << G4endl
1109       G4double minDist = kInfinity;           << 598               << "p.x() = "   << p.x()/mm << " mm" << G4endl
1110       for(G4int i = 0 ; i < limit ; ++i)      << 599               << "p.y() = "   << p.y()/mm << " mm" << G4endl
1111       {                                       << 600               << "p.z() = "   << p.z()/mm << " mm";
1112         G4int candidate = candidates[i];      << 601       message.precision(oldprc);
1113         G4VFacet& facet = *fFacets[candidate] << 602       G4Exception("G4TessellatedSolid::Inside()",
1114         G4double dist = facet.Distance(p, min << 603                   "GeomSolids1002", JustWarning, message);
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     }                                            604     }
                                                   >> 605 #endif
1138   }                                              606   }
1139   return index;                               << 607 
                                                   >> 608   return location;
1140 }                                                609 }
1141                                                  610 
1142 /////////////////////////////////////////////    611 ///////////////////////////////////////////////////////////////////////////////
1143 //                                               612 //
                                                   >> 613 // G4ThreeVector G4TessellatedSolid::SurfaceNormal (const G4ThreeVector &p) const
                                                   >> 614 //
1144 // Return the outwards pointing unit normal o    615 // Return the outwards pointing unit normal of the shape for the
1145 // surface closest to the point at offset p.     616 // 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                                                  617 
1160     if (auto limit = (G4int)candidates.size() << 618 G4ThreeVector G4TessellatedSolid::SurfaceNormal (const G4ThreeVector &p) const
1161     {                                         << 619 {
1162       minDist = kInfinity;                    << 620   FacetCI minFacet;
1163       for(G4int i = 0 ; i < limit ; ++i)      << 621   G4double minDist   = kInfinity;
1164       {                                       << 622   G4double dist      = 0.0;
1165         G4int candidate = candidates[i];      << 623   G4ThreeVector normal;
1166         G4VFacet &fct = *fFacets[candidate];  << 624   
1167         G4double dist = fct.Distance(p,minDis << 625   for (FacetCI f=facets.begin(); f!=facets.end(); f++)
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   {                                              626   {
1180     minDist = kInfinity;                      << 627     dist = (*f)->Distance(p,minDist);
1181     std::size_t size = fFacets.size();        << 628     if (dist < minDist)
1182     for (std::size_t i = 0; i < size; ++i)    << 
1183     {                                            629     {
1184       G4VFacet& f = *fFacets[i];              << 630       minDist  = dist;
1185       G4double dist = f.Distance(p, minDist); << 631       minFacet = f;
1186       if (dist < minDist)                     << 
1187       {                                       << 
1188         minDist  = dist;                      << 
1189         facet = &f;                           << 
1190       }                                       << 
1191     }                                            632     }
1192   }                                              633   }
1193                                               << 634   
1194   if (minDist != kInfinity)                      635   if (minDist != kInfinity)
1195   {                                              636   {
1196     if (facet != nullptr)  { aNormal = facet- << 637      normal = (*minFacet)->GetSurfaceNormal();
1197     return minDist <= kCarToleranceHalf;      << 
1198   }                                              638   }
1199   else                                           639   else
1200   {                                              640   {
1201 #ifdef G4VERBOSE                                 641 #ifdef G4VERBOSE
1202     std::ostringstream message;                  642     std::ostringstream message;
1203     message << "Point p is not on surface !?"    643     message << "Point p is not on surface !?" << G4endl
1204       << "          No facets found for point << 644             << "          No facets found for point: " << p << " !" << G4endl
1205       << "          Returning approximated va << 645             << "          Returning approximated value for normal.";
1206                                               << 646     G4Exception("G4TessellatedSolid::SurfaceNormal(p)", "GeomSolids1002",
1207     G4Exception("G4TessellatedSolid::SurfaceN << 647                 JustWarning, message );
1208                 "GeomSolids1002", JustWarning << 
1209 #endif                                           648 #endif
1210     aNormal = (p.z() > 0 ? G4ThreeVector(0,0, << 649     normal = (p.z()>0 ? G4ThreeVector(0,0,1) : G4ThreeVector(0,0,-1));
1211     return false;                             << 
1212   }                                              650   }
                                                   >> 651 
                                                   >> 652   return normal;
1213 }                                                653 }
1214                                                  654 
1215 /////////////////////////////////////////////    655 ///////////////////////////////////////////////////////////////////////////////
1216 //                                               656 //
1217 // G4double DistanceToIn(const G4ThreeVector&    657 // G4double DistanceToIn(const G4ThreeVector& p, const G4ThreeVector& v)
1218 //                                               658 //
1219 // Return the distance along the normalised v    659 // Return the distance along the normalised vector v to the shape,
1220 // from the point at offset p. If there is no    660 // from the point at offset p. If there is no intersection, return
1221 // kInfinity. The first intersection resultin << 661 // kInfinity. The first intersection resulting from ‘leaving’ a
1222 // surface/volume is discarded. Hence, this i    662 // surface/volume is discarded. Hence, this is tolerant of points on
1223 // surface of shape.                             663 // surface of shape.
1224 //                                            << 664 
1225 G4double                                      << 665 G4double G4TessellatedSolid::DistanceToIn (const G4ThreeVector &p,
1226 G4TessellatedSolid::DistanceToInNoVoxels (con << 666   const G4ThreeVector &v) const
1227                                           con << 
1228                                               << 
1229 {                                                667 {
1230   G4double minDist         = kInfinity;          668   G4double minDist         = kInfinity;
1231   G4double dist            = 0.0;                669   G4double dist            = 0.0;
1232   G4double distFromSurface = 0.0;                670   G4double distFromSurface = 0.0;
1233   G4ThreeVector normal;                       << 671   G4ThreeVector normal(0.0,0.0,0.0);
1234                                               << 672   
1235 #if G4SPECSDEBUG                                 673 #if G4SPECSDEBUG
1236   if (Inside(p) == kInside )                  << 674   if ( Inside(p) == kInside )
1237   {                                              675   {
1238     std::ostringstream message;               << 676      std::ostringstream message;
1239     G4int oldprc = message.precision(16) ;    << 677      G4int oldprc = message.precision(16) ;
1240     message << "Point p is already inside!?"  << 678      message << "Point p is already inside!?" << G4endl
1241       << "Position:"  << G4endl << G4endl     << 679              << "Position:"  << G4endl << G4endl
1242       << "   p.x() = "   << p.x()/mm << " mm" << 680              << "   p.x() = "   << p.x()/mm << " mm" << G4endl
1243       << "   p.y() = "   << p.y()/mm << " mm" << 681              << "   p.y() = "   << p.y()/mm << " mm" << G4endl
1244       << "   p.z() = "   << p.z()/mm << " mm" << 682              << "   p.z() = "   << p.z()/mm << " mm" << G4endl
1245       << "DistanceToOut(p) == " << DistanceTo << 683              << "DistanceToOut(p) == " << DistanceToOut(p);
1246     message.precision(oldprc) ;               << 684      message.precision(oldprc) ;
1247     G4Exception("G4TriangularFacet::DistanceT << 685      G4Exception("G4TriangularFacet::DistanceToIn(p,v)", "GeomSolids1002",
1248                 "GeomSolids1002", JustWarning << 686                  JustWarning, message);
1249   }                                              687   }
1250 #endif                                           688 #endif
1251                                                  689 
1252   std::size_t size = fFacets.size();          << 690   for (FacetCI f=facets.begin(); f!=facets.end(); f++)
1253   for (std::size_t i = 0; i < size; ++i)      << 
1254   {                                              691   {
1255     G4VFacet& facet = *fFacets[i];            << 692     if ((*f)->Intersect(p,v,false,dist,distFromSurface,normal))
1256     if (facet.Intersect(p,v,false,dist,distFr << 
1257     {                                            693     {
1258       //                                      << 694 //
1259       // set minDist to the new distance to c << 695 //
1260       // is in positive direction and point i << 696 // Set minDist to the new distance to current facet if distFromSurface is in
1261       // within 0.5*kCarTolerance of the surf << 697 // positive direction and point is not at surface.  If the point is within
1262       // zero and leave member function immed << 698 // 0.5*kCarTolerance of the surface, then force distance to be zero and
1263       // proposed by & credit to Akira Okumur << 699 // leave member function immediately (for efficiency), as proposed by & credit
1264       //                                      << 700 // to Akira Okumura.
1265       if (distFromSurface > kCarToleranceHalf << 701 //
                                                   >> 702       if (distFromSurface > 0.5*kCarTolerance && dist >= 0.0 && dist < minDist)
1266       {                                          703       {
1267         minDist  = dist;                         704         minDist  = dist;
1268       }                                          705       }
1269       else                                    << 706       else if (-0.5*kCarTolerance <= dist && dist <= 0.5*kCarTolerance)
1270       {                                          707       {
1271         if (-kCarToleranceHalf <= dist && dis << 708         return 0.0;
1272         {                                     << 
1273           return 0.0;                         << 
1274         }                                     << 
1275         else                                  << 
1276         {                                     << 
1277           if  (distFromSurface > -kCarToleran << 
1278             && distFromSurface <  kCarToleran << 
1279           {                                   << 
1280             minDist = dist;                   << 
1281           }                                   << 
1282         }                                     << 
1283       }                                          709       }
1284     }                                            710     }
1285   }                                              711   }
                                                   >> 712 
1286   return minDist;                                713   return minDist;
1287 }                                                714 }
1288                                                  715 
1289 /////////////////////////////////////////////    716 ///////////////////////////////////////////////////////////////////////////////
1290 //                                               717 //
1291 G4double                                      << 718 // G4double DistanceToIn(const G4ThreeVector& p)
1292 G4TessellatedSolid::DistanceToOutNoVoxels (co << 719 //
1293                                            co << 720 // Calculate distance to nearest surface of shape from an outside point p. The
1294                                               << 721 // distance can be an underestimate.
1295                                               << 
1296                                               << 
1297 {                                             << 
1298   G4double minDist         = kInfinity;       << 
1299   G4double dist            = 0.0;             << 
1300   G4double distFromSurface = 0.0;             << 
1301   G4ThreeVector normal, minNormal;            << 
1302                                                  722 
                                                   >> 723 G4double G4TessellatedSolid::DistanceToIn (const G4ThreeVector &p) const
                                                   >> 724 {
                                                   >> 725   G4double minDist = kInfinity;
                                                   >> 726   G4double dist    = 0.0;
                                                   >> 727   
1303 #if G4SPECSDEBUG                                 728 #if G4SPECSDEBUG
1304   if ( Inside(p) == kOutside )                << 729   if ( Inside(p) == kInside )
1305   {                                              730   {
1306     std::ostringstream message;               << 731      std::ostringstream message;
1307     G4int oldprc = message.precision(16) ;    << 732      G4int oldprc = message.precision(16) ;
1308     message << "Point p is already outside!?" << 733      message << "Point p is already inside!?" << G4endl
1309       << "Position:"  << G4endl << G4endl     << 734              << "Position:"  << G4endl << G4endl
1310       << "   p.x() = "   << p.x()/mm << " mm" << 735              << "p.x() = "   << p.x()/mm << " mm" << G4endl
1311       << "   p.y() = "   << p.y()/mm << " mm" << 736              << "p.y() = "   << p.y()/mm << " mm" << G4endl
1312       << "   p.z() = "   << p.z()/mm << " mm" << 737              << "p.z() = "   << p.z()/mm << " mm" << G4endl
1313       << "DistanceToIn(p) == " << DistanceToI << 738              << "DistanceToOut(p) == " << DistanceToOut(p);
1314     message.precision(oldprc) ;               << 739      message.precision(oldprc) ;
1315     G4Exception("G4TriangularFacet::DistanceT << 740      G4Exception("G4TriangularFacet::DistanceToIn(p)", "GeomSolids1002",
1316                 "GeomSolids1002", JustWarning << 741                  JustWarning, message);
1317   }                                              742   }
1318 #endif                                           743 #endif
1319                                                  744 
1320   G4bool isExtreme = false;                   << 745   for (FacetCI f=facets.begin(); f!=facets.end(); f++)
1321   std::size_t size = fFacets.size();          << 746   {
1322   for (std::size_t i = 0; i < size; ++i)      << 747     //dist = (*f)->Distance(p,minDist,false);
1323   {                                           << 748     dist = (*f)->Distance(p,minDist);
1324     G4VFacet& facet = *fFacets[i];            << 749     if (dist < minDist)  { minDist  = dist; }
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   }                                              750   }
                                                   >> 751   
                                                   >> 752   return minDist;
1358 }                                                753 }
1359                                                  754 
1360 /////////////////////////////////////////////    755 ///////////////////////////////////////////////////////////////////////////////
1361 //                                               756 //
1362 void G4TessellatedSolid::                     << 757 // G4double DistanceToOut(const G4ThreeVector& p, const G4ThreeVector& v,
1363 DistanceToOutCandidates(const std::vector<G4i << 758 //                        const G4bool calcNorm=false,
1364                         const G4ThreeVector&  << 759 //                        G4bool *validNorm=0, G4ThreeVector *n=0);
1365                         const G4ThreeVector&  << 760 //
1366                               G4double& minDi << 761 // Return distance along the normalised vector v to the shape, from a
1367                               G4int& minCandi << 762 // point at an offset p inside or on the surface of the
                                                   >> 763 // shape. Intersections with surfaces, when the point is not greater
                                                   >> 764 // than kCarTolerance/2 from a surface, must be ignored.
                                                   >> 765 //     If calcNorm is true, then it must also set validNorm to either
                                                   >> 766 //     * true, if the solid lies entirely behind or on the exiting
                                                   >> 767 //        surface. Then it must set n to the outwards normal vector
                                                   >> 768 //        (the Magnitude of the vector is not defined).
                                                   >> 769 //     * false, if the solid does not lie entirely behind or on the
                                                   >> 770 //       exiting surface.
                                                   >> 771 // If calcNorm is false, then validNorm and n are unused.
                                                   >> 772 
                                                   >> 773 G4double G4TessellatedSolid::DistanceToOut (const G4ThreeVector &p,
                                                   >> 774                     const G4ThreeVector &v, const G4bool calcNorm,
                                                   >> 775                           G4bool *validNorm, G4ThreeVector *n) const
1368 {                                                776 {
1369   auto candidatesCount = (G4int)candidates.si << 777   G4double minDist         = kInfinity;
1370   G4double dist            = 0.0;                778   G4double dist            = 0.0;
1371   G4double distFromSurface = 0.0;                779   G4double distFromSurface = 0.0;
1372   G4ThreeVector normal;                       << 780   G4ThreeVector normal(0.0,0.0,0.0);
                                                   >> 781   G4ThreeVector minNormal(0.0,0.0,0.0);
                                                   >> 782   
                                                   >> 783 #if G4SPECSDEBUG
                                                   >> 784   if ( Inside(p) == kOutside )
                                                   >> 785   {
                                                   >> 786      std::ostringstream message;
                                                   >> 787      G4int oldprc = message.precision(16) ;
                                                   >> 788      message << "Point p is already outside!?" << G4endl
                                                   >> 789              << "Position:"  << G4endl << G4endl
                                                   >> 790              << "   p.x() = "   << p.x()/mm << " mm" << G4endl
                                                   >> 791              << "   p.y() = "   << p.y()/mm << " mm" << G4endl
                                                   >> 792              << "   p.z() = "   << p.z()/mm << " mm" << G4endl
                                                   >> 793              << "DistanceToIn(p) == " << DistanceToIn(p);
                                                   >> 794      message.precision(oldprc) ;
                                                   >> 795      G4Exception("G4TriangularFacet::DistanceToOut(p)", "GeomSolids1002",
                                                   >> 796                  JustWarning, message);
                                                   >> 797   }
                                                   >> 798 #endif
1373                                                  799 
1374   for (G4int i = 0 ; i < candidatesCount; ++i << 800   G4bool isExtreme = false;
                                                   >> 801   for (FacetCI f=facets.begin(); f!=facets.end(); f++)
1375   {                                              802   {
1376     G4int candidate = candidates[i];          << 803     if ((*f)->Intersect(p,v,true,dist,distFromSurface,normal))
1377     G4VFacet& facet = *fFacets[candidate];    << 804      {
1378     if (facet.Intersect(aPoint,direction,true << 805       if (distFromSurface > 0.0 && distFromSurface <= 0.5*kCarTolerance &&
1379     {                                         << 806           (*f)->Distance(p,kCarTolerance) <= 0.5*kCarTolerance)
1380       if (distFromSurface > 0.0 && distFromSu << 
1381        && facet.Distance(aPoint,kCarTolerance << 
1382       {                                          807       {
1383         // We are on a surface                << 808         // We are on a surface. Return zero.
1384         //                                    << 809         if (calcNorm) {
1385         minDist = 0.0;                        << 810           *validNorm = extremeFacets.count(*f);
1386         minNormal = normal;                   << 811           *n         = SurfaceNormal(p);
1387         minCandidate = candidate;             << 812         }  
1388         break;                                << 813         return 0.0;
1389       }                                          814       }
1390       if (dist >= 0.0 && dist < minDist)         815       if (dist >= 0.0 && dist < minDist)
1391       {                                          816       {
1392         minDist = dist;                       << 817         minDist   = dist;
1393         minNormal = normal;                      818         minNormal = normal;
1394         minCandidate = candidate;             << 819         isExtreme = extremeFacets.count(*f);
1395       }                                          820       }
1396     }                                            821     }
1397   }                                              822   }
1398 }                                             << 823   
1399                                               << 824   if (minDist < kInfinity)
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   {                                              825   {
1413     minDistance = kInfinity;                  << 826     if (calcNorm)
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     {                                            827     {
1461       aConvex = (fExtremeFacets.find(fFacets[ << 828       *validNorm = isExtreme;
1462               != fExtremeFacets.end());       << 829       *n         = minNormal;
1463     }                                            830     }
                                                   >> 831     return minDist;
1464   }                                              832   }
1465   else                                           833   else
1466   {                                              834   {
1467     minDistance = DistanceToOutNoVoxels(aPoin << 835     // No intersection found
1468                                         aConv << 836     if (calcNorm)
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     {                                            837     {
1492       //                                      << 838       *validNorm = false;
1493       // Set minDist to the new distance to c << 839       *n         = SurfaceNormal(p);
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     }                                            840     }
                                                   >> 841     return 0.0;
1517   }                                              842   }
1518   return minDistance;                         << 
1519 }                                                843 }
1520                                                  844 
1521 /////////////////////////////////////////////    845 ///////////////////////////////////////////////////////////////////////////////
1522 //                                               846 //
1523 G4double                                      << 847 // G4double DistanceToOut(const G4ThreeVector& p)
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 //                                               848 //
1577 G4bool                                        << 849 // Calculate distance to nearest surface of shape from an inside
1578 G4TessellatedSolid::CompareSortedVoxel(const  << 850 // point. The distance can be an underestimate.
1579                                        const  << 
1580 {                                             << 
1581   return l.second < r.second;                 << 
1582 }                                             << 
1583                                                  851 
1584 ///////////////////////////////////////////// << 852 G4double G4TessellatedSolid::DistanceToOut (const G4ThreeVector &p) const
1585 //                                            << 
1586 G4double                                      << 
1587 G4TessellatedSolid::MinDistanceFacet(const G4 << 
1588                                            G4 << 
1589                                            G4 << 
1590 {                                                853 {
1591   G4double minDist = kInfinity;                  854   G4double minDist = kInfinity;
1592                                               << 855   G4double dist    = 0.0;
1593   G4int size = fVoxels.GetVoxelBoxesSize();   << 856   
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                                 857 #if G4SPECSDEBUG
1700   if ( Inside(p) == kOutside )                   858   if ( Inside(p) == kOutside )
1701   {                                              859   {
1702     std::ostringstream message;               << 860      std::ostringstream message;
1703     G4int oldprc = message.precision(16) ;    << 861      G4int oldprc = message.precision(16) ;
1704     message << "Point p is already outside!?" << 862      message << "Point p is already outside!?" << G4endl
1705       << "Position:"  << G4endl << G4endl     << 863              << "Position:"  << G4endl << G4endl
1706       << "p.x() = "   << p.x()/mm << " mm" << << 864              << "p.x() = "   << p.x()/mm << " mm" << G4endl
1707       << "p.y() = "   << p.y()/mm << " mm" << << 865              << "p.y() = "   << p.y()/mm << " mm" << G4endl
1708       << "p.z() = "   << p.z()/mm << " mm" << << 866              << "p.z() = "   << p.z()/mm << " mm" << G4endl
1709       << "DistanceToIn(p) == " << DistanceToI << 867              << "DistanceToIn(p) == " << DistanceToIn(p);
1710     message.precision(oldprc) ;               << 868      message.precision(oldprc) ;
1711     G4Exception("G4TriangularFacet::DistanceT << 869      G4Exception("G4TriangularFacet::DistanceToOut(p)", "GeomSolids1002",
1712                 "GeomSolids1002", JustWarning << 870                  JustWarning, message);
1713   }                                              871   }
1714 #endif                                           872 #endif
1715                                                  873 
1716   G4double minDist;                           << 874   for (FacetCI f=facets.begin(); f!=facets.end(); f++)
1717                                               << 875   {
1718   if (OutsideOfExtent(p, kCarTolerance)) retu << 876     //dist = (*f)->Distance(p,minDist,true);
1719                                               << 877     dist = (*f)->Distance(p,minDist);
1720   if (fVoxels.GetCountOfVoxels() > 1)         << 878     if (dist < minDist) minDist  = dist;
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   }                                              879   }
                                                   >> 880   
1737   return minDist;                                881   return minDist;
1738 }                                                882 }
1739                                                  883 
1740 /////////////////////////////////////////////    884 ///////////////////////////////////////////////////////////////////////////////
1741 //                                               885 //
1742 // G4GeometryType GetEntityType() const;         886 // G4GeometryType GetEntityType() const;
1743 //                                               887 //
1744 // Provide identification of the class of an  << 888 // Provide identification of the class of an object (required for
                                                   >> 889 // persistency and STEP interface).
1745 //                                               890 //
1746 G4GeometryType G4TessellatedSolid::GetEntityT    891 G4GeometryType G4TessellatedSolid::GetEntityType () const
1747 {                                                892 {
1748   return fGeometryType;                       << 893   return geometryType;
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 }                                                894 }
1780                                                  895 
1781 /////////////////////////////////////////////    896 ///////////////////////////////////////////////////////////////////////////////
1782 //                                               897 //
1783 // Make a clone of the object                    898 // Make a clone of the object
1784 //                                               899 //
1785 G4VSolid* G4TessellatedSolid::Clone() const      900 G4VSolid* G4TessellatedSolid::Clone() const
1786 {                                                901 {
1787   return new G4TessellatedSolid(*this);          902   return new G4TessellatedSolid(*this);
1788 }                                                903 }
1789                                                  904 
1790 /////////////////////////////////////////////    905 ///////////////////////////////////////////////////////////////////////////////
1791 //                                               906 //
1792 // EInside G4TessellatedSolid::Inside (const  << 907 void G4TessellatedSolid::DescribeYourselfTo (G4VGraphicsScene& scene) 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 {                                                908 {
1819   G4ThreeVector n;                            << 909   scene.AddSolid (*this);
1820   Normal(p, n);                               << 
1821   return n;                                   << 
1822 }                                                910 }
1823                                                  911 
1824 /////////////////////////////////////////////    912 ///////////////////////////////////////////////////////////////////////////////
1825 //                                               913 //
1826 // G4double DistanceToIn(const G4ThreeVector& << 914 // Dispatch to parameterisation for replication mechanism dimension
1827 //                                            << 915 // computation & modification.
1828 // Calculate distance to nearest surface of s << 916 //                                                                                
1829 // distance can be an underestimate.          << 917 //void G4TessellatedSolid::ComputeDimensions (G4VPVParameterisation* p,
1830 //                                            << 918 //  const G4int n, const G4VPhysicalVolume* pRep) const
1831 G4double G4TessellatedSolid::DistanceToIn(con << 919 //{
1832 {                                             << 920 //  G4VSolid *ptr = 0;
1833   return SafetyFromOutside(p, false);         << 921 //  ptr           = *this;
1834 }                                             << 922 //  p->ComputeDimensions(ptr,n,pRep);
                                                   >> 923 //}
1835                                                  924 
1836 /////////////////////////////////////////////    925 ///////////////////////////////////////////////////////////////////////////////
1837 //                                               926 //
1838 G4double G4TessellatedSolid::DistanceToIn(con << 927 std::ostream &G4TessellatedSolid::StreamInfo(std::ostream &os) const
1839                                           con << 
1840 {                                                928 {
1841   G4double dist = DistanceToInCore(p,v,kInfin << 929   os << G4endl;
1842 #ifdef G4SPECSDEBUG                           << 930   os << "Geometry Type    = " << geometryType  << G4endl;
1843   if (dist < kInfinity)                       << 931   os << "Number of facets = " << facets.size() << G4endl;
                                                   >> 932   
                                                   >> 933   for (FacetCI f = facets.begin(); f != facets.end(); f++)
1844   {                                              934   {
1845     if (Inside(p + dist*v) != kSurface)       << 935     os << "FACET #          = " << f-facets.begin()+1 << G4endl;
1846     {                                         << 936     (*f)->StreamInfo(os);
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   }                                              937   }
1855 #endif                                        << 938   os <<G4endl;
1856   return dist;                                << 939   
1857 }                                             << 940   return os;
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 }                                                941 }
1870                                                  942 
1871 /////////////////////////////////////////////    943 ///////////////////////////////////////////////////////////////////////////////
1872 //                                               944 //
1873 // G4double DistanceToOut(const G4ThreeVector << 945 G4Polyhedron *G4TessellatedSolid::CreatePolyhedron () const
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 {                                                946 {
1895   G4ThreeVector n;                            << 947   size_t nVertices = vertexList.size();
1896   G4bool valid;                               << 948   size_t nFacets   = facets.size();
1897                                               << 949   G4PolyhedronArbitrary *polyhedron =
1898   G4double dist = DistanceToOutCore(p, v, n,  << 950     new G4PolyhedronArbitrary (nVertices, nFacets);
1899   if (calcNorm)                               << 951   for (G4ThreeVectorList::const_iterator v = vertexList.begin();
                                                   >> 952         v!=vertexList.end(); v++) polyhedron->AddVertex(*v);
                                                   >> 953     
                                                   >> 954   for (FacetCI f=facets.begin(); f != facets.end(); f++)
1900   {                                              955   {
1901     *norm = n;                                << 956     size_t v[4];
1902     *validNorm = valid;                       << 957     for (size_t j=0; j<4; j++)
1903   }                                           << 
1904 #ifdef G4SPECSDEBUG                           << 
1905   if (dist < kInfinity)                       << 
1906   {                                           << 
1907     if (Inside(p + dist*v) != kSurface)       << 
1908     {                                            958     {
1909       std::ostringstream message;             << 959       size_t i = (*f)->GetVertexIndex(j);
1910       message << "Invalid response from facet << 960       if (i == 999999999) v[j] = 0;
1911               << G4endl                       << 961       else                v[j] = i+1;
1912               << "at point: " << p <<  "and d << 962     }
1913       G4Exception("G4TessellatedSolid::Distan << 963     if ((*f)->GetEntityType() == "G4RectangularFacet")
1914                   "GeomSolids1002", JustWarni << 964     {
                                                   >> 965       size_t i = v[3];
                                                   >> 966       v[3]     = v[2];
                                                   >> 967       v[2]     = i;
1915     }                                            968     }
                                                   >> 969     polyhedron->AddFacet(v[0],v[1],v[2],v[3]);
1916   }                                              970   }
1917 #endif                                        << 971   polyhedron->SetReferences();  
1918   return dist;                                << 972  
                                                   >> 973   return (G4Polyhedron*) polyhedron;
1919 }                                                974 }
1920                                                  975 
1921 /////////////////////////////////////////////    976 ///////////////////////////////////////////////////////////////////////////////
1922 //                                               977 //
1923 void G4TessellatedSolid::DescribeYourselfTo ( << 978 G4NURBS *G4TessellatedSolid::CreateNURBS () const
1924 {                                                979 {
1925   scene.AddSolid (*this);                     << 980   return 0;
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 }                                                981 }
1956                                                  982 
1957 /////////////////////////////////////////////    983 ///////////////////////////////////////////////////////////////////////////////
1958 //                                               984 //
1959 // GetPolyhedron                                 985 // GetPolyhedron
1960 //                                               986 //
1961 G4Polyhedron* G4TessellatedSolid::GetPolyhedr << 987 G4Polyhedron* G4TessellatedSolid::GetPolyhedron () const
1962 {                                                988 {
1963   if (fpPolyhedron == nullptr ||              << 989   if (!fpPolyhedron ||
1964       fRebuildPolyhedron ||                   << 
1965       fpPolyhedron->GetNumberOfRotationStepsA    990       fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
1966       fpPolyhedron->GetNumberOfRotationSteps(    991       fpPolyhedron->GetNumberOfRotationSteps())
1967   {                                           << 992     {
1968     G4AutoLock l(&polyhedronMutex);           << 993       delete fpPolyhedron;
1969     delete fpPolyhedron;                      << 994       fpPolyhedron = CreatePolyhedron();
1970     fpPolyhedron = CreatePolyhedron();        << 995     }
1971     fRebuildPolyhedron = false;               << 
1972     l.unlock();                               << 
1973   }                                           << 
1974   return fpPolyhedron;                           996   return fpPolyhedron;
1975 }                                                997 }
1976                                                  998 
1977 /////////////////////////////////////////////    999 ///////////////////////////////////////////////////////////////////////////////
1978 //                                               1000 //
1979 // Get bounding box                           << 1001 // CalculateExtent
1980 //                                               1002 //
1981 void G4TessellatedSolid::BoundingLimits(G4Thr << 1003 // Based on correction provided by Stan Seibert, University of Texas.
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 //                                               1004 //
2006 G4bool                                           1005 G4bool
2007 G4TessellatedSolid::CalculateExtent(const EAx    1006 G4TessellatedSolid::CalculateExtent(const EAxis pAxis,
2008                                     const G4V    1007                                     const G4VoxelLimits& pVoxelLimit,
2009                                     const G4A    1008                                     const G4AffineTransform& pTransform,
2010                                           G4d    1009                                           G4double& pMin, G4double& pMax) const
2011 {                                                1010 {
2012   G4ThreeVector bmin, bmax;                   << 1011     G4ThreeVectorList transVertexList(vertexList);
2013                                                  1012 
2014   // Check bounding box (bbox)                << 1013     // Put solid into transformed frame
2015   //                                          << 1014     for (size_t i=0; i<vertexList.size(); i++)
2016   BoundingLimits(bmin,bmax);                  << 1015       { pTransform.ApplyPointTransform(transVertexList[i]); }
2017   G4BoundingEnvelope bbox(bmin,bmax);         << 
2018                                                  1016 
2019   // Use simple bounding-box to help in the c << 1017     // Find min and max extent in each dimension
2020   //                                          << 1018     G4ThreeVector minExtent(kInfinity, kInfinity, kInfinity);
2021   return bbox.CalculateExtent(pAxis,pVoxelLim << 1019     G4ThreeVector maxExtent(-kInfinity, -kInfinity, -kInfinity);
                                                   >> 1020     for (size_t i=0; i<transVertexList.size(); i++)
                                                   >> 1021     {
                                                   >> 1022       for (G4int axis=G4ThreeVector::X; axis < G4ThreeVector::SIZE; axis++)
                                                   >> 1023       {
                                                   >> 1024         G4double coordinate = transVertexList[i][axis];
                                                   >> 1025         if (coordinate < minExtent[axis])
                                                   >> 1026           { minExtent[axis] = coordinate; }
                                                   >> 1027         if (coordinate > maxExtent[axis])
                                                   >> 1028           { maxExtent[axis] = coordinate; }
                                                   >> 1029       }
                                                   >> 1030     }
2022                                                  1031 
2023 #if 0                                         << 1032     // Check for containment and clamp to voxel boundaries
2024   // Precise extent computation (disabled by  << 1033     for (G4int axis=G4ThreeVector::X; axis < G4ThreeVector::SIZE; axis++)
2025   //                                          << 1034     {
2026   if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVo << 1035       EAxis geomAxis = kXAxis; // G4 geom classes use different index type
2027   {                                           << 1036       switch(axis)
2028     return (pMin < pMax) ? true : false;      << 1037       {
2029   }                                           << 1038         case G4ThreeVector::X: geomAxis = kXAxis; break;
                                                   >> 1039         case G4ThreeVector::Y: geomAxis = kYAxis; break;
                                                   >> 1040         case G4ThreeVector::Z: geomAxis = kZAxis; break;
                                                   >> 1041       }
                                                   >> 1042       G4bool isLimited = pVoxelLimit.IsLimited(geomAxis);
                                                   >> 1043       G4double voxelMinExtent = pVoxelLimit.GetMinExtent(geomAxis);
                                                   >> 1044       G4double voxelMaxExtent = pVoxelLimit.GetMaxExtent(geomAxis);
2030                                                  1045 
2031   // The extent is calculated as cumulative e << 1046       if (isLimited)
2032   // formed by facets and the center of the b << 1047       {
2033   //                                          << 1048         if ( minExtent[axis] > voxelMaxExtent+kCarTolerance ||
2034   G4double eminlim = pVoxelLimit.GetMinExtent << 1049              maxExtent[axis] < voxelMinExtent-kCarTolerance    )
2035   G4double emaxlim = pVoxelLimit.GetMaxExtent << 1050         {
                                                   >> 1051           return false ;
                                                   >> 1052         }
                                                   >> 1053         else
                                                   >> 1054         {
                                                   >> 1055           if (minExtent[axis] < voxelMinExtent)
                                                   >> 1056           {
                                                   >> 1057             minExtent[axis] = voxelMinExtent ;
                                                   >> 1058           }
                                                   >> 1059           if (maxExtent[axis] > voxelMaxExtent)
                                                   >> 1060           {
                                                   >> 1061             maxExtent[axis] = voxelMaxExtent;
                                                   >> 1062           }
                                                   >> 1063         }
                                                   >> 1064       }
                                                   >> 1065     }
2036                                                  1066 
2037   G4ThreeVectorList base;                     << 1067     // Convert pAxis into G4ThreeVector index
2038   G4ThreeVectorList apex(1);                  << 1068     G4int vecAxis=0;
2039   std::vector<const G4ThreeVectorList *> pyra << 1069     switch(pAxis)
2040   pyramid[0] = &base;                         << 1070     {
2041   pyramid[1] = &apex;                         << 1071       case kXAxis: vecAxis = G4ThreeVector::X; break;
2042   apex[0] = (bmin+bmax)*0.5;                  << 1072       case kYAxis: vecAxis = G4ThreeVector::Y; break;
2043                                               << 1073       case kZAxis: vecAxis = G4ThreeVector::Z; break;
2044   // main loop along facets                   << 1074       default: break;
2045   pMin =  kInfinity;                          << 1075     } 
2046   pMax = -kInfinity;                          << 1076 
2047   for (G4int i=0; i<GetNumberOfFacets(); ++i) << 1077     pMin = minExtent[vecAxis] - kCarTolerance;
2048   {                                           << 1078     pMax = maxExtent[vecAxis] + kCarTolerance;
2049     G4VFacet* facet = GetFacet(i);            << 1079 
2050     if (std::abs((facet->GetSurfaceNormal()). << 1080     return true;
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 }                                                1081 }
2067                                                  1082 
2068 /////////////////////////////////////////////    1083 ///////////////////////////////////////////////////////////////////////////////
2069 //                                               1084 //
2070 G4double G4TessellatedSolid::GetMinXExtent ()    1085 G4double G4TessellatedSolid::GetMinXExtent () const
2071 {                                             << 1086   {return xMinExtent;}
2072   return fMinExtent.x();                      << 
2073 }                                             << 
2074                                                  1087 
2075 /////////////////////////////////////////////    1088 ///////////////////////////////////////////////////////////////////////////////
2076 //                                               1089 //
2077 G4double G4TessellatedSolid::GetMaxXExtent ()    1090 G4double G4TessellatedSolid::GetMaxXExtent () const
2078 {                                             << 1091   {return xMaxExtent;}
2079   return fMaxExtent.x();                      << 
2080 }                                             << 
2081                                                  1092 
2082 /////////////////////////////////////////////    1093 ///////////////////////////////////////////////////////////////////////////////
2083 //                                               1094 //
2084 G4double G4TessellatedSolid::GetMinYExtent ()    1095 G4double G4TessellatedSolid::GetMinYExtent () const
2085 {                                             << 1096   {return yMinExtent;}
2086   return fMinExtent.y();                      << 
2087 }                                             << 
2088                                                  1097 
2089 /////////////////////////////////////////////    1098 ///////////////////////////////////////////////////////////////////////////////
2090 //                                               1099 //
2091 G4double G4TessellatedSolid::GetMaxYExtent ()    1100 G4double G4TessellatedSolid::GetMaxYExtent () const
2092 {                                             << 1101   {return yMaxExtent;}
2093   return fMaxExtent.y();                      << 
2094 }                                             << 
2095                                                  1102 
2096 /////////////////////////////////////////////    1103 ///////////////////////////////////////////////////////////////////////////////
2097 //                                               1104 //
2098 G4double G4TessellatedSolid::GetMinZExtent ()    1105 G4double G4TessellatedSolid::GetMinZExtent () const
2099 {                                             << 1106   {return zMinExtent;}
2100   return fMinExtent.z();                      << 
2101 }                                             << 
2102                                                  1107 
2103 /////////////////////////////////////////////    1108 ///////////////////////////////////////////////////////////////////////////////
2104 //                                               1109 //
2105 G4double G4TessellatedSolid::GetMaxZExtent ()    1110 G4double G4TessellatedSolid::GetMaxZExtent () const
2106 {                                             << 1111   {return zMaxExtent;}
2107   return fMaxExtent.z();                      << 
2108 }                                             << 
2109                                                  1112 
2110 /////////////////////////////////////////////    1113 ///////////////////////////////////////////////////////////////////////////////
2111 //                                               1114 //
2112 G4VisExtent G4TessellatedSolid::GetExtent ()     1115 G4VisExtent G4TessellatedSolid::GetExtent () const
2113 {                                                1116 {
2114   return { fMinExtent.x(), fMaxExtent.x(),    << 1117   return G4VisExtent (xMinExtent, xMaxExtent, yMinExtent, yMaxExtent,
2115            fMinExtent.y(), fMaxExtent.y(),    << 1118     zMinExtent, zMaxExtent);
2116            fMinExtent.z(), fMaxExtent.z() };  << 
2117 }                                                1119 }
2118                                                  1120 
2119 /////////////////////////////////////////////    1121 ///////////////////////////////////////////////////////////////////////////////
2120 //                                               1122 //
2121 G4double G4TessellatedSolid::GetCubicVolume (    1123 G4double G4TessellatedSolid::GetCubicVolume ()
2122 {                                                1124 {
2123   if (fCubicVolume != 0.) return fCubicVolume << 1125   if(cubicVolume != 0.) {;}
2124                                               << 1126   else   { cubicVolume = G4VSolid::GetCubicVolume(); }
2125   // For explanation of the following algorit << 1127   return cubicVolume;
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 }                                                1128 }
2140                                                  1129 
2141 /////////////////////////////////////////////    1130 ///////////////////////////////////////////////////////////////////////////////
2142 //                                               1131 //
2143 G4double G4TessellatedSolid::GetSurfaceArea (    1132 G4double G4TessellatedSolid::GetSurfaceArea ()
2144 {                                                1133 {
2145   if (fSurfaceArea != 0.) return fSurfaceArea << 1134   if(surfaceArea != 0.) { return surfaceArea; }
2146                                                  1135 
2147   std::size_t size = fFacets.size();          << 1136   for (FacetI f=facets.begin(); f!=facets.end(); f++)
2148   for (std::size_t i = 0; i < size; ++i)      << 
2149   {                                              1137   {
2150     G4VFacet &facet = *fFacets[i];            << 1138     surfaceArea += (*f)->GetArea();
2151     fSurfaceArea += facet.GetArea();          << 
2152   }                                              1139   }
2153   return fSurfaceArea;                        << 1140   return surfaceArea;
2154 }                                                1141 }
2155                                                  1142 
2156 /////////////////////////////////////////////    1143 ///////////////////////////////////////////////////////////////////////////////
2157 //                                               1144 //
2158 G4ThreeVector G4TessellatedSolid::GetPointOnS    1145 G4ThreeVector G4TessellatedSolid::GetPointOnSurface() const
2159 {                                                1146 {
2160   // Select randomly a facet and return a ran    1147   // Select randomly a facet and return a random point on it
2161                                                  1148 
2162   auto i = (G4int) G4RandFlat::shoot(0., fFac << 1149   G4int i = G4RandFlat::shootInt(facets.size());
2163   return fFacets[i]->GetPointOnFace();        << 1150   return facets[i]->GetPointOnFace();
2164 }                                                1151 }
2165                                               << 
2166 /////////////////////////////////////////////    1152 ///////////////////////////////////////////////////////////////////////////////
2167 //                                               1153 //
2168 // SetRandomVectorSet                            1154 // SetRandomVectorSet
2169 //                                               1155 //
2170 // This is a set of predefined random vectors    1156 // This is a set of predefined random vectors (if that isn't a contradition
2171 // in terms!) used to generate rays from a us    1157 // in terms!) used to generate rays from a user-defined point.  The member
2172 // function Inside uses these to determine wh    1158 // function Inside uses these to determine whether the point is inside or
2173 // outside of the tessellated solid.  All vec    1159 // outside of the tessellated solid.  All vectors should be unit vectors.
2174 //                                               1160 //
2175 void G4TessellatedSolid::SetRandomVectors ()  << 1161 void G4TessellatedSolid::SetRandomVectorSet()
2176 {                                                1162 {
2177   fRandir.resize(20);                         << 1163   randir[0]  = G4ThreeVector(-0.9577428892113370, 0.2732676269591740, 0.0897405271949221);
2178   fRandir[0]  =                               << 1164   randir[1]  = G4ThreeVector(-0.8331264504940770,-0.5162067214954600,-0.1985722492445700);
2179     G4ThreeVector(-0.9577428892113370, 0.2732 << 1165   randir[2]  = G4ThreeVector(-0.1516671651108820, 0.9666292616127460, 0.2064580868390110);
2180   fRandir[1]  =                               << 1166   randir[3]  = G4ThreeVector( 0.6570250350323190,-0.6944539025883300, 0.2933460081893360);
2181     G4ThreeVector(-0.8331264504940770,-0.5162 << 1167   randir[4]  = G4ThreeVector(-0.4820456281280320,-0.6331060000098690,-0.6056474264406270);
2182   fRandir[2]  =                               << 1168   randir[5]  = G4ThreeVector( 0.7629032554236800, 0.1016854697539910,-0.6384658864065180);
2183     G4ThreeVector(-0.1516671651108820, 0.9666 << 1169   randir[6]  = G4ThreeVector( 0.7689540409061150, 0.5034929891988220, 0.3939600142169160);
2184   fRandir[3]  =                               << 1170   randir[7]  = G4ThreeVector( 0.5765188359255740, 0.5997271636278330,-0.5549354566343150);
2185     G4ThreeVector( 0.6570250350323190,-0.6944 << 1171   randir[8]  = G4ThreeVector( 0.6660632777862070,-0.6362809868288380, 0.3892379937580790);
2186   fRandir[4]  =                               << 1172   randir[9]  = G4ThreeVector( 0.3824415020414780, 0.6541792713761380,-0.6525243125110690);
2187     G4ThreeVector(-0.4820456281280320,-0.6331 << 1173   randir[10] = G4ThreeVector(-0.5107726564526760, 0.6020905056811610, 0.6136760679616570);
2188   fRandir[5]  =                               << 1174   randir[11] = G4ThreeVector( 0.7459135439578050, 0.6618796061649330, 0.0743530220183488);
2189     G4ThreeVector( 0.7629032554236800 , 0.101 << 1175   randir[12] = G4ThreeVector( 0.1536405855311580, 0.8117477913978260,-0.5634359711967240);
2190   fRandir[6]  =                               << 1176   randir[13] = G4ThreeVector( 0.0744395301705579,-0.8707110101772920,-0.4861286795736560);
2191     G4ThreeVector( 0.7689540409061150, 0.5034 << 1177   randir[14] = G4ThreeVector(-0.1665874645185400, 0.6018553940549240,-0.7810369397872780);
2192   fRandir[7]  =                               << 1178   randir[15] = G4ThreeVector( 0.7766902003633100, 0.6014617505959970,-0.1870724331097450);
2193     G4ThreeVector( 0.5765188359255740, 0.5997 << 1179   randir[16] = G4ThreeVector(-0.8710128685847430,-0.1434320216603030,-0.4698551243971010);
2194   fRandir[8]  =                               << 1180   randir[17] = G4ThreeVector( 0.8901082092766820,-0.4388411398893870, 0.1229871120030100);
2195     G4ThreeVector( 0.6660632777862070,-0.6362 << 1181   randir[18] = G4ThreeVector(-0.6430417431544370,-0.3295938228697690, 0.6912779675984150);
2196   fRandir[9]  =                               << 1182   randir[19] = G4ThreeVector( 0.6331124368380410, 0.6306211461665000, 0.4488714875425340);
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                                                  1183 
2256 #endif                                        << 1184   maxTries = 20;
                                                   >> 1185 }
2257                                                  1186