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 11.1)


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