Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/management/src/G4SmartVoxelHeader.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/management/src/G4SmartVoxelHeader.cc (Version 11.3.0) and /geometry/management/src/G4SmartVoxelHeader.cc (Version 8.1.p1)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 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 //
                                                   >>  26 //
                                                   >>  27 // $Id: G4SmartVoxelHeader.cc,v 1.28 2006/06/29 18:33:42 gunter Exp $
                                                   >>  28 // GEANT4 tag $Name: geant4-08-01-patch-01 $
                                                   >>  29 //
 25 //                                                 30 // 
 26 // class G4SmartVoxelHeader implementation     <<  31 // class G4SmartVoxelHeader
                                                   >>  32 //
                                                   >>  33 // Implementation
 27 //                                                 34 //
 28 // Define G4GEOMETRY_VOXELDEBUG for debugging      35 // Define G4GEOMETRY_VOXELDEBUG for debugging information on G4cout
 29 //                                                 36 //
                                                   >>  37 // History:
 30 // 29.04.02 Use 3D voxelisation for non consum     38 // 29.04.02 Use 3D voxelisation for non consuming replication - G.C.
 31 // 18.04.01 Migrated to STL vector - G.C.          39 // 18.04.01 Migrated to STL vector - G.C.
 32 // 12.02.99 Introduction of new quality/smartl <<  40 // 12.02.99 Introduction of new quality/smartless: max for (slices/candid) S.G.
 33 // 11.02.99 Voxels at lower levels are now bui <<  41 // 11.02.99 Voxels at lower levels are now built for collapsed slices      S.G.
 34 // 21.07.95 Full implementation, supporting no <<  42 // 21.07.95 Full implementation, supporting non divided physical volumes
 35 // 14.07.95 Initial version - stubb definition <<  43 // 14.07.95 Initial version - stubb definitions only
 36 // -------------------------------------------     44 // --------------------------------------------------------------------
 37                                                    45 
 38 #include "G4SmartVoxelHeader.hh"                   46 #include "G4SmartVoxelHeader.hh"
 39                                                    47 
 40 #include "G4ios.hh"                                48 #include "G4ios.hh"
 41                                                    49 
 42 #include "G4LogicalVolume.hh"                      50 #include "G4LogicalVolume.hh"
 43 #include "G4VPhysicalVolume.hh"                    51 #include "G4VPhysicalVolume.hh"
 44 #include "G4VoxelLimits.hh"                        52 #include "G4VoxelLimits.hh"
 45                                                    53 
 46 #include "voxeldefs.hh"                            54 #include "voxeldefs.hh"
 47 #include "G4AffineTransform.hh"                    55 #include "G4AffineTransform.hh"
 48 #include "G4VSolid.hh"                             56 #include "G4VSolid.hh"
 49 #include "G4VPVParameterisation.hh"                57 #include "G4VPVParameterisation.hh"
 50                                                    58 
 51 // *******************************************     59 // ***************************************************************************
 52 // Constructor for topmost header, to begin vo     60 // Constructor for topmost header, to begin voxel construction at a
 53 // given logical volume.                           61 // given logical volume.
 54 // Constructs target List of volumes, calls "B     62 // Constructs target List of volumes, calls "Build and refine" constructor.
 55 // Assumes all daughters represent single volu     63 // Assumes all daughters represent single volumes (ie. no divisions
 56 // or parametric)                                  64 // or parametric)
 57 // *******************************************     65 // ***************************************************************************
 58 //                                                 66 //
 59 G4SmartVoxelHeader::G4SmartVoxelHeader(G4Logic     67 G4SmartVoxelHeader::G4SmartVoxelHeader(G4LogicalVolume* pVolume,
 60                                        G4int p     68                                        G4int pSlice)
 61   : fminEquivalent(pSlice),                        69   : fminEquivalent(pSlice),
 62     fmaxEquivalent(pSlice),                        70     fmaxEquivalent(pSlice),
 63     fparamAxis(kUndefined)                         71     fparamAxis(kUndefined)
 64 {                                                  72 {
 65   std::size_t nDaughters = pVolume->GetNoDaugh <<  73   G4int nDaughters = pVolume->GetNoDaughters();
                                                   >>  74   G4VoxelLimits limits;   // Create `unlimited' limits object
 66                                                    75 
 67   // Determine whether daughter is replicated      76   // Determine whether daughter is replicated
 68   //                                               77   //
 69   if ((nDaughters!=1) || (!pVolume->GetDaughte     78   if ((nDaughters!=1) || (!pVolume->GetDaughter(0)->IsReplicated()))
 70   {                                                79   {
 71     // Daughter not replicated => conventional     80     // Daughter not replicated => conventional voxel Build
 72     // where each daughters extents are comput     81     // where each daughters extents are computed
 73     //                                             82     //
 74     BuildVoxels(pVolume);                          83     BuildVoxels(pVolume);
 75   }                                                84   }
 76   else                                             85   else
 77   {                                                86   {
 78     // Single replicated daughter                  87     // Single replicated daughter
 79     //                                             88     //
 80     BuildReplicaVoxels(pVolume);                   89     BuildReplicaVoxels(pVolume);
 81   }                                                90   }
 82 }                                                  91 }
 83                                                    92 
 84 // *******************************************     93 // ***************************************************************************
 85 // Protected constructor:                          94 // Protected constructor:
 86 // builds and refines voxels between specified     95 // builds and refines voxels between specified limits, considering only
 87 // the physical volumes numbered `pCandidates'     96 // the physical volumes numbered `pCandidates'. `pSlice' is used to set max
 88 // and min equivalent slice nos for the header     97 // and min equivalent slice nos for the header - they apply to the level
 89 // of the header, not its nodes.                   98 // of the header, not its nodes.
 90 // *******************************************     99 // ***************************************************************************
 91 //                                                100 //
 92 G4SmartVoxelHeader::G4SmartVoxelHeader(G4Logic    101 G4SmartVoxelHeader::G4SmartVoxelHeader(G4LogicalVolume* pVolume,
 93                                  const G4Voxel    102                                  const G4VoxelLimits& pLimits,
 94                                  const G4Volum    103                                  const G4VolumeNosVector* pCandidates,
 95                                        G4int p    104                                        G4int pSlice)
 96   : fminEquivalent(pSlice),                       105   : fminEquivalent(pSlice),
 97     fmaxEquivalent(pSlice),                       106     fmaxEquivalent(pSlice),
 98     fparamAxis(kUndefined)                        107     fparamAxis(kUndefined)
 99 {                                                 108 {
100 #ifdef G4GEOMETRY_VOXELDEBUG                      109 #ifdef G4GEOMETRY_VOXELDEBUG
101   G4cout << "**** G4SmartVoxelHeader::G4SmartV    110   G4cout << "**** G4SmartVoxelHeader::G4SmartVoxelHeader" << G4endl
102          << "     Limits " << pLimits << G4end    111          << "     Limits " << pLimits << G4endl
103          << "     Candidate #s = " ;              112          << "     Candidate #s = " ;
104   for (auto i=0; i<pCandidates->size(); ++i)   << 113   for (size_t i=0;i<pCandidates->size();i++)
105   {                                               114   {
106     G4cout << (*pCandidates)[i] << " ";           115     G4cout << (*pCandidates)[i] << " ";
107   }                                               116   }
108   G4cout << G4endl;                               117   G4cout << G4endl;
109 #endif                                            118 #endif   
110                                                   119 
111   BuildVoxelsWithinLimits(pVolume,pLimits,pCan    120   BuildVoxelsWithinLimits(pVolume,pLimits,pCandidates);
112 }                                                 121 }
113                                                   122 
114 // *******************************************    123 // ***************************************************************************
115 // Destructor:                                    124 // Destructor:
116 // deletes all proxies and underlying objects.    125 // deletes all proxies and underlying objects.
117 // *******************************************    126 // ***************************************************************************
118 //                                                127 //
119 G4SmartVoxelHeader::~G4SmartVoxelHeader()         128 G4SmartVoxelHeader::~G4SmartVoxelHeader()
120 {                                                 129 {
121   // Manually destroy underlying nodes/headers    130   // Manually destroy underlying nodes/headers
122   // Delete collected headers and nodes once o    131   // Delete collected headers and nodes once only
123   //                                              132   //
124   std::size_t node, proxy, maxNode=fslices.siz << 133   G4int node, proxy, maxNode=fslices.size();
125   G4SmartVoxelProxy* lastProxy = nullptr;      << 134   G4SmartVoxelProxy *lastProxy=0;
126   G4SmartVoxelNode *dyingNode, *lastNode=nullp << 135   G4SmartVoxelNode *dyingNode, *lastNode=0;
127   G4SmartVoxelHeader *dyingHeader, *lastHeader << 136   G4SmartVoxelHeader *dyingHeader, *lastHeader=0;
128                                                   137 
129   for (node=0; node<maxNode; ++node)           << 138   for (node=0; node<maxNode; node++)
130   {                                               139   {
131     if (fslices[node]->IsHeader())                140     if (fslices[node]->IsHeader())
132     {                                             141     {
133       dyingHeader = fslices[node]->GetHeader()    142       dyingHeader = fslices[node]->GetHeader();
134       if (lastHeader != dyingHeader)           << 143       if (lastHeader!=dyingHeader)
135       {                                           144       {
136         lastHeader = dyingHeader;                 145         lastHeader = dyingHeader;
137         lastNode = nullptr;                    << 146         lastNode = 0;
138         delete dyingHeader;                       147         delete dyingHeader;
139       }                                           148       }
140     }                                             149     }
141     else                                       << 150       else
142     {                                             151     {
143       dyingNode = fslices[node]->GetNode();       152       dyingNode = fslices[node]->GetNode();
144       if (dyingNode != lastNode)               << 153       if (dyingNode!=lastNode)
145       {                                           154       {
146         lastNode = dyingNode;                  << 155         lastNode=dyingNode;
147         lastHeader = nullptr;                  << 156         lastHeader=0;
148         delete dyingNode;                         157         delete dyingNode;
149       }                                           158       }
150     }                                             159     }
151   }                                               160   }
152   // Delete proxies                               161   // Delete proxies
153   //                                              162   //
154   for (proxy=0; proxy<maxNode; ++proxy)        << 163   for (proxy=0; proxy<maxNode; proxy++)
155   {                                               164   {
156     if (fslices[proxy] != lastProxy)           << 165     if (fslices[proxy]!=lastProxy)
157     {                                             166     {
158       lastProxy = fslices[proxy];                 167       lastProxy = fslices[proxy];
159       delete lastProxy;                           168       delete lastProxy;
160     }                                             169     }
161   }                                               170   }
162   // Don't need to clear slices                   171   // Don't need to clear slices
163   // fslices.clear();                             172   // fslices.clear();
164 }                                                 173 }
165                                                   174 
166 // *******************************************    175 // ***************************************************************************
167 // Equality operator: returns true if contents    176 // Equality operator: returns true if contents are equivalent.
168 // Implies a deep search through contained nod    177 // Implies a deep search through contained nodes/header.
169 // Compares headers' axes,sizes,extents. Retur    178 // Compares headers' axes,sizes,extents. Returns false if different.
170 // For each contained proxy, determines whethe    179 // For each contained proxy, determines whether node/header, compares and
171 // returns if different. Compares and returns     180 // returns if different. Compares and returns if proxied nodes/headers
172 // are different.                                 181 // are different.
173 // *******************************************    182 // ***************************************************************************
174 //                                                183 //
175 G4bool G4SmartVoxelHeader::operator == (const     184 G4bool G4SmartVoxelHeader::operator == (const G4SmartVoxelHeader& pHead) const
176 {                                                 185 {
177   if ( (GetAxis()      == pHead.GetAxis())        186   if ( (GetAxis()      == pHead.GetAxis())
178     && (GetNoSlices()  == pHead.GetNoSlices())    187     && (GetNoSlices()  == pHead.GetNoSlices())
179     && (GetMinExtent() == pHead.GetMinExtent()    188     && (GetMinExtent() == pHead.GetMinExtent())
180     && (GetMaxExtent() == pHead.GetMaxExtent()    189     && (GetMaxExtent() == pHead.GetMaxExtent()) )
181   {                                               190   {
182     std::size_t node, maxNode;                 << 191     G4int node, maxNode;
183     G4SmartVoxelProxy *leftProxy, *rightProxy;    192     G4SmartVoxelProxy *leftProxy, *rightProxy;
184     G4SmartVoxelHeader *leftHeader, *rightHead    193     G4SmartVoxelHeader *leftHeader, *rightHeader;
185     G4SmartVoxelNode *leftNode, *rightNode;       194     G4SmartVoxelNode *leftNode, *rightNode;
186                                                   195 
187     maxNode = GetNoSlices();                   << 196     maxNode=GetNoSlices();
188     for (node=0; node<maxNode; ++node)         << 197     for (node=0; node<maxNode; node++)
189     {                                             198     {
190       leftProxy  = GetSlice(node);                199       leftProxy  = GetSlice(node);
191       rightProxy = pHead.GetSlice(node);          200       rightProxy = pHead.GetSlice(node);
192       if (leftProxy->IsHeader())                  201       if (leftProxy->IsHeader())
193       {                                           202       {
194         if (rightProxy->IsNode())                 203         if (rightProxy->IsNode())
195         {                                         204         {
196           return false;                           205           return false;
197         }                                         206         }
198         else                                      207         else
199         {                                         208         {
200           leftHeader  = leftProxy->GetHeader()    209           leftHeader  = leftProxy->GetHeader();
201           rightHeader = rightProxy->GetHeader(    210           rightHeader = rightProxy->GetHeader();
202           if (!(*leftHeader == *rightHeader))  << 211           if (!(*leftHeader==*rightHeader))
203           {                                       212           {
204             return false;                         213             return false;
205           }                                       214           }
206         }                                         215         }
207       }                                           216       }
208       else                                        217       else
209       {                                           218       {
210         if (rightProxy->IsHeader())               219         if (rightProxy->IsHeader())
211         {                                         220         {
212           return false;                           221           return false;
213         }                                         222         }
214         else                                      223         else
215         {                                         224         {
216           leftNode  = leftProxy->GetNode();       225           leftNode  = leftProxy->GetNode();
217           rightNode = rightProxy->GetNode();      226           rightNode = rightProxy->GetNode();
218           if (!(*leftNode == *rightNode))      << 227           if (!(*leftNode==*rightNode))
219           {                                       228           {
220             return false;                         229             return false;
221           }                                       230           }
222         }                                         231         }
223       }                                           232       }
224     }                                             233     }
225     return true;                                  234     return true;
226   }                                               235   }
227   else                                            236   else
228   {                                               237   {
229     return false;                                 238     return false;
230   }                                               239   }
231 }                                                 240 }
232                                                   241 
233 // *******************************************    242 // ***************************************************************************
234 // Builds voxels for daughters specified volum    243 // Builds voxels for daughters specified volume, in NON-REPLICATED case
235 // o Create List of target volume nos (all dau    244 // o Create List of target volume nos (all daughters; 0->noDaughters-1)
236 // o BuildWithinLimits does Build & also deter    245 // o BuildWithinLimits does Build & also determines mother dimensions.
237 // *******************************************    246 // ***************************************************************************
238 //                                                247 //
239 void G4SmartVoxelHeader::BuildVoxels(G4Logical    248 void G4SmartVoxelHeader::BuildVoxels(G4LogicalVolume* pVolume)
240 {                                                 249 {
241   G4VoxelLimits limits;   // Create `unlimited    250   G4VoxelLimits limits;   // Create `unlimited' limits object
242   std::size_t nDaughters = pVolume->GetNoDaugh << 251   G4int nDaughters = pVolume->GetNoDaughters();
243                                                   252 
244   G4VolumeNosVector targetList;                   253   G4VolumeNosVector targetList;
245   targetList.reserve(nDaughters);                 254   targetList.reserve(nDaughters);
246   for (std::size_t i=0; i<nDaughters; ++i)     << 255   for (G4int i=0; i<nDaughters; i++)
247   {                                               256   {
248     targetList.push_back((G4int)i);            << 257     targetList.push_back(i);
249   }                                               258   }
250   BuildVoxelsWithinLimits(pVolume, limits, &ta    259   BuildVoxelsWithinLimits(pVolume, limits, &targetList);
251 }                                                 260 }
252                                                   261 
253 // *******************************************    262 // ***************************************************************************
254 // Builds voxels for specified volume containi    263 // Builds voxels for specified volume containing a single replicated volume.
255 // If axis is not specified (i.e. "kUndefined"    264 // If axis is not specified (i.e. "kUndefined"), 3D voxelisation is applied,
256 // and the best axis is determined according t    265 // and the best axis is determined according to heuristics as for placements.
257 // *******************************************    266 // ***************************************************************************
258 //                                                267 //
259 void G4SmartVoxelHeader::BuildReplicaVoxels(G4    268 void G4SmartVoxelHeader::BuildReplicaVoxels(G4LogicalVolume* pVolume)
260 {                                                 269 {
261   G4VPhysicalVolume* pDaughter = nullptr;      << 270   G4VPhysicalVolume *pDaughter=0;
262                                                   271 
263   // Replication data                             272   // Replication data
264   //                                              273   //
265   EAxis axis;                                     274   EAxis axis;
266   G4int nReplicas;                                275   G4int nReplicas;
267   G4double width,offset;                          276   G4double width,offset;
268   G4bool consuming;                               277   G4bool consuming;
269                                                   278 
270   // Consistency check: pVolume should contain    279   // Consistency check: pVolume should contain single replicated volume
271   //                                              280   //
272   if ( (pVolume->GetNoDaughters()==1)             281   if ( (pVolume->GetNoDaughters()==1)
273     && (pVolume->GetDaughter(0)->IsReplicated( << 282     && (pVolume->GetDaughter(0)->IsReplicated()==true) )
274   {                                               283   {
275     // Obtain replication data                    284     // Obtain replication data
276     //                                            285     //
277     pDaughter = pVolume->GetDaughter(0);       << 286     pDaughter=pVolume->GetDaughter(0);
278     pDaughter->GetReplicationData(axis,nReplic    287     pDaughter->GetReplicationData(axis,nReplicas,width,offset,consuming);
279     fparamAxis = axis;                            288     fparamAxis = axis;
280     if ( !consuming )                          << 289     if ( consuming==false )
281     {                                             290     {
282       G4VoxelLimits limits;   // Create `unlim    291       G4VoxelLimits limits;   // Create `unlimited' limits object
283       G4VolumeNosVector targetList;               292       G4VolumeNosVector targetList;
284       targetList.reserve(nReplicas);              293       targetList.reserve(nReplicas);
285       for (auto i=0; i<nReplicas; ++i)         << 294       for (G4int i=0; i<nReplicas; i++)
286       {                                           295       {
287         targetList.push_back(i);                  296         targetList.push_back(i);
288       }                                           297       }
289       if (axis != kUndefined)                     298       if (axis != kUndefined)
290       {                                           299       {
291         // Apply voxelisation along the specif    300         // Apply voxelisation along the specified axis only
292                                                   301 
293         G4ProxyVector* pSlices=BuildNodes(pVol    302         G4ProxyVector* pSlices=BuildNodes(pVolume,limits,&targetList,axis);
294         faxis = axis;                             303         faxis = axis;
295         fslices = *pSlices;                       304         fslices = *pSlices;
296         delete pSlices;                           305         delete pSlices;
297                                                   306 
298         // Calculate and set min and max exten    307         // Calculate and set min and max extents given our axis
299         //                                        308         //
300         const G4AffineTransform origin;           309         const G4AffineTransform origin;
301         pVolume->GetSolid()->CalculateExtent(f    310         pVolume->GetSolid()->CalculateExtent(faxis, limits, origin,
302                                              f    311                                              fminExtent, fmaxExtent);
303         // Calculate equivalent nos               312         // Calculate equivalent nos
304         //                                        313         //
305         BuildEquivalentSliceNos();                314         BuildEquivalentSliceNos();
306         CollectEquivalentNodes();   // Collect    315         CollectEquivalentNodes();   // Collect common nodes
307       }                                           316       }
308       else                                        317       else
309       {                                           318       {
310         // Build voxels similarly as for norma    319         // Build voxels similarly as for normal placements considering
311         // all three cartesian axes.              320         // all three cartesian axes.
312                                                   321 
313         BuildVoxelsWithinLimits(pVolume, limit    322         BuildVoxelsWithinLimits(pVolume, limits, &targetList);
314       }                                           323       }
315     }                                             324     }
316     else                                          325     else
317     {                                             326     {
318       // Replication is consuming -> Build vox    327       // Replication is consuming -> Build voxels directly
319       //                                          328       //
320       // o Cartesian axes - range is -width*nR    329       // o Cartesian axes - range is -width*nREplicas/2 to +width*nREplicas/2
321       //                    nReplicas replicat    330       //                    nReplicas replications result
322       // o Radial axis (rho) = range is 0 to w    331       // o Radial axis (rho) = range is 0 to width*nReplicas
323       //                    nReplicas replicat    332       //                    nReplicas replications result
324       // o Phi axi       - range is offset to     333       // o Phi axi       - range is offset to offset+width*nReplicas radians
325       //                                          334       //
326       // Equivalent slices no computation & co    335       // Equivalent slices no computation & collection not required - all
327       // slices are different                     336       // slices are different
328       //                                          337       //
329       switch (axis)                               338       switch (axis)
330       {                                           339       {
331         case kXAxis:                              340         case kXAxis:
332         case kYAxis:                              341         case kYAxis:
333         case kZAxis:                              342         case kZAxis:
334           fminExtent = -width*nReplicas*0.5;      343           fminExtent = -width*nReplicas*0.5;
335           fmaxExtent =  width*nReplicas*0.5;      344           fmaxExtent =  width*nReplicas*0.5;
336           break;                                  345           break;
337         case kRho:                                346         case kRho:
338           fminExtent = offset;                    347           fminExtent = offset;
339           fmaxExtent = width*nReplicas+offset;    348           fmaxExtent = width*nReplicas+offset;
340           break;                                  349           break;
341         case kPhi:                                350         case kPhi:
342           fminExtent = offset;                    351           fminExtent = offset;
343           fmaxExtent = offset+width*nReplicas;    352           fmaxExtent = offset+width*nReplicas;
344           break;                                  353           break;
345         default:                                  354         default:
346           G4Exception("G4SmartVoxelHeader::Bui << 355           G4cerr << "ERROR - G4SmartVoxelHeader::BuildReplicaVoxels()"
347                       "GeomMgt0002", FatalExce << 356                  << G4endl
                                                   >> 357                  << "        Illegal axis !" << G4endl;
                                                   >> 358           G4Exception("G4SmartVoxelHeader::BuildReplicaVoxels()", "FatalError",
                                                   >> 359                       FatalException, "Illegal axis.");
348           break;                                  360           break;
349       }                                           361       }  
350       faxis = axis;   // Set axis                 362       faxis = axis;   // Set axis
351       BuildConsumedNodes(nReplicas);              363       BuildConsumedNodes(nReplicas);
352       if ( (axis==kXAxis) || (axis==kYAxis) ||    364       if ( (axis==kXAxis) || (axis==kYAxis) || (axis==kZAxis) )
353       {                                           365       {
354         // Sanity check on extent                 366         // Sanity check on extent
355         //                                        367         //
356         G4double emin = kInfinity, emax = -kIn << 368         G4double min, max;
357         G4VoxelLimits limits;                     369         G4VoxelLimits limits;
358         G4AffineTransform origin;                 370         G4AffineTransform origin;
359         pVolume->GetSolid()->CalculateExtent(a << 371         pVolume->GetSolid()->CalculateExtent(axis, limits, origin, min, max);
360         if ( (std::fabs((emin-fminExtent)/fmin << 372         if ( (std::fabs((min-fminExtent)/fminExtent) +
361               std::fabs((emax-fmaxExtent)/fmax << 373               std::fabs((max-fmaxExtent)/fmaxExtent)) > 0.05)
362         {                                         374         {
363           std::ostringstream message;          << 375           G4cerr << "ERROR - G4SmartVoxelHeader::BuildReplicaVoxels()"
364           message << "Sanity check: wrong soli << 376                  << G4endl
365                   << "        Replicated geome << 377                  << "        Replicated geometry, logical volume: "
366                   << pVolume->GetName();       << 378                  << pVolume->GetName() << G4endl;
367           G4Exception("G4SmartVoxelHeader::Bui << 379           G4Exception("G4SmartVoxelHeader::BuildReplicaVoxels", "FatalError",
368                       "GeomMgt0002", FatalExce << 380                       FatalException, "Sanity check: wrong solid extent.");
369         }                                         381         }
370       }                                           382       }
371     }                                             383     }
372   }                                               384   }
373   else                                            385   else
374   {                                               386   {
375     G4Exception("G4SmartVoxelHeader::BuildRepl << 387     G4cerr << "ERROR - G4SmartVoxelHeader::BuildReplicaVoxels()"
                                                   >> 388            << G4endl
                                                   >> 389            << "        There must be a single replicated volume !" << G4endl;
                                                   >> 390     G4Exception("G4SmartVoxelHeader::BuildReplicaVoxels", "InvalidSetup",
376                 FatalException, "Only one repl    391                 FatalException, "Only one replicated daughter is allowed !");
377   }                                               392   }
378 }                                                 393 }
379                                                   394 
380 // *******************************************    395 // ***************************************************************************
381 // Builds `consumed nodes': nReplicas nodes ea    396 // Builds `consumed nodes': nReplicas nodes each containing one replication,
382 // numbered in sequence 0->nReplicas-1            397 // numbered in sequence 0->nReplicas-1
383 // o Modifies fslices `in place'                  398 // o Modifies fslices `in place'
384 // o faxis,fminExtent,fmaxExtent NOT modified.    399 // o faxis,fminExtent,fmaxExtent NOT modified.
385 // *******************************************    400 // ***************************************************************************
386 //                                                401 //
387 void G4SmartVoxelHeader::BuildConsumedNodes(G4    402 void G4SmartVoxelHeader::BuildConsumedNodes(G4int nReplicas)
388 {                                                 403 {
389   G4int nNode, nVol;                              404   G4int nNode, nVol;
390   G4SmartVoxelNode* pNode;                     << 405   G4SmartVoxelNode *pNode;
391   G4SmartVoxelProxy* pProxyNode;               << 406   G4SmartVoxelProxy *pProxyNode;
392                                                   407 
393   // Create and fill nodes in temporary G4Node    408   // Create and fill nodes in temporary G4NodeVector (on stack)
394   //                                              409   //
395   G4NodeVector nodeList;                          410   G4NodeVector nodeList;
396   nodeList.reserve(nReplicas);                    411   nodeList.reserve(nReplicas);
397   for (nNode=0; nNode<nReplicas; ++nNode)      << 412   for (nNode=0; nNode<nReplicas; nNode++)
398   {                                               413   {
399     pNode = new G4SmartVoxelNode(nNode);       << 414     pNode=new G4SmartVoxelNode(nNode);
400     if (pNode == nullptr)                      << 415     if (!pNode)
401     {                                             416     {
402       G4Exception("G4SmartVoxelHeader::BuildCo << 417       G4cerr << "ERROR - G4SmartVoxelHeader::BuildConsumedNodes()" << G4endl
                                                   >> 418              << "        Node allocation failed." << G4endl;
                                                   >> 419       G4Exception("G4SmartVoxelHeader::BuildConsumedNodes()", "FatalError",
403                   FatalException, "Node alloca    420                   FatalException, "Node allocation error.");
404     }                                             421     }
405     nodeList.push_back(pNode);                    422     nodeList.push_back(pNode);
406   }                                               423   }
407   for (nVol=0; nVol<nReplicas; ++nVol)         << 424   for (nVol=0; nVol<nReplicas; nVol++)
408   {                                               425   {
409     nodeList[nVol]->Insert(nVol);   // Insert     426     nodeList[nVol]->Insert(nVol);   // Insert replication of number
410   }                                 // identic    427   }                                 // identical to voxel number
411                                                   428 
412   // Create & fill proxy List `in place' by mo    429   // Create & fill proxy List `in place' by modifying instance data fslices
413   //                                              430   //
414   fslices.clear();                                431   fslices.clear();
415   for (nNode=0; nNode<nReplicas; ++nNode)      << 432   for (nNode=0; nNode<nReplicas; nNode++)
416   {                                               433   {
417     pProxyNode = new G4SmartVoxelProxy(nodeLis    434     pProxyNode = new G4SmartVoxelProxy(nodeList[nNode]);
418     if (pProxyNode == nullptr)                 << 435     if (!pProxyNode)
419     {                                             436     {
420       G4Exception("G4SmartVoxelHeader::BuildCo << 437       G4cerr << "ERROR - G4SmartVoxelHeader::BuildConsumedNodes()" << G4endl
                                                   >> 438              << "        Proxy node allocation failed." << G4endl;
                                                   >> 439       G4Exception("G4SmartVoxelHeader::BuildConsumedNodes()", "FatalError",
421                   FatalException, "Proxy node     440                   FatalException, "Proxy node allocation error.");
422     }                                             441     }
423     fslices.push_back(pProxyNode);                442     fslices.push_back(pProxyNode);
424   }                                               443   }
425 }                                                 444 }
426                                                   445 
427 // *******************************************    446 // ***************************************************************************
428 // Builds and refines voxels between specified    447 // Builds and refines voxels between specified limits, considering only
429 // the physical volumes numbered `pCandidates'    448 // the physical volumes numbered `pCandidates'.
430 // o Chooses axis                                 449 // o Chooses axis
431 // o Determines min and max extents (of mother    450 // o Determines min and max extents (of mother solid) within limits.
432 // *******************************************    451 // ***************************************************************************
433 //                                                452 //
434 void                                              453 void
435 G4SmartVoxelHeader::BuildVoxelsWithinLimits(G4    454 G4SmartVoxelHeader::BuildVoxelsWithinLimits(G4LogicalVolume* pVolume,
436                                             G4    455                                             G4VoxelLimits pLimits,
437                                       const G4    456                                       const G4VolumeNosVector* pCandidates)
438 {                                                 457 {
439   // Choose best axis for slicing by:             458   // Choose best axis for slicing by:
440   // 1. Trying all unlimited cartesian axes       459   // 1. Trying all unlimited cartesian axes
441   // 2. Select axis which gives greatest no sl    460   // 2. Select axis which gives greatest no slices
442                                                   461 
443   G4ProxyVector *pGoodSlices=nullptr, *pTestSl << 462   G4ProxyVector *pGoodSlices=0, *pTestSlices, *tmpSlices;
444   G4double goodSliceScore=kInfinity, testSlice    463   G4double goodSliceScore=kInfinity, testSliceScore;
445   EAxis goodSliceAxis = kXAxis;                   464   EAxis goodSliceAxis = kXAxis;
446   std::size_t node, maxNode;                   << 465   EAxis testAxis      = kXAxis;
                                                   >> 466   G4int node, maxNode, iaxis;
447   G4VoxelLimits noLimits;                         467   G4VoxelLimits noLimits;
448                                                   468 
449   // Try all non-limited cartesian axes           469   // Try all non-limited cartesian axes
450   //                                              470   //
451   for ( EAxis testAxis : { kXAxis, kYAxis, kZA << 471   for (iaxis=0; iaxis<3; iaxis++)
452   {                                               472   {
                                                   >> 473     switch(iaxis)
                                                   >> 474     {
                                                   >> 475       case 0:
                                                   >> 476         testAxis = kXAxis;
                                                   >> 477         break;
                                                   >> 478       case 1:
                                                   >> 479         testAxis = kYAxis;
                                                   >> 480         break;
                                                   >> 481       case 2:
                                                   >> 482         testAxis = kZAxis;
                                                   >> 483         break;
                                                   >> 484     }
453     if (!pLimits.IsLimited(testAxis))             485     if (!pLimits.IsLimited(testAxis))
454     {                                             486     {
455       pTestSlices = BuildNodes(pVolume,pLimits    487       pTestSlices = BuildNodes(pVolume,pLimits,pCandidates,testAxis);
456       testSliceScore = CalculateQuality(pTestS    488       testSliceScore = CalculateQuality(pTestSlices);
457       if ( (pGoodSlices == nullptr) || (testSl << 489       if ( (!pGoodSlices) || (testSliceScore<goodSliceScore) )
458       {                                           490       {
459         goodSliceAxis  = testAxis;                491         goodSliceAxis  = testAxis;
460         goodSliceScore = testSliceScore;          492         goodSliceScore = testSliceScore;
461         std::swap( pGoodSlices, pTestSlices);  << 493         tmpSlices      = pGoodSlices;
                                                   >> 494         pGoodSlices    = pTestSlices;
                                                   >> 495         pTestSlices    = tmpSlices;
462       }                                           496       }
463       if (pTestSlices != nullptr)              << 497       if (pTestSlices)
464       {                                           498       {
465         // Destroy pTestSlices and all its con    499         // Destroy pTestSlices and all its contents
466         //                                        500         //
467         maxNode=pTestSlices->size();              501         maxNode=pTestSlices->size();
468         for (node=0; node<maxNode; ++node)     << 502         for (node=0; node<maxNode; node++)
469         {                                         503         {
470           delete (*pTestSlices)[node]->GetNode    504           delete (*pTestSlices)[node]->GetNode();
471         }                                         505         }
472         G4SmartVoxelProxy* tmpProx;               506         G4SmartVoxelProxy* tmpProx;
473         while (!pTestSlices->empty())  // Loop << 507         while (pTestSlices->size()>0)
474         {                                         508         {
475           tmpProx = pTestSlices->back();          509           tmpProx = pTestSlices->back();
476           pTestSlices->pop_back();                510           pTestSlices->pop_back();
477           for (auto i=pTestSlices->cbegin(); i << 511           for (G4ProxyVector::iterator i=pTestSlices->begin();
                                                   >> 512                                        i!=pTestSlices->end(); i++)
478           {                                       513           {
479             if (*i==tmpProx)                      514             if (*i==tmpProx)
480             {                                     515             {
481               i = pTestSlices->erase(i);       << 516               pTestSlices->erase(i); i--;
482             }                                  << 
483             else                               << 
484             {                                  << 
485               ++i;                             << 
486             }                                     517             }
487           }                                       518           }
488           delete tmpProx;                      << 519           if ( tmpProx ) { delete tmpProx; }
489         }                                      << 520         } 
490         delete pTestSlices;                       521         delete pTestSlices;
491       }                                           522       }
492     }                                             523     }
493   }                                               524   }
494   // Check for error case.. when limits alread    525   // Check for error case.. when limits already 3d,
495   // so cannot select a new axis                  526   // so cannot select a new axis
496   //                                              527   //
497   if (pGoodSlices == nullptr)                  << 528   if (!pGoodSlices)
498   {                                               529   {
                                                   >> 530     G4cerr << "ERROR - G4SmartVoxelHeader::BuildVoxelsWithinLimits()"
                                                   >> 531            << G4endl
                                                   >> 532            << "        Illegal limits: only 3 dimensions allowed." << G4endl;
499     G4Exception("G4SmartVoxelHeader::BuildVoxe    533     G4Exception("G4SmartVoxelHeader::BuildVoxelsWithinLimits()",
500                 "GeomMgt0002", FatalException, << 534                 "InvalidSetup", FatalException,
501                 "Cannot select more than 3 axi    535                 "Cannot select more than 3 axis for optimisation.");
502     return;                                    << 
503   }                                               536   }
504                                                   537 
505   //                                              538   // 
506   // We have selected pGoodSlices, with a scor    539   // We have selected pGoodSlices, with a score testSliceScore
507   //                                              540   //
508                                                   541 
509   // Store chosen axis, slice ptr                 542   // Store chosen axis, slice ptr
510   //                                              543   //
511   fslices =* pGoodSlices; // Set slice informa << 544   fslices=*pGoodSlices; // Set slice information, copy ptrs in collection
512   delete pGoodSlices;     // Destroy slices ve << 545   delete pGoodSlices;   // Destroy slices vector, but not contained
513                           // proxies or nodes  << 546                         // proxies or nodes
514   faxis = goodSliceAxis;                       << 547   faxis=goodSliceAxis;
515                                                   548 
516 #ifdef G4GEOMETRY_VOXELDEBUG                      549 #ifdef G4GEOMETRY_VOXELDEBUG
517   G4cout << G4endl << "     Volume = " << pVol << 550   G4cout << G4endl << "     Selected axis = " << faxis << G4endl;
518          << G4endl << "     Selected axis = "  << 551   for (size_t islice=0; islice<fslices.size(); islice++)
519   for (auto islice=0; islice<fslices.size(); + << 
520   {                                               552   {
521     G4cout << "     Node #" << islice << " = {    553     G4cout << "     Node #" << islice << " = {";
522     for (auto j=0; j<fslices[islice]->GetNode( << 554     for (G4int j=0; j<fslices[islice]->GetNode()->GetNoContained(); j++)
523     {                                             555     {
524       G4cout << " " << fslices[islice]->GetNod    556       G4cout << " " << fslices[islice]->GetNode()->GetVolume(j);
525     }                                             557     }
526     G4cout << " }" << G4endl;                     558     G4cout << " }" << G4endl;
527   }                                               559   }
528   G4cout << G4endl;                               560   G4cout << G4endl;
529 #endif                                            561 #endif
530                                                   562 
531   // Calculate and set min and max extents giv    563   // Calculate and set min and max extents given our axis
532   //                                              564   //
533   G4VSolid* outerSolid = pVolume->GetSolid();     565   G4VSolid* outerSolid = pVolume->GetSolid();
534   const G4AffineTransform origin;                 566   const G4AffineTransform origin;
535   if(!outerSolid->CalculateExtent(faxis,pLimit    567   if(!outerSolid->CalculateExtent(faxis,pLimits,origin,fminExtent,fmaxExtent))
536   {                                               568   {
537     outerSolid->CalculateExtent(faxis,noLimits    569     outerSolid->CalculateExtent(faxis,noLimits,origin,fminExtent,fmaxExtent);
538   }                                               570   }
539                                                   571 
540   // Calculate equivalent nos                     572   // Calculate equivalent nos
541   //                                              573   //
542   BuildEquivalentSliceNos();                      574   BuildEquivalentSliceNos();
543   CollectEquivalentNodes();      // Collect co << 575   CollectEquivalentNodes();     // Collect common nodes
544   RefineNodes(pVolume, pLimits); // Refine nod << 576   RefineNodes(pVolume,pLimits); // Refine nodes creating headers
545                                                   577 
546   // No common headers can exist because colla    578   // No common headers can exist because collapsed by construction
547 }                                                 579 }
548                                                   580 
549 // *******************************************    581 // ***************************************************************************
550 // Calculates and stores the minimum and maxim    582 // Calculates and stores the minimum and maximum equivalent neighbour
551 // values for all slices at our level.            583 // values for all slices at our level.
552 //                                                584 //
553 // Precondition: all slices are nodes.            585 // Precondition: all slices are nodes.
554 // For each potential start of a group of equi    586 // For each potential start of a group of equivalent nodes:
555 // o searches forwards in fslices to find grou    587 // o searches forwards in fslices to find group end
556 // o loops from start to end setting start and    588 // o loops from start to end setting start and end slices.
557 // *******************************************    589 // ***************************************************************************
558 //                                                590 //
559 void G4SmartVoxelHeader::BuildEquivalentSliceN    591 void G4SmartVoxelHeader::BuildEquivalentSliceNos()
560 {                                                 592 {
561   std::size_t sliceNo, minNo, maxNo, equivNo;  << 593   G4int sliceNo, minNo, maxNo, equivNo;
562   std::size_t maxNode = fslices.size();        << 594   G4int maxNode = fslices.size();
563   G4SmartVoxelNode *startNode, *sampleNode;       595   G4SmartVoxelNode *startNode, *sampleNode;
564   for (sliceNo=0; sliceNo<maxNode; ++sliceNo)  << 596   for (sliceNo=0; sliceNo<maxNode; sliceNo++)
565   {                                               597   {
566     minNo = sliceNo;                              598     minNo = sliceNo;
567                                                   599 
568     // Get first node (see preconditions - wil    600     // Get first node (see preconditions - will throw exception if a header)
569     //                                            601     //
570     startNode = fslices[minNo]->GetNode();        602     startNode = fslices[minNo]->GetNode();
571                                                   603 
572     // Find max equivalent                        604     // Find max equivalent
573     //                                            605     //
574     for (equivNo=minNo+1; equivNo<maxNode; ++e << 606     for (equivNo=minNo+1; equivNo<maxNode; equivNo++)
575     {                                             607     {
576       sampleNode = fslices[equivNo]->GetNode()    608       sampleNode = fslices[equivNo]->GetNode();
577       if (!((*startNode) == (*sampleNode))) {     609       if (!((*startNode) == (*sampleNode))) { break; }
578     }                                             610     }
579     maxNo = equivNo-1;                            611     maxNo = equivNo-1;
580     if (maxNo != minNo)                           612     if (maxNo != minNo)
581     {                                             613     {
582       // Set min and max nos                      614       // Set min and max nos
583       //                                          615       //
584       for (equivNo=minNo; equivNo<=maxNo; ++eq << 616       for (equivNo=minNo; equivNo<=maxNo; equivNo++)
585       {                                           617       {
586         sampleNode = fslices[equivNo]->GetNode    618         sampleNode = fslices[equivNo]->GetNode();
587         sampleNode->SetMinEquivalentSliceNo((G << 619         sampleNode->SetMinEquivalentSliceNo(minNo);
588         sampleNode->SetMaxEquivalentSliceNo((G << 620         sampleNode->SetMaxEquivalentSliceNo(maxNo);
589       }                                           621       }
590       // Advance outer loop to end of equivale    622       // Advance outer loop to end of equivalent group
591       //                                          623       //
592       sliceNo = maxNo;                            624       sliceNo = maxNo;
593     }                                             625     }
594   }                                               626   }
595 }                                                 627 }
596                                                   628 
597 // *******************************************    629 // ***************************************************************************
598 // Collects common nodes at our level, deletin    630 // Collects common nodes at our level, deleting all but one to save
599 // memory, and adjusting stored slice pointers    631 // memory, and adjusting stored slice pointers appropriately.
600 //                                                632 //
601 // Preconditions:                                 633 // Preconditions:
602 // o the slices have not previously be "collec    634 // o the slices have not previously be "collected"
603 // o all of the slices are nodes.                 635 // o all of the slices are nodes.
604 // *******************************************    636 // ***************************************************************************
605 //                                                637 //
606 void G4SmartVoxelHeader::CollectEquivalentNode    638 void G4SmartVoxelHeader::CollectEquivalentNodes()
607 {                                                 639 {
608   std::size_t sliceNo, maxNo, equivNo;         << 640   G4int sliceNo, maxNo, equivNo;
609   std::size_t maxNode=fslices.size();          << 641   G4int maxNode=fslices.size();
610   G4SmartVoxelNode* equivNode;                 << 642   G4SmartVoxelNode *equivNode;
611   G4SmartVoxelProxy* equivProxy;               << 643   G4SmartVoxelProxy *equivProxy;
612                                                   644 
613   for (sliceNo=0; sliceNo<maxNode; ++sliceNo)  << 645   for (sliceNo=0; sliceNo<maxNode; sliceNo++)
614   {                                               646   {
615     equivProxy=fslices[sliceNo];                  647     equivProxy=fslices[sliceNo];
616                                                   648 
617     // Assumption (see preconditions): all sli    649     // Assumption (see preconditions): all slices are nodes
618     //                                            650     //
619     equivNode = equivProxy->GetNode();            651     equivNode = equivProxy->GetNode();
620     maxNo = equivNode->GetMaxEquivalentSliceNo    652     maxNo = equivNode->GetMaxEquivalentSliceNo();
621     if (maxNo != sliceNo)                         653     if (maxNo != sliceNo)
622     {                                             654     {
623 #ifdef G4GEOMETRY_VOXELDEBUG                      655 #ifdef G4GEOMETRY_VOXELDEBUG
624       G4cout << "**** G4SmartVoxelHeader::Coll    656       G4cout << "**** G4SmartVoxelHeader::CollectEquivalentNodes" << G4endl
625              << "     Collecting Nodes = "        657              << "     Collecting Nodes = " 
626              << sliceNo << " - " << maxNo << G    658              << sliceNo << " - " << maxNo << G4endl;
627 #endif                                            659 #endif
628       // Do collection between sliceNo and max    660       // Do collection between sliceNo and maxNo inclusive
629       //                                          661       //
630       for (equivNo=sliceNo+1; equivNo<=maxNo;  << 662       for (equivNo=sliceNo+1; equivNo<=maxNo; equivNo++)
631       {                                           663       {
632         delete fslices[equivNo]->GetNode();       664         delete fslices[equivNo]->GetNode();
633         delete fslices[equivNo];                  665         delete fslices[equivNo];
634         fslices[equivNo] = equivProxy;            666         fslices[equivNo] = equivProxy;
635       }                                           667       }
636       sliceNo = maxNo;                            668       sliceNo = maxNo;
637     }                                             669     }
638   }                                               670   }
639 }                                                 671 }
640                                                   672 
641 // *******************************************    673 // ***************************************************************************
642 // Collects common headers at our level, delet    674 // Collects common headers at our level, deleting all but one to save
643 // memory, and adjusting stored slice pointers    675 // memory, and adjusting stored slice pointers appropriately.
644 //                                                676 // 
645 // Preconditions:                                 677 // Preconditions:
646 // o if a header forms part of a range of equi    678 // o if a header forms part of a range of equivalent slices
647 //   (ie. GetMaxEquivalentSliceNo()>GetMinEqui    679 //   (ie. GetMaxEquivalentSliceNo()>GetMinEquivalentSliceNo()),
648 //   it is assumed that all slices in the rang    680 //   it is assumed that all slices in the range are headers.
649 // o this will be true if a constant Expressio    681 // o this will be true if a constant Expression is used to evaluate
650 //   when to refine nodes.                        682 //   when to refine nodes.
651 // *******************************************    683 // ***************************************************************************
652 //                                                684 //
653 void G4SmartVoxelHeader::CollectEquivalentHead    685 void G4SmartVoxelHeader::CollectEquivalentHeaders()
654 {                                                 686 {
655   std::size_t sliceNo, maxNo, equivNo;         << 687   G4int sliceNo, maxNo, equivNo;
656   std::size_t maxNode = fslices.size();        << 688   G4int maxNode = fslices.size();
657   G4SmartVoxelHeader *equivHeader, *sampleHead    689   G4SmartVoxelHeader *equivHeader, *sampleHeader;
658   G4SmartVoxelProxy *equivProxy;                  690   G4SmartVoxelProxy *equivProxy;
659                                                   691 
660   for (sliceNo=0; sliceNo<maxNode; ++sliceNo)  << 692   for (sliceNo=0; sliceNo<maxNode; sliceNo++)
661   {                                               693   {
662     equivProxy = fslices[sliceNo];                694     equivProxy = fslices[sliceNo];
663     if (equivProxy->IsHeader())                   695     if (equivProxy->IsHeader())
664     {                                             696     {
665       equivHeader = equivProxy->GetHeader();      697       equivHeader = equivProxy->GetHeader();
666       maxNo = equivHeader->GetMaxEquivalentSli    698       maxNo = equivHeader->GetMaxEquivalentSliceNo();
667       if (maxNo != sliceNo)                       699       if (maxNo != sliceNo)
668       {                                           700       {
669         // Attempt collection between sliceNo     701         // Attempt collection between sliceNo and maxNo inclusive:
670         // look for common headers. All slices    702         // look for common headers. All slices between sliceNo and maxNo
671         // are guaranteed to be headers but ma    703         // are guaranteed to be headers but may not have equal contents
672         //                                        704         //
673 #ifdef G4GEOMETRY_VOXELDEBUG                      705 #ifdef G4GEOMETRY_VOXELDEBUG
674         G4cout << "**** G4SmartVoxelHeader::Co    706         G4cout << "**** G4SmartVoxelHeader::CollectEquivalentHeaders" << G4endl
675                << "     Collecting Headers =";    707                << "     Collecting Headers =";
676 #endif                                            708 #endif
677         for (equivNo=sliceNo+1; equivNo<=maxNo << 709         for (equivNo=sliceNo+1; equivNo<=maxNo; equivNo++)
678         {                                         710         {
679           sampleHeader = fslices[equivNo]->Get    711           sampleHeader = fslices[equivNo]->GetHeader();
680           if ( (*sampleHeader) == (*equivHeade    712           if ( (*sampleHeader) == (*equivHeader) )
681           {                                       713           {
682 #ifdef G4GEOMETRY_VOXELDEBUG                      714 #ifdef G4GEOMETRY_VOXELDEBUG
683             G4cout << " " << equivNo;             715             G4cout << " " << equivNo;
684 #endif                                            716 #endif
685             // Delete sampleHeader + proxy and    717             // Delete sampleHeader + proxy and replace with equivHeader/Proxy
686             //                                    718             //
687             delete sampleHeader;                  719             delete sampleHeader;
688             delete fslices[equivNo];              720             delete fslices[equivNo];
689             fslices[equivNo] = equivProxy;        721             fslices[equivNo] = equivProxy;
690           }                                       722           }
691           else                                    723           else
692           {                                       724           {
693             // Not equal. Set this header to b    725             // Not equal. Set this header to be
694             // the current header for comparis    726             // the current header for comparisons
695             //                                    727             //
696             equivProxy  = fslices[equivNo];       728             equivProxy  = fslices[equivNo];
697             equivHeader = equivProxy->GetHeade    729             equivHeader = equivProxy->GetHeader();
698           }                                       730           }
699                                                   731 
700         }                                         732         }
701 #ifdef G4GEOMETRY_VOXELDEBUG                      733 #ifdef G4GEOMETRY_VOXELDEBUG
702         G4cout << G4endl;                         734         G4cout << G4endl;
703 #endif                                            735 #endif
704         // Skip past examined slices              736         // Skip past examined slices
705         //                                        737         //
706         sliceNo = maxNo;                          738         sliceNo = maxNo;
707       }                                           739       }
708     }                                             740     }
709   }                                               741   }
710 }                                                 742 }
711                                                   743 
712 // *******************************************    744 // ***************************************************************************
713 // Builds the nodes corresponding to slices be    745 // Builds the nodes corresponding to slices between the specified limits
714 // and along the specified axis, using candida    746 // and along the specified axis, using candidate volume no.s in the vector
715 // pCandidates. If the `daughters' are replica    747 // pCandidates. If the `daughters' are replicated volumes (ie. the logical
716 // volume has a single replicated/parameterise    748 // volume has a single replicated/parameterised volume for a daughter)
717 // the candidate no.s are interpreted as PARAM    749 // the candidate no.s are interpreted as PARAMETERISED volume no.s & 
718 // PARAMETERISATIONs are applied to compute tr    750 // PARAMETERISATIONs are applied to compute transformations & solid
719 // dimensions appropriately. The volume must b    751 // dimensions appropriately. The volume must be parameterised - ie. has a
720 // parameterisation object & non-consuming) -     752 // parameterisation object & non-consuming) - in this case.
721 //                                                753 // 
722 // Returns pointer to built node "structure" (    754 // Returns pointer to built node "structure" (guaranteed non NULL) consisting
723 // of G4SmartVoxelNodeProxies referring to G4S    755 // of G4SmartVoxelNodeProxies referring to G4SmartVoxelNodes.
724 // *******************************************    756 // ***************************************************************************
725 //                                                757 //
726 G4ProxyVector* G4SmartVoxelHeader::BuildNodes(    758 G4ProxyVector* G4SmartVoxelHeader::BuildNodes(G4LogicalVolume* pVolume,
727                                                   759                                               G4VoxelLimits pLimits,
728                                         const     760                                         const G4VolumeNosVector* pCandidates,
729                                                   761                                               EAxis pAxis)
730 {                                                 762 {
731   G4double motherMinExtent= kInfinity, motherM << 763   G4double motherMinExtent, motherMaxExtent, targetMinExtent, targetMaxExtent;
732            targetMinExtent= kInfinity, targetM << 764   G4VPhysicalVolume *pDaughter=0;
733   G4VPhysicalVolume* pDaughter = nullptr;      << 765   G4VPVParameterisation *pParam=0;
734   G4VPVParameterisation* pParam = nullptr;     << 
735   G4VSolid *targetSolid;                          766   G4VSolid *targetSolid;
736   G4AffineTransform targetTransform;              767   G4AffineTransform targetTransform;
737   G4bool replicated;                              768   G4bool replicated;
738   std::size_t nCandidates = pCandidates->size( << 769   G4int nCandidates = pCandidates->size();
739   std::size_t nVol, nNode, targetVolNo;        << 770   G4int nVol, nNode, targetVolNo;
740   G4VoxelLimits noLimits;                         771   G4VoxelLimits noLimits;
741                                                << 772     
742 #ifdef G4GEOMETRY_VOXELDEBUG                      773 #ifdef G4GEOMETRY_VOXELDEBUG
743   G4cout << "**** G4SmartVoxelHeader::BuildNod    774   G4cout << "**** G4SmartVoxelHeader::BuildNodes" << G4endl
744          << "     Limits = " << pLimits << G4e    775          << "     Limits = " << pLimits << G4endl
745          << "       Axis = " << pAxis << G4end    776          << "       Axis = " << pAxis << G4endl
746          << " Candidates = " << nCandidates <<    777          << " Candidates = " << nCandidates << G4endl;
747 #endif                                            778 #endif
748                                                   779 
749   // Compute extent of logical volume's solid     780   // Compute extent of logical volume's solid along this axis
750   // NOTE: results stored locally and not pres    781   // NOTE: results stored locally and not preserved/reused
751   //                                              782   //
752   G4VSolid* outerSolid = pVolume->GetSolid();     783   G4VSolid* outerSolid = pVolume->GetSolid();
753   const G4AffineTransform origin;                 784   const G4AffineTransform origin;
754   if( !outerSolid->CalculateExtent(pAxis, pLim    785   if( !outerSolid->CalculateExtent(pAxis, pLimits, origin,
755                                    motherMinEx    786                                    motherMinExtent, motherMaxExtent) )
756   {                                               787   {
757     outerSolid->CalculateExtent(pAxis, noLimit    788     outerSolid->CalculateExtent(pAxis, noLimits, origin,
758                                 motherMinExten    789                                 motherMinExtent, motherMaxExtent);
759   }                                               790   }
760   G4VolumeExtentVector minExtents(nCandidates,    791   G4VolumeExtentVector minExtents(nCandidates,0.);
761   G4VolumeExtentVector maxExtents(nCandidates,    792   G4VolumeExtentVector maxExtents(nCandidates,0.);
762                                                   793 
763   if ( (pVolume->GetNoDaughters() == 1)        << 794   if ( (pVolume->GetNoDaughters()==1)
764     && (pVolume->GetDaughter(0)->IsReplicated( << 795     && (pVolume->GetDaughter(0)->IsReplicated()==true) )
765   {                                               796   {
766     // Replication data not required: only par    797     // Replication data not required: only parameterisation object 
767     // and volume no. List used                   798     // and volume no. List used
768     //                                            799     //
769     pDaughter = pVolume->GetDaughter(0);          800     pDaughter = pVolume->GetDaughter(0);
770     pParam = pDaughter->GetParameterisation();    801     pParam = pDaughter->GetParameterisation();
771     if (pParam == nullptr)                     << 802     if (!pParam)
772     {                                             803     {
773       std::ostringstream message;              << 804       G4cerr << "PANIC! - G4SmartVoxelHeader::BuildNodes()" << G4endl
774       message << "PANIC! - Missing parameteris << 805              << "         Replicated volume with no parameterisation object !"
775               << "         Replicated volume w << 806              << G4endl;
776       G4Exception("G4SmartVoxelHeader::BuildNo << 807       G4Exception("G4SmartVoxelHeader::BuildNodes()", "InvalidSetup",
777                   FatalException, message);    << 808                   FatalException, "Missing parameterisation.");
778       return nullptr;                          << 
779     }                                             809     }
780                                                   810 
781     // Setup daughter's transformations           811     // Setup daughter's transformations
782     //                                            812     //
783     targetTransform = G4AffineTransform(pDaugh    813     targetTransform = G4AffineTransform(pDaughter->GetRotation(),
784                                         pDaugh    814                                         pDaughter->GetTranslation());
785     replicated = true;                            815     replicated = true;
786   }                                               816   }
787     else                                          817     else
788   {                                               818   {
789     replicated = false;                           819     replicated = false;
790   }                                               820   }
791                                                   821     
792   // Compute extents                              822   // Compute extents
793   //                                              823   //
794   for (nVol=0; nVol<nCandidates; ++nVol)       << 824   for (nVol=0; nVol<nCandidates; nVol++)
795   {                                               825   {
796     targetVolNo = (*pCandidates)[nVol];        << 826     targetVolNo=(*pCandidates)[nVol];
797     if (!replicated)                           << 827     if (replicated == false)
798     {                                             828     {
799       pDaughter = pVolume->GetDaughter(targetV << 829       pDaughter=pVolume->GetDaughter(targetVolNo);
800                                                   830 
801       // Setup daughter's transformations         831       // Setup daughter's transformations
802       //                                          832       //
803       targetTransform = G4AffineTransform(pDau    833       targetTransform = G4AffineTransform(pDaughter->GetRotation(),
804                                           pDau    834                                           pDaughter->GetTranslation());
805       // Get underlying (and setup) solid         835       // Get underlying (and setup) solid
806       //                                          836       //
807       targetSolid = pDaughter->GetLogicalVolum    837       targetSolid = pDaughter->GetLogicalVolume()->GetSolid();
808     }                                             838     }
809     else                                          839     else
810     {                                             840     {
811       // Find  solid                              841       // Find  solid
812       //                                          842       //
813       targetSolid = pParam->ComputeSolid((G4in << 843       targetSolid = pParam->ComputeSolid(targetVolNo,pDaughter);
814                                                   844 
815       // Setup solid                              845       // Setup solid
816       //                                          846       //
817       targetSolid->ComputeDimensions(pParam,(G << 847       targetSolid->ComputeDimensions(pParam,targetVolNo,pDaughter);
818                                                   848 
819       // Setup transform                          849       // Setup transform
820       //                                          850       //
821       pParam->ComputeTransformation((G4int)tar << 851       pParam->ComputeTransformation(targetVolNo,pDaughter);
822       targetTransform = G4AffineTransform(pDau    852       targetTransform = G4AffineTransform(pDaughter->GetRotation(),
823                                           pDau    853                                           pDaughter->GetTranslation());
824     }                                             854     }
825     // Calculate extents                          855     // Calculate extents
826     //                                            856     //
827     if(!targetSolid->CalculateExtent(pAxis, pL    857     if(!targetSolid->CalculateExtent(pAxis, pLimits, targetTransform,
828                                      targetMin    858                                      targetMinExtent, targetMaxExtent))
829     {                                             859     {
830       targetSolid->CalculateExtent(pAxis, noLi    860       targetSolid->CalculateExtent(pAxis, noLimits, targetTransform,
831                                    targetMinEx    861                                    targetMinExtent,targetMaxExtent);
832     }                                             862     }
833     minExtents[nVol] = targetMinExtent;           863     minExtents[nVol] = targetMinExtent;
834     maxExtents[nVol] = targetMaxExtent;           864     maxExtents[nVol] = targetMaxExtent;
835                                                   865 
836 #ifdef G4GEOMETRY_VOXELDEBUG                   << 
837    G4cout << "-------------------------------- << 
838           << "     Volume = " << pDaughter->Ge << 
839           << " Min Extent = " << targetMinExte << 
840           << " Max Extent = " << targetMaxExte << 
841           << "-------------------------------- << 
842 #endif                                         << 
843                                                << 
844     // Check not entirely outside mother when     866     // Check not entirely outside mother when processing toplevel nodes
845     //                                            867     //
846     if ( (!pLimits.IsLimited()) && ((targetMax    868     if ( (!pLimits.IsLimited()) && ((targetMaxExtent<=motherMinExtent)
847                                   ||(targetMin    869                                   ||(targetMinExtent>=motherMaxExtent)) )
848     {                                             870     {
849       std::ostringstream message;              << 871       G4cerr << "PANIC! - G4SmartVoxelHeader::BuildNodes()" << G4endl
850       message << "PANIC! - Overlapping daughte << 872              << "         Daughter physical volume "
851               << "         Daughter physical v << 873              << pDaughter->GetName() << G4endl
852               << pDaughter->GetName() << G4end << 874              << "         is entirely outside mother logical volume "
853               << "         is entirely outside << 875              << pVolume->GetName() << " !!" << G4endl;
854               << pVolume->GetName() << " !!";  << 876       G4Exception("G4SmartVoxelHeader::BuildNodes()", "InvalidSetup",
855       G4Exception("G4SmartVoxelHeader::BuildNo << 877                   FatalException, "Overlapping daughter with mother volume.");
856                   FatalException, message);    << 
857     }                                             878     }
858                                                   879 
859 #ifdef G4GEOMETRY_VOXELDEBUG                      880 #ifdef G4GEOMETRY_VOXELDEBUG
860     // Check for straddling volumes when debug    881     // Check for straddling volumes when debugging.
861     // If a volume is >kStraddlePercent percen    882     // If a volume is >kStraddlePercent percent over the mother
862     // boundary, print a warning.                 883     // boundary, print a warning.
863     //                                            884     //
864     if (!pLimits.IsLimited())                     885     if (!pLimits.IsLimited())
865     {                                             886     {
866       G4double width;                             887       G4double width;
867       G4int kStraddlePercent = 5;              << 888       G4int kStraddlePercent=5;
868       width = maxExtents[nVol]-minExtents[nVol    889       width = maxExtents[nVol]-minExtents[nVol];
869       if ( (((motherMinExtent-minExtents[nVol]    890       if ( (((motherMinExtent-minExtents[nVol])*100/width) > kStraddlePercent)
870          ||(((maxExtents[nVol]-motherMaxExtent    891          ||(((maxExtents[nVol]-motherMaxExtent)*100/width) > kStraddlePercent) )
871       {                                           892       {
872         G4cout << "**** G4SmartVoxelHeader::Bu    893         G4cout << "**** G4SmartVoxelHeader::BuildNodes" << G4endl
873                << "     WARNING : Daughter # "    894                << "     WARNING : Daughter # " << nVol
874                << " name = " << pDaughter->Get    895                << " name = " << pDaughter->GetName() << G4endl
875                << "     Crosses mother boundar    896                << "     Crosses mother boundary of logical volume, name = " 
876                << pVolume->GetName() << G4endl    897                << pVolume->GetName() << G4endl
877                << "     by more than " << kStr    898                << "     by more than " << kStraddlePercent 
878                << "%" << G4endl;                  899                << "%" << G4endl;
879       }                                           900       }
880     }                                             901     }
881 #endif                                            902 #endif
                                                   >> 903 
882   }                                               904   }
883                                                   905 
884   // Extents of all daughters known               906   // Extents of all daughters known
885                                                   907 
886   // Calculate minimum slice width, only inclu    908   // Calculate minimum slice width, only including volumes inside the limits
887   //                                              909   //
888   G4double minWidth = kInfinity;                  910   G4double minWidth = kInfinity;
889   G4double currentWidth;                          911   G4double currentWidth;
890   for (nVol=0; nVol<nCandidates; ++nVol)       << 912   for (nVol=0; nVol<nCandidates; nVol++)
891   {                                               913   {
892     // currentWidth should -always- be a posit    914     // currentWidth should -always- be a positive value. Inaccurate computed extent
893     // from the solid or situations of malform    915     // from the solid or situations of malformed geometries (overlaps) may lead to
894     // negative values and therefore unpredict    916     // negative values and therefore unpredictable crashes !
895     //                                            917     //
896     currentWidth = std::abs(maxExtents[nVol]-m    918     currentWidth = std::abs(maxExtents[nVol]-minExtents[nVol]);
897     if ( (currentWidth<minWidth)                  919     if ( (currentWidth<minWidth)
898       && (maxExtents[nVol]>=pLimits.GetMinExte    920       && (maxExtents[nVol]>=pLimits.GetMinExtent(pAxis))
899       && (minExtents[nVol]<=pLimits.GetMaxExte    921       && (minExtents[nVol]<=pLimits.GetMaxExtent(pAxis)) )
900     {                                             922     {
901       minWidth = currentWidth;                    923       minWidth = currentWidth;
902     }                                             924     }
903   }                                               925   }
904                                                   926 
905   // No. of Nodes formula - nearest integer to    927   // No. of Nodes formula - nearest integer to
906   // mother width/half min daughter width +1      928   // mother width/half min daughter width +1
907   //                                              929   //
908   G4double noNodesExactD = ((motherMaxExtent-m    930   G4double noNodesExactD = ((motherMaxExtent-motherMinExtent)*2.0/minWidth)+1.0;
909                                                   931 
910   // Compare with "smartless quality", i.e. th    932   // Compare with "smartless quality", i.e. the average number of slices
911   // used per contained volume.                   933   // used per contained volume.
912   //                                              934   //
913   G4double smartlessComputed = noNodesExactD /    935   G4double smartlessComputed = noNodesExactD / nCandidates;
914   G4double smartlessUser = pVolume->GetSmartle    936   G4double smartlessUser = pVolume->GetSmartless();
915   G4double smartless = (smartlessComputed <= s    937   G4double smartless = (smartlessComputed <= smartlessUser)
916                        ? smartlessComputed : s    938                        ? smartlessComputed : smartlessUser;
917   G4double noNodesSmart = smartless*nCandidate    939   G4double noNodesSmart = smartless*nCandidates;
918   auto     noNodesExactI = G4int(noNodesSmart) << 940   G4int    noNodesExactI = G4int(noNodesSmart);
919   G4long   noNodes = ((noNodesSmart-noNodesExa << 941   G4int    noNodes = ((noNodesSmart-noNodesExactI)>=0.5)
920                      ? noNodesExactI+1 : noNod    942                      ? noNodesExactI+1 : noNodesExactI;
921   if( noNodes == 0 ) { noNodes=1; }               943   if( noNodes == 0 ) { noNodes=1; }
922                                                   944 
923 #ifdef G4GEOMETRY_VOXELDEBUG                      945 #ifdef G4GEOMETRY_VOXELDEBUG
924   G4cout << "     Smartless computed = " << sm    946   G4cout << "     Smartless computed = " << smartlessComputed << G4endl
925          << "     Smartless volume = " << smar    947          << "     Smartless volume = " << smartlessUser
926          << " => # Smartless = " << smartless     948          << " => # Smartless = " << smartless << G4endl;
927   G4cout << "     Min width = " << minWidth       949   G4cout << "     Min width = " << minWidth
928          << " => # Nodes = " << noNodes << G4e    950          << " => # Nodes = " << noNodes << G4endl;
929 #endif                                            951 #endif
930                                                   952 
931   if (noNodes>kMaxVoxelNodes)                     953   if (noNodes>kMaxVoxelNodes)
932   {                                               954   {
933     noNodes=kMaxVoxelNodes;                       955     noNodes=kMaxVoxelNodes;
934 #ifdef G4GEOMETRY_VOXELDEBUG                      956 #ifdef G4GEOMETRY_VOXELDEBUG
935     G4cout << "     Nodes Clipped to = " << kM    957     G4cout << "     Nodes Clipped to = " << kMaxVoxelNodes << G4endl;
936 #endif                                            958 #endif   
937   }                                               959   }
938   G4double nodeWidth = (motherMaxExtent-mother    960   G4double nodeWidth = (motherMaxExtent-motherMinExtent)/noNodes;
939                                                   961 
940   // Create G4VoxelNodes. Will Add proxies bef << 962 // Create G4VoxelNodes. Will Add proxies before setting fslices
941   //                                           << 963 //
942   auto* nodeList = new G4NodeVector();         << 964   G4NodeVector* nodeList = new G4NodeVector();
943   if (nodeList == nullptr)                     << 965   nodeList->reserve(noNodes);
                                                   >> 966   if (!nodeList)
944   {                                               967   {
945     G4Exception("G4SmartVoxelHeader::BuildNode << 968     G4cerr << "ERROR - G4SmartVoxelHeader::BuildNodes()" << G4endl
                                                   >> 969            << "        NodeList allocation failed." << G4endl;
                                                   >> 970     G4Exception("G4SmartVoxelHeader::BuildNodes()", "FatalError",
946                 FatalException, "NodeList allo    971                 FatalException, "NodeList allocation error.");
947     return nullptr;                            << 
948   }                                               972   }
949   nodeList->reserve(noNodes);                  << 973   for (nNode=0; nNode<noNodes; nNode++)
950                                                << 
951   for (nNode=0; G4long(nNode)<noNodes; ++nNode << 
952   {                                               974   {
953     G4SmartVoxelNode *pNode;                      975     G4SmartVoxelNode *pNode;
954     pNode = new G4SmartVoxelNode((G4int)nNode) << 976     pNode = new G4SmartVoxelNode(nNode);
955     if (pNode == nullptr)                      << 977     if (!pNode)
956     {                                             978     {
957       G4Exception("G4SmartVoxelHeader::BuildNo << 979       G4cerr << "ERROR - G4SmartVoxelHeader::BuildNodes()" << G4endl
                                                   >> 980              << "        Node allocation failed." << G4endl;
                                                   >> 981       G4Exception("G4SmartVoxelHeader::BuildNodes()", "FatalError",
958                   FatalException, "Node alloca    982                   FatalException, "Node allocation error.");
959       return nullptr;                          << 
960     }                                             983     }
961     nodeList->push_back(pNode);                   984     nodeList->push_back(pNode);
962   }                                               985   }
963                                                   986 
964   // All nodes created (empty)                    987   // All nodes created (empty)
965                                                   988 
966   // Fill nodes: Step through extent lists        989   // Fill nodes: Step through extent lists
967   //                                              990   //
968   for (nVol=0; nVol<nCandidates; ++nVol)       << 991   for (nVol=0; nVol<nCandidates; nVol++)
969   {                                               992   {
970     G4long nodeNo, minContainingNode, maxConta << 993     G4int nodeNo, minContainingNode, maxContainingNode;
971     minContainingNode = (minExtents[nVol]-moth << 994     minContainingNode = G4int((minExtents[nVol]-motherMinExtent)/nodeWidth);
972     maxContainingNode = (maxExtents[nVol]-moth << 995     maxContainingNode = G4int((maxExtents[nVol]-motherMinExtent)/nodeWidth);
973                                                   996 
974     // Only add nodes that are inside the limi    997     // Only add nodes that are inside the limits of the axis
975     //                                            998     //
976     if ( (maxContainingNode>=0) && (minContain    999     if ( (maxContainingNode>=0) && (minContainingNode<noNodes) )
977     {                                             1000     {
978       // If max extent is on max boundary => m    1001       // If max extent is on max boundary => maxContainingNode=noNodes:
979       // should be one less as nodeList has no    1002       // should be one less as nodeList has noNodes entries
980       //                                          1003       //
981       if (maxContainingNode>=noNodes)             1004       if (maxContainingNode>=noNodes)
982       {                                           1005       {
983         maxContainingNode = noNodes-1;            1006         maxContainingNode = noNodes-1;
984       }                                           1007       }
985       //                                          1008       //
986       // Protection against protruding volumes    1009       // Protection against protruding volumes
987       //                                          1010       //
988       if (minContainingNode<0)                    1011       if (minContainingNode<0)
989       {                                           1012       {
990         minContainingNode = 0;                 << 1013         minContainingNode=0;
991       }                                           1014       }
992       for (nodeNo=minContainingNode; nodeNo<=m << 1015       for (nodeNo=minContainingNode; nodeNo<=maxContainingNode; nodeNo++)
993       {                                           1016       {
994         (*nodeList)[nodeNo]->Insert((*pCandida    1017         (*nodeList)[nodeNo]->Insert((*pCandidates)[nVol]);
995       }                                           1018       }
996     }                                             1019     }
997   }                                               1020   }
998                                                   1021 
999   // All nodes filled                             1022   // All nodes filled
1000                                                  1023 
1001   // Create proxy List : caller has deletion     1024   // Create proxy List : caller has deletion responsibility
1002   // (but we must delete nodeList *itself* -     1025   // (but we must delete nodeList *itself* - not the contents)
1003   //                                             1026   //
1004   auto* proxyList = new G4ProxyVector();      << 1027   G4ProxyVector* proxyList = new G4ProxyVector();
1005   if (proxyList == nullptr)                   << 1028   proxyList->reserve(noNodes);
                                                   >> 1029   if (!proxyList)
1006   {                                              1030   {
1007     G4Exception("G4SmartVoxelHeader::BuildNod << 1031     G4cerr << "ERROR - G4SmartVoxelHeader::BuildNodes()" << G4endl
                                                   >> 1032            << "        Proxy list allocation failed." << G4endl;
                                                   >> 1033     G4Exception("G4SmartVoxelHeader::BuildNodes()", "FatalError",
1008                 FatalException, "Proxy list a    1034                 FatalException, "Proxy list allocation error.");
1009     return nullptr;                           << 
1010   }                                              1035   }
1011   proxyList->reserve(noNodes);                << 
1012                                               << 
1013   //                                             1036   //
1014   // Fill proxy List                             1037   // Fill proxy List
1015   //                                             1038   //
1016   for (nNode=0; G4long(nNode)<noNodes; ++nNod << 1039   for (nNode=0; nNode<noNodes; nNode++)
1017   {                                              1040   {
1018     // Get rid of possible excess capacity in << 1041     G4SmartVoxelProxy* pProxyNode = new G4SmartVoxelProxy((*nodeList)[nNode]);
1019     //                                        << 1042     if (!pProxyNode)
1020     ((*nodeList)[nNode])->Shrink();           << 
1021     auto* pProxyNode = new G4SmartVoxelProxy( << 
1022     if (pProxyNode == nullptr)                << 
1023     {                                            1043     {
1024       G4Exception("G4SmartVoxelHeader::BuildN << 1044       G4cerr << "ERROR - G4SmartVoxelHeader::BuildNodes()" << G4endl
                                                   >> 1045              << "        Proxy node allocation failed." << G4endl;
                                                   >> 1046       G4Exception("G4SmartVoxelHeader::BuildNodes()", "FatalError",
1025                   FatalException, "Proxy node    1047                   FatalException, "Proxy node allocation failed.");
1026       return nullptr;                         << 
1027     }                                            1048     }
1028     proxyList->push_back(pProxyNode);            1049     proxyList->push_back(pProxyNode);
1029   }                                              1050   }
1030   delete nodeList;                               1051   delete nodeList;
1031   return proxyList;                              1052   return proxyList;
1032 }                                                1053 }
1033                                                  1054 
1034 // ******************************************    1055 // ***************************************************************************
1035 // Calculate a "quality value" for the specif    1056 // Calculate a "quality value" for the specified vector of voxels.
1036 // The value returned should be >0 and such t    1057 // The value returned should be >0 and such that the smaller the number
1037 // the higher the quality of the slice.          1058 // the higher the quality of the slice.
1038 //                                               1059 //
1039 // Preconditions: pSlice must consist of G4Sm    1060 // Preconditions: pSlice must consist of G4SmartVoxelNodeProxies only
1040 // Process:                                      1061 // Process:
1041 // o Examine each node in turn, summing:         1062 // o Examine each node in turn, summing:
1042 //      no. of non-empty nodes                   1063 //      no. of non-empty nodes
1043 //      no. of volumes in each node              1064 //      no. of volumes in each node
1044 // o Calculate Quality=sigma(volumes in nod)/    1065 // o Calculate Quality=sigma(volumes in nod)/(no. of non-empty nodes)
1045 //      if all nodes empty, return kInfinity     1066 //      if all nodes empty, return kInfinity
1046 // o Call G4Exception on finding a G4SmartVox    1067 // o Call G4Exception on finding a G4SmartVoxelHeaderProxy
1047 // ******************************************    1068 // ***************************************************************************
1048 //                                               1069 //
1049 G4double G4SmartVoxelHeader::CalculateQuality    1070 G4double G4SmartVoxelHeader::CalculateQuality(G4ProxyVector *pSlice)
1050 {                                                1071 {
1051   G4double quality;                              1072   G4double quality;
1052   std::size_t nNodes = pSlice->size();        << 1073   G4int nNodes = pSlice->size();
1053   std::size_t noContained, maxContained=0, su << 1074   G4int noContained, maxContained=0, sumContained=0, sumNonEmptyNodes=0;
1054   G4SmartVoxelNode *node;                        1075   G4SmartVoxelNode *node;
1055                                                  1076 
1056   for (std::size_t i=0; i<nNodes; ++i)        << 1077   for (G4int i=0; i<nNodes; i++)
1057   {                                              1078   {
1058     if ((*pSlice)[i]->IsNode())                  1079     if ((*pSlice)[i]->IsNode())
1059     {                                            1080     {
1060       // Definitely a node. Add info to runni    1081       // Definitely a node. Add info to running totals
1061       //                                         1082       //
1062       node = (*pSlice)[i]->GetNode();            1083       node = (*pSlice)[i]->GetNode();
1063       noContained = node->GetNoContained();      1084       noContained = node->GetNoContained();
1064       if (noContained != 0)                   << 1085       if (noContained)
1065       {                                          1086       {
1066         ++sumNonEmptyNodes;                   << 1087         sumNonEmptyNodes++;
1067         sumContained += noContained;             1088         sumContained += noContained;
1068         //                                       1089         //
1069         // Calc maxContained for statistics      1090         // Calc maxContained for statistics
1070         //                                       1091         //
1071         if (noContained>maxContained)            1092         if (noContained>maxContained)
1072         {                                        1093         {
1073           maxContained = noContained;            1094           maxContained = noContained;
1074         }                                        1095         }
1075       }                                          1096       }
1076     }                                            1097     }
1077     else                                         1098     else
1078     {                                            1099     {
1079       G4Exception("G4SmartVoxelHeader::Calcul << 1100       G4cout << "ERROR - G4SmartVoxelHeader::CalculateQuality()" << G4endl
                                                   >> 1101              << "        Not defined for sliced volumes." << G4endl;
                                                   >> 1102       G4Exception("G4SmartVoxelHeader::CalculateQuality()", "NotApplicable",
1080                   FatalException, "Not applic    1103                   FatalException, "Not applicable to replicated volumes.");
1081     }                                            1104     }
1082   }                                              1105   }
1083                                                  1106 
1084   // Calculate quality with protection agains    1107   // Calculate quality with protection against no non-empty nodes
1085   //                                             1108   //
1086   if (sumNonEmptyNodes != 0)                  << 1109   if (sumNonEmptyNodes)
1087   {                                              1110   {
1088     quality = sumContained/sumNonEmptyNodes;     1111     quality = sumContained/sumNonEmptyNodes;
1089   }                                              1112   }
1090   else                                           1113   else
1091   {                                              1114   {
1092     quality = kInfinity;                         1115     quality = kInfinity;
1093   }                                              1116   }
1094                                                  1117 
1095 #ifdef G4GEOMETRY_VOXELDEBUG                     1118 #ifdef G4GEOMETRY_VOXELDEBUG
1096   G4cout << "**** G4SmartVoxelHeader::Calcula    1119   G4cout << "**** G4SmartVoxelHeader::CalculateQuality" << G4endl
1097          << "     Quality = " << quality << G    1120          << "     Quality = " << quality << G4endl
1098          << "     Nodes = " << nNodes            1121          << "     Nodes = " << nNodes 
1099          << " of which " << sumNonEmptyNodes     1122          << " of which " << sumNonEmptyNodes << " non empty" << G4endl
1100          << "     Max Contained = " << maxCon    1123          << "     Max Contained = " << maxContained << G4endl;
1101 #endif                                           1124 #endif
1102                                                  1125 
1103   return quality;                                1126   return quality;
1104 }                                                1127 }
1105                                                  1128 
1106 // ******************************************    1129 // ***************************************************************************
1107 // Examined each contained node, refines (cre    1130 // Examined each contained node, refines (creates a replacement additional
1108 // dimension of voxels) when there is more th    1131 // dimension of voxels) when there is more than one voxel in the slice.
1109 // Does not refine further if already limited    1132 // Does not refine further if already limited in two dimensions (=> this
1110 // is the third level of limits)                 1133 // is the third level of limits)
1111 //                                               1134 //
1112 // Preconditions: slices (nodes) have been bu    1135 // Preconditions: slices (nodes) have been built.
1113 // ******************************************    1136 // ***************************************************************************
1114 //                                               1137 //
1115 void G4SmartVoxelHeader::RefineNodes(G4Logica    1138 void G4SmartVoxelHeader::RefineNodes(G4LogicalVolume* pVolume,
1116                                      G4VoxelL    1139                                      G4VoxelLimits pLimits)
1117 {                                                1140 {
1118   std::size_t refinedDepth=0, minVolumes;     << 1141   G4int refinedDepth=0, minVolumes;
1119   std::size_t maxNode = fslices.size();       << 1142   G4int maxNode = fslices.size();
1120                                                  1143 
1121   if (pLimits.IsXLimited())                      1144   if (pLimits.IsXLimited()) 
1122   {                                              1145   {
1123     ++refinedDepth;                           << 1146     refinedDepth++;
1124   }                                              1147   }
1125   if (pLimits.IsYLimited())                      1148   if (pLimits.IsYLimited()) 
1126   {                                              1149   {
1127     ++refinedDepth;                           << 1150     refinedDepth++;
1128   }                                              1151   }
1129   if (pLimits.IsZLimited())                      1152   if (pLimits.IsZLimited()) 
1130   {                                              1153   {
1131     ++refinedDepth;                           << 1154     refinedDepth++;
1132   }                                              1155   }
1133                                                  1156 
1134   // Calculate minimum number of volumes nece    1157   // Calculate minimum number of volumes necessary to refine
1135   //                                             1158   //
1136   switch (refinedDepth)                          1159   switch (refinedDepth)
1137   {                                              1160   {
1138     case 0:                                      1161     case 0:
1139       minVolumes=kMinVoxelVolumesLevel2;         1162       minVolumes=kMinVoxelVolumesLevel2;
1140       break;                                     1163       break;
1141     case 1:                                      1164     case 1:
1142       minVolumes=kMinVoxelVolumesLevel3;         1165       minVolumes=kMinVoxelVolumesLevel3;
1143       break;                                     1166       break;
1144     default:                                     1167     default:
1145       minVolumes=10000;   // catch refinedDep    1168       minVolumes=10000;   // catch refinedDepth=3 and errors
1146       break;                                     1169       break;
1147   }                                              1170   }
1148                                                  1171 
1149   if (refinedDepth<2)                            1172   if (refinedDepth<2)
1150   {                                              1173   {
1151     std::size_t targetNo, noContainedDaughter << 1174     G4int targetNo, noContainedDaughters, minNo, maxNo, replaceNo, i;
1152     G4double sliceWidth = (fmaxExtent-fminExt    1175     G4double sliceWidth = (fmaxExtent-fminExtent)/maxNode;
1153     G4VoxelLimits newLimits;                     1176     G4VoxelLimits newLimits;
1154     G4SmartVoxelNode* targetNode;                1177     G4SmartVoxelNode* targetNode;
1155     G4SmartVoxelProxy* targetNodeProxy;          1178     G4SmartVoxelProxy* targetNodeProxy;
1156     G4SmartVoxelHeader* replaceHeader;           1179     G4SmartVoxelHeader* replaceHeader;
1157     G4SmartVoxelProxy* replaceHeaderProxy;       1180     G4SmartVoxelProxy* replaceHeaderProxy;
1158     G4VolumeNosVector* targetList;               1181     G4VolumeNosVector* targetList;
1159     G4SmartVoxelProxy* lastProxy;                1182     G4SmartVoxelProxy* lastProxy;
1160                                                  1183       
1161     for (targetNo=0; targetNo<maxNode; ++targ << 1184     for (targetNo=0; targetNo<maxNode; targetNo++)
1162     {                                            1185     {
1163       // Assume all slices are nodes (see pre    1186       // Assume all slices are nodes (see preconditions)
1164       //                                         1187       //
1165       targetNodeProxy = fslices[targetNo];       1188       targetNodeProxy = fslices[targetNo];
1166       targetNode = targetNodeProxy->GetNode()    1189       targetNode = targetNodeProxy->GetNode();
1167                                                  1190 
1168       if (targetNode->GetNoContained() >= min    1191       if (targetNode->GetNoContained() >= minVolumes)
1169       {                                          1192       {
1170         noContainedDaughters = targetNode->Ge    1193         noContainedDaughters = targetNode->GetNoContained();
1171         targetList = new G4VolumeNosVector();    1194         targetList = new G4VolumeNosVector();
1172         if (targetList == nullptr)            << 1195         targetList->reserve(noContainedDaughters);
                                                   >> 1196         if (!targetList)
1173         {                                        1197         {
                                                   >> 1198           G4cerr << "ERROR - G4SmartVoxelHeader::RefineNodes()" << G4endl
                                                   >> 1199                  << "        Target volume node list allocation failed."
                                                   >> 1200                  << G4endl;
1174           G4Exception("G4SmartVoxelHeader::Re    1201           G4Exception("G4SmartVoxelHeader::RefineNodes()",
1175                       "GeomMgt0003", FatalExc << 1202                       "FatalError", FatalException,
1176                       "Target volume node lis    1203                       "Target volume node list allocation error.");
1177           return;                             << 
1178         }                                        1204         }
1179         targetList->reserve(noContainedDaught << 1205         for (i=0; i<noContainedDaughters; i++)
1180         for (i=0; i<noContainedDaughters; ++i << 
1181         {                                        1206         {
1182           targetList->push_back(targetNode->G << 1207           targetList->push_back(targetNode->GetVolume(i));
1183         }                                        1208         }
1184         minNo = targetNode->GetMinEquivalentS    1209         minNo = targetNode->GetMinEquivalentSliceNo();
1185         maxNo = targetNode->GetMaxEquivalentS    1210         maxNo = targetNode->GetMaxEquivalentSliceNo();
1186                                                  1211 
1187 #ifdef G4GEOMETRY_VOXELDEBUG                     1212 #ifdef G4GEOMETRY_VOXELDEBUG
1188         G4cout << "**** G4SmartVoxelHeader::R    1213         G4cout << "**** G4SmartVoxelHeader::RefineNodes" << G4endl
1189                << "     Refining nodes " << m    1214                << "     Refining nodes " << minNo 
1190                << " - " << maxNo << " inclusi    1215                << " - " << maxNo << " inclusive" << G4endl;
1191 #endif                                           1216 #endif
1192         if (minNo > maxNo)    // Delete node  << 
1193         {                     // and avoid fu << 
1194           delete targetNode;                  << 
1195           delete targetList;                  << 
1196           return;                             << 
1197         }                                     << 
1198                                               << 
1199         // Delete node proxies at start of co    1217         // Delete node proxies at start of collected sets of nodes/headers
1200         //                                       1218         //
1201         lastProxy=nullptr;                    << 1219         lastProxy=0;
1202         for (replaceNo=minNo; replaceNo<=maxN << 1220         for (replaceNo=minNo; replaceNo<=maxNo; replaceNo++)
1203         {                                        1221         {
1204           if (lastProxy != fslices[replaceNo]    1222           if (lastProxy != fslices[replaceNo])
1205           {                                      1223           {
1206             lastProxy=fslices[replaceNo];        1224             lastProxy=fslices[replaceNo];
1207             delete lastProxy;                    1225             delete lastProxy;
1208           }                                      1226           }
1209         }                                        1227         }
1210         // Delete node to be replaced            1228         // Delete node to be replaced
1211         //                                       1229         //
1212         delete targetNode;                       1230         delete targetNode;
1213                                                  1231 
1214         // Create new headers + proxies and r    1232         // Create new headers + proxies and replace in fslices
1215         //                                       1233         //
1216         newLimits = pLimits;                     1234         newLimits = pLimits;
1217         newLimits.AddLimit(faxis,fminExtent+s    1235         newLimits.AddLimit(faxis,fminExtent+sliceWidth*minNo,
1218                            fminExtent+sliceWi    1236                            fminExtent+sliceWidth*(maxNo+1));
1219         replaceHeader = new G4SmartVoxelHeade    1237         replaceHeader = new G4SmartVoxelHeader(pVolume,newLimits,
1220                                               << 1238                                                targetList,replaceNo);
1221         if (replaceHeader == nullptr)         << 1239         if (!replaceHeader)
1222         {                                        1240         {
1223           G4Exception("G4SmartVoxelHeader::Re << 1241           G4cerr << "ERROR - G4SmartVoxelHeader::RefineNodes()" << G4endl
                                                   >> 1242                  << "        Refined VoxelHeader allocation failed." << G4endl;
                                                   >> 1243           G4Exception("G4SmartVoxelHeader::RefineNodes()", "FatalError",
1224                       FatalException, "Refine    1244                       FatalException, "Refined VoxelHeader allocation error.");
1225           return;                             << 
1226         }                                        1245         }
1227         replaceHeader->SetMinEquivalentSliceN << 1246         replaceHeader->SetMinEquivalentSliceNo(minNo);
1228         replaceHeader->SetMaxEquivalentSliceN << 1247         replaceHeader->SetMaxEquivalentSliceNo(maxNo);
1229         replaceHeaderProxy = new G4SmartVoxel    1248         replaceHeaderProxy = new G4SmartVoxelProxy(replaceHeader);
1230         if (replaceHeaderProxy == nullptr)    << 1249         if (!replaceHeader)
1231         {                                        1250         {
1232           G4Exception("G4SmartVoxelHeader::Re << 1251           G4cerr << "ERROR - G4SmartVoxelHeader::RefineNodes()" << G4endl
                                                   >> 1252                  << "        Refined VoxelProxy allocation failed." << G4endl;
                                                   >> 1253           G4Exception("G4SmartVoxelHeader::RefineNodes()", "FatalError",
1233                       FatalException, "Refine    1254                       FatalException, "Refined VoxelProxy allocation error.");
1234           return;                             << 
1235         }                                        1255         }
1236         for (replaceNo=minNo; replaceNo<=maxN << 1256         for (replaceNo=minNo; replaceNo<=maxNo; replaceNo++)
1237         {                                        1257         {
1238           fslices[replaceNo] = replaceHeaderP    1258           fslices[replaceNo] = replaceHeaderProxy;
1239         }                                        1259         }
1240         // Finished replacing current `equiva    1260         // Finished replacing current `equivalent' group
1241         //                                       1261         //
1242         delete targetList;                       1262         delete targetList;
1243         targetNo=maxNo;                          1263         targetNo=maxNo;
1244       }                                          1264       }
1245     }                                            1265     }
1246   }                                              1266   }
1247 }                                                1267 }
1248                                                  1268 
1249 // ******************************************    1269 // ***************************************************************************
1250 // Returns true if all slices have equal cont    1270 // Returns true if all slices have equal contents.
1251 // Preconditions: all equal slices have been     1271 // Preconditions: all equal slices have been collected.
1252 // Procedure:                                    1272 // Procedure:
1253 // o checks all slice proxy pointers are equa    1273 // o checks all slice proxy pointers are equal
1254 // o returns true if only one slice or all sl    1274 // o returns true if only one slice or all slice proxies pointers equal.
1255 // ******************************************    1275 // ***************************************************************************
1256 //                                               1276 //
1257 G4bool G4SmartVoxelHeader::AllSlicesEqual() c    1277 G4bool G4SmartVoxelHeader::AllSlicesEqual() const
1258 {                                                1278 {
1259   std::size_t noSlices = fslices.size();      << 1279   G4int noSlices = fslices.size();
1260   G4SmartVoxelProxy* refProxy;                   1280   G4SmartVoxelProxy* refProxy;
1261                                                  1281 
1262   if (noSlices>1)                                1282   if (noSlices>1)
1263   {                                              1283   {
1264     refProxy=fslices[0];                         1284     refProxy=fslices[0];
1265     for (std::size_t i=1; i<noSlices; ++i)    << 1285     for (G4int i=1; i<noSlices; i++)
1266     {                                            1286     {
1267       if (refProxy!=fslices[i])                  1287       if (refProxy!=fslices[i])
1268       {                                          1288       {
1269         return false;                            1289         return false;
1270       }                                          1290       }
1271     }                                            1291     }
1272   }                                              1292   }
1273   return true;                                   1293   return true;
1274 }                                                1294 }
1275                                                  1295 
1276 // ******************************************    1296 // ***************************************************************************
1277 // Streaming operator for debugging.             1297 // Streaming operator for debugging.
1278 // ******************************************    1298 // ***************************************************************************
1279 //                                               1299 //
1280 std::ostream& operator << (std::ostream& os,  << 1300 std::ostream& operator << (std::ostream& s, const G4SmartVoxelHeader& h)
1281 {                                                1301 {
1282   os << "Axis = " << G4int(h.faxis) << G4endl << 1302   s << "Axis = " << G4int(h.faxis) << G4endl;
1283   G4SmartVoxelProxy *collectNode=nullptr, *co << 1303   G4SmartVoxelProxy *collectNode=0, *collectHead=0;
1284   std::size_t collectNodeNo = 0;              << 1304   G4int collectNodeNo=0;
1285   std::size_t collectHeadNo = 0;              << 1305   G4int collectHeadNo=0;
1286   std::size_t i, j;                           << 1306   size_t i, j;
1287   G4bool haveHeaders = false;                 << 1307   G4bool haveHeaders=false;
1288                                                  1308 
1289   for (i=0; i<h.fslices.size(); ++i)          << 1309   for (i=0; i<h.fslices.size(); i++)
1290   {                                              1310   {
1291     os << "Slice #" << i << " = ";            << 1311     s << "Slice #" << i << " = ";
1292     if (h.fslices[i]->IsNode())                  1312     if (h.fslices[i]->IsNode())
1293     {                                            1313     {
1294       if (h.fslices[i]!=collectNode)             1314       if (h.fslices[i]!=collectNode)
1295       {                                          1315       {
1296         os << "{";                            << 1316         s << "{";
1297         for (std::size_t k=0; k<h.fslices[i]- << 1317         for (G4int j=0; j<h.fslices[i]->GetNode()->GetNoContained(); j++)
1298         {                                        1318         {
1299           os << " " << h.fslices[i]->GetNode( << 1319           s << " " << h.fslices[i]->GetNode()->GetVolume(j);
1300         }                                        1320         }
1301         os << " }" << G4endl;                 << 1321         s << " }" << G4endl;
1302         collectNode = h.fslices[i];              1322         collectNode = h.fslices[i];
1303         collectNodeNo = i;                       1323         collectNodeNo = i;
1304       }                                          1324       }
1305       else                                       1325       else
1306       {                                          1326       {
1307         os << "As slice #" << collectNodeNo < << 1327         s << "As slice #" << collectNodeNo << G4endl;
1308       }                                          1328       }
1309     }                                            1329     }
1310     else                                         1330     else
1311     {                                            1331     {
1312       haveHeaders=true;                          1332       haveHeaders=true;
1313       if (h.fslices[i] != collectHead)           1333       if (h.fslices[i] != collectHead)
1314       {                                          1334       {
1315         os << "Header" << G4endl;             << 1335         s << "Header" << G4endl;
1316         collectHead = h.fslices[i];              1336         collectHead = h.fslices[i];
1317         collectHeadNo = i;                       1337         collectHeadNo = i;
1318       }                                          1338       }
1319       else                                       1339       else
1320       {                                          1340       {
1321         os << "As slice #" << collectHeadNo < << 1341         s << "As slice #" << collectHeadNo << G4endl;
1322       }                                          1342       }
1323     }                                            1343     }
1324   }                                              1344   }
1325                                                  1345 
1326   if (haveHeaders)                               1346   if (haveHeaders)
1327   {                                              1347   {
1328     collectHead=nullptr;                      << 1348     collectHead=0;
1329     for (j=0; j<h.fslices.size(); ++j)        << 1349     for (j=0; j<h.fslices.size(); j++)
1330     {                                            1350     {
1331       if (h.fslices[j]->IsHeader())              1351       if (h.fslices[j]->IsHeader())
1332       {                                          1352       {
1333         os << "Header at Slice #" << j << " = << 1353         s << "Header at Slice #" << j << " = ";
1334         if (h.fslices[j] != collectHead)         1354         if (h.fslices[j] != collectHead)
1335         {                                        1355         {
1336           os << G4endl                        << 1356           s << G4endl 
1337              << (*(h.fslices[j]->GetHeader()) << 1357             << (*(h.fslices[j]->GetHeader()));
1338           collectHead = h.fslices[j];            1358           collectHead = h.fslices[j];
1339           collectHeadNo = j;                     1359           collectHeadNo = j;
1340         }                                        1360         }
1341         else                                     1361         else
1342         {                                        1362         {
1343           os << "As slice #" << collectHeadNo << 1363           s << "As slice #" << collectHeadNo << G4endl;
1344         }                                        1364         }
1345       }                                          1365       }
1346     }                                            1366     }
1347   }                                              1367   }
1348   return os;                                  << 1368   return s;
1349 }                                                1369 }
1350                                                  1370