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 9.0.p1)


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