Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/solids/specific/src/G4GenericTrap.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/G4GenericTrap.cc (Version 11.3.0) and /geometry/solids/specific/src/G4GenericTrap.cc (Version 10.5.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 // G4GenericTrap implementation                <<  26 //
                                                   >>  27 //
                                                   >>  28 //
                                                   >>  29 // --------------------------------------------------------------------
                                                   >>  30 // GEANT 4 class source file
                                                   >>  31 //
                                                   >>  32 // G4GenericTrap.cc
 27 //                                                 33 //
 28 // Authors:                                        34 // Authors:
 29 //   Tatiana Nikitina, CERN; Ivana Hrivnacova,     35 //   Tatiana Nikitina, CERN; Ivana Hrivnacova, IPN Orsay
 30 //   Adapted from Root Arb8 implementation by  <<  36 //   Adapted from Root Arb8 implementation by Andrei Gheata, CERN 
 31 //                                                 37 //
 32 //   27.05.2024 - Evgueni Tcherniaev, complete <<  38 // History:
                                                   >>  39 // 04.08.2011 T.Nikitina - Added SetReferences() and InvertFacets()
                                                   >>  40 //            to CreatePolyhedron() for Visualisation of Boolean
                                                   >>  41 // 03.02.2016 E.Tcherniaev - Revised GetSurfaceArea() and GetCubicVolume(),
                                                   >>  42 //            rewritten GetFaceSurfaceArea(), added GetFaceCubicVolume()      
                                                   >>  43 // 25.09.2016 E.Tcherniaev - Use G4BoundingEnvelope for CalculateExtent(),
                                                   >>  44 //            removed CreateRotatedVertices()
 33 // -------------------------------------------     45 // --------------------------------------------------------------------
 34                                                    46 
 35 #include "G4GenericTrap.hh"                        47 #include "G4GenericTrap.hh"
 36                                                    48 
 37 #if !defined(G4GEOM_USE_UGENERICTRAP)              49 #if !defined(G4GEOM_USE_UGENERICTRAP)
 38                                                    50 
 39 #include <iomanip>                                 51 #include <iomanip>
 40                                                    52 
 41 #include "G4PhysicalConstants.hh"                  53 #include "G4PhysicalConstants.hh"
 42 #include "G4SystemOfUnits.hh"                      54 #include "G4SystemOfUnits.hh"
                                                   >>  55 #include "G4TessellatedSolid.hh"
                                                   >>  56 #include "G4TriangularFacet.hh"
                                                   >>  57 #include "G4QuadrangularFacet.hh"
 43 #include "G4VoxelLimits.hh"                        58 #include "G4VoxelLimits.hh"
 44 #include "G4AffineTransform.hh"                    59 #include "G4AffineTransform.hh"
 45 #include "G4BoundingEnvelope.hh"                   60 #include "G4BoundingEnvelope.hh"
 46 #include "G4QuickRand.hh"                      <<  61 #include "Randomize.hh"
 47                                                << 
 48 #include "G4GeomTools.hh"                      << 
 49                                                    62 
 50 #include "G4VGraphicsScene.hh"                     63 #include "G4VGraphicsScene.hh"
 51 #include "G4Polyhedron.hh"                         64 #include "G4Polyhedron.hh"
                                                   >>  65 #include "G4PolyhedronArbitrary.hh"
 52 #include "G4VisExtent.hh"                          66 #include "G4VisExtent.hh"
 53                                                    67 
 54 #include "G4AutoLock.hh"                           68 #include "G4AutoLock.hh"
 55                                                    69 
 56 namespace                                          70 namespace
 57 {                                                  71 {
 58   G4Mutex polyhedronMutex  = G4MUTEX_INITIALIZ <<  72   G4Mutex polyhedronMutex = G4MUTEX_INITIALIZER;
 59   G4Mutex lateralareaMutex = G4MUTEX_INITIALIZ << 
 60 }                                                  73 }
 61                                                    74 
 62 ////////////////////////////////////////////// <<  75 const G4int    G4GenericTrap::fgkNofVertices = 8;
 63 //                                             <<  76 const G4double G4GenericTrap::fgkTolerance = 1E-3;
 64 // Constructor                                 <<  77 
 65 //                                             <<  78 // --------------------------------------------------------------------
 66 G4GenericTrap::G4GenericTrap(const G4String& n <<  79 
 67                              const std::vector <<  80 G4GenericTrap::G4GenericTrap( const G4String& name, G4double halfZ,
 68   : G4VSolid(name)                             <<  81                               const std::vector<G4TwoVector>&  vertices )
 69 {                                              <<  82   : G4VSolid(name),
 70   halfTolerance = 0.5*kCarTolerance;           <<  83     fRebuildPolyhedron(false),
 71   CheckParameters(halfZ, vertices);            <<  84     fpPolyhedron(0),
 72   ComputeLateralSurfaces();                    <<  85     fDz(halfZ),
 73   ComputeBoundingBox();                        <<  86     fVertices(),
 74   ComputeScratchLength();                      <<  87     fIsTwisted(false),
                                                   >>  88     fTessellatedSolid(0),
                                                   >>  89     fMinBBoxVector(G4ThreeVector(0,0,0)),
                                                   >>  90     fMaxBBoxVector(G4ThreeVector(0,0,0)),
                                                   >>  91     fVisSubdivisions(0),
                                                   >>  92     fSurfaceArea(0.),
                                                   >>  93     fCubicVolume(0.)
                                                   >>  94    
                                                   >>  95 {
                                                   >>  96   // General constructor
                                                   >>  97   const G4double min_length=5*1.e-6;
                                                   >>  98   G4double length = 0.;
                                                   >>  99   G4int k=0;
                                                   >> 100   G4String errorDescription = "InvalidSetup in \" ";
                                                   >> 101   errorDescription += name;
                                                   >> 102   errorDescription += "\""; 
                                                   >> 103 
                                                   >> 104   halfCarTolerance = kCarTolerance*0.5;
                                                   >> 105 
                                                   >> 106   // Check vertices size
                                                   >> 107 
                                                   >> 108   if ( G4int(vertices.size()) != fgkNofVertices )
                                                   >> 109   {
                                                   >> 110     G4Exception("G4GenericTrap::G4GenericTrap()", "GeomSolids0002",
                                                   >> 111                 FatalErrorInArgument, "Number of vertices != 8");
                                                   >> 112   }            
                                                   >> 113   
                                                   >> 114   // Check dZ
                                                   >> 115   // 
                                                   >> 116   if (halfZ < kCarTolerance)
                                                   >> 117   {
                                                   >> 118      G4Exception("G4GenericTrap::G4GenericTrap()", "GeomSolids0002",
                                                   >> 119                 FatalErrorInArgument, "dZ is too small or negative");
                                                   >> 120   }           
                                                   >> 121  
                                                   >> 122   // Check Ordering and Copy vertices 
                                                   >> 123   //
                                                   >> 124   if(CheckOrder(vertices))
                                                   >> 125   {
                                                   >> 126     for (G4int i=0; i<fgkNofVertices; ++i) {fVertices.push_back(vertices[i]);}
                                                   >> 127   }
                                                   >> 128   else
                                                   >> 129   { 
                                                   >> 130     for (G4int i=0; i <4; ++i) {fVertices.push_back(vertices[3-i]);}
                                                   >> 131     for (G4int i=0; i <4; ++i) {fVertices.push_back(vertices[7-i]);}
                                                   >> 132   }
                                                   >> 133 
                                                   >> 134    // Check length of segments and Adjust
                                                   >> 135   // 
                                                   >> 136   for (G4int j=0; j < 2; j++)
                                                   >> 137   {
                                                   >> 138     for (G4int i=1; i<4; ++i)
                                                   >> 139     {
                                                   >> 140       k = j*4+i;
                                                   >> 141       length = (fVertices[k]-fVertices[k-1]).mag();
                                                   >> 142       if ( ( length < min_length) && ( length > kCarTolerance ) )
                                                   >> 143       {
                                                   >> 144         std::ostringstream message;
                                                   >> 145         message << "Length segment is too small." << G4endl
                                                   >> 146                 << "Distance between " << fVertices[k-1] << " and "
                                                   >> 147                 << fVertices[k] << " is only " << length << " mm !"; 
                                                   >> 148         G4Exception("G4GenericTrap::G4GenericTrap()", "GeomSolids1001",
                                                   >> 149                     JustWarning, message, "Vertices will be collapsed.");
                                                   >> 150         fVertices[k]=fVertices[k-1];
                                                   >> 151       }
                                                   >> 152     }
                                                   >> 153   }
                                                   >> 154 
                                                   >> 155   // Compute Twist
                                                   >> 156   //
                                                   >> 157   for( G4int i=0; i<4; i++) { fTwist[i]=0.; }
                                                   >> 158   fIsTwisted = ComputeIsTwisted();
                                                   >> 159 
                                                   >> 160   // Compute Bounding Box 
                                                   >> 161   //
                                                   >> 162   ComputeBBox();
                                                   >> 163   
                                                   >> 164   // If not twisted - create tessellated solid 
                                                   >> 165   // (an alternative implementation for testing)
                                                   >> 166   //
                                                   >> 167 #ifdef G4TESS_TEST
                                                   >> 168    if ( !fIsTwisted )  { fTessellatedSolid = CreateTessellatedSolid(); }
                                                   >> 169 #endif
 75 }                                                 170 }
 76                                                   171 
 77 ////////////////////////////////////////////// << 172 // --------------------------------------------------------------------
 78 //                                             << 173 
 79 // Fake default constructor - sets only member << 174 G4GenericTrap::G4GenericTrap( __void__& a )
 80 //                            for usage restri << 175   : G4VSolid(a),
 81 G4GenericTrap::G4GenericTrap(__void__& a)      << 176     fRebuildPolyhedron(false),
 82   : G4VSolid(a)                                << 177     fpPolyhedron(0),
                                                   >> 178     halfCarTolerance(0.),
                                                   >> 179     fDz(0.),
                                                   >> 180     fVertices(),
                                                   >> 181     fIsTwisted(false),
                                                   >> 182     fTessellatedSolid(0),
                                                   >> 183     fMinBBoxVector(G4ThreeVector(0,0,0)),
                                                   >> 184     fMaxBBoxVector(G4ThreeVector(0,0,0)),
                                                   >> 185     fVisSubdivisions(0),
                                                   >> 186     fSurfaceArea(0.),
                                                   >> 187     fCubicVolume(0.)
 83 {                                                 188 {
                                                   >> 189   // Fake default constructor - sets only member data and allocates memory
                                                   >> 190   //                            for usage restricted to object persistency.
 84 }                                                 191 }
 85                                                   192 
 86 ////////////////////////////////////////////// << 193 // --------------------------------------------------------------------
 87 //                                             << 
 88 // Destructor                                  << 
 89                                                   194 
 90 G4GenericTrap::~G4GenericTrap()                   195 G4GenericTrap::~G4GenericTrap()
 91 {                                                 196 {
                                                   >> 197   // Destructor
                                                   >> 198   delete fTessellatedSolid;
 92 }                                                 199 }
 93                                                   200 
 94 ////////////////////////////////////////////// << 201 // --------------------------------------------------------------------
 95 //                                             << 202 
 96 // Copy constructor                            << 
 97 //                                             << 
 98 G4GenericTrap::G4GenericTrap(const G4GenericTr    203 G4GenericTrap::G4GenericTrap(const G4GenericTrap& rhs)
 99   : G4VSolid(rhs),                                204   : G4VSolid(rhs),
100     halfTolerance(rhs.halfTolerance), fScratch << 205     fRebuildPolyhedron(false), fpPolyhedron(0),
101     fDz(rhs.fDz), fVertices(rhs.fVertices), fI << 206     halfCarTolerance(rhs.halfCarTolerance),
102     fMinBBox(rhs.fMinBBox), fMaxBBox(rhs.fMaxB << 207     fDz(rhs.fDz), fVertices(rhs.fVertices),
                                                   >> 208     fIsTwisted(rhs.fIsTwisted), fTessellatedSolid(0),
                                                   >> 209     fMinBBoxVector(rhs.fMinBBoxVector), fMaxBBoxVector(rhs.fMaxBBoxVector),
103     fVisSubdivisions(rhs.fVisSubdivisions),       210     fVisSubdivisions(rhs.fVisSubdivisions),
104     fSurfaceArea(rhs.fSurfaceArea), fCubicVolu << 211     fSurfaceArea(rhs.fSurfaceArea), fCubicVolume(rhs.fCubicVolume) 
105 {                                                 212 {
106   for (auto i = 0; i < 5; ++i) { fTwist[i] = r << 213    for (size_t i=0; i<4; ++i)  { fTwist[i] = rhs.fTwist[i]; }
107   for (auto i = 0; i < 4; ++i) { fDelta[i] = r << 214 #ifdef G4TESS_TEST
108   for (auto i = 0; i < 8; ++i) { fPlane[i] = r << 215    if (rhs.fTessellatedSolid && !fIsTwisted )
109   for (auto i = 0; i < 4; ++i) { fSurf[i] = rh << 216    { fTessellatedSolid = CreateTessellatedSolid(); } 
110   for (auto i = 0; i < 4; ++i) { fArea[i] = rh << 217 #endif
111 }                                                 218 }
112                                                   219 
113 ////////////////////////////////////////////// << 220 // --------------------------------------------------------------------
114 //                                             << 221 
115 // Assignment                                  << 222 G4GenericTrap& G4GenericTrap::operator = (const G4GenericTrap& rhs) 
116 //                                             << 
117 G4GenericTrap& G4GenericTrap::operator=(const  << 
118 {                                                 223 {
119   // Check assignment to self                  << 224    // Check assignment to self
120   if (this == &rhs)  { return *this; }         << 225    //
                                                   >> 226    if (this == &rhs)  { return *this; }
                                                   >> 227 
                                                   >> 228    // Copy base class data
                                                   >> 229    //
                                                   >> 230    G4VSolid::operator=(rhs);
                                                   >> 231 
                                                   >> 232    // Copy data
                                                   >> 233    //
                                                   >> 234    halfCarTolerance = rhs.halfCarTolerance;
                                                   >> 235    fDz = rhs.fDz; fVertices = rhs.fVertices;
                                                   >> 236    fIsTwisted = rhs.fIsTwisted; fTessellatedSolid = 0;
                                                   >> 237    fMinBBoxVector = rhs.fMinBBoxVector; fMaxBBoxVector = rhs.fMaxBBoxVector;
                                                   >> 238    fVisSubdivisions = rhs.fVisSubdivisions;
                                                   >> 239    fSurfaceArea = rhs.fSurfaceArea; fCubicVolume = rhs.fCubicVolume;
                                                   >> 240 
                                                   >> 241    for (size_t i=0; i<4; ++i)  { fTwist[i] = rhs.fTwist[i]; }
                                                   >> 242 #ifdef G4TESS_TEST
                                                   >> 243    if (rhs.fTessellatedSolid && !fIsTwisted )
                                                   >> 244    { delete fTessellatedSolid; fTessellatedSolid = CreateTessellatedSolid(); } 
                                                   >> 245 #endif
                                                   >> 246    fRebuildPolyhedron = false;
                                                   >> 247    delete fpPolyhedron; fpPolyhedron = 0;
121                                                   248 
122   // Copy base class data                      << 249    return *this;
123   G4VSolid::operator=(rhs);                    << 250 }
124                                                   251 
125   // Copy data                                 << 252 // --------------------------------------------------------------------
126   halfTolerance = rhs.halfTolerance; fScratch  << 
127   fDz = rhs.fDz; fVertices = rhs.fVertices; fI << 
128   fMinBBox = rhs.fMinBBox; fMaxBBox = rhs.fMax << 
129   fVisSubdivisions = rhs.fVisSubdivisions;     << 
130   fSurfaceArea = rhs.fSurfaceArea; fCubicVolum << 
131                                                   253 
132   for (auto i = 0; i < 8; ++i) { fVertices[i]  << 254 EInside
133   for (auto i = 0; i < 5; ++i) { fTwist[i] = r << 255 G4GenericTrap::InsidePolygone(const G4ThreeVector& p,
134   for (auto i = 0; i < 4; ++i) { fDelta[i] = r << 256                               const std::vector<G4TwoVector>& poly) const 
135   for (auto i = 0; i < 8; ++i) { fPlane[i] = r << 257 {
136   for (auto i = 0; i < 4; ++i) { fSurf[i] = rh << 258   EInside  in = kInside;
137   for (auto i = 0; i < 4; ++i) { fArea[i] = rh << 259   G4double cross, len2;
                                                   >> 260   G4int count=0;
138                                                   261 
139   fRebuildPolyhedron = false;                  << 262   for (G4int i = 0; i < 4; i++)
140   delete fpPolyhedron; fpPolyhedron = nullptr; << 263   {
                                                   >> 264     G4int j = (i+1) % 4;
141                                                   265 
142   return *this;                                << 266     cross = (p.x()-poly[i].x())*(poly[j].y()-poly[i].y())-
143 }                                              << 267             (p.y()-poly[i].y())*(poly[j].x()-poly[i].x());
144                                                   268 
145 ////////////////////////////////////////////// << 269     len2=(poly[i]-poly[j]).mag2();
146 //                                             << 270     if (len2 > kCarTolerance)
147 // Returns position of the point (inside/outsi << 271     {
148 //                                             << 272       if(cross*cross<=len2*halfCarTolerance*halfCarTolerance)  // Surface check
149 EInside G4GenericTrap::Inside(const G4ThreeVec << 273       {
150 {                                              << 274         G4double test;
151   G4double px = p.x(), py = p.y(), pz = p.z(); << 
152                                                   275 
153   // intersect edges by z = pz plane           << 276         // Check if p lies between the two extremes of the segment
154   G4TwoVector pp[4];                           << 277         //
155   G4double z = (pz + fDz);                     << 278         G4int iMax;
156   for (auto i = 0; i < 4; ++i) { pp[i] = fVert << 279         G4int iMin;
157                                                   280 
158   // estimate distance to the solid            << 281         if (poly[j].x() > poly[i].x())
159   G4double dist = std::abs(pz) - fDz;          << 282         {
160   for (auto i = 0; i < 4; ++i)                 << 283           iMax = j;
161   {                                            << 284           iMin = i;
162     if (fTwist[i] == 0.)                       << 285         }
163     {                                          << 286         else {
164       G4double dd = fSurf[i].D*px + fSurf[i].E << 287           iMax = i;
165       dist = std::max(dd, dist);               << 288           iMin = j;
                                                   >> 289         }
                                                   >> 290         if ( p.x() > poly[iMax].x()+halfCarTolerance
                                                   >> 291           || p.x() < poly[iMin].x()-halfCarTolerance )
                                                   >> 292         {
                                                   >> 293           return kOutside;
                                                   >> 294         }
                                                   >> 295 
                                                   >> 296         if (poly[j].y() > poly[i].y())
                                                   >> 297         {
                                                   >> 298           iMax = j;
                                                   >> 299           iMin = i;
                                                   >> 300         }
                                                   >> 301         else
                                                   >> 302         {
                                                   >> 303           iMax = i;
                                                   >> 304           iMin = j;
                                                   >> 305         }
                                                   >> 306         if ( p.y() > poly[iMax].y()+halfCarTolerance
                                                   >> 307           || p.y() < poly[iMin].y()-halfCarTolerance )
                                                   >> 308         {
                                                   >> 309           return kOutside;
                                                   >> 310         }
                                                   >> 311 
                                                   >> 312         if ( poly[iMax].x() != poly[iMin].x() )
                                                   >> 313         {
                                                   >> 314           test = (p.x()-poly[iMin].x())/(poly[iMax].x()-poly[iMin].x())
                                                   >> 315                * (poly[iMax].y()-poly[iMin].y())+poly[iMin].y();
                                                   >> 316         }
                                                   >> 317         else
                                                   >> 318         {
                                                   >> 319           test = p.y();
                                                   >> 320         }
                                                   >> 321 
                                                   >> 322         // Check if point is Inside Segment
                                                   >> 323         // 
                                                   >> 324         if( (test>=(poly[iMin].y()-halfCarTolerance))
                                                   >> 325          && (test<=(poly[iMax].y()+halfCarTolerance)) )
                                                   >> 326         { 
                                                   >> 327           return kSurface;
                                                   >> 328         }
                                                   >> 329         else
                                                   >> 330         {
                                                   >> 331           return kOutside;
                                                   >> 332         }
                                                   >> 333       }
                                                   >> 334       else if (cross<0.)  { return kOutside; }
166     }                                             335     }
167     else                                          336     else
168     {                                             337     {
169       auto j = (i + 1)%4;                      << 338       count++;
170       G4TwoVector a = pp[i];                   << 
171       G4TwoVector b = pp[j];                   << 
172       G4double dx = b.x() - a.x();             << 
173       G4double dy = b.y() - a.y();             << 
174       G4double leng = std::sqrt(dx*dx + dy*dy) << 
175       G4double dd = (dx*(py - a.y()) - dy*(px  << 
176       dist = std::max(dd, dist);               << 
177     }                                             339     }
178   }                                               340   }
179   return (dist > halfTolerance) ? kOutside :   << 341 
180     ((dist > -halfTolerance) ? kSurface : kIns << 342   // All collapsed vertices, Tet like
                                                   >> 343   //
                                                   >> 344   if(count==4)
                                                   >> 345   { 
                                                   >> 346     if ( (std::fabs(p.x()-poly[0].x())+std::fabs(p.y()-poly[0].y())) > halfCarTolerance )
                                                   >> 347     {
                                                   >> 348       in=kOutside;
                                                   >> 349     }
                                                   >> 350   }
                                                   >> 351   return in;
181 }                                                 352 }
182                                                   353 
183 ////////////////////////////////////////////// << 354 // --------------------------------------------------------------------
184 //                                             << 355 
185 // Return unit normal to surface at p          << 356 EInside G4GenericTrap::Inside(const G4ThreeVector& p) const
186 //                                             << 
187 G4ThreeVector G4GenericTrap::SurfaceNormal( co << 
188 {                                                 357 {
189   G4double halfToleranceSquared = halfToleranc << 358   // Test if point is inside this shape
190   G4double px = p.x(), py = p.y(), pz = p.z(); << 359 
191   G4double nx = 0, ny = 0, nz = 0;             << 360 #ifdef G4TESS_TEST
192                                                << 361    if ( fTessellatedSolid )
193   // intersect edges by z = pz plane           << 362    { 
194   G4TwoVector pp[4];                           << 363      return fTessellatedSolid->Inside(p);
195   G4double tz = (pz + fDz);                    << 364    }
196   for (auto i = 0; i < 4; ++i) { pp[i] = fVert << 365 #endif  
197                                                << 366 
198   // check bottom and top faces                << 367   EInside innew=kOutside;
199   G4double dz = std::abs(pz) - fDz;            << 368   std::vector<G4TwoVector> xy;
200   nz = std::copysign(G4double(std::abs(dz) <=  << 369  
201                                                << 370   if (std::fabs(p.z()) <= fDz+halfCarTolerance)  // First check Z range
202   // check lateral faces                       << 371   {
203   for (auto i = 0; i < 4; ++i)                 << 372     // Compute intersection between Z plane containing point and the shape
204   {                                            << 373     //
205     if (fTwist[i] == 0.)                       << 374     G4double cf = 0.5*(fDz-p.z())/fDz;
206     {                                          << 375     for (G4int i=0; i<4; i++)
207       G4double dd = fSurf[i].D*px + fSurf[i].E << 
208       if (std::abs(dd) <= halfTolerance)       << 
209       {                                        << 
210         nx += fSurf[i].D;                      << 
211         ny += fSurf[i].E;                      << 
212         nz += fSurf[i].F;                      << 
213       }                                        << 
214     }                                          << 
215     else                                       << 
216     {                                             376     {
217       auto j = (i + 1)%4;                      << 377       xy.push_back(fVertices[i+4]+cf*( fVertices[i]-fVertices[i+4]));
218       G4TwoVector a = pp[i];                   << 378     }
219       G4TwoVector b = pp[j];                   << 379 
220       G4double dx = b.x() - a.x();             << 380     innew=InsidePolygone(p,xy);
221       G4double dy = b.y() - a.y();             << 381 
222       G4double ll = dx*dx + dy*dy;             << 382     if( (innew==kInside) || (innew==kSurface) )
223       G4double dd = dx*(py - a.y()) - dy*(px - << 383     { 
224       if (dd*dd <= halfToleranceSquared*ll)    << 384       if(std::fabs(p.z()) > fDz-halfCarTolerance)  { innew=kSurface; }
225       {                                        << 
226         G4double x = fSurf[i].A*pz + fSurf[i]. << 
227         G4double y = fSurf[i].B*pz + fSurf[i]. << 
228         G4double z = fSurf[i].A*px + fSurf[i]. << 
229         G4double inv = 1./std::sqrt(x*x + y*y  << 
230         nx += x*inv;                           << 
231         ny += y*inv;                           << 
232         nz += z*inv;                           << 
233       }                                        << 
234     }                                             385     }
235   }                                               386   }
                                                   >> 387   return innew;    
                                                   >> 388 } 
236                                                   389 
237   // return normal                             << 390 // --------------------------------------------------------------------
238   G4double mag2 = nx*nx + ny*ny + nz*nz;       << 
239   if (mag2 == 0.) return ApproxSurfaceNormal(p << 
240   G4double mag = std::sqrt(mag2);              << 
241   G4double inv = (mag == 1.) ? 1. : 1./mag;    << 
242   return { nx*inv, ny*inv, nz*inv };           << 
243 }                                              << 
244                                                   391 
245 ////////////////////////////////////////////// << 392 G4ThreeVector G4GenericTrap::SurfaceNormal( const G4ThreeVector& p ) const
246 //                                             << 
247 // Find surface nearest to the point and retur << 
248 // Normally this method should not be called   << 
249 //                                             << 
250 G4ThreeVector G4GenericTrap::ApproxSurfaceNorm << 
251 {                                                 393 {
252 #ifdef G4SPECSDEBUG                            << 394   // Calculate side nearest to p, and return normal
253   std::ostringstream message;                  << 395   // If two sides are equidistant, sum of the Normal is returned
254   message.precision(16);                       << 396 
255   message << "Point p is not on surface of sol << 397 #ifdef G4TESS_TEST
256           << "Position: " << p << " is "       << 398   if ( fTessellatedSolid )
257           << ((Inside(p) == kInside) ? "inside << 399   {
258   StreamInfo(message);                         << 400     return fTessellatedSolid->SurfaceNormal(p);
259   G4Exception("G4GenericTrap::ApproxSurfaceNor << 401   }  
260               JustWarning, message );          << 402 #endif   
261 #endif                                         << 403  
262   G4double px = p.x(), py = p.y(), pz = p.z(); << 404   G4ThreeVector lnorm, sumnorm(0.,0.,0.), apprnorm(0.,0.,1.),
263   G4double dist = -DBL_MAX;                    << 405                 p0, p1, p2, r1, r2, r3, r4;
264   auto iside = 0;                              << 406   G4int noSurfaces = 0; 
265                                                << 407   G4double distxy,distz;
266   // intersect edges by z = pz plane           << 408   G4bool zPlusSide=false;
267   G4TwoVector pp[4];                           << 
268   G4double tz = (pz + fDz);                    << 
269   for (auto i = 0; i < 4; ++i) { pp[i] = fVert << 
270                                                   409 
271   // check lateral faces                       << 410   distz = fDz-std::fabs(p.z());
272   for (auto i = 0; i < 4; ++i)                 << 411   if (distz < halfCarTolerance)
273   {                                               412   {
274     if (fTwist[i] == 0.)                       << 413     if(p.z()>0)
275     {                                             414     {
276       G4double d = fSurf[i].D*px + fSurf[i].E* << 415       zPlusSide=true;
277       if (d > dist) { dist = d; iside = i; }   << 416       sumnorm=G4ThreeVector(0,0,1);
278     }                                             417     }
279     else                                          418     else
280     {                                             419     {
281       auto j = (i + 1)%4;                      << 420       sumnorm=G4ThreeVector(0,0,-1);
282       G4TwoVector a = pp[i];                   << 421     }
283       G4TwoVector b = pp[j];                   << 422     noSurfaces ++;
284       G4double dx = b.x() - a.x();             << 423   } 
285       G4double dy = b.y() - a.y();             << 
286       G4double leng = std::sqrt(dx*dx + dy*dy) << 
287       G4double d = (dx*(py - a.y()) - dy*(px - << 
288       if (d > dist) { dist = d; iside = i; }   << 
289     }                                          << 
290   }                                            << 
291   // check bottom and top faces                << 
292   G4double distz = std::abs(pz) - fDz;         << 
293   if (distz >= dist) return { 0., 0., std::cop << 
294                                                << 
295   G4double x = fSurf[iside].A*pz + fSurf[iside << 
296   G4double y = fSurf[iside].B*pz + fSurf[iside << 
297   G4double z = fSurf[iside].A*px + fSurf[iside << 
298   G4double inv = 1./std::sqrt(x*x + y*y + z*z) << 
299   return { x*inv, y*inv, z*inv };              << 
300 }                                              << 
301                                                   424 
302 ////////////////////////////////////////////// << 425   // Check lateral planes
303 //                                             << 426   //
304 // Compute distance to the surface from outsid << 427   std:: vector<G4TwoVector> vertices;  
305 // return kInfinity if no intersection         << 428   G4double cf = 0.5*(fDz-p.z())/fDz;
306 //                                             << 429   for (G4int i=0; i<4; i++)
307 G4double G4GenericTrap::DistanceToIn(const G4T << 430   {
308                                      const G4T << 431     vertices.push_back(fVertices[i+4]+cf*(fVertices[i]-fVertices[i+4]));
309 {                                              << 432   }
310   G4double px = p.x(), py = p.y(), pz = p.z(); << 
311   G4double vx = v.x(), vy = v.y(), vz = v.z(); << 
312                                                   433 
313   // Find intersections with the bounding poly << 434   // Compute distance for lateral planes
314   //                                              435   //
315   if (std::abs(pz) - fDz >= -halfTolerance &&  << 436   for (G4int q=0; q<4; q++)
316   G4double invz = (vz == 0) ? kInfinity : -1./ << 437   {
317   G4double dz = std::copysign(fDz,invz);       << 438     p0=G4ThreeVector(vertices[q].x(),vertices[q].y(),p.z());
318   G4double xin  = (pz - dz)*invz;              << 439     if(zPlusSide)
319   G4double xout = (pz + dz)*invz;              << 440     {
320                                                << 441       p1=G4ThreeVector(fVertices[q].x(),fVertices[q].y(),-fDz);
321   // Check plane faces                         << 
322   for (auto k = 0; k < 4; ++k)                 << 
323   {                                            << 
324     if (fTwist[k] != 0) continue; // skip twis << 
325     const G4GenericTrapPlane& surf = fPlane[2* << 
326     G4double cosa = surf.A*vx + surf.B*vy + su << 
327     G4double dist = surf.A*px + surf.B*py + su << 
328     if (dist >= -halfTolerance)                << 
329     {                                          << 
330       if (cosa >= 0.) { return kInfinity; } // << 
331       G4double tmp  = -dist/cosa;              << 
332       xin = std::max(tmp, xin);                << 
333     }                                             442     }
334     else                                          443     else
335     {                                             444     {
336       if (cosa > 0) { xout = std::min(-dist/co << 445       p1=G4ThreeVector(fVertices[q+4].x(),fVertices[q+4].y(),fDz); 
337       if (cosa < 0) { xin = std::max(-dist/cos << 
338     }                                             446     }
339   }                                            << 447     p2=G4ThreeVector(vertices[(q+1)%4].x(),vertices[(q+1)%4].y(),p.z());
340                                                   448 
341   // Check planes around twisted faces, each t << 449     // Collapsed vertices
342   G4double tin  = xin;                         << 450     //
343   G4double tout = xout;                        << 451     if ( (p2-p0).mag2() < kCarTolerance )
344   for (auto i = 0; i < 4; ++i)                 << 
345   {                                            << 
346     if (fTwist[i] == 0) continue; // skip plan << 
347                                                << 
348     // check intersection with 1st bounding pl << 
349     const G4GenericTrapPlane& surf1 = fPlane[2 << 
350     G4double cosa = surf1.A*vx + surf1.B*vy +  << 
351     G4double dist = surf1.A*px + surf1.B*py +  << 
352     if (dist >= -halfTolerance)                << 
353     {                                             452     {
354       if (cosa >= 0.) { return kInfinity; } // << 453       if ( std::fabs(p.z()+fDz) > kCarTolerance )
355       G4double tmp  = -dist/cosa;              << 454       {
356       tin = std::max(tmp, tin);                << 455         p2=G4ThreeVector(fVertices[(q+1)%4].x(),fVertices[(q+1)%4].y(),-fDz);
                                                   >> 456       }
                                                   >> 457       else
                                                   >> 458       {
                                                   >> 459         p2=G4ThreeVector(fVertices[(q+1)%4+4].x(),fVertices[(q+1)%4+4].y(),fDz);
                                                   >> 460       }
357     }                                             461     }
358     else                                       << 462     lnorm = (p1-p0).cross(p2-p0);
                                                   >> 463     lnorm = lnorm.unit();
                                                   >> 464     if(zPlusSide)  { lnorm=-lnorm; }
                                                   >> 465 
                                                   >> 466     // Adjust Normal for Twisted Surface
                                                   >> 467     //
                                                   >> 468     if ( (fIsTwisted) && (GetTwistAngle(q)!=0) )
                                                   >> 469     {
                                                   >> 470       G4double normP=(p2-p0).mag();
                                                   >> 471       if(normP)
                                                   >> 472       {
                                                   >> 473         G4double proj=(p-p0).dot(p2-p0)/normP;
                                                   >> 474         if(proj<0)     { proj=0; }
                                                   >> 475         if(proj>normP) { proj=normP; }
                                                   >> 476         G4int j=(q+1)%4;
                                                   >> 477         r1=G4ThreeVector(fVertices[q+4].x(),fVertices[q+4].y(),fDz);
                                                   >> 478         r2=G4ThreeVector(fVertices[j+4].x(),fVertices[j+4].y(),fDz);
                                                   >> 479         r3=G4ThreeVector(fVertices[q].x(),fVertices[q].y(),-fDz);
                                                   >> 480         r4=G4ThreeVector(fVertices[j].x(),fVertices[j].y(),-fDz);
                                                   >> 481         r1=r1+proj*(r2-r1)/normP;
                                                   >> 482         r3=r3+proj*(r4-r3)/normP;
                                                   >> 483         r2=r1-r3;
                                                   >> 484         r4=r2.cross(p2-p0); r4=r4.unit();
                                                   >> 485         lnorm=r4;
                                                   >> 486       }
                                                   >> 487     }   // End if fIsTwisted
                                                   >> 488 
                                                   >> 489     distxy=std::fabs((p0-p).dot(lnorm));
                                                   >> 490     if ( distxy<halfCarTolerance )
359     {                                             491     {
360       if (cosa > 0) { tout = std::min(-dist/co << 492       noSurfaces ++;
361       if (cosa < 0) { tin = std::max(-dist/cos << 493 
                                                   >> 494       // Negative sign for Normal is taken for Outside Normal
                                                   >> 495       //
                                                   >> 496       sumnorm=sumnorm+lnorm;
362     }                                             497     }
363                                                   498 
364     // check intersection with 2nd bounding pl << 499     // For ApproxSurfaceNormal
365     const G4GenericTrapPlane& surf2 = fPlane[2 << 500     //
366     cosa = surf2.A*vx + surf2.B*vy + surf2.C*v << 501     if (distxy<distz)
367     dist = surf2.A*px + surf2.B*py + surf2.C*p << 502     {
368     if (dist >= -halfTolerance)                << 503       distz=distxy;
369     {                                          << 504       apprnorm=lnorm;
370       if (cosa >= 0.) { return kInfinity; } // << 505     }      
371       G4double tmp  = -dist/cosa;              << 506   }  // End for loop
372       tin = std::max(tmp, tin);                << 507 
                                                   >> 508   // Calculate final Normal, add Normal in the Corners and Touching Sides
                                                   >> 509   //
                                                   >> 510   if ( noSurfaces == 0 )
                                                   >> 511   {
                                                   >> 512 #ifdef G4SPECSDEBUG
                                                   >> 513     G4Exception("G4GenericTrap::SurfaceNormal(p)", "GeomSolids1002",
                                                   >> 514                 JustWarning, "Point p is not on surface !?" );
                                                   >> 515 #endif
                                                   >> 516     sumnorm=apprnorm;
                                                   >> 517     // Add Approximative Surface Normal Calculation?
                                                   >> 518   }
                                                   >> 519   else if ( noSurfaces == 1 )  { ; }
                                                   >> 520   else                         { sumnorm = sumnorm.unit(); }
                                                   >> 521 
                                                   >> 522   return sumnorm ; 
                                                   >> 523 }    
                                                   >> 524 
                                                   >> 525 // --------------------------------------------------------------------
                                                   >> 526 
                                                   >> 527 G4ThreeVector G4GenericTrap::NormalToPlane( const G4ThreeVector& p,
                                                   >> 528                                             const G4int ipl ) const
                                                   >> 529 {
                                                   >> 530   // Return normal to given lateral plane ipl
                                                   >> 531 
                                                   >> 532 #ifdef G4TESS_TEST
                                                   >> 533   if ( fTessellatedSolid )
                                                   >> 534   { 
                                                   >> 535     return fTessellatedSolid->SurfaceNormal(p);
                                                   >> 536   }  
                                                   >> 537 #endif   
                                                   >> 538 
                                                   >> 539   G4ThreeVector lnorm, norm(0.,0.,0.), p0,p1,p2;
                                                   >> 540  
                                                   >> 541   G4double  distz = fDz-p.z();
                                                   >> 542   G4int i=ipl;  // current plane index
                                                   >> 543  
                                                   >> 544   G4TwoVector u,v;  
                                                   >> 545   G4ThreeVector r1,r2,r3,r4;
                                                   >> 546   G4double cf = 0.5*(fDz-p.z())/fDz;
                                                   >> 547   G4int j=(i+1)%4;
                                                   >> 548 
                                                   >> 549   u=fVertices[i+4]+cf*(fVertices[i]-fVertices[i+4]);
                                                   >> 550   v=fVertices[j+4]+cf*(fVertices[j]-fVertices[j+4]);
                                                   >> 551 
                                                   >> 552   // Compute cross product
                                                   >> 553   //
                                                   >> 554   p0=G4ThreeVector(u.x(),u.y(),p.z());
                                                   >> 555       
                                                   >> 556   if (std::fabs(distz)<halfCarTolerance)
                                                   >> 557   {
                                                   >> 558     p1=G4ThreeVector(fVertices[i].x(),fVertices[i].y(),-fDz);
                                                   >> 559     distz=-1;
                                                   >> 560   }
                                                   >> 561   else
                                                   >> 562   {
                                                   >> 563     p1=G4ThreeVector(fVertices[i+4].x(),fVertices[i+4].y(),fDz);
                                                   >> 564   }  
                                                   >> 565   p2=G4ThreeVector(v.x(),v.y(),p.z());
                                                   >> 566 
                                                   >> 567   // Collapsed vertices
                                                   >> 568   //
                                                   >> 569   if ( (p2-p0).mag2() < kCarTolerance )
                                                   >> 570   {
                                                   >> 571     if ( std::fabs(p.z()+fDz) > halfCarTolerance )
                                                   >> 572     {
                                                   >> 573       p2=G4ThreeVector(fVertices[j].x(),fVertices[j].y(),-fDz);
373     }                                             574     }
374     else                                          575     else
375     {                                             576     {
376       if (cosa > 0) { tout = std::min(-dist/co << 577       p2=G4ThreeVector(fVertices[j+4].x(),fVertices[j+4].y(),fDz);
377       if (cosa < 0) { tin = std::max(-dist/cos << 
378     }                                             578     }
379   }                                               579   }
380   if (tout - tin <= halfTolerance) { return kI << 580   lnorm=-(p1-p0).cross(p2-p0);
                                                   >> 581   if (distz>-halfCarTolerance)  { lnorm=-lnorm.unit(); }
                                                   >> 582   else                          { lnorm=lnorm.unit();  }
                                                   >> 583  
                                                   >> 584   // Adjust Normal for Twisted Surface
                                                   >> 585   //
                                                   >> 586   if( (fIsTwisted) && (GetTwistAngle(ipl)!=0) )
                                                   >> 587   {
                                                   >> 588     G4double normP=(p2-p0).mag();
                                                   >> 589     if(normP)
                                                   >> 590     {
                                                   >> 591       G4double proj=(p-p0).dot(p2-p0)/normP;
                                                   >> 592       if (proj<0)     { proj=0; }
                                                   >> 593       if (proj>normP) { proj=normP; }
                                                   >> 594 
                                                   >> 595       r1=G4ThreeVector(fVertices[i+4].x(),fVertices[i+4].y(),fDz);
                                                   >> 596       r2=G4ThreeVector(fVertices[j+4].x(),fVertices[j+4].y(),fDz);
                                                   >> 597       r3=G4ThreeVector(fVertices[i].x(),fVertices[i].y(),-fDz);
                                                   >> 598       r4=G4ThreeVector(fVertices[j].x(),fVertices[j].y(),-fDz);
                                                   >> 599       r1=r1+proj*(r2-r1)/normP;
                                                   >> 600       r3=r3+proj*(r4-r3)/normP;
                                                   >> 601       r2=r1-r3;
                                                   >> 602       r4=r2.cross(p2-p0);r4=r4.unit();
                                                   >> 603       lnorm=r4;
                                                   >> 604     }
                                                   >> 605   }  // End if fIsTwisted
381                                                   606 
382   // if point is outside of the bounding box   << 607   return lnorm;
383   // then move it to the surface of the boundi << 608 }    
384   G4double t0 = 0., x0 = px, y0 = py, z0 = pz; << 
385   if (x0 < fMinBBox.x() - halfTolerance ||     << 
386       y0 < fMinBBox.y() - halfTolerance ||     << 
387       z0 < fMinBBox.z() - halfTolerance ||     << 
388       x0 > fMaxBBox.x() + halfTolerance ||     << 
389       y0 > fMaxBBox.y() + halfTolerance ||     << 
390       z0 > fMaxBBox.z() + halfTolerance)       << 
391   {                                            << 
392     t0 = tin;                                  << 
393     x0 += vx*t0;                               << 
394     y0 += vy*t0;                               << 
395     z0 += vz*t0;                               << 
396    }                                           << 
397                                                   609 
398   // Check intersections with twisted faces    << 610 // --------------------------------------------------------------------
399   //                                           << 
400   G4double ttin[2] = { DBL_MAX, DBL_MAX };     << 
401   G4double ttout[2] = { tout, tout };          << 
402                                                   611 
403   if (tin - xin < halfTolerance) ttin[0] = xin << 612 G4double G4GenericTrap::DistToPlane(const G4ThreeVector& p,
404   if (xout - tout < halfTolerance) ttout[0] =  << 613                                     const G4ThreeVector& v,
405   G4double tminimal = tin - halfTolerance;     << 614                                     const G4int ipl) const 
406   G4double tmaximal = tout + halfTolerance;    << 615 {
407                                                << 616   // Computes distance to plane ipl :
408   constexpr G4double EPSILON = 1000.*DBL_EPSIL << 617   // ipl=0 : points 0,4,1,5
409   for (auto i = 0; i < 4; ++i)                 << 618   // ipl=1 : points 1,5,2,6
410   {                                            << 619   // ipl=2 : points 2,6,3,7
411     if (fTwist[i] == 0) continue; // skip plan << 620   // ipl=3 : points 3,7,0,4
412                                                << 621 
413     // twisted face, solve quadratic equation  << 622   G4double xa,xb,xc,xd,ya,yb,yc,yd;
414     G4double ABC  = fSurf[i].A*vx + fSurf[i].B << 623   
415     G4double ABCF = fSurf[i].A*x0 + fSurf[i].B << 624   G4int j = (ipl+1)%4;
416     G4double A = ABC*vz;                       << 625   
417     G4double B = 0.5*(fSurf[i].D*vx + fSurf[i] << 626   xa=fVertices[ipl].x();
418     G4double C = fSurf[i].D*x0 + fSurf[i].E*y0 << 627   ya=fVertices[ipl].y();
419     if (std::abs(A) <= EPSILON)                << 628   xb=fVertices[ipl+4].x();
420     {                                          << 629   yb=fVertices[ipl+4].y();
421       // case 1: track is parallel to the surf << 630   xc=fVertices[j].x();
422       if (std::abs(B) <= EPSILON)              << 631   yc=fVertices[j].y();
423       {                                        << 632   xd=fVertices[4+j].x();
424         // check position of the track relativ << 633   yd=fVertices[4+j].y();
425         // for the reason of precision it's be << 634  
426         auto j = (i + 1)%4;                    << 635   G4double dz2 =0.5/fDz;
427         G4double z = (z0 + fDz);               << 636   G4double tx1 =dz2*(xb-xa);
428         G4TwoVector a = fVertices[i] + fDelta[ << 637   G4double ty1 =dz2*(yb-ya);
429         G4TwoVector b = fVertices[j] + fDelta[ << 638   G4double tx2 =dz2*(xd-xc);
430         G4double dx = b.x() - a.x();           << 639   G4double ty2 =dz2*(yd-yc);
431         G4double dy = b.y() - a.y();           << 640   G4double dzp =fDz+p.z();
432         G4double leng = std::sqrt(dx*dx + dy*d << 641   G4double xs1 =xa+tx1*dzp;
433         G4double dist = dx*(y0 - a.y()) - dy*( << 642   G4double ys1 =ya+ty1*dzp;
434         if (dist >= -halfTolerance*leng) { ret << 643   G4double xs2 =xc+tx2*dzp;
435         continue;                              << 644   G4double ys2 =yc+ty2*dzp;
                                                   >> 645   G4double dxs =xs2-xs1;
                                                   >> 646   G4double dys =ys2-ys1;
                                                   >> 647   G4double dtx =tx2-tx1;
                                                   >> 648   G4double dty =ty2-ty1;
                                                   >> 649 
                                                   >> 650   G4double a = (dtx*v.y()-dty*v.x()+(tx1*ty2-tx2*ty1)*v.z())*v.z();
                                                   >> 651   G4double b = dxs*v.y()-dys*v.x()+(dtx*p.y()-dty*p.x()+ty2*xs1-ty1*xs2
                                                   >> 652              + tx1*ys2-tx2*ys1)*v.z();
                                                   >> 653   G4double c=dxs*p.y()-dys*p.x()+xs1*ys2-xs2*ys1;
                                                   >> 654   G4double q=kInfinity;
                                                   >> 655   G4double x1,x2,y1,y2,xp,yp,zi;
                                                   >> 656 
                                                   >> 657   if (std::fabs(a)<kCarTolerance)
                                                   >> 658   {           
                                                   >> 659     if (std::fabs(b)<kCarTolerance)  { return kInfinity; }
                                                   >> 660     q=-c/b;
                                                   >> 661 
                                                   >> 662     // Check if Point is on the Surface
                                                   >> 663 
                                                   >> 664     if (q>-halfCarTolerance)
                                                   >> 665     {
                                                   >> 666       if (q<halfCarTolerance)
                                                   >> 667       {
                                                   >> 668         if (NormalToPlane(p,ipl).dot(v)<=0)
                                                   >> 669           { if(Inside(p) != kOutside) { return 0.; } }
                                                   >> 670         else
                                                   >> 671           { return kInfinity; }
436       }                                           672       }
437                                                   673 
438       // case 2: single root                   << 674       // Check the Intersection
439       G4double tmp = t0 - 0.5*C/B;             << 675       //
440       // compute normal at the intersection po << 676       zi=p.z()+q*v.z();
441       G4double x = px + vx*tmp;                << 677       if (std::fabs(zi)<fDz)
442       G4double y = py + vy*tmp;                << 678       {
443       G4double z = pz + vz*tmp;                << 679         x1=xs1+tx1*v.z()*q;
444       const G4GenericTrapSurface& surf = fSurf << 680         x2=xs2+tx2*v.z()*q;
445       G4double nx = surf.A*z + surf.D;         << 681         xp=p.x()+q*v.x();
446       G4double ny = surf.B*z + surf.E;         << 682         y1=ys1+ty1*v.z()*q;
447       G4double nz = surf.A*x + surf.B*y + 2.*s << 683         y2=ys2+ty2*v.z()*q;
448                                                << 684         yp=p.y()+q*v.y();
449       if (nx*vx + ny*vy + nz*vz >= 0.) // poin << 685         zi = (xp-x1)*(xp-x2)+(yp-y1)*(yp-y2);
450       {                                        << 686         if (zi<=halfCarTolerance)  { return q; }
451         auto k = (i == 3) ? 0 : i + 1;         << 687       }
452         G4double tz = (pz + fDz);              << 688     }
453         G4TwoVector a = fVertices[i] + fDelta[ << 689     return kInfinity;
454         G4TwoVector b = fVertices[k] + fDelta[ << 690   }      
455         G4double dx = b.x() - a.x();           << 691   G4double d=b*b-4*a*c;
456         G4double dy = b.y() - a.y();           << 692   if (d>=0)
457         G4double leng = std::sqrt(dx*dx + dy*d << 693   {
458         G4double dist = dx*(py - a.y()) - dy*( << 694     if (a>0) { q=0.5*(-b-std::sqrt(d))/a; }
459         if (dist >= -halfTolerance*leng) { ret << 695     else     { q=0.5*(-b+std::sqrt(d))/a; }
460                                                << 696 
461         if (tmp < tminimal || tmp > tmaximal)  << 697     // Check if Point is on the Surface
462         if (std::abs(tmp - ttout[0]) < halfTol << 698     //
463         if (tmp < ttout[0])                    << 699     if (q>-halfCarTolerance)
                                                   >> 700     {
                                                   >> 701       if(q<halfCarTolerance)
                                                   >> 702       {
                                                   >> 703         if (NormalToPlane(p,ipl).dot(v)<=0)
464         {                                         704         {
465           ttout[1] = ttout[0];                 << 705           if(Inside(p)!= kOutside) { return 0.; }
466           ttout[0] = tmp;                      << 
467         }                                         706         }
468         else { ttout[1] = std::min(tmp, ttout[ << 707         else  // Check second root; return kInfinity
469       }                                        << 
470       else // point is flying to inside        << 
471       {                                        << 
472         if (tmp < tminimal || tmp > tmaximal)  << 
473         if (std::abs(tmp - ttin[0]) < halfTole << 
474         if (tmp < ttin[0])                     << 
475         {                                         708         {
476           ttin[1] = ttin[0];                   << 709           if (a>0) { q=0.5*(-b+std::sqrt(d))/a; }
477           ttin[0] = tmp;                       << 710           else     { q=0.5*(-b-std::sqrt(d))/a; }
                                                   >> 711           if (q<=halfCarTolerance) { return kInfinity; }
478         }                                         712         }
479         else { ttin[1] = std::min(tmp, ttin[1] << 
480       }                                           713       }
481       continue;                                << 714       // Check the Intersection
482     }                                          << 715       //
483                                                << 716       zi=p.z()+q*v.z();
484     // case 3: scratch or no intersection      << 717       if (std::fabs(zi)<fDz)
485     G4double D = B*B - A*C;                    << 718       {
486     if (D < 0.25*fScratch*fScratch*A*A)        << 719         x1=xs1+tx1*v.z()*q;
487     {                                          << 720         x2=xs2+tx2*v.z()*q;
488       if (A > 0) return kInfinity;             << 721         xp=p.x()+q*v.x();
489       continue;                                << 722         y1=ys1+ty1*v.z()*q;
                                                   >> 723         y2=ys2+ty2*v.z()*q;
                                                   >> 724         yp=p.y()+q*v.y();
                                                   >> 725         zi = (xp-x1)*(xp-x2)+(yp-y1)*(yp-y2);
                                                   >> 726         if (zi<=halfCarTolerance)  { return q; }
                                                   >> 727       }
490     }                                             728     }
                                                   >> 729     if (a>0)  { q=0.5*(-b+std::sqrt(d))/a; }
                                                   >> 730     else      { q=0.5*(-b-std::sqrt(d))/a; }
491                                                   731 
492     // case 4: two intersection points         << 732     // Check if Point is on the Surface
493     G4double tmp = -B - std::copysign(std::sqr << 733     //
494     G4double t1 = tmp/A + t0;                  << 734     if (q>-halfCarTolerance)
495     G4double t2 = C/tmp + t0;                  << 
496     G4double tsurfin = std::min(t1, t2);       << 
497     G4double tsurfout = std::max(t1, t2);      << 
498     if (A < 0) std::swap(tsurfin, tsurfout);   << 
499                                                << 
500     if (tsurfin >= tminimal && tsurfin <= tmax << 
501     {                                             735     {
502       if (std::abs(tsurfin - ttin[0]) >= halfT << 736       if(q<halfCarTolerance)
503       {                                           737       {
504         if (tsurfin < ttin[0])                 << 738         if (NormalToPlane(p,ipl).dot(v)<=0)
505         {                                         739         {
506           ttin[1] = ttin[0];                   << 740           if(Inside(p) != kOutside)  { return 0.; }
507           ttin[0] = tsurfin;                   << 
508         }                                         741         }
509         else { ttin[1] = std::min(tsurfin, tti << 742         else   // Check second root; return kInfinity.
                                                   >> 743         {
                                                   >> 744           if (a>0) { q=0.5*(-b-std::sqrt(d))/a; }
                                                   >> 745           else     { q=0.5*(-b+std::sqrt(d))/a; }
                                                   >> 746           if (q<=halfCarTolerance)  { return kInfinity; }
                                                   >> 747         }
                                                   >> 748       }
                                                   >> 749       // Check the Intersection
                                                   >> 750       //
                                                   >> 751       zi=p.z()+q*v.z();
                                                   >> 752       if (std::fabs(zi)<fDz)
                                                   >> 753       {
                                                   >> 754         x1=xs1+tx1*v.z()*q;
                                                   >> 755         x2=xs2+tx2*v.z()*q;
                                                   >> 756         xp=p.x()+q*v.x();
                                                   >> 757         y1=ys1+ty1*v.z()*q;
                                                   >> 758         y2=ys2+ty2*v.z()*q;
                                                   >> 759         yp=p.y()+q*v.y();
                                                   >> 760         zi = (xp-x1)*(xp-x2)+(yp-y1)*(yp-y2);
                                                   >> 761         if (zi<=halfCarTolerance)  { return q; }
510       }                                           762       }
511     }                                             763     }
512     if (tsurfout >= tminimal && tsurfout <= tm << 764   }
                                                   >> 765   return kInfinity;
                                                   >> 766 }      
                                                   >> 767 
                                                   >> 768 // --------------------------------------------------------------------
                                                   >> 769 
                                                   >> 770 G4double G4GenericTrap::DistanceToIn(const G4ThreeVector& p,
                                                   >> 771                                      const G4ThreeVector& v) const
                                                   >> 772 {
                                                   >> 773 #ifdef G4TESS_TEST
                                                   >> 774   if ( fTessellatedSolid )
                                                   >> 775   { 
                                                   >> 776     return fTessellatedSolid->DistanceToIn(p, v);
                                                   >> 777   }  
                                                   >> 778 #endif
                                                   >> 779     
                                                   >> 780   G4double dist[5];
                                                   >> 781   G4ThreeVector n;
                                                   >> 782 
                                                   >> 783   // Check lateral faces
                                                   >> 784   //
                                                   >> 785   G4int i;
                                                   >> 786   for (i=0; i<4; i++)
                                                   >> 787   {
                                                   >> 788     dist[i]=DistToPlane(p, v, i);  
                                                   >> 789   }
                                                   >> 790 
                                                   >> 791   // Check Z planes
                                                   >> 792   //
                                                   >> 793   dist[4]=kInfinity;
                                                   >> 794   if (std::fabs(p.z())>fDz-halfCarTolerance)
                                                   >> 795   {
                                                   >> 796     if (v.z())
513     {                                             797     {
514       if (std::abs(tsurfout - ttout[0]) >= hal << 798       G4ThreeVector pt;
                                                   >> 799       if (p.z()>0)
515       {                                           800       {
516         if (tsurfout < ttout[0])               << 801         dist[4] = (fDz-p.z())/v.z();
                                                   >> 802       }
                                                   >> 803       else
                                                   >> 804       {   
                                                   >> 805         dist[4] = (-fDz-p.z())/v.z();
                                                   >> 806       }   
                                                   >> 807       if (dist[4]<-halfCarTolerance)
                                                   >> 808       {
                                                   >> 809         dist[4]=kInfinity;
                                                   >> 810       }
                                                   >> 811       else
                                                   >> 812       {
                                                   >> 813         if(dist[4]<halfCarTolerance)
517         {                                         814         {
518           ttout[1] = ttout[0];                 << 815           if(p.z()>0)  { n=G4ThreeVector(0,0,1); }
519           ttout[0] = tsurfout;                 << 816           else         { n=G4ThreeVector(0,0,-1); }
                                                   >> 817           if (n.dot(v)<0) { dist[4]=0.; }
                                                   >> 818           else            { dist[4]=kInfinity; }
520         }                                         819         }
521         else { ttout[1] = std::min(tsurfout, t << 820         pt=p+dist[4]*v;
                                                   >> 821         if (Inside(pt)==kOutside)  { dist[4]=kInfinity; }
522       }                                           822       }
523     }                                             823     }
                                                   >> 824   }   
                                                   >> 825   G4double distmin = dist[0];
                                                   >> 826   for (i=1;i<5;i++)
                                                   >> 827   {
                                                   >> 828     if (dist[i] < distmin)  { distmin = dist[i]; }
524   }                                               829   }
525                                                   830 
526   // Compute distance to In                    << 831   if (distmin<halfCarTolerance)  { distmin=0.; }
527   //                                           << 
528   if (ttin[0] == DBL_MAX) { return kInfinity;  << 
529                                                   832 
530   // single entry point                        << 833   return distmin;
531   if (ttin[1] == DBL_MAX)                      << 834 }    
532   {                                            << 835   
533     G4double distin = ttin[0];                 << 836 // --------------------------------------------------------------------
534     G4double distout = (distin >= ttout[0] - h << 
535     G4double dist = (distout <= halfTolerance  << 
536     return (dist < halfTolerance) ? 0. : dist; << 
537   }                                            << 
538                                                   837 
539   // two entry points                          << 838 G4double G4GenericTrap::DistanceToIn(const G4ThreeVector& p) const
540   if (ttin[1] < ttout[0])                      << 839 {
                                                   >> 840   // Computes the closest distance from given point to this shape
                                                   >> 841 
                                                   >> 842 #ifdef G4TESS_TEST
                                                   >> 843   if ( fTessellatedSolid )
541   {                                               844   {
542     G4double distin = ttin[1], distout = ttout << 845     return fTessellatedSolid->DistanceToIn(p);
543     G4double dist = (distout <= halfTolerance  << 846   }  
544     return (dist < halfTolerance) ? 0. : dist; << 847 #endif
                                                   >> 848  
                                                   >> 849   G4double safz = std::fabs(p.z())-fDz;
                                                   >> 850   if(safz<0) { safz=0; }
                                                   >> 851 
                                                   >> 852   G4int iseg;
                                                   >> 853   G4double safe  = safz;
                                                   >> 854   G4double safxy = safz;
                                                   >> 855  
                                                   >> 856   for (iseg=0; iseg<4; iseg++)
                                                   >> 857   { 
                                                   >> 858     safxy = SafetyToFace(p,iseg);
                                                   >> 859     if (safxy>safe)  { safe=safxy; }
545   }                                               860   }
546                                                   861 
547   // check 1st pair of in-out points           << 862   return safe;
548   G4double distin1 = ttin[0], distout1 = ttout << 863 }
549   G4double dist1 = (distout1 <= halfTolerance  << 864 
550   if (dist1 != kInfinity) { return (dist1 < ha << 865 // --------------------------------------------------------------------
                                                   >> 866 
                                                   >> 867 G4double
                                                   >> 868 G4GenericTrap::SafetyToFace(const G4ThreeVector& p, const G4int iseg) const
                                                   >> 869 {
                                                   >> 870   // Estimate distance to lateral plane defined by segment iseg in range [0,3]
                                                   >> 871   // Might be negative: plane seen only from inside
                                                   >> 872 
                                                   >> 873   G4ThreeVector p1,norm;
                                                   >> 874   G4double safe;
551                                                   875 
552   // check 2nd pair of in-out points           << 876   p1=G4ThreeVector(fVertices[iseg].x(),fVertices[iseg].y(),-fDz);
553   G4double distin2 = ttin[1], distout2 = ttout << 877   
554   G4double dist2 = (distout2 <= halfTolerance  << 878   norm=NormalToPlane(p,iseg);
555   return (dist2 < halfTolerance) ? 0. : dist2; << 879   safe = (p-p1).dot(norm); // Can be negative
                                                   >> 880  
                                                   >> 881   return safe;
556 }                                                 882 }
557                                                   883 
558 ////////////////////////////////////////////// << 884 // --------------------------------------------------------------------
559 //                                             << 885 
560 // Estimate safety distance to the surface fro << 886 G4double
561 //                                             << 887 G4GenericTrap::DistToTriangle(const G4ThreeVector& p,
562 G4double G4GenericTrap::DistanceToIn(const G4T << 888                               const G4ThreeVector& v, const G4int ipl) const
563 {                                                 889 {
564   G4double px = p.x(), py = p.y(), pz = p.z(); << 890   G4double xa=fVertices[ipl].x();
                                                   >> 891   G4double ya=fVertices[ipl].y();
                                                   >> 892   G4double xb=fVertices[ipl+4].x();
                                                   >> 893   G4double yb=fVertices[ipl+4].y();
                                                   >> 894   G4int j=(ipl+1)%4;
                                                   >> 895   G4double xc=fVertices[j].x();
                                                   >> 896   G4double yc=fVertices[j].y();
                                                   >> 897   G4double zab=2*fDz;
                                                   >> 898   G4double zac=0;
                                                   >> 899   
                                                   >> 900   if ( (std::fabs(xa-xc)+std::fabs(ya-yc)) < halfCarTolerance )
                                                   >> 901   {
                                                   >> 902     xc=fVertices[j+4].x();
                                                   >> 903     yc=fVertices[j+4].y();
                                                   >> 904     zac=2*fDz;
                                                   >> 905     zab=2*fDz;
565                                                   906 
566   // intersect edges by z = pz plane           << 907     //Line case
567   G4TwoVector pp[4];                           << 908     //
568   G4double z = (pz + fDz);                     << 909     if ( (std::fabs(xb-xc)+std::fabs(yb-yc)) < halfCarTolerance )
569   for (auto i = 0; i < 4; ++i) { pp[i] = fVert << 910     {
                                                   >> 911       return kInfinity;
                                                   >> 912     }
                                                   >> 913   }
                                                   >> 914   G4double a=(yb-ya)*zac-(yc-ya)*zab;
                                                   >> 915   G4double b=(xc-xa)*zab-(xb-xa)*zac;
                                                   >> 916   G4double c=(xb-xa)*(yc-ya)-(xc-xa)*(yb-ya);
                                                   >> 917   G4double d=-xa*a-ya*b+fDz*c;
                                                   >> 918   G4double t=a*v.x()+b*v.y()+c*v.z();
570                                                   919 
571   // estimate distance to the solid            << 920   if (t!=0)
572   G4double dist = std::abs(pz) - fDz;          << 
573   for (auto i = 0; i < 4; ++i)                 << 
574   {                                               921   {
575     if (fTwist[i] == 0.)                       << 922     t=-(a*p.x()+b*p.y()+c*p.z()+d)/t;
                                                   >> 923   }
                                                   >> 924   if ( (t<halfCarTolerance) && (t>-halfCarTolerance) )
                                                   >> 925   {
                                                   >> 926     if (NormalToPlane(p,ipl).dot(v)<kCarTolerance)
576     {                                             927     {
577       G4double dd = fSurf[i].D*px + fSurf[i].E << 928       t=kInfinity;
578       dist = std::max(dd, dist);               << 
579     }                                             929     }
580     else                                          930     else
581     {                                             931     {
582       // comptute distance to the wedge (two p << 932       t=0;
583       auto j = (i + 1)%4;                      << 
584       G4double cx = pp[j].x() - pp[i].x();     << 
585       G4double cy = pp[j].y() - pp[i].y();     << 
586       G4double d = (pp[i].x() - px)*cy + (py - << 
587       G4ThreeVector na(-cy, cx, fDelta[i].x()* << 
588       G4ThreeVector nb(-cy, cx, fDelta[j].x()* << 
589       G4double amag2 = na.mag2();              << 
590       G4double bmag2 = nb.mag2();              << 
591       G4double distab = (amag2 > bmag2) ? d/st << 
592       dist = std::max(distab, dist);           << 
593     }                                             933     }
594   }                                               934   }
595   return (dist > 0.) ? dist : 0.; // return sa << 935   if (Inside(p+v*t) != kSurface)  { t=kInfinity; }
596 }                                              << 936  
                                                   >> 937   return t;
                                                   >> 938 } 
                                                   >> 939 
                                                   >> 940 // --------------------------------------------------------------------
597                                                   941 
598 ////////////////////////////////////////////// << 
599 //                                             << 
600 // Calculate distance to surface from inside   << 
601 //                                             << 
602 G4double G4GenericTrap::DistanceToOut(const G4    942 G4double G4GenericTrap::DistanceToOut(const G4ThreeVector& p,
603                                       const G4    943                                       const G4ThreeVector& v,
604                                       const G4    944                                       const G4bool calcNorm,
605                                             G4    945                                             G4bool* validNorm,
606                                             G4    946                                             G4ThreeVector* n) const
607 {                                                 947 {
608   G4double px = p.x(), py = p.y(), pz = p.z(); << 948 #ifdef G4TESS_TEST
609   G4double vx = v.x(), vy = v.y(), vz = v.z(); << 949   if ( fTessellatedSolid )
610                                                << 950   { 
611   // Check intersections with plane faces      << 951     return fTessellatedSolid->DistanceToOut(p, v, calcNorm, validNorm, n);
612   //                                           << 
613   if ((std::abs(pz) - fDz) >= -halfTolerance & << 
614   {                                            << 
615     if (calcNorm)                              << 
616     {                                          << 
617       *validNorm = true;                       << 
618       n->set(0., 0., std::copysign(1., pz));   << 
619     }                                          << 
620     return 0.;                                 << 
621   }                                               952   }
622   G4double tout = (vz == 0) ? DBL_MAX : (std:: << 953 #endif
623   G4int iface = (vz < 0) ? -4 : -2; // little  << 954 
                                                   >> 955   G4double distmin;
                                                   >> 956   G4bool lateral_cross = false;
                                                   >> 957   ESide side = kUndefined;
                                                   >> 958  
                                                   >> 959   if (calcNorm)  { *validNorm=true; } // All normals are valid
624                                                   960 
625   for (auto i = 0; i < 4; ++i)                 << 961   if (v.z() < 0)
626   {                                               962   {
627     if (fTwist[i] != 0) continue; // skip twis << 963     distmin=(-fDz-p.z())/v.z();
628     const G4GenericTrapPlane& surf = fPlane[2* << 964     if (calcNorm) { side=kMZ; *n=G4ThreeVector(0,0,-1); }
629     G4double cosa = surf.A*vx + surf.B*vy + su << 
630     if (cosa > 0)                              << 
631     {                                          << 
632       G4double dist = surf.A*px + surf.B*py +  << 
633       if (dist >= -halfTolerance)              << 
634       {                                        << 
635         if (calcNorm)                          << 
636         {                                      << 
637            *validNorm = true;                  << 
638            n->set(surf.A, surf.B, surf.C);     << 
639         }                                      << 
640         return 0.;                             << 
641       }                                        << 
642       G4double tmp = -dist/cosa;               << 
643       if (tout > tmp) { tout = tmp; iface = i; << 
644     }                                          << 
645   }                                               965   }
646                                                << 966   else
647   // Check intersections with twisted faces    << 967   {
648   //                                           << 968     if (v.z() > 0)
649   constexpr G4double EPSILON = 1000.*DBL_EPSIL << 969     { 
650   for (auto i = 0; i < 4; ++i)                 << 970       distmin = (fDz-p.z())/v.z(); 
651   {                                            << 971       if (calcNorm) { side=kPZ; *n=G4ThreeVector(0,0,1); } 
652     if (fTwist[i] == 0) continue; // skip plan << 972     }
653                                                << 973     else            { distmin = kInfinity; }
654     // twisted face, solve quadratic equation  << 974   }      
655     const G4GenericTrapSurface& surf = fSurf[i << 975 
656     G4double ABC  = surf.A*vx + surf.B*vy + su << 976   G4double dz2 =0.5/fDz;
657     G4double ABCF = surf.A*px + surf.B*py + su << 977   G4double xa,xb,xc,xd;
658     G4double A = ABC*vz;                       << 978   G4double ya,yb,yc,yd;
659     G4double B = 0.5*(surf.D*vx + surf.E*vy +  << 979 
660     G4double C = surf.D*px + surf.E*py + ABCF* << 980   for (G4int ipl=0; ipl<4; ipl++)
661                                                << 981   {
662     if (std::abs(A) <= EPSILON)                << 982     G4int j = (ipl+1)%4;
663     {                                          << 983     xa=fVertices[ipl].x();
664       // case 1: track is parallel to the surf << 984     ya=fVertices[ipl].y();
665       if (std::abs(B) <= EPSILON) { continue;  << 985     xb=fVertices[ipl+4].x();
666                                                << 986     yb=fVertices[ipl+4].y();
667       // case 2: single root                   << 987     xc=fVertices[j].x();
668       G4double tmp = -0.5*C/B;                 << 988     yc=fVertices[j].y();
669       // compute normal at intersection point  << 989     xd=fVertices[4+j].x();
670       G4double x = px + vx*tmp;                << 990     yd=fVertices[4+j].y();
671       G4double y = py + vy*tmp;                << 991 
672       G4double z = pz + vz*tmp;                << 992     if ( ((std::fabs(xb-xd)+std::fabs(yb-yd))<halfCarTolerance)
673       G4double nx = surf.A*z + surf.D;         << 993       || ((std::fabs(xa-xc)+std::fabs(ya-yc))<halfCarTolerance) )
674       G4double ny = surf.B*z + surf.E;         << 994     {
675       G4double nz = surf.A*x + surf.B*y + 2.*s << 995       G4double q=DistToTriangle(p,v,ipl) ;
676                                                << 996       if ( (q>=0) && (q<distmin) )
677       if (nx*vx + ny*vy + nz*vz > 0.) // point << 997       {
678       {                                        << 998         distmin=q;
679         auto k = (i + 1)%4;                    << 999         lateral_cross=true;
680         G4double tz = (pz + fDz);              << 1000         side=ESide(ipl+1);
681         G4TwoVector a = fVertices[i] + fDelta[ << 
682         G4TwoVector b = fVertices[k] + fDelta[ << 
683         G4double dx = b.x() - a.x();           << 
684         G4double dy = b.y() - a.y();           << 
685         G4double leng = std::sqrt(dx*dx + dy*d << 
686         G4double dist = dx*(py - a.y()) - dy*( << 
687         if (dist >= -halfTolerance*leng) // po << 
688         {                                      << 
689           if (calcNorm)                        << 
690           {                                    << 
691             *validNorm = false;                << 
692             G4double normx = surf.A*pz + surf. << 
693             G4double normy = surf.B*pz + surf. << 
694             G4double normz = surf.A*px + surf. << 
695             G4double inv = 1./std::sqrt(normx* << 
696             n->set(normx*inv, normy*inv, normz << 
697           }                                    << 
698           return 0.;                           << 
699         }                                      << 
700         if (tout > tmp) { tout = tmp; iface =  << 
701       }                                           1001       }
702       continue;                                   1002       continue;
703     }                                             1003     }
704                                                << 1004     G4double tx1 =dz2*(xb-xa);
705     // case 3: scratch or no intersection      << 1005     G4double ty1 =dz2*(yb-ya);
706     G4double D = B*B - A*C;                    << 1006     G4double tx2 =dz2*(xd-xc);
707     if (D < 0.25*fScratch*fScratch*A*A)        << 1007     G4double ty2 =dz2*(yd-yc);
708     {                                          << 1008     G4double dzp =fDz+p.z();
709       // check position of the point           << 1009     G4double xs1 =xa+tx1*dzp;
710       auto j = (i + 1)%4;                      << 1010     G4double ys1 =ya+ty1*dzp;
711       G4double tz = pz + fDz;                  << 1011     G4double xs2 =xc+tx2*dzp;
712       G4TwoVector a = fVertices[i] + fDelta[i] << 1012     G4double ys2 =yc+ty2*dzp;
713       G4TwoVector b = fVertices[j] + fDelta[j] << 1013     G4double dxs =xs2-xs1;
714       G4double dx = b.x() - a.x();             << 1014     G4double dys =ys2-ys1;
715       G4double dy = b.y() - a.y();             << 1015     G4double dtx =tx2-tx1;
716       G4double leng = std::sqrt(dx*dx + dy*dy) << 1016     G4double dty =ty2-ty1;
717       G4double dist = dx*(py - a.y()) - dy*(px << 1017     G4double a = (dtx*v.y()-dty*v.x()+(tx1*ty2-tx2*ty1)*v.z())*v.z();
718       if  (dist <= -halfTolerance*leng) { cont << 1018     G4double b = dxs*v.y()-dys*v.x()+(dtx*p.y()-dty*p.x()+ty2*xs1-ty1*xs2
719       if  (A > 0 || dist > halfTolerance*leng) << 1019                + tx1*ys2-tx2*ys1)*v.z();
                                                   >> 1020     G4double c=dxs*p.y()-dys*p.x()+xs1*ys2-xs2*ys1;
                                                   >> 1021     G4double q=kInfinity;
                                                   >> 1022 
                                                   >> 1023     if (std::fabs(a) < kCarTolerance)
                                                   >> 1024     {           
                                                   >> 1025       if (std::fabs(b) < kCarTolerance) { continue; }
                                                   >> 1026       q=-c/b;
                                                   >> 1027          
                                                   >> 1028       // Check for Point on the Surface
                                                   >> 1029       //
                                                   >> 1030       if ((q > -halfCarTolerance) && (q < distmin))
720       {                                           1031       {
721         if (calcNorm)                          << 1032         if (q < halfCarTolerance)
722         {                                         1033         {
723           *validNorm = false;                  << 1034           if (NormalToPlane(p,ipl).dot(v)<0.)  { continue; }
724           G4double nx = surf.A*pz + surf.D;    << 
725           G4double ny = surf.B*pz + surf.E;    << 
726           G4double nz = surf.A*px + surf.B*py  << 
727           G4double inv = 1./std::sqrt(nx*nx +  << 
728           n->set(nx*inv, ny*inv, nz*inv);      << 
729         }                                         1035         }
730         return 0.;                             << 1036         distmin =q;
731       }                                        << 1037         lateral_cross=true;
                                                   >> 1038         side=ESide(ipl+1);
                                                   >> 1039       }   
732       continue;                                   1040       continue;
733     }                                             1041     }
                                                   >> 1042     G4double d=b*b-4*a*c;
                                                   >> 1043     if (d >= 0.)
                                                   >> 1044     {
                                                   >> 1045       if (a > 0)  { q=0.5*(-b-std::sqrt(d))/a; }
                                                   >> 1046       else        { q=0.5*(-b+std::sqrt(d))/a; }
734                                                   1047 
735     // case 4: two intersection points         << 1048       // Check for Point on the Surface
736     G4double tmp = -B - std::copysign(std::sqr << 1049       //
737     G4double t1 = tmp / A;                     << 1050       if (q > -halfCarTolerance )
738     G4double t2 = C / tmp;                     << 1051       {
739     G4double tmin = std::min(t1, t2);          << 1052         if (q < distmin)
740     G4double tmax = std::max(t1, t2);          << 
741                                                << 
742     if (A < 0) // concave profile: tmin(out) - << 
743     {                                          << 
744       if (std::abs(tmax) < std::abs(tmin)) con << 
745       if (tmin <= halfTolerance) // point is o << 
746       {                                        << 
747         G4double t = 0.5*(tmin + tmax);        << 
748         G4double x = px + vx*t;                << 
749         G4double y = py + vy*t;                << 
750         G4double z = pz + vz*t;                << 
751                                                << 
752         auto j = (i + 1)%4;                    << 
753         G4double tz = z + fDz;                 << 
754         G4TwoVector a = fVertices[i] + fDelta[ << 
755         G4TwoVector b = fVertices[j] + fDelta[ << 
756         G4double dx = b.x() - a.x();           << 
757         G4double dy = b.y() - a.y();           << 
758         G4double leng = std::sqrt(dx*dx + dy*d << 
759         G4double dist = dx*(y - a.y()) - dy*(x << 
760         if  (dist <= -halfTolerance*leng) cont << 
761         if (calcNorm)                          << 
762         {                                         1053         {
763           *validNorm = false;                  << 1054           if(q < halfCarTolerance)
764           G4double nx = surf.A*pz + surf.D;    << 1055           {
765           G4double ny = surf.B*pz + surf.E;    << 1056             if (NormalToPlane(p,ipl).dot(v)<0.)  // Check second root
766           G4double nz = surf.A*px + surf.B*py  << 1057             {
767           G4double inv = 1./std::sqrt(nx*nx +  << 1058               if (a > 0)  { q=0.5*(-b+std::sqrt(d))/a; }
768           n->set(nx*inv, ny*inv, nz*inv);      << 1059               else        { q=0.5*(-b-std::sqrt(d))/a; }
                                                   >> 1060               if (( q > halfCarTolerance) && (q < distmin))
                                                   >> 1061               {
                                                   >> 1062                 distmin=q;
                                                   >> 1063                 lateral_cross = true;
                                                   >> 1064                 side=ESide(ipl+1);
                                                   >> 1065               }
                                                   >> 1066               continue;
                                                   >> 1067             }
                                                   >> 1068           }
                                                   >> 1069           distmin = q;
                                                   >> 1070           lateral_cross = true;
                                                   >> 1071           side=ESide(ipl+1);
769         }                                         1072         }
770         return 0.;                             << 
771       }                                           1073       }
772       if (tout > tmin) { tout = tmin; iface =  << 1074       else
773     }                                          << 
774     else // convex profile: tmin(in) -> tmax(o << 
775     {                                          << 
776       if (tmax < halfTolerance) // point is on << 
777       {                                           1075       {
778         if (calcNorm)                          << 1076         if (a > 0)  { q=0.5*(-b+std::sqrt(d))/a; }
                                                   >> 1077         else        { q=0.5*(-b-std::sqrt(d))/a; }
                                                   >> 1078 
                                                   >> 1079         // Check for Point on the Surface
                                                   >> 1080         //
                                                   >> 1081         if ((q > -halfCarTolerance) && (q < distmin))
779         {                                         1082         {
780           *validNorm = false;                  << 1083           if (q < halfCarTolerance)
781           G4double nx = surf.A*pz + surf.D;    << 1084           {
782           G4double ny = surf.B*pz + surf.E;    << 1085             if (NormalToPlane(p,ipl).dot(v)<0.)  // Check second root
783           G4double nz = surf.A*px + surf.B*py  << 1086             {
784           G4double inv = 1./std::sqrt(nx*nx +  << 1087               if (a > 0)  { q=0.5*(-b-std::sqrt(d))/a; }
785           n->set(nx*inv, ny*inv, nz*inv);      << 1088               else        { q=0.5*(-b+std::sqrt(d))/a; }
786         }                                      << 1089               if ( ( q > halfCarTolerance) && (q < distmin) )
787         return 0.;                             << 1090               {
                                                   >> 1091                 distmin=q;
                                                   >> 1092                 lateral_cross = true;
                                                   >> 1093                 side=ESide(ipl+1);
                                                   >> 1094               }
                                                   >> 1095               continue;
                                                   >> 1096             }  
                                                   >> 1097           }
                                                   >> 1098           distmin =q;
                                                   >> 1099           lateral_cross = true;
                                                   >> 1100           side=ESide(ipl+1);
                                                   >> 1101         }   
788       }                                           1102       }
789       if (tout > tmax) { tout = tmax; iface =  << 
790     }                                             1103     }
791   }                                               1104   }
792                                                << 1105   if (!lateral_cross)  // Make sure that track crosses the top or bottom
793   // Compute normal, if required, and return d << 1106   {
794   //                                           << 1107     if (distmin >= kInfinity)  { distmin=kCarTolerance; }
795   if (tout < halfTolerance) tout = 0.;         << 1108     G4ThreeVector pt=p+distmin*v;
796   if (calcNorm)                                << 1109     
797   {                                            << 1110     // Check if propagated point is in the polygon
798     if (iface < 0)                             << 1111     //
799     {                                          << 1112     G4int i=0;
800       *validNorm = true;                       << 1113     if (v.z()>0.) { i=4; }
801       n->set(0, 0, iface + 3); // little trick << 1114     std::vector<G4TwoVector> xy;
                                                   >> 1115     for ( G4int j=0; j<4; j++)  { xy.push_back(fVertices[i+j]); }
                                                   >> 1116 
                                                   >> 1117     // Check Inside
                                                   >> 1118     //
                                                   >> 1119     if (InsidePolygone(pt,xy)==kOutside)
                                                   >> 1120     { 
                                                   >> 1121       if(calcNorm)
                                                   >> 1122       {
                                                   >> 1123         if (v.z()>0) {side= kPZ; *n = G4ThreeVector(0,0,1);}
                                                   >> 1124         else         { side=kMZ; *n = G4ThreeVector(0,0,-1);}
                                                   >> 1125       } 
                                                   >> 1126       return 0.;
802     }                                             1127     }
803     else                                          1128     else
804     {                                             1129     {
805       const G4GenericTrapSurface& surf = fSurf << 1130       if(v.z()>0) {side=kPZ;}
806       if (fTwist[iface] == 0)                  << 1131       else        {side=kMZ;}
807       {                                        << 
808         *validNorm = true;                     << 
809         n->set(surf.D, surf.E, surf.F);        << 
810       }                                        << 
811       else                                     << 
812       {                                        << 
813         *validNorm = false;                    << 
814         G4double x = px + vx*tout;             << 
815         G4double y = py + vy*tout;             << 
816         G4double z = pz + vz*tout;             << 
817         G4double nx = surf.A*z + surf.D;       << 
818         G4double ny = surf.B*z + surf.E;       << 
819         G4double nz = surf.A*x + surf.B*y + 2. << 
820         G4double inv = 1./std::sqrt(nx*nx + ny << 
821         n->set(nx*inv, ny*inv, nz*inv);        << 
822       }                                        << 
823     }                                             1132     }
824   }                                               1133   }
825   return tout;                                 << 
826 }                                              << 
827                                                   1134 
828 ////////////////////////////////////////////// << 1135   if (calcNorm)
829 //                                             << 1136   {
830 // Estimate safety distance to the surface fro << 1137     G4ThreeVector pt=p+v*distmin;     
831 //                                             << 1138     switch (side)
                                                   >> 1139     {
                                                   >> 1140       case kXY0:
                                                   >> 1141         *n=NormalToPlane(pt,0);
                                                   >> 1142         break;
                                                   >> 1143       case kXY1:
                                                   >> 1144         *n=NormalToPlane(pt,1);
                                                   >> 1145         break;
                                                   >> 1146       case kXY2:
                                                   >> 1147         *n=NormalToPlane(pt,2);
                                                   >> 1148         break;
                                                   >> 1149       case kXY3:
                                                   >> 1150         *n=NormalToPlane(pt,3);
                                                   >> 1151         break;
                                                   >> 1152       case kPZ:
                                                   >> 1153         *n=G4ThreeVector(0,0,1);
                                                   >> 1154         break;
                                                   >> 1155       case kMZ:
                                                   >> 1156         *n=G4ThreeVector(0,0,-1);
                                                   >> 1157         break;
                                                   >> 1158       default:
                                                   >> 1159         DumpInfo();
                                                   >> 1160         std::ostringstream message;
                                                   >> 1161         G4int oldprc = message.precision(16);
                                                   >> 1162         message << "Undefined side for valid surface normal to solid." << G4endl
                                                   >> 1163                 << "Position:" << G4endl
                                                   >> 1164                 << "  p.x() = "   << p.x()/mm << " mm" << G4endl
                                                   >> 1165                 << "  p.y() = "   << p.y()/mm << " mm" << G4endl
                                                   >> 1166                 << "  p.z() = "   << p.z()/mm << " mm" << G4endl
                                                   >> 1167                 << "Direction:" << G4endl
                                                   >> 1168                 << "  v.x() = "   << v.x() << G4endl
                                                   >> 1169                 << "  v.y() = "   << v.y() << G4endl
                                                   >> 1170                 << "  v.z() = "   << v.z() << G4endl
                                                   >> 1171                 << "Proposed distance :" << G4endl
                                                   >> 1172                 << "  distmin = " << distmin/mm << " mm";
                                                   >> 1173         message.precision(oldprc);
                                                   >> 1174         G4Exception("G4GenericTrap::DistanceToOut(p,v,..)",
                                                   >> 1175                     "GeomSolids1002", JustWarning, message);
                                                   >> 1176         break;
                                                   >> 1177      }
                                                   >> 1178   }
                                                   >> 1179  
                                                   >> 1180   if (distmin<halfCarTolerance)  { distmin=0.; }
                                                   >> 1181  
                                                   >> 1182   return distmin;
                                                   >> 1183 }    
                                                   >> 1184 
                                                   >> 1185 // --------------------------------------------------------------------
                                                   >> 1186 
832 G4double G4GenericTrap::DistanceToOut(const G4    1187 G4double G4GenericTrap::DistanceToOut(const G4ThreeVector& p) const
833 {                                                 1188 {
834   G4double px = p.x(), py = p.y(), pz = p.z(); << 
835                                                   1189 
836   // intersect edges by z = pz plane           << 1190 #ifdef G4TESS_TEST
837   G4TwoVector pp[4];                           << 1191   if ( fTessellatedSolid )
838   G4double z = (pz + fDz);                     << 1192   { 
839   for (auto i = 0; i < 4; ++i) { pp[i] = fVert << 1193     return fTessellatedSolid->DistanceToOut(p);
                                                   >> 1194   }  
                                                   >> 1195 #endif
840                                                   1196 
841   // estimate distance to the solid            << 1197   G4double safz = fDz-std::fabs(p.z());
842   G4double dist =  std::abs(pz) - fDz;         << 1198   if (safz<0) { safz = 0; }
843   for (auto i = 0; i < 4; ++i)                 << 1199 
844   {                                            << 1200   G4double safe  = safz;
845     if (fTwist[i] == 0.)                       << 1201   G4double safxy = safz;
846     {                                          << 1202  
847       G4double dd = fSurf[i].D*px + fSurf[i].E << 1203   for (G4int iseg=0; iseg<4; iseg++)
848       dist = std::max(dd, dist);               << 1204   { 
849     }                                          << 1205     safxy = std::fabs(SafetyToFace(p,iseg));
850     else                                       << 1206     if (safxy < safe)  { safe = safxy; }
851     {                                          << 
852       // comptute distance to the wedge (two p << 
853       auto j = (i + 1)%4;                      << 
854       G4double cx = pp[j].x() - pp[i].x();     << 
855       G4double cy = pp[j].y() - pp[i].y();     << 
856       G4double d = (pp[i].x() - px)*cy + (py - << 
857       G4ThreeVector na(-cy, cx, fDelta[i].x()* << 
858       G4ThreeVector nb(-cy, cx, fDelta[j].x()* << 
859       G4double amag2 = na.mag2();              << 
860       G4double bmag2 = nb.mag2();              << 
861       G4double distab = (amag2 > bmag2) ? d/st << 
862       dist = std::max(distab, dist);           << 
863     }                                          << 
864   }                                               1207   }
865   return (dist < 0.) ? -dist : 0.; // return s << 
866 }                                              << 
867                                                   1208 
868 ////////////////////////////////////////////// << 1209   return safe;
869 //                                             << 1210 }    
870 // Return bounding box                         << 1211 
871 //                                             << 1212 // --------------------------------------------------------------------
                                                   >> 1213 
872 void G4GenericTrap::BoundingLimits(G4ThreeVect    1214 void G4GenericTrap::BoundingLimits(G4ThreeVector& pMin,
873                                    G4ThreeVect    1215                                    G4ThreeVector& pMax) const
874 {                                                 1216 {
875   pMin = fMinBBox;                             << 1217   pMin = GetMinimumBBox();
876   pMax = fMaxBBox;                             << 1218   pMax = GetMaximumBBox();
                                                   >> 1219 
                                                   >> 1220   // Check correctness of the bounding box
                                                   >> 1221   //
                                                   >> 1222   if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
                                                   >> 1223   {
                                                   >> 1224     std::ostringstream message;
                                                   >> 1225     message << "Bad bounding box (min >= max) for solid: "
                                                   >> 1226             << GetName() << " !"
                                                   >> 1227             << "\npMin = " << pMin
                                                   >> 1228             << "\npMax = " << pMax;
                                                   >> 1229     G4Exception("G4GenericTrap::BoundingLimits()", "GeomMgt0001",
                                                   >> 1230                 JustWarning, message);
                                                   >> 1231     DumpInfo();
                                                   >> 1232   }
877 }                                                 1233 }
878                                                   1234 
879 ////////////////////////////////////////////// << 1235 // --------------------------------------------------------------------
880 //                                             << 1236 
881 // Calculate extent under transform and specif << 
882 //                                             << 
883 G4bool                                            1237 G4bool
884 G4GenericTrap::CalculateExtent(const EAxis pAx    1238 G4GenericTrap::CalculateExtent(const EAxis pAxis,
885                                const G4VoxelLi    1239                                const G4VoxelLimits& pVoxelLimit,
886                                const G4AffineT    1240                                const G4AffineTransform& pTransform,
887                                      G4double&    1241                                      G4double& pMin, G4double& pMax) const
888 {                                                 1242 {
889   G4ThreeVector bmin, bmax;                       1243   G4ThreeVector bmin, bmax;
890   G4bool exist;                                   1244   G4bool exist;
891                                                   1245 
892   // Check bounding box (bbox)                    1246   // Check bounding box (bbox)
893   //                                              1247   //
894   BoundingLimits(bmin,bmax);                      1248   BoundingLimits(bmin,bmax);
895   G4BoundingEnvelope bbox(bmin,bmax);             1249   G4BoundingEnvelope bbox(bmin,bmax);
896 #ifdef G4BBOX_EXTENT                              1250 #ifdef G4BBOX_EXTENT
897   return bbox.CalculateExtent(pAxis,pVoxelLimi << 1251   if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
898 #endif                                            1252 #endif
899   if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox    1253   if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
900   {                                               1254   {
901     return exist = pMin < pMax;                << 1255     return exist = (pMin < pMax) ? true : false;
902   }                                               1256   }
903                                                   1257 
904   // Set bounding envelope (benv) and calculat    1258   // Set bounding envelope (benv) and calculate extent
905   //                                              1259   //
906   // To build the bounding envelope with plane << 1260   // To build the bounding envelope with plane faces each side face of
907   // the trapezoid is subdivided in two triang << 1261   // the trapezoid is subdivided in triangles. Subdivision is done by
908   // duplication of vertices in the bases in a    1262   // duplication of vertices in the bases in a way that the envelope be
909   // a convex polyhedron (some faces of the en << 1263   // a convex polyhedron (some faces of the envelope can be degenerate)
910   //                                              1264   //
911   G4double dz = GetZHalfLength();                 1265   G4double dz = GetZHalfLength();
912   G4ThreeVectorList baseA(8), baseB(8);           1266   G4ThreeVectorList baseA(8), baseB(8);
913   for (G4int i = 0; i < 4; ++i)                << 1267   for (G4int i=0; i<4; ++i)
914   {                                               1268   {
915     G4TwoVector va = GetVertex(i);                1269     G4TwoVector va = GetVertex(i);
916     G4TwoVector vb = GetVertex(i+4);              1270     G4TwoVector vb = GetVertex(i+4);
917     baseA[2*i].set(va.x(), va.y(),-dz);        << 1271     baseA[2*i].set(va.x(),va.y(),-dz);
918     baseB[2*i].set(vb.x(), vb.y(), dz);        << 1272     baseB[2*i].set(vb.x(),vb.y(), dz);
919   }                                               1273   }
920   for (G4int i = 0; i < 4; ++i)                << 1274   for (G4int i=0; i<4; ++i)
921   {                                               1275   {
922     G4int k1 = 2*i, k2 = (2*i + 2)%8;          << 1276     G4int k1=2*i, k2=(2*i+2)%8;
923     G4double ax = (baseA[k2].x() - baseA[k1].x << 1277     G4double ax = (baseA[k2].x()-baseA[k1].x());
924     G4double ay = (baseA[k2].y() - baseA[k1].y << 1278     G4double ay = (baseA[k2].y()-baseA[k1].y());
925     G4double bx = (baseB[k2].x() - baseB[k1].x << 1279     G4double bx = (baseB[k2].x()-baseB[k1].x());
926     G4double by = (baseB[k2].y() - baseB[k1].y << 1280     G4double by = (baseB[k2].y()-baseB[k1].y());
927     G4double znorm = ax*by - ay*bx;               1281     G4double znorm = ax*by - ay*bx;
928     baseA[k1+1] = (znorm < 0.0) ? baseA[k2] :     1282     baseA[k1+1] = (znorm < 0.0) ? baseA[k2] : baseA[k1];
929     baseB[k1+1] = (znorm < 0.0) ? baseB[k1] :     1283     baseB[k1+1] = (znorm < 0.0) ? baseB[k1] : baseB[k2];
930   }                                               1284   }
931                                                   1285 
932   std::vector<const G4ThreeVectorList *> polyg    1286   std::vector<const G4ThreeVectorList *> polygons(2);
933   polygons[0] = &baseA;                           1287   polygons[0] = &baseA;
934   polygons[1] = &baseB;                           1288   polygons[1] = &baseB;
935                                                   1289 
936   G4BoundingEnvelope benv(bmin, bmax, polygons << 1290   G4BoundingEnvelope benv(bmin,bmax,polygons);
937   exist = benv.CalculateExtent(pAxis,pVoxelLim    1291   exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
938   return exist;                                   1292   return exist;
939 }                                                 1293 }
                                                   >> 1294   
                                                   >> 1295 // --------------------------------------------------------------------
940                                                   1296 
941 ////////////////////////////////////////////// << 
942 //                                             << 
943 // Return type of the solid                    << 
944 //                                             << 
945 G4GeometryType G4GenericTrap::GetEntityType()     1297 G4GeometryType G4GenericTrap::GetEntityType() const
946 {                                                 1298 {
947   return { "G4GenericTrap" };                  << 1299   return G4String("G4GenericTrap");
948 }                                              << 
949                                                << 
950 ////////////////////////////////////////////// << 
951 //                                             << 
952 // Return true if not twisted, false otherwise << 
953 //                                             << 
954 G4bool G4GenericTrap::IsFaceted() const        << 
955 {                                              << 
956   return (!fIsTwisted);                        << 
957 }                                                 1300 }
                                                   >> 1301   
                                                   >> 1302 // --------------------------------------------------------------------
958                                                   1303 
959 ////////////////////////////////////////////// << 
960 //                                             << 
961 // Make a clone of the solid                   << 
962 //                                             << 
963 G4VSolid* G4GenericTrap::Clone() const            1304 G4VSolid* G4GenericTrap::Clone() const
964 {                                                 1305 {
965   return new G4GenericTrap(*this);                1306   return new G4GenericTrap(*this);
966 }                                                 1307 }
967                                                   1308 
968 ////////////////////////////////////////////// << 1309 // --------------------------------------------------------------------
969 //                                             << 1310 
970 // Write parameters of the solid to the specif << 
971 //                                             << 
972 std::ostream& G4GenericTrap::StreamInfo(std::o    1311 std::ostream& G4GenericTrap::StreamInfo(std::ostream& os) const
973 {                                                 1312 {
974   G4long oldprc = os.precision(16);            << 1313   G4int oldprc = os.precision(16);
975   os << "-------------------------------------    1314   os << "-----------------------------------------------------------\n"
976      << "    *** Dump for solid - " << GetName << 1315      << "    *** Dump for solid - " << GetName() << " *** \n"
977      << "    ================================= << 1316      << "    =================================================== \n"
978      << "Solid geometry type: " << GetEntityTy << 1317      << " Solid geometry type: " << GetEntityType()  << G4endl
979      << "   half length Z: " << fDz/mm << "\n" << 1318      << "   half length Z: " << fDz/mm << " mm \n"
980      << "   list of vertices:\n";                 1319      << "   list of vertices:\n";
981   for (G4int i = 0; i < 8; ++i)                << 1320      
                                                   >> 1321   for ( G4int i=0; i<fgkNofVertices; ++i )
982   {                                               1322   {
983     os << "    #" << i << " " << fVertices[i]  << 1323     os << std::setw(5) << "#" << i 
                                                   >> 1324        << "   vx = " << fVertices[i].x()/mm << " mm" 
                                                   >> 1325        << "   vy = " << fVertices[i].y()/mm << " mm" << G4endl;
984   }                                               1326   }
985   os << "------------------------------------- << 
986   os.precision(oldprc);                           1327   os.precision(oldprc);
                                                   >> 1328 
987   return os;                                      1329   return os;
988 }                                              << 1330 } 
                                                   >> 1331 
                                                   >> 1332 // --------------------------------------------------------------------
989                                                   1333 
990 ////////////////////////////////////////////// << 
991 //                                             << 
992 // Pick up a random point on the surface       << 
993 //                                             << 
994 G4ThreeVector G4GenericTrap::GetPointOnSurface    1334 G4ThreeVector G4GenericTrap::GetPointOnSurface() const
995 {                                                 1335 {
996   if (fArea[0] + fArea[1] + fArea[2] + fArea[3 << 1336 
                                                   >> 1337 #ifdef G4TESS_TEST
                                                   >> 1338   if ( fTessellatedSolid )
                                                   >> 1339   { 
                                                   >> 1340     return fTessellatedSolid->GetPointOnSurface();
                                                   >> 1341   }  
                                                   >> 1342 #endif
                                                   >> 1343 
                                                   >> 1344   G4ThreeVector point;
                                                   >> 1345   G4TwoVector u,v,w;
                                                   >> 1346   G4double rand,area,chose,cf,lambda0,lambda1,alfa,beta,zp;
                                                   >> 1347   G4int ipl,j;
                                                   >> 1348  
                                                   >> 1349   std::vector<G4ThreeVector> vertices;
                                                   >> 1350   for (G4int i=0; i<4;i++)
997   {                                               1351   {
998     G4AutoLock l(&lateralareaMutex);           << 1352     vertices.push_back(G4ThreeVector(fVertices[i].x(),fVertices[i].y(),-fDz));
999     fArea[0] = GetLateralFaceArea(0);          << 1353   }
1000     fArea[1] = GetLateralFaceArea(1);         << 1354   for (G4int i=4; i<8;i++)
1001     fArea[2] = GetLateralFaceArea(2);         << 1355   {
1002     fArea[3] = GetLateralFaceArea(3);         << 1356     vertices.push_back(G4ThreeVector(fVertices[i].x(),fVertices[i].y(),fDz));
1003     l.unlock();                               << 
1004   }                                              1357   }
1005                                                  1358 
1006   constexpr G4int iface[6][4] =               << 1359   // Surface Area of Planes(only estimation for twisted)
1007     { {0,1,2,3}, {0,4,5,1}, {1,5,6,2}, {2,6,7 << 1360   //
                                                   >> 1361   G4double Surface0=GetFaceSurfaceArea(vertices[0],vertices[1],
                                                   >> 1362                                        vertices[2],vertices[3]);//-fDz plane 
                                                   >> 1363   G4double Surface1=GetFaceSurfaceArea(vertices[0],vertices[1],
                                                   >> 1364                                        vertices[5],vertices[4]);// Lat plane
                                                   >> 1365   G4double Surface2=GetFaceSurfaceArea(vertices[3],vertices[0],
                                                   >> 1366                                        vertices[4],vertices[7]);// Lat plane
                                                   >> 1367   G4double Surface3=GetFaceSurfaceArea(vertices[2],vertices[3],
                                                   >> 1368                                        vertices[7],vertices[6]);// Lat plane
                                                   >> 1369   G4double Surface4=GetFaceSurfaceArea(vertices[2],vertices[1],
                                                   >> 1370                                        vertices[5],vertices[6]);// Lat plane
                                                   >> 1371   G4double Surface5=GetFaceSurfaceArea(vertices[4],vertices[5],
                                                   >> 1372                                        vertices[6],vertices[7]);// fDz plane
                                                   >> 1373   rand = G4UniformRand();
                                                   >> 1374   area = Surface0+Surface1+Surface2+Surface3+Surface4+Surface5;
                                                   >> 1375   chose = rand*area;
                                                   >> 1376 
                                                   >> 1377   if ( ( chose < Surface0)
                                                   >> 1378     || ( chose > (Surface0+Surface1+Surface2+Surface3+Surface4)) )
                                                   >> 1379   {                                        // fDz or -fDz Plane
                                                   >> 1380     ipl = G4int(G4UniformRand()*4);
                                                   >> 1381     j = (ipl+1)%4;
                                                   >> 1382     if(chose < Surface0)
                                                   >> 1383     { 
                                                   >> 1384       zp = -fDz;
                                                   >> 1385       u = fVertices[ipl]; v = fVertices[j];
                                                   >> 1386       w = fVertices[(ipl+3)%4]; 
                                                   >> 1387     }
                                                   >> 1388     else
                                                   >> 1389     {
                                                   >> 1390       zp = fDz;
                                                   >> 1391       u = fVertices[ipl+4]; v = fVertices[j+4];
                                                   >> 1392       w = fVertices[(ipl+3)%4+4]; 
                                                   >> 1393     }
                                                   >> 1394     alfa = G4UniformRand();
                                                   >> 1395     beta = G4UniformRand();
                                                   >> 1396     lambda1=alfa*beta;
                                                   >> 1397     lambda0=alfa-lambda1;
                                                   >> 1398     v = v-u;
                                                   >> 1399     w = w-u;
                                                   >> 1400     v = u+lambda0*v+lambda1*w;
                                                   >> 1401   }
                                                   >> 1402   else                                     // Lateral Plane Twisted or Not
                                                   >> 1403   {
                                                   >> 1404     if (chose < Surface0+Surface1) { ipl=0; }
                                                   >> 1405     else if (chose < Surface0+Surface1+Surface2) { ipl=1; }
                                                   >> 1406     else if (chose < Surface0+Surface1+Surface2+Surface3) { ipl=2; }
                                                   >> 1407     else { ipl=3; }
                                                   >> 1408     j = (ipl+1)%4;
                                                   >> 1409     zp = -fDz+G4UniformRand()*2*fDz;
                                                   >> 1410     cf = 0.5*(fDz-zp)/fDz;
                                                   >> 1411     u = fVertices[ipl+4]+cf*( fVertices[ipl]-fVertices[ipl+4]);
                                                   >> 1412     v = fVertices[j+4]+cf*(fVertices[j]-fVertices[j+4]); 
                                                   >> 1413     v = u+(v-u)*G4UniformRand();
                                                   >> 1414   }
                                                   >> 1415   point=G4ThreeVector(v.x(),v.y(),zp);
1008                                                  1416 
1009   G4bool isTwisted[6] = {false};              << 1417   return point;
1010   for (auto i = 0; i < 4; ++i) { isTwisted[i  << 1418 }
1011                                                  1419 
1012   G4double ssurf[6];                          << 1420 // --------------------------------------------------------------------
1013   G4TwoVector A = fVertices[3] - fVertices[1] << 
1014   G4TwoVector B = fVertices[2] - fVertices[0] << 
1015   G4TwoVector C = fVertices[7] - fVertices[5] << 
1016   G4TwoVector D = fVertices[6] - fVertices[4] << 
1017   ssurf[0] = (A.x()*B.y() - A.y()*B.x())*0.5; << 
1018   ssurf[1] = ssurf[0] + fArea[0];             << 
1019   ssurf[2] = ssurf[1] + fArea[1];             << 
1020   ssurf[3] = ssurf[2] + fArea[2];             << 
1021   ssurf[4] = ssurf[3] + fArea[3];             << 
1022   ssurf[5] = ssurf[4] + (C.x()*D.y() - C.y()* << 
1023                                               << 
1024   G4double select = ssurf[5]*G4QuickRand();   << 
1025   G4int k;                                    << 
1026   for (k = 0; k < 5; ++k) { if (select <= ssu << 
1027                                               << 
1028   G4int i0 = iface[k][0];                     << 
1029   G4int i1 = iface[k][1];                     << 
1030   G4int i2 = iface[k][2];                     << 
1031   G4int i3 = iface[k][3];                     << 
1032   G4ThreeVector pp[4];                        << 
1033   pp[0].set(fVertices[i0].x(), fVertices[i0]. << 
1034   pp[1].set(fVertices[i1].x(), fVertices[i1]. << 
1035   pp[2].set(fVertices[i2].x(), fVertices[i2]. << 
1036   pp[3].set(fVertices[i3].x(), fVertices[i3]. << 
1037                                                  1421 
1038   G4ThreeVector point;                        << 1422 G4double G4GenericTrap::GetSurfaceArea()
1039   if (isTwisted[k])                           << 1423 {
1040   { // twisted face, rejection sampling       << 1424   if (fSurfaceArea == 0.0) {
1041     G4double maxlength = std::max((pp[2] - pp << 1425     if(fIsTwisted) {
1042     point = (pp[0] + pp[1] + pp[2] + pp[3])*0 << 1426       fSurfaceArea = G4VSolid::GetSurfaceArea();
1043     for (auto i = 0; i < 10000; ++i)          << 1427     } else {
1044     {                                         << 1428       // Set vertices
1045       G4double u = G4QuickRand();             << 1429       G4ThreeVector vertix0(fVertices[0].x(),fVertices[0].y(),-fDz);
1046       G4ThreeVector p0 = pp[0] + (pp[1] - pp[ << 1430       G4ThreeVector vertix1(fVertices[1].x(),fVertices[1].y(),-fDz);
1047       G4ThreeVector p1 = pp[3] + (pp[2] - pp[ << 1431       G4ThreeVector vertix2(fVertices[2].x(),fVertices[2].y(),-fDz);
1048       G4double v = G4QuickRand()*(maxlength/( << 1432       G4ThreeVector vertix3(fVertices[3].x(),fVertices[3].y(),-fDz);
1049       if (v >= 1.) continue;                  << 1433       G4ThreeVector vertix4(fVertices[4].x(),fVertices[4].y(), fDz);
1050       point = p0 + (p1 - p0)*v;               << 1434       G4ThreeVector vertix5(fVertices[5].x(),fVertices[5].y(), fDz);
1051       break;                                  << 1435       G4ThreeVector vertix6(fVertices[6].x(),fVertices[6].y(), fDz);
                                                   >> 1436       G4ThreeVector vertix7(fVertices[7].x(),fVertices[7].y(), fDz);
                                                   >> 1437 
                                                   >> 1438       // Find Surface Area
                                                   >> 1439       fSurfaceArea = GetFaceSurfaceArea(vertix0,vertix1,vertix2,vertix3)  // -fDz plane
                                                   >> 1440                    + GetFaceSurfaceArea(vertix1,vertix0,vertix4,vertix5)  //  Lat plane
                                                   >> 1441                    + GetFaceSurfaceArea(vertix2,vertix1,vertix5,vertix6)  //  Lat plane 
                                                   >> 1442                    + GetFaceSurfaceArea(vertix3,vertix2,vertix6,vertix7)  //  Lat plane
                                                   >> 1443                    + GetFaceSurfaceArea(vertix0,vertix3,vertix7,vertix4)  //  Lat plane
                                                   >> 1444                    + GetFaceSurfaceArea(vertix7,vertix6,vertix5,vertix4); // +fDz plane 
1052     }                                            1445     }
1053   }                                              1446   }
1054   else                                        << 1447   return fSurfaceArea;
1055   { // plane face                             << 
1056     G4double u = G4QuickRand();               << 
1057     G4double v = G4QuickRand();               << 
1058     if (u + v > 1.) { u = 1. - u; v = 1. - v; << 
1059     G4double ss = (((pp[2] - pp[0]).cross(pp[ << 
1060     G4int j = (select > ssurf[k] - ss) ? 3 :  << 
1061     point = pp[0] + (pp[2] - pp[0])*u + (pp[j << 
1062   }                                           << 
1063   return point;                               << 
1064 }                                                1448 }
1065                                                  1449 
1066 ///////////////////////////////////////////// << 1450 // --------------------------------------------------------------------
1067 //                                            << 1451 
1068 // Return volume of the solid                 << 
1069 //                                            << 
1070 G4double G4GenericTrap::GetCubicVolume()         1452 G4double G4GenericTrap::GetCubicVolume()
1071 {                                                1453 {
1072   if (fCubicVolume == 0.0)                    << 1454   if (fCubicVolume == 0.0) {
1073   {                                           << 1455     if(fIsTwisted) {
1074     // diagonals                              << 1456       fCubicVolume = G4VSolid::GetCubicVolume();
1075     G4TwoVector A = fVertices[3] - fVertices[ << 1457     } else {
1076     G4TwoVector B = fVertices[2] - fVertices[ << 1458       // Set vertices
1077     G4TwoVector C = fVertices[7] - fVertices[ << 1459       G4ThreeVector vertix0(fVertices[0].x(),fVertices[0].y(),-fDz);
1078     G4TwoVector D = fVertices[6] - fVertices[ << 1460       G4ThreeVector vertix1(fVertices[1].x(),fVertices[1].y(),-fDz);
1079                                               << 1461       G4ThreeVector vertix2(fVertices[2].x(),fVertices[2].y(),-fDz);
1080     // kross products                         << 1462       G4ThreeVector vertix3(fVertices[3].x(),fVertices[3].y(),-fDz);
1081     G4double AB = A.x()*B.y() - A.y()*B.x();  << 1463       G4ThreeVector vertix4(fVertices[4].x(),fVertices[4].y(), fDz);
1082     G4double CD = C.x()*D.y() - C.y()*D.x();  << 1464       G4ThreeVector vertix5(fVertices[5].x(),fVertices[5].y(), fDz);
1083     G4double AD = A.x()*D.y() - A.y()*D.x();  << 1465       G4ThreeVector vertix6(fVertices[6].x(),fVertices[6].y(), fDz);
1084     G4double CB = C.x()*B.y() - C.y()*B.x();  << 1466       G4ThreeVector vertix7(fVertices[7].x(),fVertices[7].y(), fDz);
1085                                               << 1467 
1086     fCubicVolume = ((AB + CD)/3. + (AD + CB)/ << 1468       // Find Cubic Volume
                                                   >> 1469       fCubicVolume = GetFaceCubicVolume(vertix0,vertix1,vertix2,vertix3)  // -fDz plane
                                                   >> 1470                    + GetFaceCubicVolume(vertix1,vertix0,vertix4,vertix5)  //  Lat plane
                                                   >> 1471                    + GetFaceCubicVolume(vertix2,vertix1,vertix5,vertix6)  //  Lat plane 
                                                   >> 1472                    + GetFaceCubicVolume(vertix3,vertix2,vertix6,vertix7)  //  Lat plane
                                                   >> 1473                    + GetFaceCubicVolume(vertix0,vertix3,vertix7,vertix4)  //  Lat plane
                                                   >> 1474                    + GetFaceCubicVolume(vertix7,vertix6,vertix5,vertix4); // +fDz plane 
                                                   >> 1475     }
1087   }                                              1476   }
1088   return fCubicVolume;                           1477   return fCubicVolume;
1089 }                                                1478 }
1090                                                  1479 
1091 ///////////////////////////////////////////// << 1480 // --------------------------------------------------------------------
1092 //                                            << 1481 
1093 // Compute lateral face area                  << 1482 G4double G4GenericTrap::GetFaceSurfaceArea(const G4ThreeVector& p0,
1094 //                                            << 1483                                            const G4ThreeVector& p1, 
1095 G4double G4GenericTrap::GetLateralFaceArea(G4 << 1484                                            const G4ThreeVector& p2,
                                                   >> 1485                                            const G4ThreeVector& p3) const
1096 {                                                1486 {
1097   G4int i1 = iface, i2 = (i1 + 1)%4, i3 = i1  << 1487   // Returns area of the facet 
                                                   >> 1488   return (((p2-p0).cross(p3-p1)).mag()) / 2.;
                                                   >> 1489 }
1098                                                  1490 
1099   // plane face                               << 1491 // --------------------------------------------------------------------
1100   if (fTwist[iface] == 0.0)                   << 
1101   {                                           << 
1102     G4ThreeVector p1(fVertices[i1].x(), fVert << 
1103     G4ThreeVector p2(fVertices[i2].x(), fVert << 
1104     G4ThreeVector p3(fVertices[i3].x(), fVert << 
1105     G4ThreeVector p4(fVertices[i4].x(), fVert << 
1106     return ((p4 - p1).cross(p3 - p2)).mag()*0 << 
1107   }                                           << 
1108                                                  1492 
1109   // twisted face                             << 1493 G4double G4GenericTrap::GetFaceCubicVolume(const G4ThreeVector& p0,
1110   constexpr G4int NSTEP = 250;                << 1494                                            const G4ThreeVector& p1, 
1111   constexpr G4double dt = 1./NSTEP;           << 1495                                            const G4ThreeVector& p2,
                                                   >> 1496                                            const G4ThreeVector& p3) const
                                                   >> 1497 {
                                                   >> 1498   // Returns contribution of the facet to the volume of the solid.
                                                   >> 1499   // Orientation of the facet is important, normal should point to outside. 
                                                   >> 1500   return (((p2-p0).cross(p3-p1)).dot(p0)) / 6.;
                                                   >> 1501 }
1112                                                  1502 
1113   G4double x21 = fVertices[i2].x() - fVertice << 1503 // --------------------------------------------------------------------
1114   G4double y21 = fVertices[i2].y() - fVertice << 
1115   G4double x31 = fVertices[i3].x() - fVertice << 
1116   G4double y31 = fVertices[i3].y() - fVertice << 
1117   G4double x42 = fVertices[i4].x() - fVertice << 
1118   G4double y42 = fVertices[i4].y() - fVertice << 
1119   G4double x43 = fVertices[i4].x() - fVertice << 
1120   G4double y43 = fVertices[i4].y() - fVertice << 
1121                                                  1504 
1122   G4double A = x21*y43 - y21*x43;             << 1505 G4bool G4GenericTrap::ComputeIsTwisted() 
1123   G4double B0 = x21*y31 - y21*x31;            << 1506 {
1124   G4double B1 = x42*y31 - y42*x31;            << 1507   // Computes tangents of twist angles (angles between projections on XY plane 
1125   G4double HH = 4*fDz*fDz;                    << 1508   // of corresponding -dz +dz edges). 
1126   G4double invAA = 1./(A*A);                  << 
1127   G4double sqrtAA = 2.*std::abs(A);           << 
1128   G4double invSqrtAA = 1./sqrtAA;             << 
1129                                                  1509 
1130   G4double area = 0.;                         << 1510   G4bool twisted = false;
1131   for (G4int i = 0; i < NSTEP; ++i)           << 1511   G4double dx1, dy1, dx2, dy2;
                                                   >> 1512   G4int nv = fgkNofVertices/2;
                                                   >> 1513 
                                                   >> 1514   for ( G4int i=0; i<4; i++ )
1132   {                                              1515   {
1133     G4double t = (i + 0.5)*dt;                << 1516     dx1 = fVertices[(i+1)%nv].x()-fVertices[i].x();
1134     G4double I = y21 + (y43 - y21)*t;         << 1517     dy1 = fVertices[(i+1)%nv].y()-fVertices[i].y();
1135     G4double J = x21 + (x43 - x21)*t;         << 1518     if ( (dx1 == 0) && (dy1 == 0) ) { continue; }
1136     G4double IIJJ = HH*(I*I + J*J);           << 1519 
1137     G4double B = B1*t + B0;                   << 1520     dx2 = fVertices[nv+(i+1)%nv].x()-fVertices[nv+i].x();
                                                   >> 1521     dy2 = fVertices[nv+(i+1)%nv].y()-fVertices[nv+i].y();
1138                                                  1522 
1139     G4double aa = A*A;                        << 1523     if ( dx2 == 0 && dy2 == 0 ) { continue; }
1140     G4double bb = 2.*A*B;                     << 1524     G4double twist_angle = std::fabs(dy1*dx2 - dx1*dy2);        
1141     G4double cc = IIJJ + B*B;                 << 1525     if ( twist_angle < fgkTolerance ) { continue; }
                                                   >> 1526     twisted = true;
                                                   >> 1527     SetTwistAngle(i,twist_angle);
1142                                                  1528 
1143     G4double R1 = std::sqrt(aa + bb + cc);    << 1529     // Check on big angles, potentially navigation problem
1144     G4double R0 = std::sqrt(cc);              << 
1145     G4double log1 = std::log(std::abs(sqrtAA* << 
1146     G4double log0 = std::log(std::abs(sqrtAA* << 
1147                                                  1530 
1148     area += 0.5*R1 + 0.25*bb*invAA*(R1 - R0)  << 1531     twist_angle = std::acos( (dx1*dx2 + dy1*dy2)
                                                   >> 1532                            / (std::sqrt(dx1*dx1+dy1*dy1)
                                                   >> 1533                              * std::sqrt(dx2*dx2+dy2*dy2)) );
                                                   >> 1534    
                                                   >> 1535     if ( std::fabs(twist_angle) > 0.5*pi+kCarTolerance )
                                                   >> 1536     {
                                                   >> 1537       std::ostringstream message;
                                                   >> 1538       message << "Twisted Angle is bigger than 90 degrees - " << GetName()
                                                   >> 1539               << G4endl
                                                   >> 1540               << "     Potential problem of malformed Solid !" << G4endl
                                                   >> 1541               << "     TwistANGLE = " << twist_angle
                                                   >> 1542               << "*rad  for lateral plane N= " << i;
                                                   >> 1543       G4Exception("G4GenericTrap::ComputeIsTwisted()", "GeomSolids1002",
                                                   >> 1544                   JustWarning, message);
                                                   >> 1545     }
1149   }                                              1546   }
1150   return area*dt;                             << 1547 
                                                   >> 1548   return twisted;
1151 }                                                1549 }
1152                                                  1550 
1153 ///////////////////////////////////////////// << 1551 // --------------------------------------------------------------------
1154 //                                            << 1552 
1155 // Return surface area of the solid           << 1553 G4bool G4GenericTrap::CheckOrder(const std::vector<G4TwoVector>& vertices) const
1156 //                                            << 
1157 G4double G4GenericTrap::GetSurfaceArea()      << 
1158 {                                                1554 {
1159   if (fSurfaceArea == 0.0)                    << 1555   // Test if the vertices are in a clockwise order, if not reorder them.
                                                   >> 1556   // Also test if they're well defined without crossing opposite segments
                                                   >> 1557 
                                                   >> 1558   G4bool clockwise_order=true;
                                                   >> 1559   G4double sum1 = 0.;
                                                   >> 1560   G4double sum2 = 0.;
                                                   >> 1561   G4int j;
                                                   >> 1562 
                                                   >> 1563   for (G4int i=0; i<4; i++)
1160   {                                              1564   {
1161     G4TwoVector A = fVertices[3] - fVertices[ << 1565     j = (i+1)%4;
1162     G4TwoVector B = fVertices[2] - fVertices[ << 1566     sum1 += vertices[i].x()*vertices[j].y() - vertices[j].x()*vertices[i].y();
1163     G4TwoVector C = fVertices[7] - fVertices[ << 1567     sum2 += vertices[i+4].x()*vertices[j+4].y()
1164     G4TwoVector D = fVertices[6] - fVertices[ << 1568           - vertices[j+4].x()*vertices[i+4].y();
1165     G4double S_bot = (A.x()*B.y() - A.y()*B.x << 
1166     G4double S_top = (C.x()*D.y() - C.y()*D.x << 
1167     fArea[0] = GetLateralFaceArea(0);         << 
1168     fArea[1] = GetLateralFaceArea(1);         << 
1169     fArea[2] = GetLateralFaceArea(2);         << 
1170     fArea[3] = GetLateralFaceArea(3);         << 
1171     fSurfaceArea = S_bot + S_top + fArea[0] + << 
1172   }                                              1569   }
1173   return fSurfaceArea;                        << 1570   if (sum1*sum2 < -fgkTolerance)
                                                   >> 1571   {
                                                   >> 1572      std::ostringstream message;
                                                   >> 1573      message << "Lower/upper faces defined with opposite clockwise - "
                                                   >> 1574              << GetName();
                                                   >> 1575      G4Exception("G4GenericTrap::CheckOrder()", "GeomSolids0002",
                                                   >> 1576                 FatalException, message);
                                                   >> 1577    }
                                                   >> 1578    
                                                   >> 1579    if ((sum1 > 0.)||(sum2 > 0.))
                                                   >> 1580    {
                                                   >> 1581      std::ostringstream message;
                                                   >> 1582      message << "Vertices must be defined in clockwise XY planes - "
                                                   >> 1583              << GetName();
                                                   >> 1584      G4Exception("G4GenericTrap::CheckOrder()", "GeomSolids1001",
                                                   >> 1585                  JustWarning,message, "Re-ordering...");
                                                   >> 1586      clockwise_order = false;
                                                   >> 1587    }
                                                   >> 1588 
                                                   >> 1589    // Check for illegal crossings
                                                   >> 1590    //
                                                   >> 1591    G4bool illegal_cross = false;
                                                   >> 1592    illegal_cross = IsSegCrossingZ(vertices[0],vertices[4],
                                                   >> 1593                                   vertices[1],vertices[5]);
                                                   >> 1594      
                                                   >> 1595    if (!illegal_cross)
                                                   >> 1596    {
                                                   >> 1597      illegal_cross = IsSegCrossingZ(vertices[2],vertices[6],
                                                   >> 1598                                     vertices[3],vertices[7]);
                                                   >> 1599    }
                                                   >> 1600    // +/- dZ planes
                                                   >> 1601    if (!illegal_cross)
                                                   >> 1602    {
                                                   >> 1603      illegal_cross = IsSegCrossing(vertices[0],vertices[1],
                                                   >> 1604                                    vertices[2],vertices[3]);
                                                   >> 1605    }
                                                   >> 1606    if (!illegal_cross)
                                                   >> 1607    {
                                                   >> 1608      illegal_cross = IsSegCrossing(vertices[0],vertices[3],
                                                   >> 1609                                    vertices[1],vertices[2]);
                                                   >> 1610    }
                                                   >> 1611    if (!illegal_cross)
                                                   >> 1612    {
                                                   >> 1613      illegal_cross = IsSegCrossing(vertices[4],vertices[5],
                                                   >> 1614                                    vertices[6],vertices[7]);
                                                   >> 1615    }
                                                   >> 1616    if (!illegal_cross)
                                                   >> 1617    {
                                                   >> 1618      illegal_cross = IsSegCrossing(vertices[4],vertices[7],
                                                   >> 1619                                    vertices[5],vertices[6]);
                                                   >> 1620    }
                                                   >> 1621 
                                                   >> 1622    if (illegal_cross)
                                                   >> 1623    {
                                                   >> 1624       std::ostringstream message;
                                                   >> 1625       message << "Malformed polygone with opposite sides - " << GetName();
                                                   >> 1626       G4Exception("G4GenericTrap::CheckOrderAndSetup()",
                                                   >> 1627                   "GeomSolids0002", FatalException, message);
                                                   >> 1628    }
                                                   >> 1629    return clockwise_order;
1174 }                                                1630 }
1175                                                  1631 
1176 ///////////////////////////////////////////// << 1632 // --------------------------------------------------------------------
1177 //                                            << 1633 
1178 // Check parameters of the solid              << 1634 void G4GenericTrap::ReorderVertices(std::vector<G4ThreeVector>& vertices) const
1179 //                                            << 
1180 void                                          << 
1181 G4GenericTrap::CheckParameters(G4double halfZ << 
1182                                const std::vec << 
1183 {                                                1635 {
1184   // Check number of vertices                 << 1636   // Reorder the vector of vertices 
1185   //                                          << 1637 
1186   if (vertices.size() != 8)                   << 1638   std::vector<G4ThreeVector> oldVertices(vertices);
                                                   >> 1639 
                                                   >> 1640   for ( G4int i=0; i < G4int(oldVertices.size()); ++i )
1187   {                                              1641   {
1188     std::ostringstream message;               << 1642     vertices[i] = oldVertices[oldVertices.size()-1-i];
1189     message << "Number of vertices is " << ve << 1643   }  
1190             << " instead of 8 for Solid: " << << 1644 } 
1191     G4Exception("G4GenericTrap::CheckParamete << 1645  
1192                 FatalException, message);     << 1646 // --------------------------------------------------------------------
1193   }                                           << 
1194                                                  1647 
1195   // Check dZ                                 << 1648 G4bool
1196   //                                          << 1649 G4GenericTrap::IsSegCrossing(const G4TwoVector& a, const G4TwoVector& b, 
1197   if ((fDz = halfZ) < 2.*kCarTolerance)       << 1650                              const G4TwoVector& c, const G4TwoVector& d) const
                                                   >> 1651 { 
                                                   >> 1652   // Check if segments [A,B] and [C,D] are crossing
                                                   >> 1653 
                                                   >> 1654   G4bool stand1 = false;
                                                   >> 1655   G4bool stand2 = false;
                                                   >> 1656   G4double dx1,dx2,xm=0.,ym=0.,a1=0.,a2=0.,b1=0.,b2=0.;
                                                   >> 1657   dx1=(b-a).x();
                                                   >> 1658   dx2=(d-c).x();
                                                   >> 1659 
                                                   >> 1660   if( std::fabs(dx1) < fgkTolerance )  { stand1 = true; }
                                                   >> 1661   if( std::fabs(dx2) < fgkTolerance )  { stand2 = true; }
                                                   >> 1662   if (!stand1)
                                                   >> 1663   {
                                                   >> 1664     a1 = (b.x()*a.y()-a.x()*b.y())/dx1;
                                                   >> 1665     b1 = (b-a).y()/dx1;
                                                   >> 1666   }
                                                   >> 1667   if (!stand2)
                                                   >> 1668   {
                                                   >> 1669     a2 = (d.x()*c.y()-c.x()*d.y())/dx2;
                                                   >> 1670     b2 = (d-c).y()/dx2;
                                                   >> 1671   }   
                                                   >> 1672   if (stand1 && stand2)
                                                   >> 1673   {
                                                   >> 1674     // Segments parallel and vertical
                                                   >> 1675     //
                                                   >> 1676     if (std::fabs(a.x()-c.x())<fgkTolerance)
                                                   >> 1677     {
                                                   >> 1678        // Check if segments are overlapping
                                                   >> 1679        //
                                                   >> 1680        if ( ((c.y()-a.y())*(c.y()-b.y())<-fgkTolerance)
                                                   >> 1681          || ((d.y()-a.y())*(d.y()-b.y())<-fgkTolerance)
                                                   >> 1682          || ((a.y()-c.y())*(a.y()-d.y())<-fgkTolerance)
                                                   >> 1683          || ((b.y()-c.y())*(b.y()-d.y())<-fgkTolerance) )  { return true; }
                                                   >> 1684 
                                                   >> 1685        return false;
                                                   >> 1686     }
                                                   >> 1687     // Different x values
                                                   >> 1688     //
                                                   >> 1689     return false;
                                                   >> 1690   }
                                                   >> 1691    
                                                   >> 1692   if (stand1)    // First segment vertical
1198   {                                              1693   {
1199     std::ostringstream message;               << 1694     xm = a.x();
1200     message << "Z-dimension is too small or n << 1695     ym = a2+b2*xm; 
1201             << " for Solid: " << GetName() << << 1696   }
1202     G4Exception("G4GenericTrap::CheckParamete << 1697   else
1203                 FatalException, message);     << 1698   {
                                                   >> 1699     if (stand2)  // Second segment vertical
                                                   >> 1700     {
                                                   >> 1701       xm = c.x();
                                                   >> 1702       ym = a1+b1*xm;
                                                   >> 1703     }
                                                   >> 1704     else  // Normal crossing
                                                   >> 1705     {
                                                   >> 1706       if (std::fabs(b1-b2) < fgkTolerance)
                                                   >> 1707       {
                                                   >> 1708         // Parallel segments, are they aligned
                                                   >> 1709         //
                                                   >> 1710         if (std::fabs(c.y()-(a1+b1*c.x())) > fgkTolerance)  { return false; }
                                                   >> 1711 
                                                   >> 1712         // Aligned segments, are they overlapping
                                                   >> 1713         //
                                                   >> 1714         if ( ((c.x()-a.x())*(c.x()-b.x())<-fgkTolerance)
                                                   >> 1715           || ((d.x()-a.x())*(d.x()-b.x())<-fgkTolerance)
                                                   >> 1716           || ((a.x()-c.x())*(a.x()-d.x())<-fgkTolerance)
                                                   >> 1717           || ((b.x()-c.x())*(b.x()-d.x())<-fgkTolerance) )  { return true; }
                                                   >> 1718 
                                                   >> 1719         return false;
                                                   >> 1720       }
                                                   >> 1721       xm = (a1-a2)/(b2-b1);
                                                   >> 1722       ym = (a1*b2-a2*b1)/(b2-b1);
                                                   >> 1723     }
1204   }                                              1724   }
1205                                                  1725 
1206   // Check order of vertices                  << 1726   // Check if crossing point is both between A,B and C,D
                                                   >> 1727   //
                                                   >> 1728   G4double check = (xm-a.x())*(xm-b.x())+(ym-a.y())*(ym-b.y());
                                                   >> 1729   if (check > -fgkTolerance)  { return false; }
                                                   >> 1730   check = (xm-c.x())*(xm-d.x())+(ym-c.y())*(ym-d.y());
                                                   >> 1731   if (check > -fgkTolerance)  { return false; }
                                                   >> 1732 
                                                   >> 1733   return true;
                                                   >> 1734 }
                                                   >> 1735 
                                                   >> 1736 // --------------------------------------------------------------------
                                                   >> 1737 
                                                   >> 1738 G4bool
                                                   >> 1739 G4GenericTrap::IsSegCrossingZ(const G4TwoVector& a, const G4TwoVector& b, 
                                                   >> 1740                               const G4TwoVector& c, const G4TwoVector& d) const
                                                   >> 1741 { 
                                                   >> 1742   // Check if segments [A,B] and [C,D] are crossing when
                                                   >> 1743   // A and C are on -dZ and B and D are on +dZ
                                                   >> 1744 
                                                   >> 1745   // Calculate the Intersection point between two lines in 3D
                                                   >> 1746   //
                                                   >> 1747   G4ThreeVector temp1,temp2;
                                                   >> 1748   G4ThreeVector v1,v2,p1,p2,p3,p4,dv;
                                                   >> 1749   G4double q,det;
                                                   >> 1750   p1=G4ThreeVector(a.x(),a.y(),-fDz);
                                                   >> 1751   p2=G4ThreeVector(c.x(),c.y(),-fDz);
                                                   >> 1752   p3=G4ThreeVector(b.x(),b.y(),fDz);
                                                   >> 1753   p4=G4ThreeVector(d.x(),d.y(),fDz);
                                                   >> 1754   v1=p3-p1;
                                                   >> 1755   v2=p4-p2;
                                                   >> 1756   dv=p2-p1;
                                                   >> 1757 
                                                   >> 1758   // In case of Collapsed Vertices No crossing
                                                   >> 1759   //
                                                   >> 1760   if( (std::fabs(dv.x()) < kCarTolerance )&&
                                                   >> 1761       (std::fabs(dv.y()) < kCarTolerance ) )  { return false; }
                                                   >> 1762     
                                                   >> 1763   if( (std::fabs((p4-p3).x()) < kCarTolerance )&&
                                                   >> 1764       (std::fabs((p4-p3).y()) < kCarTolerance ) )  { return false; }
                                                   >> 1765  
                                                   >> 1766   // First estimate if Intersection is possible( if det is 0)
1207   //                                             1767   //
1208   for (auto i = 0; i < 8; ++i) { fVertices.at << 1768   det = dv.x()*v1.y()*v2.z()+dv.y()*v1.z()*v2.x()
                                                   >> 1769       - dv.x()*v1.z()*v2.y()-dv.y()*v1.x()*v2.z();
                                                   >> 1770    
                                                   >> 1771   if (std::fabs(det)<kCarTolerance)  //Intersection
                                                   >> 1772   {
                                                   >> 1773     temp1 = v1.cross(v2);
                                                   >> 1774     temp2 = (p2-p1).cross(v2);
                                                   >> 1775     if (temp1.dot(temp2) < 0)  { return false; } // intersection negative
                                                   >> 1776     q = temp1.mag();
                                                   >> 1777 
                                                   >> 1778     if ( q < kCarTolerance )  { return false; }  // parallel lines
                                                   >> 1779     q = ((dv).cross(v2)).mag()/q;
                                                   >> 1780    
                                                   >> 1781     if(q < 1.-kCarTolerance)  { return true; }
                                                   >> 1782   }
                                                   >> 1783   return false;
                                                   >> 1784 }
                                                   >> 1785 
                                                   >> 1786 // --------------------------------------------------------------------
1209                                                  1787 
1210   // Bottom polygon area                      << 1788 G4VFacet*
1211   G4TwoVector diag1 = fVertices[2] - fVertice << 1789 G4GenericTrap::MakeDownFacet(const std::vector<G4ThreeVector>& fromVertices, 
1212   G4TwoVector diag2 = fVertices[3] - fVertice << 1790                              G4int ind1, G4int ind2, G4int ind3) const 
1213   G4double ldiagbot = std::max(diag1.mag(), d << 1791 {
1214   G4double zbot = diag1.x()*diag2.y() - diag1 << 1792   // Create a triangular facet from the polygon points given by indices
1215   if (std::abs(zbot) < ldiagbot*kCarTolerance << 1793   // forming the down side ( the normal goes in -z)
1216                                               << 1794   // Do not create facet if 2 vertices are the same
1217   // Top polygon area                         << 1795 
1218   G4TwoVector diag3 = fVertices[6] - fVertice << 1796   if ( (fromVertices[ind1] == fromVertices[ind2]) ||
1219   G4TwoVector diag4 = fVertices[7] - fVertice << 1797        (fromVertices[ind2] == fromVertices[ind3]) ||
1220   G4double ldiagtop = std::max(diag3.mag(), d << 1798        (fromVertices[ind1] == fromVertices[ind3]) )  { return 0; }
1221   G4double ztop = diag3.x()*diag4.y() - diag3 << 1799 
1222   if (std::abs(ztop) < ldiagtop*kCarTolerance << 1800   std::vector<G4ThreeVector> vertices;
                                                   >> 1801   vertices.push_back(fromVertices[ind1]);
                                                   >> 1802   vertices.push_back(fromVertices[ind2]);
                                                   >> 1803   vertices.push_back(fromVertices[ind3]);
                                                   >> 1804   
                                                   >> 1805   // first vertex most left
                                                   >> 1806   //
                                                   >> 1807   G4ThreeVector cross=(vertices[1]-vertices[0]).cross(vertices[2]-vertices[1]);
1223                                                  1808 
1224   if (zbot*ztop < 0.)                         << 1809   if ( cross.z() > 0.0 )
1225   {                                              1810   {
                                                   >> 1811     // Should not happen, as vertices should have been reordered at this stage
                                                   >> 1812 
1226     std::ostringstream message;                  1813     std::ostringstream message;
1227     message << "Vertices of the bottom and to << 1814     message << "Vertices in wrong order - " << GetName();
1228     StreamInfo(message);                      << 1815     G4Exception("G4GenericTrap::MakeDownFacet", "GeomSolids0002",
1229     G4Exception("G4GenericTrap::CheckParamete << 
1230                 FatalException, message);        1816                 FatalException, message);
1231   }                                              1817   }
1232   if ((zbot > 0.) || (ztop > 0.))             << 1818   
1233   {                                           << 1819   return new G4TriangularFacet(vertices[0], vertices[1], vertices[2], ABSOLUTE);
1234     std::swap(fVertices[1], fVertices[3]);    << 1820 }
1235     std::swap(fVertices[5], fVertices[7]);    << 1821 
1236     std::ostringstream message;               << 1822 // --------------------------------------------------------------------
1237     message << "Vertices re-ordered in Solid: << 
1238             << "Vertices of the bottom and to << 
1239     G4Exception("G4GenericTrap::CheckParamete << 
1240                 JustWarning, message);        << 
1241    }                                          << 
1242                                                  1823 
1243   // Check for degeneracy                     << 1824 G4VFacet*
                                                   >> 1825 G4GenericTrap::MakeUpFacet(const std::vector<G4ThreeVector>& fromVertices, 
                                                   >> 1826                            G4int ind1, G4int ind2, G4int ind3) const     
                                                   >> 1827 {
                                                   >> 1828   // Create a triangular facet from the polygon points given by indices
                                                   >> 1829   // forming the upper side ( z>0 )
                                                   >> 1830 
                                                   >> 1831   // Do not create facet if 2 vertices are the same
1244   //                                             1832   //
1245   G4int ndegenerated = 0;                     << 1833   if ( (fromVertices[ind1] == fromVertices[ind2]) ||
1246   for (auto i = 0; i < 4; ++i)                << 1834        (fromVertices[ind2] == fromVertices[ind3]) ||
1247   {                                           << 1835        (fromVertices[ind1] == fromVertices[ind3]) )  { return 0; }
1248     auto j = (i + 1)%4;                       << 1836 
1249     G4double lbot = (fVertices[j] - fVertices << 1837   std::vector<G4ThreeVector> vertices;
1250     G4double ltop = (fVertices[j + 4] - fVert << 1838   vertices.push_back(fromVertices[ind1]);
1251     ndegenerated += (std::max(lbot, ltop) < k << 1839   vertices.push_back(fromVertices[ind2]);
1252   }                                           << 1840   vertices.push_back(fromVertices[ind3]);
1253   if (ndegenerated > 1 ||                     << 1841   
1254       GetCubicVolume() < fDz*std::max(ldiagbo << 1842   // First vertex most left
                                                   >> 1843   //
                                                   >> 1844   G4ThreeVector cross=(vertices[1]-vertices[0]).cross(vertices[2]-vertices[1]);
                                                   >> 1845 
                                                   >> 1846   if ( cross.z() < 0.0 )
1255   {                                              1847   {
                                                   >> 1848     // Should not happen, as vertices should have been reordered at this stage
                                                   >> 1849 
1256     std::ostringstream message;                  1850     std::ostringstream message;
1257     message << "Degenerated solid !\n";       << 1851     message << "Vertices in wrong order - " << GetName();
1258     StreamInfo(message);                      << 1852     G4Exception("G4GenericTrap::MakeUpFacet", "GeomSolids0002",
1259     G4Exception("G4GenericTrap::CheckParamete << 
1260                 FatalException, message);        1853                 FatalException, message);
1261   }                                              1854   }
                                                   >> 1855   
                                                   >> 1856   return new G4TriangularFacet(vertices[0], vertices[1], vertices[2], ABSOLUTE);
                                                   >> 1857 }      
1262                                                  1858 
1263   // Check that the polygons are convex       << 1859 // --------------------------------------------------------------------
1264   //                                          << 1860 
1265   G4bool isConvex = true;                     << 1861 G4VFacet*
1266   for (auto i = 0; i < 4; ++i)                << 1862 G4GenericTrap::MakeSideFacet(const G4ThreeVector& downVertex0,
                                                   >> 1863                              const G4ThreeVector& downVertex1,
                                                   >> 1864                              const G4ThreeVector& upVertex1,
                                                   >> 1865                              const G4ThreeVector& upVertex0) const      
                                                   >> 1866 {
                                                   >> 1867   // Creates a triangular facet from the polygon points given by indices
                                                   >> 1868   // forming the upper side ( z>0 )
                                                   >> 1869 
                                                   >> 1870   if ( (downVertex0 == downVertex1) && (upVertex0 == upVertex1) )
1267   {                                              1871   {
1268     auto j = (i + 1)%4;                       << 1872     return 0;
1269     auto k = (j + 1)%4;                       << 
1270     G4TwoVector edge1 = fVertices[j] - fVerti << 
1271     G4TwoVector edge2 = fVertices[k] - fVerti << 
1272     isConvex = ((edge1.x()*edge2.y() - edge1. << 
1273     if (!isConvex) break;                     << 
1274     G4TwoVector edge3 = fVertices[j + 4] - fV << 
1275     G4TwoVector edge4 = fVertices[k + 4] - fV << 
1276     isConvex = ((edge3.x()*edge4.y() - edge3. << 
1277     if (!isConvex) break;                     << 
1278   }                                              1873   }
1279   if (!isConvex)                              << 1874 
                                                   >> 1875   if ( downVertex0 == downVertex1 )
1280   {                                              1876   {
1281     std::ostringstream message;               << 1877     return new G4TriangularFacet(downVertex0, upVertex1, upVertex0, ABSOLUTE);
1282     message << "The bottom and top faces must << 
1283     StreamInfo(message);                      << 
1284     G4Exception("G4GenericTrap::CheckParamete << 
1285                 FatalException, message);     << 
1286   }                                              1878   }
1287 }                                             << 
1288                                                  1879 
1289 ///////////////////////////////////////////// << 1880   if ( upVertex0 == upVertex1 )
1290 //                                            << 
1291 // Compute surface equations and twist angles << 
1292 //                                            << 
1293 void G4GenericTrap::ComputeLateralSurfaces()  << 
1294 {                                             << 
1295   for (auto i = 0; i < 4; ++i)                << 
1296   {                                              1881   {
1297     auto j = (i + 1)%4;                       << 1882     return new G4TriangularFacet(downVertex0, downVertex1, upVertex0, ABSOLUTE);
1298     G4ThreeVector p1(fVertices[j].x(), fVerti << 
1299     G4ThreeVector p2(fVertices[i].x(), fVerti << 
1300     G4ThreeVector p3(fVertices[j + 4].x(), fV << 
1301     G4ThreeVector p4(fVertices[i + 4].x(), fV << 
1302     G4ThreeVector ebot = p2 - p1;             << 
1303     G4ThreeVector etop = p4 - p3;             << 
1304     G4double lbot = ebot.mag();               << 
1305     G4double ltop = etop.mag();               << 
1306     G4double zcross = ebot.x()*etop.y() - ebo << 
1307     G4double eps = kCarTolerance*std::max(lbo << 
1308     if (std::min(lbot, ltop) < kCarTolerance  << 
1309     { // plane surface: Dx + Ey + Fz + G = 0  << 
1310       G4ThreeVector normal;                   << 
1311       if (std::max(lbot, ltop) < kCarToleranc << 
1312       {                                       << 
1313         auto k = (j + 1)%4;                   << 
1314         auto l = (k + 1)%4;                   << 
1315         G4TwoVector vl = fVertices[l] + fVert << 
1316         G4TwoVector vi = fVertices[i] + fVert << 
1317         G4TwoVector vj = fVertices[j] + fVert << 
1318         G4TwoVector vk = fVertices[k] + fVert << 
1319         G4TwoVector vij = (vi - vl).unit() +  << 
1320         G4ThreeVector epar = (p4 + p3 - p2 -  << 
1321         G4ThreeVector eort = epar.cross(G4Thr << 
1322         normal = (eort.cross(epar)).unit();   << 
1323       }                                       << 
1324       else                                    << 
1325       {                                       << 
1326         normal = ((p4 - p1).cross(p3 - p2)).u << 
1327       }                                       << 
1328       fSurf[i].D = fPlane[2*i].A = fPlane[2*i << 
1329       fSurf[i].E = fPlane[2*i].B = fPlane[2*i << 
1330       fSurf[i].F = fPlane[2*i].C = fPlane[2*i << 
1331       fSurf[i].G = fPlane[2*i].D = fPlane[2*i << 
1332     }                                         << 
1333     else                                      << 
1334     { // hyperbolic paraboloid: Axz + Byz + C << 
1335       fIsTwisted = true;                      << 
1336       G4double angle = std::acos(ebot.dot(eto << 
1337       if (angle > CLHEP::halfpi)              << 
1338       {                                       << 
1339         std::ostringstream message;           << 
1340         message << "Twist on " << angle/CLHEP << 
1341                 << " degrees, should not be m << 
1342         StreamInfo(message);                  << 
1343         G4Exception("G4GenericTrap::ComputeLa << 
1344                     FatalException, message); << 
1345       }                                       << 
1346       fTwist[i] = std::copysign(angle, zcross << 
1347       // set equation of twisted surface (hyp << 
1348       fSurf[i].A = 2.*fDz*(p4.y() - p3.y() -  << 
1349       fSurf[i].B =-2.*fDz*(p4.x() - p3.x() -  << 
1350       fSurf[i].C = ((p4.x() - p2.x())*(p3.y() << 
1351       fSurf[i].D = 2.*fDz*fDz*(p4.y() - p3.y( << 
1352       fSurf[i].E =-2.*fDz*fDz*(p4.x() - p3.x( << 
1353       fSurf[i].F = 2.*fDz*(p4.x()*p3.y() - p3 << 
1354       fSurf[i].G = fDz*fDz*((p4.x() + p2.x()) << 
1355       G4double magnitude =  G4ThreeVector(fSu << 
1356       if (magnitude < kCarTolerance) continue << 
1357       fSurf[i].A /= magnitude;                << 
1358       fSurf[i].B /= magnitude;                << 
1359       fSurf[i].C /= magnitude;                << 
1360       fSurf[i].D /= magnitude;                << 
1361       fSurf[i].E /= magnitude;                << 
1362       fSurf[i].F /= magnitude;                << 
1363       fSurf[i].G /= magnitude;                << 
1364       // set planes of bounding polyhedron    << 
1365       G4ThreeVector normal1, normal2;         << 
1366       G4ThreeVector c1, c2;                   << 
1367       if (fTwist[i] < 0.)                     << 
1368       {                                       << 
1369         normal1 = ((p2 - p1).cross(p4 - p1)). << 
1370         normal2 = ((p3 - p4).cross(p1 - p4)). << 
1371         c1 = p1;                              << 
1372         c2 = p4;                              << 
1373       }                                       << 
1374       else                                    << 
1375       {                                       << 
1376         normal1 = ((p3 - p2).cross(p1 - p2)). << 
1377         normal2 = ((p2 - p3).cross(p4 - p3)). << 
1378         c1 = p2;                              << 
1379         c2 = p3;                              << 
1380       }                                       << 
1381       fPlane[2*i].A = normal1.x();            << 
1382       fPlane[2*i].B = normal1.y();            << 
1383       fPlane[2*i].C = normal1.z();            << 
1384       fPlane[2*i].D = -normal1.dot(c1);       << 
1385       fPlane[2*i + 1].A = normal2.x();        << 
1386       fPlane[2*i + 1].B = normal2.y();        << 
1387       fPlane[2*i + 1].C = normal2.z();        << 
1388       fPlane[2*i + 1].D = -normal2.dot(c2);   << 
1389     }                                         << 
1390     fDelta[i] = (fVertices[i + 4] - fVertices << 
1391   }                                              1883   }
1392 }                                             << 
1393                                                  1884 
1394 ///////////////////////////////////////////// << 1885   return new G4QuadrangularFacet(downVertex0, downVertex1, 
1395 //                                            << 1886                                  upVertex1, upVertex0, ABSOLUTE);   
1396 // Set bounding box                           << 1887 }    
1397 //                                            << 1888 
1398 void G4GenericTrap::ComputeBoundingBox()      << 1889 // --------------------------------------------------------------------
                                                   >> 1890 
                                                   >> 1891 G4TessellatedSolid* G4GenericTrap::CreateTessellatedSolid() const
1399 {                                                1892 {
1400   G4double minX, maxX, minY, maxY;            << 1893   // 3D vertices
1401   minX = maxX = fVertices[0].x();             << 1894   //
1402   minY = maxY = fVertices[0].y();             << 1895   G4int nv = fgkNofVertices/2;
1403   for (auto i = 1; i < 8; ++i)                << 1896   std::vector<G4ThreeVector> downVertices;
1404   {                                           << 1897   for ( G4int i=0; i<nv; i++ )
1405     minX = std::min(minX, fVertices[i].x());  << 1898   { 
1406     maxX = std::max(maxX, fVertices[i].x());  << 1899     downVertices.push_back(G4ThreeVector(fVertices[i].x(),
1407     minY = std::min(minY, fVertices[i].y());  << 1900                                          fVertices[i].y(), -fDz));
1408     maxY = std::max(maxY, fVertices[i].y());  << 1901   }
                                                   >> 1902 
                                                   >> 1903   std::vector<G4ThreeVector> upVertices;
                                                   >> 1904   for ( G4int i=nv; i<2*nv; i++ )
                                                   >> 1905   { 
                                                   >> 1906     upVertices.push_back(G4ThreeVector(fVertices[i].x(),
                                                   >> 1907                                        fVertices[i].y(), fDz));
1409   }                                              1908   }
1410   fMinBBox = G4ThreeVector(minX, minY,-fDz);  << 1909                                          
1411   fMaxBBox = G4ThreeVector(maxX, maxY, fDz);  << 1910   // Reorder vertices if they are not ordered anti-clock wise
                                                   >> 1911   //
                                                   >> 1912   G4ThreeVector cross 
                                                   >> 1913     = (downVertices[1]-downVertices[0]).cross(downVertices[2]-downVertices[1]);
                                                   >> 1914    G4ThreeVector cross1 
                                                   >> 1915     = (upVertices[1]-upVertices[0]).cross(upVertices[2]-upVertices[1]);
                                                   >> 1916   if ( (cross.z() > 0.0) || (cross1.z() > 0.0) )
                                                   >> 1917   {
                                                   >> 1918     ReorderVertices(downVertices);
                                                   >> 1919     ReorderVertices(upVertices);
                                                   >> 1920   }
                                                   >> 1921     
                                                   >> 1922   G4TessellatedSolid* tessellatedSolid = new G4TessellatedSolid(GetName());
                                                   >> 1923   
                                                   >> 1924   G4VFacet* facet = 0;
                                                   >> 1925   facet = MakeDownFacet(downVertices, 0, 1, 2);
                                                   >> 1926   if (facet)  { tessellatedSolid->AddFacet( facet ); }
                                                   >> 1927   facet = MakeDownFacet(downVertices, 0, 2, 3);
                                                   >> 1928   if (facet)  { tessellatedSolid->AddFacet( facet ); }
                                                   >> 1929   facet = MakeUpFacet(upVertices, 0, 2, 1);
                                                   >> 1930   if (facet)  { tessellatedSolid->AddFacet( facet ); }
                                                   >> 1931   facet = MakeUpFacet(upVertices, 0, 3, 2);
                                                   >> 1932   if (facet)  { tessellatedSolid->AddFacet( facet ); }
1412                                                  1933 
1413   // Check correctness of the bounding box    << 1934   // The quadrangular sides
1414   //                                             1935   //
1415   if (minX >= maxX || minY >= maxY || -fDz >= << 1936   for ( G4int i = 0; i < nv; ++i )
1416   {                                              1937   {
1417     std::ostringstream message;               << 1938     G4int j = (i+1) % nv;
1418     message << "Bad bounding box (min >= max) << 1939     facet = MakeSideFacet(downVertices[j], downVertices[i], 
1419             << GetName() << " !"              << 1940                           upVertices[i], upVertices[j]);
1420             << "\npMin = " << fMinBBox        << 1941 
1421             << "\npMax = " << fMaxBBox;       << 1942     if ( facet )  { tessellatedSolid->AddFacet( facet ); }
1422     G4Exception("G4GenericTrap::ComputeBoundi << 
1423                 JustWarning, message);        << 
1424     DumpInfo();                               << 
1425   }                                              1943   }
1426 }                                             << 
1427                                                  1944 
1428 ///////////////////////////////////////////// << 1945   tessellatedSolid->SetSolidClosed(true);
1429 //                                            << 1946 
1430 // Set max length of a scratch                << 1947   return tessellatedSolid;
1431 //                                            << 1948 }  
1432 void G4GenericTrap::ComputeScratchLength()    << 1949 
                                                   >> 1950 // --------------------------------------------------------------------
                                                   >> 1951 
                                                   >> 1952 void G4GenericTrap::ComputeBBox() 
1433 {                                                1953 {
1434   G4double scratch = kInfinity;               << 1954   // Computes bounding box for a shape.
1435   for (auto i = 0; i < 4; ++i)                << 1955 
                                                   >> 1956   G4double minX, maxX, minY, maxY;
                                                   >> 1957   minX = maxX = fVertices[0].x();
                                                   >> 1958   minY = maxY = fVertices[0].y();
                                                   >> 1959    
                                                   >> 1960   for (G4int i=1; i< fgkNofVertices; i++)
1436   {                                              1961   {
1437     if (fTwist[i] == 0.) continue; // skip pl << 1962     if (minX>fVertices[i].x()) { minX=fVertices[i].x(); }
1438     auto k = (i + 1)%4;                       << 1963     if (maxX<fVertices[i].x()) { maxX=fVertices[i].x(); }
1439     G4ThreeVector p1(fVertices[i].x(), fVerti << 1964     if (minY>fVertices[i].y()) { minY=fVertices[i].y(); }
1440     G4ThreeVector p2(fVertices[k].x(), fVerti << 1965     if (maxY<fVertices[i].y()) { maxY=fVertices[i].y(); }
1441     G4ThreeVector p3(fVertices[i + 4].x(), fV << 
1442     G4ThreeVector p4(fVertices[k + 4].x(), fV << 
1443     G4ThreeVector p0 = (p1 + p2 + p3 + p4)*0. << 
1444     G4ThreeVector norm = SurfaceNormal(p0);   << 
1445     G4ThreeVector pp[2]; // points inside and << 
1446     pp[0] = p0 - norm * halfTolerance;        << 
1447     pp[1] = p0 + norm * halfTolerance;        << 
1448     G4ThreeVector vv[2]; // unit vectors alon << 
1449     vv[0] = (p4 - p1).unit();                 << 
1450     vv[1] = (p3 - p2).unit();                 << 
1451     // find intersection points and compute t << 
1452     for (auto ip = 0; ip < 2; ++ip)           << 
1453     {                                         << 
1454       G4double px = pp[ip].x();               << 
1455       G4double py = pp[ip].y();               << 
1456       G4double pz = pp[ip].z();               << 
1457       for (auto iv = 0; iv < 2; ++iv)         << 
1458       {                                       << 
1459         G4double vx = vv[iv].x();             << 
1460         G4double vy = vv[iv].y();             << 
1461         G4double vz = vv[iv].z();             << 
1462         // solve quadratic equation           << 
1463         G4double ABC  = fSurf[i].A*vx + fSurf << 
1464         G4double ABCF = fSurf[i].A*px + fSurf << 
1465         G4double A = ABC*vz;                  << 
1466         G4double B = 0.5*(fSurf[i].D*vx + fSu << 
1467         G4double C = fSurf[i].D*px + fSurf[i] << 
1468         G4double D = B*B - A*C;               << 
1469         if (D < 0) continue;                  << 
1470         G4double leng = 2.*std::sqrt(D)/std:: << 
1471         scratch = std::min(leng, scratch);    << 
1472       }                                       << 
1473     }                                         << 
1474   }                                              1966   }
1475   fScratch = std::max(kCarTolerance, scratch) << 1967   fMinBBoxVector = G4ThreeVector(minX,minY,-fDz);
                                                   >> 1968   fMaxBBoxVector = G4ThreeVector(maxX,maxY, fDz);
1476 }                                                1969 }
1477                                                  1970 
1478 ///////////////////////////////////////////// << 1971 // --------------------------------------------------------------------
1479 //                                            << 1972 
1480 // GetPolyhedron                              << 
1481 //                                            << 
1482 G4Polyhedron* G4GenericTrap::GetPolyhedron ()    1973 G4Polyhedron* G4GenericTrap::GetPolyhedron () const
1483 {                                                1974 {
1484   if ( (fpPolyhedron == nullptr)              << 1975 
                                                   >> 1976 #ifdef G4TESS_TEST
                                                   >> 1977   if ( fTessellatedSolid )
                                                   >> 1978   { 
                                                   >> 1979     return fTessellatedSolid->GetPolyhedron();
                                                   >> 1980   }
                                                   >> 1981 #endif  
                                                   >> 1982   
                                                   >> 1983   if ( (!fpPolyhedron)
1485     || fRebuildPolyhedron                        1984     || fRebuildPolyhedron
1486     || (fpPolyhedron->GetNumberOfRotationStep    1985     || (fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
1487         fpPolyhedron->GetNumberOfRotationStep    1986         fpPolyhedron->GetNumberOfRotationSteps()) )
1488   {                                              1987   {
1489     G4AutoLock l(&polyhedronMutex);              1988     G4AutoLock l(&polyhedronMutex);
1490     delete fpPolyhedron;                         1989     delete fpPolyhedron;
1491     fpPolyhedron = CreatePolyhedron();           1990     fpPolyhedron = CreatePolyhedron();
1492     fRebuildPolyhedron = false;                  1991     fRebuildPolyhedron = false;
1493     l.unlock();                                  1992     l.unlock();
1494   }                                              1993   }
1495   return fpPolyhedron;                           1994   return fpPolyhedron;
1496 }                                             << 1995 }    
                                                   >> 1996 
                                                   >> 1997 // --------------------------------------------------------------------
1497                                                  1998 
1498 ///////////////////////////////////////////// << 
1499 //                                            << 
1500 // Method for visualisation                   << 
1501 //                                            << 
1502 void G4GenericTrap::DescribeYourselfTo(G4VGra    1999 void G4GenericTrap::DescribeYourselfTo(G4VGraphicsScene& scene) const
1503 {                                                2000 {
                                                   >> 2001 
                                                   >> 2002 #ifdef G4TESS_TEST
                                                   >> 2003   if ( fTessellatedSolid )
                                                   >> 2004   { 
                                                   >> 2005     return fTessellatedSolid->DescribeYourselfTo(scene);
                                                   >> 2006   }
                                                   >> 2007 #endif  
                                                   >> 2008   
1504   scene.AddSolid(*this);                         2009   scene.AddSolid(*this);
1505 }                                                2010 }
1506                                                  2011 
1507 ///////////////////////////////////////////// << 2012 // --------------------------------------------------------------------
1508 //                                            << 2013 
1509 // Return VisExtent                           << 
1510 //                                            << 
1511 G4VisExtent G4GenericTrap::GetExtent() const     2014 G4VisExtent G4GenericTrap::GetExtent() const
1512 {                                                2015 {
1513   return { fMinBBox.x(), fMaxBBox.x(),        << 2016   // Computes bounding vectors for the shape
1514            fMinBBox.y(), fMaxBBox.y(),        << 2017 
1515            fMinBBox.z(), fMaxBBox.z() };      << 2018 #ifdef G4TESS_TEST
1516 }                                             << 2019   if ( fTessellatedSolid )
                                                   >> 2020   { 
                                                   >> 2021     return fTessellatedSolid->GetExtent();
                                                   >> 2022   } 
                                                   >> 2023 #endif
                                                   >> 2024    
                                                   >> 2025   G4ThreeVector minVec = GetMinimumBBox();
                                                   >> 2026   G4ThreeVector maxVec = GetMaximumBBox();
                                                   >> 2027   return G4VisExtent (minVec.x(), maxVec.x(),
                                                   >> 2028                       minVec.y(), maxVec.y(),
                                                   >> 2029                       minVec.z(), maxVec.z()); 
                                                   >> 2030 }    
1517                                                  2031 
1518 // ------------------------------------------    2032 // --------------------------------------------------------------------
1519                                                  2033 
1520 G4Polyhedron* G4GenericTrap::CreatePolyhedron    2034 G4Polyhedron* G4GenericTrap::CreatePolyhedron() const
1521 {                                                2035 {
                                                   >> 2036 
                                                   >> 2037 #ifdef G4TESS_TEST
                                                   >> 2038   if ( fTessellatedSolid )
                                                   >> 2039   { 
                                                   >> 2040     return fTessellatedSolid->CreatePolyhedron();
                                                   >> 2041   }  
                                                   >> 2042 #endif 
                                                   >> 2043   
1522   // Approximation of Twisted Side               2044   // Approximation of Twisted Side
1523   // Construct extra Points, if Twisted Side     2045   // Construct extra Points, if Twisted Side
1524   //                                             2046   //
1525   G4Polyhedron* polyhedron;                   << 2047   G4PolyhedronArbitrary* polyhedron;
1526   G4int nVertices, nFacets;                   << 2048   size_t nVertices, nFacets;
1527                                                  2049 
1528   G4int subdivisions = 0;                     << 2050   G4int subdivisions=0;
1529   if (fIsTwisted)                             << 2051   G4int i;
                                                   >> 2052   if(fIsTwisted)
1530   {                                              2053   {
1531     if (GetVisSubdivisions() != 0)            << 2054     if ( GetVisSubdivisions()!= 0 )
1532     {                                            2055     {
1533       subdivisions = GetVisSubdivisions();    << 2056       subdivisions=GetVisSubdivisions();
1534     }                                            2057     }
1535     else                                         2058     else
1536     {                                            2059     {
1537       // Estimation of Number of Subdivisions    2060       // Estimation of Number of Subdivisions for smooth visualisation
1538       //                                         2061       //
1539       G4double maxTwist = 0.;                 << 2062       G4double maxTwist=0.;
1540       for(G4int i = 0; i < 4; ++i)            << 2063       for(i=0; i<4; i++)
1541       {                                          2064       {
1542         if (GetTwistAngle(i) > maxTwist) { ma << 2065         if(GetTwistAngle(i)>maxTwist) { maxTwist=GetTwistAngle(i); }
1543       }                                          2066       }
1544                                                  2067 
1545       // Computes bounding vectors for the sh    2068       // Computes bounding vectors for the shape
1546       //                                         2069       //
1547       G4double Dx, Dy;                        << 2070       G4double Dx,Dy;
1548       Dx = 0.5*(fMaxBBox.x() - fMinBBox.y()); << 2071       G4ThreeVector minVec = GetMinimumBBox();
1549       Dy = 0.5*(fMaxBBox.y() - fMinBBox.y()); << 2072       G4ThreeVector maxVec = GetMaximumBBox();
1550       if (Dy > Dx) { Dx = Dy; }               << 2073       Dx = 0.5*(maxVec.x()- minVec.y());
                                                   >> 2074       Dy = 0.5*(maxVec.y()- minVec.y());
                                                   >> 2075       if (Dy > Dx)  { Dx=Dy; }
                                                   >> 2076     
                                                   >> 2077       subdivisions=8*G4int(maxTwist/(Dx*Dx*Dx)*fDz);
                                                   >> 2078       if (subdivisions<4)  { subdivisions=4; }
                                                   >> 2079       if (subdivisions>30) { subdivisions=30; }
                                                   >> 2080     }
                                                   >> 2081   }
                                                   >> 2082   G4int sub4=4*subdivisions;
                                                   >> 2083   nVertices = 8+subdivisions*4;
                                                   >> 2084   nFacets = 6+subdivisions*4;
                                                   >> 2085   G4double cf=1./(subdivisions+1);
                                                   >> 2086   polyhedron = new G4PolyhedronArbitrary (nVertices, nFacets);
1551                                                  2087 
1552       subdivisions = 8*G4int(maxTwist/(Dx*Dx* << 2088   // Add Vertex
1553       if (subdivisions < 4)  { subdivisions = << 
1554       if (subdivisions > 30) { subdivisions = << 
1555     }                                         << 
1556   }                                           << 
1557   G4int sub4 = 4*subdivisions;                << 
1558   nVertices = 8 + subdivisions*4;             << 
1559   nFacets = 6 + subdivisions*4;               << 
1560   G4double cf = 1./(subdivisions + 1);        << 
1561   polyhedron = new G4Polyhedron(nVertices, nF << 
1562                                               << 
1563   // Set vertices                             << 
1564   //                                             2089   //
1565   G4int icur = 0;                             << 2090   for (i=0;i<4;i++)
1566   for (G4int i = 0; i < 4; ++i)               << 
1567   {                                              2091   {
1568     G4ThreeVector v(fVertices[i].x(),fVertice << 2092     polyhedron->AddVertex(G4ThreeVector(fVertices[i].x(),
1569     polyhedron->SetVertex(++icur, v);         << 2093                                         fVertices[i].y(),-fDz));
1570   }                                              2094   }
1571   for (G4int i = 0; i < subdivisions; ++i)    << 2095   for( i=0;i<subdivisions;i++)
1572   {                                              2096   {
1573     for (G4int j = 0; j < 4; ++j)             << 2097     for(G4int j=0;j<4;j++)
1574     {                                            2098     {
1575       G4TwoVector u = fVertices[j]+cf*(i+1)*( << 2099       G4TwoVector u=fVertices[j]+cf*(i+1)*( fVertices[j+4]-fVertices[j]);
1576       G4ThreeVector v(u.x(),u.y(),-fDz+cf*2*f << 2100       polyhedron->AddVertex(G4ThreeVector(u.x(),u.y(),-fDz+cf*2*fDz*(i+1)));
1577       polyhedron->SetVertex(++icur, v);       << 2101     }    
1578     }                                         << 
1579   }                                              2102   }
1580   for (G4int i = 4; i < 8; ++i)               << 2103   for (i=4;i<8;i++)
1581   {                                              2104   {
1582     G4ThreeVector v(fVertices[i].x(),fVertice << 2105     polyhedron->AddVertex(G4ThreeVector(fVertices[i].x(),
1583     polyhedron->SetVertex(++icur, v);         << 2106                                         fVertices[i].y(),fDz));
1584   }                                              2107   }
1585                                                  2108 
1586   // Set facets                               << 2109   // Add Facets
1587   //                                             2110   //
1588   icur = 0;                                   << 2111   polyhedron->AddFacet(1,4,3,2);  //Z-plane
1589   polyhedron->SetFacet(++icur, 1, 4, 3, 2); / << 2112   for (i=0;i<subdivisions+1;i++)
1590   for (G4int i = 0; i < subdivisions + 1; ++i << 
1591   {                                              2113   {
1592     G4int is = i*4;                           << 2114     G4int is=i*4;
1593     polyhedron->SetFacet(++icur, 5+is, 8+is,  << 2115     polyhedron->AddFacet(5+is,8+is,4+is,1+is);
1594     polyhedron->SetFacet(++icur, 8+is, 7+is,  << 2116     polyhedron->AddFacet(8+is,7+is,3+is,4+is);
1595     polyhedron->SetFacet(++icur, 7+is, 6+is,  << 2117     polyhedron->AddFacet(7+is,6+is,2+is,3+is);
1596     polyhedron->SetFacet(++icur, 6+is, 5+is,  << 2118     polyhedron->AddFacet(6+is,5+is,1+is,2+is); 
1597   }                                              2119   }
1598   polyhedron->SetFacet(++icur, 5+sub4, 6+sub4 << 2120   polyhedron->AddFacet(5+sub4,6+sub4,7+sub4,8+sub4);  //Z-plane
1599                                                  2121 
1600   polyhedron->SetReferences();                   2122   polyhedron->SetReferences();
1601   polyhedron->InvertFacets();                    2123   polyhedron->InvertFacets();
1602                                                  2124 
1603   return polyhedron;                          << 2125   return (G4Polyhedron*) polyhedron;
1604 }                                                2126 }
1605                                                  2127 
1606 ///////////////////////////////////////////// << 2128 // --------------------------------------------------------------------
1607 //                                            << 
1608 // Print out a warning if A has an unexpected << 
1609 //                                            << 
1610 void G4GenericTrap::WarningSignA(const G4Stri << 
1611                                  const G4Thre << 
1612 {                                             << 
1613   std::ostringstream message;                 << 
1614   message.precision(16);                      << 
1615   message << icase << " in " << GetName() <<  << 
1616           << "   p" << p << "\n"              << 
1617           << "   v" << v << "\n"              << 
1618           << "   A = " << A << " (is "        << 
1619           << ((A < 0) ? "negative, instead of << 
1620   StreamInfo(message);                        << 
1621   const G4String function = "G4GenericTrap::D << 
1622   G4Exception(function, "GeomSolids1002", Jus << 
1623 }                                             << 
1624                                               << 
1625 ///////////////////////////////////////////// << 
1626 //                                            << 
1627 // Print out a warning if B has an unexpected << 
1628 //                                            << 
1629 void G4GenericTrap::WarningSignB(const G4Stri << 
1630                                  G4double f,  << 
1631                                  const G4Thre << 
1632 {                                             << 
1633   std::ostringstream message;                 << 
1634   message.precision(16);                      << 
1635   message << icase << " in " << GetName() <<  << 
1636           << "   p" << p << "\n"              << 
1637           << "   v" << v << "\n"              << 
1638           << "   f = " << f << " B = " << B < << 
1639           << ((B < 0) ? "negative, instead of << 
1640   StreamInfo(message);                        << 
1641   const G4String function = "G4GenericTrap::D << 
1642   G4Exception(function, "GeomSolids1002", Jus << 
1643 }                                             << 
1644                                               << 
1645 ///////////////////////////////////////////// << 
1646 //                                            << 
1647 // Print out a warning in DistanceToIn(p,v)   << 
1648 //                                            << 
1649 void G4GenericTrap::WarningDistanceToIn(G4int << 
1650                                         G4dou << 
1651                                         const << 
1652 {                                             << 
1653   G4String check = "";                        << 
1654   if (ttin[1] != DBL_MAX)                     << 
1655   {                                           << 
1656     G4double tcheck = 0.5*(ttout[0] + ttin[1] << 
1657     if (Inside(p + v*tcheck) != kOutside) che << 
1658   }                                           << 
1659                                               << 
1660   auto position = Inside(p);                  << 
1661   std::ostringstream message;                 << 
1662   message.precision(16);                      << 
1663   message << k << "_Unexpected sequence of in << 
1664           << "   position = " << ((position = << 
1665           << "   p" << p << "\n"              << 
1666           << "   v" << v << "\n"              << 
1667           << "   range    : [" << tmin << ",  << 
1668           << "   ttin[2]  : "                 << 
1669           << ((ttin[0] == DBL_MAX) ? kInfinit << 
1670           << ((ttin[1] == DBL_MAX) ? kInfinit << 
1671           << "   ttout[2] : "                 << 
1672           << ((ttout[0] == DBL_MAX) ? kInfini << 
1673           << ((ttout[1] == DBL_MAX) ? kInfini << 
1674   StreamInfo(message);                        << 
1675   G4Exception("G4GenericTrap::DistanceToIn(p, << 
1676               JustWarning, message );         << 
1677 }                                             << 
1678                                               << 
1679 ///////////////////////////////////////////// << 
1680 //                                            << 
1681 // Print out a warning in DistanceToOut(p,v)  << 
1682 //                                            << 
1683 void G4GenericTrap::WarningDistanceToOut(cons << 
1684                                          cons << 
1685                                          G4do << 
1686 {                                             << 
1687   auto position = Inside(p);                  << 
1688   std::ostringstream message;                 << 
1689   message.precision(16);                      << 
1690   message << "Unexpected final tout = " << to << 
1691           << "   position = " << ((position = << 
1692           << "   p" << p << "\n"              << 
1693           << "   v" << v << "\n";             << 
1694   StreamInfo(message);                        << 
1695   G4Exception("G4GenericTrap::DistanceToOut(p << 
1696               JustWarning, message );         << 
1697 }                                             << 
1698                                                  2129 
1699 #endif                                           2130 #endif
1700                                                  2131