Geant4 Cross Reference

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

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

Diff markup

Differences between /geometry/solids/specific/src/G4ExtrudedSolid.cc (Version 11.3.0) and /geometry/solids/specific/src/G4ExtrudedSolid.cc (Version 10.5)


  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 // G4ExtrudedSolid implementation              <<  26 //
                                                   >>  27 //
                                                   >>  28 //
                                                   >>  29 // --------------------------------------------------------------------
                                                   >>  30 // GEANT 4 class source file
                                                   >>  31 //
                                                   >>  32 // G4ExtrudedSolid.cc
 27 //                                                 33 //
 28 // Author: Ivana Hrivnacova, IPN Orsay             34 // Author: Ivana Hrivnacova, IPN Orsay
 29 //                                                 35 //
 30 // CHANGE HISTORY                                  36 // CHANGE HISTORY
 31 // --------------                                  37 // --------------
 32 //                                                 38 //
 33 // 31.10.2017 E.Tcherniaev: added implementati     39 // 31.10.2017 E.Tcherniaev: added implementation for a non-convex
 34 //            right prism                          40 //            right prism
 35 // 08.09.2017 E.Tcherniaev: added implementati     41 // 08.09.2017 E.Tcherniaev: added implementation for a convex
 36 //            right prism                          42 //            right prism
 37 // 21.10.2016 E.Tcherniaev: reimplemented Calc     43 // 21.10.2016 E.Tcherniaev: reimplemented CalculateExtent(),
 38 //            used G4GeomTools::PolygonArea()      44 //            used G4GeomTools::PolygonArea() to calculate area,
 39 //            replaced IsConvex() with G4GeomT     45 //            replaced IsConvex() with G4GeomTools::IsConvex()
 40 // 02.03.2016 E.Tcherniaev: added CheckPolygon     46 // 02.03.2016 E.Tcherniaev: added CheckPolygon() to remove
 41 //            collinear and coincident points      47 //            collinear and coincident points from polygon
 42 // -------------------------------------------     48 // --------------------------------------------------------------------
 43                                                    49 
 44 #include "G4ExtrudedSolid.hh"                      50 #include "G4ExtrudedSolid.hh"
 45                                                    51 
 46 #if !defined(G4GEOM_USE_UEXTRUDEDSOLID)            52 #if !defined(G4GEOM_USE_UEXTRUDEDSOLID)
 47                                                    53 
 48 #include <set>                                     54 #include <set>
 49 #include <algorithm>                               55 #include <algorithm>
 50 #include <cmath>                                   56 #include <cmath>
 51 #include <iomanip>                                 57 #include <iomanip>
 52                                                    58 
 53 #include "G4GeomTools.hh"                          59 #include "G4GeomTools.hh"
 54 #include "G4VoxelLimits.hh"                        60 #include "G4VoxelLimits.hh"
 55 #include "G4AffineTransform.hh"                    61 #include "G4AffineTransform.hh"
 56 #include "G4BoundingEnvelope.hh"                   62 #include "G4BoundingEnvelope.hh"
 57                                                    63 
 58 #include "G4GeometryTolerance.hh"                  64 #include "G4GeometryTolerance.hh"
 59 #include "G4PhysicalConstants.hh"                  65 #include "G4PhysicalConstants.hh"
 60 #include "G4SystemOfUnits.hh"                      66 #include "G4SystemOfUnits.hh"
                                                   >>  67 #include "G4VFacet.hh"
 61 #include "G4TriangularFacet.hh"                    68 #include "G4TriangularFacet.hh"
 62 #include "G4QuadrangularFacet.hh"                  69 #include "G4QuadrangularFacet.hh"
 63                                                    70 
 64 //____________________________________________     71 //_____________________________________________________________________________
 65                                                    72 
 66 G4ExtrudedSolid::G4ExtrudedSolid( const G4Stri     73 G4ExtrudedSolid::G4ExtrudedSolid( const G4String& pName,
 67                                   const std::v     74                                   const std::vector<G4TwoVector>& polygon,
 68                                   const std::v     75                                   const std::vector<ZSection>& zsections)
 69   : G4TessellatedSolid(pName),                     76   : G4TessellatedSolid(pName),
 70     fNv(polygon.size()),                           77     fNv(polygon.size()),
 71     fNz(zsections.size()),                         78     fNz(zsections.size()),
 72     fIsConvex(false),                              79     fIsConvex(false),
 73     fGeometryType("G4ExtrudedSolid"),              80     fGeometryType("G4ExtrudedSolid"),
 74     fSolidType(0)                                  81     fSolidType(0)
 75 {                                                  82 {
 76   // General constructor                           83   // General constructor
 77                                                    84 
 78   // First check input parameters                  85   // First check input parameters
 79                                                    86 
 80   if (fNv < 3)                                     87   if (fNv < 3)
 81   {                                                88   {
 82     std::ostringstream message;                    89     std::ostringstream message;
 83     message << "Number of vertices in polygon      90     message << "Number of vertices in polygon < 3 - " << pName;
 84     G4Exception("G4ExtrudedSolid::G4ExtrudedSo     91     G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0002",
 85                 FatalErrorInArgument, message)     92                 FatalErrorInArgument, message);
 86   }                                                93   }
 87                                                    94      
 88   if (fNz < 2)                                     95   if (fNz < 2)
 89   {                                                96   {
 90     std::ostringstream message;                    97     std::ostringstream message;
 91     message << "Number of z-sides < 2 - " << p     98     message << "Number of z-sides < 2 - " << pName;
 92     G4Exception("G4ExtrudedSolid::G4ExtrudedSo     99     G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0002",
 93                 FatalErrorInArgument, message)    100                 FatalErrorInArgument, message);
 94   }                                               101   }
 95                                                   102      
 96   for ( std::size_t i=0; i<fNz-1; ++i )        << 103   for ( G4int i=0; i<fNz-1; ++i ) 
 97   {                                               104   {
 98     if ( zsections[i].fZ > zsections[i+1].fZ )    105     if ( zsections[i].fZ > zsections[i+1].fZ ) 
 99     {                                             106     {
100       std::ostringstream message;                 107       std::ostringstream message;
101       message << "Z-sections have to be ordere    108       message << "Z-sections have to be ordered by z value (z0 < z1 < z2...) - "
102               << pName;                           109               << pName;
103       G4Exception("G4ExtrudedSolid::G4Extruded    110       G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0002",
104                   FatalErrorInArgument, messag    111                   FatalErrorInArgument, message);
105     }                                             112     }
106     if ( std::fabs( zsections[i+1].fZ - zsecti    113     if ( std::fabs( zsections[i+1].fZ - zsections[i].fZ ) < kCarToleranceHalf )
107     {                                             114     {
108       std::ostringstream message;                 115       std::ostringstream message;
109       message << "Z-sections with the same z p    116       message << "Z-sections with the same z position are not supported - "
110               << pName;                           117               << pName;
111       G4Exception("G4ExtrudedSolid::G4Extruded    118       G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0001",
112                   FatalException, message);       119                   FatalException, message);
113     }                                             120     }
114   }                                               121   }  
115                                                   122   
116   // Copy polygon                                 123   // Copy polygon
117   //                                              124   //
118   fPolygon = polygon;                             125   fPolygon = polygon;
119                                                   126 
120   // Remove collinear and coincident vertices,    127   // Remove collinear and coincident vertices, if any
121   //                                              128   //
122   std::vector<G4int> removedVertices;             129   std::vector<G4int> removedVertices;
123   G4GeomTools::RemoveRedundantVertices(fPolygo    130   G4GeomTools::RemoveRedundantVertices(fPolygon,removedVertices,
124                                        2*kCarT    131                                        2*kCarTolerance);
125   if (!removedVertices.empty())                << 132   if (removedVertices.size() != 0)
126   {                                               133   {
127     std::size_t nremoved = removedVertices.siz << 134     G4int nremoved = removedVertices.size();
128     std::ostringstream message;                   135     std::ostringstream message;
129     message << "The following "<< nremoved        136     message << "The following "<< nremoved 
130             << " vertices have been removed fr    137             << " vertices have been removed from polygon in " << pName 
131             << "\nas collinear or coincident w    138             << "\nas collinear or coincident with other vertices: "
132             << removedVertices[0];                139             << removedVertices[0];
133     for (std::size_t i=1; i<nremoved; ++i) mes << 140     for (G4int i=1; i<nremoved; ++i) message << ", " << removedVertices[i];
134     G4Exception("G4ExtrudedSolid::G4ExtrudedSo    141     G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids1001",
135                 JustWarning, message);            142                 JustWarning, message);
136   }                                               143   }
137                                                   144 
138   fNv = fPolygon.size();                          145   fNv = fPolygon.size();
139   if (fNv < 3)                                    146   if (fNv < 3)
140   {                                               147   {
141     std::ostringstream message;                   148     std::ostringstream message;
142     message << "Number of vertices in polygon     149     message << "Number of vertices in polygon after removal < 3 - " << pName;
143     G4Exception("G4ExtrudedSolid::G4ExtrudedSo    150     G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0002",
144                 FatalErrorInArgument, message)    151                 FatalErrorInArgument, message);
145   }                                               152   }
146                                                   153 
147   // Check if polygon vertices are defined clo    154   // Check if polygon vertices are defined clockwise
148   // (the area is positive if polygon vertices    155   // (the area is positive if polygon vertices are defined anti-clockwise)
149   //                                              156   //
150   if (G4GeomTools::PolygonArea(fPolygon) > 0.)    157   if (G4GeomTools::PolygonArea(fPolygon) > 0.)
151   {                                               158   {   
152     // Polygon vertices are defined anti-clock    159     // Polygon vertices are defined anti-clockwise, we revert them
153     // G4Exception("G4ExtrudedSolid::G4Extrude    160     // G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids1001",
154     //            JustWarning,                    161     //            JustWarning, 
155     //            "Polygon vertices defined an    162     //            "Polygon vertices defined anti-clockwise, reverting polygon");
156     std::reverse(fPolygon.begin(),fPolygon.end    163     std::reverse(fPolygon.begin(),fPolygon.end());
157   }                                               164   }
158                                                   165 
159   // Copy z-sections                              166   // Copy z-sections
160   //                                              167   //
161   fZSections = zsections;                         168   fZSections = zsections;
162                                                   169 
163   G4bool result = MakeFacets();                   170   G4bool result = MakeFacets();
164   if (!result)                                    171   if (!result)
165   {                                               172   {   
166     std::ostringstream message;                   173     std::ostringstream message;
167     message << "Making facets failed - " << pN    174     message << "Making facets failed - " << pName;
168     G4Exception("G4ExtrudedSolid::G4ExtrudedSo    175     G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0003",
169                 FatalException, message);         176                 FatalException, message);
170   }                                               177   }
171   fIsConvex = G4GeomTools::IsConvex(fPolygon);    178   fIsConvex = G4GeomTools::IsConvex(fPolygon);
172                                                   179   
173   ComputeProjectionParameters();                  180   ComputeProjectionParameters();
174                                                   181 
175   // Check if the solid is a right prism, if s    182   // Check if the solid is a right prism, if so then set lateral planes
176   //                                              183   //
177   if ((fNz == 2)                                  184   if ((fNz == 2)
178       && (fZSections[0].fScale == 1) && (fZSec    185       && (fZSections[0].fScale == 1) && (fZSections[1].fScale == 1)
179       && (fZSections[0].fOffset == G4TwoVector    186       && (fZSections[0].fOffset == G4TwoVector(0,0))
180       && (fZSections[1].fOffset == G4TwoVector    187       && (fZSections[1].fOffset == G4TwoVector(0,0)))
181   {                                               188   {
182     fSolidType = (fIsConvex) ? 1 : 2; // 1 - c    189     fSolidType = (fIsConvex) ? 1 : 2; // 1 - convex, 2 - non-convex right prism
183     ComputeLateralPlanes();                       190     ComputeLateralPlanes();
184   }                                               191   }
185 }                                                 192 }
186                                                   193 
187 //____________________________________________    194 //_____________________________________________________________________________
188                                                   195 
189 G4ExtrudedSolid::G4ExtrudedSolid( const G4Stri    196 G4ExtrudedSolid::G4ExtrudedSolid( const G4String& pName,
190                                   const std::v    197                                   const std::vector<G4TwoVector>& polygon,
191                                         G4doub    198                                         G4double dz,
192                                   const G4TwoV    199                                   const G4TwoVector& off1, G4double scale1,
193                                   const G4TwoV    200                                   const G4TwoVector& off2, G4double scale2 )
194   : G4TessellatedSolid(pName),                    201   : G4TessellatedSolid(pName),
195     fNv(polygon.size()),                          202     fNv(polygon.size()),
196     fNz(2),                                       203     fNz(2),
197     fGeometryType("G4ExtrudedSolid")           << 204     fIsConvex(false),
                                                   >> 205     fGeometryType("G4ExtrudedSolid"),
                                                   >> 206     fSolidType(0)
198 {                                                 207 {
199   // Special constructor for solid with 2 z-se    208   // Special constructor for solid with 2 z-sections
200                                                   209 
201   // First check input parameters                 210   // First check input parameters
202   //                                              211   //
203   if (fNv < 3)                                    212   if (fNv < 3)
204   {                                               213   {
205     std::ostringstream message;                   214     std::ostringstream message;
206     message << "Number of vertices in polygon     215     message << "Number of vertices in polygon < 3 - " << pName;
207     G4Exception("G4ExtrudedSolid::G4ExtrudedSo    216     G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0002",
208                 FatalErrorInArgument, message)    217                 FatalErrorInArgument, message);
209   }                                               218   }
210                                                   219      
211   // Copy polygon                                 220   // Copy polygon
212   //                                              221   //
213   fPolygon = polygon;                             222   fPolygon = polygon;
214                                                   223 
215   // Remove collinear and coincident vertices,    224   // Remove collinear and coincident vertices, if any
216   //                                              225   //
217   std::vector<G4int> removedVertices;             226   std::vector<G4int> removedVertices;
218   G4GeomTools::RemoveRedundantVertices(fPolygo    227   G4GeomTools::RemoveRedundantVertices(fPolygon,removedVertices,
219                                        2*kCarT    228                                        2*kCarTolerance);
220   if (!removedVertices.empty())                << 229   if (removedVertices.size() != 0)
221   {                                               230   {
222     std::size_t nremoved = removedVertices.siz << 231     G4int nremoved = removedVertices.size();
223     std::ostringstream message;                   232     std::ostringstream message;
224     message << "The following "<< nremoved        233     message << "The following "<< nremoved 
225             << " vertices have been removed fr    234             << " vertices have been removed from polygon in " << pName 
226             << "\nas collinear or coincident w    235             << "\nas collinear or coincident with other vertices: "
227             << removedVertices[0];                236             << removedVertices[0];
228     for (std::size_t i=1; i<nremoved; ++i) mes << 237     for (G4int i=1; i<nremoved; ++i) message << ", " << removedVertices[i];
229     G4Exception("G4ExtrudedSolid::G4ExtrudedSo    238     G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids1001",
230                 JustWarning, message);            239                 JustWarning, message);
231   }                                               240   }
232                                                   241 
233   fNv = fPolygon.size();                          242   fNv = fPolygon.size();
234   if (fNv < 3)                                    243   if (fNv < 3)
235   {                                               244   {
236     std::ostringstream message;                   245     std::ostringstream message;
237     message << "Number of vertices in polygon     246     message << "Number of vertices in polygon after removal < 3 - " << pName;
238     G4Exception("G4ExtrudedSolid::G4ExtrudedSo    247     G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0002",
239                 FatalErrorInArgument, message)    248                 FatalErrorInArgument, message);
240   }                                               249   }
241                                                   250 
242   // Check if polygon vertices are defined clo    251   // Check if polygon vertices are defined clockwise
243   // (the area is positive if polygon vertices    252   // (the area is positive if polygon vertices are defined anti-clockwise)
244   //                                              253   //  
245   if (G4GeomTools::PolygonArea(fPolygon) > 0.)    254   if (G4GeomTools::PolygonArea(fPolygon) > 0.)
246   {                                               255   {
247     // Polygon vertices are defined anti-clock    256     // Polygon vertices are defined anti-clockwise, we revert them
248     // G4Exception("G4ExtrudedSolid::G4Extrude    257     // G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids1001",
249     //            JustWarning,                    258     //            JustWarning, 
250     //            "Polygon vertices defined an    259     //            "Polygon vertices defined anti-clockwise, reverting polygon");
251     std::reverse(fPolygon.begin(),fPolygon.end    260     std::reverse(fPolygon.begin(),fPolygon.end());
252   }                                               261   }
253                                                   262   
254   // Copy z-sections                              263   // Copy z-sections
255   //                                              264   //
256   fZSections.emplace_back(-dz, off1, scale1);  << 265   fZSections.push_back(ZSection(-dz, off1, scale1));
257   fZSections.emplace_back( dz, off2, scale2);  << 266   fZSections.push_back(ZSection( dz, off2, scale2));
258                                                   267     
259   G4bool result = MakeFacets();                   268   G4bool result = MakeFacets();
260   if (!result)                                    269   if (!result)
261   {                                               270   {   
262     std::ostringstream message;                   271     std::ostringstream message;
263     message << "Making facets failed - " << pN    272     message << "Making facets failed - " << pName;
264     G4Exception("G4ExtrudedSolid::G4ExtrudedSo    273     G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0003",
265                 FatalException, message);         274                 FatalException, message);
266   }                                               275   }
267   fIsConvex = G4GeomTools::IsConvex(fPolygon);    276   fIsConvex = G4GeomTools::IsConvex(fPolygon);
268                                                   277 
269   ComputeProjectionParameters();                  278   ComputeProjectionParameters();
270                                                   279 
271   // Check if the solid is a right prism, if s    280   // Check if the solid is a right prism, if so then set lateral planes
272   //                                              281   //
273   if ((scale1 == 1) && (scale2 == 1)              282   if ((scale1 == 1) && (scale2 == 1)
274       && (off1 == G4TwoVector(0,0)) && (off2 =    283       && (off1 == G4TwoVector(0,0)) && (off2 == G4TwoVector(0,0)))
275   {                                               284   {
276     fSolidType = (fIsConvex) ? 1 : 2; // 1 - c    285     fSolidType = (fIsConvex) ? 1 : 2; // 1 - convex, 2 - non-convex right prism
277     ComputeLateralPlanes();                       286     ComputeLateralPlanes();
278   }                                               287   }
279 }                                                 288 }
280                                                   289 
281 //____________________________________________    290 //_____________________________________________________________________________
282                                                   291 
283 G4ExtrudedSolid::G4ExtrudedSolid( __void__& a     292 G4ExtrudedSolid::G4ExtrudedSolid( __void__& a )
284   : G4TessellatedSolid(a), fGeometryType("G4Ex << 293   : G4TessellatedSolid(a), fNv(0), fNz(0), fIsConvex(false),
                                                   >> 294     fGeometryType("G4ExtrudedSolid"), fSolidType(0)
285 {                                                 295 {
286   // Fake default constructor - sets only memb    296   // Fake default constructor - sets only member data and allocates memory
287   //                            for usage rest    297   //                            for usage restricted to object persistency.
288 }                                                 298 }
289                                                   299 
290 //____________________________________________    300 //_____________________________________________________________________________
291                                                   301 
292 G4ExtrudedSolid::G4ExtrudedSolid(const G4Extru << 302 G4ExtrudedSolid::G4ExtrudedSolid(const G4ExtrudedSolid& rhs)
                                                   >> 303   : G4TessellatedSolid(rhs), fNv(rhs.fNv), fNz(rhs.fNz),
                                                   >> 304     fPolygon(rhs.fPolygon), fZSections(rhs.fZSections),
                                                   >> 305     fTriangles(rhs.fTriangles), fIsConvex(rhs.fIsConvex),
                                                   >> 306     fGeometryType(rhs.fGeometryType),
                                                   >> 307     fSolidType(rhs.fSolidType), fPlanes(rhs.fPlanes),
                                                   >> 308     fLines(rhs.fLines), fLengths(rhs.fLengths),
                                                   >> 309     fKScales(rhs.fKScales), fScale0s(rhs.fScale0s),
                                                   >> 310     fKOffsets(rhs.fKOffsets), fOffset0s(rhs.fOffset0s)
                                                   >> 311 {
                                                   >> 312 }
293                                                   313 
294 //____________________________________________    314 //_____________________________________________________________________________
295                                                   315 
296 G4ExtrudedSolid& G4ExtrudedSolid::operator = (    316 G4ExtrudedSolid& G4ExtrudedSolid::operator = (const G4ExtrudedSolid& rhs)
297 {                                                 317 {
298    // Check assignment to self                    318    // Check assignment to self
299    //                                             319    //
300    if (this == &rhs)  { return *this; }           320    if (this == &rhs)  { return *this; }
301                                                   321 
302    // Copy base class data                        322    // Copy base class data
303    //                                             323    //
304    G4TessellatedSolid::operator=(rhs);            324    G4TessellatedSolid::operator=(rhs);
305                                                   325 
306    // Copy data                                   326    // Copy data
307    //                                             327    //
308    fNv = rhs.fNv; fNz = rhs.fNz;                  328    fNv = rhs.fNv; fNz = rhs.fNz;
309    fPolygon = rhs.fPolygon; fZSections = rhs.f    329    fPolygon = rhs.fPolygon; fZSections = rhs.fZSections;
310    fTriangles = rhs.fTriangles; fIsConvex = rh    330    fTriangles = rhs.fTriangles; fIsConvex = rhs.fIsConvex;
311    fGeometryType = rhs.fGeometryType;             331    fGeometryType = rhs.fGeometryType;
312    fSolidType = rhs.fSolidType; fPlanes = rhs.    332    fSolidType = rhs.fSolidType; fPlanes = rhs.fPlanes;
313    fLines = rhs.fLines; fLengths = rhs.fLength    333    fLines = rhs.fLines; fLengths = rhs.fLengths;
314    fKScales = rhs.fKScales; fScale0s = rhs.fSc    334    fKScales = rhs.fKScales; fScale0s = rhs.fScale0s;
315    fKOffsets = rhs.fKOffsets; fOffset0s = rhs.    335    fKOffsets = rhs.fKOffsets; fOffset0s = rhs.fOffset0s;
316                                                   336 
317    return *this;                                  337    return *this;
318 }                                                 338 }
319                                                   339 
320 //____________________________________________    340 //_____________________________________________________________________________
321                                                   341 
322 G4ExtrudedSolid::~G4ExtrudedSolid()               342 G4ExtrudedSolid::~G4ExtrudedSolid()
323 {                                                 343 {
324   // Destructor                                   344   // Destructor
325 }                                                 345 }
326                                                   346 
327 //____________________________________________    347 //_____________________________________________________________________________
328                                                   348 
329 void G4ExtrudedSolid::ComputeProjectionParamet    349 void G4ExtrudedSolid::ComputeProjectionParameters()
330 {                                                 350 {
331   // Compute parameters for point projections     351   // Compute parameters for point projections p(z)
332   // to the polygon scale & offset:               352   // to the polygon scale & offset:
333   // scale(z) = k*z + scale0                      353   // scale(z) = k*z + scale0
334   // offset(z) = l*z + offset0                    354   // offset(z) = l*z + offset0
335   // p(z) = scale(z)*p0 + offset(z)               355   // p(z) = scale(z)*p0 + offset(z)
336   // p0 = (p(z) - offset(z))/scale(z);            356   // p0 = (p(z) - offset(z))/scale(z);
337   //                                              357   //
338                                                   358 
339   for (std::size_t iz=0; iz<fNz-1; ++iz)       << 359   for ( G4int iz=0; iz<fNz-1; ++iz)
340   {                                               360   {
341     G4double z1      = fZSections[iz].fZ;         361     G4double z1      = fZSections[iz].fZ;
342     G4double z2      = fZSections[iz+1].fZ;       362     G4double z2      = fZSections[iz+1].fZ;
343     G4double scale1  = fZSections[iz].fScale;     363     G4double scale1  = fZSections[iz].fScale;
344     G4double scale2  = fZSections[iz+1].fScale    364     G4double scale2  = fZSections[iz+1].fScale;
345     G4TwoVector off1 = fZSections[iz].fOffset;    365     G4TwoVector off1 = fZSections[iz].fOffset;
346     G4TwoVector off2 = fZSections[iz+1].fOffse    366     G4TwoVector off2 = fZSections[iz+1].fOffset;
347                                                   367 
348     G4double kscale = (scale2 - scale1)/(z2 -     368     G4double kscale = (scale2 - scale1)/(z2 - z1);
349     G4double scale0 =  scale2 - kscale*(z2 - z    369     G4double scale0 =  scale2 - kscale*(z2 - z1)/2.0;
350     G4TwoVector koff = (off2 - off1)/(z2 - z1)    370     G4TwoVector koff = (off2 - off1)/(z2 - z1);
351     G4TwoVector off0 =  off2 - koff*(z2 - z1)/    371     G4TwoVector off0 =  off2 - koff*(z2 - z1)/2.0;
352                                                   372 
353     fKScales.push_back(kscale);                   373     fKScales.push_back(kscale);
354     fScale0s.push_back(scale0);                   374     fScale0s.push_back(scale0);
355     fKOffsets.push_back(koff);                    375     fKOffsets.push_back(koff);
356     fOffset0s.push_back(off0);                    376     fOffset0s.push_back(off0);
357   }                                               377   }
358 }                                                 378 }
359                                                   379 
360 //____________________________________________    380 //_____________________________________________________________________________
361                                                   381 
362 void G4ExtrudedSolid::ComputeLateralPlanes()      382 void G4ExtrudedSolid::ComputeLateralPlanes()
363 {                                                 383 {
364   // Compute lateral planes: a*x + b*y + c*z +    384   // Compute lateral planes: a*x + b*y + c*z + d = 0
365   //                                              385   //
366   std::size_t Nv = fPolygon.size();            << 386   G4int Nv = fPolygon.size();
367   fPlanes.resize(Nv);                             387   fPlanes.resize(Nv);
368   for (std::size_t i=0, k=Nv-1; i<Nv; k=i++)   << 388   for (G4int i=0, k=Nv-1; i<Nv; k=i++)
369   {                                               389   {
370     G4TwoVector norm = (fPolygon[i] - fPolygon    390     G4TwoVector norm = (fPolygon[i] - fPolygon[k]).unit();
371     fPlanes[i].a = -norm.y();                     391     fPlanes[i].a = -norm.y();
372     fPlanes[i].b =  norm.x();                     392     fPlanes[i].b =  norm.x();
373     fPlanes[i].c =  0;                            393     fPlanes[i].c =  0;
374     fPlanes[i].d =  norm.y()*fPolygon[i].x() -    394     fPlanes[i].d =  norm.y()*fPolygon[i].x() - norm.x()*fPolygon[i].y();
375   }                                               395   }
376                                                   396 
377   // Compute edge equations: x = k*y + m          397   // Compute edge equations: x = k*y + m
378   // and edge lengths                             398   // and edge lengths
379   //                                              399   //
380   fLines.resize(Nv);                              400   fLines.resize(Nv);
381   fLengths.resize(Nv);                            401   fLengths.resize(Nv);
382   for (std::size_t i=0, k=Nv-1; i<Nv; k=i++)   << 402   for (G4int i=0, k=Nv-1; i<Nv; k=i++)
383   {                                               403   {
384     if (fPolygon[k].y() == fPolygon[i].y())       404     if (fPolygon[k].y() == fPolygon[i].y())
385     {                                             405     {
386       fLines[i].k = 0;                            406       fLines[i].k = 0;
387       fLines[i].m = fPolygon[i].x();              407       fLines[i].m = fPolygon[i].x();
388     }                                             408     }
389     else                                          409     else
390     {                                             410     {
391       G4double ctg = (fPolygon[k].x()-fPolygon    411       G4double ctg = (fPolygon[k].x()-fPolygon[i].x())/(fPolygon[k].y()-fPolygon[i].y());
392       fLines[i].k = ctg;                          412       fLines[i].k = ctg;
393       fLines[i].m = fPolygon[i].x() - ctg*fPol    413       fLines[i].m = fPolygon[i].x() - ctg*fPolygon[i].y();
394     }                                             414     }
395     fLengths[i]  =  (fPolygon[i] - fPolygon[k]    415     fLengths[i]  =  (fPolygon[i] - fPolygon[k]).mag();
396   }                                               416   }
397 }                                                 417 }
398                                                   418 
399 //____________________________________________    419 //_____________________________________________________________________________
400                                                   420 
401 G4ThreeVector G4ExtrudedSolid::GetVertex(G4int    421 G4ThreeVector G4ExtrudedSolid::GetVertex(G4int iz, G4int ind) const
402 {                                                 422 {
403   // Shift and scale vertices                     423   // Shift and scale vertices
404                                                   424 
405   return { fPolygon[ind].x() * fZSections[iz]. << 425   return G4ThreeVector( fPolygon[ind].x() * fZSections[iz].fScale
406           + fZSections[iz].fOffset.x(),        << 426                       + fZSections[iz].fOffset.x(), 
407            fPolygon[ind].y() * fZSections[iz]. << 427                         fPolygon[ind].y() * fZSections[iz].fScale
408           + fZSections[iz].fOffset.y(),        << 428                       + fZSections[iz].fOffset.y(), fZSections[iz].fZ);
409            fZSections[iz].fZ };                << 
410 }                                                 429 }       
411                                                   430 
412 //____________________________________________    431 //_____________________________________________________________________________
413                                                   432 
414 G4TwoVector G4ExtrudedSolid::ProjectPoint(cons    433 G4TwoVector G4ExtrudedSolid::ProjectPoint(const G4ThreeVector& point) const
415 {                                                 434 {
416   // Project point in the polygon scale           435   // Project point in the polygon scale
417   // scale(z) = k*z + scale0                      436   // scale(z) = k*z + scale0
418   // offset(z) = l*z + offset0                    437   // offset(z) = l*z + offset0
419   // p(z) = scale(z)*p0 + offset(z)               438   // p(z) = scale(z)*p0 + offset(z)  
420   // p0 = (p(z) - offset(z))/scale(z);            439   // p0 = (p(z) - offset(z))/scale(z);
421                                                   440   
422   // Select projection (z-segment of the solid    441   // Select projection (z-segment of the solid) according to p.z()
423   //                                              442   //
424   std::size_t iz = 0;                          << 443   G4int iz = 0;
425   while ( point.z() > fZSections[iz+1].fZ && i    444   while ( point.z() > fZSections[iz+1].fZ && iz < fNz-2 ) { ++iz; }
426       // Loop checking, 13.08.2015, G.Cosmo       445       // Loop checking, 13.08.2015, G.Cosmo
427                                                   446   
428   G4double z0 = ( fZSections[iz+1].fZ + fZSect    447   G4double z0 = ( fZSections[iz+1].fZ + fZSections[iz].fZ )/2.0;
429   G4TwoVector p2(point.x(), point.y());           448   G4TwoVector p2(point.x(), point.y());
430   G4double pscale  = fKScales[iz]*(point.z()-z    449   G4double pscale  = fKScales[iz]*(point.z()-z0) + fScale0s[iz];
431   G4TwoVector poffset = fKOffsets[iz]*(point.z    450   G4TwoVector poffset = fKOffsets[iz]*(point.z()-z0) + fOffset0s[iz];
432                                                   451   
433   // G4cout << point << " projected to "          452   // G4cout << point << " projected to " 
434   //        << iz << "-th z-segment polygon as    453   //        << iz << "-th z-segment polygon as "
435   //        << (p2 - poffset)/pscale << G4endl    454   //        << (p2 - poffset)/pscale << G4endl;
436                                                   455 
437   // pscale is always >0 as it is an interpola    456   // pscale is always >0 as it is an interpolation between two
438   // positive scale values                        457   // positive scale values
439   //                                              458   //
440   return (p2 - poffset)/pscale;                   459   return (p2 - poffset)/pscale;
441 }                                                 460 }  
442                                                   461 
443 //____________________________________________    462 //_____________________________________________________________________________
444                                                   463 
445 G4bool G4ExtrudedSolid::IsSameLine(const G4Two    464 G4bool G4ExtrudedSolid::IsSameLine(const G4TwoVector& p,
446                                    const G4Two    465                                    const G4TwoVector& l1,
447                                    const G4Two    466                                    const G4TwoVector& l2) const
448 {                                                 467 {
449   // Return true if p is on the line through l    468   // Return true if p is on the line through l1, l2 
450                                                   469 
451   if ( l1.x() == l2.x() )                         470   if ( l1.x() == l2.x() )
452   {                                               471   {
453     return std::fabs(p.x() - l1.x()) < kCarTol    472     return std::fabs(p.x() - l1.x()) < kCarToleranceHalf; 
454   }                                               473   }
455    G4double slope= ((l2.y() - l1.y())/(l2.x()     474    G4double slope= ((l2.y() - l1.y())/(l2.x() - l1.x())); 
456    G4double predy= l1.y() +  slope *(p.x() - l    475    G4double predy= l1.y() +  slope *(p.x() - l1.x()); 
457    G4double dy= p.y() - predy;                    476    G4double dy= p.y() - predy; 
458                                                   477 
459    // Calculate perpendicular distance            478    // Calculate perpendicular distance
460    //                                             479    //
461    // G4double perpD= std::fabs(dy) / std::sqr    480    // G4double perpD= std::fabs(dy) / std::sqrt( 1 + slope * slope ); 
462    // G4bool   simpleComp= (perpD<kCarToleranc    481    // G4bool   simpleComp= (perpD<kCarToleranceHalf); 
463                                                   482 
464    // Check perpendicular distance vs toleranc    483    // Check perpendicular distance vs tolerance 'directly'
465    //                                             484    //
466    G4bool squareComp = (dy*dy < (1+slope*slope    485    G4bool squareComp = (dy*dy < (1+slope*slope)
467                      * kCarToleranceHalf * kCa    486                      * kCarToleranceHalf * kCarToleranceHalf); 
468                                                   487 
469    // return  simpleComp;                         488    // return  simpleComp; 
470    return squareComp;                             489    return squareComp;
471 }                                                 490 }                    
472                                                   491 
473 //____________________________________________    492 //_____________________________________________________________________________
474                                                   493 
475 G4bool G4ExtrudedSolid::IsSameLineSegment(cons    494 G4bool G4ExtrudedSolid::IsSameLineSegment(const G4TwoVector& p,  
476                                           cons    495                                           const G4TwoVector& l1,
477                                           cons    496                                           const G4TwoVector& l2) const
478 {                                                 497 {
479   // Return true if p is on the line through l    498   // Return true if p is on the line through l1, l2 and lies between
480   // l1 and l2                                    499   // l1 and l2 
481                                                   500 
482   if ( p.x() < std::min(l1.x(), l2.x()) - kCar    501   if ( p.x() < std::min(l1.x(), l2.x()) - kCarToleranceHalf || 
483        p.x() > std::max(l1.x(), l2.x()) + kCar    502        p.x() > std::max(l1.x(), l2.x()) + kCarToleranceHalf ||
484        p.y() < std::min(l1.y(), l2.y()) - kCar    503        p.y() < std::min(l1.y(), l2.y()) - kCarToleranceHalf || 
485        p.y() > std::max(l1.y(), l2.y()) + kCar    504        p.y() > std::max(l1.y(), l2.y()) + kCarToleranceHalf )
486   {                                               505   {
487     return false;                                 506     return false;
488   }                                               507   }
489                                                   508 
490   return IsSameLine(p, l1, l2);                   509   return IsSameLine(p, l1, l2);
491 }                                                 510 }
492                                                   511 
493 //____________________________________________    512 //_____________________________________________________________________________
494                                                   513 
495 G4bool G4ExtrudedSolid::IsSameSide(const G4Two    514 G4bool G4ExtrudedSolid::IsSameSide(const G4TwoVector& p1,
496                                    const G4Two    515                                    const G4TwoVector& p2,
497                                    const G4Two    516                                    const G4TwoVector& l1,
498                                    const G4Two    517                                    const G4TwoVector& l2) const
499 {                                                 518 {
500   // Return true if p1 and p2 are on the same     519   // Return true if p1 and p2 are on the same side of the line through l1, l2 
501                                                   520 
502   return   ( (p1.x() - l1.x()) * (l2.y() - l1.    521   return   ( (p1.x() - l1.x()) * (l2.y() - l1.y())
503          - (l2.x() - l1.x()) * (p1.y() - l1.y(    522          - (l2.x() - l1.x()) * (p1.y() - l1.y()) )
504          * ( (p2.x() - l1.x()) * (l2.y() - l1.    523          * ( (p2.x() - l1.x()) * (l2.y() - l1.y())
505          - (l2.x() - l1.x()) * (p2.y() - l1.y(    524          - (l2.x() - l1.x()) * (p2.y() - l1.y()) ) > 0;
506 }                                                 525 }       
507                                                   526 
508 //____________________________________________    527 //_____________________________________________________________________________
509                                                   528 
510 G4bool G4ExtrudedSolid::IsPointInside(const G4    529 G4bool G4ExtrudedSolid::IsPointInside(const G4TwoVector& a,
511                                       const G4    530                                       const G4TwoVector& b,
512                                       const G4    531                                       const G4TwoVector& c,
513                                       const G4    532                                       const G4TwoVector& p) const
514 {                                                 533 {
515   // Return true if p is inside of triangle ab    534   // Return true if p is inside of triangle abc or on its edges, 
516   // else returns false                           535   // else returns false 
517                                                   536 
518   // Check extent first                           537   // Check extent first
519   //                                              538   //
520   if ( ( p.x() < a.x() && p.x() < b.x() && p.x    539   if ( ( p.x() < a.x() && p.x() < b.x() && p.x() < c.x() ) || 
521        ( p.x() > a.x() && p.x() > b.x() && p.x    540        ( p.x() > a.x() && p.x() > b.x() && p.x() > c.x() ) || 
522        ( p.y() < a.y() && p.y() < b.y() && p.y    541        ( p.y() < a.y() && p.y() < b.y() && p.y() < c.y() ) || 
523        ( p.y() > a.y() && p.y() > b.y() && p.y    542        ( p.y() > a.y() && p.y() > b.y() && p.y() > c.y() ) ) return false;
524                                                   543   
525   G4bool inside                                   544   G4bool inside 
526     = IsSameSide(p, a, b, c)                      545     = IsSameSide(p, a, b, c)
527       && IsSameSide(p, b, a, c)                   546       && IsSameSide(p, b, a, c)
528       && IsSameSide(p, c, a, b);                  547       && IsSameSide(p, c, a, b);
529                                                   548 
530   G4bool onEdge                                   549   G4bool onEdge
531     = IsSameLineSegment(p, a, b)                  550     = IsSameLineSegment(p, a, b)
532       || IsSameLineSegment(p, b, c)               551       || IsSameLineSegment(p, b, c)
533       || IsSameLineSegment(p, c, a);              552       || IsSameLineSegment(p, c, a);
534                                                   553       
535   return inside || onEdge;                        554   return inside || onEdge;    
536 }                                                 555 }     
537                                                   556 
538 //____________________________________________    557 //_____________________________________________________________________________
539                                                   558 
540 G4double                                          559 G4double 
541 G4ExtrudedSolid::GetAngle(const G4TwoVector& p    560 G4ExtrudedSolid::GetAngle(const G4TwoVector& po,
542                           const G4TwoVector& p    561                           const G4TwoVector& pa,
543                           const G4TwoVector& p    562                           const G4TwoVector& pb) const
544 {                                                 563 {
545   // Return the angle of the vertex in po         564   // Return the angle of the vertex in po
546                                                   565 
547   G4TwoVector t1 = pa - po;                       566   G4TwoVector t1 = pa - po;
548   G4TwoVector t2 = pb - po;                       567   G4TwoVector t2 = pb - po;
549                                                   568   
550   G4double result = (std::atan2(t1.y(), t1.x()    569   G4double result = (std::atan2(t1.y(), t1.x()) - std::atan2(t2.y(), t2.x()));
551                                                   570 
552   if ( result < 0 ) result += 2*pi;               571   if ( result < 0 ) result += 2*pi;
553                                                   572 
554   return result;                                  573   return result;
555 }                                                 574 }
556                                                   575 
557 //____________________________________________    576 //_____________________________________________________________________________
558                                                   577 
559 G4VFacet*                                         578 G4VFacet*
560 G4ExtrudedSolid::MakeDownFacet(G4int ind1, G4i    579 G4ExtrudedSolid::MakeDownFacet(G4int ind1, G4int ind2, G4int ind3) const
561 {                                                 580 {
562   // Create a triangular facet from the polygo    581   // Create a triangular facet from the polygon points given by indices
563   // forming the down side ( the normal goes i    582   // forming the down side ( the normal goes in -z)
564                                                   583 
565   std::vector<G4ThreeVector> vertices;            584   std::vector<G4ThreeVector> vertices;
566   vertices.push_back(GetVertex(0, ind1));         585   vertices.push_back(GetVertex(0, ind1));
567   vertices.push_back(GetVertex(0, ind2));         586   vertices.push_back(GetVertex(0, ind2));
568   vertices.push_back(GetVertex(0, ind3));         587   vertices.push_back(GetVertex(0, ind3));
569                                                   588   
570   // first vertex most left                       589   // first vertex most left
571   //                                              590   //
572   G4ThreeVector cross                             591   G4ThreeVector cross 
573     = (vertices[1]-vertices[0]).cross(vertices    592     = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[1]);
574                                                   593   
575   if ( cross.z() > 0.0 )                          594   if ( cross.z() > 0.0 )
576   {                                               595   {
577     // vertices ordered clock wise has to be r    596     // vertices ordered clock wise has to be reordered
578                                                   597 
579     // G4cout << "G4ExtrudedSolid::MakeDownFac    598     // G4cout << "G4ExtrudedSolid::MakeDownFacet: reordering vertices " 
580     //        << ind1 << ", " << ind2 << ", "     599     //        << ind1 << ", " << ind2 << ", " << ind3 << G4endl; 
581                                                   600 
582     G4ThreeVector tmp = vertices[1];              601     G4ThreeVector tmp = vertices[1];
583     vertices[1] = vertices[2];                    602     vertices[1] = vertices[2];
584     vertices[2] = tmp;                            603     vertices[2] = tmp;
585   }                                               604   }
586                                                   605   
587   return new G4TriangularFacet(vertices[0], ve    606   return new G4TriangularFacet(vertices[0], vertices[1],
588                                vertices[2], AB    607                                vertices[2], ABSOLUTE);
589 }                                                 608 }      
590                                                   609 
591 //____________________________________________    610 //_____________________________________________________________________________
592                                                   611 
593 G4VFacet*                                         612 G4VFacet*
594 G4ExtrudedSolid::MakeUpFacet(G4int ind1, G4int    613 G4ExtrudedSolid::MakeUpFacet(G4int ind1, G4int ind2, G4int ind3) const      
595 {                                                 614 {
596   // Creates a triangular facet from the polyg    615   // Creates a triangular facet from the polygon points given by indices
597   // forming the upper side ( z>0 )               616   // forming the upper side ( z>0 )
598                                                   617 
599   std::vector<G4ThreeVector> vertices;            618   std::vector<G4ThreeVector> vertices;
600   vertices.push_back(GetVertex((G4int)fNz-1, i << 619   vertices.push_back(GetVertex(fNz-1, ind1));
601   vertices.push_back(GetVertex((G4int)fNz-1, i << 620   vertices.push_back(GetVertex(fNz-1, ind2));
602   vertices.push_back(GetVertex((G4int)fNz-1, i << 621   vertices.push_back(GetVertex(fNz-1, ind3));
603                                                   622   
604   // first vertex most left                       623   // first vertex most left
605   //                                              624   //
606   G4ThreeVector cross                             625   G4ThreeVector cross 
607     = (vertices[1]-vertices[0]).cross(vertices    626     = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[1]);
608                                                   627   
609   if ( cross.z() < 0.0 )                          628   if ( cross.z() < 0.0 )
610   {                                               629   {
611     // vertices ordered clock wise has to be r    630     // vertices ordered clock wise has to be reordered
612                                                   631 
613     // G4cout << "G4ExtrudedSolid::MakeUpFacet    632     // G4cout << "G4ExtrudedSolid::MakeUpFacet: reordering vertices " 
614     //        << ind1 << ", " << ind2 << ", "     633     //        << ind1 << ", " << ind2 << ", " << ind3 << G4endl; 
615                                                   634 
616     G4ThreeVector tmp = vertices[1];              635     G4ThreeVector tmp = vertices[1];
617     vertices[1] = vertices[2];                    636     vertices[1] = vertices[2];
618     vertices[2] = tmp;                            637     vertices[2] = tmp;
619   }                                               638   }
620                                                   639   
621   return new G4TriangularFacet(vertices[0], ve    640   return new G4TriangularFacet(vertices[0], vertices[1],
622                                vertices[2], AB    641                                vertices[2], ABSOLUTE);
623 }                                                 642 }      
624                                                   643 
625 //____________________________________________    644 //_____________________________________________________________________________
626                                                   645 
627 G4bool G4ExtrudedSolid::AddGeneralPolygonFacet    646 G4bool G4ExtrudedSolid::AddGeneralPolygonFacets()
628 {                                                 647 {
629   // Decompose polygonal sides in triangular f    648   // Decompose polygonal sides in triangular facets
630                                                   649 
631   typedef std::pair < G4TwoVector, G4int > Ver    650   typedef std::pair < G4TwoVector, G4int > Vertex;
632                                                   651 
633   static const G4double kAngTolerance =           652   static const G4double kAngTolerance =
634     G4GeometryTolerance::GetInstance()->GetAng    653     G4GeometryTolerance::GetInstance()->GetAngularTolerance();
635                                                   654 
636   // Fill one more vector                         655   // Fill one more vector
637   //                                              656   //
638   std::vector< Vertex > verticesToBeDone;         657   std::vector< Vertex > verticesToBeDone;
639   for ( G4int i=0; i<(G4int)fNv; ++i )         << 658   for ( G4int i=0; i<fNv; ++i )
640   {                                               659   {
641     verticesToBeDone.emplace_back(fPolygon[i], << 660     verticesToBeDone.push_back(Vertex(fPolygon[i], i));
642   }                                               661   }
643   std::vector< Vertex > ears;                     662   std::vector< Vertex > ears;
644                                                   663   
645   auto c1 = verticesToBeDone.begin();          << 664   std::vector< Vertex >::iterator c1 = verticesToBeDone.begin();
646   auto c2 = c1+1;                              << 665   std::vector< Vertex >::iterator c2 = c1+1;  
647   auto c3 = c1+2;                              << 666   std::vector< Vertex >::iterator c3 = c1+2;  
648   while ( verticesToBeDone.size()>2 )    // Lo    667   while ( verticesToBeDone.size()>2 )    // Loop checking, 13.08.2015, G.Cosmo
649   {                                               668   {
650                                                   669 
651     // G4cout << "Looking at triangle : "         670     // G4cout << "Looking at triangle : "
652     //         << c1->second << "  " << c2->se    671     //         << c1->second << "  " << c2->second
653     //        << "  " << c3->second << G4endl;    672     //        << "  " << c3->second << G4endl;  
654     //G4cout << "Looking at triangle : "          673     //G4cout << "Looking at triangle : "
655     //        << c1->first << "  " << c2->firs    674     //        << c1->first << "  " << c2->first
656     //        << "  " << c3->first << G4endl;     675     //        << "  " << c3->first << G4endl;  
657                                                   676 
658     // skip concave vertices                      677     // skip concave vertices
659     //                                            678     //
660     G4double angle = GetAngle(c2->first, c3->f    679     G4double angle = GetAngle(c2->first, c3->first, c1->first);
661                                                   680    
662     //G4cout << "angle " << angle  << G4endl;     681     //G4cout << "angle " << angle  << G4endl;
663                                                   682 
664     std::size_t counter = 0;                   << 683     G4int counter = 0;
665     while ( angle >= (pi-kAngTolerance) )  //     684     while ( angle >= (pi-kAngTolerance) )  // Loop checking, 13.08.2015, G.Cosmo
666     {                                             685     {
667       // G4cout << "Skipping concave vertex "     686       // G4cout << "Skipping concave vertex " << c2->second << G4endl;
668                                                   687 
669       // try next three consecutive vertices      688       // try next three consecutive vertices
670       //                                          689       //
671       c1 = c2;                                    690       c1 = c2;
672       c2 = c3;                                    691       c2 = c3;
673       ++c3;                                       692       ++c3; 
674       if ( c3 == verticesToBeDone.end() ) { c3    693       if ( c3 == verticesToBeDone.end() ) { c3 = verticesToBeDone.begin(); }
675                                                   694 
676       //G4cout << "Looking at triangle : "        695       //G4cout << "Looking at triangle : "
677       //      << c1->first << "  " << c2->firs    696       //      << c1->first << "  " << c2->first
678       //        << "  " << c3->first << G4endl    697       //        << "  " << c3->first << G4endl; 
679                                                   698       
680       angle = GetAngle(c2->first, c3->first, c    699       angle = GetAngle(c2->first, c3->first, c1->first); 
681       //G4cout << "angle " << angle  << G4endl    700       //G4cout << "angle " << angle  << G4endl;
682                                                   701       
683       ++counter;                               << 702       counter++;
684                                                   703       
685       if ( counter > fNv )                     << 704       if ( counter > fNv) {
686       {                                        << 
687         G4Exception("G4ExtrudedSolid::AddGener    705         G4Exception("G4ExtrudedSolid::AddGeneralPolygonFacets",
688                     "GeomSolids0003", FatalExc    706                     "GeomSolids0003", FatalException,
689                     "Triangularisation has fai    707                     "Triangularisation has failed.");
690         break;                                    708         break;
691       }                                           709       }  
692     }                                             710     }
693                                                   711 
694     G4bool good = true;                           712     G4bool good = true;
695     for ( auto it=verticesToBeDone.cbegin(); i << 713     std::vector< Vertex >::iterator it;
                                                   >> 714     for ( it=verticesToBeDone.begin(); it != verticesToBeDone.end(); ++it )
696     {                                             715     {
697       // skip vertices of tested triangle         716       // skip vertices of tested triangle
698       //                                          717       //
699       if ( it == c1 || it == c2 || it == c3 )     718       if ( it == c1 || it == c2 || it == c3 ) { continue; }
700                                                   719 
701       if ( IsPointInside(c1->first, c2->first,    720       if ( IsPointInside(c1->first, c2->first, c3->first, it->first) )
702       {                                           721       {
703         // G4cout << "Point " << it->second <<    722         // G4cout << "Point " << it->second << " is inside" << G4endl;
704         good = false;                             723         good = false;
705                                                   724 
706         // try next three consecutive vertices    725         // try next three consecutive vertices
707         //                                        726         //
708         c1 = c2;                                  727         c1 = c2;
709         c2 = c3;                                  728         c2 = c3;
710         ++c3;                                     729         ++c3; 
711         if ( c3 == verticesToBeDone.end() ) {     730         if ( c3 == verticesToBeDone.end() ) { c3 = verticesToBeDone.begin(); }
712         break;                                    731         break;
713       }                                           732       }
714       // else                                     733       // else 
715       //   { G4cout << "Point " << it->second     734       //   { G4cout << "Point " << it->second << " is outside" << G4endl; }
716     }                                             735     }
717     if ( good )                                   736     if ( good )
718     {                                             737     {
719       // all points are outside triangle, we c    738       // all points are outside triangle, we can make a facet
720                                                   739 
721       // G4cout << "Found triangle : "            740       // G4cout << "Found triangle : "
722       //        << c1->second << "  " << c2->s    741       //        << c1->second << "  " << c2->second
723       //        << "  " << c3->second << G4end    742       //        << "  " << c3->second << G4endl;  
724                                                   743 
725       G4bool result;                              744       G4bool result;
726       result = AddFacet( MakeDownFacet(c1->sec    745       result = AddFacet( MakeDownFacet(c1->second, c2->second, c3->second) );
727       if ( ! result ) { return false; }           746       if ( ! result ) { return false; }
728                                                   747 
729       result = AddFacet( MakeUpFacet(c1->secon    748       result = AddFacet( MakeUpFacet(c1->second, c2->second, c3->second) );
730       if ( ! result ) { return false; }           749       if ( ! result ) { return false; }
731                                                   750 
732       std::vector<G4int> triangle(3);             751       std::vector<G4int> triangle(3);
733       triangle[0] = c1->second;                   752       triangle[0] = c1->second;
734       triangle[1] = c2->second;                   753       triangle[1] = c2->second;
735       triangle[2] = c3->second;                   754       triangle[2] = c3->second;
736       fTriangles.push_back(std::move(triangle) << 755       fTriangles.push_back(triangle);
737                                                   756 
738       // remove the ear point from verticesToB    757       // remove the ear point from verticesToBeDone
739       //                                          758       //
740       verticesToBeDone.erase(c2);                 759       verticesToBeDone.erase(c2);
741       c1 = verticesToBeDone.begin();              760       c1 = verticesToBeDone.begin();
742       c2 = c1+1;                                  761       c2 = c1+1;  
743       c3 = c1+2;                                  762       c3 = c1+2;  
744     }                                             763     } 
745   }                                               764   }
746   return true;                                    765   return true;
747 }                                                 766 }
748                                                   767 
749 //____________________________________________    768 //_____________________________________________________________________________
750                                                   769 
751 G4bool G4ExtrudedSolid::MakeFacets()              770 G4bool G4ExtrudedSolid::MakeFacets()
752 {                                                 771 {
753   // Define facets                                772   // Define facets
754                                                   773 
755   G4bool good;                                    774   G4bool good;
756                                                   775   
757   // Decomposition of polygonal sides in the f    776   // Decomposition of polygonal sides in the facets
758   //                                              777   //
759   if ( fNv == 3 )                                 778   if ( fNv == 3 )
760   {                                               779   {
761     good = AddFacet( new G4TriangularFacet( Ge    780     good = AddFacet( new G4TriangularFacet( GetVertex(0, 0), GetVertex(0, 1),
762                                             Ge    781                                             GetVertex(0, 2), ABSOLUTE) );
763     if ( ! good ) { return false; }               782     if ( ! good ) { return false; }
764                                                   783 
765     good = AddFacet( new G4TriangularFacet( Ge << 784     good = AddFacet( new G4TriangularFacet( GetVertex(fNz-1, 2),
766                                             Ge << 785                                             GetVertex(fNz-1, 1),
767                                             Ge << 786                                             GetVertex(fNz-1, 0),
768                                             AB    787                                             ABSOLUTE) );
769     if ( ! good ) { return false; }               788     if ( ! good ) { return false; }
770                                                   789     
771     std::vector<G4int> triangle(3);               790     std::vector<G4int> triangle(3);
772     triangle[0] = 0;                              791     triangle[0] = 0;
773     triangle[1] = 1;                              792     triangle[1] = 1;
774     triangle[2] = 2;                              793     triangle[2] = 2;
775     fTriangles.push_back(std::move(triangle)); << 794     fTriangles.push_back(triangle);
776   }                                               795   }
777                                                   796   
778   else if ( fNv == 4 )                            797   else if ( fNv == 4 )
779   {                                               798   {
780     good = AddFacet( new G4QuadrangularFacet(     799     good = AddFacet( new G4QuadrangularFacet( GetVertex(0, 0),GetVertex(0, 1),
781                                                   800                                               GetVertex(0, 2),GetVertex(0, 3),
782                                                   801                                               ABSOLUTE) );
783     if ( ! good ) { return false; }               802     if ( ! good ) { return false; }
784                                                   803 
785     good = AddFacet( new G4QuadrangularFacet(  << 804     good = AddFacet( new G4QuadrangularFacet( GetVertex(fNz-1, 3),
786                                                << 805                                               GetVertex(fNz-1, 2), 
787                                                << 806                                               GetVertex(fNz-1, 1),
788                                                << 807                                               GetVertex(fNz-1, 0),
789                                                   808                                               ABSOLUTE) );
790     if ( ! good ) { return false; }               809     if ( ! good ) { return false; }
791                                                   810 
792     std::vector<G4int> triangle1(3);              811     std::vector<G4int> triangle1(3);
793     triangle1[0] = 0;                             812     triangle1[0] = 0;
794     triangle1[1] = 1;                             813     triangle1[1] = 1;
795     triangle1[2] = 2;                             814     triangle1[2] = 2;
796     fTriangles.push_back(std::move(triangle1)) << 815     fTriangles.push_back(triangle1);
797                                                   816 
798     std::vector<G4int> triangle2(3);              817     std::vector<G4int> triangle2(3);
799     triangle2[0] = 0;                             818     triangle2[0] = 0;
800     triangle2[1] = 2;                             819     triangle2[1] = 2;
801     triangle2[2] = 3;                             820     triangle2[2] = 3;
802     fTriangles.push_back(std::move(triangle2)) << 821     fTriangles.push_back(triangle2);
803   }                                               822   }  
804   else                                            823   else
805   {                                               824   {
806     good = AddGeneralPolygonFacets();             825     good = AddGeneralPolygonFacets();
807     if ( ! good ) { return false; }               826     if ( ! good ) { return false; }
808   }                                               827   }
809                                                   828     
810   // The quadrangular sides                       829   // The quadrangular sides
811   //                                              830   //
812   for ( G4int iz = 0; iz < (G4int)fNz-1; ++iz  << 831   for ( G4int iz = 0; iz < fNz-1; ++iz ) 
813   {                                               832   {
814     for ( G4int i = 0; i < (G4int)fNv; ++i )   << 833     for ( G4int i = 0; i < fNv; ++i )
815     {                                             834     {
816       G4int j = (i+1) % fNv;                      835       G4int j = (i+1) % fNv;
817       good = AddFacet( new G4QuadrangularFacet    836       good = AddFacet( new G4QuadrangularFacet
818                         ( GetVertex(iz, j), Ge    837                         ( GetVertex(iz, j), GetVertex(iz, i), 
819                           GetVertex(iz+1, i),     838                           GetVertex(iz+1, i), GetVertex(iz+1, j), ABSOLUTE) );
820       if ( ! good ) { return false; }             839       if ( ! good ) { return false; }
821     }                                             840     }
822   }                                               841   }  
823                                                   842 
824   SetSolidClosed(true);                           843   SetSolidClosed(true);
825                                                   844 
826   return good;                                    845   return good;
827 }                                                 846 }
828                                                   847 
829 //____________________________________________    848 //_____________________________________________________________________________
830                                                   849 
831 G4GeometryType G4ExtrudedSolid::GetEntityType     850 G4GeometryType G4ExtrudedSolid::GetEntityType () const
832 {                                                 851 {
833   // Return entity type                           852   // Return entity type
834                                                   853 
835   return fGeometryType;                           854   return fGeometryType;
836 }                                                 855 }
837                                                   856 
838 //____________________________________________    857 //_____________________________________________________________________________
839                                                   858 
840 G4bool G4ExtrudedSolid::IsFaceted () const     << 
841 {                                              << 
842   return true;                                 << 
843 }                                              << 
844                                                << 
845 //____________________________________________ << 
846                                                << 
847 G4VSolid* G4ExtrudedSolid::Clone() const          859 G4VSolid* G4ExtrudedSolid::Clone() const
848 {                                                 860 {
849   return new G4ExtrudedSolid(*this);              861   return new G4ExtrudedSolid(*this);
850 }                                                 862 }
851                                                   863 
852 //____________________________________________    864 //_____________________________________________________________________________
853                                                   865 
854 EInside G4ExtrudedSolid::Inside(const G4ThreeV    866 EInside G4ExtrudedSolid::Inside(const G4ThreeVector &p) const
855 {                                                 867 {
856   switch (fSolidType)                             868   switch (fSolidType)
857   {                                               869   {
858     case 1: // convex right prism                 870     case 1: // convex right prism
859     {                                             871     {
860       G4double dist = std::max(fZSections[0].f    872       G4double dist = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
861       if (dist > kCarToleranceHalf)  { return     873       if (dist > kCarToleranceHalf)  { return kOutside; }
862                                                   874 
863       std::size_t np = fPlanes.size();         << 875       G4int np = fPlanes.size();
864       for (std::size_t i=0; i<np; ++i)         << 876       for (G4int i=0; i<np; ++i)
865       {                                           877       {
866         G4double dd = fPlanes[i].a*p.x() + fPl    878         G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
867         if (dd > dist)  { dist = dd; }            879         if (dd > dist)  { dist = dd; }
868       }                                           880       }
869       if (dist > kCarToleranceHalf)  { return     881       if (dist > kCarToleranceHalf)  { return kOutside; }
870       return (dist > -kCarToleranceHalf) ? kSu    882       return (dist > -kCarToleranceHalf) ? kSurface : kInside;
871     }                                             883     }
872     case 2: // non-convex right prism             884     case 2: // non-convex right prism
873     {                                             885     {
874       G4double distz = std::max(fZSections[0].    886       G4double distz = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
875       if (distz > kCarToleranceHalf)  { return    887       if (distz > kCarToleranceHalf)  { return kOutside; }
876                                                   888 
877       G4bool in = PointInPolygon(p);              889       G4bool in = PointInPolygon(p);
878       if (distz > -kCarToleranceHalf && in) {     890       if (distz > -kCarToleranceHalf && in) { return kSurface; }
879                                                   891 
880       G4double dd = DistanceToPolygonSqr(p) -     892       G4double dd = DistanceToPolygonSqr(p) - kCarToleranceHalf*kCarToleranceHalf;
881       if (in)                                     893       if (in)
882       {                                           894       {
883         return (dd >= 0) ? kInside : kSurface;    895         return (dd >= 0) ? kInside : kSurface;
884       }                                           896       }
885       else                                        897       else
886       {                                           898       {
887         return (dd > 0) ? kOutside : kSurface;    899         return (dd > 0) ? kOutside : kSurface;
888       }                                           900       }
889     }                                             901     }
890   }                                               902   }
891                                                   903 
892   // Override the base class function  as it f    904   // Override the base class function  as it fails in case of concave polygon.
893   // Project the point in the original polygon    905   // Project the point in the original polygon scale and check if it is inside
894   // for each triangle.                           906   // for each triangle.
895                                                   907 
896   // Check first if outside extent                908   // Check first if outside extent
897   //                                              909   //
898   if ( p.x() < GetMinXExtent() - kCarTolerance    910   if ( p.x() < GetMinXExtent() - kCarToleranceHalf ||
899        p.x() > GetMaxXExtent() + kCarTolerance    911        p.x() > GetMaxXExtent() + kCarToleranceHalf ||
900        p.y() < GetMinYExtent() - kCarTolerance    912        p.y() < GetMinYExtent() - kCarToleranceHalf ||
901        p.y() > GetMaxYExtent() + kCarTolerance    913        p.y() > GetMaxYExtent() + kCarToleranceHalf ||
902        p.z() < GetMinZExtent() - kCarTolerance    914        p.z() < GetMinZExtent() - kCarToleranceHalf ||
903        p.z() > GetMaxZExtent() + kCarTolerance    915        p.z() > GetMaxZExtent() + kCarToleranceHalf )
904   {                                               916   {
905     // G4cout << "G4ExtrudedSolid::Outside ext    917     // G4cout << "G4ExtrudedSolid::Outside extent: " << p << G4endl;
906     return kOutside;                              918     return kOutside;
907   }                                               919   }
908                                                   920 
909   // Project point p(z) to the polygon scale p    921   // Project point p(z) to the polygon scale p0
910   //                                              922   //
911   G4TwoVector pscaled = ProjectPoint(p);          923   G4TwoVector pscaled = ProjectPoint(p);
912                                                   924   
913   // Check if on surface of polygon               925   // Check if on surface of polygon
914   //                                              926   //
915   for ( G4int i=0; i<(G4int)fNv; ++i )         << 927   for ( G4int i=0; i<fNv; ++i )
916   {                                               928   {
917     G4int j = (i+1) % fNv;                        929     G4int j = (i+1) % fNv;
918     if ( IsSameLineSegment(pscaled, fPolygon[i    930     if ( IsSameLineSegment(pscaled, fPolygon[i], fPolygon[j]) )
919     {                                             931     {
920       // G4cout << "G4ExtrudedSolid::Inside re    932       // G4cout << "G4ExtrudedSolid::Inside return Surface (on polygon) "
921       //        << G4endl;                        933       //        << G4endl;
922                                                   934 
923       return kSurface;                            935       return kSurface;
924     }                                             936     }
925   }                                               937   }
926                                                   938 
927   // Now check if inside triangles                939   // Now check if inside triangles
928   //                                              940   //
929   auto it = fTriangles.cbegin();               << 941   std::vector< std::vector<G4int> >::const_iterator it = fTriangles.begin();
930   G4bool inside = false;                          942   G4bool inside = false;
931   do    // Loop checking, 13.08.2015, G.Cosmo     943   do    // Loop checking, 13.08.2015, G.Cosmo
932   {                                               944   {
933     if ( IsPointInside(fPolygon[(*it)[0]], fPo    945     if ( IsPointInside(fPolygon[(*it)[0]], fPolygon[(*it)[1]],
934                        fPolygon[(*it)[2]], psc    946                        fPolygon[(*it)[2]], pscaled) )  { inside = true; }
935     ++it;                                         947     ++it;
936   } while ( (!inside) && (it != fTriangles.cen << 948   } while ( (inside == false) && (it != fTriangles.end()) );
937                                                   949 
938   if ( inside )                                   950   if ( inside )
939   {                                               951   {
940     // Check if on surface of z sides             952     // Check if on surface of z sides
941     //                                            953     //
942     if ( std::fabs( p.z() - fZSections[0].fZ )    954     if ( std::fabs( p.z() - fZSections[0].fZ ) < kCarToleranceHalf ||
943          std::fabs( p.z() - fZSections[fNz-1].    955          std::fabs( p.z() - fZSections[fNz-1].fZ ) < kCarToleranceHalf )
944     {                                             956     {
945       // G4cout << "G4ExtrudedSolid::Inside re    957       // G4cout << "G4ExtrudedSolid::Inside return Surface (on z side)"
946       //        << G4endl;                        958       //        << G4endl;
947                                                   959 
948       return kSurface;                            960       return kSurface;
949     }                                             961     }
950                                                   962 
951     // G4cout << "G4ExtrudedSolid::Inside retu    963     // G4cout << "G4ExtrudedSolid::Inside return Inside" << G4endl;
952                                                   964 
953     return kInside;                               965     return kInside;
954   }                                               966   }
955                                                   967 
956   // G4cout << "G4ExtrudedSolid::Inside return    968   // G4cout << "G4ExtrudedSolid::Inside return Outside " << G4endl;
957                                                   969 
958   return kOutside;                                970   return kOutside;
959 }                                                 971 }
960                                                   972 
961 //____________________________________________    973 //_____________________________________________________________________________
962                                                   974 
963 G4ThreeVector G4ExtrudedSolid::SurfaceNormal(c    975 G4ThreeVector G4ExtrudedSolid::SurfaceNormal(const G4ThreeVector& p) const
964 {                                                 976 {
965   G4int nsurf = 0;                                977   G4int nsurf = 0;
966   G4double nx = 0., ny = 0., nz = 0.;          << 978   G4double nx = 0, ny = 0, nz = 0;
967   switch (fSolidType)                             979   switch (fSolidType)
968   {                                               980   {
969     case 1: // convex right prism                 981     case 1: // convex right prism
970     {                                             982     {
971       if (std::abs(p.z() - fZSections[0].fZ) < << 983       if (std::abs(p.z() - fZSections[0].fZ) <= kCarToleranceHalf)  { nz = -1; ++nsurf; }
972       {                                        << 984       if (std::abs(p.z() - fZSections[1].fZ) <= kCarToleranceHalf)  { nz =  1; ++nsurf; }
973         nz = -1; ++nsurf;                      << 985       for (G4int i=0; i<fNv; ++i)
974       }                                        << 
975       if (std::abs(p.z() - fZSections[1].fZ) < << 
976       {                                        << 
977         nz =  1; ++nsurf;                      << 
978       }                                        << 
979       for (std::size_t i=0; i<fNv; ++i)        << 
980       {                                           986       {
981         G4double dd = fPlanes[i].a*p.x() + fPl    987         G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
982         if (std::abs(dd) > kCarToleranceHalf)     988         if (std::abs(dd) > kCarToleranceHalf) continue;
983         nx += fPlanes[i].a;                       989         nx += fPlanes[i].a;
984         ny += fPlanes[i].b;                       990         ny += fPlanes[i].b;
985         ++nsurf;                                  991         ++nsurf;
986       }                                           992       }
987       break;                                      993       break;
988     }                                             994     }
989     case 2: // non-convex right prism             995     case 2: // non-convex right prism
990     {                                             996     {
991       if (std::abs(p.z() - fZSections[0].fZ) < << 997       if (std::abs(p.z() - fZSections[0].fZ) <= kCarToleranceHalf)  { nz = -1; ++nsurf; }
992       {                                        << 998       if (std::abs(p.z() - fZSections[1].fZ) <= kCarToleranceHalf)  { nz =  1; ++nsurf; }
993         nz = -1; ++nsurf;                      << 
994       }                                        << 
995       if (std::abs(p.z() - fZSections[1].fZ) < << 
996       {                                        << 
997         nz =  1; ++nsurf;                      << 
998       }                                        << 
999                                                   999 
1000       G4double sqrCarToleranceHalf = kCarTole    1000       G4double sqrCarToleranceHalf = kCarToleranceHalf*kCarToleranceHalf;
1001       for (std::size_t i=0, k=fNv-1; i<fNv; k << 1001       for (G4int i=0, k=fNv-1; i<fNv; k=i++)
1002       {                                          1002       {
1003         G4double ix = p.x() - fPolygon[i].x()    1003         G4double ix = p.x() - fPolygon[i].x();
1004         G4double iy = p.y() - fPolygon[i].y()    1004         G4double iy = p.y() - fPolygon[i].y();
1005         G4double u  = fPlanes[i].a*iy - fPlan    1005         G4double u  = fPlanes[i].a*iy - fPlanes[i].b*ix;
1006         if (u < 0)                               1006         if (u < 0)
1007         {                                        1007         {
1008           if (ix*ix + iy*iy > sqrCarTolerance    1008           if (ix*ix + iy*iy > sqrCarToleranceHalf) continue;
1009         }                                        1009         }
1010         else if (u > fLengths[i])                1010         else if (u > fLengths[i])
1011         {                                        1011         {
1012           G4double kx = p.x() - fPolygon[k].x    1012           G4double kx = p.x() - fPolygon[k].x();
1013           G4double ky = p.y() - fPolygon[k].y    1013           G4double ky = p.y() - fPolygon[k].y();
1014           if (kx*kx + ky*ky > sqrCarTolerance    1014           if (kx*kx + ky*ky > sqrCarToleranceHalf) continue;
1015         }                                        1015         }
1016         else                                     1016         else
1017         {                                        1017         {
1018           G4double dd = fPlanes[i].a*p.x() +     1018           G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
1019           if (dd*dd > sqrCarToleranceHalf) co    1019           if (dd*dd > sqrCarToleranceHalf) continue;
1020         }                                        1020         }
1021         nx += fPlanes[i].a;                      1021         nx += fPlanes[i].a;
1022         ny += fPlanes[i].b;                      1022         ny += fPlanes[i].b;
1023         ++nsurf;                                 1023         ++nsurf;
1024       }                                          1024       }
1025       break;                                     1025       break;
1026     }                                            1026     }
1027     default:                                     1027     default:
1028     {                                            1028     {
1029       return G4TessellatedSolid::SurfaceNorma    1029       return G4TessellatedSolid::SurfaceNormal(p);
1030     }                                            1030     }
1031   }                                              1031   }
1032                                                  1032 
1033   // Return normal (right prism)                 1033   // Return normal (right prism)
1034   //                                             1034   //
1035   if (nsurf == 1)                                1035   if (nsurf == 1)
1036   {                                              1036   {
1037     return { nx,ny,nz };                      << 1037     return G4ThreeVector(nx,ny,nz);
1038   }                                              1038   }
1039   else if (nsurf != 0) // edge or corner         1039   else if (nsurf != 0) // edge or corner
1040   {                                              1040   {
1041     return G4ThreeVector(nx,ny,nz).unit();       1041     return G4ThreeVector(nx,ny,nz).unit();
1042   }                                              1042   }
1043   else                                           1043   else
1044   {                                              1044   {
1045     // Point is not on the surface, compute a    1045     // Point is not on the surface, compute approximate normal
1046     //                                           1046     //
1047 #ifdef G4CSGDEBUG                                1047 #ifdef G4CSGDEBUG
1048     std::ostringstream message;                  1048     std::ostringstream message;
1049     G4long oldprc = message.precision(16);    << 1049     G4int oldprc = message.precision(16);
1050     message << "Point p is not on surface (!?    1050     message << "Point p is not on surface (!?) of solid: "
1051             << GetName() << G4endl;              1051             << GetName() << G4endl;
1052     message << "Position:\n";                    1052     message << "Position:\n";
1053     message << "   p.x() = " << p.x()/mm << "    1053     message << "   p.x() = " << p.x()/mm << " mm\n";
1054     message << "   p.y() = " << p.y()/mm << "    1054     message << "   p.y() = " << p.y()/mm << " mm\n";
1055     message << "   p.z() = " << p.z()/mm << "    1055     message << "   p.z() = " << p.z()/mm << " mm";
1056     G4cout.precision(oldprc) ;                   1056     G4cout.precision(oldprc) ;
1057     G4Exception("G4TesselatedSolid::SurfaceNo    1057     G4Exception("G4TesselatedSolid::SurfaceNormal(p)", "GeomSolids1002",
1058                 JustWarning, message );          1058                 JustWarning, message );
1059     DumpInfo();                                  1059     DumpInfo();
1060 #endif                                           1060 #endif
1061     return ApproxSurfaceNormal(p);               1061     return ApproxSurfaceNormal(p);
1062   }                                              1062   }
1063 }                                                1063 }
1064                                                  1064 
1065 //___________________________________________    1065 //_____________________________________________________________________________
1066                                                  1066 
1067 G4ThreeVector G4ExtrudedSolid::ApproxSurfaceN    1067 G4ThreeVector G4ExtrudedSolid::ApproxSurfaceNormal(const G4ThreeVector& p) const
1068 {                                                1068 {
1069   // This method is valid only for right pris    1069   // This method is valid only for right prisms and
1070   // normally should not be called               1070   // normally should not be called
1071                                                  1071 
1072   if (fSolidType == 1 || fSolidType == 2)        1072   if (fSolidType == 1 || fSolidType == 2)
1073   {                                              1073   {
1074     // Find distances to z-planes                1074     // Find distances to z-planes
1075     //                                           1075     //
1076     G4double dz0 = fZSections[0].fZ - p.z();     1076     G4double dz0 = fZSections[0].fZ - p.z();
1077     G4double dz1 = p.z() - fZSections[1].fZ;     1077     G4double dz1 = p.z() - fZSections[1].fZ;
1078     G4double ddz0 = dz0*dz0;                     1078     G4double ddz0 = dz0*dz0;
1079     G4double ddz1 = dz1*dz1;                     1079     G4double ddz1 = dz1*dz1;
1080                                                  1080 
1081     // Find nearest lateral side and distance    1081     // Find nearest lateral side and distance to it
1082     //                                           1082     //
1083     std::size_t iside = 0;                    << 1083     G4int iside = 0;
1084     G4double dd = DBL_MAX;                       1084     G4double dd = DBL_MAX;
1085     for (std::size_t i=0, k=fNv-1; i<fNv; k=i << 1085     for (G4int i=0, k=fNv-1; i<fNv; k=i++)
1086     {                                            1086     {
1087       G4double ix = p.x() - fPolygon[i].x();     1087       G4double ix = p.x() - fPolygon[i].x();
1088       G4double iy = p.y() - fPolygon[i].y();     1088       G4double iy = p.y() - fPolygon[i].y();
1089       G4double u  = fPlanes[i].a*iy - fPlanes    1089       G4double u  = fPlanes[i].a*iy - fPlanes[i].b*ix;
1090       if (u < 0)                                 1090       if (u < 0)
1091       {                                          1091       {
1092         G4double tmp = ix*ix + iy*iy;            1092         G4double tmp = ix*ix + iy*iy;
1093         if (tmp < dd) { dd = tmp; iside = i;     1093         if (tmp < dd) { dd = tmp; iside = i; }
1094       }                                          1094       }
1095       else if (u > fLengths[i])                  1095       else if (u > fLengths[i])
1096       {                                          1096       {
1097         G4double kx = p.x() - fPolygon[k].x()    1097         G4double kx = p.x() - fPolygon[k].x();
1098         G4double ky = p.y() - fPolygon[k].y()    1098         G4double ky = p.y() - fPolygon[k].y();
1099         G4double tmp = kx*kx + ky*ky;            1099         G4double tmp = kx*kx + ky*ky;
1100         if (tmp < dd)  { dd = tmp; iside = i;    1100         if (tmp < dd)  { dd = tmp; iside = i; }
1101       }                                          1101       }
1102       else                                       1102       else
1103       {                                          1103       {
1104         G4double tmp = fPlanes[i].a*p.x() + f    1104         G4double tmp = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
1105         tmp *= tmp;                              1105         tmp *= tmp;
1106         if (tmp < dd)  { dd = tmp; iside = i;    1106         if (tmp < dd)  { dd = tmp; iside = i; }
1107       }                                          1107       }
1108     }                                            1108     }
1109                                                  1109 
1110     // Find region                               1110     // Find region
1111     //                                           1111     //
1112     //  3  |   1   |  3                          1112     //  3  |   1   |  3
1113     // ----+-------+----                         1113     // ----+-------+----
1114     //  2  |   0   |  2                          1114     //  2  |   0   |  2
1115     // ----+-------+----                         1115     // ----+-------+----
1116     //  3  |   1   |  3                          1116     //  3  |   1   |  3
1117     //                                           1117     //
1118     G4int iregion = 0;                           1118     G4int iregion = 0;
1119     if (std::max(dz0,dz1) > 0) iregion = 1;      1119     if (std::max(dz0,dz1) > 0) iregion = 1;
1120                                                  1120 
1121     G4bool in = PointInPolygon(p);               1121     G4bool in = PointInPolygon(p);
1122     if (!in) iregion += 2;                       1122     if (!in) iregion += 2;
1123                                                  1123 
1124     // Return normal                             1124     // Return normal
1125     //                                           1125     //
1126     switch (iregion)                             1126     switch (iregion)
1127     {                                            1127     {
1128       case 0:                                    1128       case 0:
1129       {                                          1129       {
1130         if (ddz0 <= ddz1 && ddz0 <= dd) retur << 1130         if (ddz0 <= ddz1 && ddz0 <= dd) return G4ThreeVector(0, 0,-1);
1131         if (ddz1 <= ddz0 && ddz1 <= dd) retur << 1131         if (ddz1 <= ddz0 && ddz1 <= dd) return G4ThreeVector(0, 0, 1);
1132         return { fPlanes[iside].a, fPlanes[is << 1132         return G4ThreeVector(fPlanes[iside].a,fPlanes[iside].b, 0);
1133       }                                          1133       }
1134       case 1:                                    1134       case 1:
1135       {                                          1135       {
1136         return { 0, 0, (G4double)((dz0 > dz1) << 1136         return G4ThreeVector(0, 0, (dz0 > dz1) ? -1 : 1);
1137       }                                          1137       }
1138       case 2:                                    1138       case 2:
1139       {                                          1139       {
1140         return { fPlanes[iside].a, fPlanes[is << 1140         return G4ThreeVector(fPlanes[iside].a,fPlanes[iside].b, 0);
1141       }                                          1141       }
1142       case 3:                                    1142       case 3:
1143       {                                          1143       {
1144         G4double dzmax = std::max(dz0,dz1);      1144         G4double dzmax = std::max(dz0,dz1);
1145         if (dzmax*dzmax > dd) return { 0, 0,  << 1145         if (dzmax*dzmax > dd) return G4ThreeVector(0,0,(dz0 > dz1) ? -1 : 1);
1146         return { fPlanes[iside].a, fPlanes[is << 1146         return G4ThreeVector(fPlanes[iside].a,fPlanes[iside].b, 0);
1147       }                                          1147       }
1148     }                                            1148     }
1149   }                                              1149   }
1150   return {0,0,0};                             << 1150   return G4ThreeVector(0,0,0);
1151 }                                                1151 }
1152                                                  1152 
1153 //___________________________________________    1153 //_____________________________________________________________________________
1154                                                  1154 
1155 G4double G4ExtrudedSolid::DistanceToIn(const     1155 G4double G4ExtrudedSolid::DistanceToIn(const G4ThreeVector& p,
1156                                        const     1156                                        const G4ThreeVector& v) const
1157 {                                                1157 {
1158   G4double z0 = fZSections[0].fZ;                1158   G4double z0 = fZSections[0].fZ;
1159   G4double z1 = fZSections[fNz-1].fZ;            1159   G4double z1 = fZSections[fNz-1].fZ;
1160   if ((p.z() <= z0 + kCarToleranceHalf) && v.    1160   if ((p.z() <= z0 + kCarToleranceHalf) && v.z() <= 0) return kInfinity;
1161   if ((p.z() >= z1 - kCarToleranceHalf) && v.    1161   if ((p.z() >= z1 - kCarToleranceHalf) && v.z() >= 0) return kInfinity;
1162                                                  1162 
1163   switch (fSolidType)                            1163   switch (fSolidType)
1164   {                                              1164   {
1165     case 1: // convex right prism                1165     case 1: // convex right prism
1166     {                                            1166     {
1167       // Intersection with Z planes              1167       // Intersection with Z planes
1168       //                                         1168       //
1169       G4double dz = (z1 - z0)*0.5;               1169       G4double dz = (z1 - z0)*0.5;
1170       G4double pz = p.z() - dz - z0;             1170       G4double pz = p.z() - dz - z0;
1171                                                  1171 
1172       G4double invz = (v.z() == 0) ? DBL_MAX     1172       G4double invz = (v.z() == 0) ? DBL_MAX : -1./v.z();
1173       G4double ddz = (invz < 0) ? dz : -dz;      1173       G4double ddz = (invz < 0) ? dz : -dz;
1174       G4double tzmin = (pz + ddz)*invz;          1174       G4double tzmin = (pz + ddz)*invz;
1175       G4double tzmax = (pz - ddz)*invz;          1175       G4double tzmax = (pz - ddz)*invz;
1176                                                  1176 
1177       // Intersection with lateral planes        1177       // Intersection with lateral planes
1178       //                                         1178       //
1179       std::size_t np = fPlanes.size();        << 1179       G4int np = fPlanes.size();
1180       G4double txmin = tzmin, txmax = tzmax;     1180       G4double txmin = tzmin, txmax = tzmax;
1181       for (std::size_t i=0; i<np; ++i)        << 1181       for (G4int i=0; i<np; ++i)
1182       {                                          1182       { 
1183         G4double cosa = fPlanes[i].a*v.x()+fP    1183         G4double cosa = fPlanes[i].a*v.x()+fPlanes[i].b*v.y();
1184         G4double dist = fPlanes[i].a*p.x()+fP    1184         G4double dist = fPlanes[i].a*p.x()+fPlanes[i].b*p.y()+fPlanes[i].d;
1185         if (dist >= -kCarToleranceHalf)          1185         if (dist >= -kCarToleranceHalf)
1186         {                                        1186         {
1187           if (cosa >= 0)  { return kInfinity;    1187           if (cosa >= 0)  { return kInfinity; }
1188           G4double tmp  = -dist/cosa;            1188           G4double tmp  = -dist/cosa;
1189           if (txmin < tmp)  { txmin = tmp; }     1189           if (txmin < tmp)  { txmin = tmp; }
1190         }                                        1190         }
1191         else if (cosa > 0)                       1191         else if (cosa > 0)
1192         {                                        1192         {
1193           G4double tmp  = -dist/cosa;            1193           G4double tmp  = -dist/cosa;
1194           if (txmax > tmp)  { txmax = tmp; }     1194           if (txmax > tmp)  { txmax = tmp; }
1195         }                                        1195         } 
1196       }                                          1196       }
1197                                                  1197 
1198       // Find distance                           1198       // Find distance
1199       //                                         1199       //
1200       G4double tmin = txmin, tmax = txmax;       1200       G4double tmin = txmin, tmax = txmax;
1201       if (tmax <= tmin + kCarToleranceHalf)      1201       if (tmax <= tmin + kCarToleranceHalf)   // touch or no hit
1202       {                                          1202       {
1203         return kInfinity;                        1203         return kInfinity;
1204       }                                          1204       }
1205       return (tmin < kCarToleranceHalf) ? 0.     1205       return (tmin < kCarToleranceHalf) ? 0. : tmin;
1206     }                                            1206     }
1207     case 2: // non-convex right prism            1207     case 2: // non-convex right prism
1208     {                                            1208     {
1209     }                                            1209     }
1210   }                                              1210   }
1211   return G4TessellatedSolid::DistanceToIn(p,v    1211   return G4TessellatedSolid::DistanceToIn(p,v);
1212 }                                                1212 }
1213                                                  1213 
1214 //___________________________________________    1214 //_____________________________________________________________________________
1215                                                  1215 
1216 G4double G4ExtrudedSolid::DistanceToIn (const    1216 G4double G4ExtrudedSolid::DistanceToIn (const G4ThreeVector& p) const
1217 {                                                1217 {
1218   switch (fSolidType)                            1218   switch (fSolidType)
1219   {                                              1219   {
1220     case 1: // convex right prism                1220     case 1: // convex right prism
1221     {                                            1221     {
1222       G4double dist = std::max(fZSections[0].    1222       G4double dist = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
1223       std::size_t np = fPlanes.size();        << 1223       G4int np = fPlanes.size();
1224       for (std::size_t i=0; i<np; ++i)        << 1224       for (G4int i=0; i<np; ++i)
1225       {                                          1225       {
1226         G4double dd = fPlanes[i].a*p.x() + fP    1226         G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
1227         if (dd > dist) dist = dd;                1227         if (dd > dist) dist = dd;
1228       }                                          1228       }
1229       return (dist > 0) ? dist : 0.;             1229       return (dist > 0) ? dist : 0.;
1230     }                                            1230     }
1231     case 2: // non-convex right prism            1231     case 2: // non-convex right prism
1232     {                                            1232     {
1233       G4bool in = PointInPolygon(p);             1233       G4bool in = PointInPolygon(p);
1234       if (in)                                    1234       if (in)
1235       {                                          1235       {
1236         G4double distz= std::max(fZSections[0 << 1236         G4double distz = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
1237         return (distz > 0) ? distz : 0;          1237         return (distz > 0) ? distz : 0;
1238       }                                          1238       }
1239       else                                       1239       else
1240       {                                          1240       {
1241         G4double distz= std::max(fZSections[0 << 1241         G4double distz = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
1242         G4double dd = DistanceToPolygonSqr(p)    1242         G4double dd = DistanceToPolygonSqr(p);
1243         if (distz > 0) dd += distz*distz;        1243         if (distz > 0) dd += distz*distz;
1244         return std::sqrt(dd);                    1244         return std::sqrt(dd);
1245       }                                          1245       }
1246     }                                            1246     }
1247   }                                              1247   }
1248                                                  1248 
1249   // General case: use tessellated solid         1249   // General case: use tessellated solid
1250   return G4TessellatedSolid::DistanceToIn(p);    1250   return G4TessellatedSolid::DistanceToIn(p);
1251 }                                                1251 }
1252                                                  1252 
1253 //___________________________________________    1253 //_____________________________________________________________________________
1254                                                  1254 
1255 G4double G4ExtrudedSolid::DistanceToOut (cons    1255 G4double G4ExtrudedSolid::DistanceToOut (const G4ThreeVector &p,
1256                                          cons    1256                                          const G4ThreeVector &v,
1257                                          cons    1257                                          const G4bool calcNorm,
1258                                               << 1258                                                G4bool *validNorm,
1259                                               << 1259                                                G4ThreeVector *n) const
1260 {                                                1260 {
1261   G4bool getnorm = calcNorm;                     1261   G4bool getnorm = calcNorm;
1262   if (getnorm) *validNorm = true;                1262   if (getnorm) *validNorm = true;
1263                                                  1263 
1264   G4double z0 = fZSections[0].fZ;                1264   G4double z0 = fZSections[0].fZ;
1265   G4double z1 = fZSections[fNz-1].fZ;            1265   G4double z1 = fZSections[fNz-1].fZ;
1266   if ((p.z() <= z0 + kCarToleranceHalf) && v.    1266   if ((p.z() <= z0 + kCarToleranceHalf) && v.z() < 0)
1267   {                                              1267   {
1268     if (getnorm) n->set(0,0,-1);                 1268     if (getnorm) n->set(0,0,-1);
1269     return 0;                                    1269     return 0;
1270   }                                              1270   }
1271   if ((p.z() >= z1 - kCarToleranceHalf) && v.    1271   if ((p.z() >= z1 - kCarToleranceHalf) && v.z() > 0)
1272   {                                              1272   {
1273     if (getnorm) n->set(0,0,1);                  1273     if (getnorm) n->set(0,0,1);
1274     return 0;                                    1274     return 0;
1275   }                                              1275   }
1276                                                  1276 
1277   switch (fSolidType)                            1277   switch (fSolidType)
1278   {                                              1278   {
1279     case 1: // convex right prism                1279     case 1: // convex right prism
1280     {                                            1280     {
1281       // Intersection with Z planes              1281       // Intersection with Z planes
1282       //                                         1282       //
1283       G4double dz = (z1 - z0)*0.5;               1283       G4double dz = (z1 - z0)*0.5;
1284       G4double pz = p.z() - 0.5 * (z0 + z1);  << 1284       G4double pz = p.z() - z1 - z0;
1285                                                  1285 
1286       G4double vz = v.z();                       1286       G4double vz = v.z();
1287       G4double tmax = (vz == 0) ? DBL_MAX : (    1287       G4double tmax = (vz == 0) ? DBL_MAX : (std::copysign(dz,vz) - pz)/vz;
1288       G4int iside = (vz < 0) ? -4 : -2; // li    1288       G4int iside = (vz < 0) ? -4 : -2; // little trick: (-4+3)=-1, (-2+3)=+1
1289                                                  1289 
1290       // Intersection with lateral planes        1290       // Intersection with lateral planes
1291       //                                         1291       //
1292       std::size_t np = fPlanes.size();        << 1292       G4int np = fPlanes.size();
1293       for (std::size_t i=0; i<np; ++i)        << 1293       for (G4int i=0; i<np; ++i)
1294       {                                          1294       {
1295         G4double cosa = fPlanes[i].a*v.x()+fP    1295         G4double cosa = fPlanes[i].a*v.x()+fPlanes[i].b*v.y();
1296         if (cosa > 0)                            1296         if (cosa > 0)
1297         {                                        1297         {
1298           G4double dist = fPlanes[i].a*p.x()+    1298           G4double dist = fPlanes[i].a*p.x()+fPlanes[i].b*p.y()+fPlanes[i].d;
1299           if (dist >= -kCarToleranceHalf)        1299           if (dist >= -kCarToleranceHalf)
1300           {                                      1300           {
1301             if (getnorm) n->set(fPlanes[i].a,    1301             if (getnorm) n->set(fPlanes[i].a, fPlanes[i].b, fPlanes[i].c);
1302             return 0;                            1302             return 0;
1303           }                                      1303           }
1304           G4double tmp = -dist/cosa;             1304           G4double tmp = -dist/cosa;
1305           if (tmax > tmp) { tmax = tmp; iside << 1305           if (tmax > tmp) { tmax = tmp; iside = i; }
1306         }                                        1306         }
1307       }                                          1307       }
1308                                                  1308 
1309       // Set normal, if required, and return     1309       // Set normal, if required, and return distance
1310       //                                         1310       //
1311       if (getnorm)                               1311       if (getnorm)
1312       {                                          1312       {
1313         if (iside < 0)                           1313         if (iside < 0)
1314           { n->set(0, 0, iside + 3); } // (-4    1314           { n->set(0, 0, iside + 3); } // (-4+3)=-1, (-2+3)=+1
1315         else                                     1315         else
1316           { n->set(fPlanes[iside].a, fPlanes[    1316           { n->set(fPlanes[iside].a, fPlanes[iside].b, fPlanes[iside].c); }
1317       }                                          1317       }
1318       return tmax;                               1318       return tmax;
1319     }                                            1319     }
1320     case 2: // non-convex right prism            1320     case 2: // non-convex right prism
1321     {                                            1321     {
1322     }                                            1322     }
1323   }                                              1323   }
1324                                                  1324 
1325   // Override the base class function to rede    1325   // Override the base class function to redefine validNorm
1326   // (the solid can be concave)                  1326   // (the solid can be concave)
1327                                                  1327 
1328   G4double distOut =                             1328   G4double distOut =
1329     G4TessellatedSolid::DistanceToOut(p, v, c    1329     G4TessellatedSolid::DistanceToOut(p, v, calcNorm, validNorm, n);
1330   if (validNorm != nullptr) { *validNorm = fI << 1330   if (validNorm) { *validNorm = fIsConvex; }
1331                                                  1331 
1332   return distOut;                                1332   return distOut;
1333 }                                                1333 }
1334                                                  1334 
1335 //___________________________________________    1335 //_____________________________________________________________________________
1336                                                  1336 
1337 G4double G4ExtrudedSolid::DistanceToOut(const << 1337 G4double G4ExtrudedSolid::DistanceToOut(const G4ThreeVector &p) const
1338 {                                                1338 {
1339   switch (fSolidType)                            1339   switch (fSolidType)
1340   {                                              1340   {
1341     case 1: // convex right prism                1341     case 1: // convex right prism
1342     {                                            1342     {
1343       G4double dist = std::max(fZSections[0].    1343       G4double dist = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
1344       std::size_t np = fPlanes.size();        << 1344       G4int np = fPlanes.size();
1345       for (std::size_t i=0; i<np; ++i)        << 1345       for (G4int i=0; i<np; ++i)
1346       {                                          1346       {
1347         G4double dd = fPlanes[i].a*p.x() + fP    1347         G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
1348         if (dd > dist) dist = dd;                1348         if (dd > dist) dist = dd;
1349       }                                          1349       }
1350       return (dist < 0) ? -dist : 0.;            1350       return (dist < 0) ? -dist : 0.;
1351     }                                            1351     }
1352     case 2: // non-convex right prism            1352     case 2: // non-convex right prism
1353     {                                            1353     {
1354       G4double distz = std::max(fZSections[0]    1354       G4double distz = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
1355       G4bool in = PointInPolygon(p);             1355       G4bool in = PointInPolygon(p);
1356       if (distz >= 0 || (!in)) return 0; // p    1356       if (distz >= 0 || (!in)) return 0; // point is outside
1357       return std::min(-distz,std::sqrt(Distan    1357       return std::min(-distz,std::sqrt(DistanceToPolygonSqr(p)));
1358     }                                            1358     }
1359   }                                              1359   }
1360                                                  1360 
1361   // General case: use tessellated solid         1361   // General case: use tessellated solid
1362   return G4TessellatedSolid::DistanceToOut(p)    1362   return G4TessellatedSolid::DistanceToOut(p);
1363 }                                                1363 }
1364                                                  1364 
1365 //___________________________________________    1365 //_____________________________________________________________________________
1366 // Get bounding box                              1366 // Get bounding box
1367                                                  1367 
1368 void G4ExtrudedSolid::BoundingLimits(G4ThreeV    1368 void G4ExtrudedSolid::BoundingLimits(G4ThreeVector& pMin,
1369                                      G4ThreeV    1369                                      G4ThreeVector& pMax) const
1370 {                                                1370 {
1371   G4double xmin0 = kInfinity, xmax0 = -kInfin    1371   G4double xmin0 = kInfinity, xmax0 = -kInfinity;
1372   G4double ymin0 = kInfinity, ymax0 = -kInfin    1372   G4double ymin0 = kInfinity, ymax0 = -kInfinity;
1373                                                  1373 
1374   for (G4int i=0; i<GetNofVertices(); ++i)       1374   for (G4int i=0; i<GetNofVertices(); ++i)
1375   {                                              1375   {
1376     G4double x = fPolygon[i].x();                1376     G4double x = fPolygon[i].x();
1377     if (x < xmin0) xmin0 = x;                    1377     if (x < xmin0) xmin0 = x;
1378     if (x > xmax0) xmax0 = x;                    1378     if (x > xmax0) xmax0 = x;
1379     G4double y = fPolygon[i].y();                1379     G4double y = fPolygon[i].y();
1380     if (y < ymin0) ymin0 = y;                    1380     if (y < ymin0) ymin0 = y;
1381     if (y > ymax0) ymax0 = y;                    1381     if (y > ymax0) ymax0 = y;
1382   }                                              1382   }
1383                                                  1383 
1384   G4double xmin = kInfinity, xmax = -kInfinit    1384   G4double xmin = kInfinity, xmax = -kInfinity;
1385   G4double ymin = kInfinity, ymax = -kInfinit    1385   G4double ymin = kInfinity, ymax = -kInfinity;
1386                                                  1386 
1387   G4int nsect = GetNofZSections();               1387   G4int nsect = GetNofZSections();
1388   for (G4int i=0; i<nsect; ++i)                  1388   for (G4int i=0; i<nsect; ++i)
1389   {                                              1389   {
1390     ZSection zsect = GetZSection(i);             1390     ZSection zsect = GetZSection(i);
1391     G4double dx    = zsect.fOffset.x();          1391     G4double dx    = zsect.fOffset.x();
1392     G4double dy    = zsect.fOffset.y();          1392     G4double dy    = zsect.fOffset.y();
1393     G4double scale = zsect.fScale;               1393     G4double scale = zsect.fScale;
1394     xmin = std::min(xmin,xmin0*scale+dx);        1394     xmin = std::min(xmin,xmin0*scale+dx);
1395     xmax = std::max(xmax,xmax0*scale+dx);        1395     xmax = std::max(xmax,xmax0*scale+dx);
1396     ymin = std::min(ymin,ymin0*scale+dy);        1396     ymin = std::min(ymin,ymin0*scale+dy);
1397     ymax = std::max(ymax,ymax0*scale+dy);        1397     ymax = std::max(ymax,ymax0*scale+dy);
1398   }                                              1398   }
1399                                                  1399 
1400   G4double zmin = GetZSection(0).fZ;             1400   G4double zmin = GetZSection(0).fZ;
1401   G4double zmax = GetZSection(nsect-1).fZ;       1401   G4double zmax = GetZSection(nsect-1).fZ;
1402                                                  1402 
1403   pMin.set(xmin,ymin,zmin);                      1403   pMin.set(xmin,ymin,zmin);
1404   pMax.set(xmax,ymax,zmax);                      1404   pMax.set(xmax,ymax,zmax);
1405                                                  1405 
1406   // Check correctness of the bounding box       1406   // Check correctness of the bounding box
1407   //                                             1407   //
1408   if (pMin.x() >= pMax.x() || pMin.y() >= pMa    1408   if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
1409   {                                              1409   {
1410     std::ostringstream message;                  1410     std::ostringstream message;
1411     message << "Bad bounding box (min >= max)    1411     message << "Bad bounding box (min >= max) for solid: "
1412             << GetName() << " !"                 1412             << GetName() << " !"
1413             << "\npMin = " << pMin               1413             << "\npMin = " << pMin
1414             << "\npMax = " << pMax;              1414             << "\npMax = " << pMax;
1415     G4Exception("G4ExtrudedSolid::BoundingLim    1415     G4Exception("G4ExtrudedSolid::BoundingLimits()",
1416                 "GeomMgt0001", JustWarning, m    1416                 "GeomMgt0001", JustWarning, message);
1417     DumpInfo();                                  1417     DumpInfo();
1418   }                                              1418   }
1419 }                                                1419 }
1420                                                  1420 
1421 //___________________________________________    1421 //_____________________________________________________________________________
1422 // Calculate extent under transform and speci    1422 // Calculate extent under transform and specified limit
1423                                                  1423 
1424 G4bool                                           1424 G4bool
1425 G4ExtrudedSolid::CalculateExtent(const EAxis     1425 G4ExtrudedSolid::CalculateExtent(const EAxis pAxis,
1426                                  const G4Voxe    1426                                  const G4VoxelLimits& pVoxelLimit,
1427                                  const G4Affi    1427                                  const G4AffineTransform& pTransform,
1428                                        G4doub    1428                                        G4double& pMin, G4double& pMax) const
1429 {                                                1429 {
1430   G4ThreeVector bmin, bmax;                      1430   G4ThreeVector bmin, bmax;
1431   G4bool exist;                                  1431   G4bool exist;
1432                                                  1432 
1433   // Check bounding box (bbox)                   1433   // Check bounding box (bbox)
1434   //                                             1434   //
1435   BoundingLimits(bmin,bmax);                     1435   BoundingLimits(bmin,bmax);
1436   G4BoundingEnvelope bbox(bmin,bmax);            1436   G4BoundingEnvelope bbox(bmin,bmax);
1437 #ifdef G4BBOX_EXTENT                             1437 #ifdef G4BBOX_EXTENT
1438   return bbox.CalculateExtent(pAxis,pVoxelLim << 1438   if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
1439 #endif                                           1439 #endif
1440   if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVo    1440   if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
1441   {                                              1441   {
1442     return exist = pMin < pMax;               << 1442     return exist = (pMin < pMax) ? true : false;
1443   }                                              1443   }
1444                                                  1444 
1445   // To find the extent, the base polygon is     1445   // To find the extent, the base polygon is subdivided in triangles.
1446   // The extent is calculated as cumulative e    1446   // The extent is calculated as cumulative extent of the parts
1447   // formed by extrusion of the triangles        1447   // formed by extrusion of the triangles
1448   //                                             1448   //
1449   G4TwoVectorList triangles;                     1449   G4TwoVectorList triangles;
1450   G4double eminlim = pVoxelLimit.GetMinExtent    1450   G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
1451   G4double emaxlim = pVoxelLimit.GetMaxExtent    1451   G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
1452                                                  1452 
1453   // triangulate the base polygon                1453   // triangulate the base polygon
1454   if (!G4GeomTools::TriangulatePolygon(fPolyg    1454   if (!G4GeomTools::TriangulatePolygon(fPolygon,triangles))
1455   {                                              1455   {
1456     std::ostringstream message;                  1456     std::ostringstream message;
1457     message << "Triangulation of the base pol    1457     message << "Triangulation of the base polygon has failed for solid: "
1458             << GetName() << " !"                 1458             << GetName() << " !"
1459             << "\nExtent has been calculated     1459             << "\nExtent has been calculated using boundary box";
1460     G4Exception("G4ExtrudedSolid::CalculateEx    1460     G4Exception("G4ExtrudedSolid::CalculateExtent()",
1461                 "GeomMgt1002",JustWarning,mes    1461                 "GeomMgt1002",JustWarning,message);
1462     return bbox.CalculateExtent(pAxis,pVoxelL    1462     return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
1463   }                                              1463   }
1464                                                  1464 
1465   // allocate vector lists                       1465   // allocate vector lists
1466   G4int nsect = GetNofZSections();               1466   G4int nsect = GetNofZSections();
1467   std::vector<const G4ThreeVectorList *> poly    1467   std::vector<const G4ThreeVectorList *> polygons;
1468   polygons.resize(nsect);                        1468   polygons.resize(nsect);
1469   for (G4int k=0; k<nsect; ++k) { polygons[k]    1469   for (G4int k=0; k<nsect; ++k) { polygons[k] = new G4ThreeVectorList(3); }
1470                                                  1470 
1471   // main loop along triangles                   1471   // main loop along triangles
1472   pMin =  kInfinity;                             1472   pMin =  kInfinity;
1473   pMax = -kInfinity;                             1473   pMax = -kInfinity;
1474   G4int ntria = (G4int)triangles.size()/3;    << 1474   G4int ntria = triangles.size()/3;
1475   for (G4int i=0; i<ntria; ++i)                  1475   for (G4int i=0; i<ntria; ++i)
1476   {                                              1476   {
1477     G4int i3 = i*3;                              1477     G4int i3 = i*3;
1478     for (G4int k=0; k<nsect; ++k) // extrude     1478     for (G4int k=0; k<nsect; ++k) // extrude triangle
1479     {                                            1479     {
1480       ZSection zsect = GetZSection(k);           1480       ZSection zsect = GetZSection(k);
1481       G4double z     = zsect.fZ;                 1481       G4double z     = zsect.fZ;
1482       G4double dx    = zsect.fOffset.x();        1482       G4double dx    = zsect.fOffset.x();
1483       G4double dy    = zsect.fOffset.y();        1483       G4double dy    = zsect.fOffset.y();
1484       G4double scale = zsect.fScale;             1484       G4double scale = zsect.fScale;
1485                                                  1485 
1486       auto ptr = const_cast<G4ThreeVectorList << 1486       G4ThreeVectorList* ptr = const_cast<G4ThreeVectorList*>(polygons[k]);
1487       auto iter = ptr->begin();               << 1487       G4ThreeVectorList::iterator iter = ptr->begin();
1488       G4double x0 = triangles[i3+0].x()*scale    1488       G4double x0 = triangles[i3+0].x()*scale+dx;
1489       G4double y0 = triangles[i3+0].y()*scale    1489       G4double y0 = triangles[i3+0].y()*scale+dy;
1490       iter->set(x0,y0,z);                        1490       iter->set(x0,y0,z);
1491       iter++;                                    1491       iter++;
1492       G4double x1 = triangles[i3+1].x()*scale    1492       G4double x1 = triangles[i3+1].x()*scale+dx;
1493       G4double y1 = triangles[i3+1].y()*scale    1493       G4double y1 = triangles[i3+1].y()*scale+dy;
1494       iter->set(x1,y1,z);                        1494       iter->set(x1,y1,z);
1495       iter++;                                    1495       iter++;
1496       G4double x2 = triangles[i3+2].x()*scale    1496       G4double x2 = triangles[i3+2].x()*scale+dx;
1497       G4double y2 = triangles[i3+2].y()*scale    1497       G4double y2 = triangles[i3+2].y()*scale+dy;
1498       iter->set(x2,y2,z);                        1498       iter->set(x2,y2,z);
1499     }                                            1499     }
1500                                                  1500 
1501     // set sub-envelope and adjust extent        1501     // set sub-envelope and adjust extent
1502     G4double emin,emax;                          1502     G4double emin,emax;
1503     G4BoundingEnvelope benv(polygons);           1503     G4BoundingEnvelope benv(polygons);
1504     if (!benv.CalculateExtent(pAxis,pVoxelLim    1504     if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
1505     if (emin < pMin) pMin = emin;                1505     if (emin < pMin) pMin = emin;
1506     if (emax > pMax) pMax = emax;                1506     if (emax > pMax) pMax = emax;
1507     if (eminlim > pMin && emaxlim < pMax) bre    1507     if (eminlim > pMin && emaxlim < pMax) break; // max possible extent
1508   }                                              1508   }
1509   // free memory                                 1509   // free memory
1510   for (G4int k=0; k<nsect; ++k) { delete poly << 1510   for (G4int k=0; k<nsect; ++k) { delete polygons[k]; polygons[k]=0;}
1511   return (pMin < pMax);                          1511   return (pMin < pMax);
1512 }                                                1512 }
1513                                                  1513 
1514 //___________________________________________    1514 //_____________________________________________________________________________
1515                                                  1515 
1516 std::ostream& G4ExtrudedSolid::StreamInfo(std    1516 std::ostream& G4ExtrudedSolid::StreamInfo(std::ostream &os) const
1517 {                                                1517 {
1518   G4long oldprc = os.precision(16);           << 1518   G4int oldprc = os.precision(16);
1519   os << "------------------------------------    1519   os << "-----------------------------------------------------------\n"
1520      << "    *** Dump for solid - " << GetNam    1520      << "    *** Dump for solid - " << GetName() << " ***\n"
1521      << "    ================================    1521      << "    ===================================================\n"
1522      << " Solid geometry type: " << fGeometry    1522      << " Solid geometry type: " << fGeometryType  << G4endl;
1523                                                  1523 
1524   if ( fIsConvex)                                1524   if ( fIsConvex) 
1525     { os << " Convex polygon; list of vertice    1525     { os << " Convex polygon; list of vertices:" << G4endl; }
1526   else                                           1526   else  
1527     { os << " Concave polygon; list of vertic    1527     { os << " Concave polygon; list of vertices:" << G4endl; }
1528                                                  1528   
1529   for ( std::size_t i=0; i<fNv; ++i )         << 1529   for ( G4int i=0; i<fNv; ++i )
1530   {                                              1530   {
1531     os << std::setw(5) << "#" << i               1531     os << std::setw(5) << "#" << i 
1532        << "   vx = " << fPolygon[i].x()/mm <<    1532        << "   vx = " << fPolygon[i].x()/mm << " mm" 
1533        << "   vy = " << fPolygon[i].y()/mm <<    1533        << "   vy = " << fPolygon[i].y()/mm << " mm" << G4endl;
1534   }                                              1534   }
1535                                                  1535   
1536   os << " Sections:" << G4endl;                  1536   os << " Sections:" << G4endl;
1537   for ( std::size_t iz=0; iz<fNz; ++iz )      << 1537   for ( G4int iz=0; iz<fNz; ++iz ) 
1538   {                                              1538   {
1539     os << "   z = "   << fZSections[iz].fZ/mm    1539     os << "   z = "   << fZSections[iz].fZ/mm          << " mm  "
1540        << "  x0= "    << fZSections[iz].fOffs    1540        << "  x0= "    << fZSections[iz].fOffset.x()/mm << " mm  "
1541        << "  y0= "    << fZSections[iz].fOffs    1541        << "  y0= "    << fZSections[iz].fOffset.y()/mm << " mm  " 
1542        << "  scale= " << fZSections[iz].fScal    1542        << "  scale= " << fZSections[iz].fScale << G4endl;
1543   }                                              1543   }     
1544                                                  1544 
1545 /*                                               1545 /*
1546   // Triangles (for debugging)                   1546   // Triangles (for debugging)
1547   os << G4endl;                                  1547   os << G4endl; 
1548   os << " Triangles:" << G4endl;                 1548   os << " Triangles:" << G4endl;
1549   os << " Triangle #   vertex1   vertex2   ve    1549   os << " Triangle #   vertex1   vertex2   vertex3" << G4endl;
1550                                                  1550 
1551   G4int counter = 0;                             1551   G4int counter = 0;
1552   std::vector< std::vector<G4int> >::const_it    1552   std::vector< std::vector<G4int> >::const_iterator it;
1553   for ( it = fTriangles.begin(); it != fTrian    1553   for ( it = fTriangles.begin(); it != fTriangles.end(); it++ ) {
1554      std::vector<G4int> triangle = *it;          1554      std::vector<G4int> triangle = *it;
1555      os << std::setw(10) << counter++            1555      os << std::setw(10) << counter++ 
1556         << std::setw(10) << triangle[0] << st    1556         << std::setw(10) << triangle[0] << std::setw(10)  << triangle[1]
1557         << std::setw(10)  << triangle[2]         1557         << std::setw(10)  << triangle[2] 
1558         << G4endl;                               1558         << G4endl;
1559   }                                              1559   }          
1560 */                                               1560 */
1561   os.precision(oldprc);                          1561   os.precision(oldprc);
1562                                                  1562 
1563   return os;                                     1563   return os;
1564 }                                                1564 }  
1565                                                  1565 
1566 #endif                                           1566 #endif
1567                                                  1567