Geant4 Cross Reference

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


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
                                                   >>  26 //
                                                   >>  27 // $Id:$
                                                   >>  28 //
                                                   >>  29 //
 26 // Implementation of G4BoundingEnvelope            30 // Implementation of G4BoundingEnvelope
 27 //                                                 31 //
 28 // 2016.05.25, E.Tcherniaev - initial version  <<  32 // Author: evgueni.tcherniaev@cern.ch
                                                   >>  33 //
                                                   >>  34 // 2016.05.25 E.Tcherniaev - initial version
                                                   >>  35 // 
 29 // -------------------------------------------     36 // --------------------------------------------------------------------
 30                                                    37 
 31 #include <cmath>                                   38 #include <cmath>
 32                                                << 
 33 #include "globals.hh"                              39 #include "globals.hh"
                                                   >>  40 
 34 #include "G4BoundingEnvelope.hh"                   41 #include "G4BoundingEnvelope.hh"
 35 #include "G4GeometryTolerance.hh"                  42 #include "G4GeometryTolerance.hh"
 36 #include "G4Normal3D.hh"                       << 
 37                                                    43 
 38 const G4double kCarTolerance =                     44 const G4double kCarTolerance =
 39   G4GeometryTolerance::GetInstance()->GetSurfa     45   G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
 40                                                    46 
 41 //////////////////////////////////////////////     47 ///////////////////////////////////////////////////////////////////////
 42 //                                                 48 //
 43 // Constructor from an axis aligned bounding b     49 // Constructor from an axis aligned bounding box
 44 //                                                 50 //
 45 G4BoundingEnvelope::G4BoundingEnvelope(const G     51 G4BoundingEnvelope::G4BoundingEnvelope(const G4ThreeVector& pMin,
 46                                        const G     52                                        const G4ThreeVector& pMax)
 47   : fMin(pMin), fMax(pMax)                     <<  53   : fMin(pMin), fMax(pMax), fPolygons(0)
 48 {                                                  54 {
 49   // Check correctness of bounding box             55   // Check correctness of bounding box
 50   //                                               56   //
 51   CheckBoundingBox();                              57   CheckBoundingBox();
 52 }                                                  58 }
 53                                                    59 
 54 //////////////////////////////////////////////     60 ///////////////////////////////////////////////////////////////////////
 55 //                                                 61 //
 56 // Constructor from a sequence of polygons         62 // Constructor from a sequence of polygons
 57 //                                                 63 //
 58 G4BoundingEnvelope::                               64 G4BoundingEnvelope::
 59 G4BoundingEnvelope(const std::vector<const G4T     65 G4BoundingEnvelope(const std::vector<const G4ThreeVectorList*>& polygons)
 60   : fPolygons(&polygons)                           66   : fPolygons(&polygons)
 61 {                                                  67 {
 62   // Check correctness of polygons                 68   // Check correctness of polygons
 63   //                                               69   //
 64   CheckBoundingPolygons();                         70   CheckBoundingPolygons();
 65                                                    71 
 66   // Set bounding box                              72   // Set bounding box
 67   //                                               73   //
 68   G4double xmin =  kInfinity, ymin =  kInfinit     74   G4double xmin =  kInfinity, ymin =  kInfinity, zmin =  kInfinity;
 69   G4double xmax = -kInfinity, ymax = -kInfinit     75   G4double xmax = -kInfinity, ymax = -kInfinity, zmax = -kInfinity;
 70   for (const auto & polygon : *fPolygons)      <<  76   std::vector<const G4ThreeVectorList*>::const_iterator ibase;
 71   {                                            <<  77   for (ibase = fPolygons->begin(); ibase != fPolygons->end(); ibase++)
 72     for (auto ipoint = polygon->cbegin(); ipoi <<  78   { 
                                                   >>  79     std::vector<G4ThreeVector>::const_iterator ipoint;
                                                   >>  80     for (ipoint = (*ibase)->begin(); ipoint != (*ibase)->end(); ipoint++)
 73     {                                              81     {
 74       G4double x = ipoint->x();                <<  82       G4double x = ipoint->x(); 
 75       if (x < xmin) xmin = x;                      83       if (x < xmin) xmin = x;
 76       if (x > xmax) xmax = x;                      84       if (x > xmax) xmax = x;
 77       G4double y = ipoint->y();                <<  85       G4double y = ipoint->y(); 
 78       if (y < ymin) ymin = y;                      86       if (y < ymin) ymin = y;
 79       if (y > ymax) ymax = y;                      87       if (y > ymax) ymax = y;
 80       G4double z = ipoint->z();                <<  88       G4double z = ipoint->z(); 
 81       if (z < zmin) zmin = z;                      89       if (z < zmin) zmin = z;
 82       if (z > zmax) zmax = z;                      90       if (z > zmax) zmax = z;
 83     }                                              91     }
 84   }                                                92   }
 85   fMin.set(xmin,ymin,zmin);                        93   fMin.set(xmin,ymin,zmin);
 86   fMax.set(xmax,ymax,zmax);                        94   fMax.set(xmax,ymax,zmax);
 87                                                    95 
 88   // Check correctness of bounding box             96   // Check correctness of bounding box
 89   //                                               97   //
 90   CheckBoundingBox();                              98   CheckBoundingBox();
 91 }                                                  99 }
 92                                                   100 
 93 //////////////////////////////////////////////    101 ///////////////////////////////////////////////////////////////////////
 94 //                                                102 //
 95 // Constructor from a bounding box and a seque    103 // Constructor from a bounding box and a sequence of polygons
 96 //                                                104 //
 97 G4BoundingEnvelope::                              105 G4BoundingEnvelope::
 98 G4BoundingEnvelope( const G4ThreeVector& pMin,    106 G4BoundingEnvelope( const G4ThreeVector& pMin,
 99                     const G4ThreeVector& pMax,    107                     const G4ThreeVector& pMax,
100                     const std::vector<const G4    108                     const std::vector<const G4ThreeVectorList*>& polygons)
101   : fMin(pMin), fMax(pMax), fPolygons(&polygon    109   : fMin(pMin), fMax(pMax), fPolygons(&polygons)
102 {                                                 110 {
103   // Check correctness of bounding box and pol    111   // Check correctness of bounding box and polygons
104   //                                           << 112   // 
105   CheckBoundingBox();                             113   CheckBoundingBox();
106   CheckBoundingPolygons();                        114   CheckBoundingPolygons();
107 }                                                 115 }
108                                                   116 
109 //////////////////////////////////////////////    117 ///////////////////////////////////////////////////////////////////////
110 //                                                118 //
                                                   >> 119 // Destructor
                                                   >> 120 //
                                                   >> 121 G4BoundingEnvelope::~G4BoundingEnvelope()
                                                   >> 122 {
                                                   >> 123 }
                                                   >> 124 
                                                   >> 125 ///////////////////////////////////////////////////////////////////////
                                                   >> 126 //
111 // Check correctness of the axis aligned bound    127 // Check correctness of the axis aligned bounding box
112 //                                                128 //
113 void G4BoundingEnvelope::CheckBoundingBox()       129 void G4BoundingEnvelope::CheckBoundingBox()
114 {                                                 130 {
115   if (fMin.x() >= fMax.x() || fMin.y() >= fMax    131   if (fMin.x() >= fMax.x() || fMin.y() >= fMax.y() || fMin.z() >= fMax.z())
116   {                                               132   {
117     std::ostringstream message;                   133     std::ostringstream message;
118     message << "Badly defined bounding box (mi    134     message << "Badly defined bounding box (min >= max)!"
119             << "\npMin = " << fMin             << 135             << "\npMin = " << fMin 
120             << "\npMax = " << fMax;               136             << "\npMax = " << fMax;
121     G4Exception("G4BoundingEnvelope::CheckBoun    137     G4Exception("G4BoundingEnvelope::CheckBoundingBox()",
122                 "GeomMgt0001", JustWarning, me    138                 "GeomMgt0001", JustWarning, message);
123   }                                               139   }
124 }                                                 140 }
125                                                   141 
126 //////////////////////////////////////////////    142 ///////////////////////////////////////////////////////////////////////
127 //                                                143 //
128 // Check correctness of the sequence of boundi    144 // Check correctness of the sequence of bounding polygons.
129 // Firsf and last polygons may consist of a si    145 // Firsf and last polygons may consist of a single vertex
130 //                                                146 //
131 void G4BoundingEnvelope::CheckBoundingPolygons    147 void G4BoundingEnvelope::CheckBoundingPolygons()
132 {                                                 148 {
133   std::size_t nbases = fPolygons->size();      << 149   G4int nbases = fPolygons->size();
134   if (nbases < 2)                                 150   if (nbases < 2)
135   {                                               151   {
136     std::ostringstream message;                   152     std::ostringstream message;
137     message << "Wrong number of polygons in th    153     message << "Wrong number of polygons in the sequence: " << nbases
138             << "\nShould be at least two!";       154             << "\nShould be at least two!";
139     G4Exception("G4BoundingEnvelope::CheckBoun << 155     G4Exception("G4BoundingEnvelope::CheckBoundingPolygons()", 
140                 "GeomMgt0001", FatalException,    156                 "GeomMgt0001", FatalException, message);
141     return;                                       157     return;
142   }                                               158   }
143                                                   159 
144   std::size_t nsize  = std::max((*fPolygons)[0 << 160   G4int nsize  = std::max((*fPolygons)[0]->size(),(*fPolygons)[1]->size());
145   if (nsize < 3)                                  161   if (nsize < 3)
146   {                                               162   {
147     std::ostringstream message;                   163     std::ostringstream message;
148     message << "Badly constructed polygons!"      164     message << "Badly constructed polygons!"
149             << "\nNumber of polygons: " << nba    165             << "\nNumber of polygons: " << nbases
150             << "\nPolygon #0 size: " << (*fPol    166             << "\nPolygon #0 size: " << (*fPolygons)[0]->size()
151             << "\nPolygon #1 size: " << (*fPol    167             << "\nPolygon #1 size: " << (*fPolygons)[1]->size()
152             << "\n...";                           168             << "\n...";
153     G4Exception("G4BoundingEnvelope::CheckBoun << 169     G4Exception("G4BoundingEnvelope::CheckBoundingPolygons()", 
154                 "GeomMgt0001", FatalException,    170                 "GeomMgt0001", FatalException, message);
155     return;                                       171     return;
156   }                                               172   }
157                                                   173 
158   for (std::size_t k=0; k<nbases; ++k)         << 174   for (G4int k=0; k<nbases; ++k)
159   {                                               175   {
160     std::size_t np = (*fPolygons)[k]->size();  << 176     G4int np = (*fPolygons)[k]->size();
161     if (np == nsize)            continue;         177     if (np == nsize)            continue;
162     if (np == 1 && k==0)        continue;         178     if (np == 1 && k==0)        continue;
163     if (np == 1 && k==nbases-1) continue;         179     if (np == 1 && k==nbases-1) continue;
164     std::ostringstream message;                   180     std::ostringstream message;
165     message << "Badly constructed polygons!"      181     message << "Badly constructed polygons!"
166             << "\nNumber of polygons: " << nba    182             << "\nNumber of polygons: " << nbases
167             << "\nPolygon #" << k << " size: "    183             << "\nPolygon #" << k << " size: " << np
168             << "\nexpected size: " << nsize;      184             << "\nexpected size: " << nsize;
169     G4Exception("G4BoundingEnvelope::SetBoundi << 185     G4Exception("G4BoundingEnvelope::SetBoundingPolygons()", 
170                 "GeomMgt0001", FatalException,    186                 "GeomMgt0001", FatalException, message);
171     return;                                       187     return;
172   }                                            << 188   }  
173 }                                                 189 }
174                                                   190 
175 //////////////////////////////////////////////    191 ///////////////////////////////////////////////////////////////////////
176 //                                                192 //
177 // Quick comparison: bounding box vs voxel, it    193 // Quick comparison: bounding box vs voxel, it return true if further
178 // calculations are not needed                    194 // calculations are not needed
179 //                                                195 //
180 G4bool                                            196 G4bool
181 G4BoundingEnvelope::                              197 G4BoundingEnvelope::
182 BoundingBoxVsVoxelLimits(const EAxis pAxis,       198 BoundingBoxVsVoxelLimits(const EAxis pAxis,
183                          const G4VoxelLimits&     199                          const G4VoxelLimits& pVoxelLimits,
184                          const G4Transform3D&     200                          const G4Transform3D& pTransform3D,
185                          G4double& pMin, G4dou    201                          G4double& pMin, G4double& pMax) const
186 {                                                 202 {
187   pMin =  kInfinity;                              203   pMin =  kInfinity;
188   pMax = -kInfinity;                              204   pMax = -kInfinity;
189   G4double xminlim = pVoxelLimits.GetMinXExten    205   G4double xminlim = pVoxelLimits.GetMinXExtent();
190   G4double xmaxlim = pVoxelLimits.GetMaxXExten    206   G4double xmaxlim = pVoxelLimits.GetMaxXExtent();
191   G4double yminlim = pVoxelLimits.GetMinYExten    207   G4double yminlim = pVoxelLimits.GetMinYExtent();
192   G4double ymaxlim = pVoxelLimits.GetMaxYExten    208   G4double ymaxlim = pVoxelLimits.GetMaxYExtent();
193   G4double zminlim = pVoxelLimits.GetMinZExten    209   G4double zminlim = pVoxelLimits.GetMinZExtent();
194   G4double zmaxlim = pVoxelLimits.GetMaxZExten    210   G4double zmaxlim = pVoxelLimits.GetMaxZExtent();
195                                                   211 
196   // Special case of pure translation             212   // Special case of pure translation
197   //                                              213   //
198   if (pTransform3D.xx()==1 && pTransform3D.yy(    214   if (pTransform3D.xx()==1 && pTransform3D.yy()==1 && pTransform3D.zz()==1)
199   {                                               215   {
200     G4double xmin = fMin.x() + pTransform3D.dx    216     G4double xmin = fMin.x() + pTransform3D.dx();
201     G4double xmax = fMax.x() + pTransform3D.dx    217     G4double xmax = fMax.x() + pTransform3D.dx();
202     G4double ymin = fMin.y() + pTransform3D.dy    218     G4double ymin = fMin.y() + pTransform3D.dy();
203     G4double ymax = fMax.y() + pTransform3D.dy    219     G4double ymax = fMax.y() + pTransform3D.dy();
204     G4double zmin = fMin.z() + pTransform3D.dz    220     G4double zmin = fMin.z() + pTransform3D.dz();
205     G4double zmax = fMax.z() + pTransform3D.dz    221     G4double zmax = fMax.z() + pTransform3D.dz();
206                                                   222 
207     if (xmin-kCarTolerance > xmaxlim) return t    223     if (xmin-kCarTolerance > xmaxlim) return true;
208     if (xmax+kCarTolerance < xminlim) return t    224     if (xmax+kCarTolerance < xminlim) return true;
209     if (ymin-kCarTolerance > ymaxlim) return t    225     if (ymin-kCarTolerance > ymaxlim) return true;
210     if (ymax+kCarTolerance < yminlim) return t    226     if (ymax+kCarTolerance < yminlim) return true;
211     if (zmin-kCarTolerance > zmaxlim) return t    227     if (zmin-kCarTolerance > zmaxlim) return true;
212     if (zmax+kCarTolerance < zminlim) return t    228     if (zmax+kCarTolerance < zminlim) return true;
213                                                   229 
214     if (xmin >= xminlim && xmax <= xmaxlim &&     230     if (xmin >= xminlim && xmax <= xmaxlim &&
215         ymin >= yminlim && ymax <= ymaxlim &&     231         ymin >= yminlim && ymax <= ymaxlim &&
216         zmin >= zminlim && zmax <= zmaxlim)       232         zmin >= zminlim && zmax <= zmaxlim)
217     {                                             233     {
218       if (pAxis == kXAxis)                        234       if (pAxis == kXAxis)
219       {                                           235       {
220         pMin = (xmin-kCarTolerance < xminlim)     236         pMin = (xmin-kCarTolerance < xminlim) ? xminlim : xmin;
221         pMax = (xmax+kCarTolerance > xmaxlim)     237         pMax = (xmax+kCarTolerance > xmaxlim) ? xmaxlim : xmax;
222       }                                        << 238       } 
223       else if (pAxis == kYAxis)                   239       else if (pAxis == kYAxis)
224       {                                           240       {
225         pMin = (ymin-kCarTolerance < yminlim)     241         pMin = (ymin-kCarTolerance < yminlim) ? yminlim : ymin;
226         pMax = (ymax+kCarTolerance > ymaxlim)     242         pMax = (ymax+kCarTolerance > ymaxlim) ? ymaxlim : ymax;
227       }                                           243       }
228       else if (pAxis == kZAxis)                   244       else if (pAxis == kZAxis)
229       {                                           245       {
230         pMin = (zmin-kCarTolerance < zminlim)     246         pMin = (zmin-kCarTolerance < zminlim) ? zminlim : zmin;
231         pMax = (zmax+kCarTolerance > zmaxlim)     247         pMax = (zmax+kCarTolerance > zmaxlim) ? zmaxlim : zmax;
232       }                                           248       }
233       pMin -= kCarTolerance;                      249       pMin -= kCarTolerance;
234       pMax += kCarTolerance;                      250       pMax += kCarTolerance;
235       return true;                                251       return true;
236     }                                             252     }
237   }                                               253   }
238                                                   254 
239   // Find max scale factor of the transformati << 255   // Find max scale factor of the transformation, set delta 
240   // equal to kCarTolerance multiplied by the     256   // equal to kCarTolerance multiplied by the scale factor
241   //                                              257   //
242   G4double scale = FindScaleFactor(pTransform3    258   G4double scale = FindScaleFactor(pTransform3D);
243   G4double delta = kCarTolerance*scale;        << 259   G4double delta = kCarTolerance*scale;  
244                                                   260 
245   // Set the sphere surrounding the bounding b    261   // Set the sphere surrounding the bounding box
246   //                                              262   //
247   G4Point3D center = pTransform3D*G4Point3D(0.    263   G4Point3D center = pTransform3D*G4Point3D(0.5*(fMin+fMax));
248   G4double  radius = 0.5*scale*(fMax-fMin).mag    264   G4double  radius = 0.5*scale*(fMax-fMin).mag() + delta;
249                                                   265 
250   // Check if the sphere surrounding the bound    266   // Check if the sphere surrounding the bounding box is outside
251   // the voxel limits                             267   // the voxel limits
252   //                                              268   //
253   if (center.x()-radius > xmaxlim) return true    269   if (center.x()-radius > xmaxlim) return true;
254   if (center.y()-radius > ymaxlim) return true    270   if (center.y()-radius > ymaxlim) return true;
255   if (center.z()-radius > zmaxlim) return true    271   if (center.z()-radius > zmaxlim) return true;
256   if (center.x()+radius < xminlim) return true    272   if (center.x()+radius < xminlim) return true;
257   if (center.y()+radius < yminlim) return true    273   if (center.y()+radius < yminlim) return true;
258   if (center.z()+radius < zminlim) return true    274   if (center.z()+radius < zminlim) return true;
259   return false;                                   275   return false;
260 }                                                 276 }
261                                                   277 
262 //////////////////////////////////////////////    278 ///////////////////////////////////////////////////////////////////////
263 //                                                279 //
264 // Calculate extent of the specified bounding     280 // Calculate extent of the specified bounding envelope
265 //                                                281 //
266 G4bool                                            282 G4bool
267 G4BoundingEnvelope::CalculateExtent(const EAxi    283 G4BoundingEnvelope::CalculateExtent(const EAxis pAxis,
268                                     const G4Vo    284                                     const G4VoxelLimits& pVoxelLimits,
269                                     const G4Tr    285                                     const G4Transform3D& pTransform3D,
270                                     G4double&     286                                     G4double& pMin, G4double& pMax) const
271 {                                                 287 {
272   pMin =  kInfinity;                              288   pMin =  kInfinity;
273   pMax = -kInfinity;                              289   pMax = -kInfinity;
274   G4double xminlim = pVoxelLimits.GetMinXExten    290   G4double xminlim = pVoxelLimits.GetMinXExtent();
275   G4double xmaxlim = pVoxelLimits.GetMaxXExten    291   G4double xmaxlim = pVoxelLimits.GetMaxXExtent();
276   G4double yminlim = pVoxelLimits.GetMinYExten    292   G4double yminlim = pVoxelLimits.GetMinYExtent();
277   G4double ymaxlim = pVoxelLimits.GetMaxYExten    293   G4double ymaxlim = pVoxelLimits.GetMaxYExtent();
278   G4double zminlim = pVoxelLimits.GetMinZExten    294   G4double zminlim = pVoxelLimits.GetMinZExtent();
279   G4double zmaxlim = pVoxelLimits.GetMaxZExten    295   G4double zmaxlim = pVoxelLimits.GetMaxZExtent();
280                                                   296 
281   // Special case of pure translation             297   // Special case of pure translation
282   //                                              298   //
283   if (pTransform3D.xx()==1 && pTransform3D.yy(    299   if (pTransform3D.xx()==1 && pTransform3D.yy()==1 && pTransform3D.zz()==1)
284   {                                               300   {
285     G4double xmin = fMin.x() + pTransform3D.dx    301     G4double xmin = fMin.x() + pTransform3D.dx();
286     G4double xmax = fMax.x() + pTransform3D.dx    302     G4double xmax = fMax.x() + pTransform3D.dx();
287     G4double ymin = fMin.y() + pTransform3D.dy    303     G4double ymin = fMin.y() + pTransform3D.dy();
288     G4double ymax = fMax.y() + pTransform3D.dy    304     G4double ymax = fMax.y() + pTransform3D.dy();
289     G4double zmin = fMin.z() + pTransform3D.dz    305     G4double zmin = fMin.z() + pTransform3D.dz();
290     G4double zmax = fMax.z() + pTransform3D.dz    306     G4double zmax = fMax.z() + pTransform3D.dz();
291                                                   307 
292     if (xmin-kCarTolerance > xmaxlim) return f    308     if (xmin-kCarTolerance > xmaxlim) return false;
293     if (xmax+kCarTolerance < xminlim) return f    309     if (xmax+kCarTolerance < xminlim) return false;
294     if (ymin-kCarTolerance > ymaxlim) return f    310     if (ymin-kCarTolerance > ymaxlim) return false;
295     if (ymax+kCarTolerance < yminlim) return f    311     if (ymax+kCarTolerance < yminlim) return false;
296     if (zmin-kCarTolerance > zmaxlim) return f    312     if (zmin-kCarTolerance > zmaxlim) return false;
297     if (zmax+kCarTolerance < zminlim) return f    313     if (zmax+kCarTolerance < zminlim) return false;
298                                                   314 
299     if (fPolygons == nullptr)                  << 315     if (fPolygons == 0)
300     {                                             316     {
301       if (pAxis == kXAxis)                        317       if (pAxis == kXAxis)
302       {                                           318       {
303         pMin = (xmin-kCarTolerance < xminlim)     319         pMin = (xmin-kCarTolerance < xminlim) ? xminlim : xmin;
304         pMax = (xmax+kCarTolerance > xmaxlim)     320         pMax = (xmax+kCarTolerance > xmaxlim) ? xmaxlim : xmax;
305       }                                        << 321       } 
306       else if (pAxis == kYAxis)                   322       else if (pAxis == kYAxis)
307       {                                           323       {
308         pMin = (ymin-kCarTolerance < yminlim)     324         pMin = (ymin-kCarTolerance < yminlim) ? yminlim : ymin;
309         pMax = (ymax+kCarTolerance > ymaxlim)     325         pMax = (ymax+kCarTolerance > ymaxlim) ? ymaxlim : ymax;
310       }                                           326       }
311       else if (pAxis == kZAxis)                   327       else if (pAxis == kZAxis)
312       {                                           328       {
313         pMin = (zmin-kCarTolerance < zminlim)     329         pMin = (zmin-kCarTolerance < zminlim) ? zminlim : zmin;
314         pMax = (zmax+kCarTolerance > zmaxlim)     330         pMax = (zmax+kCarTolerance > zmaxlim) ? zmaxlim : zmax;
315       }                                           331       }
316       pMin -= kCarTolerance;                      332       pMin -= kCarTolerance;
317       pMax += kCarTolerance;                      333       pMax += kCarTolerance;
318       return true;                                334       return true;
319     }                                             335     }
320   }                                               336   }
321                                                   337 
322   // Find max scale factor of the transformati << 338   // Find max scale factor of the transformation, set delta 
323   // equal to kCarTolerance multiplied by the     339   // equal to kCarTolerance multiplied by the scale factor
324   //                                              340   //
325   G4double scale = FindScaleFactor(pTransform3    341   G4double scale = FindScaleFactor(pTransform3D);
326   G4double delta = kCarTolerance*scale;        << 342   G4double delta = kCarTolerance*scale;  
327                                                   343 
328   // Set the sphere surrounding the bounding b    344   // Set the sphere surrounding the bounding box
329   //                                              345   //
330   G4Point3D center = pTransform3D*G4Point3D(0.    346   G4Point3D center = pTransform3D*G4Point3D(0.5*(fMin+fMax));
331   G4double  radius = 0.5*scale*(fMax-fMin).mag    347   G4double  radius = 0.5*scale*(fMax-fMin).mag() + delta;
332                                                   348 
333   // Check if the sphere surrounding the bound    349   // Check if the sphere surrounding the bounding box is within
334   // the voxel limits, if so then transform on    350   // the voxel limits, if so then transform only one coordinate
335   //                                              351   //
336   if (center.x()-radius >= xminlim && center.x    352   if (center.x()-radius >= xminlim && center.x()+radius <= xmaxlim &&
337       center.y()-radius >= yminlim && center.y    353       center.y()-radius >= yminlim && center.y()+radius <= ymaxlim &&
338       center.z()-radius >= zminlim && center.z    354       center.z()-radius >= zminlim && center.z()+radius <= zmaxlim )
339   {                                               355   {
340     G4double cx, cy, cz, cd;                      356     G4double cx, cy, cz, cd;
341     if (pAxis == kXAxis)                          357     if (pAxis == kXAxis)
342     {                                          << 358     { 
343       cx = pTransform3D.xx();                  << 359       cx = pTransform3D.xx(); 
344       cy = pTransform3D.xy();                     360       cy = pTransform3D.xy();
345       cz = pTransform3D.xz();                     361       cz = pTransform3D.xz();
346       cd = pTransform3D.dx();                     362       cd = pTransform3D.dx();
347     }                                             363     }
348     else if (pAxis == kYAxis)                     364     else if (pAxis == kYAxis)
349     {                                          << 365     { 
350       cx = pTransform3D.yx();                  << 366       cx = pTransform3D.yx(); 
351       cy = pTransform3D.yy();                     367       cy = pTransform3D.yy();
352       cz = pTransform3D.yz();                     368       cz = pTransform3D.yz();
353       cd = pTransform3D.dy();                     369       cd = pTransform3D.dy();
354     }                                             370     }
355     else if (pAxis == kZAxis)                     371     else if (pAxis == kZAxis)
356     {                                          << 372     { 
357       cx = pTransform3D.zx();                  << 373       cx = pTransform3D.zx(); 
358       cy = pTransform3D.zy();                     374       cy = pTransform3D.zy();
359       cz = pTransform3D.zz();                     375       cz = pTransform3D.zz();
360       cd = pTransform3D.dz();                     376       cd = pTransform3D.dz();
361     }                                             377     }
362     else                                          378     else
363     {                                          << 379     { 
364       cx = cy = cz = cd = kInfinity;              380       cx = cy = cz = cd = kInfinity;
365     }                                             381     }
366     G4double emin = kInfinity, emax = -kInfini    382     G4double emin = kInfinity, emax = -kInfinity;
367     if (fPolygons == nullptr)                  << 383     if (fPolygons == 0)
368     {                                             384     {
369       G4double coor;                              385       G4double coor;
370       coor = cx*fMin.x() + cy*fMin.y() + cz*fM    386       coor = cx*fMin.x() + cy*fMin.y() + cz*fMin.z() + cd;
371       if (coor < emin) emin = coor;               387       if (coor < emin) emin = coor;
372       if (coor > emax) emax = coor;               388       if (coor > emax) emax = coor;
373       coor = cx*fMax.x() + cy*fMin.y() + cz*fM    389       coor = cx*fMax.x() + cy*fMin.y() + cz*fMin.z() + cd;
374       if (coor < emin) emin = coor;               390       if (coor < emin) emin = coor;
375       if (coor > emax) emax = coor;               391       if (coor > emax) emax = coor;
376       coor = cx*fMax.x() + cy*fMax.y() + cz*fM    392       coor = cx*fMax.x() + cy*fMax.y() + cz*fMin.z() + cd;
377       if (coor < emin) emin = coor;               393       if (coor < emin) emin = coor;
378       if (coor > emax) emax = coor;               394       if (coor > emax) emax = coor;
379       coor = cx*fMin.x() + cy*fMax.y() + cz*fM    395       coor = cx*fMin.x() + cy*fMax.y() + cz*fMin.z() + cd;
380       if (coor < emin) emin = coor;               396       if (coor < emin) emin = coor;
381       if (coor > emax) emax = coor;               397       if (coor > emax) emax = coor;
382       coor = cx*fMin.x() + cy*fMin.y() + cz*fM    398       coor = cx*fMin.x() + cy*fMin.y() + cz*fMax.z() + cd;
383       if (coor < emin) emin = coor;               399       if (coor < emin) emin = coor;
384       if (coor > emax) emax = coor;               400       if (coor > emax) emax = coor;
385       coor = cx*fMax.x() + cy*fMin.y() + cz*fM    401       coor = cx*fMax.x() + cy*fMin.y() + cz*fMax.z() + cd;
386       if (coor < emin) emin = coor;               402       if (coor < emin) emin = coor;
387       if (coor > emax) emax = coor;               403       if (coor > emax) emax = coor;
388       coor = cx*fMax.x() + cy*fMax.y() + cz*fM    404       coor = cx*fMax.x() + cy*fMax.y() + cz*fMax.z() + cd;
389       if (coor < emin) emin = coor;               405       if (coor < emin) emin = coor;
390       if (coor > emax) emax = coor;               406       if (coor > emax) emax = coor;
391       coor = cx*fMin.x() + cy*fMax.y() + cz*fM    407       coor = cx*fMin.x() + cy*fMax.y() + cz*fMax.z() + cd;
392       if (coor < emin) emin = coor;               408       if (coor < emin) emin = coor;
393       if (coor > emax) emax = coor;               409       if (coor > emax) emax = coor;
394     }                                             410     }
395     else                                          411     else
396     {                                             412     {
397       for (const auto & polygon : *fPolygons)  << 413       std::vector<const G4ThreeVectorList*>::const_iterator ibase;
398       {                                        << 414       for (ibase = fPolygons->begin(); ibase != fPolygons->end(); ibase++)
399         for (auto ipoint=polygon->cbegin(); ip << 415       { 
                                                   >> 416         G4ThreeVectorList::const_iterator ipoint;
                                                   >> 417         for (ipoint = (*ibase)->begin(); ipoint != (*ibase)->end(); ipoint++)
400         {                                         418         {
401           G4double coor = ipoint->x()*cx + ipo    419           G4double coor = ipoint->x()*cx + ipoint->y()*cy + ipoint->z()*cz + cd;
402           if (coor < emin) emin = coor;           420           if (coor < emin) emin = coor;
403           if (coor > emax) emax = coor;           421           if (coor > emax) emax = coor;
404         }                                         422         }
405       }                                           423       }
406     }                                             424     }
407     pMin = emin - delta;                          425     pMin = emin - delta;
408     pMax = emax + delta;                          426     pMax = emax + delta;
409     return true;                                  427     return true;
410   }                                            << 428   } 
411                                                   429 
412   // Check if the sphere surrounding the bound    430   // Check if the sphere surrounding the bounding box is outside
413   // the voxel limits                             431   // the voxel limits
414   //                                              432   //
415   if (center.x()-radius > xmaxlim) return fals    433   if (center.x()-radius > xmaxlim) return false;
416   if (center.y()-radius > ymaxlim) return fals    434   if (center.y()-radius > ymaxlim) return false;
417   if (center.z()-radius > zmaxlim) return fals    435   if (center.z()-radius > zmaxlim) return false;
418   if (center.x()+radius < xminlim) return fals    436   if (center.x()+radius < xminlim) return false;
419   if (center.y()+radius < yminlim) return fals    437   if (center.y()+radius < yminlim) return false;
420   if (center.z()+radius < zminlim) return fals    438   if (center.z()+radius < zminlim) return false;
421                                                   439 
422   // Transform polygons                        << 440   // Allocate memory for transformed polygons
423   //                                              441   //
424   std::vector<G4Point3D> vertices;             << 442   G4int nbases = (fPolygons == 0) ? 2 : fPolygons->size();
425   std::vector<std::pair<G4int, G4int>> bases;  << 443   std::vector<G4Polygon3D*> bases(nbases);
426   TransformVertices(pTransform3D, vertices, ba << 444   if (fPolygons == 0)
427   std::size_t nbases = bases.size();           << 445   {
                                                   >> 446     bases[0] = new G4Polygon3D(4); 
                                                   >> 447     bases[1] = new G4Polygon3D(4);
                                                   >> 448   }
                                                   >> 449   else
                                                   >> 450   {
                                                   >> 451     for (G4int i=0; i<nbases; ++i)
                                                   >> 452     { 
                                                   >> 453       bases[i] = new G4Polygon3D((*fPolygons)[i]->size());
                                                   >> 454     }
                                                   >> 455   }
                                                   >> 456 
                                                   >> 457   //  Transform vertices 
                                                   >> 458   //
                                                   >> 459   TransformVertices(pTransform3D, bases);
428                                                   460 
429   // Create adjusted G4VoxelLimits box. New li << 461   // Create adjusted G4VoxelLimits box. New limits are extended by 
430   // delta, kCarTolerance multiplied by max sc    462   // delta, kCarTolerance multiplied by max scale factor of
431   // the transformation                           463   // the transformation
432   //                                              464   //
433   EAxis axes[] = { kXAxis, kYAxis, kZAxis };   << 465   EAxis axis[] = { kXAxis,kYAxis,kZAxis };
434   G4VoxelLimits limits; // default is unlimite << 466   G4VoxelLimits limits; // default is unlimited 
435   for (const auto & iAxis : axes)              << 467   for (G4int i=0; i<3; ++i)
436   {                                            << 468   {
437     if (pVoxelLimits.IsLimited(iAxis))         << 469     if (pVoxelLimits.IsLimited(axis[i]))
438     {                                          << 470     {
439       G4double emin = pVoxelLimits.GetMinExten << 471       G4double emin = pVoxelLimits.GetMinExtent(axis[i]) - delta;
440       G4double emax = pVoxelLimits.GetMaxExten << 472       G4double emax = pVoxelLimits.GetMaxExtent(axis[i]) + delta;
441       limits.AddLimit(iAxis, emin, emax);      << 473       limits.AddLimit(axis[i], emin, emax);
442     }                                             474     }
443   }                                               475   }
444                                                   476 
445   // Main loop along the set of prisms            477   // Main loop along the set of prisms
446   //                                              478   //
447   G4Polygon3D baseA, baseB;                    << 
448   G4Segment3D extent;                             479   G4Segment3D extent;
449   extent.first  = G4Point3D( kInfinity, kInfin    480   extent.first  = G4Point3D( kInfinity, kInfinity, kInfinity);
450   extent.second = G4Point3D(-kInfinity,-kInfin    481   extent.second = G4Point3D(-kInfinity,-kInfinity,-kInfinity);
451   for (std::size_t k=0; k<nbases-1; ++k)       << 482   for (G4int k=0; k<nbases-1; ++k)
452   {                                               483   {
453     baseA.resize(bases[k].second);             << 
454     for (G4int i = 0; i < bases[k].second; ++i << 
455       baseA[i] = vertices[bases[k].first + i]; << 
456                                                << 
457     baseB.resize(bases[k+1].second);           << 
458     for (G4int i = 0; i < bases[k+1].second; + << 
459       baseB[i] = vertices[bases[k+1].first + i << 
460                                                << 
461     // Find bounding box of current prism         484     // Find bounding box of current prism
                                                   >> 485     G4Polygon3D* baseA = bases[k];
                                                   >> 486     G4Polygon3D* baseB = bases[k+1];
462     G4Segment3D  prismAABB;                       487     G4Segment3D  prismAABB;
463     GetPrismAABB(baseA, baseB, prismAABB);     << 488     GetPrismAABB(*baseA, *baseB, prismAABB);
464                                                   489 
465     // Check if prismAABB is completely within    490     // Check if prismAABB is completely within the voxel limits
466     if (prismAABB.first.x() >= limits.GetMinXE    491     if (prismAABB.first.x() >= limits.GetMinXExtent() &&
467         prismAABB.first.y() >= limits.GetMinYE    492         prismAABB.first.y() >= limits.GetMinYExtent() &&
468         prismAABB.first.z() >= limits.GetMinZE    493         prismAABB.first.z() >= limits.GetMinZExtent() &&
469         prismAABB.second.x()<= limits.GetMaxXE    494         prismAABB.second.x()<= limits.GetMaxXExtent() &&
470         prismAABB.second.y()<= limits.GetMaxYE    495         prismAABB.second.y()<= limits.GetMaxYExtent() &&
471         prismAABB.second.z()<= limits.GetMaxZE << 496         prismAABB.second.z()<= limits.GetMaxZExtent()) 
472     {                                             497     {
473       if (extent.first.x()  > prismAABB.first.    498       if (extent.first.x()  > prismAABB.first.x())
474         extent.first.setX( prismAABB.first.x() << 499         extent.first.setX( prismAABB.first.x() ); 
475       if (extent.first.y()  > prismAABB.first.    500       if (extent.first.y()  > prismAABB.first.y())
476         extent.first.setY( prismAABB.first.y() << 501         extent.first.setY( prismAABB.first.y() ); 
477       if (extent.first.z()  > prismAABB.first.    502       if (extent.first.z()  > prismAABB.first.z())
478         extent.first.setZ( prismAABB.first.z() << 503         extent.first.setZ( prismAABB.first.z() ); 
479       if (extent.second.x() < prismAABB.second    504       if (extent.second.x() < prismAABB.second.x())
480         extent.second.setX(prismAABB.second.x( << 505         extent.second.setX(prismAABB.second.x()); 
481       if (extent.second.y() < prismAABB.second    506       if (extent.second.y() < prismAABB.second.y())
482         extent.second.setY(prismAABB.second.y( << 507         extent.second.setY(prismAABB.second.y()); 
483       if (extent.second.z() < prismAABB.second    508       if (extent.second.z() < prismAABB.second.z())
484         extent.second.setZ(prismAABB.second.z(    509         extent.second.setZ(prismAABB.second.z());
485       continue;                                << 510       continue; 
486     }                                             511     }
487                                                   512 
488     // Check if prismAABB is outside the voxel    513     // Check if prismAABB is outside the voxel limits
489     if (prismAABB.first.x()  > limits.GetMaxXE    514     if (prismAABB.first.x()  > limits.GetMaxXExtent()) continue;
490     if (prismAABB.first.y()  > limits.GetMaxYE    515     if (prismAABB.first.y()  > limits.GetMaxYExtent()) continue;
491     if (prismAABB.first.z()  > limits.GetMaxZE    516     if (prismAABB.first.z()  > limits.GetMaxZExtent()) continue;
492     if (prismAABB.second.x() < limits.GetMinXE    517     if (prismAABB.second.x() < limits.GetMinXExtent()) continue;
493     if (prismAABB.second.y() < limits.GetMinYE    518     if (prismAABB.second.y() < limits.GetMinYExtent()) continue;
494     if (prismAABB.second.z() < limits.GetMinZE    519     if (prismAABB.second.z() < limits.GetMinZExtent()) continue;
495                                                   520 
496     // Clip edges of the prism by adjusted G4V    521     // Clip edges of the prism by adjusted G4VoxelLimits box
497     std::vector<G4Segment3D> vecEdges;         << 522     std::vector<G4Segment3D> vecEdges; 
498     CreateListOfEdges(baseA, baseB, vecEdges); << 523     CreateListOfEdges(*baseA, *baseB, vecEdges);
499     if (ClipEdgesByVoxel(vecEdges, limits, ext    524     if (ClipEdgesByVoxel(vecEdges, limits, extent)) continue;
500                                                   525 
501     // Some edges of the prism are completely     526     // Some edges of the prism are completely outside of the voxel
502     // limits, clip selected edges (see bits)     527     // limits, clip selected edges (see bits) of adjusted G4VoxelLimits
503     // by the prism                            << 528     // by the prism 
504     G4int bits = 0x000;                           529     G4int bits = 0x000;
505     if (limits.GetMinXExtent() < prismAABB.fir    530     if (limits.GetMinXExtent() < prismAABB.first.x())
506       bits |= 0x988; // 1001 1000 1000            531       bits |= 0x988; // 1001 1000 1000
507     if (limits.GetMaxXExtent() > prismAABB.sec    532     if (limits.GetMaxXExtent() > prismAABB.second.x())
508       bits |= 0x622; // 0110 0010 0010            533       bits |= 0x622; // 0110 0010 0010
509                                                   534 
510     if (limits.GetMinYExtent() < prismAABB.fir    535     if (limits.GetMinYExtent() < prismAABB.first.y())
511       bits |= 0x311; // 0011 0001 0001            536       bits |= 0x311; // 0011 0001 0001
512     if (limits.GetMaxYExtent() > prismAABB.sec    537     if (limits.GetMaxYExtent() > prismAABB.second.y())
513       bits |= 0xC44; // 1100 0100 0100            538       bits |= 0xC44; // 1100 0100 0100
514                                                   539 
515     if (limits.GetMinZExtent() < prismAABB.fir    540     if (limits.GetMinZExtent() < prismAABB.first.z())
516       bits |= 0x00F; // 0000 0000 1111            541       bits |= 0x00F; // 0000 0000 1111
517     if (limits.GetMaxZExtent() > prismAABB.sec    542     if (limits.GetMaxZExtent() > prismAABB.second.z())
518       bits |= 0x0F0; // 0000 1111 0000            543       bits |= 0x0F0; // 0000 1111 0000
519     if (bits == 0xFFF) continue;                  544     if (bits == 0xFFF) continue;
520                                                   545 
521     std::vector<G4Plane3D> vecPlanes;          << 546     std::vector<G4Plane3D> vecPlanes; 
522     CreateListOfPlanes(baseA, baseB, vecPlanes << 547     CreateListOfPlanes(*baseA, *baseB, vecPlanes);
523     ClipVoxelByPlanes(bits, limits, vecPlanes,    548     ClipVoxelByPlanes(bits, limits, vecPlanes, prismAABB, extent);
524   } // End of the main loop                       549   } // End of the main loop
525                                                   550 
526   // Final adjustment of the extent            << 551   // Free memory
527   //                                              552   //
                                                   >> 553   for (G4int i=0; i<nbases; ++i) { delete bases[i]; bases[i] = 0; }
                                                   >> 554 
                                                   >> 555   // Final adjustment of the extent
                                                   >> 556   // 
528   G4double emin = 0, emax = 0;                    557   G4double emin = 0, emax = 0;
529   if (pAxis == kXAxis) { emin = extent.first.x    558   if (pAxis == kXAxis) { emin = extent.first.x(); emax = extent.second.x(); }
530   if (pAxis == kYAxis) { emin = extent.first.y    559   if (pAxis == kYAxis) { emin = extent.first.y(); emax = extent.second.y(); }
531   if (pAxis == kZAxis) { emin = extent.first.z    560   if (pAxis == kZAxis) { emin = extent.first.z(); emax = extent.second.z(); }
532                                                   561 
533   if (emin > emax) return false;                  562   if (emin > emax) return false;
534   emin -= delta;                                  563   emin -= delta;
535   emax += delta;                                  564   emax += delta;
536   G4double minlim = pVoxelLimits.GetMinExtent(    565   G4double minlim = pVoxelLimits.GetMinExtent(pAxis);
537   G4double maxlim = pVoxelLimits.GetMaxExtent(    566   G4double maxlim = pVoxelLimits.GetMaxExtent(pAxis);
538   pMin = (emin < minlim) ? minlim-kCarToleranc    567   pMin = (emin < minlim) ? minlim-kCarTolerance : emin;
539   pMax = (emax > maxlim) ? maxlim+kCarToleranc    568   pMax = (emax > maxlim) ? maxlim+kCarTolerance : emax;
540   return true;                                    569   return true;
541 }                                                 570 }
542                                                   571 
                                                   >> 572 
543 //////////////////////////////////////////////    573 ///////////////////////////////////////////////////////////////////////
544 //                                                574 //
545 // Find max scale factor of the transformation    575 // Find max scale factor of the transformation
546 //                                                576 //
547 G4double                                          577 G4double
548 G4BoundingEnvelope::FindScaleFactor(const G4Tr    578 G4BoundingEnvelope::FindScaleFactor(const G4Transform3D& pTransform3D) const
549 {                                                 579 {
550   if (pTransform3D.xx() == 1. &&                  580   if (pTransform3D.xx() == 1. &&
551       pTransform3D.yy() == 1. &&                  581       pTransform3D.yy() == 1. &&
552       pTransform3D.zz() == 1.) return 1.;         582       pTransform3D.zz() == 1.) return 1.;
553                                                   583 
554   G4double xx = pTransform3D.xx();                584   G4double xx = pTransform3D.xx();
555   G4double yx = pTransform3D.yx();                585   G4double yx = pTransform3D.yx();
556   G4double zx = pTransform3D.zx();                586   G4double zx = pTransform3D.zx();
557   G4double sxsx = xx*xx + yx*yx + zx*zx;          587   G4double sxsx = xx*xx + yx*yx + zx*zx;
558   G4double xy = pTransform3D.xy();                588   G4double xy = pTransform3D.xy();
559   G4double yy = pTransform3D.yy();                589   G4double yy = pTransform3D.yy();
560   G4double zy = pTransform3D.zy();                590   G4double zy = pTransform3D.zy();
561   G4double sysy = xy*xy + yy*yy + zy*zy;          591   G4double sysy = xy*xy + yy*yy + zy*zy;
562   G4double xz = pTransform3D.xz();                592   G4double xz = pTransform3D.xz();
563   G4double yz = pTransform3D.yz();                593   G4double yz = pTransform3D.yz();
564   G4double zz = pTransform3D.zz();                594   G4double zz = pTransform3D.zz();
565   G4double szsz = xz*xz + yz*yz + zz*zz;          595   G4double szsz = xz*xz + yz*yz + zz*zz;
566   G4double ss = std::max(std::max(sxsx,sysy),s    596   G4double ss = std::max(std::max(sxsx,sysy),szsz);
567   return (ss <= 1.) ? 1. : std::sqrt(ss);         597   return (ss <= 1.) ? 1. : std::sqrt(ss);
568 }                                                 598 }
569                                                   599 
570 //////////////////////////////////////////////    600 ///////////////////////////////////////////////////////////////////////
571 //                                                601 //
572 // Transform polygonal bases                      602 // Transform polygonal bases
573 //                                                603 //
574 void                                              604 void
575 G4BoundingEnvelope::                           << 605 G4BoundingEnvelope::TransformVertices(const G4Transform3D& pTransform3D,
576 TransformVertices(const G4Transform3D& pTransf << 606                                       std::vector<G4Polygon3D*>& pBases) const
577                   std::vector<G4Point3D>& pVer << 
578                   std::vector<std::pair<G4int, << 
579 {                                                 607 {
580   G4ThreeVectorList baseA(4), baseB(4);           608   G4ThreeVectorList baseA(4), baseB(4);
581   std::vector<const G4ThreeVectorList*> aabb(2    609   std::vector<const G4ThreeVectorList*> aabb(2);
582   aabb[0] = &baseA;                            << 610   aabb[0] = &baseA; aabb[1] = &baseB;
583   aabb[1] = &baseB;                            << 611   if (fPolygons == 0)
584   if (fPolygons == nullptr)                    << 
585   {                                               612   {
586     baseA[0].set(fMin.x(),fMin.y(),fMin.z());     613     baseA[0].set(fMin.x(),fMin.y(),fMin.z());
587     baseA[1].set(fMax.x(),fMin.y(),fMin.z());     614     baseA[1].set(fMax.x(),fMin.y(),fMin.z());
588     baseA[2].set(fMax.x(),fMax.y(),fMin.z());     615     baseA[2].set(fMax.x(),fMax.y(),fMin.z());
589     baseA[3].set(fMin.x(),fMax.y(),fMin.z());     616     baseA[3].set(fMin.x(),fMax.y(),fMin.z());
590     baseB[0].set(fMin.x(),fMin.y(),fMax.z());     617     baseB[0].set(fMin.x(),fMin.y(),fMax.z());
591     baseB[1].set(fMax.x(),fMin.y(),fMax.z());     618     baseB[1].set(fMax.x(),fMin.y(),fMax.z());
592     baseB[2].set(fMax.x(),fMax.y(),fMax.z());     619     baseB[2].set(fMax.x(),fMax.y(),fMax.z());
593     baseB[3].set(fMin.x(),fMax.y(),fMax.z());     620     baseB[3].set(fMin.x(),fMax.y(),fMax.z());
594   }                                               621   }
595   auto ia    = (fPolygons == nullptr) ? aabb.c << 622   std::vector<const G4ThreeVectorList*>::const_iterator ia, iaend;
596   auto iaend = (fPolygons == nullptr) ? aabb.c << 623   std::vector<G4Polygon3D*>::iterator ib = pBases.begin();
                                                   >> 624   ia    = (fPolygons == 0) ? aabb.begin() : fPolygons->begin();
                                                   >> 625   iaend = (fPolygons == 0) ? aabb.end()   : fPolygons->end();
597                                                   626 
598   // Fill vector of bases                      << 627   if (pTransform3D.xx()==1 && pTransform3D.yy()==1 && pTransform3D.zz()==1)
599   //                                           << 
600   G4int index = 0;                             << 
601   for (auto i = ia; i != iaend; ++i)           << 
602   {                                            << 
603     auto nv = (G4int)(*i)->size();             << 
604     pBases.emplace_back(index, nv);            << 
605     index += nv;                               << 
606   }                                            << 
607                                                << 
608   // Fill vector of transformed vertices       << 
609   //                                           << 
610   if (pTransform3D.xx() == 1. &&               << 
611       pTransform3D.yy() == 1. &&               << 
612       pTransform3D.zz() == 1.)                 << 
613   {                                               628   {
614     G4ThreeVector offset = pTransform3D.getTra    629     G4ThreeVector offset = pTransform3D.getTranslation();
615     for (auto i = ia; i != iaend; ++i)         << 630     for ( ; ia != iaend; ia++, ib++)
616       for (auto k = (*i)->cbegin(); k != (*i)- << 631     { 
617         pVertices.emplace_back((*k) + offset); << 632       G4ThreeVectorList::const_iterator ka = (*ia)->begin();
                                                   >> 633       G4Polygon3D::iterator             kb = (*ib)->begin();
                                                   >> 634       for ( ; ka != (*ia)->end(); ka++, kb++) { (*kb) = (*ka) + offset; }
                                                   >> 635     }
618   }                                               636   }
619   else                                            637   else
620   {                                               638   {
621     for (auto i = ia; i != iaend; ++i)         << 639     for ( ; ia != iaend; ia++, ib++)
622       for (auto k = (*i)->cbegin(); k != (*i)- << 640     { 
623         pVertices.push_back(pTransform3D*G4Poi << 641       G4ThreeVectorList::const_iterator ka = (*ia)->begin();
                                                   >> 642       G4Polygon3D::iterator             kb = (*ib)->begin();
                                                   >> 643       for ( ; ka != (*ia)->end(); ka++, kb++)
                                                   >> 644       {
                                                   >> 645         (*kb) = pTransform3D*G4Point3D(*ka);
                                                   >> 646       }
                                                   >> 647     }
624   }                                               648   }
625 }                                                 649 }
626                                                   650 
627 //////////////////////////////////////////////    651 ///////////////////////////////////////////////////////////////////////
628 //                                                652 //
629 // Find bounding box of a prism                   653 // Find bounding box of a prism
630 //                                                654 //
631 void                                              655 void
632 G4BoundingEnvelope::GetPrismAABB(const G4Polyg    656 G4BoundingEnvelope::GetPrismAABB(const G4Polygon3D& pBaseA,
633                                  const G4Polyg    657                                  const G4Polygon3D& pBaseB,
634                                        G4Segme    658                                        G4Segment3D& pAABB) const
635 {                                                 659 {
636   G4double xmin =  kInfinity, ymin =  kInfinit    660   G4double xmin =  kInfinity, ymin =  kInfinity, zmin =  kInfinity;
637   G4double xmax = -kInfinity, ymax = -kInfinit    661   G4double xmax = -kInfinity, ymax = -kInfinity, zmax = -kInfinity;
                                                   >> 662   G4Polygon3D::const_iterator it;
638                                                   663 
639   // First base                                   664   // First base
640   //                                              665   //
641   for (const auto & it1 : pBaseA)              << 666   for (it = pBaseA.begin(); it != pBaseA.end(); it++)
642   {                                            << 667   { 
643     G4double x = it1.x();                      << 668     G4double x = it->x();
644     if (x < xmin) xmin = x;                       669     if (x < xmin) xmin = x;
645     if (x > xmax) xmax = x;                       670     if (x > xmax) xmax = x;
646     G4double y = it1.y();                      << 671     G4double y = it->y(); 
647     if (y < ymin) ymin = y;                       672     if (y < ymin) ymin = y;
648     if (y > ymax) ymax = y;                       673     if (y > ymax) ymax = y;
649     G4double z = it1.z();                      << 674     G4double z = it->z(); 
650     if (z < zmin) zmin = z;                       675     if (z < zmin) zmin = z;
651     if (z > zmax) zmax = z;                       676     if (z > zmax) zmax = z;
652   }                                               677   }
653                                                   678 
654   // Second base                                  679   // Second base
655   //                                              680   //
656   for (const auto & it2 : pBaseB)              << 681   for (it = pBaseB.begin(); it != pBaseB.end(); it++)
657   {                                            << 682   { 
658     G4double x = it2.x();                      << 683     G4double x = it->x(); 
659     if (x < xmin) xmin = x;                       684     if (x < xmin) xmin = x;
660     if (x > xmax) xmax = x;                       685     if (x > xmax) xmax = x;
661     G4double y = it2.y();                      << 686     G4double y = it->y(); 
662     if (y < ymin) ymin = y;                       687     if (y < ymin) ymin = y;
663     if (y > ymax) ymax = y;                       688     if (y > ymax) ymax = y;
664     G4double z = it2.z();                      << 689     G4double z = it->z(); 
665     if (z < zmin) zmin = z;                       690     if (z < zmin) zmin = z;
666     if (z > zmax) zmax = z;                       691     if (z > zmax) zmax = z;
667   }                                               692   }
668                                                   693 
669   // Set bounding box                             694   // Set bounding box
670   //                                              695   //
671   pAABB.first  = G4Point3D(xmin,ymin,zmin);       696   pAABB.first  = G4Point3D(xmin,ymin,zmin);
672   pAABB.second = G4Point3D(xmax,ymax,zmax);       697   pAABB.second = G4Point3D(xmax,ymax,zmax);
673 }                                                 698 }
674                                                   699 
675 //////////////////////////////////////////////    700 ///////////////////////////////////////////////////////////////////////
676 //                                                701 //
677 // Create list of edges of a prism                702 // Create list of edges of a prism
678 //                                                703 //
679 void                                              704 void
680 G4BoundingEnvelope::CreateListOfEdges(const G4    705 G4BoundingEnvelope::CreateListOfEdges(const G4Polygon3D& baseA,
681                                       const G4    706                                       const G4Polygon3D& baseB,
682                                       std::vec    707                                       std::vector<G4Segment3D>& pEdges) const
683 {                                                 708 {
684   std::size_t na = baseA.size();               << 709   G4int na = baseA.size();
685   std::size_t nb = baseB.size();               << 710   G4int nb = baseB.size();
686   pEdges.clear();                                 711   pEdges.clear();
687   if (na == nb)                                   712   if (na == nb)
688   {                                               713   {
689     pEdges.resize(3*na);                          714     pEdges.resize(3*na);
690     std::size_t k = na - 1;                    << 715     G4int k = na - 1;
691     for (std::size_t i=0; i<na; ++i)           << 716     for (G4int i=0; i<na; ++i)
692     {                                             717     {
693       pEdges.emplace_back(baseA[i],baseB[i]);  << 718       pEdges.push_back(G4Segment3D(baseA[i],baseB[i]));
694       pEdges.emplace_back(baseA[i],baseA[k]);  << 719       pEdges.push_back(G4Segment3D(baseA[i],baseA[k]));
695       pEdges.emplace_back(baseB[i],baseB[k]);  << 720       pEdges.push_back(G4Segment3D(baseB[i],baseB[k]));
696       k = i;                                      721       k = i;
697     }                                             722     }
698   }                                               723   }
699   else if (nb == 1)                               724   else if (nb == 1)
700   {                                               725   {
701     pEdges.resize(2*na);                          726     pEdges.resize(2*na);
702     std::size_t k = na - 1;                    << 727     G4int k = na - 1;
703     for (std::size_t i=0; i<na; ++i)           << 728     for (G4int i=0; i<na; ++i)
704     {                                             729     {
705       pEdges.emplace_back(baseA[i],baseA[k]);  << 730       pEdges.push_back(G4Segment3D(baseA[i],baseA[k]));
706       pEdges.emplace_back(baseA[i],baseB[0]);  << 731       pEdges.push_back(G4Segment3D(baseA[i],baseB[0]));
707       k = i;                                      732       k = i;
708     }                                             733     }
709   }                                               734   }
710   else if (na == 1)                               735   else if (na == 1)
711   {                                               736   {
712     pEdges.resize(2*nb);                          737     pEdges.resize(2*nb);
713     std::size_t k = nb - 1;                    << 738     G4int k = nb - 1;
714     for (std::size_t i=0; i<nb; ++i)           << 739     for (G4int i=0; i<nb; ++i)
715     {                                             740     {
716       pEdges.emplace_back(baseB[i],baseB[k]);  << 741       pEdges.push_back(G4Segment3D(baseB[i],baseB[k]));
717       pEdges.emplace_back(baseB[i],baseA[0]);  << 742       pEdges.push_back(G4Segment3D(baseB[i],baseA[0]));
718       k = i;                                      743       k = i;
719     }                                             744     }
720   }                                               745   }
721 }                                                 746 }
722                                                   747 
723 //////////////////////////////////////////////    748 ///////////////////////////////////////////////////////////////////////
724 //                                                749 //
725 // Create list of planes bounding a prism         750 // Create list of planes bounding a prism
726 //                                                751 //
727 void                                              752 void
728 G4BoundingEnvelope::CreateListOfPlanes(const G    753 G4BoundingEnvelope::CreateListOfPlanes(const G4Polygon3D& baseA,
729                                        const G    754                                        const G4Polygon3D& baseB,
730                                        std::ve    755                                        std::vector<G4Plane3D>& pPlanes) const
731 {                                                 756 {
732   // Find centers of the bases and internal po    757   // Find centers of the bases and internal point of the prism
733   //                                              758   //
734   std::size_t na = baseA.size();               << 759   G4int na = baseA.size();
735   std::size_t nb = baseB.size();               << 760   G4int nb = baseB.size();
736   G4Point3D pa(0.,0.,0.), pb(0.,0.,0.), p0;       761   G4Point3D pa(0.,0.,0.), pb(0.,0.,0.), p0;
737   G4Normal3D norm;                                762   G4Normal3D norm;
738   for (std::size_t i=0; i<na; ++i) pa += baseA << 763   for (G4int i=0; i<na; ++i) pa += baseA[i];
739   for (std::size_t i=0; i<nb; ++i) pb += baseB << 764   for (G4int i=0; i<nb; ++i) pb += baseB[i];
740   pa /= na; pb /= nb; p0 = (pa+pb)/2.;            765   pa /= na; pb /= nb; p0 = (pa+pb)/2.;
741                                                   766 
742   // Create list of planes                        767   // Create list of planes
743   //                                              768   //
744   pPlanes.clear();                                769   pPlanes.clear();
745   if (na == nb)  // bases with equal number of    770   if (na == nb)  // bases with equal number of vertices
746   {                                               771   {
747     std::size_t k = na - 1;                    << 772     G4int k = na - 1;
748     for (std::size_t i=0; i<na; ++i)           << 773     for (G4int i=0; i<na; ++i)
749     {                                             774     {
750       norm = (baseB[k]-baseA[i]).cross(baseA[k    775       norm = (baseB[k]-baseA[i]).cross(baseA[k]-baseB[i]);
751       if (norm.mag2() > kCarTolerance)            776       if (norm.mag2() > kCarTolerance)
752       {                                           777       {
753         pPlanes.emplace_back(norm,baseA[i]);   << 778         pPlanes.push_back(G4Plane3D(norm,baseA[i]));
754       }                                           779       }
755       k = i;                                      780       k = i;
756     }                                             781     }
757     norm = (baseA[2]-baseA[0]).cross(baseA[1]-    782     norm = (baseA[2]-baseA[0]).cross(baseA[1]-pa);
758     if (norm.mag2() > kCarTolerance)              783     if (norm.mag2() > kCarTolerance)
759     {                                             784     {
760       pPlanes.emplace_back(norm,pa);           << 785       pPlanes.push_back(G4Plane3D(norm,pa));
761     }                                             786     }
762     norm = (baseB[2]-baseB[0]).cross(baseB[1]-    787     norm = (baseB[2]-baseB[0]).cross(baseB[1]-pb);
763     if (norm.mag2() > kCarTolerance)              788     if (norm.mag2() > kCarTolerance)
764     {                                             789     {
765       pPlanes.emplace_back(norm,pb);           << 790       pPlanes.push_back(G4Plane3D(norm,pb));
766     }                                             791     }
767   }                                               792   }
768   else if (nb == 1) // baseB has one vertex       793   else if (nb == 1) // baseB has one vertex
769   {                                               794   {
770     std::size_t k = na - 1;                    << 795     G4int k = na - 1;
771     for (std::size_t i=0; i<na; ++i)           << 796     for (G4int i=0; i<na; ++i)
772     {                                             797     {
773       norm = (baseA[i]-baseB[0]).cross(baseA[k    798       norm = (baseA[i]-baseB[0]).cross(baseA[k]-baseB[0]);
774       if (norm.mag2() > kCarTolerance)            799       if (norm.mag2() > kCarTolerance)
775       {                                           800       {
776         pPlanes.emplace_back(norm,baseB[0]);   << 801         pPlanes.push_back(G4Plane3D(norm,baseB[0]));
777       }                                           802       }
778       k = i;                                      803       k = i;
779     }                                             804     }
780     norm = (baseA[2]-baseA[0]).cross(baseA[1]-    805     norm = (baseA[2]-baseA[0]).cross(baseA[1]-pa);
781     if (norm.mag2() > kCarTolerance)              806     if (norm.mag2() > kCarTolerance)
782     {                                             807     {
783       pPlanes.emplace_back(norm,pa);           << 808       pPlanes.push_back(G4Plane3D(norm,pa));
784     }                                             809     }
785   }                                               810   }
786   else if (na == 1) // baseA has one vertex       811   else if (na == 1) // baseA has one vertex
787   {                                               812   {
788     std::size_t k = nb - 1;                    << 813     G4int k = nb - 1;
789     for (std::size_t i=0; i<nb; ++i)           << 814     for (G4int i=0; i<nb; ++i)
790     {                                             815     {
791       norm = (baseB[i]-baseA[0]).cross(baseB[k    816       norm = (baseB[i]-baseA[0]).cross(baseB[k]-baseA[0]);
792       if (norm.mag2() > kCarTolerance)            817       if (norm.mag2() > kCarTolerance)
793       {                                           818       {
794         pPlanes.emplace_back(norm,baseA[0]);   << 819         pPlanes.push_back(G4Plane3D(norm,baseA[0]));
795       }                                           820       }
796       k = i;                                      821       k = i;
797     }                                             822     }
798     norm = (baseB[2]-baseB[0]).cross(baseB[1]-    823     norm = (baseB[2]-baseB[0]).cross(baseB[1]-pb);
799     if (norm.mag2() > kCarTolerance)              824     if (norm.mag2() > kCarTolerance)
800     {                                             825     {
801       pPlanes.emplace_back(norm,pb);           << 826       pPlanes.push_back(G4Plane3D(norm,pb));
802     }                                             827     }
803   }                                               828   }
804                                                   829 
805   // Ensure that normals of the planes point t    830   // Ensure that normals of the planes point to outside
806   //                                              831   //
807   std::size_t nplanes = pPlanes.size();        << 832   G4int nplanes = pPlanes.size();
808   for (std::size_t i=0; i<nplanes; ++i)        << 833   for (G4int i=0; i<nplanes; ++i)
809   {                                               834   {
810     pPlanes[i].normalize();                       835     pPlanes[i].normalize();
811     if (pPlanes[i].distance(p0) > 0)              836     if (pPlanes[i].distance(p0) > 0)
812     {                                             837     {
813       pPlanes[i] = G4Plane3D(-pPlanes[i].a(),-    838       pPlanes[i] = G4Plane3D(-pPlanes[i].a(),-pPlanes[i].b(),
814                              -pPlanes[i].c(),-    839                              -pPlanes[i].c(),-pPlanes[i].d());
815     }                                          << 840     } 
816   }                                               841   }
817 }                                                 842 }
818                                                   843 
819 //////////////////////////////////////////////    844 ///////////////////////////////////////////////////////////////////////
820 //                                                845 //
821 // Clip edges of a prism by G4VoxelLimits box.    846 // Clip edges of a prism by G4VoxelLimits box. Return true if all edges
822 // are inside or intersect the voxel, in this     847 // are inside or intersect the voxel, in this case further calculations
823 // are not needed                              << 848 // are not needed  
824 //                                                849 //
825 G4bool                                            850 G4bool
826 G4BoundingEnvelope::ClipEdgesByVoxel(const std    851 G4BoundingEnvelope::ClipEdgesByVoxel(const std::vector<G4Segment3D>& pEdges,
827                                      const G4V    852                                      const G4VoxelLimits& pBox,
828                                            G4S    853                                            G4Segment3D& pExtent) const
829 {                                                 854 {
830   G4bool    done = true;                          855   G4bool    done = true;
831   G4Point3D emin = pExtent.first;                 856   G4Point3D emin = pExtent.first;
832   G4Point3D emax = pExtent.second;                857   G4Point3D emax = pExtent.second;
833                                                   858 
834   std::size_t nedges = pEdges.size();          << 859   G4int nedges = pEdges.size();
835   for (std::size_t k=0; k<nedges; ++k)         << 860   for (G4int k=0; k<nedges; ++k)
836   {                                               861   {
837     G4Point3D p1 = pEdges[k].first;               862     G4Point3D p1 = pEdges[k].first;
838     G4Point3D p2 = pEdges[k].second;              863     G4Point3D p2 = pEdges[k].second;
839     if (std::abs(p1.x()-p2.x())+                  864     if (std::abs(p1.x()-p2.x())+
840         std::abs(p1.y()-p2.y())+                  865         std::abs(p1.y()-p2.y())+
841         std::abs(p1.z()-p2.z()) < kCarToleranc    866         std::abs(p1.z()-p2.z()) < kCarTolerance) continue;
842     G4double  d1, d2;                             867     G4double  d1, d2;
843     // Clip current edge by X min                 868     // Clip current edge by X min
844     d1 = pBox.GetMinXExtent() - p1.x();        << 869     d1 = pBox.GetMinXExtent() - p1.x(); 
845     d2 = pBox.GetMinXExtent() - p2.x();        << 870     d2 = pBox.GetMinXExtent() - p2.x(); 
846     if (d1 > 0.0)                                 871     if (d1 > 0.0)
847     {                                             872     {
848       if (d2 > 0.0) { done = false; continue;     873       if (d2 > 0.0) { done = false; continue; } // go to next edge
849       p1 = (p2*d1-p1*d2)/(d1-d2);                 874       p1 = (p2*d1-p1*d2)/(d1-d2);                   // move p1
850     }                                             875     }
851     else                                          876     else
852     {                                             877     {
853       if (d2 > 0.0) { p2 = (p1*d2-p2*d1)/(d2-d    878       if (d2 > 0.0) { p2 = (p1*d2-p2*d1)/(d2-d1); } // move p2
854     }                                             879     }
855                                                   880 
856     // Clip current edge by X max                 881     // Clip current edge by X max
857     d1 = p1.x() - pBox.GetMaxXExtent();        << 882     d1 = p1.x() - pBox.GetMaxXExtent(); 
858     d2 = p2.x() - pBox.GetMaxXExtent();        << 883     d2 = p2.x() - pBox.GetMaxXExtent(); 
859     if (d1 > 0.)                                  884     if (d1 > 0.)
860     {                                             885     {
861       if (d2 > 0.) { done = false; continue; }    886       if (d2 > 0.) { done = false; continue; } // go to next edge
862       p1 = (p2*d1-p1*d2)/(d1-d2);                 887       p1 = (p2*d1-p1*d2)/(d1-d2);
863     }                                             888     }
864     else                                          889     else
865     {                                             890     {
866       if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1    891       if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
867     }                                             892     }
868                                                   893 
869     // Clip current edge by Y min                 894     // Clip current edge by Y min
870     d1 = pBox.GetMinYExtent() - p1.y();        << 895     d1 = pBox.GetMinYExtent() - p1.y(); 
871     d2 = pBox.GetMinYExtent() - p2.y();        << 896     d2 = pBox.GetMinYExtent() - p2.y(); 
872     if (d1 > 0.)                                  897     if (d1 > 0.)
873     {                                             898     {
874       if (d2 > 0.) { done = false; continue; }    899       if (d2 > 0.) { done = false; continue; } // go to next edge
875       p1 = (p2*d1-p1*d2)/(d1-d2);                 900       p1 = (p2*d1-p1*d2)/(d1-d2);
876     }                                             901     }
877     else                                          902     else
878     {                                             903     {
879       if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1    904       if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
880     }                                             905     }
881                                                   906 
882     // Clip current edge by Y max                 907     // Clip current edge by Y max
883     d1 = p1.y() - pBox.GetMaxYExtent();        << 908     d1 = p1.y() - pBox.GetMaxYExtent(); 
884     d2 = p2.y() - pBox.GetMaxYExtent();        << 909     d2 = p2.y() - pBox.GetMaxYExtent(); 
885     if (d1 > 0.)                                  910     if (d1 > 0.)
886     {                                             911     {
887       if (d2 > 0.) { done = false; continue; }    912       if (d2 > 0.) { done = false; continue; } // go to next edge
888       p1 = (p2*d1-p1*d2)/(d1-d2);                 913       p1 = (p2*d1-p1*d2)/(d1-d2);
889     }                                             914     }
890     else                                          915     else
891     {                                             916     {
892       if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1    917       if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
893     }                                             918     }
894                                                   919 
895     // Clip current edge by Z min                 920     // Clip current edge by Z min
896     d1 = pBox.GetMinZExtent() - p1.z();        << 921     d1 = pBox.GetMinZExtent() - p1.z(); 
897     d2 = pBox.GetMinZExtent() - p2.z();        << 922     d2 = pBox.GetMinZExtent() - p2.z(); 
898     if (d1 > 0.)                                  923     if (d1 > 0.)
899     {                                             924     {
900       if (d2 > 0.) { done = false; continue; }    925       if (d2 > 0.) { done = false; continue; } // go to next edge
901       p1 = (p2*d1-p1*d2)/(d1-d2);                 926       p1 = (p2*d1-p1*d2)/(d1-d2);
902     }                                             927     }
903     else                                          928     else
904     {                                             929     {
905       if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1    930       if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
906     }                                             931     }
907                                                   932 
908     // Clip current edge by Z max                 933     // Clip current edge by Z max
909     d1 = p1.z() - pBox.GetMaxZExtent();        << 934     d1 = p1.z() - pBox.GetMaxZExtent(); 
910     d2 = p2.z() - pBox.GetMaxZExtent();        << 935     d2 = p2.z() - pBox.GetMaxZExtent(); 
911     if (d1 > 0.)                                  936     if (d1 > 0.)
912     {                                             937     {
913       if (d2 > 0.) { done = false; continue; }    938       if (d2 > 0.) { done = false; continue; } // go to next edge
914       p1 = (p2*d1-p1*d2)/(d1-d2);                 939       p1 = (p2*d1-p1*d2)/(d1-d2);
915     }                                             940     }
916     else                                          941     else
917     {                                             942     {
918       if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1    943       if (d2 > 0.) { p2 = (p1*d2-p2*d1)/(d2-d1); }
919     }                                             944     }
920                                                   945 
921     // Adjust current extent                      946     // Adjust current extent
922     emin.setX(std::min(std::min(p1.x(),p2.x()) << 947     emin.setX(std::min(std::min(p1.x(),p2.x()),emin.x())); 
923     emin.setY(std::min(std::min(p1.y(),p2.y()) << 948     emin.setY(std::min(std::min(p1.y(),p2.y()),emin.y())); 
924     emin.setZ(std::min(std::min(p1.z(),p2.z()) << 949     emin.setZ(std::min(std::min(p1.z(),p2.z()),emin.z())); 
925                                                << 950 
926     emax.setX(std::max(std::max(p1.x(),p2.x()) << 951     emax.setX(std::max(std::max(p1.x(),p2.x()),emax.x())); 
927     emax.setY(std::max(std::max(p1.y(),p2.y()) << 952     emax.setY(std::max(std::max(p1.y(),p2.y()),emax.y())); 
928     emax.setZ(std::max(std::max(p1.z(),p2.z()) << 953     emax.setZ(std::max(std::max(p1.z(),p2.z()),emax.z())); 
929   }                                               954   }
930                                                   955 
931   // Return true if all edges (at least partia    956   // Return true if all edges (at least partially) are inside
932   // the voxel limits, otherwise return false     957   // the voxel limits, otherwise return false
933   pExtent.first  = emin;                          958   pExtent.first  = emin;
934   pExtent.second = emax;                          959   pExtent.second = emax;
935                                                   960 
936   return done;                                    961   return done;
937 }                                                 962 }
938                                                   963 
939 //////////////////////////////////////////////    964 ///////////////////////////////////////////////////////////////////////
940 //                                                965 //
941 // Clip G4VoxelLimits by set of planes boundin    966 // Clip G4VoxelLimits by set of planes bounding a prism
942 //                                                967 //
943 void                                              968 void
944 G4BoundingEnvelope::ClipVoxelByPlanes(G4int pB    969 G4BoundingEnvelope::ClipVoxelByPlanes(G4int pBits,
945                                       const G4    970                                       const G4VoxelLimits& pBox,
946                                       const st    971                                       const std::vector<G4Plane3D>& pPlanes,
947                                       const G4    972                                       const G4Segment3D& pAABB,
948                                             G4    973                                             G4Segment3D& pExtent) const
949 {                                                 974 {
950   G4Point3D emin = pExtent.first;                 975   G4Point3D emin = pExtent.first;
951   G4Point3D emax = pExtent.second;                976   G4Point3D emax = pExtent.second;
952                                                   977 
953   // Create edges of the voxel limits box redu    978   // Create edges of the voxel limits box reducing them where
954   // appropriate to avoid calculations with bi    979   // appropriate to avoid calculations with big numbers (kInfinity)
955   //                                              980   //
956   G4double xmin = std::max(pBox.GetMinXExtent(    981   G4double xmin = std::max(pBox.GetMinXExtent(),pAABB.first.x() -1.);
957   G4double xmax = std::min(pBox.GetMaxXExtent(    982   G4double xmax = std::min(pBox.GetMaxXExtent(),pAABB.second.x()+1.);
958                                                   983 
959   G4double ymin = std::max(pBox.GetMinYExtent(    984   G4double ymin = std::max(pBox.GetMinYExtent(),pAABB.first.y() -1.);
960   G4double ymax = std::min(pBox.GetMaxYExtent(    985   G4double ymax = std::min(pBox.GetMaxYExtent(),pAABB.second.y()+1.);
961                                                   986 
962   G4double zmin = std::max(pBox.GetMinZExtent(    987   G4double zmin = std::max(pBox.GetMinZExtent(),pAABB.first.z() -1.);
963   G4double zmax = std::min(pBox.GetMaxZExtent(    988   G4double zmax = std::min(pBox.GetMaxZExtent(),pAABB.second.z()+1.);
964                                                   989 
965   std::vector<G4Segment3D> edges(12);             990   std::vector<G4Segment3D> edges(12);
966   G4int i = 0, bits = pBits;                      991   G4int i = 0, bits = pBits;
967   if ((bits & 0x001) == 0)                     << 992   if (!(bits & 0x001))
968   {                                            << 993   { 
969     edges[i  ].first.set( xmin,ymin,zmin);     << 994     edges[i  ].first.set( xmin,ymin,zmin); 
970     edges[i++].second.set(xmax,ymin,zmin);        995     edges[i++].second.set(xmax,ymin,zmin);
971   }                                               996   }
972   if ((bits & 0x002) == 0)                     << 997   if (!(bits & 0x002))
973   {                                               998   {
974     edges[i  ].first.set( xmax,ymin,zmin);        999     edges[i  ].first.set( xmax,ymin,zmin);
975     edges[i++].second.set(xmax,ymax,zmin);        1000     edges[i++].second.set(xmax,ymax,zmin);
976   }                                               1001   }
977   if ((bits & 0x004) == 0)                     << 1002   if (!(bits & 0x004))
978   {                                               1003   {
979     edges[i  ].first.set( xmax,ymax,zmin);        1004     edges[i  ].first.set( xmax,ymax,zmin);
980     edges[i++].second.set(xmin,ymax,zmin);        1005     edges[i++].second.set(xmin,ymax,zmin);
981   }                                               1006   }
982   if ((bits & 0x008) == 0)                     << 1007   if (!(bits & 0x008))
983   {                                               1008   {
984     edges[i  ].first.set( xmin,ymax,zmin);        1009     edges[i  ].first.set( xmin,ymax,zmin);
985     edges[i++].second.set(xmin,ymin,zmin);     << 1010     edges[i++].second.set(xmin,ymin,zmin); 
986   }                                               1011   }
987                                                   1012 
988   if ((bits & 0x010) == 0)                     << 1013   if (!(bits & 0x010))
989   {                                            << 1014   { 
990     edges[i  ].first.set( xmin,ymin,zmax);     << 1015     edges[i  ].first.set( xmin,ymin,zmax); 
991     edges[i++].second.set(xmax,ymin,zmax);        1016     edges[i++].second.set(xmax,ymin,zmax);
992   }                                               1017   }
993   if ((bits & 0x020) == 0)                     << 1018   if (!(bits & 0x020))
994   {                                               1019   {
995     edges[i  ].first.set( xmax,ymin,zmax);        1020     edges[i  ].first.set( xmax,ymin,zmax);
996     edges[i++].second.set(xmax,ymax,zmax);        1021     edges[i++].second.set(xmax,ymax,zmax);
997   }                                               1022   }
998   if ((bits & 0x040) == 0)                     << 1023   if (!(bits & 0x040))
999   {                                               1024   {
1000     edges[i  ].first.set( xmax,ymax,zmax);       1025     edges[i  ].first.set( xmax,ymax,zmax);
1001     edges[i++].second.set(xmin,ymax,zmax);       1026     edges[i++].second.set(xmin,ymax,zmax);
1002   }                                              1027   }
1003   if ((bits & 0x080) == 0)                    << 1028   if (!(bits & 0x080))
1004   {                                              1029   {
1005     edges[i  ].first.set( xmin,ymax,zmax);       1030     edges[i  ].first.set( xmin,ymax,zmax);
1006     edges[i++].second.set(xmin,ymin,zmax);    << 1031     edges[i++].second.set(xmin,ymin,zmax); 
1007   }                                              1032   }
1008                                                  1033 
1009   if ((bits & 0x100) == 0)                    << 1034   if (!(bits & 0x100))
1010   {                                           << 1035   { 
1011     edges[i  ].first.set( xmin,ymin,zmin);    << 1036     edges[i  ].first.set( xmin,ymin,zmin); 
1012     edges[i++].second.set(xmin,ymin,zmax);    << 1037     edges[i++].second.set(xmin,ymin,zmax); 
1013   }                                              1038   }
1014   if ((bits & 0x200) == 0)                    << 1039   if (!(bits & 0x200))
1015   {                                              1040   {
1016     edges[i  ].first.set( xmax,ymin,zmin);       1041     edges[i  ].first.set( xmax,ymin,zmin);
1017     edges[i++].second.set(xmax,ymin,zmax);       1042     edges[i++].second.set(xmax,ymin,zmax);
1018   }                                              1043   }
1019   if ((bits & 0x400) == 0)                    << 1044   if (!(bits & 0x400))
1020   {                                              1045   {
1021     edges[i  ].first.set( xmax,ymax,zmin);       1046     edges[i  ].first.set( xmax,ymax,zmin);
1022     edges[i++].second.set(xmax,ymax,zmax);       1047     edges[i++].second.set(xmax,ymax,zmax);
1023   }                                              1048   }
1024   if ((bits & 0x800) == 0)                    << 1049   if (!(bits & 0x800))
1025   {                                              1050   {
1026     edges[i  ].first.set( xmin,ymax,zmin);       1051     edges[i  ].first.set( xmin,ymax,zmin);
1027     edges[i++].second.set(xmin,ymax,zmax);       1052     edges[i++].second.set(xmin,ymax,zmax);
1028   }                                              1053   }
1029   edges.resize(i);                               1054   edges.resize(i);
1030                                                  1055 
1031   // Clip the edges by the planes                1056   // Clip the edges by the planes
1032   //                                             1057   //
1033   for (const auto & edge : edges)             << 1058   std::vector<G4Segment3D>::const_iterator iedge;  
                                                   >> 1059   for (iedge = edges.begin(); iedge != edges.end(); iedge++)
1034   {                                              1060   {
1035     G4bool    exist = true;                      1061     G4bool    exist = true;
1036     G4Point3D p1    = edge.first;             << 1062     G4Point3D p1    = iedge->first;
1037     G4Point3D p2    = edge.second;            << 1063     G4Point3D p2    = iedge->second;
1038     for (const auto & plane : pPlanes)        << 1064     std::vector<G4Plane3D>::const_iterator iplane;  
                                                   >> 1065     for (iplane = pPlanes.begin(); iplane != pPlanes.end(); iplane++)
1039     {                                            1066     {
1040       // Clip current edge                       1067       // Clip current edge
1041       G4double d1 = plane.distance(p1);       << 1068       G4double d1 = iplane->distance(p1); 
1042       G4double d2 = plane.distance(p2);       << 1069       G4double d2 = iplane->distance(p2); 
1043       if (d1 > 0.0)                              1070       if (d1 > 0.0)
1044       {                                          1071       {
1045         if (d2 > 0.0) { exist = false; break;    1072         if (d2 > 0.0) { exist = false; break; } // go to next edge
1046         p1 = (p2*d1-p1*d2)/(d1-d2);              1073         p1 = (p2*d1-p1*d2)/(d1-d2);                   // move p1
1047       }                                          1074       }
1048       else                                       1075       else
1049       {                                          1076       {
1050         if (d2 > 0.0) { p2 = (p1*d2-p2*d1)/(d    1077         if (d2 > 0.0) { p2 = (p1*d2-p2*d1)/(d2-d1); } // move p2
1051       }                                          1078       }
1052     }                                            1079     }
1053     // Adjust the extent                         1080     // Adjust the extent
1054     if (exist)                                   1081     if (exist)
1055     {                                            1082     {
1056       emin.setX(std::min(std::min(p1.x(),p2.x << 1083       emin.setX(std::min(std::min(p1.x(),p2.x()),emin.x())); 
1057       emin.setY(std::min(std::min(p1.y(),p2.y << 1084       emin.setY(std::min(std::min(p1.y(),p2.y()),emin.y())); 
1058       emin.setZ(std::min(std::min(p1.z(),p2.z << 1085       emin.setZ(std::min(std::min(p1.z(),p2.z()),emin.z())); 
1059                                               << 1086 
1060       emax.setX(std::max(std::max(p1.x(),p2.x << 1087       emax.setX(std::max(std::max(p1.x(),p2.x()),emax.x())); 
1061       emax.setY(std::max(std::max(p1.y(),p2.y << 1088       emax.setY(std::max(std::max(p1.y(),p2.y()),emax.y())); 
1062       emax.setZ(std::max(std::max(p1.z(),p2.z << 1089       emax.setZ(std::max(std::max(p1.z(),p2.z()),emax.z())); 
1063     }                                            1090     }
1064   }                                              1091   }
1065                                                  1092 
1066   // Copy the extent back                        1093   // Copy the extent back
1067   //                                             1094   //
1068   pExtent.first  = emin;                         1095   pExtent.first  = emin;
1069   pExtent.second = emax;                         1096   pExtent.second = emax;
1070 }                                                1097 }
1071                                                  1098