Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/solids/Boolean/src/G4MultiUnion.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/Boolean/src/G4MultiUnion.cc (Version 11.3.0) and /geometry/solids/Boolean/src/G4MultiUnion.cc (Version 10.6)


  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.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
 26 // Implementation of G4MultiUnion class            26 // Implementation of G4MultiUnion class
 27 //                                                 27 //
 28 // 19.10.12 M.Gayer - Original implementation      28 // 19.10.12 M.Gayer - Original implementation from USolids module
 29 // 06.04.17 G.Cosmo - Adapted implementation i     29 // 06.04.17 G.Cosmo - Adapted implementation in Geant4 for VecGeom migration
 30 // -------------------------------------------     30 // --------------------------------------------------------------------
 31                                                    31 
 32 #include <iostream>                                32 #include <iostream>
 33 #include <sstream>                                 33 #include <sstream>
 34                                                    34 
 35 #include "G4MultiUnion.hh"                         35 #include "G4MultiUnion.hh"
 36 #include "Randomize.hh"                            36 #include "Randomize.hh"
 37 #include "G4GeometryTolerance.hh"                  37 #include "G4GeometryTolerance.hh"
 38 #include "G4BoundingEnvelope.hh"                   38 #include "G4BoundingEnvelope.hh"
 39 #include "G4AffineTransform.hh"                    39 #include "G4AffineTransform.hh"
 40 #include "G4DisplacedSolid.hh"                     40 #include "G4DisplacedSolid.hh"
 41                                                    41 
 42 #include "G4VGraphicsScene.hh"                     42 #include "G4VGraphicsScene.hh"
 43 #include "G4Polyhedron.hh"                         43 #include "G4Polyhedron.hh"
 44 #include "G4PolyhedronArbitrary.hh"            << 
 45 #include "HepPolyhedronProcessor.h"                44 #include "HepPolyhedronProcessor.h"
 46                                                    45 
 47 #include "G4BooleanSolid.hh"                   << 
 48                                                << 
 49 #include "G4AutoLock.hh"                           46 #include "G4AutoLock.hh"
 50                                                    47 
 51 namespace                                          48 namespace
 52 {                                                  49 {
 53   G4Mutex polyhedronMutex = G4MUTEX_INITIALIZE     50   G4Mutex polyhedronMutex = G4MUTEX_INITIALIZER;
 54 }                                                  51 }
 55                                                    52 
 56 //____________________________________________     53 //______________________________________________________________________________
 57 G4MultiUnion::G4MultiUnion(const G4String& nam     54 G4MultiUnion::G4MultiUnion(const G4String& name)
 58   : G4VSolid(name)                                 55   : G4VSolid(name)
 59 {                                                  56 {
 60   SetName(name);                                   57   SetName(name);
 61   fSolids.clear();                                 58   fSolids.clear();
 62   fTransformObjs.clear();                          59   fTransformObjs.clear();
 63   kRadTolerance = G4GeometryTolerance::GetInst     60   kRadTolerance = G4GeometryTolerance::GetInstance()->GetRadialTolerance();
 64 }                                                  61 }
 65                                                    62 
 66 //____________________________________________     63 //______________________________________________________________________________
 67 G4MultiUnion::~G4MultiUnion()                      64 G4MultiUnion::~G4MultiUnion()
 68 = default;                                     << 
 69                                                << 
 70 //____________________________________________ << 
 71 void G4MultiUnion::AddNode(G4VSolid& solid, co << 
 72 {                                                  65 {
 73   fSolids.push_back(&solid);                   << 
 74   fTransformObjs.push_back(trans);  // Store a << 
 75 }                                                  66 }
 76                                                    67 
 77 //____________________________________________     68 //______________________________________________________________________________
 78 void G4MultiUnion::AddNode(G4VSolid* solid, co <<  69 void G4MultiUnion::AddNode(G4VSolid& solid, G4Transform3D& trans)
 79 {                                                  70 {
 80   fSolids.push_back(solid);                    <<  71   fSolids.push_back(&solid);
 81   fTransformObjs.push_back(trans);  // Store a     72   fTransformObjs.push_back(trans);  // Store a local copy of transformations
 82 }                                                  73 }
 83                                                    74 
 84 //____________________________________________     75 //______________________________________________________________________________
 85 G4VSolid* G4MultiUnion::Clone() const              76 G4VSolid* G4MultiUnion::Clone() const
 86 {                                                  77 {
 87   return new G4MultiUnion(*this);                  78   return new G4MultiUnion(*this);
 88 }                                                  79 }
 89                                                    80 
 90 // Copy constructor                                81 // Copy constructor
 91 //____________________________________________     82 //______________________________________________________________________________
 92 G4MultiUnion::G4MultiUnion(const G4MultiUnion&     83 G4MultiUnion::G4MultiUnion(const G4MultiUnion& rhs)
 93   : G4VSolid(rhs), fCubicVolume(rhs.fCubicVolu     84   : G4VSolid(rhs), fCubicVolume(rhs.fCubicVolume),
 94     fSurfaceArea(rhs.fSurfaceArea),                85     fSurfaceArea(rhs.fSurfaceArea),
 95     kRadTolerance(rhs.kRadTolerance), fAccurat     86     kRadTolerance(rhs.kRadTolerance), fAccurate(rhs.fAccurate)
 96 {                                                  87 {
 97 }                                                  88 }
 98                                                    89 
 99 // Fake default constructor for persistency        90 // Fake default constructor for persistency
100 //____________________________________________     91 //______________________________________________________________________________
101 G4MultiUnion::G4MultiUnion( __void__& a )          92 G4MultiUnion::G4MultiUnion( __void__& a )
102   : G4VSolid(a)                                    93   : G4VSolid(a)
103 {                                                  94 {
104 }                                                  95 }
105                                                    96 
106 // Assignment operator                             97 // Assignment operator
107 //____________________________________________     98 //______________________________________________________________________________
108 G4MultiUnion& G4MultiUnion::operator = (const      99 G4MultiUnion& G4MultiUnion::operator = (const G4MultiUnion& rhs)
109 {                                                 100 {
110   // Check assignment to self                     101   // Check assignment to self
111   //                                              102   //
112   if (this == &rhs)                               103   if (this == &rhs)
113   {                                               104   {
114     return *this;                                 105     return *this;
115   }                                               106   }
116                                                   107 
117   // Copy base class data                         108   // Copy base class data
118   //                                              109   //
119   G4VSolid::operator=(rhs);                       110   G4VSolid::operator=(rhs);
120                                                   111 
121   return *this;                                   112   return *this;
122 }                                                 113 }
123                                                   114 
124 //____________________________________________    115 //______________________________________________________________________________
125 G4double G4MultiUnion::GetCubicVolume()           116 G4double G4MultiUnion::GetCubicVolume()
126 {                                                 117 {
127   if (fCubicVolume == 0.0)                     << 118   // Computes the cubic volume of the "G4MultiUnion" structure using
                                                   >> 119   // random points
                                                   >> 120 
                                                   >> 121   if (!fCubicVolume)
128   {                                               122   {
129     fCubicVolume = EstimateCubicVolume(1000000 << 123     G4ThreeVector extentMin, extentMax, d, p, point;
                                                   >> 124     G4int inside = 0, generated;
                                                   >> 125     BoundingLimits(extentMin, extentMax);
                                                   >> 126     d = (extentMax - extentMin) / 2.;
                                                   >> 127     p = (extentMax + extentMin) / 2.;
                                                   >> 128     G4ThreeVector left = p - d;
                                                   >> 129     G4ThreeVector length = d * 2;
                                                   >> 130     for (generated = 0; generated < 10000; ++generated)
                                                   >> 131     {
                                                   >> 132       G4ThreeVector rvec(G4UniformRand(), G4UniformRand(), G4UniformRand());
                                                   >> 133       point = left + G4ThreeVector(length.x()*rvec.x(),
                                                   >> 134                                    length.y()*rvec.y(),
                                                   >> 135                                    length.z()*rvec.z());
                                                   >> 136       if (Inside(point) != EInside::kOutside) ++inside;
                                                   >> 137     }
                                                   >> 138     G4double vbox = (2 * d.x()) * (2 * d.y()) * (2 * d.z());
                                                   >> 139     fCubicVolume = inside * vbox / generated;
130   }                                               140   }
131   return fCubicVolume;                            141   return fCubicVolume;
132 }                                                 142 }
133                                                   143 
134 //____________________________________________    144 //______________________________________________________________________________
135 G4double                                          145 G4double
136 G4MultiUnion::DistanceToInNoVoxels(const G4Thr    146 G4MultiUnion::DistanceToInNoVoxels(const G4ThreeVector& aPoint,
137                                    const G4Thr    147                                    const G4ThreeVector& aDirection) const
138 {                                                 148 {
139   G4ThreeVector direction = aDirection.unit();    149   G4ThreeVector direction = aDirection.unit();
140   G4ThreeVector localPoint, localDirection;       150   G4ThreeVector localPoint, localDirection;
141   G4double minDistance = kInfinity;               151   G4double minDistance = kInfinity;
142                                                   152 
143   std::size_t numNodes = fSolids.size();       << 153   G4int numNodes = fSolids.size();
144   for (std::size_t i = 0 ; i < numNodes ; ++i) << 154   for (G4int i = 0 ; i < numNodes ; ++i)
145   {                                               155   {
146     G4VSolid& solid = *fSolids[i];                156     G4VSolid& solid = *fSolids[i];
147     const G4Transform3D& transform = fTransfor    157     const G4Transform3D& transform = fTransformObjs[i];
148                                                   158 
149     localPoint = GetLocalPoint(transform, aPoi    159     localPoint = GetLocalPoint(transform, aPoint);
150     localDirection = GetLocalVector(transform,    160     localDirection = GetLocalVector(transform, direction);
151                                                   161 
152     G4double distance = solid.DistanceToIn(loc    162     G4double distance = solid.DistanceToIn(localPoint, localDirection);
153     if (minDistance > distance) minDistance =     163     if (minDistance > distance) minDistance = distance;
154   }                                               164   }
155   return minDistance;                             165   return minDistance;
156 }                                                 166 }
157                                                   167 
158 //____________________________________________    168 //______________________________________________________________________________
159 G4double G4MultiUnion::DistanceToInCandidates(    169 G4double G4MultiUnion::DistanceToInCandidates(const G4ThreeVector& aPoint,
160                                                   170                                               const G4ThreeVector& direction,
161                                                   171                                               std::vector<G4int>& candidates,
162                                                   172                                               G4SurfBits& bits) const
163 {                                                 173 {
164   std::size_t candidatesCount = candidates.siz << 174   G4int candidatesCount = candidates.size();
165   G4ThreeVector localPoint, localDirection;       175   G4ThreeVector localPoint, localDirection;
166                                                   176 
167   G4double minDistance = kInfinity;               177   G4double minDistance = kInfinity;
168   for (std::size_t i = 0 ; i < candidatesCount << 178   for (G4int i = 0 ; i < candidatesCount; ++i)
169   {                                               179   {
170     G4int candidate = candidates[i];              180     G4int candidate = candidates[i];
171     G4VSolid& solid = *fSolids[candidate];        181     G4VSolid& solid = *fSolids[candidate];
172     const G4Transform3D& transform = fTransfor    182     const G4Transform3D& transform = fTransformObjs[candidate];
173                                                   183 
174     localPoint = GetLocalPoint(transform, aPoi    184     localPoint = GetLocalPoint(transform, aPoint);
175     localDirection = GetLocalVector(transform,    185     localDirection = GetLocalVector(transform, direction);
176     G4double distance = solid.DistanceToIn(loc    186     G4double distance = solid.DistanceToIn(localPoint, localDirection);
177     if (minDistance > distance) minDistance =     187     if (minDistance > distance) minDistance = distance;
178     bits.SetBitNumber(candidate);                 188     bits.SetBitNumber(candidate);
179     if (minDistance == 0) break;                  189     if (minDistance == 0) break;
180   }                                               190   }
181   return minDistance;                             191   return minDistance;
182 }                                                 192 }
183                                                   193 
184 // Algorithm note: we have to look also for al    194 // Algorithm note: we have to look also for all other objects in next voxels,
185 // if the distance is not shorter ... we have     195 // if the distance is not shorter ... we have to do it because,
186 // for example for objects which starts in fir    196 // for example for objects which starts in first voxel in which they
187 // do not collide with direction line, but in     197 // do not collide with direction line, but in second it collides...
188 // The idea of crossing voxels would be still     198 // The idea of crossing voxels would be still applicable,
189 // because this way we could exclude from the     199 // because this way we could exclude from the testing such solids,
190 // which were found that obviously are not goo    200 // which were found that obviously are not good candidates, because
191 // they would return infinity                     201 // they would return infinity
192 // But if distance is smaller than the shift t    202 // But if distance is smaller than the shift to next voxel, we can return
193 // it immediately                                 203 // it immediately
194 //____________________________________________    204 //______________________________________________________________________________
195 G4double G4MultiUnion::DistanceToIn(const G4Th    205 G4double G4MultiUnion::DistanceToIn(const G4ThreeVector& aPoint,
196                                     const G4Th    206                                     const G4ThreeVector& aDirection) const
197 {                                                 207 {
198   G4double minDistance = kInfinity;               208   G4double minDistance = kInfinity;
199   G4ThreeVector direction = aDirection.unit();    209   G4ThreeVector direction = aDirection.unit();
200   G4double shift = fVoxels.DistanceToFirst(aPo    210   G4double shift = fVoxels.DistanceToFirst(aPoint, direction);
201   if (shift == kInfinity) return shift;           211   if (shift == kInfinity) return shift;
202                                                   212 
203   G4ThreeVector currentPoint = aPoint;            213   G4ThreeVector currentPoint = aPoint;
204   if (shift != 0.0) currentPoint += direction  << 214   if (shift) currentPoint += direction * shift;
205                                                   215 
206   G4SurfBits exclusion(fVoxels.GetBitsPerSlice    216   G4SurfBits exclusion(fVoxels.GetBitsPerSlice());
207   std::vector<G4int> candidates, curVoxel(3);     217   std::vector<G4int> candidates, curVoxel(3);
208   fVoxels.GetVoxel(curVoxel, currentPoint);       218   fVoxels.GetVoxel(curVoxel, currentPoint);
209                                                   219 
210   do                                              220   do
211   {                                               221   {
212     {                                             222     {
213       if (fVoxels.GetCandidatesVoxelArray(curV << 223       if (fVoxels.GetCandidatesVoxelArray(curVoxel, candidates, &exclusion))
214       {                                           224       {
215         G4double distance = DistanceToInCandid    225         G4double distance = DistanceToInCandidates(aPoint, direction,
216                                                   226                                                    candidates, exclusion);
217         if (minDistance > distance) minDistanc    227         if (minDistance > distance) minDistance = distance;
218         if (distance < shift) break;              228         if (distance < shift) break;
219       }                                           229       }
220     }                                             230     }
221     shift = fVoxels.DistanceToNext(aPoint, dir    231     shift = fVoxels.DistanceToNext(aPoint, direction, curVoxel);
222   }                                               232   }
223   while (minDistance > shift);                    233   while (minDistance > shift);
224                                                   234  
225   return minDistance;                             235   return minDistance;
226 }                                                 236 }
227                                                   237 
228 //____________________________________________    238 //______________________________________________________________________________
229 G4double G4MultiUnion::DistanceToOutNoVoxels(c    239 G4double G4MultiUnion::DistanceToOutNoVoxels(const G4ThreeVector& aPoint,
230                                              c    240                                              const G4ThreeVector& aDirection,
231                                              G    241                                              G4ThreeVector* aNormal) const
232 {                                                 242 {
233   // Computes distance from a point presumably    243   // Computes distance from a point presumably outside the solid to the solid
234   // surface. Ignores first surface if the poi    244   // surface. Ignores first surface if the point is actually inside.
235   // Early return infinity in case the safety     245   // Early return infinity in case the safety to any surface is found greater
236   // than the proposed step aPstep.               246   // than the proposed step aPstep.
237   // The normal vector to the crossed surface     247   // The normal vector to the crossed surface is filled only in case the box
238   // is crossed, otherwise aNormal->IsNull() i    248   // is crossed, otherwise aNormal->IsNull() is true.
239                                                   249 
240   // algorithm:                                   250   // algorithm:
241   G4ThreeVector direction = aDirection.unit();    251   G4ThreeVector direction = aDirection.unit();
242   G4ThreeVector localPoint, localDirection;       252   G4ThreeVector localPoint, localDirection;
243   G4int ignoredSolid = -1;                        253   G4int ignoredSolid = -1;
244   G4double resultDistToOut = 0;                   254   G4double resultDistToOut = 0;
245   G4ThreeVector currentPoint = aPoint;            255   G4ThreeVector currentPoint = aPoint;
246                                                   256 
247   auto numNodes = (G4int)fSolids.size();       << 257   G4int numNodes = fSolids.size();
248   for (auto i = 0; i < numNodes; ++i)          << 258   for (G4int i = 0; i < numNodes; ++i)
249   {                                               259   {
250     if (i != ignoredSolid)                        260     if (i != ignoredSolid)
251     {                                             261     {
252       G4VSolid& solid = *fSolids[i];              262       G4VSolid& solid = *fSolids[i];
253       const G4Transform3D& transform = fTransf    263       const G4Transform3D& transform = fTransformObjs[i];
254       localPoint = GetLocalPoint(transform, cu    264       localPoint = GetLocalPoint(transform, currentPoint);
255       localDirection = GetLocalVector(transfor    265       localDirection = GetLocalVector(transform, direction);
256       EInside location = solid.Inside(localPoi    266       EInside location = solid.Inside(localPoint);
257       if (location != EInside::kOutside)          267       if (location != EInside::kOutside)
258       {                                           268       {
259         G4double distance = solid.DistanceToOu    269         G4double distance = solid.DistanceToOut(localPoint, localDirection,
260                                                << 270                                                 aNormal);
261         if (distance < kInfinity)                 271         if (distance < kInfinity)
262         {                                         272         {
263           if (resultDistToOut == kInfinity) re    273           if (resultDistToOut == kInfinity) resultDistToOut = 0;
264           if (distance > 0)                       274           if (distance > 0)
265           {                                       275           {
266             currentPoint = GetGlobalPoint(tran    276             currentPoint = GetGlobalPoint(transform, localPoint
267                                           + di    277                                           + distance*localDirection);
268             resultDistToOut += distance;          278             resultDistToOut += distance;
269             ignoredSolid = i; // skip the soli    279             ignoredSolid = i; // skip the solid which we have just left
270             i = -1; // force the loop to conti    280             i = -1; // force the loop to continue from 0
271           }                                       281           }
272         }                                         282         }
273       }                                           283       }
274     }                                             284     }
275   }                                               285   }
276   return resultDistToOut;                         286   return resultDistToOut;
277 }                                                 287 }
278                                                   288 
279 //____________________________________________    289 //______________________________________________________________________________
280 G4double G4MultiUnion::DistanceToOut(const G4T    290 G4double G4MultiUnion::DistanceToOut(const G4ThreeVector& aPoint,
281                                      const G4T    291                                      const G4ThreeVector& aDirection,
282                                      const G4b    292                                      const G4bool /* calcNorm */,
283                                      G4bool* /    293                                      G4bool* /* validNorm */,
284                                      G4ThreeVe    294                                      G4ThreeVector* aNormal) const
285 {                                                 295 {
286   return DistanceToOutVoxels(aPoint, aDirectio    296   return DistanceToOutVoxels(aPoint, aDirection, aNormal);
287 }                                                 297 }
288                                                   298 
289 //____________________________________________    299 //______________________________________________________________________________
290 G4double G4MultiUnion::DistanceToOutVoxels(con    300 G4double G4MultiUnion::DistanceToOutVoxels(const G4ThreeVector& aPoint,
291                                            con    301                                            const G4ThreeVector& aDirection,
292                                            G4T    302                                            G4ThreeVector* aNormal) const
293 {                                                 303 {
294   // Computes distance from a point presumably    304   // Computes distance from a point presumably inside the solid to the solid
295   // surface. Ignores first surface along each    305   // surface. Ignores first surface along each axis systematically (for points
296   // inside or outside. Early returns zero in     306   // inside or outside. Early returns zero in case the second surface is behind
297   // the starting point.                          307   // the starting point.
298   // o The proposed step is ignored.              308   // o The proposed step is ignored.
299   // o The normal vector to the crossed surfac    309   // o The normal vector to the crossed surface is always filled.
300                                                   310 
301   // In the case the considered point is locat    311   // In the case the considered point is located inside the G4MultiUnion
302   // structure, the treatments are as follows:    312   // structure, the treatments are as follows:
303   //      - investigation of the candidates fo    313   //      - investigation of the candidates for the passed point
304   //      - progressive moving of the point to    314   //      - progressive moving of the point towards the surface, along the
305   //        passed direction                      315   //        passed direction
306   //      - processing of the normal              316   //      - processing of the normal
307                                                   317 
308   G4ThreeVector direction = aDirection.unit();    318   G4ThreeVector direction = aDirection.unit();
309   std::vector<G4int> candidates;                  319   std::vector<G4int> candidates;
310   G4double distance = 0;                          320   G4double distance = 0;
311   std::size_t numNodes = 2*fSolids.size();     << 321   G4int numNodes = 2*fSolids.size();
312   std::size_t count=0;                         << 322   G4int count=0;
313                                                   323 
314   if (fVoxels.GetCandidatesVoxelArray(aPoint,  << 324   if (fVoxels.GetCandidatesVoxelArray(aPoint, candidates))
315   {                                               325   {
316     // For normal case for which we presume th    326     // For normal case for which we presume the point is inside
317     G4ThreeVector localPoint, localDirection,     327     G4ThreeVector localPoint, localDirection, localNormal;
318     G4ThreeVector currentPoint = aPoint;          328     G4ThreeVector currentPoint = aPoint;
319     G4SurfBits exclusion(fVoxels.GetBitsPerSli    329     G4SurfBits exclusion(fVoxels.GetBitsPerSlice());
320     G4bool notOutside;                            330     G4bool notOutside;
321     G4ThreeVector maxNormal;                      331     G4ThreeVector maxNormal;
322                                                   332 
323     do                                            333     do
324     {                                             334     {
325       notOutside = false;                         335       notOutside = false;
326                                                   336 
327       G4double maxDistance = -kInfinity;          337       G4double maxDistance = -kInfinity;
328       G4int maxCandidate = 0;                     338       G4int maxCandidate = 0;
329       G4ThreeVector maxLocalPoint;                339       G4ThreeVector maxLocalPoint;
330                                                   340 
331       std::size_t limit = candidates.size();   << 341       G4int limit = candidates.size();
332       for (std::size_t i = 0 ; i < limit ; ++i << 342       for (G4int i = 0 ; i < limit ; ++i)
333       {                                           343       {
334         G4int candidate = candidates[i];          344         G4int candidate = candidates[i];
335         // ignore the current component (that     345         // ignore the current component (that you just got out of) since
336         // numerically the propagated point wi    346         // numerically the propagated point will be on its surface
337                                                   347 
338         G4VSolid& solid = *fSolids[candidate];    348         G4VSolid& solid = *fSolids[candidate];
339         const G4Transform3D& transform = fTran    349         const G4Transform3D& transform = fTransformObjs[candidate];
340                                                   350 
341         // The coordinates of the point are mo    351         // The coordinates of the point are modified so as to fit the
342         // intrinsic solid local frame:           352         // intrinsic solid local frame:
343         localPoint = GetLocalPoint(transform,     353         localPoint = GetLocalPoint(transform, currentPoint);
344                                                   354 
345         // DistanceToOut at least for Trd some    355         // DistanceToOut at least for Trd sometimes return non-zero value
346         // even from points that are outside.     356         // even from points that are outside. Therefore, this condition
347         // must currently be here, otherwise i    357         // must currently be here, otherwise it would not work.
348         // But it means it would be slower.       358         // But it means it would be slower.
349                                                   359 
350         if (solid.Inside(localPoint) != EInsid    360         if (solid.Inside(localPoint) != EInside::kOutside)
351         {                                         361         {
352           notOutside = true;                      362           notOutside = true;
353                                                   363 
354           localDirection = GetLocalVector(tran    364           localDirection = GetLocalVector(transform, direction);
355                                                   365 
356           // propagate with solid.DistanceToOu    366           // propagate with solid.DistanceToOut
357           G4double shift = solid.DistanceToOut    367           G4double shift = solid.DistanceToOut(localPoint, localDirection,
358                                                << 368                                                false, 0, &localNormal);
359           if (maxDistance < shift)                369           if (maxDistance < shift)
360           {                                       370           {
361             maxDistance = shift;                  371             maxDistance = shift;
362             maxCandidate = candidate;             372             maxCandidate = candidate;
363             maxNormal = localNormal;              373             maxNormal = localNormal;
364           }                                       374           }
365         }                                         375         }
366       }                                           376       }
367                                                   377 
368       if (notOutside)                             378       if (notOutside)
369       {                                           379       {
370         const G4Transform3D& transform = fTran    380         const G4Transform3D& transform = fTransformObjs[maxCandidate];
371                                                   381 
372         // convert from local normal              382         // convert from local normal
373         if (aNormal != nullptr) *aNormal = Get << 383         if (aNormal) *aNormal = GetGlobalVector(transform, maxNormal);
374                                                   384 
375         distance += maxDistance;                  385         distance += maxDistance;
376         currentPoint += maxDistance * directio    386         currentPoint += maxDistance * direction;
377         if(maxDistance == 0.) ++count;            387         if(maxDistance == 0.) ++count;
378                                                   388 
379         // the current component will be ignor    389         // the current component will be ignored
380         exclusion.SetBitNumber(maxCandidate);     390         exclusion.SetBitNumber(maxCandidate);
381         EInside location = InsideWithExclusion    391         EInside location = InsideWithExclusion(currentPoint, &exclusion);
382                                                   392 
383         // perform a Inside                       393         // perform a Inside
384         // it should be excluded current solid    394         // it should be excluded current solid from checking
385         // we have to collect the maximum dist    395         // we have to collect the maximum distance from all given candidates.
386         // such "maximum" candidate should be     396         // such "maximum" candidate should be then used for finding next
387         // candidates                             397         // candidates
388         if (location == EInside::kOutside)        398         if (location == EInside::kOutside)
389         {                                         399         {
390           // else return cumulated distances t    400           // else return cumulated distances to outside of the traversed
391           // components                           401           // components
392           break;                                  402           break;
393         }                                         403         }
394         // if inside another component, redo 1    404         // if inside another component, redo 1 to 3 but add the next
395         // DistanceToOut on top of the previou    405         // DistanceToOut on top of the previous.
396                                                   406 
397         // and fill the candidates for the cor    407         // and fill the candidates for the corresponding voxel (just
398         // exiting current component along dir    408         // exiting current component along direction)
399         candidates.clear();                       409         candidates.clear();
400                                                   410 
401         fVoxels.GetCandidatesVoxelArray(curren    411         fVoxels.GetCandidatesVoxelArray(currentPoint, candidates, &exclusion);
402         exclusion.ResetBitNumber(maxCandidate)    412         exclusion.ResetBitNumber(maxCandidate);
403       }                                           413       }
404     }                                             414     }
405     while  ((notOutside) && (count < numNodes)    415     while  ((notOutside) && (count < numNodes));
406   }                                               416   }
407                                                   417 
408   return distance;                                418   return distance;
409 }                                                 419 }
410                                                   420 
411 //____________________________________________    421 //______________________________________________________________________________
412 EInside G4MultiUnion::InsideWithExclusion(cons    422 EInside G4MultiUnion::InsideWithExclusion(const G4ThreeVector& aPoint,
413                                           G4Su    423                                           G4SurfBits* exclusion) const
414 {                                                 424 {
415   // Classify point location with respect to s    425   // Classify point location with respect to solid:
416   //  o eInside       - inside the solid          426   //  o eInside       - inside the solid
417   //  o eSurface      - close to surface withi    427   //  o eSurface      - close to surface within tolerance
418   //  o eOutside      - outside the solid         428   //  o eOutside      - outside the solid
419                                                   429 
420   // Hitherto, it is considered that only para    430   // Hitherto, it is considered that only parallelepipedic nodes
421   // can be added to the container                431   // can be added to the container
422                                                   432 
423   // Implementation using voxelisation techniq    433   // Implementation using voxelisation techniques:
424   // -----------------------------------------    434   // ---------------------------------------------
425                                                   435 
426   G4ThreeVector localPoint;                       436   G4ThreeVector localPoint;
427   EInside location = EInside::kOutside;           437   EInside location = EInside::kOutside;
428                                                   438 
429   std::vector<G4int> candidates;                  439   std::vector<G4int> candidates;
430   std::vector<G4MultiUnionSurface> surfaces;      440   std::vector<G4MultiUnionSurface> surfaces;
431                                                   441 
432   // TODO: test if it works well and if so mea    442   // TODO: test if it works well and if so measure performance
433   // TODO: getPointIndex should not be used, i    443   // TODO: getPointIndex should not be used, instead GetVoxel + GetVoxelsIndex
434   //       should be used                         444   //       should be used
435   // TODO: than pass result to GetVoxel furthe    445   // TODO: than pass result to GetVoxel further to GetCandidatesVoxelArray
436   // TODO: eventually GetVoxel should be inlin    446   // TODO: eventually GetVoxel should be inlined here, early exit if any
437   //       binary search is -1                    447   //       binary search is -1
438                                                   448 
439   G4int limit = fVoxels.GetCandidatesVoxelArra    449   G4int limit = fVoxels.GetCandidatesVoxelArray(aPoint, candidates, exclusion);
440   for (G4int i = 0 ; i < limit ; ++i)             450   for (G4int i = 0 ; i < limit ; ++i)
441   {                                               451   {
442     G4int candidate = candidates[i];              452     G4int candidate = candidates[i];
443     G4VSolid& solid = *fSolids[candidate];        453     G4VSolid& solid = *fSolids[candidate];
444     const G4Transform3D& transform = fTransfor    454     const G4Transform3D& transform = fTransformObjs[candidate];
445                                                   455 
446     // The coordinates of the point are modifi    456     // The coordinates of the point are modified so as to fit the intrinsic
447     // solid local frame:                         457     // solid local frame:
448     localPoint = GetLocalPoint(transform, aPoi    458     localPoint = GetLocalPoint(transform, aPoint);
449     location = solid.Inside(localPoint);          459     location = solid.Inside(localPoint);
450     if (location == EInside::kInside) return E    460     if (location == EInside::kInside) return EInside::kInside;
451     else if (location == EInside::kSurface)       461     else if (location == EInside::kSurface)
452     {                                             462     {
453       G4MultiUnionSurface surface;                463       G4MultiUnionSurface surface;
454       surface.point = localPoint;                 464       surface.point = localPoint;
455       surface.solid = &solid;                     465       surface.solid = &solid;
456       surfaces.push_back(surface);                466       surfaces.push_back(surface);
457     }                                             467     }
458   }                                               468   }
459                                                   469 
460   ////////////////////////////////////////////    470   ///////////////////////////////////////////////////////////////////////////
461   // Important comment: When two solids touch     471   // Important comment: When two solids touch each other along a flat
462   // surface, the surface points will be consi    472   // surface, the surface points will be considered as kSurface, while points
463   // located around will correspond to kInside    473   // located around will correspond to kInside (cf. G4UnionSolid)
464                                                   474 
465   std::size_t size = surfaces.size();          << 475   G4int size = surfaces.size();
466                                                << 476   for (G4int i = 0; i < size - 1; ++i)
467   if (size == 0)                               << 
468   {                                            << 
469     return EInside::kOutside;                  << 
470   }                                            << 
471                                                << 
472   for (std::size_t i = 0; i < size - 1; ++i)   << 
473   {                                               477   {
474     G4MultiUnionSurface& left = surfaces[i];      478     G4MultiUnionSurface& left = surfaces[i];
475     for (std::size_t j = i + 1; j < size; ++j) << 479     for (G4int j = i + 1; j < size; ++j)
476     {                                             480     {
477       G4MultiUnionSurface& right = surfaces[j]    481       G4MultiUnionSurface& right = surfaces[j];
478       G4ThreeVector n, n2;                        482       G4ThreeVector n, n2;
479       n = left.solid->SurfaceNormal(left.point    483       n = left.solid->SurfaceNormal(left.point);
480       n2 = right.solid->SurfaceNormal(right.po    484       n2 = right.solid->SurfaceNormal(right.point);
481       if ((n +  n2).mag2() < 1000 * kRadTolera    485       if ((n +  n2).mag2() < 1000 * kRadTolerance)
482         return EInside::kInside;                  486         return EInside::kInside;
483     }                                             487     }
484   }                                               488   }
485                                                   489 
486   return EInside::kSurface;                    << 490   location = size ? EInside::kSurface : EInside::kOutside;
                                                   >> 491 
                                                   >> 492   return location;
487 }                                                 493 }
488                                                   494 
489 //____________________________________________    495 //______________________________________________________________________________
490 EInside G4MultiUnion::Inside(const G4ThreeVect    496 EInside G4MultiUnion::Inside(const G4ThreeVector& aPoint) const
491 {                                                 497 {
492   // Classify point location with respect to s    498   // Classify point location with respect to solid:
493   //  o eInside       - inside the solid          499   //  o eInside       - inside the solid
494   //  o eSurface      - close to surface withi    500   //  o eSurface      - close to surface within tolerance
495   //  o eOutside      - outside the solid         501   //  o eOutside      - outside the solid
496                                                   502 
497   // Hitherto, it is considered that only para    503   // Hitherto, it is considered that only parallelepipedic nodes can be
498   // added to the container                       504   // added to the container
499                                                   505 
500   // Implementation using voxelisation techniq    506   // Implementation using voxelisation techniques:
501   // -----------------------------------------    507   // ---------------------------------------------
502                                                   508 
503   //  return InsideIterator(aPoint);              509   //  return InsideIterator(aPoint);
504                                                   510 
505   EInside location = InsideWithExclusion(aPoin    511   EInside location = InsideWithExclusion(aPoint);
506   return location;                                512   return location;
507 }                                                 513 }
508                                                   514 
509 //____________________________________________    515 //______________________________________________________________________________
510 EInside G4MultiUnion::InsideNoVoxels(const G4T    516 EInside G4MultiUnion::InsideNoVoxels(const G4ThreeVector& aPoint) const
511 {                                                 517 {
512   G4ThreeVector localPoint;                       518   G4ThreeVector localPoint;
513   EInside location = EInside::kOutside;           519   EInside location = EInside::kOutside;
514   G4int countSurface = 0;                         520   G4int countSurface = 0;
515                                                   521 
516   auto numNodes = (G4int)fSolids.size();       << 522   G4int numNodes = fSolids.size();
517   for (auto i = 0 ; i < numNodes ; ++i)        << 523   for (G4int i = 0 ; i < numNodes ; ++i)
518   {                                               524   {
519     G4VSolid& solid = *fSolids[i];                525     G4VSolid& solid = *fSolids[i];
520     G4Transform3D transform = GetTransformatio    526     G4Transform3D transform = GetTransformation(i);
521                                                   527 
522     // The coordinates of the point are modifi    528     // The coordinates of the point are modified so as to fit the
523     // intrinsic solid local frame:               529     // intrinsic solid local frame:
524     localPoint = GetLocalPoint(transform, aPoi    530     localPoint = GetLocalPoint(transform, aPoint);
525                                                   531 
526     location = solid.Inside(localPoint);          532     location = solid.Inside(localPoint);
527                                                   533 
528     if (location == EInside::kSurface)            534     if (location == EInside::kSurface)
529       ++countSurface;                             535       ++countSurface;
530                                                   536 
531     if (location == EInside::kInside) return E    537     if (location == EInside::kInside) return EInside::kInside;
532   }                                               538   }
533   if (countSurface != 0) return EInside::kSurf    539   if (countSurface != 0) return EInside::kSurface;
534   return EInside::kOutside;                       540   return EInside::kOutside;
535 }                                                 541 }
536                                                   542 
537 //____________________________________________    543 //______________________________________________________________________________
538 void G4MultiUnion::Extent(EAxis aAxis, G4doubl    544 void G4MultiUnion::Extent(EAxis aAxis, G4double& aMin, G4double& aMax) const
539 {                                                 545 {
540   // Determines the bounding box for the consi    546   // Determines the bounding box for the considered instance of "UMultipleUnion"
541   G4ThreeVector min, max;                         547   G4ThreeVector min, max;
542                                                   548 
543   auto numNodes = (G4int)fSolids.size();       << 549   G4int numNodes = fSolids.size();
544   for (auto i = 0 ; i < numNodes ; ++i)        << 550   for (G4int i = 0 ; i < numNodes ; ++i)
545   {                                               551   {
546     G4VSolid& solid = *fSolids[i];                552     G4VSolid& solid = *fSolids[i];
547     G4Transform3D transform = GetTransformatio    553     G4Transform3D transform = GetTransformation(i);
548     solid.BoundingLimits(min, max);               554     solid.BoundingLimits(min, max);
549                                                   555    
550     TransformLimits(min, max, transform);         556     TransformLimits(min, max, transform);
551                                                   557     
552     if (i == 0)                                   558     if (i == 0)
553     {                                             559     {
554       switch (aAxis)                              560       switch (aAxis)
555       {                                           561       {
556         case kXAxis:                              562         case kXAxis:
557           aMin = min.x();                         563           aMin = min.x();
558           aMax = max.x();                         564           aMax = max.x();
559           break;                                  565           break;
560         case kYAxis:                              566         case kYAxis:
561           aMin = min.y();                         567           aMin = min.y();
562           aMax = max.y();                         568           aMax = max.y();
563           break;                                  569           break;
564         case kZAxis:                              570         case kZAxis:
565           aMin = min.z();                         571           aMin = min.z();
566           aMax = max.z();                         572           aMax = max.z();
567           break;                                  573           break;
568         default:                                  574         default:
569           break;                                  575           break;
570       }                                           576       }
571     }                                             577     }
572     else                                          578     else
573     {                                             579     {
574       // Determine the min/max on the consider    580       // Determine the min/max on the considered axis:
575       switch (aAxis)                              581       switch (aAxis)
576       {                                           582       {
577         case kXAxis:                              583         case kXAxis:
578           if (min.x() < aMin)                     584           if (min.x() < aMin)
579             aMin = min.x();                       585             aMin = min.x();
580           if (max.x() > aMax)                     586           if (max.x() > aMax)
581             aMax = max.x();                       587             aMax = max.x();
582           break;                                  588           break;
583         case kYAxis:                              589         case kYAxis:
584           if (min.y() < aMin)                     590           if (min.y() < aMin)
585             aMin = min.y();                       591             aMin = min.y();
586           if (max.y() > aMax)                     592           if (max.y() > aMax)
587             aMax = max.y();                       593             aMax = max.y();
588           break;                                  594           break;
589         case kZAxis:                              595         case kZAxis:
590           if (min.z() < aMin)                     596           if (min.z() < aMin)
591             aMin = min.z();                       597             aMin = min.z();
592           if (max.z() > aMax)                     598           if (max.z() > aMax)
593             aMax = max.z();                       599             aMax = max.z();
594           break;                                  600           break;
595         default:                                  601         default:
596           break;                                  602           break;
597       }                                           603       }
598     }                                             604     }
599   }                                               605   }
600 }                                                 606 }
601                                                   607 
602 //____________________________________________    608 //______________________________________________________________________________
603 void G4MultiUnion::BoundingLimits(G4ThreeVecto    609 void G4MultiUnion::BoundingLimits(G4ThreeVector& aMin,
604                                   G4ThreeVecto    610                                   G4ThreeVector& aMax) const
605 {                                                 611 {
606    Extent(kXAxis, aMin[0], aMax[0]);              612    Extent(kXAxis, aMin[0], aMax[0]);
607    Extent(kYAxis, aMin[1], aMax[1]);              613    Extent(kYAxis, aMin[1], aMax[1]);
608    Extent(kZAxis, aMin[2], aMax[2]);              614    Extent(kZAxis, aMin[2], aMax[2]);
609 }                                                 615 }
610                                                   616 
611 //____________________________________________    617 //______________________________________________________________________________
612 G4bool                                            618 G4bool
613 G4MultiUnion::CalculateExtent(const EAxis pAxi    619 G4MultiUnion::CalculateExtent(const EAxis pAxis,
614                               const G4VoxelLim    620                               const G4VoxelLimits& pVoxelLimit,
615                               const G4AffineTr    621                               const G4AffineTransform& pTransform,
616                                     G4double&     622                                     G4double& pMin, G4double& pMax) const
617 {                                                 623 {
618   G4ThreeVector bmin, bmax;                       624   G4ThreeVector bmin, bmax;
619                                                   625 
620   // Get bounding box                             626   // Get bounding box
621   BoundingLimits(bmin,bmax);                      627   BoundingLimits(bmin,bmax);
622                                                   628 
623   // Find extent                                  629   // Find extent
624   G4BoundingEnvelope bbox(bmin,bmax);             630   G4BoundingEnvelope bbox(bmin,bmax);
625   return bbox.CalculateExtent(pAxis,pVoxelLimi    631   return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
626 }                                                 632 }
627                                                   633 
628 //____________________________________________    634 //______________________________________________________________________________
629 G4ThreeVector G4MultiUnion::SurfaceNormal(cons    635 G4ThreeVector G4MultiUnion::SurfaceNormal(const G4ThreeVector& aPoint) const
630 {                                                 636 {
631   // Computes the localNormal on a surface and    637   // Computes the localNormal on a surface and returns it as a unit vector.
632   // Must return a valid vector. (even if the     638   // Must return a valid vector. (even if the point is not on the surface).
633   //                                              639   //
634   //   On an edge or corner, provide an averag    640   //   On an edge or corner, provide an average localNormal of all facets within
635   //   tolerance                                  641   //   tolerance
636   //   NOTE: the tolerance value used in here     642   //   NOTE: the tolerance value used in here is not yet the global surface
637   //         tolerance - we will have to revis    643   //         tolerance - we will have to revise this value - TODO
638                                                   644 
639   std::vector<G4int> candidates;                  645   std::vector<G4int> candidates;
640   G4ThreeVector localPoint, normal, localNorma    646   G4ThreeVector localPoint, normal, localNormal;
641   G4double safety = kInfinity;                    647   G4double safety = kInfinity;
642   G4int node = 0;                                 648   G4int node = 0;
643                                                   649 
644   ////////////////////////////////////////////    650   ///////////////////////////////////////////////////////////////////////////
645   // Important comment: Cases for which the po    651   // Important comment: Cases for which the point is located on an edge or
646   // on a vertice remain to be treated            652   // on a vertice remain to be treated
647                                                   653 
648   // determine weather we are in voxel area       654   // determine weather we are in voxel area
649   if (fVoxels.GetCandidatesVoxelArray(aPoint,  << 655   if (fVoxels.GetCandidatesVoxelArray(aPoint, candidates))
650   {                                               656   {
651     std::size_t limit = candidates.size();     << 657     G4int limit = candidates.size();
652     for (std::size_t i = 0 ; i < limit ; ++i)  << 658     for (G4int i = 0 ; i < limit ; ++i)
653     {                                             659     {
654       G4int candidate = candidates[i];            660       G4int candidate = candidates[i];
655       const G4Transform3D& transform = fTransf    661       const G4Transform3D& transform = fTransformObjs[candidate];
656                                                   662 
657       // The coordinates of the point are modi    663       // The coordinates of the point are modified so as to fit the intrinsic
658       // solid local frame:                       664       // solid local frame:
659       localPoint = GetLocalPoint(transform, aP    665       localPoint = GetLocalPoint(transform, aPoint);
660       G4VSolid& solid = *fSolids[candidate];      666       G4VSolid& solid = *fSolids[candidate];
661       EInside location = solid.Inside(localPoi    667       EInside location = solid.Inside(localPoint);
662                                                   668 
663       if (location == EInside::kSurface)          669       if (location == EInside::kSurface)
664       {                                           670       {
665         // normal case when point is on surfac    671         // normal case when point is on surface, we pick first solid
666         normal = GetGlobalVector(transform, so    672         normal = GetGlobalVector(transform, solid.SurfaceNormal(localPoint));
667         return normal.unit();                     673         return normal.unit();
668       }                                           674       }
669       else                                        675       else
670       {                                           676       {
671         // collect the smallest safety and rem    677         // collect the smallest safety and remember solid node
672         G4double s = (location == EInside::kIn    678         G4double s = (location == EInside::kInside)
673                    ? solid.DistanceToOut(local    679                    ? solid.DistanceToOut(localPoint)
674                    : solid.DistanceToIn(localP    680                    : solid.DistanceToIn(localPoint);
675         if (s < safety)                           681         if (s < safety)
676         {                                         682         {
677           safety = s;                             683           safety = s;
678           node = candidate;                       684           node = candidate;
679         }                                         685         }
680       }                                           686       }
681     }                                             687     }
682     // on none of the solids, the point was no    688     // on none of the solids, the point was not on the surface
683     G4VSolid& solid = *fSolids[node];             689     G4VSolid& solid = *fSolids[node];
684     const G4Transform3D& transform = fTransfor    690     const G4Transform3D& transform = fTransformObjs[node];
685     localPoint = GetLocalPoint(transform, aPoi    691     localPoint = GetLocalPoint(transform, aPoint);
686                                                   692 
687     normal = GetGlobalVector(transform, solid.    693     normal = GetGlobalVector(transform, solid.SurfaceNormal(localPoint));
688     return normal.unit();                         694     return normal.unit();
689   }                                               695   }
690   else                                            696   else
691   {                                               697   {
692     // for the case when point is certainly ou    698     // for the case when point is certainly outside:
693                                                   699 
694     // find a solid in union with the smallest    700     // find a solid in union with the smallest safety
695     node = SafetyFromOutsideNumberNode(aPoint,    701     node = SafetyFromOutsideNumberNode(aPoint, safety);
696     G4VSolid& solid = *fSolids[node];             702     G4VSolid& solid = *fSolids[node];
697                                                   703 
698     const G4Transform3D& transform = fTransfor    704     const G4Transform3D& transform = fTransformObjs[node];
699     localPoint = GetLocalPoint(transform, aPoi    705     localPoint = GetLocalPoint(transform, aPoint);
700                                                   706 
701     // evaluate normal for point at this found    707     // evaluate normal for point at this found solid
702     // and transform multi-union coordinates      708     // and transform multi-union coordinates
703     normal = GetGlobalVector(transform, solid.    709     normal = GetGlobalVector(transform, solid.SurfaceNormal(localPoint));
704                                                   710 
705     return normal.unit();                         711     return normal.unit();
706   }                                               712   }
707 }                                                 713 }
708                                                   714 
709 //____________________________________________    715 //______________________________________________________________________________
710 G4double G4MultiUnion::DistanceToOut(const G4T    716 G4double G4MultiUnion::DistanceToOut(const G4ThreeVector& point) const
711 {                                                 717 {
712   // Estimates isotropic distance to the surfa    718   // Estimates isotropic distance to the surface of the solid. This must
713   // be either accurate or an underestimate.      719   // be either accurate or an underestimate.
714   // Two modes: - default/fast mode, sacrifici    720   // Two modes: - default/fast mode, sacrificing accuracy for speed
715   //            - "precise" mode,  requests ac    721   //            - "precise" mode,  requests accurate value if available.
716                                                   722 
717   std::vector<G4int> candidates;                  723   std::vector<G4int> candidates;
718   G4ThreeVector localPoint;                       724   G4ThreeVector localPoint;
719   G4double safetyMin = kInfinity;                 725   G4double safetyMin = kInfinity;
720                                                   726 
721   // In general, the value return by DistanceT    727   // In general, the value return by DistanceToIn(p) will not be the exact
722   // but only an undervalue (cf. overlaps)        728   // but only an undervalue (cf. overlaps)
723   fVoxels.GetCandidatesVoxelArray(point, candi    729   fVoxels.GetCandidatesVoxelArray(point, candidates);
724                                                   730 
725   std::size_t limit = candidates.size();       << 731   G4int limit = candidates.size();
726   for (std::size_t i = 0; i < limit; ++i)      << 732   for (G4int i = 0; i < limit; ++i)
727   {                                               733   {
728     G4int candidate = candidates[i];              734     G4int candidate = candidates[i];
729                                                   735 
730     // The coordinates of the point are modifi    736     // The coordinates of the point are modified so as to fit the intrinsic
731     // solid local frame:                         737     // solid local frame:
732     const G4Transform3D& transform = fTransfor    738     const G4Transform3D& transform = fTransformObjs[candidate];
733     localPoint = GetLocalPoint(transform, poin    739     localPoint = GetLocalPoint(transform, point);
734     G4VSolid& solid = *fSolids[candidate];        740     G4VSolid& solid = *fSolids[candidate];
735     if (solid.Inside(localPoint) == EInside::k    741     if (solid.Inside(localPoint) == EInside::kInside)
736     {                                             742     {
737       G4double safety = solid.DistanceToOut(lo    743       G4double safety = solid.DistanceToOut(localPoint);
738       if (safetyMin > safety) safetyMin = safe    744       if (safetyMin > safety) safetyMin = safety;
739     }                                             745     }
740   }                                               746   }
741   if (safetyMin == kInfinity) safetyMin = 0; /    747   if (safetyMin == kInfinity) safetyMin = 0; // we are not inside
742                                                   748 
743   return safetyMin;                               749   return safetyMin;
744 }                                                 750 }
745                                                   751 
746 //____________________________________________    752 //______________________________________________________________________________
747 G4double G4MultiUnion::DistanceToIn(const G4Th    753 G4double G4MultiUnion::DistanceToIn(const G4ThreeVector& point) const
748 {                                                 754 {
749   // Estimates the isotropic safety from a poi    755   // Estimates the isotropic safety from a point outside the current solid to
750   // any of its surfaces. The algorithm may be    756   // any of its surfaces. The algorithm may be accurate or should provide a fast
751   // underestimate.                               757   // underestimate.
752                                                   758 
753   if (!fAccurate)  { return fVoxels.DistanceTo    759   if (!fAccurate)  { return fVoxels.DistanceToBoundingBox(point); }
754                                                   760 
755   const std::vector<G4VoxelBox>& boxes = fVoxe    761   const std::vector<G4VoxelBox>& boxes = fVoxels.GetBoxes();
756   G4double safetyMin = kInfinity;                 762   G4double safetyMin = kInfinity;
757   G4ThreeVector localPoint;                       763   G4ThreeVector localPoint;
758                                                   764 
759   std::size_t numNodes = fSolids.size();       << 765   G4int numNodes = fSolids.size();
760   for (std::size_t j = 0; j < numNodes; ++j)   << 766   for (G4int j = 0; j < numNodes; ++j)
761   {                                               767   {
762     G4ThreeVector dxyz;                           768     G4ThreeVector dxyz;
763     if (j > 0)                                    769     if (j > 0)
764     {                                             770     {
765       const G4ThreeVector& pos = boxes[j].pos;    771       const G4ThreeVector& pos = boxes[j].pos;
766       const G4ThreeVector& hlen = boxes[j].hle    772       const G4ThreeVector& hlen = boxes[j].hlen;
767       for (auto i = 0; i <= 2; ++i)               773       for (auto i = 0; i <= 2; ++i)
768         // distance to middle point - hlength     774         // distance to middle point - hlength => distance from point to border
769         // of x,y,z                               775         // of x,y,z
770         if ((dxyz[i] = std::abs(point[i] - pos    776         if ((dxyz[i] = std::abs(point[i] - pos[i]) - hlen[i]) > safetyMin)
771           continue;                               777           continue;
772                                                   778 
773       G4double d2xyz = 0.;                        779       G4double d2xyz = 0.;
774       for (auto i = 0; i <= 2; ++i)               780       for (auto i = 0; i <= 2; ++i)
775         if (dxyz[i] > 0) d2xyz += dxyz[i] * dx    781         if (dxyz[i] > 0) d2xyz += dxyz[i] * dxyz[i];
776                                                   782 
777       // minimal distance is at least this, bu    783       // minimal distance is at least this, but could be even higher. therefore,
778       // we can stop if previous was already l    784       // we can stop if previous was already lower, let us check if it does any
779       // chance to be better tha previous valu    785       // chance to be better tha previous values...
780       if (d2xyz >= safetyMin * safetyMin)         786       if (d2xyz >= safetyMin * safetyMin)
781       {                                           787       {
782         continue;                                 788         continue;
783       }                                           789       }
784     }                                             790     }
785     const G4Transform3D& transform = fTransfor    791     const G4Transform3D& transform = fTransformObjs[j];
786     localPoint = GetLocalPoint(transform, poin    792     localPoint = GetLocalPoint(transform, point);
787     G4VSolid& solid = *fSolids[j];                793     G4VSolid& solid = *fSolids[j];
788                                                   794 
789     G4double safety = solid.DistanceToIn(local    795     G4double safety = solid.DistanceToIn(localPoint);
790     if (safety <= 0) return safety;               796     if (safety <= 0) return safety;
791       // it was detected, that the point is no    797       // it was detected, that the point is not located outside
792     if (safetyMin > safety) safetyMin = safety    798     if (safetyMin > safety) safetyMin = safety;
793   }                                               799   }
794   return safetyMin;                               800   return safetyMin;
795 }                                                 801 }
796                                                   802 
797 //____________________________________________    803 //______________________________________________________________________________
798 G4double G4MultiUnion::GetSurfaceArea()           804 G4double G4MultiUnion::GetSurfaceArea()
799 {                                                 805 {
800   if (fSurfaceArea == 0.0)                     << 806   if (!fSurfaceArea)
801   {                                               807   {
802     fSurfaceArea = EstimateSurfaceArea(1000000    808     fSurfaceArea = EstimateSurfaceArea(1000000, 0.001);
803   }                                               809   }
804   return fSurfaceArea;                            810   return fSurfaceArea;
805 }                                                 811 }
806                                                   812 
807 //____________________________________________    813 //______________________________________________________________________________
808 G4int G4MultiUnion::GetNumOfConstituents() con << 
809 {                                              << 
810   G4int num = 0;                               << 
811   for (const auto solid : fSolids) { num += so << 
812   return num;                                  << 
813 }                                              << 
814                                                << 
815 //____________________________________________ << 
816 G4bool G4MultiUnion::IsFaceted() const         << 
817 {                                              << 
818   for (const auto solid : fSolids) { if (!soli << 
819   return true;                                 << 
820 }                                              << 
821                                                << 
822 //____________________________________________ << 
823 void G4MultiUnion::Voxelize()                     814 void G4MultiUnion::Voxelize()
824 {                                                 815 {
825   fVoxels.Voxelize(fSolids, fTransformObjs);      816   fVoxels.Voxelize(fSolids, fTransformObjs);
826 }                                                 817 }
827                                                   818 
828 //____________________________________________    819 //______________________________________________________________________________
829 G4int G4MultiUnion::SafetyFromOutsideNumberNod    820 G4int G4MultiUnion::SafetyFromOutsideNumberNode(const G4ThreeVector& aPoint,
830                                                   821                                                 G4double& safetyMin) const
831 {                                                 822 {
832   // Method returning the closest node from a     823   // Method returning the closest node from a point located outside a
833   // G4MultiUnion.                                824   // G4MultiUnion.
834   // This is used to compute the normal in the    825   // This is used to compute the normal in the case no candidate has been found.
835                                                   826 
836   const std::vector<G4VoxelBox>& boxes = fVoxe    827   const std::vector<G4VoxelBox>& boxes = fVoxels.GetBoxes();
837   safetyMin = kInfinity;                          828   safetyMin = kInfinity;
838   std::size_t safetyNode = 0;                  << 829   G4int safetyNode = 0;
839   G4ThreeVector localPoint;                       830   G4ThreeVector localPoint;
840                                                   831 
841   std::size_t numNodes = fSolids.size();       << 832   G4int numNodes = fSolids.size();
842   for (std::size_t i = 0; i < numNodes; ++i)   << 833   for (G4int i = 0; i < numNodes; ++i)
843   {                                               834   {
844     G4double d2xyz = 0.;                          835     G4double d2xyz = 0.;
845     G4double dxyz0 = std::abs(aPoint.x() - box    836     G4double dxyz0 = std::abs(aPoint.x() - boxes[i].pos.x()) - boxes[i].hlen.x();
846     if (dxyz0 > safetyMin) continue;              837     if (dxyz0 > safetyMin) continue;
847     G4double dxyz1 = std::abs(aPoint.y() - box    838     G4double dxyz1 = std::abs(aPoint.y() - boxes[i].pos.y()) - boxes[i].hlen.y();
848     if (dxyz1 > safetyMin) continue;              839     if (dxyz1 > safetyMin) continue;
849     G4double dxyz2 = std::abs(aPoint.z() - box    840     G4double dxyz2 = std::abs(aPoint.z() - boxes[i].pos.z()) - boxes[i].hlen.z();
850     if (dxyz2 > safetyMin) continue;              841     if (dxyz2 > safetyMin) continue;
851                                                   842 
852     if (dxyz0 > 0) d2xyz += dxyz0 * dxyz0;        843     if (dxyz0 > 0) d2xyz += dxyz0 * dxyz0;
853     if (dxyz1 > 0) d2xyz += dxyz1 * dxyz1;        844     if (dxyz1 > 0) d2xyz += dxyz1 * dxyz1;
854     if (dxyz2 > 0) d2xyz += dxyz2 * dxyz2;        845     if (dxyz2 > 0) d2xyz += dxyz2 * dxyz2;
855     if (d2xyz >= safetyMin * safetyMin) contin    846     if (d2xyz >= safetyMin * safetyMin) continue;
856                                                   847 
857     G4VSolid& solid = *fSolids[i];                848     G4VSolid& solid = *fSolids[i];
858     const G4Transform3D& transform = fTransfor    849     const G4Transform3D& transform = fTransformObjs[i];
859     localPoint = GetLocalPoint(transform, aPoi    850     localPoint = GetLocalPoint(transform, aPoint);
860     fAccurate = true;                             851     fAccurate = true;
861     G4double safety = solid.DistanceToIn(local    852     G4double safety = solid.DistanceToIn(localPoint);
862     fAccurate = false;                            853     fAccurate = false;
863     if (safetyMin > safety)                       854     if (safetyMin > safety)
864     {                                             855     {
865       safetyMin = safety;                         856       safetyMin = safety;
866       safetyNode = i;                             857       safetyNode = i;
867     }                                             858     }
868   }                                               859   }
869   return (G4int)safetyNode;                    << 860   return safetyNode;
870 }                                                 861 }
871                                                   862 
872 //____________________________________________    863 //______________________________________________________________________________
873 void G4MultiUnion::TransformLimits(G4ThreeVect    864 void G4MultiUnion::TransformLimits(G4ThreeVector& min, G4ThreeVector& max,
874                                    const G4Tra    865                                    const G4Transform3D& transformation) const
875 {                                                 866 {
876   // The goal of this method is to convert the    867   // The goal of this method is to convert the quantities min and max
877   // (representing the bounding box of a given    868   // (representing the bounding box of a given solid in its local frame)
878   // to the main frame, using "transformation"    869   // to the main frame, using "transformation"
879                                                   870 
880   G4ThreeVector vertices[8] =     // Deteminat    871   G4ThreeVector vertices[8] =     // Detemination of the vertices thanks to
881   {                               // the exten    872   {                               // the extension of each solid:
882     G4ThreeVector(min.x(), min.y(), min.z()),     873     G4ThreeVector(min.x(), min.y(), min.z()), // 1st vertice:
883     G4ThreeVector(min.x(), max.y(), min.z()),     874     G4ThreeVector(min.x(), max.y(), min.z()), // 2nd vertice:
884     G4ThreeVector(max.x(), max.y(), min.z()),     875     G4ThreeVector(max.x(), max.y(), min.z()),
885     G4ThreeVector(max.x(), min.y(), min.z()),     876     G4ThreeVector(max.x(), min.y(), min.z()),
886     G4ThreeVector(min.x(), min.y(), max.z()),     877     G4ThreeVector(min.x(), min.y(), max.z()),
887     G4ThreeVector(min.x(), max.y(), max.z()),     878     G4ThreeVector(min.x(), max.y(), max.z()),
888     G4ThreeVector(max.x(), max.y(), max.z()),     879     G4ThreeVector(max.x(), max.y(), max.z()),
889     G4ThreeVector(max.x(), min.y(), max.z())      880     G4ThreeVector(max.x(), min.y(), max.z())
890   };                                              881   };
891                                                   882 
892   min.set(kInfinity,kInfinity,kInfinity);         883   min.set(kInfinity,kInfinity,kInfinity);
893   max.set(-kInfinity,-kInfinity,-kInfinity);      884   max.set(-kInfinity,-kInfinity,-kInfinity);
894                                                   885 
895   // Loop on th vertices                          886   // Loop on th vertices
896   G4int limit = sizeof(vertices) / sizeof(G4Th    887   G4int limit = sizeof(vertices) / sizeof(G4ThreeVector);
897   for (G4int i = 0 ; i < limit; ++i)              888   for (G4int i = 0 ; i < limit; ++i)
898   {                                               889   {
899     // From local frame to the global one:        890     // From local frame to the global one:
900     // Current positions on the three axis:       891     // Current positions on the three axis:
901     G4ThreeVector current = GetGlobalPoint(tra    892     G4ThreeVector current = GetGlobalPoint(transformation, vertices[i]);
902                                                   893 
903     // If need be, replacement of the min & ma    894     // If need be, replacement of the min & max values:
904     if (current.x() > max.x()) max.setX(curren    895     if (current.x() > max.x()) max.setX(current.x());
905     if (current.x() < min.x()) min.setX(curren    896     if (current.x() < min.x()) min.setX(current.x());
906                                                   897 
907     if (current.y() > max.y()) max.setY(curren    898     if (current.y() > max.y()) max.setY(current.y());
908     if (current.y() < min.y()) min.setY(curren    899     if (current.y() < min.y()) min.setY(current.y());
909                                                   900 
910     if (current.z() > max.z()) max.setZ(curren    901     if (current.z() > max.z()) max.setZ(current.z());
911     if (current.z() < min.z()) min.setZ(curren    902     if (current.z() < min.z()) min.setZ(current.z());
912   }                                               903   }
913 }                                                 904 }
914                                                   905 
915 // Stream object contents to an output stream     906 // Stream object contents to an output stream
916 //____________________________________________    907 //______________________________________________________________________________
917 std::ostream& G4MultiUnion::StreamInfo(std::os    908 std::ostream& G4MultiUnion::StreamInfo(std::ostream& os) const
918 {                                                 909 {
919   G4long oldprc = os.precision(16);            << 910   G4int oldprc = os.precision(16);
920   os << "-------------------------------------    911   os << "-----------------------------------------------------------\n"
921      << "                *** Dump for solid -     912      << "                *** Dump for solid - " << GetName() << " ***\n"
922      << "                =====================    913      << "                ===================================================\n"
923      << " Solid type: G4MultiUnion\n"             914      << " Solid type: G4MultiUnion\n"
924      << " Parameters: \n";                        915      << " Parameters: \n";
925      std::size_t numNodes = fSolids.size();    << 916      G4int numNodes = fSolids.size();
926      for (std::size_t i = 0 ; i < numNodes ; + << 917      for (G4int i = 0 ; i < numNodes ; ++i)
927      {                                            918      {
928       G4VSolid& solid = *fSolids[i];              919       G4VSolid& solid = *fSolids[i];
929       solid.StreamInfo(os);                       920       solid.StreamInfo(os);
930       const G4Transform3D& transform = fTransf    921       const G4Transform3D& transform = fTransformObjs[i];
931       os << " Translation is " << transform.ge    922       os << " Translation is " << transform.getTranslation() << " \n";
932       os << " Rotation is :" << " \n";            923       os << " Rotation is :" << " \n";
933       os << " " << transform.getRotation() <<     924       os << " " << transform.getRotation() << "\n";
934      }                                            925      }
935   os << "             \n"                         926   os << "             \n"
936      << "-------------------------------------    927      << "-----------------------------------------------------------\n";
937   os.precision(oldprc);                           928   os.precision(oldprc);
938                                                   929 
939   return os;                                      930   return os;
940 }                                                 931 }
941                                                   932 
942 //____________________________________________    933 //______________________________________________________________________________
943 G4ThreeVector G4MultiUnion::GetPointOnSurface(    934 G4ThreeVector G4MultiUnion::GetPointOnSurface() const
944 {                                                 935 {
945   G4ThreeVector point;                            936   G4ThreeVector point;
946                                                   937 
947   G4long size = fSolids.size();                   938   G4long size = fSolids.size();
948                                                   939 
949   do                                              940   do
950   {                                               941   {
951     G4long rnd = G4RandFlat::shootInt(G4long(0    942     G4long rnd = G4RandFlat::shootInt(G4long(0), size);
952     G4VSolid& solid = *fSolids[rnd];              943     G4VSolid& solid = *fSolids[rnd];
953     point = solid.GetPointOnSurface();            944     point = solid.GetPointOnSurface();
954     const G4Transform3D& transform = fTransfor    945     const G4Transform3D& transform = fTransformObjs[rnd];
955     point = GetGlobalPoint(transform, point);     946     point = GetGlobalPoint(transform, point);
956   }                                               947   }
957   while (Inside(point) != EInside::kSurface);     948   while (Inside(point) != EInside::kSurface);
958                                                   949 
959   return point;                                   950   return point;
960 }                                                 951 }
961                                                   952 
962 //____________________________________________    953 //______________________________________________________________________________
963 void                                              954 void 
964 G4MultiUnion::DescribeYourselfTo ( G4VGraphics    955 G4MultiUnion::DescribeYourselfTo ( G4VGraphicsScene& scene ) const 
965 {                                                 956 {
966   scene.AddSolid (*this);                         957   scene.AddSolid (*this);
967 }                                                 958 }
968                                                   959 
969 //____________________________________________    960 //______________________________________________________________________________
970 G4Polyhedron* G4MultiUnion::CreatePolyhedron()    961 G4Polyhedron* G4MultiUnion::CreatePolyhedron() const
971 {                                                 962 {
972   if (G4BooleanSolid::GetExternalBooleanProces << 963   HepPolyhedronProcessor processor;
973   {                                            << 964   HepPolyhedronProcessor::Operation operation = HepPolyhedronProcessor::UNION;
974     HepPolyhedronProcessor processor;          << 
975     HepPolyhedronProcessor::Operation operatio << 
976                                                << 
977     G4VSolid* solidA = GetSolid(0);            << 
978     const G4Transform3D transform0 = GetTransf << 
979     G4DisplacedSolid dispSolidA("placedA", sol << 
980                                                << 
981     auto top = new G4Polyhedron(*dispSolidA.Ge << 
982                                                   965 
983     for (G4int i = 1; i < GetNumberOfSolids(); << 966   G4VSolid* solidA = GetSolid(0);
984     {                                          << 967   const G4Transform3D transform0=GetTransformation(0);
985       G4VSolid* solidB = GetSolid(i);          << 968   G4DisplacedSolid dispSolidA("placedA",solidA,transform0);
986       const G4Transform3D transform = GetTrans << 
987       G4DisplacedSolid dispSolidB("placedB", s << 
988       G4Polyhedron* operand = dispSolidB.GetPo << 
989       processor.push_back(operation, *operand) << 
990     }                                          << 
991                                                   969 
992     if (processor.execute(*top))               << 970   G4Polyhedron* top = new G4Polyhedron(*dispSolidA.GetPolyhedron());
993     {                                          << 971     
994       return top;                              << 972   for(G4int i=1; i<GetNumberOfSolids(); ++i)
995     }                                          << 
996     else                                       << 
997     {                                          << 
998       return nullptr;                          << 
999     }                                          << 
1000   }                                           << 
1001   else                                        << 
1002   {                                              973   {
1003     return G4BooleanSolid::GetExternalBoolean << 974     G4VSolid* solidB = GetSolid(i);
                                                   >> 975     const G4Transform3D transform=GetTransformation(i);
                                                   >> 976     G4DisplacedSolid dispSolidB("placedB",solidB,transform);
                                                   >> 977     G4Polyhedron* operand = dispSolidB.GetPolyhedron();
                                                   >> 978     processor.push_back (operation, *operand);
1004   }                                              979   }
                                                   >> 980    
                                                   >> 981   if (processor.execute(*top)) { return top; }
                                                   >> 982   else { return 0; } 
1005 }                                                983 }
1006                                                  984 
1007 //___________________________________________    985 //______________________________________________________________________________
1008 G4Polyhedron* G4MultiUnion::GetPolyhedron() c    986 G4Polyhedron* G4MultiUnion::GetPolyhedron() const
1009 {                                                987 {
1010   if (fpPolyhedron == nullptr ||                 988   if (fpPolyhedron == nullptr ||
1011       fRebuildPolyhedron ||                      989       fRebuildPolyhedron ||
1012       fpPolyhedron->GetNumberOfRotationStepsA    990       fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
1013       fpPolyhedron->GetNumberOfRotationSteps(    991       fpPolyhedron->GetNumberOfRotationSteps())
1014   {                                           << 992     {
1015     G4AutoLock l(&polyhedronMutex);           << 993       G4AutoLock l(&polyhedronMutex);
1016     delete fpPolyhedron;                      << 994       delete fpPolyhedron;
1017     fpPolyhedron = CreatePolyhedron();        << 995       fpPolyhedron = CreatePolyhedron();
1018     fRebuildPolyhedron = false;               << 996       fRebuildPolyhedron = false;
1019     l.unlock();                               << 997       l.unlock();
1020   }                                           << 998     }
1021   return fpPolyhedron;                           999   return fpPolyhedron;
1022 }                                                1000 }
1023                                                  1001