Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/solids/specific/src/G4Voxelizer.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /geometry/solids/specific/src/G4Voxelizer.cc (Version 11.3.0) and /geometry/solids/specific/src/G4Voxelizer.cc (Version 10.7.p3)


  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 // G4Voxelizer implementation                      26 // G4Voxelizer implementation
 27 //                                                 27 //
 28 // 19.10.12 Marek Gayer, created                   28 // 19.10.12 Marek Gayer, created
 29 // -------------------------------------------     29 // --------------------------------------------------------------------
 30                                                    30 
 31 #include <iostream>                                31 #include <iostream>
 32 #include <iomanip>                                 32 #include <iomanip>
 33 #include <sstream>                                 33 #include <sstream>
 34 #include <algorithm>                               34 #include <algorithm>
 35 #include <set>                                     35 #include <set>
 36                                                    36 
 37 #include "G4VSolid.hh"                             37 #include "G4VSolid.hh" 
 38                                                    38 
 39 #include "G4CSGSolid.hh"                       << 
 40 #include "G4GeometryTolerance.hh"              << 
 41 #include "G4Orb.hh"                                39 #include "G4Orb.hh"
 42 #include "G4PhysicalConstants.hh"              << 
 43 #include "G4SolidStore.hh"                     << 
 44 #include "G4Types.hh"                          << 
 45 #include "G4Voxelizer.hh"                          40 #include "G4Voxelizer.hh"
                                                   >>  41 #include "G4SolidStore.hh"
 46 #include "Randomize.hh"                            42 #include "Randomize.hh"
                                                   >>  43 #include "G4PhysicalConstants.hh"
                                                   >>  44 #include "G4GeometryTolerance.hh"
                                                   >>  45 #include "G4CSGSolid.hh"
                                                   >>  46 #include "G4Orb.hh"
                                                   >>  47 #include "G4Types.hh"
 47 #include "geomdefs.hh"                             48 #include "geomdefs.hh"
 48                                                    49 
 49 using namespace std;                               50 using namespace std;
 50                                                    51 
 51 G4ThreadLocal G4int G4Voxelizer::fDefaultVoxel     52 G4ThreadLocal G4int G4Voxelizer::fDefaultVoxelsCount = -1;
 52                                                    53 
 53 //____________________________________________     54 //______________________________________________________________________________
 54 G4Voxelizer::G4Voxelizer()                         55 G4Voxelizer::G4Voxelizer()
 55   : fBoundingBox("VoxBBox", 1, 1, 1)               56   : fBoundingBox("VoxBBox", 1, 1, 1)
 56 {                                                  57 {
 57   fCountOfVoxels = fNPerSlice = fTotalCandidat     58   fCountOfVoxels = fNPerSlice = fTotalCandidates = 0;
 58                                                    59   
 59   fTolerance = G4GeometryTolerance::GetInstanc     60   fTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
 60                                                    61 
 61   SetMaxVoxels(fDefaultVoxelsCount);               62   SetMaxVoxels(fDefaultVoxelsCount); 
 62                                                    63 
 63   G4SolidStore::GetInstance()->DeRegister(&fBo     64   G4SolidStore::GetInstance()->DeRegister(&fBoundingBox);
 64 }                                                  65 }
 65                                                    66 
 66 //____________________________________________     67 //______________________________________________________________________________
 67 G4Voxelizer::~G4Voxelizer() = default;         <<  68 G4Voxelizer::~G4Voxelizer()
                                                   >>  69 {
                                                   >>  70 }
 68                                                    71 
 69 //____________________________________________     72 //______________________________________________________________________________
 70 void G4Voxelizer::BuildEmpty()                     73 void G4Voxelizer::BuildEmpty()
 71 {                                                  74 {
 72   // by reserving the size of candidates, we w     75   // by reserving the size of candidates, we would avoid reallocation of 
 73   // the vector which could cause fragmentatio     76   // the vector which could cause fragmentation
 74   //                                               77   //
 75   std::vector<G4int> xyz(3), max(3), candidate     78   std::vector<G4int> xyz(3), max(3), candidates(fTotalCandidates);
 76   const std::vector<G4int> empty(0);               79   const std::vector<G4int> empty(0);
 77                                                    80 
 78   for (auto i = 0; i <= 2; ++i) max[i] = (G4in <<  81   for (auto i = 0; i <= 2; ++i) max[i] = fBoundaries[i].size();
 79   unsigned int size = max[0] * max[1] * max[2]     82   unsigned int size = max[0] * max[1] * max[2];
 80                                                    83 
 81   fEmpty.Clear();                                  84   fEmpty.Clear();
 82   fEmpty.ResetBitNumber(size-1);                   85   fEmpty.ResetBitNumber(size-1);
 83   fEmpty.ResetAllBits(true);                       86   fEmpty.ResetAllBits(true);
 84                                                    87 
 85   for (xyz[2] = 0; xyz[2] < max[2]; ++xyz[2])      88   for (xyz[2] = 0; xyz[2] < max[2]; ++xyz[2])
 86   {                                                89   {
 87     for (xyz[1] = 0; xyz[1] < max[1]; ++xyz[1]     90     for (xyz[1] = 0; xyz[1] < max[1]; ++xyz[1])
 88     {                                              91     {
 89       for (xyz[0] = 0; xyz[0] < max[0]; ++xyz[     92       for (xyz[0] = 0; xyz[0] < max[0]; ++xyz[0])
 90       {                                            93       {
 91         if (GetCandidatesVoxelArray(xyz, candi <<  94         if (GetCandidatesVoxelArray(xyz, candidates)) 
 92         {                                          95         {
 93           G4int index = GetVoxelsIndex(xyz);       96           G4int index = GetVoxelsIndex(xyz);
 94           fEmpty.SetBitNumber(index, false);       97           fEmpty.SetBitNumber(index, false);
 95                                                    98 
 96           // rather than assigning directly wi     99           // rather than assigning directly with:
 97           // "fCandidates[index] = candidates;    100           // "fCandidates[index] = candidates;", in an effort to ensure that 
 98           // capacity would be just exact, we     101           // capacity would be just exact, we rather use following 3 lines
 99           //                                      102           //
100           std::vector<G4int> &c = (fCandidates    103           std::vector<G4int> &c = (fCandidates[index] = empty);
101           c.reserve(candidates.size());           104           c.reserve(candidates.size());
102           c.assign(candidates.begin(), candida    105           c.assign(candidates.begin(), candidates.end());
103         }                                         106         }
104       }                                           107       }
105     }                                             108     }
106   }                                               109   }
107 #ifdef G4SPECSDEBUG                               110 #ifdef G4SPECSDEBUG
108   G4cout << "Non-empty voxels count: " << fCan    111   G4cout << "Non-empty voxels count: " << fCandidates.size() << G4endl;
109 #endif                                            112 #endif
110 }                                                 113 }
111                                                   114 
112 //____________________________________________    115 //______________________________________________________________________________
113 void G4Voxelizer::BuildVoxelLimits(std::vector    116 void G4Voxelizer::BuildVoxelLimits(std::vector<G4VSolid*>& solids,
114                                    std::vector    117                                    std::vector<G4Transform3D>& transforms)
115 {                                                 118 {
116   // "BuildVoxelLimits"'s aim is to store the     119   // "BuildVoxelLimits"'s aim is to store the coordinates of the origin as
117   // well as the half lengths related to the b    120   // well as the half lengths related to the bounding box of each node.
118   // These quantities are stored in the array     121   // These quantities are stored in the array "fBoxes" (6 different values per
119   // node                                         122   // node
120   //                                              123   //
121   if (std::size_t numNodes = solids.size()) // << 124   if (G4int numNodes = solids.size()) // Number of nodes in "multiUnion"
122   {                                               125   {
123     fBoxes.resize(numNodes); // Array which wi    126     fBoxes.resize(numNodes); // Array which will store the half lengths
124     fNPerSlice = G4int(1 + (fBoxes.size() - 1) << 127     fNPerSlice = 1 + (fBoxes.size() - 1) / (8 * sizeof(unsigned int));
125                                                   128 
126     // related to a particular node, but also     129     // related to a particular node, but also
127     // the coordinates of its origin              130     // the coordinates of its origin
128                                                   131 
129     G4ThreeVector toleranceVector(fTolerance,f    132     G4ThreeVector toleranceVector(fTolerance,fTolerance,fTolerance);
130                                                   133 
131     for (std::size_t i = 0; i < numNodes; ++i) << 134     for (G4int i = 0; i < numNodes; ++i)
132     {                                             135     {
133       G4VSolid& solid = *solids[i];               136       G4VSolid& solid = *solids[i];
134       G4Transform3D transform = transforms[i];    137       G4Transform3D transform = transforms[i];
135       G4ThreeVector min, max;                     138       G4ThreeVector min, max;
136                                                   139 
137       solid.BoundingLimits(min, max);             140       solid.BoundingLimits(min, max);
138       if (solid.GetEntityType() == "G4Orb")       141       if (solid.GetEntityType() == "G4Orb")
139       {                                           142       {
140         G4Orb& orb = *(G4Orb*) &solid;            143         G4Orb& orb = *(G4Orb*) &solid;
141         G4ThreeVector orbToleranceVector;         144         G4ThreeVector orbToleranceVector;
142         G4double tolerance = orb.GetRadialTole    145         G4double tolerance = orb.GetRadialTolerance() / 2.0;
143         orbToleranceVector.set(tolerance,toler    146         orbToleranceVector.set(tolerance,tolerance,tolerance);
144         min -= orbToleranceVector;                147         min -= orbToleranceVector;
145         max += orbToleranceVector;                148         max += orbToleranceVector;
146       }                                           149       }
147       else                                        150       else
148       {                                           151       {
149         min -= toleranceVector;                   152         min -= toleranceVector;
150         max += toleranceVector;                   153         max += toleranceVector;
151       }                                           154       }
152       TransformLimits(min, max, transform);       155       TransformLimits(min, max, transform);
153       fBoxes[i].hlen = (max - min) / 2.;          156       fBoxes[i].hlen = (max - min) / 2.;
154       fBoxes[i].pos =  (max + min) / 2.;          157       fBoxes[i].pos =  (max + min) / 2.;
155     }                                             158     }
156     fTotalCandidates = (G4int)fBoxes.size();   << 159     fTotalCandidates = fBoxes.size();
157   }                                               160   }
158 }                                                 161 }
159                                                   162 
160 //____________________________________________    163 //______________________________________________________________________________
161 void G4Voxelizer::BuildVoxelLimits(std::vector    164 void G4Voxelizer::BuildVoxelLimits(std::vector<G4VFacet*>& facets)
162 {                                                 165 {
163   // "BuildVoxelLimits"'s aim is to store the     166   // "BuildVoxelLimits"'s aim is to store the coordinates of the origin as well
164   // as the half lengths related to the boundi    167   // as the half lengths related to the bounding box of each node.
165   // These quantities are stored in the array     168   // These quantities are stored in the array "fBoxes" (6 different values per
166   // node.                                        169   // node.
167                                                   170 
168   if (std::size_t numNodes = facets.size()) // << 171   if (G4int numNodes = facets.size()) // Number of nodes
169   {                                               172   {
170     fBoxes.resize(numNodes); // Array which wi    173     fBoxes.resize(numNodes); // Array which will store the half lengths
171     fNPerSlice = G4int(1+(fBoxes.size()-1)/(8* << 174     fNPerSlice = 1+(fBoxes.size()-1)/(8*sizeof(unsigned int));
172                                                   175 
173     G4ThreeVector toleranceVector(10*fToleranc    176     G4ThreeVector toleranceVector(10*fTolerance, 10*fTolerance, 10*fTolerance);
174                                                   177 
175     for (std::size_t i = 0; i < numNodes; ++i) << 178     for (G4int i = 0; i < numNodes; ++i)
176     {                                             179     {
177       G4VFacet &facet = *facets[i];               180       G4VFacet &facet = *facets[i];
178       G4ThreeVector min, max;                     181       G4ThreeVector min, max;
179       G4ThreeVector x(1,0,0), y(0,1,0), z(0,0,    182       G4ThreeVector x(1,0,0), y(0,1,0), z(0,0,1);
180       G4ThreeVector extent;                       183       G4ThreeVector extent;
181       max.set (facet.Extent(x), facet.Extent(y    184       max.set (facet.Extent(x), facet.Extent(y), facet.Extent(z));
182       min.set (-facet.Extent(-x), -facet.Exten    185       min.set (-facet.Extent(-x), -facet.Extent(-y), -facet.Extent(-z));
183       min -= toleranceVector;                     186       min -= toleranceVector;
184       max += toleranceVector;                     187       max += toleranceVector;
185       G4ThreeVector hlen = (max - min) / 2;       188       G4ThreeVector hlen = (max - min) / 2;
186       fBoxes[i].hlen = hlen;                      189       fBoxes[i].hlen = hlen;
187       fBoxes[i].pos = min + hlen;                 190       fBoxes[i].pos = min + hlen;
188     }                                             191     }
189     fTotalCandidates = (G4int)fBoxes.size();   << 192     fTotalCandidates = fBoxes.size();
190   }                                               193   }
191 }                                                 194 }
192                                                   195 
193 //____________________________________________    196 //______________________________________________________________________________
194 void G4Voxelizer::DisplayVoxelLimits() const      197 void G4Voxelizer::DisplayVoxelLimits() const
195 {                                                 198 {
196   // "DisplayVoxelLimits" displays the dX, dY,    199   // "DisplayVoxelLimits" displays the dX, dY, dZ, pX, pY and pZ for each node
197                                                   200 
198   std::size_t numNodes = fBoxes.size();        << 201   G4int numNodes = fBoxes.size();
199   G4long oldprec = G4cout.precision(16);       << 202   G4int oldprec = G4cout.precision(16);
200   for(std::size_t i = 0; i < numNodes; ++i)    << 203   for(G4int i = 0; i < numNodes; ++i)
201   {                                               204   {
202     G4cout << setw(10) << setiosflags(ios::fix    205     G4cout << setw(10) << setiosflags(ios::fixed) <<
203       "    -> Node " << i+1 <<  ":\n" <<          206       "    -> Node " << i+1 <<  ":\n" << 
204       "\t * [x,y,z] = " << fBoxes[i].hlen <<      207       "\t * [x,y,z] = " << fBoxes[i].hlen <<
205       "\t * [x,y,z] = " << fBoxes[i].pos << "\    208       "\t * [x,y,z] = " << fBoxes[i].pos << "\n";
206   }                                               209   }
207   G4cout.precision(oldprec);                      210   G4cout.precision(oldprec);
208 }                                                 211 }
209                                                   212 
210 //____________________________________________    213 //______________________________________________________________________________
211 void G4Voxelizer::CreateSortedBoundary(std::ve    214 void G4Voxelizer::CreateSortedBoundary(std::vector<G4double>& boundary,
212                                        G4int a    215                                        G4int axis)
213 {                                                 216 {
214   // "CreateBoundaries"'s aim is to determine     217   // "CreateBoundaries"'s aim is to determine the slices induced by the
215   // bounding fBoxes, along each axis. The cre    218   // bounding fBoxes, along each axis. The created boundaries are stored
216   // in the array "boundariesRaw"                 219   // in the array "boundariesRaw"
217                                                   220 
218   std::size_t numNodes = fBoxes.size(); // Num << 221   G4int numNodes = fBoxes.size(); // Number of nodes in structure
219                                                   222 
220   // Determination of the boundaries along x,     223   // Determination of the boundaries along x, y and z axis
221   //                                              224   //
222   for(std::size_t i = 0 ; i < numNodes; ++i)   << 225   for(G4int i = 0 ; i < numNodes; ++i)   
223   {                                               226   {
224     // For each node, the boundaries are creat    227     // For each node, the boundaries are created by using the array "fBoxes"
225     // built in method "BuildVoxelLimits"         228     // built in method "BuildVoxelLimits"
226     //                                            229     //
227     G4double p = fBoxes[i].pos[axis], d = fBox    230     G4double p = fBoxes[i].pos[axis], d = fBoxes[i].hlen[axis];
228                                                   231 
229     // x boundaries                               232     // x boundaries
230     //                                            233     //
231 #ifdef G4SPECSDEBUG                               234 #ifdef G4SPECSDEBUG
232     G4cout << "Boundary " << p - d << " - " <<    235     G4cout << "Boundary " << p - d << " - " << p + d << G4endl;
233 #endif                                            236 #endif
234     boundary[2*i] = p - d;                        237     boundary[2*i] = p - d;
235     boundary[2*i+1] = p + d;                      238     boundary[2*i+1] = p + d;
236   }                                               239   }
237   std::sort(boundary.begin(), boundary.end());    240   std::sort(boundary.begin(), boundary.end());
238 }                                                 241 }
239                                                   242 
240 //____________________________________________    243 //______________________________________________________________________________
241 void G4Voxelizer::BuildBoundaries()               244 void G4Voxelizer::BuildBoundaries()
242 {                                                 245 {
243   // "SortBoundaries" orders the boundaries al    246   // "SortBoundaries" orders the boundaries along each axis (increasing order)
244   // and also does not take into account redun    247   // and also does not take into account redundant boundaries, i.e. if two
245   // boundaries are separated by a distance st    248   // boundaries are separated by a distance strictly inferior to "tolerance".
246   // The sorted boundaries are respectively st    249   // The sorted boundaries are respectively stored in:
247   //              * boundaries[0..2]              250   //              * boundaries[0..2]
248                                                   251 
249   // In addition, the number of elements conta    252   // In addition, the number of elements contained in the three latter arrays
250   // are precise thanks to variables: boundari    253   // are precise thanks to variables: boundariesCountX, boundariesCountY and
251   // boundariesCountZ.                            254   // boundariesCountZ.
252                                                   255 
253   if (std::size_t numNodes = fBoxes.size())    << 256   if (G4int numNodes = fBoxes.size())
254   {                                               257   {
255     const G4double tolerance = fTolerance / 10    258     const G4double tolerance = fTolerance / 100.0;
256       // Minimal distance to discriminate two     259       // Minimal distance to discriminate two boundaries.
257                                                   260 
258     std::vector<G4double> sortedBoundary(2*num    261     std::vector<G4double> sortedBoundary(2*numNodes);
259                                                   262 
                                                   >> 263     G4int considered;
                                                   >> 264 
260     for (auto j = 0; j <= 2; ++j)                 265     for (auto j = 0; j <= 2; ++j)
261     {                                             266     {
262       CreateSortedBoundary(sortedBoundary, j);    267       CreateSortedBoundary(sortedBoundary, j);
263       std::vector<G4double> &boundary = fBound    268       std::vector<G4double> &boundary = fBoundaries[j];
264       boundary.clear();                           269       boundary.clear();
265                                                   270 
266       for(std::size_t i = 0 ; i < 2*numNodes;  << 271       considered = 0;
                                                   >> 272 
                                                   >> 273       for(G4int i = 0 ; i < 2*numNodes; ++i)
267       {                                           274       {
268         G4double newBoundary = sortedBoundary[    275         G4double newBoundary = sortedBoundary[i];
269 #ifdef G4SPECSDEBUG                               276 #ifdef G4SPECSDEBUG 
270         if (j == 0) G4cout << "Examining " <<     277         if (j == 0) G4cout << "Examining " << newBoundary << "..." << G4endl;
271 #endif                                            278 #endif
272         auto size = (G4int)boundary.size();    << 279         G4int size = boundary.size();
273         if((size == 0) || std::abs(boundary[si << 280         if(!size || std::abs(boundary[size-1] - newBoundary) > tolerance)
274         {                                         281         {
                                                   >> 282           considered++;
275           {                                       283           {
276 #ifdef G4SPECSDEBUG                               284 #ifdef G4SPECSDEBUG     
277             if (j == 0) G4cout << "Adding boun    285             if (j == 0) G4cout << "Adding boundary " << newBoundary << "..."
278                                << G4endl;         286                                << G4endl;
279 #endif                                            287 #endif    
280             boundary.push_back(newBoundary);      288             boundary.push_back(newBoundary);
281             continue;                             289             continue;
282           }                                       290           }
283         }                                         291         }
284         // If two successive boundaries are to    292         // If two successive boundaries are too close from each other,
285         // only the first one is considered       293         // only the first one is considered   
286       }                                           294       }
287                                                   295 
288       auto n = (G4int)boundary.size();         << 296       G4int n = boundary.size();
289       G4int max = 100000;                         297       G4int max = 100000;
290       if (n > max/2)                              298       if (n > max/2)
291       {                                           299       {
292         G4int skip = n / (max /2); // n has to    300         G4int skip = n / (max /2); // n has to be 2x bigger then 50.000.
293                                    // therefor    301                                    // therefore only from 100.000 reduced
294         std::vector<G4double> reduced;            302         std::vector<G4double> reduced;
295         for (G4int i = 0; i < n; ++i)             303         for (G4int i = 0; i < n; ++i)
296         {                                         304         {
297           // 50 ok for 2k, 1000, 2000             305           // 50 ok for 2k, 1000, 2000
298           auto size = (G4int)boundary.size();  << 306           G4int size = boundary.size();
299           if (i % skip == 0 || i == 0 || i ==     307           if (i % skip == 0 || i == 0 || i == size - 1)
300           {                                       308           {
301             // this condition of merging bound    309             // this condition of merging boundaries was wrong,
302             // it did not count with right par    310             // it did not count with right part, which can be
303             // completely ommited and not incl    311             // completely ommited and not included in final consideration.
304             // Now should be OK                   312             // Now should be OK
305             //                                    313             //
306             reduced.push_back(boundary[i]);       314             reduced.push_back(boundary[i]);
307           }                                       315           }
308         }                                         316         }
309         boundary = std::move(reduced);         << 317         boundary = reduced;
310       }                                           318       }
311     }                                             319     }
312   }                                               320   }
313 }                                                 321 }
314                                                   322 
315 //____________________________________________    323 //______________________________________________________________________________
316 void G4Voxelizer::DisplayBoundaries()             324 void G4Voxelizer::DisplayBoundaries()
317 {                                                 325 {
318   char axis[3] = {'X', 'Y', 'Z'};                 326   char axis[3] = {'X', 'Y', 'Z'};
319   for (auto i = 0; i <= 2; ++i)                   327   for (auto i = 0; i <= 2; ++i)
320   {                                               328   {
321     G4cout << " * " << axis[i] << " axis:" <<     329     G4cout << " * " << axis[i] << " axis:" << G4endl << "    | ";
322     DisplayBoundaries(fBoundaries[i]);            330     DisplayBoundaries(fBoundaries[i]);
323   }                                               331   }
324 }                                                 332 }
325                                                   333 
326 //____________________________________________    334 //______________________________________________________________________________
327 void G4Voxelizer::DisplayBoundaries(std::vecto    335 void G4Voxelizer::DisplayBoundaries(std::vector<G4double> &boundaries)
328 {                                                 336 {
329   // Prints the positions of the boundaries of    337   // Prints the positions of the boundaries of the slices on the three axes
330                                                   338 
331   std::size_t count = boundaries.size();       << 339   G4int count = boundaries.size();
332   G4long oldprec = G4cout.precision(16);       << 340   G4int oldprec = G4cout.precision(16);
333   for(std::size_t i = 0; i < count; ++i)       << 341   for(G4int i = 0; i < count; ++i)
334   {                                               342   {
335     G4cout << setw(10) << setiosflags(ios::fix    343     G4cout << setw(10) << setiosflags(ios::fixed) << boundaries[i];
336     if(i != count-1) G4cout << "-> ";             344     if(i != count-1) G4cout << "-> ";
337   }                                               345   }
338   G4cout << "|" << G4endl << "Number of bounda    346   G4cout << "|" << G4endl << "Number of boundaries: " << count << G4endl;
339   G4cout.precision(oldprec);                      347   G4cout.precision(oldprec);
340 }                                                 348 }
341                                                   349 
342 //____________________________________________    350 //______________________________________________________________________________
343 void G4Voxelizer::BuildBitmasks(std::vector<G4    351 void G4Voxelizer::BuildBitmasks(std::vector<G4double> boundaries[],
344                                 G4SurfBits bit    352                                 G4SurfBits bitmasks[], G4bool countsOnly)
345 {                                                 353 {
346   // "BuildListNodes" stores in the bitmasks s    354   // "BuildListNodes" stores in the bitmasks solids present in each slice
347   // along an axis.                               355   // along an axis.
348                                                   356 
349   std::size_t numNodes = fBoxes.size();        << 357   G4int numNodes = fBoxes.size();
350   G4int bitsPerSlice = GetBitsPerSlice();         358   G4int bitsPerSlice = GetBitsPerSlice();
351                                                   359 
352   for (auto k = 0; k < 3; ++k)                    360   for (auto k = 0; k < 3; ++k)
353   {                                               361   {
                                                   >> 362     G4int total = 0;
354     std::vector<G4double>& boundary = boundari    363     std::vector<G4double>& boundary = boundaries[k];
355     G4int voxelsCount = (G4int)boundary.size() << 364     G4int voxelsCount = boundary.size() - 1;
356     G4SurfBits& bitmask = bitmasks[k];            365     G4SurfBits& bitmask = bitmasks[k];
357                                                   366 
358     if (!countsOnly)                              367     if (!countsOnly)
359     {                                             368     {
360       bitmask.Clear();                            369       bitmask.Clear();
361 #ifdef G4SPECSDEBUG                               370 #ifdef G4SPECSDEBUG
362       G4cout << "Allocating bitmask..." << G4e    371       G4cout << "Allocating bitmask..." << G4endl;
363 #endif                                            372 #endif
364       bitmask.SetBitNumber(voxelsCount*bitsPer    373       bitmask.SetBitNumber(voxelsCount*bitsPerSlice-1, false);
365         // it is here so we can set the maximu    374         // it is here so we can set the maximum number of bits. this line
366         // will rellocate the memory and set a    375         // will rellocate the memory and set all to zero
367     }                                             376     }
368     std::vector<G4int>& candidatesCount = fCan    377     std::vector<G4int>& candidatesCount = fCandidatesCounts[k];
369     candidatesCount.resize(voxelsCount);          378     candidatesCount.resize(voxelsCount);
370                                                   379 
371     for(G4int i = 0 ; i < voxelsCount; ++i) {     380     for(G4int i = 0 ; i < voxelsCount; ++i) { candidatesCount[i] = 0; }
372                                                   381 
373     // Loop on the nodes, number of slices per    382     // Loop on the nodes, number of slices per axis
374     //                                            383     //
375     for(std::size_t j = 0 ; j < numNodes; ++j) << 384     for(G4int j = 0 ; j < numNodes; ++j)
376     {                                             385     {
377       // Determination of the minimum and maxi    386       // Determination of the minimum and maximum position along x
378       // of the bounding boxe of each node        387       // of the bounding boxe of each node
379       //                                          388       //
380       G4double p = fBoxes[j].pos[k], d = fBoxe    389       G4double p = fBoxes[j].pos[k], d = fBoxes[j].hlen[k];
381                                                   390 
382       G4double min = p - d; // - localToleranc    391       G4double min = p - d; // - localTolerance;
383       G4double max = p + d; // + localToleranc    392       G4double max = p + d; // + localTolerance;
384                                                   393 
385       G4int i = BinarySearch(boundary, min);      394       G4int i = BinarySearch(boundary, min);
386       if (i < 0)  { i = 0; }                      395       if (i < 0)  { i = 0; }
387                                                   396 
388       do    // Loop checking, 13.08.2015, G.Co    397       do    // Loop checking, 13.08.2015, G.Cosmo
389       {                                           398       {
390         if (!countsOnly)                          399         if (!countsOnly)
391         {                                         400         {
392           bitmask.SetBitNumber(i*bitsPerSlice+ << 401           bitmask.SetBitNumber(i*bitsPerSlice+j);
393         }                                         402         }
394         candidatesCount[i]++;                     403         candidatesCount[i]++;
                                                   >> 404         ++total;
395         ++i;                                      405         ++i;
396       }                                           406       }
397       while (max > boundary[i] && i < voxelsCo    407       while (max > boundary[i] && i < voxelsCount);
398     }                                             408     }
399   }                                               409   }
400 #ifdef G4SPECSDEBUG                               410 #ifdef G4SPECSDEBUG
401   G4cout << "Build list nodes completed." << G    411   G4cout << "Build list nodes completed." << G4endl;
402 #endif                                            412 #endif
403 }                                                 413 }
404                                                   414 
405 //____________________________________________    415 //______________________________________________________________________________
406 G4String G4Voxelizer::GetCandidatesAsString(co    416 G4String G4Voxelizer::GetCandidatesAsString(const G4SurfBits& bits) const
407 {                                                 417 {
408   // Decodes the candidates in mask as G4Strin    418   // Decodes the candidates in mask as G4String.
409                                                   419 
410   stringstream ss;                                420   stringstream ss;
411   auto numNodes = (G4int)fBoxes.size();        << 421   G4int numNodes = fBoxes.size();
412                                                   422 
413   for(auto i=0; i<numNodes; ++i)               << 423   for(G4int i=0; i<numNodes; ++i)
414   {                                               424   {
415     if (bits.TestBitNumber(i))  { ss << i+1 <<    425     if (bits.TestBitNumber(i))  { ss << i+1 << " "; }
416   }                                               426   }
417   return ss.str();                                427   return ss.str();
418 }                                                 428 }
419                                                   429 
420 //____________________________________________    430 //______________________________________________________________________________
421 void G4Voxelizer::DisplayListNodes() const        431 void G4Voxelizer::DisplayListNodes() const
422 {                                                 432 {
423   // Prints which solids are present in the sl    433   // Prints which solids are present in the slices previously elaborated.
424                                                   434 
425   char axis[3] = {'X', 'Y', 'Z'};                 435   char axis[3] = {'X', 'Y', 'Z'};
426   G4int size=8*sizeof(G4int)*fNPerSlice;          436   G4int size=8*sizeof(G4int)*fNPerSlice;
427   G4SurfBits bits(size);                          437   G4SurfBits bits(size);
428                                                   438 
429   for (auto j = 0; j <= 2; ++j)                   439   for (auto j = 0; j <= 2; ++j)
430   {                                               440   {
431     G4cout << " * " << axis[j] << " axis:" <<     441     G4cout << " * " << axis[j] << " axis:" << G4endl;
432     auto count = (G4int)fBoundaries[j].size(); << 442     G4int count = fBoundaries[j].size();
433     for(G4int i=0; i < count-1; ++i)              443     for(G4int i=0; i < count-1; ++i)
434     {                                             444     {
435       G4cout << "    Slice #" << i+1 << ": ["     445       G4cout << "    Slice #" << i+1 << ": [" << fBoundaries[j][i]
436              << " ; " << fBoundaries[j][i+1] <    446              << " ; " << fBoundaries[j][i+1] << "] -> ";
437       bits.set(size,(const char *)fBitmasks[j]    447       bits.set(size,(const char *)fBitmasks[j].fAllBits+i
438                                  *fNPerSlice*s    448                                  *fNPerSlice*sizeof(G4int));
439       G4String result = GetCandidatesAsString(    449       G4String result = GetCandidatesAsString(bits);
440       G4cout << "[ " << result.c_str() << "]      450       G4cout << "[ " << result.c_str() << "]  " << G4endl;
441     }                                             451     }
442   }                                               452   }
443 }                                                 453 }
444                                                   454 
445 //____________________________________________    455 //______________________________________________________________________________
446 void G4Voxelizer::BuildBoundingBox()              456 void G4Voxelizer::BuildBoundingBox()
447 {                                                 457 {
448   G4ThreeVector min(fBoundaries[0].front(),       458   G4ThreeVector min(fBoundaries[0].front(),
449                     fBoundaries[1].front(),       459                     fBoundaries[1].front(),
450                     fBoundaries[2].front());      460                     fBoundaries[2].front());
451   G4ThreeVector max(fBoundaries[0].back(),        461   G4ThreeVector max(fBoundaries[0].back(),
452                     fBoundaries[1].back(),        462                     fBoundaries[1].back(),
453                     fBoundaries[2].back());       463                     fBoundaries[2].back());
454   BuildBoundingBox(min, max);                     464   BuildBoundingBox(min, max);
455 }                                                 465 }
456                                                   466 
457 //____________________________________________    467 //______________________________________________________________________________
458 void G4Voxelizer::BuildBoundingBox(G4ThreeVect    468 void G4Voxelizer::BuildBoundingBox(G4ThreeVector& amin,
459                                    G4ThreeVect    469                                    G4ThreeVector& amax,
460                                    G4double to    470                                    G4double tolerance)
461 {                                                 471 {
462   for (auto i = 0; i <= 2; ++i)                   472   for (auto i = 0; i <= 2; ++i)
463   {                                               473   {
464     G4double min = amin[i];                       474     G4double min = amin[i];
465     G4double max = amax[i];                       475     G4double max = amax[i];
466     fBoundingBoxSize[i] = (max - min) / 2 + to    476     fBoundingBoxSize[i] = (max - min) / 2 + tolerance * 0.5;
467     fBoundingBoxCenter[i] = min + fBoundingBox    477     fBoundingBoxCenter[i] = min + fBoundingBoxSize[i];
468   }                                               478   }
469   fBoundingBox.SetXHalfLength(fBoundingBoxSize    479   fBoundingBox.SetXHalfLength(fBoundingBoxSize.x());
470   fBoundingBox.SetYHalfLength(fBoundingBoxSize    480   fBoundingBox.SetYHalfLength(fBoundingBoxSize.y());
471   fBoundingBox.SetZHalfLength(fBoundingBoxSize    481   fBoundingBox.SetZHalfLength(fBoundingBoxSize.z());
472 }                                                 482 }
473                                                   483 
474 // algorithm -                                    484 // algorithm - 
475                                                   485 
476 // in order to get balanced voxels, merge shou    486 // in order to get balanced voxels, merge should always unite those regions,
477 // where the number of voxels is least the num    487 // where the number of voxels is least the number.
478 // We will keep sorted list (std::set) with al    488 // We will keep sorted list (std::set) with all voxels. there will be
479 // comparator function between two voxels, whi    489 // comparator function between two voxels, which will tell if voxel is less
480 // by looking at his right neighbor.              490 // by looking at his right neighbor.
481 // First, we will add all the voxels into the     491 // First, we will add all the voxels into the tree.
482 // We will be pick the first item in the tree,    492 // We will be pick the first item in the tree, merging it, adding the right
483 // merged voxel into the a list for future red    493 // merged voxel into the a list for future reduction (fBitmasks will be
484 // rebuilded later, therefore they need not to    494 // rebuilded later, therefore they need not to be updated).
485 // The merged voxel need to be added to the tr    495 // The merged voxel need to be added to the tree again, so it's position
486 // would be updated.                              496 // would be updated.
487                                                   497 
488 //____________________________________________    498 //______________________________________________________________________________
489 void G4Voxelizer::SetReductionRatio(G4int maxV    499 void G4Voxelizer::SetReductionRatio(G4int maxVoxels,
490                                     G4ThreeVec    500                                     G4ThreeVector& reductionRatio)
491 {                                                 501 {
492   G4double maxTotal = (G4double) fCandidatesCo    502   G4double maxTotal = (G4double) fCandidatesCounts[0].size()
493                     * fCandidatesCounts[1].siz    503                     * fCandidatesCounts[1].size() * fCandidatesCounts[2].size();
494                                                   504 
495   if (maxVoxels > 0 && maxVoxels < maxTotal)      505   if (maxVoxels > 0 && maxVoxels < maxTotal)
496   {                                               506   {
497     G4double ratio = (G4double) maxVoxels / ma    507     G4double ratio = (G4double) maxVoxels / maxTotal;
498     ratio = std::pow(ratio, 1./3.);               508     ratio = std::pow(ratio, 1./3.);
499     if (ratio > 1)  { ratio = 1; }                509     if (ratio > 1)  { ratio = 1; }
500     reductionRatio.set(ratio,ratio,ratio);        510     reductionRatio.set(ratio,ratio,ratio);
501   }                                               511   }
502 }                                                 512 }
503                                                   513 
504 //____________________________________________    514 //______________________________________________________________________________
505 void G4Voxelizer::BuildReduceVoxels(std::vecto    515 void G4Voxelizer::BuildReduceVoxels(std::vector<G4double> boundaries[],
506                                     G4ThreeVec    516                                     G4ThreeVector reductionRatio)
507 {                                                 517 {
508   for (auto k = 0; k <= 2; ++k)                   518   for (auto k = 0; k <= 2; ++k)
509   {                                               519   {
510     std::vector<G4int> &candidatesCount = fCan    520     std::vector<G4int> &candidatesCount = fCandidatesCounts[k];
511     auto max = (G4int)candidatesCount.size();  << 521     G4int max = candidatesCount.size();
512     std::vector<G4VoxelInfo> voxels(max);         522     std::vector<G4VoxelInfo> voxels(max);
513     G4VoxelComparator comp(voxels);               523     G4VoxelComparator comp(voxels);
514     std::set<G4int, G4VoxelComparator> voxelSe    524     std::set<G4int, G4VoxelComparator> voxelSet(comp);
515     std::vector<G4int> mergings;                  525     std::vector<G4int> mergings;
516                                                   526 
517     for (G4int j = 0; j < max; ++j)               527     for (G4int j = 0; j < max; ++j)
518     {                                             528     {
519       G4VoxelInfo &voxel = voxels[j];             529       G4VoxelInfo &voxel = voxels[j];
520       voxel.count = candidatesCount[j];           530       voxel.count = candidatesCount[j];
521       voxel.previous = j - 1;                     531       voxel.previous = j - 1;
522       voxel.next = j + 1;                         532       voxel.next = j + 1;
523       voxels[j] = voxel;                          533       voxels[j] = voxel;
524     }                                             534     }
525                                                   535 
526     for (G4int j = 0; j < max - 1; ++j)  { vox    536     for (G4int j = 0; j < max - 1; ++j)  { voxelSet.insert(j); }
527       // we go to size-1 to make sure we will     537       // we go to size-1 to make sure we will not merge the last element
528                                                   538 
529     G4double reduction = reductionRatio[k];       539     G4double reduction = reductionRatio[k];
530     if (reduction != 0)                           540     if (reduction != 0)
531     {                                             541     {
532       G4int count = 0, currentCount;              542       G4int count = 0, currentCount;
533       while ((currentCount = (G4int)voxelSet.s << 543       while ((currentCount = voxelSet.size()) > 2) 
534       {                                           544       {
535         G4double currentRatio = 1 - (G4double)    545         G4double currentRatio = 1 - (G4double) count / max;
536         if ((currentRatio <= reduction) && (cu    546         if ((currentRatio <= reduction) && (currentCount <= 1000))
537           break;                                  547           break;
538         const G4int pos = *voxelSet.begin();      548         const G4int pos = *voxelSet.begin();
539         mergings.push_back(pos + 1);              549         mergings.push_back(pos + 1);
540                                                   550 
541         G4VoxelInfo& voxel = voxels[pos];         551         G4VoxelInfo& voxel = voxels[pos];
542         G4VoxelInfo& nextVoxel = voxels[voxel.    552         G4VoxelInfo& nextVoxel = voxels[voxel.next];
543                                                   553 
544         if (voxelSet.erase(pos) != 1)             554         if (voxelSet.erase(pos) != 1)
545         {                                         555         {
546           ;// k = k;                              556           ;// k = k;
547         }                                         557         }
548         if (voxel.next != max - 1)                558         if (voxel.next != max - 1)
549           if (voxelSet.erase(voxel.next) != 1)    559           if (voxelSet.erase(voxel.next) != 1)
550           {                                       560           {
551             ;// k = k;                            561             ;// k = k;
552           }                                       562           }
553         if (voxel.previous != -1)                 563         if (voxel.previous != -1)
554           if (voxelSet.erase(voxel.previous) !    564           if (voxelSet.erase(voxel.previous) != 1)
555           {                                       565           {
556             ;// k = k;                            566             ;// k = k;
557           }                                       567           }
558         nextVoxel.count += voxel.count;           568         nextVoxel.count += voxel.count;
559         voxel.count = 0;                          569         voxel.count = 0;
560         nextVoxel.previous = voxel.previous;      570         nextVoxel.previous = voxel.previous;
561                                                   571 
562         if (voxel.next != max - 1)                572         if (voxel.next != max - 1)
563           voxelSet.insert(voxel.next);            573           voxelSet.insert(voxel.next);
564                                                   574 
565         if (voxel.previous != -1)                 575         if (voxel.previous != -1)
566         {                                         576         {
567           voxels[voxel.previous].next = voxel.    577           voxels[voxel.previous].next = voxel.next;
568           voxelSet.insert(voxel.previous);        578           voxelSet.insert(voxel.previous);
569         }                                         579         }
570         ++count;                                  580         ++count;
571       }  // Loop checking, 13.08.2015, G.Cosmo    581       }  // Loop checking, 13.08.2015, G.Cosmo
572     }                                             582     }
573                                                   583 
574     if (!mergings.empty())                     << 584     if (mergings.size())
575     {                                             585     {
576       std::sort(mergings.begin(), mergings.end    586       std::sort(mergings.begin(), mergings.end());
577                                                   587 
578       const std::vector<G4double>& boundary =     588       const std::vector<G4double>& boundary = boundaries[k];
579       auto mergingsSize = (G4int)mergings.size << 589       int mergingsSize = mergings.size();
580       vector<G4double> reducedBoundary;           590       vector<G4double> reducedBoundary;
581       G4int skip = mergings[0], i = 0;            591       G4int skip = mergings[0], i = 0;
582       max = (G4int)boundary.size();            << 592       max = boundary.size();
583       for (G4int j = 0; j < max; ++j)             593       for (G4int j = 0; j < max; ++j)
584       {                                           594       {
585         if (j != skip)                            595         if (j != skip)
586         {                                         596         {
587           reducedBoundary.push_back(boundary[j    597           reducedBoundary.push_back(boundary[j]);
588         }                                         598         }
589         else if (++i < mergingsSize)              599         else if (++i < mergingsSize)
590         {                                         600         {
591           skip = mergings[i];                     601           skip = mergings[i];
592         }                                         602         }
593       }                                           603       }
594       boundaries[k] = std::move(reducedBoundar << 604       boundaries[k] = reducedBoundary;
595     }                                             605     }
596 /*                                                606 /*
597     G4int count = 0;                              607     G4int count = 0;
598     while (true)    // Loop checking, 13.08.20    608     while (true)    // Loop checking, 13.08.2015, G.Cosmo
599     {                                             609     {
600       G4double reduction = reductionRatio[k];     610       G4double reduction = reductionRatio[k];
601       if (reduction == 0)                         611       if (reduction == 0)
602         break;                                    612         break;
603       G4int currentCount = voxelSet.size();       613       G4int currentCount = voxelSet.size();
604       if (currentCount <= 2)                      614       if (currentCount <= 2)
605         break;                                    615         break;
606       G4double currentRatio = 1 - (G4double) c    616       G4double currentRatio = 1 - (G4double) count / max;
607       if (currentRatio <= reduction && current    617       if (currentRatio <= reduction && currentCount <= 1000)
608         break;                                    618         break;
609       const G4int pos = *voxelSet.begin();        619       const G4int pos = *voxelSet.begin();
610       mergings.push_back(pos);                    620       mergings.push_back(pos);
611                                                   621 
612       G4VoxelInfo &voxel = voxels[pos];           622       G4VoxelInfo &voxel = voxels[pos];
613       G4VoxelInfo &nextVoxel = voxels[voxel.ne    623       G4VoxelInfo &nextVoxel = voxels[voxel.next];
614                                                   624 
615       voxelSet.erase(pos);                        625       voxelSet.erase(pos);
616       if (voxel.next != max - 1) { voxelSet.er    626       if (voxel.next != max - 1) { voxelSet.erase(voxel.next); }
617       if (voxel.previous != -1)  { voxelSet.er    627       if (voxel.previous != -1)  { voxelSet.erase(voxel.previous); }
618                                                   628 
619       nextVoxel.count += voxel.count;             629       nextVoxel.count += voxel.count;
620       voxel.count = 0;                            630       voxel.count = 0;
621       nextVoxel.previous = voxel.previous;        631       nextVoxel.previous = voxel.previous;
622                                                   632 
623       if (voxel.next != max - 1)                  633       if (voxel.next != max - 1)
624         voxelSet.insert(voxel.next);              634         voxelSet.insert(voxel.next);
625                                                   635 
626       if (voxel.previous != -1)                   636       if (voxel.previous != -1)
627       {                                           637       {
628         voxels[voxel.previous].next = voxel.ne    638         voxels[voxel.previous].next = voxel.next;
629         voxelSet.insert(voxel.previous);          639         voxelSet.insert(voxel.previous);
630       }                                           640       }
631       ++count;                                    641       ++count;
632     }                                             642     }
633                                                   643 
634     if (mergings.size())                          644     if (mergings.size())
635     {                                             645     {
636       std::sort(mergings.begin(), mergings.end    646       std::sort(mergings.begin(), mergings.end());
637                                                   647 
638       std::vector<G4double> &boundary = bounda    648       std::vector<G4double> &boundary = boundaries[k];
639       std::vector<G4double> reducedBoundary(bo    649       std::vector<G4double> reducedBoundary(boundary.size() - mergings.size());
640       G4int skip = mergings[0] + 1, cur = 0, i    650       G4int skip = mergings[0] + 1, cur = 0, i = 0;
641       max = boundary.size();                      651       max = boundary.size();
642       for (G4int j = 0; j < max; ++j)             652       for (G4int j = 0; j < max; ++j)
643       {                                           653       {
644         if (j != skip)                            654         if (j != skip)
645         {                                         655         {
646           reducedBoundary[cur++] = boundary[j]    656           reducedBoundary[cur++] = boundary[j];
647         }                                         657         }
648         else                                      658         else
649         {                                         659         {
650           if (++i < (G4int)mergings.size())  {    660           if (++i < (G4int)mergings.size())  { skip = mergings[i] + 1; }
651         }                                         661         }
652       }                                           662       }
653       boundaries[k] = reducedBoundary;            663       boundaries[k] = reducedBoundary;
654     }                                             664     }
655 */                                                665 */
656   }                                               666   }
657 }                                                 667 }
658                                                   668 
659 //____________________________________________    669 //______________________________________________________________________________
660 void G4Voxelizer::BuildReduceVoxels2(std::vect    670 void G4Voxelizer::BuildReduceVoxels2(std::vector<G4double> boundaries[],
661                                      G4ThreeVe    671                                      G4ThreeVector reductionRatio)
662 {                                                 672 {
663   for (auto k = 0; k <= 2; ++k)                   673   for (auto k = 0; k <= 2; ++k)
664   {                                               674   {
665     std::vector<G4int> &candidatesCount = fCan    675     std::vector<G4int> &candidatesCount = fCandidatesCounts[k];
666     auto max = (G4int)candidatesCount.size();  << 676     G4int max = candidatesCount.size();
667     G4int total = 0;                              677     G4int total = 0;
668     for (G4int i = 0; i < max; ++i) total += c    678     for (G4int i = 0; i < max; ++i) total += candidatesCount[i];
669                                                   679 
670     G4double reduction = reductionRatio[k];       680     G4double reduction = reductionRatio[k];
671     if (reduction == 0)                           681     if (reduction == 0)
672       break;                                      682       break;
673                                                   683 
674     G4int destination = (G4int) (reduction * m    684     G4int destination = (G4int) (reduction * max) + 1;
675     if (destination > 1000) destination = 1000    685     if (destination > 1000) destination = 1000;
676     if (destination < 2) destination = 2;         686     if (destination < 2) destination = 2;
677     G4double average = ((G4double)total / max)    687     G4double average = ((G4double)total / max) / reduction;
678                                                   688 
679     std::vector<G4int> mergings;                  689     std::vector<G4int> mergings;
680                                                   690 
681     std::vector<G4double> &boundary = boundari    691     std::vector<G4double> &boundary = boundaries[k];
682     std::vector<G4double> reducedBoundary(dest    692     std::vector<G4double> reducedBoundary(destination);
683                                                   693 
684     G4int sum = 0, cur = 0;                       694     G4int sum = 0, cur = 0;
685     for (G4int i = 0; i < max; ++i)               695     for (G4int i = 0; i < max; ++i)
686     {                                             696     {
687       sum += candidatesCount[i];                  697       sum += candidatesCount[i];
688       if (sum > average * (cur + 1) || i == 0)    698       if (sum > average * (cur + 1) || i == 0)
689       {                                           699       {
690         G4double val = boundary[i];               700         G4double val = boundary[i];
691         reducedBoundary[cur] = val;               701         reducedBoundary[cur] = val;
692         ++cur;                                    702         ++cur;
693         if (cur == destination)                   703         if (cur == destination)
694           break;                                  704           break;
695       }                                           705       }
696     }                                             706     }
697     reducedBoundary[destination-1] = boundary[    707     reducedBoundary[destination-1] = boundary[max];
698     boundaries[k] = std::move(reducedBoundary) << 708     boundaries[k] = reducedBoundary;
699   }                                               709   }
700 }                                                 710 }
701                                                   711 
702 //____________________________________________    712 //______________________________________________________________________________
703 void G4Voxelizer::Voxelize(std::vector<G4VSoli    713 void G4Voxelizer::Voxelize(std::vector<G4VSolid*>& solids,
704                            std::vector<G4Trans    714                            std::vector<G4Transform3D>& transforms)
705 {                                                 715 {
706   BuildVoxelLimits(solids, transforms);           716   BuildVoxelLimits(solids, transforms);
707   BuildBoundaries();                              717   BuildBoundaries();
708   BuildBitmasks(fBoundaries, fBitmasks);          718   BuildBitmasks(fBoundaries, fBitmasks);
709   BuildBoundingBox();                             719   BuildBoundingBox();
710   BuildEmpty(); // this does not work well for    720   BuildEmpty(); // this does not work well for multi-union,
711                 // actually only makes perform    721                 // actually only makes performance slower,
712                 // these are only pre-calculat    722                 // these are only pre-calculated but not used by multi-union
713                                                   723 
714   for (auto & fCandidatesCount : fCandidatesCo << 724   for (auto i = 0; i < 3; ++i)
715   {                                               725   {
716     fCandidatesCount.resize(0);                << 726     fCandidatesCounts[i].resize(0);
717   }                                               727   }
718 }                                                 728 }
719                                                   729 
720 //____________________________________________    730 //______________________________________________________________________________
721 void G4Voxelizer::CreateMiniVoxels(std::vector    731 void G4Voxelizer::CreateMiniVoxels(std::vector<G4double> boundaries[],
722                                    G4SurfBits     732                                    G4SurfBits bitmasks[])
723 {                                                 733 {
724   std::vector<G4int> voxel(3), maxVoxels(3);      734   std::vector<G4int> voxel(3), maxVoxels(3);
725   for (auto i = 0; i <= 2; ++i) maxVoxels[i] = << 735   for (auto i = 0; i <= 2; ++i) maxVoxels[i] = boundaries[i].size();
726                                                   736 
727   G4ThreeVector point;                            737   G4ThreeVector point;
728   for (voxel[2] = 0; voxel[2] < maxVoxels[2] -    738   for (voxel[2] = 0; voxel[2] < maxVoxels[2] - 1; ++voxel[2])
729   {                                               739   {
730     for (voxel[1] = 0; voxel[1] < maxVoxels[1]    740     for (voxel[1] = 0; voxel[1] < maxVoxels[1] - 1; ++voxel[1])
731     {                                             741     {
732       for (voxel[0] = 0; voxel[0] < maxVoxels[    742       for (voxel[0] = 0; voxel[0] < maxVoxels[0] - 1; ++voxel[0])
733       {                                           743       {
734         std::vector<G4int> candidates;            744         std::vector<G4int> candidates;
735         if (GetCandidatesVoxelArray(voxel, bit << 745         if (GetCandidatesVoxelArray(voxel, bitmasks, candidates, 0))
736         {                                         746         {
737           // find a box for corresponding non-    747           // find a box for corresponding non-empty voxel
738           G4VoxelBox box;                         748           G4VoxelBox box;
739           for (auto i = 0; i <= 2; ++i)           749           for (auto i = 0; i <= 2; ++i)
740           {                                       750           {
741             G4int index = voxel[i];               751             G4int index = voxel[i];
742             const std::vector<G4double> &bound    752             const std::vector<G4double> &boundary = boundaries[i];
743             G4double hlen = 0.5 * (boundary[in    753             G4double hlen = 0.5 * (boundary[index+1] - boundary[index]);
744             box.hlen[i] = hlen;                   754             box.hlen[i] = hlen;
745             box.pos[i] = boundary[index] + hle    755             box.pos[i] = boundary[index] + hlen;
746           }                                       756           }
747           fVoxelBoxes.push_back(box);             757           fVoxelBoxes.push_back(box);
748           std::vector<G4int>(candidates).swap(    758           std::vector<G4int>(candidates).swap(candidates);
749           fVoxelBoxesCandidates.push_back(std: << 759           fVoxelBoxesCandidates.push_back(candidates);
750         }                                         760         }
751       }                                           761       }
752     }                                             762     }
753   }                                               763   }
754 }                                                 764 }
755                                                   765 
756 //____________________________________________    766 //______________________________________________________________________________
757 void G4Voxelizer::Voxelize(std::vector<G4VFace    767 void G4Voxelizer::Voxelize(std::vector<G4VFacet*>& facets)
758 {                                                 768 {
759   G4int maxVoxels = fMaxVoxels;                   769   G4int maxVoxels = fMaxVoxels;
760   G4ThreeVector reductionRatio = fReductionRat    770   G4ThreeVector reductionRatio = fReductionRatio;
761                                                   771 
762   std::size_t size = facets.size();            << 772   G4int size = facets.size();
763   if (size < 10)                                  773   if (size < 10)
764   {                                               774   {
765     for (const auto & facet : facets)          << 775     for (G4int i = 0; i < (G4int) facets.size(); ++i)
766     {                                             776     { 
767       if (facet->GetNumberOfVertices() > 3) ++ << 777       if (facets[i]->GetNumberOfVertices() > 3) size++;
768     }                                             778     }
769   }                                               779   }
770                                                   780 
771   if ((size >= 10 || maxVoxels > 0) && maxVoxe    781   if ((size >= 10 || maxVoxels > 0) && maxVoxels != 0 && maxVoxels != 1)
772   {                                               782   {
773 #ifdef G4SPECSDEBUG                               783 #ifdef G4SPECSDEBUG
774     G4cout << "Building voxel limits..." << G4    784     G4cout << "Building voxel limits..." << G4endl;
775 #endif                                            785 #endif
776                                                   786     
777     BuildVoxelLimits(facets);                     787     BuildVoxelLimits(facets);
778                                                   788 
779 #ifdef G4SPECSDEBUG                               789 #ifdef G4SPECSDEBUG
780     G4cout << "Building boundaries..." << G4en    790     G4cout << "Building boundaries..." << G4endl;
781 #endif                                            791 #endif
782                                                   792     
783     BuildBoundaries();                            793     BuildBoundaries();
784                                                   794 
785 #ifdef G4SPECSDEBUG                               795 #ifdef G4SPECSDEBUG
786     G4cout << "Building bitmasks..." << G4endl    796     G4cout << "Building bitmasks..." << G4endl;
787 #endif                                            797 #endif
788                                                   798     
789     BuildBitmasks(fBoundaries, nullptr, true); << 799     BuildBitmasks(fBoundaries, 0, true);
790                                                   800 
791     if (maxVoxels < 0 && reductionRatio == G4T    801     if (maxVoxels < 0 && reductionRatio == G4ThreeVector())
792     {                                             802     {
793       maxVoxels = fTotalCandidates;               803       maxVoxels = fTotalCandidates;
794       if (fTotalCandidates > 1000000) maxVoxel    804       if (fTotalCandidates > 1000000) maxVoxels = 1000000;
795     }                                             805     }
796                                                   806 
797     SetReductionRatio(maxVoxels, reductionRati    807     SetReductionRatio(maxVoxels, reductionRatio);
798                                                   808 
799     fCountOfVoxels = CountVoxels(fBoundaries);    809     fCountOfVoxels = CountVoxels(fBoundaries);
800                                                   810 
801 #ifdef G4SPECSDEBUG                               811 #ifdef G4SPECSDEBUG
802     G4cout << "Total number of voxels: " << fC    812     G4cout << "Total number of voxels: " << fCountOfVoxels << G4endl;
803 #endif                                            813 #endif
804                                                   814 
805     BuildReduceVoxels2(fBoundaries, reductionR    815     BuildReduceVoxels2(fBoundaries, reductionRatio);
806                                                   816 
807     fCountOfVoxels = CountVoxels(fBoundaries);    817     fCountOfVoxels = CountVoxels(fBoundaries);
808                                                   818 
809 #ifdef G4SPECSDEBUG                               819 #ifdef G4SPECSDEBUG
810     G4cout << "Total number of voxels after re    820     G4cout << "Total number of voxels after reduction: "
811            << fCountOfVoxels << G4endl;           821            << fCountOfVoxels << G4endl;
812 #endif                                            822 #endif
813                                                   823 
814 #ifdef G4SPECSDEBUG                               824 #ifdef G4SPECSDEBUG
815     G4cout << "Building bitmasks..." << G4endl    825     G4cout << "Building bitmasks..." << G4endl;
816 #endif                                            826 #endif
817                                                   827     
818     BuildBitmasks(fBoundaries, fBitmasks);        828     BuildBitmasks(fBoundaries, fBitmasks);
819                                                   829 
820     G4ThreeVector reductionRatioMini;             830     G4ThreeVector reductionRatioMini;
821                                                   831 
822     G4SurfBits bitmasksMini[3];                   832     G4SurfBits bitmasksMini[3];
823                                                   833 
824     // section for building mini voxels           834     // section for building mini voxels
825                                                   835 
826     std::vector<G4double> miniBoundaries[3];      836     std::vector<G4double> miniBoundaries[3];
827                                                   837 
828     for (auto i = 0; i <= 2; ++i)  { miniBound    838     for (auto i = 0; i <= 2; ++i)  { miniBoundaries[i] = fBoundaries[i]; }
829                                                   839 
830     G4int voxelsCountMini = (fCountOfVoxels >=    840     G4int voxelsCountMini = (fCountOfVoxels >= 1000)
831                           ? 100 : G4int(fCount << 841                           ? 100 : fCountOfVoxels / 10;
832                                                   842 
833     SetReductionRatio(voxelsCountMini, reducti    843     SetReductionRatio(voxelsCountMini, reductionRatioMini);
834                                                   844 
835 #ifdef G4SPECSDEBUG                               845 #ifdef G4SPECSDEBUG
836     G4cout << "Building reduced voxels..." <<     846     G4cout << "Building reduced voxels..." << G4endl;
837 #endif                                            847 #endif
838                                                   848     
839     BuildReduceVoxels(miniBoundaries, reductio    849     BuildReduceVoxels(miniBoundaries, reductionRatioMini);
840                                                   850 
841 #ifdef G4SPECSDEBUG                               851 #ifdef G4SPECSDEBUG
842     G4int total = CountVoxels(miniBoundaries);    852     G4int total = CountVoxels(miniBoundaries);
843     G4cout << "Total number of mini voxels: "     853     G4cout << "Total number of mini voxels: " << total << G4endl;
844 #endif                                            854 #endif
845                                                   855 
846 #ifdef G4SPECSDEBUG                               856 #ifdef G4SPECSDEBUG
847     G4cout << "Building mini bitmasks..." << G    857     G4cout << "Building mini bitmasks..." << G4endl;
848 #endif                                            858 #endif
849                                                   859     
850     BuildBitmasks(miniBoundaries, bitmasksMini    860     BuildBitmasks(miniBoundaries, bitmasksMini);
851                                                   861 
852 #ifdef G4SPECSDEBUG                               862 #ifdef G4SPECSDEBUG
853     G4cout << "Creating Mini Voxels..." << G4e    863     G4cout << "Creating Mini Voxels..." << G4endl;
854 #endif                                            864 #endif
855                                                   865     
856     CreateMiniVoxels(miniBoundaries, bitmasksM    866     CreateMiniVoxels(miniBoundaries, bitmasksMini);
857                                                   867 
858 #ifdef G4SPECSDEBUG                               868 #ifdef G4SPECSDEBUG
859     G4cout << "Building bounding box..." << G4    869     G4cout << "Building bounding box..." << G4endl;
860 #endif                                            870 #endif
861                                                   871     
862     BuildBoundingBox();                           872     BuildBoundingBox();
863                                                   873 
864 #ifdef G4SPECSDEBUG                               874 #ifdef G4SPECSDEBUG
865     G4cout << "Building empty..." << G4endl;      875     G4cout << "Building empty..." << G4endl;
866 #endif                                            876 #endif
867                                                   877     
868     BuildEmpty();                                 878     BuildEmpty();
869                                                   879 
870 #ifdef G4SPECSDEBUG                               880 #ifdef G4SPECSDEBUG
871     G4cout << "Deallocating unnecessary fields    881     G4cout << "Deallocating unnecessary fields during runtime..." << G4endl;
872 #endif                                            882 #endif    
873     // deallocate fields unnecessary during ru    883     // deallocate fields unnecessary during runtime
874     //                                            884     //
875     fBoxes.resize(0);                             885     fBoxes.resize(0);
876     for (auto i = 0; i < 3; ++i)                  886     for (auto i = 0; i < 3; ++i)
877     {                                             887     {
878       fCandidatesCounts[i].resize(0);             888       fCandidatesCounts[i].resize(0);
879       fBitmasks[i].Clear();                       889       fBitmasks[i].Clear();
880     }                                             890     }
881   }                                               891   }
882 }                                                 892 }
883                                                   893 
884                                                   894 
885 //____________________________________________    895 //______________________________________________________________________________
886 void G4Voxelizer::GetCandidatesVoxel(std::vect    896 void G4Voxelizer::GetCandidatesVoxel(std::vector<G4int>& voxels)
887 {                                                 897 {
888   // "GetCandidates" should compute which soli    898   // "GetCandidates" should compute which solids are possibly contained in
889   // the voxel defined by the three slices cha    899   // the voxel defined by the three slices characterized by the passed indexes.
890                                                   900 
891   G4cout << "   Candidates in voxel [" << voxe    901   G4cout << "   Candidates in voxel [" << voxels[0] << " ; " << voxels[1]
892          << " ; " << voxels[2] << "]: ";          902          << " ; " << voxels[2] << "]: ";
893   std::vector<G4int> candidates;                  903   std::vector<G4int> candidates;
894   G4int count = GetCandidatesVoxelArray(voxels    904   G4int count = GetCandidatesVoxelArray(voxels, candidates);
895   G4cout << "[ ";                                 905   G4cout << "[ ";
896   for (G4int i = 0; i < count; ++i) G4cout <<     906   for (G4int i = 0; i < count; ++i) G4cout << candidates[i];
897   G4cout << "]  " << G4endl;                      907   G4cout << "]  " << G4endl;
898 }                                                 908 }
899                                                   909 
900 //____________________________________________    910 //______________________________________________________________________________
901 void G4Voxelizer::FindComponentsFastest(unsign    911 void G4Voxelizer::FindComponentsFastest(unsigned int mask,
902                                          std::    912                                          std::vector<G4int>& list, G4int i)
903 {                                                 913 {
904   for (G4int byte = 0; byte < (G4int) (sizeof(    914   for (G4int byte = 0; byte < (G4int) (sizeof(unsigned int)); ++byte)
905   {                                               915   {
906     if (G4int maskByte = mask & 0xFF)             916     if (G4int maskByte = mask & 0xFF)
907     {                                             917     {
908       for (G4int bit = 0; bit < 8; ++bit)         918       for (G4int bit = 0; bit < 8; ++bit)
909       {                                           919       {
910         if ((maskByte & 1) != 0)               << 920         if (maskByte & 1) 
911           { list.push_back(8*(sizeof(unsigned     921           { list.push_back(8*(sizeof(unsigned int)*i+ byte) + bit); }
912         if ((maskByte >>= 1) == 0) break;      << 922         if (!(maskByte >>= 1)) break;
913       }                                           923       }
914     }                                             924     }
915     mask >>= 8;                                   925     mask >>= 8;
916   }                                               926   }
917 }                                                 927 }
918                                                   928 
919 //____________________________________________    929 //______________________________________________________________________________
920 void G4Voxelizer::TransformLimits(G4ThreeVecto    930 void G4Voxelizer::TransformLimits(G4ThreeVector& min, G4ThreeVector& max,
921                                   const G4Tran    931                                   const G4Transform3D& transformation) const
922 {                                                 932 {
923   // The goal of this method is to convert the    933   // The goal of this method is to convert the quantities min and max
924   // (representing the bounding box of a given    934   // (representing the bounding box of a given solid in its local frame)
925   // to the main frame, using "transformation"    935   // to the main frame, using "transformation"
926                                                   936 
927   G4ThreeVector vertices[8] =     // Deteminat    937   G4ThreeVector vertices[8] =     // Detemination of the vertices thanks to
928   {                               // the exten    938   {                               // the extension of each solid:
929     G4ThreeVector(min.x(), min.y(), min.z()),     939     G4ThreeVector(min.x(), min.y(), min.z()), // 1st vertice:
930     G4ThreeVector(min.x(), max.y(), min.z()),     940     G4ThreeVector(min.x(), max.y(), min.z()), // 2nd vertice:
931     G4ThreeVector(max.x(), max.y(), min.z()),     941     G4ThreeVector(max.x(), max.y(), min.z()),
932     G4ThreeVector(max.x(), min.y(), min.z()),     942     G4ThreeVector(max.x(), min.y(), min.z()),
933     G4ThreeVector(min.x(), min.y(), max.z()),     943     G4ThreeVector(min.x(), min.y(), max.z()),
934     G4ThreeVector(min.x(), max.y(), max.z()),     944     G4ThreeVector(min.x(), max.y(), max.z()),
935     G4ThreeVector(max.x(), max.y(), max.z()),     945     G4ThreeVector(max.x(), max.y(), max.z()),
936     G4ThreeVector(max.x(), min.y(), max.z())      946     G4ThreeVector(max.x(), min.y(), max.z())
937   };                                              947   };
938                                                   948 
939   min.set(kInfinity,kInfinity,kInfinity);         949   min.set(kInfinity,kInfinity,kInfinity);
940   max.set(-kInfinity,-kInfinity,-kInfinity);      950   max.set(-kInfinity,-kInfinity,-kInfinity);
941                                                   951 
942   // Loop on th vertices                          952   // Loop on th vertices
943   G4int limit = sizeof(vertices) / sizeof(G4Th    953   G4int limit = sizeof(vertices) / sizeof(G4ThreeVector);
944   for (G4int i = 0 ; i < limit; ++i)              954   for (G4int i = 0 ; i < limit; ++i)
945   {                                               955   {
946     // From local frame to the global one:        956     // From local frame to the global one:
947     // Current positions on the three axis:       957     // Current positions on the three axis:
948     G4ThreeVector current = GetGlobalPoint(tra    958     G4ThreeVector current = GetGlobalPoint(transformation, vertices[i]);
949                                                   959 
950     // If need be, replacement of the min & ma    960     // If need be, replacement of the min & max values:
951     if (current.x() > max.x()) max.setX(curren    961     if (current.x() > max.x()) max.setX(current.x());
952     if (current.x() < min.x()) min.setX(curren    962     if (current.x() < min.x()) min.setX(current.x());
953                                                   963 
954     if (current.y() > max.y()) max.setY(curren    964     if (current.y() > max.y()) max.setY(current.y());
955     if (current.y() < min.y()) min.setY(curren    965     if (current.y() < min.y()) min.setY(current.y());
956                                                   966 
957     if (current.z() > max.z()) max.setZ(curren    967     if (current.z() > max.z()) max.setZ(current.z());
958     if (current.z() < min.z()) min.setZ(curren    968     if (current.z() < min.z()) min.setZ(current.z());
959   }                                               969   }
960 }                                                 970 }
961                                                   971 
962 //____________________________________________    972 //______________________________________________________________________________
963 G4int G4Voxelizer::GetCandidatesVoxelArray(con    973 G4int G4Voxelizer::GetCandidatesVoxelArray(const G4ThreeVector &point,
964                           std::vector<G4int> &    974                           std::vector<G4int> &list, G4SurfBits *crossed) const
965 {                                                 975 {
966   // Method returning the candidates correspon    976   // Method returning the candidates corresponding to the passed point
967                                                   977 
968   list.clear();                                   978   list.clear();
969                                                   979 
970   for (auto i = 0; i <= 2; ++i)                   980   for (auto i = 0; i <= 2; ++i)
971   {                                               981   {
972     if(point[i] < fBoundaries[i].front() || po    982     if(point[i] < fBoundaries[i].front() || point[i] >= fBoundaries[i].back()) 
973       return 0;                                   983       return 0;
974   }                                               984   }
975                                                   985 
976   if (fTotalCandidates == 1)                      986   if (fTotalCandidates == 1)
977   {                                               987   {
978     list.push_back(0);                            988     list.push_back(0);
979     return 1;                                     989     return 1;
980   }                                               990   } 
981   else                                            991   else
982   {                                               992   {
983     if (fNPerSlice == 1)                          993     if (fNPerSlice == 1)
984     {                                             994     {
985       unsigned int mask = 0xFFffFFff;             995       unsigned int mask = 0xFFffFFff;
986       G4int slice;                                996       G4int slice;
987       if (fBoundaries[0].size() > 2)              997       if (fBoundaries[0].size() > 2)
988       {                                           998       {
989         slice = BinarySearch(fBoundaries[0], p    999         slice = BinarySearch(fBoundaries[0], point.x());
990         if ((mask = ((unsigned int*) fBitmasks << 1000         if (!(mask = ((unsigned int*) fBitmasks[0].fAllBits)[slice]))
991           return 0;                               1001           return 0;
992       }                                           1002       }
993       if (fBoundaries[1].size() > 2)              1003       if (fBoundaries[1].size() > 2)
994       {                                           1004       {
995         slice = BinarySearch(fBoundaries[1], p    1005         slice = BinarySearch(fBoundaries[1], point.y());
996         if ((mask &= ((unsigned int*) fBitmask << 1006         if (!(mask &= ((unsigned int*) fBitmasks[1].fAllBits)[slice]))
997           return 0;                               1007           return 0;
998       }                                           1008       }
999       if (fBoundaries[2].size() > 2)              1009       if (fBoundaries[2].size() > 2)
1000       {                                          1010       {
1001         slice = BinarySearch(fBoundaries[2],     1011         slice = BinarySearch(fBoundaries[2], point.z());
1002         if ((mask &= ((unsigned int*) fBitmas << 1012         if (!(mask &= ((unsigned int*) fBitmasks[2].fAllBits)[slice]))
1003           return 0;                              1013           return 0;
1004       }                                          1014       }
1005       if ((crossed != nullptr) && ((mask &= ~ << 1015       if (crossed && (!(mask &= ~((unsigned int*)crossed->fAllBits)[0])))
1006         return 0;                                1016         return 0;
1007                                                  1017 
1008       FindComponentsFastest(mask, list, 0);      1018       FindComponentsFastest(mask, list, 0);
1009     }                                            1019     }
1010     else                                         1020     else
1011     {                                            1021     {
1012       unsigned int* masks[3], mask; // masks     1022       unsigned int* masks[3], mask; // masks for X,Y,Z axis
1013       for (auto i = 0; i <= 2; ++i)              1023       for (auto i = 0; i <= 2; ++i)
1014       {                                          1024       {
1015         G4int slice = BinarySearch(fBoundarie    1025         G4int slice = BinarySearch(fBoundaries[i], point[i]);
1016         masks[i] = ((unsigned int*) fBitmasks    1026         masks[i] = ((unsigned int*) fBitmasks[i].fAllBits)
1017                  + slice * fNPerSlice;           1027                  + slice * fNPerSlice;
1018       }                                          1028       }
1019       unsigned int* maskCrossed = crossed !=  << 1029       unsigned int* maskCrossed = crossed
1020                                 ? (unsigned i << 1030                                 ? (unsigned int*)crossed->fAllBits : 0;
1021                                                  1031 
1022       for (G4int i = 0 ; i < fNPerSlice; ++i)    1032       for (G4int i = 0 ; i < fNPerSlice; ++i)
1023       {                                          1033       {
1024         // Logic "and" of the masks along the    1034         // Logic "and" of the masks along the 3 axes x, y, z:
1025         // removing "if (!" and ") continue"     1035         // removing "if (!" and ") continue" => slightly slower
1026         //                                       1036         //
1027         if ((mask = masks[0][i]) == 0u) conti << 1037         if (!(mask = masks[0][i])) continue;
1028         if ((mask &= masks[1][i]) == 0u) cont << 1038         if (!(mask &= masks[1][i])) continue;
1029         if ((mask &= masks[2][i]) == 0u) cont << 1039         if (!(mask &= masks[2][i])) continue;
1030         if ((maskCrossed != nullptr) && ((mas << 1040         if (maskCrossed && !(mask &= ~maskCrossed[i])) continue;
1031                                                  1041 
1032         FindComponentsFastest(mask, list, i);    1042         FindComponentsFastest(mask, list, i);
1033       }                                          1043       }
1034     }                                            1044     }
1035 /*                                               1045 /*
1036     if (fNPerSlice == 1)                         1046     if (fNPerSlice == 1)
1037     {                                            1047     {
1038       unsigned int mask;                         1048       unsigned int mask;
1039       G4int slice = BinarySearch(fBoundaries[    1049       G4int slice = BinarySearch(fBoundaries[0], point.x()); 
1040       if (!(mask = ((unsigned int *) fBitmask    1050       if (!(mask = ((unsigned int *) fBitmasks[0].fAllBits)[slice]
1041       )) return 0;                               1051       )) return 0;
1042       slice = BinarySearch(fBoundaries[1], po    1052       slice = BinarySearch(fBoundaries[1], point.y());
1043       if (!(mask &= ((unsigned int *) fBitmas    1053       if (!(mask &= ((unsigned int *) fBitmasks[1].fAllBits)[slice]
1044       )) return 0;                               1054       )) return 0;
1045       slice = BinarySearch(fBoundaries[2], po    1055       slice = BinarySearch(fBoundaries[2], point.z());
1046       if (!(mask &= ((unsigned int *) fBitmas    1056       if (!(mask &= ((unsigned int *) fBitmasks[2].fAllBits)[slice]
1047       )) return 0;                               1057       )) return 0;
1048       if (crossed && (!(mask &= ~((unsigned i    1058       if (crossed && (!(mask &= ~((unsigned int *)crossed->fAllBits)[0])))
1049         return 0;                                1059         return 0;
1050                                                  1060 
1051       FindComponentsFastest(mask, list, 0);      1061       FindComponentsFastest(mask, list, 0);
1052     }                                            1062     }
1053     else                                         1063     else
1054     {                                            1064     {
1055       unsigned int *masks[3], mask; // masks     1065       unsigned int *masks[3], mask; // masks for X,Y,Z axis
1056       for (auto i = 0; i <= 2; ++i)              1066       for (auto i = 0; i <= 2; ++i)
1057       {                                          1067       {
1058         G4int slice = BinarySearch(fBoundarie    1068         G4int slice = BinarySearch(fBoundaries[i], point[i]); 
1059         masks[i] = ((unsigned int *) fBitmask    1069         masks[i] = ((unsigned int *) fBitmasks[i].fAllBits) + slice*fNPerSlice;
1060       }                                          1070       }
1061       unsigned int *maskCrossed =                1071       unsigned int *maskCrossed =
1062         crossed ? (unsigned int *)crossed->fA    1072         crossed ? (unsigned int *)crossed->fAllBits : 0;
1063                                                  1073 
1064       for (G4int i = 0 ; i < fNPerSlice; ++i)    1074       for (G4int i = 0 ; i < fNPerSlice; ++i)
1065       {                                          1075       {
1066         // Logic "and" of the masks along the    1076         // Logic "and" of the masks along the 3 axes x, y, z:
1067         // removing "if (!" and ") continue"     1077         // removing "if (!" and ") continue" => slightly slower
1068         //                                       1078         //
1069         if (!(mask = masks[0][i])) continue;     1079         if (!(mask = masks[0][i])) continue;
1070         if (!(mask &= masks[1][i])) continue;    1080         if (!(mask &= masks[1][i])) continue;
1071         if (!(mask &= masks[2][i])) continue;    1081         if (!(mask &= masks[2][i])) continue;
1072         if (maskCrossed && !(mask &= ~maskCro    1082         if (maskCrossed && !(mask &= ~maskCrossed[i])) continue;
1073                                                  1083 
1074         FindComponentsFastest(mask, list, i);    1084         FindComponentsFastest(mask, list, i);
1075       }                                          1085       }
1076     }                                            1086     }
1077 */                                               1087 */
1078   }                                              1088   }
1079   return (G4int)list.size();                  << 1089   return list.size();
1080 }                                                1090 }
1081                                                  1091 
1082 //___________________________________________    1092 //______________________________________________________________________________
1083 G4int                                            1093 G4int
1084 G4Voxelizer::GetCandidatesVoxelArray(const st    1094 G4Voxelizer::GetCandidatesVoxelArray(const std::vector<G4int>& voxels,
1085                                      const G4    1095                                      const G4SurfBits bitmasks[],
1086                                      std::vec    1096                                      std::vector<G4int>& list,
1087                                      G4SurfBi    1097                                      G4SurfBits* crossed) const
1088 {                                                1098 {
1089   list.clear();                                  1099   list.clear();
1090                                                  1100 
1091   if (fTotalCandidates == 1)                     1101   if (fTotalCandidates == 1)
1092   {                                              1102   {
1093     list.push_back(0);                           1103     list.push_back(0);
1094     return 1;                                    1104     return 1;
1095   }                                              1105   }
1096   else                                           1106   else
1097   {                                              1107   {
1098     if (fNPerSlice == 1)                         1108     if (fNPerSlice == 1)
1099     {                                            1109     {
1100       unsigned int mask;                         1110       unsigned int mask;
1101       if ((mask = ((unsigned int *) bitmasks[ << 1111       if (!(mask = ((unsigned int *) bitmasks[0].fAllBits)[voxels[0]]))
1102         return 0;                                1112         return 0;
1103       if ((mask &= ((unsigned int *) bitmasks << 1113       if (!(mask &= ((unsigned int *) bitmasks[1].fAllBits)[voxels[1]]))
1104         return 0;                                1114         return 0;
1105       if ((mask &= ((unsigned int *) bitmasks << 1115       if (!(mask &= ((unsigned int *) bitmasks[2].fAllBits)[voxels[2]]))
1106         return 0;                                1116         return 0;
1107       if ((crossed != nullptr) && ((mask &= ~ << 1117       if (crossed && (!(mask &= ~((unsigned int *)crossed->fAllBits)[0])))
1108         return 0;                                1118         return 0;
1109                                                  1119 
1110       FindComponentsFastest(mask, list, 0);      1120       FindComponentsFastest(mask, list, 0);
1111     }                                            1121     }
1112     else                                         1122     else
1113     {                                            1123     {
1114       unsigned int *masks[3], mask; // masks     1124       unsigned int *masks[3], mask; // masks for X,Y,Z axis
1115       for (auto i = 0; i <= 2; ++i)              1125       for (auto i = 0; i <= 2; ++i)
1116       {                                          1126       {
1117         masks[i] = ((unsigned int *) bitmasks    1127         masks[i] = ((unsigned int *) bitmasks[i].fAllBits)
1118                  + voxels[i]*fNPerSlice;         1128                  + voxels[i]*fNPerSlice;
1119       }                                          1129       }
1120       unsigned int *maskCrossed = crossed !=     1130       unsigned int *maskCrossed = crossed != nullptr
1121                                 ? (unsigned i << 1131                                 ? (unsigned int *)crossed->fAllBits : 0;
1122                                                  1132 
1123       for (G4int i = 0 ; i < fNPerSlice; ++i)    1133       for (G4int i = 0 ; i < fNPerSlice; ++i)
1124       {                                          1134       {
1125         // Logic "and" of the masks along the    1135         // Logic "and" of the masks along the 3 axes x, y, z:
1126         // removing "if (!" and ") continue"     1136         // removing "if (!" and ") continue" => slightly slower
1127         //                                       1137         //
1128         if ((mask = masks[0][i]) == 0u) conti << 1138         if (!(mask = masks[0][i])) continue;
1129         if ((mask &= masks[1][i]) == 0u) cont << 1139         if (!(mask &= masks[1][i])) continue;
1130         if ((mask &= masks[2][i]) == 0u) cont << 1140         if (!(mask &= masks[2][i])) continue;
1131         if ((maskCrossed != nullptr) && ((mas << 1141         if (maskCrossed && !(mask &= ~maskCrossed[i])) continue;
1132                                                  1142 
1133         FindComponentsFastest(mask, list, i);    1143         FindComponentsFastest(mask, list, i);
1134       }                                          1144       }
1135     }                                            1145     }
1136   }                                              1146   }
1137   return (G4int)list.size();                  << 1147   return list.size();
1138 }                                                1148 }
1139                                                  1149 
1140 //___________________________________________    1150 //______________________________________________________________________________
1141 G4int                                            1151 G4int
1142 G4Voxelizer::GetCandidatesVoxelArray(const st    1152 G4Voxelizer::GetCandidatesVoxelArray(const std::vector<G4int>& voxels,
1143                           std::vector<G4int>&    1153                           std::vector<G4int>& list, G4SurfBits* crossed) const
1144 {                                                1154 {
1145   // Method returning the candidates correspo    1155   // Method returning the candidates corresponding to the passed point
1146                                                  1156 
1147   return GetCandidatesVoxelArray(voxels, fBit    1157   return GetCandidatesVoxelArray(voxels, fBitmasks, list, crossed);
1148 }                                                1158 }
1149                                                  1159 
1150 //___________________________________________    1160 //______________________________________________________________________________
1151 G4bool G4Voxelizer::Contains(const G4ThreeVec    1161 G4bool G4Voxelizer::Contains(const G4ThreeVector& point) const
1152 {                                                1162 {
1153   for (auto i = 0; i < 3; ++i)                   1163   for (auto i = 0; i < 3; ++i)
1154   {                                              1164   {
1155     if (point[i] < fBoundaries[i].front() ||     1165     if (point[i] < fBoundaries[i].front() || point[i] > fBoundaries[i].back())
1156       return false;                              1166       return false;
1157   }                                              1167   }
1158   return true;                                   1168   return true;
1159 }                                                1169 }
1160                                                  1170 
1161 //___________________________________________    1171 //______________________________________________________________________________
1162 G4double                                         1172 G4double
1163 G4Voxelizer::DistanceToFirst(const G4ThreeVec    1173 G4Voxelizer::DistanceToFirst(const G4ThreeVector& point,
1164                              const G4ThreeVec    1174                              const G4ThreeVector& direction) const
1165 {                                                1175 {
1166   G4ThreeVector pointShifted = point - fBound    1176   G4ThreeVector pointShifted = point - fBoundingBoxCenter;
1167   G4double shift = fBoundingBox.DistanceToIn(    1177   G4double shift = fBoundingBox.DistanceToIn(pointShifted, direction);
1168   return shift;                                  1178   return shift;
1169 }                                                1179 }
1170                                                  1180 
1171 //___________________________________________    1181 //______________________________________________________________________________
1172 G4double                                         1182 G4double
1173 G4Voxelizer::DistanceToBoundingBox(const G4Th    1183 G4Voxelizer::DistanceToBoundingBox(const G4ThreeVector& point) const
1174 {                                                1184 {
1175   G4ThreeVector pointShifted = point - fBound    1185   G4ThreeVector pointShifted = point - fBoundingBoxCenter;
1176   G4double shift = MinDistanceToBox(pointShif    1186   G4double shift = MinDistanceToBox(pointShifted, fBoundingBoxSize);
1177   return shift;                                  1187   return shift;
1178 }                                                1188 }
1179                                                  1189 
1180 //___________________________________________    1190 //______________________________________________________________________________
1181 G4double                                         1191 G4double
1182 G4Voxelizer::MinDistanceToBox (const G4ThreeV    1192 G4Voxelizer::MinDistanceToBox (const G4ThreeVector& aPoint,
1183                                const G4ThreeV    1193                                const G4ThreeVector& f)
1184 {                                                1194 {
1185   // Estimates the isotropic safety from a po    1195   // Estimates the isotropic safety from a point outside the current solid to
1186   // any of its surfaces. The algorithm may b    1196   // any of its surfaces. The algorithm may be accurate or should provide a
1187   // fast underestimate.                         1197   // fast underestimate.
1188                                                  1198 
1189   G4double safe, safx, safy, safz;               1199   G4double safe, safx, safy, safz;
1190   safe = safx = -f.x() + std::abs(aPoint.x())    1200   safe = safx = -f.x() + std::abs(aPoint.x());
1191   safy = -f.y() + std::abs(aPoint.y());          1201   safy = -f.y() + std::abs(aPoint.y());
1192   if ( safy > safe ) safe = safy;                1202   if ( safy > safe ) safe = safy;
1193   safz = -f.z() + std::abs(aPoint.z());          1203   safz = -f.z() + std::abs(aPoint.z());
1194   if ( safz > safe ) safe = safz;                1204   if ( safz > safe ) safe = safz;
1195   if (safe < 0.0) return 0.0; // point is ins    1205   if (safe < 0.0) return 0.0; // point is inside
1196                                                  1206 
1197   G4double safsq = 0.0;                          1207   G4double safsq = 0.0;
1198   G4int count = 0;                               1208   G4int count = 0;
1199   if ( safx > 0 ) { safsq += safx*safx; ++cou    1209   if ( safx > 0 ) { safsq += safx*safx; ++count; }
1200   if ( safy > 0 ) { safsq += safy*safy; ++cou    1210   if ( safy > 0 ) { safsq += safy*safy; ++count; }
1201   if ( safz > 0 ) { safsq += safz*safz; ++cou    1211   if ( safz > 0 ) { safsq += safz*safz; ++count; }
1202   if (count == 1) return safe;                   1212   if (count == 1) return safe;
1203   return std::sqrt(safsq);                       1213   return std::sqrt(safsq);
1204 }                                                1214 }
1205                                                  1215 
1206 //___________________________________________    1216 //______________________________________________________________________________
1207 G4double                                         1217 G4double
1208 G4Voxelizer::DistanceToNext(const G4ThreeVect    1218 G4Voxelizer::DistanceToNext(const G4ThreeVector& point,
1209                             const G4ThreeVect    1219                             const G4ThreeVector& direction,
1210                                   std::vector    1220                                   std::vector<G4int>& curVoxel) const
1211 {                                                1221 {
1212   G4double shift = kInfinity;                    1222   G4double shift = kInfinity;
1213                                                  1223 
1214   G4int cur = 0; // the smallest index, which    1224   G4int cur = 0; // the smallest index, which would be than increased
1215   for (G4int i = 0; i <= 2; ++i)                 1225   for (G4int i = 0; i <= 2; ++i)
1216   {                                              1226   {
1217     // Looking for the next voxels on the con    1227     // Looking for the next voxels on the considered direction X,Y,Z axis
1218     //                                           1228     //
1219     const std::vector<G4double>& boundary = f    1229     const std::vector<G4double>& boundary = fBoundaries[i];
1220     G4int index = curVoxel[i];                   1230     G4int index = curVoxel[i];
1221     if (direction[i] >= 1e-10)                   1231     if (direction[i] >= 1e-10)
1222     {                                            1232     {
1223       ++index;                                   1233       ++index;
1224     }                                            1234     }
1225     else                                         1235     else
1226     {                                            1236     {
1227       if (direction[i] > -1e-10)                 1237       if (direction[i] > -1e-10)
1228         continue;                                1238         continue;
1229     }                                            1239     }
1230     G4double dif = boundary[index] - point[i]    1240     G4double dif = boundary[index] - point[i];
1231     G4double distance = dif / direction[i];      1241     G4double distance = dif / direction[i];
1232                                                  1242 
1233     if (shift > distance)                        1243     if (shift > distance)
1234     {                                            1244     {
1235       shift = distance;                          1245       shift = distance;
1236       cur = i;                                   1246       cur = i;
1237     }                                            1247     }
1238   }                                              1248   }
1239                                                  1249 
1240   if (shift != kInfinity)                        1250   if (shift != kInfinity)
1241   {                                              1251   {
1242     // updating current voxel using the index    1252     // updating current voxel using the index corresponding
1243     // to the closest voxel boundary on the r    1253     // to the closest voxel boundary on the ray
1244                                                  1254 
1245     if (direction[cur] > 0)                      1255     if (direction[cur] > 0)
1246     {                                            1256     {
1247       if (++curVoxel[cur] >= (G4int) fBoundar    1257       if (++curVoxel[cur] >= (G4int) fBoundaries[cur].size() - 1)
1248         shift = kInfinity;                       1258         shift = kInfinity;
1249     }                                            1259     }
1250     else                                         1260     else
1251     {                                            1261     {
1252       if (--curVoxel[cur] < 0)                   1262       if (--curVoxel[cur] < 0)
1253         shift = kInfinity;                       1263         shift = kInfinity;
1254     }                                            1264     }
1255   }                                              1265   }
1256                                                  1266 
1257 /*                                               1267 /*
1258   for (auto i = 0; i <= 2; ++i)                  1268   for (auto i = 0; i <= 2; ++i)
1259   {                                              1269   {
1260     // Looking for the next voxels on the con    1270     // Looking for the next voxels on the considered direction X,Y,Z axis
1261     //                                           1271     //
1262     const std::vector<G4double> &boundary = f    1272     const std::vector<G4double> &boundary = fBoundaries[i];
1263     G4int cur = curVoxel[i];                     1273     G4int cur = curVoxel[i];
1264     if(direction[i] >= 1e-10)                    1274     if(direction[i] >= 1e-10)
1265     {                                            1275     {
1266         if (boundary[++cur] - point[i] < fTol    1276         if (boundary[++cur] - point[i] < fTolerance) // make sure shift would
1267         if (++cur >= (G4int) boundary.size())    1277         if (++cur >= (G4int) boundary.size())      // be non-zero
1268           continue;                              1278           continue;
1269     }                                            1279     }
1270     else                                         1280     else 
1271     {                                            1281     {
1272       if(direction[i] <= -1e-10)                 1282       if(direction[i] <= -1e-10) 
1273       {                                          1283       {
1274         if (point[i] - boundary[cur] < fToler    1284         if (point[i] - boundary[cur] < fTolerance) // make sure shift would
1275           if (--cur < 0)                         1285           if (--cur < 0)                           // be non-zero
1276             continue;                            1286             continue;
1277       }                                          1287       }
1278       else                                       1288       else 
1279         continue;                                1289         continue;
1280     }                                            1290     }
1281     G4double dif = boundary[cur] - point[i];     1291     G4double dif = boundary[cur] - point[i];
1282     G4double distance = dif / direction[i];      1292     G4double distance = dif / direction[i];
1283                                                  1293 
1284     if (shift > distance)                        1294     if (shift > distance) 
1285       shift = distance;                          1295       shift = distance;
1286   }                                              1296   }
1287 */                                               1297 */
1288   return shift;                                  1298   return shift;
1289 }                                                1299 }
1290                                                  1300 
1291 //___________________________________________    1301 //______________________________________________________________________________
1292 G4bool                                           1302 G4bool
1293 G4Voxelizer::UpdateCurrentVoxel(const G4Three    1303 G4Voxelizer::UpdateCurrentVoxel(const G4ThreeVector& point,
1294                                 const G4Three    1304                                 const G4ThreeVector& direction,
1295                                 std::vector<G    1305                                 std::vector<G4int>& curVoxel) const
1296 {                                                1306 {
1297   for (auto i = 0; i <= 2; ++i)                  1307   for (auto i = 0; i <= 2; ++i)
1298   {                                              1308   {
1299     G4int index = curVoxel[i];                   1309     G4int index = curVoxel[i];
1300     const std::vector<G4double> &boundary = f    1310     const std::vector<G4double> &boundary = fBoundaries[i];
1301                                                  1311 
1302     if (direction[i] > 0)                        1312     if (direction[i] > 0) 
1303     {                                            1313     {
1304       if (point[i] >= boundary[++index])         1314       if (point[i] >= boundary[++index]) 
1305         if (++curVoxel[i] >= (G4int) boundary    1315         if (++curVoxel[i] >= (G4int) boundary.size() - 1)
1306           return false;                          1316           return false;
1307     }                                            1317     }
1308     else                                         1318     else
1309     {                                            1319     {
1310       if (point[i] < boundary[index])            1320       if (point[i] < boundary[index]) 
1311         if (--curVoxel[i] < 0)                   1321         if (--curVoxel[i] < 0) 
1312           return false;                          1322           return false;
1313     }                                            1323     }
1314 #ifdef G4SPECSDEBUG                              1324 #ifdef G4SPECSDEBUG
1315     G4int indexOK = BinarySearch(boundary, po    1325     G4int indexOK = BinarySearch(boundary, point[i]);
1316     if (curVoxel[i] != indexOK)                  1326     if (curVoxel[i] != indexOK)
1317       curVoxel[i] = indexOK; // put breakpoin    1327       curVoxel[i] = indexOK; // put breakpoint here
1318 #endif                                           1328 #endif
1319   }                                              1329   }
1320   return true;                                   1330   return true;
1321 }                                                1331 }
1322                                                  1332 
1323 //___________________________________________    1333 //______________________________________________________________________________
1324 void G4Voxelizer::SetMaxVoxels(G4int max)        1334 void G4Voxelizer::SetMaxVoxels(G4int max)
1325 {                                                1335 {
1326   fMaxVoxels = max;                              1336   fMaxVoxels = max;
1327   fReductionRatio.set(0,0,0);                    1337   fReductionRatio.set(0,0,0);
1328 }                                                1338 }
1329                                                  1339 
1330 //___________________________________________    1340 //______________________________________________________________________________
1331 void G4Voxelizer::SetMaxVoxels(const G4ThreeV    1341 void G4Voxelizer::SetMaxVoxels(const G4ThreeVector& ratioOfReduction)
1332 {                                                1342 {
1333   fMaxVoxels = -1;                               1343   fMaxVoxels = -1;
1334   fReductionRatio = ratioOfReduction;            1344   fReductionRatio = ratioOfReduction;
1335 }                                                1345 }
1336                                                  1346 
1337 //___________________________________________    1347 //______________________________________________________________________________
1338 void G4Voxelizer::SetDefaultVoxelsCount(G4int    1348 void G4Voxelizer::SetDefaultVoxelsCount(G4int count)
1339 {                                                1349 {
1340   fDefaultVoxelsCount = count;                   1350   fDefaultVoxelsCount = count;
1341 }                                                1351 }
1342                                                  1352 
1343 //___________________________________________    1353 //______________________________________________________________________________
1344 G4int G4Voxelizer::GetDefaultVoxelsCount()       1354 G4int G4Voxelizer::GetDefaultVoxelsCount()
1345 {                                                1355 {
1346   return fDefaultVoxelsCount;                    1356   return fDefaultVoxelsCount;
1347 }                                                1357 }
1348                                                  1358 
1349 //___________________________________________    1359 //______________________________________________________________________________
1350 G4int G4Voxelizer::AllocatedMemory()             1360 G4int G4Voxelizer::AllocatedMemory()
1351 {                                                1361 {
1352   G4int size = fEmpty.GetNbytes();               1362   G4int size = fEmpty.GetNbytes();
1353   size += fBoxes.capacity() * sizeof(G4VoxelB    1363   size += fBoxes.capacity() * sizeof(G4VoxelBox);
1354   size += sizeof(G4double) * (fBoundaries[0].    1364   size += sizeof(G4double) * (fBoundaries[0].capacity()
1355         + fBoundaries[1].capacity() + fBounda    1365         + fBoundaries[1].capacity() + fBoundaries[2].capacity());
1356   size += sizeof(G4int) * (fCandidatesCounts[    1366   size += sizeof(G4int) * (fCandidatesCounts[0].capacity()
1357         + fCandidatesCounts[1].capacity() + f    1367         + fCandidatesCounts[1].capacity() + fCandidatesCounts[2].capacity());
1358   size += fBitmasks[0].GetNbytes() + fBitmask    1368   size += fBitmasks[0].GetNbytes() + fBitmasks[1].GetNbytes()
1359         + fBitmasks[2].GetNbytes();              1369         + fBitmasks[2].GetNbytes();
1360                                                  1370 
1361   auto csize = (G4int)fCandidates.size();     << 1371   G4int csize = fCandidates.size();
1362   for (G4int i = 0; i < csize; ++i)              1372   for (G4int i = 0; i < csize; ++i)
1363   {                                              1373   {
1364     size += sizeof(vector<G4int>) + fCandidat    1374     size += sizeof(vector<G4int>) + fCandidates[i].capacity() * sizeof(G4int);
1365   }                                              1375   }
1366                                                  1376 
1367   return size;                                   1377   return size;
1368 }                                                1378 }
1369                                                  1379