Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/management/src/G4GeomTools.cc

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

Diff markup

Differences between /geometry/management/src/G4GeomTools.cc (Version 11.3.0) and /geometry/management/src/G4GeomTools.cc (Version 10.6.p3)


  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 // class G4GeomTools implementation                26 // class G4GeomTools implementation
 27 //                                                 27 //
 28 // 10.10.2016, E.Tcherniaev: initial version.      28 // 10.10.2016, E.Tcherniaev: initial version.
 29 // -------------------------------------------     29 // --------------------------------------------------------------------
 30                                                    30 
 31 #include "G4GeomTools.hh"                          31 #include "G4GeomTools.hh"
 32                                                    32 
 33 #include "geomdefs.hh"                             33 #include "geomdefs.hh"
 34 #include "G4SystemOfUnits.hh"                      34 #include "G4SystemOfUnits.hh"
 35 #include "G4GeometryTolerance.hh"                  35 #include "G4GeometryTolerance.hh"
 36                                                    36 
 37 //////////////////////////////////////////////     37 ///////////////////////////////////////////////////////////////////////
 38 //                                                 38 //
 39 // Calculate area of a triangle in 2D              39 // Calculate area of a triangle in 2D
 40                                                    40 
 41 G4double G4GeomTools::TriangleArea(G4double Ax     41 G4double G4GeomTools::TriangleArea(G4double Ax, G4double Ay,
 42                                    G4double Bx     42                                    G4double Bx, G4double By,
 43                                    G4double Cx     43                                    G4double Cx, G4double Cy)
 44 {                                                  44 {
 45   return ((Bx-Ax)*(Cy-Ay) - (By-Ay)*(Cx-Ax))*0     45   return ((Bx-Ax)*(Cy-Ay) - (By-Ay)*(Cx-Ax))*0.5;
 46 }                                                  46 }
 47                                                    47 
 48 //////////////////////////////////////////////     48 ///////////////////////////////////////////////////////////////////////
 49 //                                                 49 //
 50 // Calculate area of a triangle in 2D              50 // Calculate area of a triangle in 2D
 51                                                    51 
 52 G4double G4GeomTools::TriangleArea(const G4Two     52 G4double G4GeomTools::TriangleArea(const G4TwoVector& A,
 53                                    const G4Two     53                                    const G4TwoVector& B,
 54                                    const G4Two     54                                    const G4TwoVector& C)
 55 {                                                  55 {
 56   G4double Ax = A.x(), Ay = A.y();                 56   G4double Ax = A.x(), Ay = A.y(); 
 57   return ((B.x()-Ax)*(C.y()-Ay) - (B.y()-Ay)*(     57   return ((B.x()-Ax)*(C.y()-Ay) - (B.y()-Ay)*(C.x()-Ax))*0.5;
 58 }                                                  58 }
 59                                                    59 
 60 //////////////////////////////////////////////     60 ///////////////////////////////////////////////////////////////////////
 61 //                                                 61 //
 62 // Calculate area of a quadrilateral in 2D         62 // Calculate area of a quadrilateral in 2D
 63                                                    63 
 64 G4double G4GeomTools::QuadArea(const G4TwoVect     64 G4double G4GeomTools::QuadArea(const G4TwoVector& A,
 65                                const G4TwoVect     65                                const G4TwoVector& B,
 66                                const G4TwoVect     66                                const G4TwoVector& C,
 67                                const G4TwoVect     67                                const G4TwoVector& D)
 68 {                                                  68 {
 69   return ((C.x()-A.x())*(D.y()-B.y()) - (C.y()     69   return ((C.x()-A.x())*(D.y()-B.y()) - (C.y()-A.y())*(D.x()-B.x()))*0.5;
 70 }                                                  70 }
 71                                                    71 
 72 //////////////////////////////////////////////     72 ///////////////////////////////////////////////////////////////////////
 73 //                                                 73 //
 74 // Calculate area of a polygon in 2D               74 // Calculate area of a polygon in 2D
 75                                                    75 
 76 G4double G4GeomTools::PolygonArea(const G4TwoV     76 G4double G4GeomTools::PolygonArea(const G4TwoVectorList& p)
 77 {                                                  77 {
 78   auto  n = (G4int)p.size();                   <<  78   G4int n = p.size();
 79   if (n < 3) return 0.0; // degenerate polygon     79   if (n < 3) return 0.0; // degenerate polygon
 80   G4double area = p[n-1].x()*p[0].y() - p[0].x     80   G4double area = p[n-1].x()*p[0].y() - p[0].x()*p[n-1].y();
 81   for(G4int i=1; i<n; ++i)                         81   for(G4int i=1; i<n; ++i)
 82   {                                                82   {
 83     area += p[i-1].x()*p[i].y() - p[i].x()*p[i     83     area += p[i-1].x()*p[i].y() - p[i].x()*p[i-1].y();
 84   }                                                84   }
 85   return area*0.5;                                 85   return area*0.5;
 86 }                                                  86 }
 87                                                    87 
 88 //////////////////////////////////////////////     88 ///////////////////////////////////////////////////////////////////////
 89 //                                                 89 //
 90 // Point inside 2D triangle                        90 // Point inside 2D triangle
 91                                                    91 
 92 G4bool G4GeomTools::PointInTriangle(G4double A     92 G4bool G4GeomTools::PointInTriangle(G4double Ax, G4double Ay,
 93                                     G4double B     93                                     G4double Bx, G4double By,
 94                                     G4double C     94                                     G4double Cx, G4double Cy,
 95                                     G4double P     95                                     G4double Px, G4double Py)
 96                                                    96 
 97 {                                                  97 {
 98   if ((Bx-Ax)*(Cy-Ay) - (By-Ay)*(Cx-Ax) > 0.)      98   if ((Bx-Ax)*(Cy-Ay) - (By-Ay)*(Cx-Ax) > 0.)
 99   {                                                99   {
100     if ((Ax-Cx)*(Py-Cy) - (Ay-Cy)*(Px-Cx) < 0.    100     if ((Ax-Cx)*(Py-Cy) - (Ay-Cy)*(Px-Cx) < 0.) return false;
101     if ((Bx-Ax)*(Py-Ay) - (By-Ay)*(Px-Ax) < 0.    101     if ((Bx-Ax)*(Py-Ay) - (By-Ay)*(Px-Ax) < 0.) return false;
102     if ((Cx-Bx)*(Py-By) - (Cy-By)*(Px-Bx) < 0.    102     if ((Cx-Bx)*(Py-By) - (Cy-By)*(Px-Bx) < 0.) return false;
103   }                                               103   }
104   else                                            104   else
105   {                                               105   {
106     if ((Ax-Cx)*(Py-Cy) - (Ay-Cy)*(Px-Cx) > 0.    106     if ((Ax-Cx)*(Py-Cy) - (Ay-Cy)*(Px-Cx) > 0.) return false;
107     if ((Bx-Ax)*(Py-Ay) - (By-Ay)*(Px-Ax) > 0.    107     if ((Bx-Ax)*(Py-Ay) - (By-Ay)*(Px-Ax) > 0.) return false;
108     if ((Cx-Bx)*(Py-By) - (Cy-By)*(Px-Bx) > 0.    108     if ((Cx-Bx)*(Py-By) - (Cy-By)*(Px-Bx) > 0.) return false;
109   }                                               109   }
110   return true;                                    110   return true;
111 }                                                 111 }
112                                                   112 
113 //////////////////////////////////////////////    113 ///////////////////////////////////////////////////////////////////////
114 //                                                114 //
115 // Point inside 2D triangle                       115 // Point inside 2D triangle
116                                                   116 
117 G4bool G4GeomTools::PointInTriangle(const G4Tw    117 G4bool G4GeomTools::PointInTriangle(const G4TwoVector& A,
118                                     const G4Tw    118                                     const G4TwoVector& B,
119                                     const G4Tw    119                                     const G4TwoVector& C,
120                                     const G4Tw    120                                     const G4TwoVector& P)
121 {                                                 121 {
122   G4double Ax = A.x(), Ay = A.y();                122   G4double Ax = A.x(), Ay = A.y();
123   G4double Bx = B.x(), By = B.y();                123   G4double Bx = B.x(), By = B.y();
124   G4double Cx = C.x(), Cy = C.y();                124   G4double Cx = C.x(), Cy = C.y();
125   G4double Px = P.x(), Py = P.y();                125   G4double Px = P.x(), Py = P.y();
126   if ((Bx-Ax)*(Cy-Ay) - (By-Ay)*(Cx-Ax) > 0.)     126   if ((Bx-Ax)*(Cy-Ay) - (By-Ay)*(Cx-Ax) > 0.)
127   {                                               127   {
128     if ((Ax-Cx)*(Py-Cy) - (Ay-Cy)*(Px-Cx) < 0.    128     if ((Ax-Cx)*(Py-Cy) - (Ay-Cy)*(Px-Cx) < 0.) return false;
129     if ((Bx-Ax)*(Py-Ay) - (By-Ay)*(Px-Ax) < 0.    129     if ((Bx-Ax)*(Py-Ay) - (By-Ay)*(Px-Ax) < 0.) return false;
130     if ((Cx-Bx)*(Py-By) - (Cy-By)*(Px-Bx) < 0.    130     if ((Cx-Bx)*(Py-By) - (Cy-By)*(Px-Bx) < 0.) return false;
131   }                                               131   }
132   else                                            132   else
133   {                                               133   {
134     if ((Ax-Cx)*(Py-Cy) - (Ay-Cy)*(Px-Cx) > 0.    134     if ((Ax-Cx)*(Py-Cy) - (Ay-Cy)*(Px-Cx) > 0.) return false;
135     if ((Bx-Ax)*(Py-Ay) - (By-Ay)*(Px-Ax) > 0.    135     if ((Bx-Ax)*(Py-Ay) - (By-Ay)*(Px-Ax) > 0.) return false;
136     if ((Cx-Bx)*(Py-By) - (Cy-By)*(Px-Bx) > 0.    136     if ((Cx-Bx)*(Py-By) - (Cy-By)*(Px-Bx) > 0.) return false;
137   }                                               137   }
138   return true;                                    138   return true;
139 }                                                 139 }
140                                                   140 
141 //////////////////////////////////////////////    141 ///////////////////////////////////////////////////////////////////////
142 //                                                142 //
143 // Point inside 2D polygon                        143 // Point inside 2D polygon
144                                                   144 
145 G4bool G4GeomTools::PointInPolygon(const G4Two    145 G4bool G4GeomTools::PointInPolygon(const G4TwoVector& p,
146                                    const G4Two    146                                    const G4TwoVectorList& v)
147 {                                                 147 {
148   auto  Nv = (G4int)v.size();                  << 148   G4int Nv = v.size();
149   G4bool in = false;                              149   G4bool in = false;
150   for (G4int i = 0, k = Nv - 1; i < Nv; k = i+    150   for (G4int i = 0, k = Nv - 1; i < Nv; k = i++)
151   {                                               151   {
152     if ((v[i].y() > p.y()) != (v[k].y() > p.y(    152     if ((v[i].y() > p.y()) != (v[k].y() > p.y()))
153     {                                             153     {
154       G4double ctg = (v[k].x()-v[i].x())/(v[k]    154       G4double ctg = (v[k].x()-v[i].x())/(v[k].y()-v[i].y());
155       in ^= static_cast<int>(p.x() < (p.y()-v[ << 155       in ^= (p.x() < (p.y()-v[i].y())*ctg + v[i].x());
156     }                                             156     }
157   }                                               157   }
158   return in;                                      158   return in;
159 }                                                 159 }
160                                                   160 
161 //////////////////////////////////////////////    161 ///////////////////////////////////////////////////////////////////////
162 //                                                162 //
163 // Detemine whether 2D polygon is convex or no    163 // Detemine whether 2D polygon is convex or not
164                                                   164 
165 G4bool G4GeomTools::IsConvex(const G4TwoVector    165 G4bool G4GeomTools::IsConvex(const G4TwoVectorList& polygon)
166 {                                                 166 {
167   static const G4double kCarTolerance =           167   static const G4double kCarTolerance =
168          G4GeometryTolerance::GetInstance()->G    168          G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
169                                                   169 
170   G4bool gotNegative = false;                     170   G4bool gotNegative = false;
171   G4bool gotPositive = false;                     171   G4bool gotPositive = false;
172   auto  n = (G4int)polygon.size();             << 172   G4int n = polygon.size();
173   if (n <= 0) return false;                       173   if (n <= 0) return false;
174   for (G4int icur=0; icur<n; ++icur)              174   for (G4int icur=0; icur<n; ++icur)
175   {                                               175   {
176     G4int iprev = (icur ==   0) ? n-1 : icur-1    176     G4int iprev = (icur ==   0) ? n-1 : icur-1;
177     G4int inext = (icur == n-1) ?   0 : icur+1    177     G4int inext = (icur == n-1) ?   0 : icur+1;
178     G4TwoVector e1 = polygon[icur]  - polygon[    178     G4TwoVector e1 = polygon[icur]  - polygon[iprev];
179     G4TwoVector e2 = polygon[inext] - polygon[    179     G4TwoVector e2 = polygon[inext] - polygon[icur];
180     G4double cross = e1.x()*e2.y() - e1.y()*e2    180     G4double cross = e1.x()*e2.y() - e1.y()*e2.x();
181     if (std::abs(cross) < kCarTolerance) retur    181     if (std::abs(cross) < kCarTolerance) return false;
182     if (cross <  0) gotNegative = true;           182     if (cross <  0) gotNegative = true;
183     if (cross >  0) gotPositive = true;           183     if (cross >  0) gotPositive = true;
184     if (gotNegative && gotPositive) return fal    184     if (gotNegative && gotPositive) return false;
185   }                                               185   }
186   return true;                                    186   return true;
187 }                                                 187 }
188                                                   188 
189 //////////////////////////////////////////////    189 ///////////////////////////////////////////////////////////////////////
190 //                                                190 //
191 // Triangulate simple polygon                     191 // Triangulate simple polygon
192                                                   192 
193 G4bool G4GeomTools::TriangulatePolygon(const G    193 G4bool G4GeomTools::TriangulatePolygon(const G4TwoVectorList& polygon,
194                                              G    194                                              G4TwoVectorList& result)
195 {                                                 195 {
196   result.resize(0);                               196   result.resize(0);
197   std::vector<G4int> triangles;                   197   std::vector<G4int> triangles;
198   G4bool reply = TriangulatePolygon(polygon,tr    198   G4bool reply = TriangulatePolygon(polygon,triangles);
199                                                   199 
200   auto  n = (G4int)triangles.size();           << 200   G4int n = triangles.size();
201   for (G4int i=0; i<n; ++i) result.push_back(p    201   for (G4int i=0; i<n; ++i) result.push_back(polygon[triangles[i]]);
202   return reply;                                   202   return reply;
203 }                                                 203 }
204                                                   204 
205 //////////////////////////////////////////////    205 ///////////////////////////////////////////////////////////////////////
206 //                                                206 //
207 // Triangulation of a simple polygon by "ear c    207 // Triangulation of a simple polygon by "ear clipping"
208                                                   208 
209 G4bool G4GeomTools::TriangulatePolygon(const G    209 G4bool G4GeomTools::TriangulatePolygon(const G4TwoVectorList& polygon,
210                                              s    210                                              std::vector<G4int>& result)
211 {                                                 211 {
212   result.resize(0);                               212   result.resize(0);
213                                                   213 
214   // allocate and initialize list of Vertices     214   // allocate and initialize list of Vertices in polygon
215   //                                              215   //
216   auto  n = (G4int)polygon.size();             << 216   G4int n = polygon.size();
217   if (n < 3) return false;                        217   if (n < 3) return false;
218                                                   218 
219   // we want a counter-clockwise polygon in V     219   // we want a counter-clockwise polygon in V
220   //                                              220   // 
221   G4double area = G4GeomTools::PolygonArea(pol    221   G4double area = G4GeomTools::PolygonArea(polygon);
222   auto  V = new G4int[n];                      << 222   G4int* V = new G4int[n];
223   if (area > 0.)                                  223   if (area > 0.)
224     for (G4int i=0; i<n; ++i) V[i] = i;           224     for (G4int i=0; i<n; ++i) V[i] = i;
225   else                                            225   else
226     for (G4int i=0; i<n; ++i) V[i] = (n-1)-i;     226     for (G4int i=0; i<n; ++i) V[i] = (n-1)-i;
227                                                   227 
228   //  Triangulation: remove nv-2 Vertices, cre    228   //  Triangulation: remove nv-2 Vertices, creating 1 triangle every time
229   //                                              229   // 
230   G4int nv = n;                                   230   G4int nv = n;
231   G4int count = 2*nv; // error detection count    231   G4int count = 2*nv; // error detection counter
232   for(G4int b=nv-1; nv>2; )                       232   for(G4int b=nv-1; nv>2; )
233   {                                               233   {
234     // ERROR: if we loop, it is probably a non    234     // ERROR: if we loop, it is probably a non-simple polygon
235     if ((count--) <= 0)                           235     if ((count--) <= 0)
236     {                                             236     {
237       delete [] V;                                237       delete [] V;
238       if (area < 0.) std::reverse(result.begin    238       if (area < 0.) std::reverse(result.begin(),result.end());
239       return false;                               239       return false; 
240     }                                             240     }
241                                                   241 
242     // three consecutive vertices in current p    242     // three consecutive vertices in current polygon, <a,b,c>
243     G4int a = (b   < nv) ? b   : 0; // previou    243     G4int a = (b   < nv) ? b   : 0; // previous
244           b = (a+1 < nv) ? a+1 : 0; // current    244           b = (a+1 < nv) ? a+1 : 0; // current
245     G4int c = (b+1 < nv) ? b+1 : 0; // next       245     G4int c = (b+1 < nv) ? b+1 : 0; // next
246                                                   246 
247     if (CheckSnip(polygon, a,b,c, nv,V))          247     if (CheckSnip(polygon, a,b,c, nv,V))
248     {                                             248     {
249       // output Triangle                          249       // output Triangle
250       result.push_back(V[a]);                     250       result.push_back(V[a]);
251       result.push_back(V[b]);                     251       result.push_back(V[b]);
252       result.push_back(V[c]);                     252       result.push_back(V[c]);
253                                                   253 
254       // remove vertex b from remaining polygo    254       // remove vertex b from remaining polygon
255       nv--;                                       255       nv--;
256       for(G4int i=b; i<nv; ++i) V[i] = V[i+1];    256       for(G4int i=b; i<nv; ++i) V[i] = V[i+1];
257                                                   257 
258       count = 2*nv; // resest error detection     258       count = 2*nv; // resest error detection counter
259     }                                             259     }
260   }                                               260   }
261   delete [] V;                                    261   delete [] V;
262   if (area < 0.) std::reverse(result.begin(),r    262   if (area < 0.) std::reverse(result.begin(),result.end());
263   return true;                                    263   return true;
264 }                                                 264 }
265                                                   265 
266 //////////////////////////////////////////////    266 ///////////////////////////////////////////////////////////////////////
267 //                                                267 //
268 // Helper function for "ear clipping" polygon     268 // Helper function for "ear clipping" polygon triangulation.
269 // Check for a valid snip                         269 // Check for a valid snip
270                                                   270 
271 G4bool G4GeomTools::CheckSnip(const G4TwoVecto    271 G4bool G4GeomTools::CheckSnip(const G4TwoVectorList& contour,
272                               G4int a, G4int b    272                               G4int a, G4int b, G4int c,
273                               G4int n, const G    273                               G4int n, const G4int* V)
274 {                                                 274 {
275   static const G4double kCarTolerance =           275   static const G4double kCarTolerance =
276          G4GeometryTolerance::GetInstance()->G    276          G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
277                                                   277 
278   // check orientation of Triangle                278   // check orientation of Triangle
279   G4double Ax = contour[V[a]].x(), Ay = contou    279   G4double Ax = contour[V[a]].x(), Ay = contour[V[a]].y();
280   G4double Bx = contour[V[b]].x(), By = contou    280   G4double Bx = contour[V[b]].x(), By = contour[V[b]].y();
281   G4double Cx = contour[V[c]].x(), Cy = contou    281   G4double Cx = contour[V[c]].x(), Cy = contour[V[c]].y();
282   if ((Bx-Ax)*(Cy-Ay) - (By-Ay)*(Cx-Ax) < kCar    282   if ((Bx-Ax)*(Cy-Ay) - (By-Ay)*(Cx-Ax) < kCarTolerance) return false;
283                                                   283   
284   // check that there is no point inside Trian    284   // check that there is no point inside Triangle
285   G4double xmin = std::min(std::min(Ax,Bx),Cx)    285   G4double xmin = std::min(std::min(Ax,Bx),Cx);
286   G4double xmax = std::max(std::max(Ax,Bx),Cx)    286   G4double xmax = std::max(std::max(Ax,Bx),Cx);
287   G4double ymin = std::min(std::min(Ay,By),Cy)    287   G4double ymin = std::min(std::min(Ay,By),Cy);
288   G4double ymax = std::max(std::max(Ay,By),Cy)    288   G4double ymax = std::max(std::max(Ay,By),Cy);
289   for (G4int i=0; i<n; ++i)                       289   for (G4int i=0; i<n; ++i)
290   {                                               290   {
291     if((i == a) || (i == b) || (i == c)) conti    291     if((i == a) || (i == b) || (i == c)) continue;
292     G4double Px = contour[V[i]].x();              292     G4double Px = contour[V[i]].x();
293     if (Px < xmin || Px > xmax) continue;         293     if (Px < xmin || Px > xmax) continue;
294     G4double Py = contour[V[i]].y();              294     G4double Py = contour[V[i]].y();
295     if (Py < ymin || Py > ymax) continue;         295     if (Py < ymin || Py > ymax) continue;
296     if (PointInTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,P    296     if (PointInTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) return false;
297   }                                               297   }
298   return true;                                    298   return true;
299 }                                                 299 }
300                                                   300 
301 //////////////////////////////////////////////    301 ///////////////////////////////////////////////////////////////////////
302 //                                                302 //
303 // Remove collinear and coincident points from    303 // Remove collinear and coincident points from 2D polygon
304                                                   304 
305 void G4GeomTools::RemoveRedundantVertices(G4Tw    305 void G4GeomTools::RemoveRedundantVertices(G4TwoVectorList& polygon,
306                                           std:    306                                           std::vector<G4int>& iout,
307                                           G4do    307                                           G4double tolerance) 
308 {                                                 308 {
309   iout.resize(0);                                 309   iout.resize(0);
310   // set tolerance squared                        310   // set tolerance squared
311   G4double delta = sqr(tolerance);                311   G4double delta = sqr(tolerance);
312   // set special value to mark vertices for re    312   // set special value to mark vertices for removal
313   G4double removeIt = kInfinity;                  313   G4double removeIt = kInfinity;
314                                                   314 
315   auto  nv = (G4int)polygon.size();            << 315   G4int nv = polygon.size();
316                                                   316 
317   // Main loop: check every three consecutive     317   // Main loop: check every three consecutive points, if the points
318   // are collinear then mark middle point for     318   // are collinear then mark middle point for removal
319   //                                              319   //
320   G4int icur = 0, iprev = 0, inext = 0, nout =    320   G4int icur = 0, iprev = 0, inext = 0, nout = 0; 
321   for (G4int i=0; i<nv; ++i)                      321   for (G4int i=0; i<nv; ++i)
322   {                                               322   {
323     icur = i;                    // index of c    323     icur = i;                    // index of current point
324                                                   324 
325     for (G4int k=1; k<nv+1; ++k) // set index     325     for (G4int k=1; k<nv+1; ++k) // set index of previous point
326     {                                             326     {
327       iprev = icur - k;                           327       iprev = icur - k;
328       if (iprev < 0) iprev += nv;                 328       if (iprev < 0) iprev += nv;
329       if (polygon[iprev].x() != removeIt) brea    329       if (polygon[iprev].x() != removeIt) break;
330     }                                             330     }
331                                                   331 
332     for (G4int k=1; k<nv+1; ++k) // set index     332     for (G4int k=1; k<nv+1; ++k) // set index of next point
333     {                                             333     {
334       inext = icur + k;                           334       inext = icur + k;
335       if (inext >= nv) inext -= nv;               335       if (inext >= nv) inext -= nv;
336       if (polygon[inext].x() != removeIt) brea    336       if (polygon[inext].x() != removeIt) break;
337     }                                             337     }
338                                                   338 
339     if (iprev == inext) break;   // degenerate    339     if (iprev == inext) break;   // degenerate polygon, stop
340                                                   340 
341     // Calculate parameters of triangle (iprev    341     // Calculate parameters of triangle (iprev->icur->inext),
342     // if triangle is too small or too narrow     342     // if triangle is too small or too narrow then mark current
343     // point for removal                          343     // point for removal
344     G4TwoVector e1 = polygon[iprev] - polygon[    344     G4TwoVector e1 = polygon[iprev] - polygon[icur];
345     G4TwoVector e2 = polygon[inext] - polygon[    345     G4TwoVector e2 = polygon[inext] - polygon[icur];
346                                                   346 
347     // Check length of edges, then check heigh    347     // Check length of edges, then check height of the triangle 
348     G4double leng1 = e1.mag2();                   348     G4double leng1 = e1.mag2();
349     G4double leng2 = e2.mag2();                   349     G4double leng2 = e2.mag2();
350     G4double leng3 = (e2-e1).mag2();              350     G4double leng3 = (e2-e1).mag2();
351     if (leng1 <= delta || leng2 <= delta || le    351     if (leng1 <= delta || leng2 <= delta || leng3 <= delta)
352     {                                             352     {
353       polygon[icur].setX(removeIt); ++nout;       353       polygon[icur].setX(removeIt); ++nout;
354     }                                             354     }
355     else                                          355     else
356     {                                             356     {
357       G4double lmax = std::max(std::max(leng1,    357       G4double lmax = std::max(std::max(leng1,leng2),leng3);
358       G4double area = std::abs(e1.x()*e2.y()-e    358       G4double area = std::abs(e1.x()*e2.y()-e1.y()*e2.x())*0.5;
359       if (area/std::sqrt(lmax) <= std::abs(tol    359       if (area/std::sqrt(lmax) <= std::abs(tolerance))
360       {                                           360       {
361         polygon[icur].setX(removeIt); ++nout;     361         polygon[icur].setX(removeIt); ++nout;
362       }                                           362       }
363     }                                             363     }
364   }                                               364   }
365                                                   365 
366   // Remove marked points                         366   // Remove marked points
367   //                                              367   //
368   icur = 0;                                       368   icur = 0;
369   if (nv - nout < 3)           // degenerate p    369   if (nv - nout < 3)           // degenerate polygon, remove all points
370   {                                               370   {
371     for (G4int i=0; i<nv; ++i) iout.push_back(    371     for (G4int i=0; i<nv; ++i) iout.push_back(i);
372     polygon.resize(0);                            372     polygon.resize(0);
373     nv = 0;                                       373     nv = 0;
374   }                                               374   }
375   for (G4int i=0; i<nv; ++i) // move points, i    375   for (G4int i=0; i<nv; ++i) // move points, if required
376   {                                               376   {
377     if (polygon[i].x() != removeIt)               377     if (polygon[i].x() != removeIt)
378       polygon[icur++] = polygon[i];               378       polygon[icur++] = polygon[i];
379     else                                          379     else
380       iout.push_back(i);                          380       iout.push_back(i);
381   }                                               381   }
382   if (icur < nv) polygon.resize(icur);            382   if (icur < nv) polygon.resize(icur);
383   return;                                         383   return;
384 }                                                 384 }
385                                                   385 
386 //////////////////////////////////////////////    386 ///////////////////////////////////////////////////////////////////////
387 //                                                387 //
388 // Find bounding rectangle of a disk sector       388 // Find bounding rectangle of a disk sector
389                                                   389 
390 G4bool G4GeomTools::DiskExtent(G4double rmin,     390 G4bool G4GeomTools::DiskExtent(G4double rmin, G4double rmax,
391                                G4double startP    391                                G4double startPhi, G4double delPhi,
392                                G4TwoVector& pm    392                                G4TwoVector& pmin, G4TwoVector& pmax)
393 {                                                 393 {
394   static const G4double kCarTolerance =           394   static const G4double kCarTolerance =
395          G4GeometryTolerance::GetInstance()->G    395          G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
396                                                   396 
397   // check parameters                             397   // check parameters
398   //                                              398   //
399   pmin.set(0,0);                                  399   pmin.set(0,0);
400   pmax.set(0,0);                                  400   pmax.set(0,0);
401   if (rmin   <  0)                    return f    401   if (rmin   <  0)                    return false;
402   if (rmax   <= rmin + kCarTolerance) return f    402   if (rmax   <= rmin + kCarTolerance) return false;
403   if (delPhi <= 0    + kCarTolerance) return f    403   if (delPhi <= 0    + kCarTolerance) return false;
404                                                   404 
405   // calculate extent                             405   // calculate extent
406   //                                              406   //
407   pmin.set(-rmax,-rmax);                          407   pmin.set(-rmax,-rmax);
408   pmax.set( rmax, rmax);                          408   pmax.set( rmax, rmax);
409   if (delPhi >= CLHEP::twopi) return true;        409   if (delPhi >= CLHEP::twopi) return true;
410                                                   410 
411   DiskExtent(rmin,rmax,                           411   DiskExtent(rmin,rmax,
412              std::sin(startPhi),std::cos(start    412              std::sin(startPhi),std::cos(startPhi),
413              std::sin(startPhi+delPhi),std::co    413              std::sin(startPhi+delPhi),std::cos(startPhi+delPhi),
414              pmin,pmax);                          414              pmin,pmax);
415   return true;                                    415   return true;
416 }                                                 416 }
417                                                   417 
418 //////////////////////////////////////////////    418 ///////////////////////////////////////////////////////////////////////
419 //                                                419 //
420 // Find bounding rectangle of a disk sector, f    420 // Find bounding rectangle of a disk sector, fast version.
421 // No check of parameters !!!                     421 // No check of parameters !!!
422                                                   422 
423 void G4GeomTools::DiskExtent(G4double rmin, G4    423 void G4GeomTools::DiskExtent(G4double rmin, G4double rmax,
424                              G4double sinStart    424                              G4double sinStart, G4double cosStart,
425                              G4double sinEnd,     425                              G4double sinEnd, G4double cosEnd,
426                              G4TwoVector& pmin    426                              G4TwoVector& pmin, G4TwoVector& pmax)
427 {                                                 427 {
428   static const G4double kCarTolerance =           428   static const G4double kCarTolerance =
429          G4GeometryTolerance::GetInstance()->G    429          G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
430                                                   430 
431   // check if 360 degrees                         431   // check if 360 degrees
432   //                                              432   //
433   pmin.set(-rmax,-rmax);                          433   pmin.set(-rmax,-rmax);
434   pmax.set( rmax, rmax);                          434   pmax.set( rmax, rmax);
435                                                   435 
436   if (std::abs(sinEnd-sinStart) < kCarToleranc    436   if (std::abs(sinEnd-sinStart) < kCarTolerance && 
437       std::abs(cosEnd-cosStart) < kCarToleranc    437       std::abs(cosEnd-cosStart) < kCarTolerance) return;
438                                                   438 
439   // get start and end quadrants                  439   // get start and end quadrants
440   //                                              440   //
441   //      1 | 0                                   441   //      1 | 0
442   //     ---+---                                  442   //     ---+--- 
443   //      3 | 2                                   443   //      3 | 2
444   //                                              444   //
445   G4int icase = (cosEnd < 0) ? 1 : 0;             445   G4int icase = (cosEnd < 0) ? 1 : 0;
446   if (sinEnd   < 0) icase += 2;                   446   if (sinEnd   < 0) icase += 2;
447   if (cosStart < 0) icase += 4;                   447   if (cosStart < 0) icase += 4;
448   if (sinStart < 0) icase += 8;                   448   if (sinStart < 0) icase += 8;
449                                                   449 
450   switch (icase)                                  450   switch (icase)
451   {                                               451   {
452   // start quadrant 0                             452   // start quadrant 0
453   case  0:                                 //     453   case  0:                                 // start->end : 0->0
454     if (sinEnd < sinStart) break;                 454     if (sinEnd < sinStart) break;
455     pmin.set(rmin*cosEnd,rmin*sinStart);          455     pmin.set(rmin*cosEnd,rmin*sinStart);
456     pmax.set(rmax*cosStart,rmax*sinEnd  );        456     pmax.set(rmax*cosStart,rmax*sinEnd  );
457     break;                                        457     break;
458   case  1:                                 //     458   case  1:                                 // start->end : 0->1
459     pmin.set(rmax*cosEnd,std::min(rmin*sinStar    459     pmin.set(rmax*cosEnd,std::min(rmin*sinStart,rmin*sinEnd));
460     pmax.set(rmax*cosStart,rmax  );               460     pmax.set(rmax*cosStart,rmax  );
461     break;                                        461     break;
462   case  2:                                 //     462   case  2:                                 // start->end : 0->2
463     pmin.set(-rmax,-rmax);                        463     pmin.set(-rmax,-rmax);
464     pmax.set(std::max(rmax*cosStart,rmax*cosEn    464     pmax.set(std::max(rmax*cosStart,rmax*cosEnd),rmax);
465     break;                                        465     break;
466   case  3:                                 //     466   case  3:                                 // start->end : 0->3
467     pmin.set(-rmax,rmax*sinEnd);                  467     pmin.set(-rmax,rmax*sinEnd);
468     pmax.set(rmax*cosStart,rmax);                 468     pmax.set(rmax*cosStart,rmax);
469     break;                                        469     break;
470   // start quadrant 1                             470   // start quadrant 1
471   case  4:                                 //     471   case  4:                                 // start->end : 1->0
472     pmin.set(-rmax,-rmax);                        472     pmin.set(-rmax,-rmax);
473     pmax.set(rmax,std::max(rmax*sinStart,rmax*    473     pmax.set(rmax,std::max(rmax*sinStart,rmax*sinEnd));
474     break;                                        474     break;
475   case  5:                                 //     475   case  5:                                 // start->end : 1->1
476     if (sinEnd > sinStart) break;                 476     if (sinEnd > sinStart) break;
477     pmin.set(rmax*cosEnd,rmin*sinEnd  );          477     pmin.set(rmax*cosEnd,rmin*sinEnd  );
478     pmax.set(rmin*cosStart,rmax*sinStart);        478     pmax.set(rmin*cosStart,rmax*sinStart);
479     break;                                        479     break;
480   case  6:                                 //     480   case  6:                                 // start->end : 1->2
481     pmin.set(-rmax,-rmax);                        481     pmin.set(-rmax,-rmax);
482     pmax.set(rmax*cosEnd,rmax*sinStart);          482     pmax.set(rmax*cosEnd,rmax*sinStart);
483     break;                                        483     break;
484   case  7:                                 //     484   case  7:                                 // start->end : 1->3
485     pmin.set(-rmax,rmax*sinEnd);                  485     pmin.set(-rmax,rmax*sinEnd);
486     pmax.set(std::max(rmin*cosStart,rmin*cosEn    486     pmax.set(std::max(rmin*cosStart,rmin*cosEnd),rmax*sinStart);
487     break;                                        487     break;
488   // start quadrant 2                             488   // start quadrant 2
489   case  8:                                 //     489   case  8:                                 // start->end : 2->0
490     pmin.set(std::min(rmin*cosStart,rmin*cosEn    490     pmin.set(std::min(rmin*cosStart,rmin*cosEnd),rmax*sinStart);
491     pmax.set(rmax,rmax*sinEnd);                   491     pmax.set(rmax,rmax*sinEnd);
492     break;                                        492     break;
493   case  9:                                 //     493   case  9:                                 // start->end : 2->1
494     pmin.set(rmax*cosEnd,rmax*sinStart);          494     pmin.set(rmax*cosEnd,rmax*sinStart);
495     pmax.set(rmax,rmax);                          495     pmax.set(rmax,rmax);
496     break;                                        496     break;
497   case 10:                                 //     497   case 10:                                 // start->end : 2->2
498     if (sinEnd < sinStart) break;                 498     if (sinEnd < sinStart) break;
499     pmin.set(rmin*cosStart,rmax*sinStart);        499     pmin.set(rmin*cosStart,rmax*sinStart);
500     pmax.set(rmax*cosEnd,rmin*sinEnd  );          500     pmax.set(rmax*cosEnd,rmin*sinEnd  );
501     break;                                        501     break;
502   case 11:                                 //     502   case 11:                                 // start->end : 2->3
503     pmin.set(-rmax,std::min(rmax*sinStart,rmax    503     pmin.set(-rmax,std::min(rmax*sinStart,rmax*sinEnd));
504     pmax.set(rmax,rmax);                          504     pmax.set(rmax,rmax);
505     break;                                        505     break;
506   // start quadrant 3                             506   // start quadrant 3
507   case 12:                                 //     507   case 12:                                 // start->end : 3->0
508     pmin.set(rmax*cosStart,-rmax);                508     pmin.set(rmax*cosStart,-rmax);
509     pmax.set(rmax,rmax*sinEnd);                   509     pmax.set(rmax,rmax*sinEnd);
510     break;                                        510     break;
511   case 13:                                 //     511   case 13:                                 // start->end : 3->1
512     pmin.set(std::min(rmax*cosStart,rmax*cosEn    512     pmin.set(std::min(rmax*cosStart,rmax*cosEnd),-rmax);
513     pmax.set(rmax,rmax);                          513     pmax.set(rmax,rmax);
514     break;                                        514     break;
515   case 14:                                 //     515   case 14:                                 // start->end : 3->2
516     pmin.set(rmax*cosStart,-rmax);                516     pmin.set(rmax*cosStart,-rmax);
517     pmax.set(rmax*cosEnd,std::max(rmin*sinStar    517     pmax.set(rmax*cosEnd,std::max(rmin*sinStart,rmin*sinEnd));
518     break;                                        518     break;
519   case 15:                                 //     519   case 15:                                 // start->end : 3->3
520     if (sinEnd > sinStart) break;                 520     if (sinEnd > sinStart) break;
521     pmin.set(rmax*cosStart,rmax*sinEnd);          521     pmin.set(rmax*cosStart,rmax*sinEnd);
522     pmax.set(rmin*cosEnd,rmin*sinStart);          522     pmax.set(rmin*cosEnd,rmin*sinStart);
523     break;                                        523     break;
524   }                                               524   }
525   return;                                         525   return;
526 }                                                 526 }
527                                                   527 
528 //////////////////////////////////////////////    528 ///////////////////////////////////////////////////////////////////////
529 //                                                529 //
530 // Compute the circumference (perimeter) of an    530 // Compute the circumference (perimeter) of an ellipse
531                                                   531 
532 G4double G4GeomTools::EllipsePerimeter(G4doubl    532 G4double G4GeomTools::EllipsePerimeter(G4double pA, G4double pB)
533 {                                                 533 {
534   G4double x = std::abs(pA);                      534   G4double x = std::abs(pA);
535   G4double y = std::abs(pB);                      535   G4double y = std::abs(pB);
536   G4double a = std::max(x,y);                     536   G4double a = std::max(x,y);
537   G4double b = std::min(x,y);                     537   G4double b = std::min(x,y);
538   G4double e = std::sqrt((1. - b/a)*(1. + b/a)    538   G4double e = std::sqrt((1. - b/a)*(1. + b/a));
539   return 4. * a * comp_ellint_2(e);               539   return 4. * a * comp_ellint_2(e);
540 }                                                 540 }
541                                                   541 
542 //////////////////////////////////////////////    542 ///////////////////////////////////////////////////////////////////////
543 //                                                543 //
544 // Compute the lateral surface area of an elli    544 // Compute the lateral surface area of an elliptic cone
545                                                   545 
546 G4double G4GeomTools::EllipticConeLateralArea(    546 G4double G4GeomTools::EllipticConeLateralArea(G4double pA,
547                                                   547                                               G4double pB,
548                                                   548                                               G4double pH)
549 {                                                 549 {
550   G4double x = std::abs(pA);                      550   G4double x = std::abs(pA);
551   G4double y = std::abs(pB);                      551   G4double y = std::abs(pB);
552   G4double h = std::abs(pH);                      552   G4double h = std::abs(pH);
553   G4double a = std::max(x,y);                     553   G4double a = std::max(x,y);
554   G4double b = std::min(x,y);                     554   G4double b = std::min(x,y);
555   G4double e = std::sqrt((1. - b/a)*(1. + b/a)    555   G4double e = std::sqrt((1. - b/a)*(1. + b/a)) / std::hypot(1.,b/h);
556   return 2. * a * std::hypot(b,h) * comp_ellin    556   return 2. * a * std::hypot(b,h) * comp_ellint_2(e);
557 }                                                 557 }
558                                                   558 
559 //////////////////////////////////////////////    559 ///////////////////////////////////////////////////////////////////////
560 //                                                560 //
561 // Compute Elliptical Integral of the Second K    561 // Compute Elliptical Integral of the Second Kind
562 //                                                562 //
563 // The algorithm is based upon Carlson B.C., "    563 // The algorithm is based upon Carlson B.C., "Computation of real
564 // or complex elliptic integrals", Numerical A    564 // or complex elliptic integrals", Numerical Algorithms,
565 // Volume 10, Issue 1, 1995 (see equations 2.3    565 // Volume 10, Issue 1, 1995 (see equations 2.36 - 2.39)
566 //                                                566 //
567 // The code was adopted from C code at:           567 // The code was adopted from C code at:
568 // http://paulbourke.net/geometry/ellipsecirc/    568 // http://paulbourke.net/geometry/ellipsecirc/
569                                                   569 
570 G4double G4GeomTools::comp_ellint_2(G4double e    570 G4double G4GeomTools::comp_ellint_2(G4double e)
571 {                                                 571 {
572   const G4double eps = 1. / 134217728.; // 1 /    572   const G4double eps = 1. / 134217728.; // 1 / 2^27
573                                                   573 
574   G4double a = 1.;                                574   G4double a = 1.;
575   G4double b = std::sqrt((1. - e)*(1. + e));      575   G4double b = std::sqrt((1. - e)*(1. + e));
576   if (b == 1.) return CLHEP::halfpi;              576   if (b == 1.) return CLHEP::halfpi;
577   if (b == 0.) return 1.;                         577   if (b == 0.) return 1.;
578                                                   578 
579   G4double x = 1.;                                579   G4double x = 1.;
580   G4double y = b;                                 580   G4double y = b;
581   G4double S = 0.;                                581   G4double S = 0.;
582   G4double M = 1.;                                582   G4double M = 1.;
583   while (x - y > eps*y)                           583   while (x - y > eps*y)
584   {                                               584   {
585     G4double tmp = (x + y) * 0.5;                 585     G4double tmp = (x + y) * 0.5;
586     y = std::sqrt(x*y);                           586     y = std::sqrt(x*y);
587     x = tmp;                                      587     x = tmp;
588     M += M;                                       588     M += M;
589     S += M * (x - y)*(x - y);                     589     S += M * (x - y)*(x - y);
590   }                                               590   }
591   return 0.5 * CLHEP::halfpi * ((a + b)*(a + b    591   return 0.5 * CLHEP::halfpi * ((a + b)*(a + b) - S) / (x + y);
592 }                                                 592 }
593                                                   593 
594 //////////////////////////////////////////////    594 ///////////////////////////////////////////////////////////////////////
595 //                                                595 //
596 // Calcuate area of a triangle in 3D              596 // Calcuate area of a triangle in 3D
597                                                   597 
598 G4ThreeVector G4GeomTools::TriangleAreaNormal(    598 G4ThreeVector G4GeomTools::TriangleAreaNormal(const G4ThreeVector& A,
599                                                   599                                               const G4ThreeVector& B,
600                                                   600                                               const G4ThreeVector& C)
601 {                                                 601 {
602   return ((B-A).cross(C-A))*0.5;                  602   return ((B-A).cross(C-A))*0.5;
603 }                                                 603 }
604                                                   604 
605 //////////////////////////////////////////////    605 ///////////////////////////////////////////////////////////////////////
606 //                                                606 //
607 // Calcuate area of a quadrilateral in 3D         607 // Calcuate area of a quadrilateral in 3D
608                                                   608 
609 G4ThreeVector G4GeomTools::QuadAreaNormal(cons    609 G4ThreeVector G4GeomTools::QuadAreaNormal(const G4ThreeVector& A,
610                                           cons    610                                           const G4ThreeVector& B,
611                                           cons    611                                           const G4ThreeVector& C,
612                                           cons    612                                           const G4ThreeVector& D)
613 {                                                 613 {
614   return ((C-A).cross(D-B))*0.5;                  614   return ((C-A).cross(D-B))*0.5;
615 }                                                 615 }
616                                                   616 
617 //////////////////////////////////////////////    617 ///////////////////////////////////////////////////////////////////////
618 //                                                618 //
619 // Calculate area of a polygon in 3D              619 // Calculate area of a polygon in 3D
620                                                   620 
621 G4ThreeVector G4GeomTools::PolygonAreaNormal(c    621 G4ThreeVector G4GeomTools::PolygonAreaNormal(const G4ThreeVectorList& p)
622 {                                                 622 {
623   auto  n = (G4int)p.size();                   << 623   G4int n = p.size();
624   if (n < 3) return {0,0,0}; // degerate polyg << 624   if (n < 3) return G4ThreeVector(0,0,0); // degerate polygon
625   G4ThreeVector normal = p[n-1].cross(p[0]);      625   G4ThreeVector normal = p[n-1].cross(p[0]);
626   for(G4int i=1; i<n; ++i)                        626   for(G4int i=1; i<n; ++i)
627   {                                               627   {
628     normal += p[i-1].cross(p[i]);                 628     normal += p[i-1].cross(p[i]);
629   }                                               629   }
630   return normal*0.5;                              630   return normal*0.5;
631 }                                                 631 }
632                                                   632 
633 //////////////////////////////////////////////    633 ///////////////////////////////////////////////////////////////////////
634 //                                                634 //
635 // Calculate distance between point P and line    635 // Calculate distance between point P and line segment AB in 3D
636                                                   636 
637 G4double G4GeomTools::DistancePointSegment(con    637 G4double G4GeomTools::DistancePointSegment(const G4ThreeVector& P,
638                                            con    638                                            const G4ThreeVector& A,
639                                            con    639                                            const G4ThreeVector& B)
640 {                                                 640 {
641   G4ThreeVector AP = P - A;                       641   G4ThreeVector AP = P - A;
642   G4ThreeVector AB = B - A;                       642   G4ThreeVector AB = B - A;
643                                                   643 
644   G4double u = AP.dot(AB);                        644   G4double u = AP.dot(AB);
645   if (u <= 0) return AP.mag();       // closes    645   if (u <= 0) return AP.mag();       // closest point is A
646                                                   646 
647   G4double len2 = AB.mag2();                      647   G4double len2 = AB.mag2();
648   if (u >= len2) return (B-P).mag(); // closes    648   if (u >= len2) return (B-P).mag(); // closest point is B
649                                                   649 
650   return ((u/len2)*AB - AP).mag();   // distan    650   return ((u/len2)*AB - AP).mag();   // distance to line
651 }                                                 651 }
652                                                   652 
653 //////////////////////////////////////////////    653 ///////////////////////////////////////////////////////////////////////
654 //                                                654 //
655 // Find closest point on line segment in 3D       655 // Find closest point on line segment in 3D
656                                                   656 
657 G4ThreeVector                                     657 G4ThreeVector
658 G4GeomTools::ClosestPointOnSegment(const G4Thr    658 G4GeomTools::ClosestPointOnSegment(const G4ThreeVector& P,
659                                    const G4Thr    659                                    const G4ThreeVector& A,
660                                    const G4Thr    660                                    const G4ThreeVector& B)
661 {                                                 661 {
662   G4ThreeVector AP = P - A;                       662   G4ThreeVector AP = P - A;
663   G4ThreeVector AB = B - A;                       663   G4ThreeVector AB = B - A;
664                                                   664 
665   G4double u = AP.dot(AB);                        665   G4double u = AP.dot(AB);
666   if (u <= 0) return A;      // closest point     666   if (u <= 0) return A;      // closest point is A
667                                                   667 
668   G4double len2 = AB.mag2();                      668   G4double len2 = AB.mag2();
669   if (u >= len2) return B;   // closest point     669   if (u >= len2) return B;   // closest point is B
670                                                   670 
671   G4double t = u/len2;                            671   G4double t = u/len2;
672   return A + t*AB;           // closest point     672   return A + t*AB;           // closest point on segment
673 }                                                 673 }
674                                                   674 
675 //////////////////////////////////////////////    675 ///////////////////////////////////////////////////////////////////////
676 //                                                676 //
677 // Find closest point on triangle in 3D.          677 // Find closest point on triangle in 3D.
678 //                                                678 //
679 // The implementation is based on the algorith    679 // The implementation is based on the algorithm published in
680 // "Geometric Tools for Computer Graphics", Ph    680 // "Geometric Tools for Computer Graphics", Philip J Scheider and
681 // David H Eberly, Elsevier Science (USA), 200    681 // David H Eberly, Elsevier Science (USA), 2003.
682 //                                                682 // 
683 // The algorithm is also available at:            683 // The algorithm is also available at:
684 // http://www.geometrictools.com/Documentation    684 // http://www.geometrictools.com/Documentation/DistancePoint3Triangle3.pdf
685                                                   685 
686 G4ThreeVector                                     686 G4ThreeVector
687 G4GeomTools::ClosestPointOnTriangle(const G4Th    687 G4GeomTools::ClosestPointOnTriangle(const G4ThreeVector& P,
688                                     const G4Th    688                                     const G4ThreeVector& A,
689                                     const G4Th    689                                     const G4ThreeVector& B,
690                                     const G4Th    690                                     const G4ThreeVector& C)
691 {                                                 691 {
692   G4ThreeVector diff  = A - P;                    692   G4ThreeVector diff  = A - P;
693   G4ThreeVector edge0 = B - A;                    693   G4ThreeVector edge0 = B - A;
694   G4ThreeVector edge1 = C - A;                    694   G4ThreeVector edge1 = C - A;
695                                                   695 
696   G4double a = edge0.mag2();                      696   G4double a = edge0.mag2();
697   G4double b = edge0.dot(edge1);                  697   G4double b = edge0.dot(edge1);
698   G4double c = edge1.mag2();                      698   G4double c = edge1.mag2();
699   G4double d = diff.dot(edge0);                   699   G4double d = diff.dot(edge0);
700   G4double e = diff.dot(edge1);                   700   G4double e = diff.dot(edge1);
701                                                   701 
702   G4double det = a*c - b*b;                       702   G4double det = a*c - b*b;
703   G4double t0  = b*e - c*d;                       703   G4double t0  = b*e - c*d;
704   G4double t1  = b*d - a*e;                       704   G4double t1  = b*d - a*e;
705                                                   705 
706   /*                                              706   /*
707              ^ t1                                 707              ^ t1
708          \ 2 |                                    708          \ 2 |
709           \  |                                    709           \  |
710            \ |     regions                        710            \ |     regions
711             \|                                    711             \|
712              C                                    712              C
713              |\                                   713              |\
714          3   | \   1                              714          3   | \   1
715              |  \                                 715              |  \
716              | 0 \                                716              | 0 \
717              |    \                               717              |    \
718         ---- A --- B ----> t0                     718         ---- A --- B ----> t0
719              |      \                             719              |      \
720          4   |   5   \   6                        720          4   |   5   \   6
721              |        \                           721              |        \
722   */                                              722   */
723                                                   723 
724   G4int region = -1;                              724   G4int region = -1;
725   if (t0+t1 <= det)                               725   if (t0+t1 <= det)
726     region = (t0 < 0) ? ((t1 < 0) ? 4 : 3) : (    726     region = (t0 < 0) ? ((t1 < 0) ? 4 : 3) : ((t1 < 0) ? 5 : 0);
727   else                                            727   else
728     region = (t0 < 0) ? 2 : ((t1 < 0) ? 6 : 1)    728     region = (t0 < 0) ? 2 : ((t1 < 0) ? 6 : 1);
729                                                   729 
730   switch (region)                                 730   switch (region)
731   {                                               731   {
732   case 0:  // interior of triangle                732   case 0:  // interior of triangle
733     {                                             733     {
734       G4double invDet = 1./det;                   734       G4double invDet = 1./det;
735       return A + (t0*invDet)*edge0 + (t1*invDe    735       return A + (t0*invDet)*edge0 + (t1*invDet)*edge1;
736     }                                             736     }
737   case 1:  // edge BC                             737   case 1:  // edge BC
738     {                                             738     {
739       G4double numer = c + e - b - d;             739       G4double numer = c + e - b - d; 
740       if (numer <= 0) return C;                   740       if (numer <= 0) return C;
741       G4double denom = a - 2*b + c;               741       G4double denom = a - 2*b + c;
742       return (numer >= denom) ? B : C + (numer    742       return (numer >= denom) ? B : C + (numer/denom)*(edge0-edge1);
743     }                                             743     }
744   case 2:  // edge AC or BC                       744   case 2:  // edge AC or BC
745     {                                             745     {
746       G4double tmp0 = b + d;                      746       G4double tmp0 = b + d;
747       G4double tmp1 = c + e;                      747       G4double tmp1 = c + e;
748       if (tmp1 > tmp0)                            748       if (tmp1 > tmp0)
749       {                                           749       {
750         G4double numer = tmp1 - tmp0;             750         G4double numer = tmp1 - tmp0;
751         G4double denom = a - 2*b + c;             751         G4double denom = a - 2*b + c;
752         return (numer >= denom) ? B : C + (num    752         return (numer >= denom) ? B : C + (numer/denom)*(edge0-edge1);
753       }                                           753       }
754       // same:  (e >= 0) ? A : ((-e >= c) ? C     754       // same:  (e >= 0) ? A : ((-e >= c) ? C : A + (-e/c)*edge1)
755       return (tmp1 <= 0) ? C : (( e >= 0) ? A     755       return (tmp1 <= 0) ? C : (( e >= 0) ? A : A + (-e/c)*edge1);
756     }                                             756     }
757   case 3:  // edge AC                             757   case 3:  // edge AC
758     return (e >= 0) ? A : ((-e >= c) ? C : A +    758     return (e >= 0) ? A : ((-e >= c) ? C : A + (-e/c)*edge1);
759                                                   759 
760   case 4:  // edge AB or AC                       760   case 4:  // edge AB or AC
761     if (d < 0)      return (-d >= a) ? B : A +    761     if (d < 0)      return (-d >= a) ? B : A + (-d/a)*edge0;
762     return (e >= 0) ? A : ((-e >= c) ? C : A +    762     return (e >= 0) ? A : ((-e >= c) ? C : A + (-e/c)*edge1);
763                                                   763 
764   case 5:  // edge AB                             764   case 5:  // edge AB
765     return (d >= 0) ? A : ((-d >= a) ? B : A +    765     return (d >= 0) ? A : ((-d >= a) ? B : A + (-d/a)*edge0);
766                                                   766 
767   case 6:  // edge AB or BC                       767   case 6:  // edge AB or BC
768     {                                             768     {
769       G4double tmp0 = b + e;                      769       G4double tmp0 = b + e;
770       G4double tmp1 = a + d;                      770       G4double tmp1 = a + d;
771       if (tmp1 > tmp0)                            771       if (tmp1 > tmp0)
772       {                                           772       {
773         G4double numer = tmp1 - tmp0;             773         G4double numer = tmp1 - tmp0;
774         G4double denom = a - 2*b + c;             774         G4double denom = a - 2*b + c;
775         return (numer >= denom) ? C : B + (num    775         return (numer >= denom) ? C : B + (numer/denom)*(edge1-edge0);
776       }                                           776       }
777       // same:  (d >= 0) ? A : ((-d >= a) ? B     777       // same:  (d >= 0) ? A : ((-d >= a) ? B : A + (-d/a)*edge0)
778       return (tmp1 <= 0) ? B : (( d >= 0) ? A     778       return (tmp1 <= 0) ? B : (( d >= 0) ? A : A + (-d/a)*edge0);
779     }                                             779     }
780   default: // impossible case                     780   default: // impossible case 
781     return {kInfinity,kInfinity,kInfinity};    << 781     return G4ThreeVector(kInfinity,kInfinity,kInfinity);
782   }                                               782   }
783 }                                                 783 }
784                                                   784 
785 //////////////////////////////////////////////    785 ///////////////////////////////////////////////////////////////////////
786 //                                                786 //
787 // Calculate bounding box of a spherical secto    787 // Calculate bounding box of a spherical sector
788                                                   788 
789 G4bool                                            789 G4bool
790 G4GeomTools::SphereExtent(G4double rmin, G4dou    790 G4GeomTools::SphereExtent(G4double rmin, G4double rmax,
791                           G4double startTheta,    791                           G4double startTheta, G4double delTheta,
792                           G4double startPhi, G    792                           G4double startPhi, G4double delPhi,
793                           G4ThreeVector& pmin,    793                           G4ThreeVector& pmin, G4ThreeVector& pmax)
794 {                                                 794 {
795   static const G4double kCarTolerance =           795   static const G4double kCarTolerance =
796          G4GeometryTolerance::GetInstance()->G    796          G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
797                                                   797 
798   // check parameters                             798   // check parameters
799   //                                              799   //
800   pmin.set(0,0,0);                                800   pmin.set(0,0,0);
801   pmax.set(0,0,0);                                801   pmax.set(0,0,0);
802   if (rmin     <  0)                    return    802   if (rmin     <  0)                    return false;
803   if (rmax     <= rmin + kCarTolerance) return    803   if (rmax     <= rmin + kCarTolerance) return false;
804   if (delTheta <= 0    + kCarTolerance) return    804   if (delTheta <= 0    + kCarTolerance) return false;
805   if (delPhi   <= 0    + kCarTolerance) return    805   if (delPhi   <= 0    + kCarTolerance) return false;
806                                                   806 
807   G4double stheta = startTheta;                   807   G4double stheta = startTheta;
808   G4double dtheta = delTheta;                     808   G4double dtheta = delTheta;
809   if (stheta < 0 && stheta > CLHEP::pi) return    809   if (stheta < 0 && stheta > CLHEP::pi) return false;
810   if (stheta + dtheta > CLHEP::pi)      dtheta    810   if (stheta + dtheta > CLHEP::pi)      dtheta = CLHEP::pi - stheta;
811   if (dtheta <= 0 + kCarTolerance)      return    811   if (dtheta <= 0 + kCarTolerance)      return false;
812                                                   812 
813   // calculate extent                             813   // calculate extent
814   //                                              814   //
815   pmin.set(-rmax,-rmax,-rmax);                    815   pmin.set(-rmax,-rmax,-rmax);
816   pmax.set( rmax, rmax, rmax);                    816   pmax.set( rmax, rmax, rmax);
817   if (dtheta >= CLHEP::pi && delPhi >= CLHEP::    817   if (dtheta >= CLHEP::pi && delPhi >= CLHEP::twopi) return true;
818                                                   818 
819   G4double etheta   = stheta + dtheta;            819   G4double etheta   = stheta + dtheta;
820   G4double sinStart = std::sin(stheta);           820   G4double sinStart = std::sin(stheta);
821   G4double cosStart = std::cos(stheta);           821   G4double cosStart = std::cos(stheta);
822   G4double sinEnd   = std::sin(etheta);           822   G4double sinEnd   = std::sin(etheta);
823   G4double cosEnd   = std::cos(etheta);           823   G4double cosEnd   = std::cos(etheta);
824                                                   824 
825   G4double rhomin = rmin*std::min(sinStart,sin    825   G4double rhomin = rmin*std::min(sinStart,sinEnd);
826   G4double rhomax = rmax;                         826   G4double rhomax = rmax;
827   if (stheta > CLHEP::halfpi) rhomax = rmax*si    827   if (stheta > CLHEP::halfpi) rhomax = rmax*sinStart;
828   if (etheta < CLHEP::halfpi) rhomax = rmax*si    828   if (etheta < CLHEP::halfpi) rhomax = rmax*sinEnd;
829                                                   829 
830   G4TwoVector xymin,xymax;                        830   G4TwoVector xymin,xymax;
831   DiskExtent(rhomin,rhomax,                       831   DiskExtent(rhomin,rhomax,
832              std::sin(startPhi),std::cos(start    832              std::sin(startPhi),std::cos(startPhi),
833              std::sin(startPhi+delPhi),std::co    833              std::sin(startPhi+delPhi),std::cos(startPhi+delPhi),
834              xymin,xymax);                        834              xymin,xymax);
835                                                   835 
836   G4double zmin = std::min(rmin*cosEnd,rmax*co    836   G4double zmin = std::min(rmin*cosEnd,rmax*cosEnd);
837   G4double zmax = std::max(rmin*cosStart,rmax*    837   G4double zmax = std::max(rmin*cosStart,rmax*cosStart);
838   pmin.set(xymin.x(),xymin.y(),zmin);             838   pmin.set(xymin.x(),xymin.y(),zmin);
839   pmax.set(xymax.x(),xymax.y(),zmax);             839   pmax.set(xymax.x(),xymax.y(),zmax);
840   return true;                                    840   return true;
841 }                                                 841 }
842                                                   842