Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4QuadrangularFacet.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration and of QinetiQ Ltd, *
20// * subject to DEFCON 705 IPR conditions. *
21// * By using, copying, modifying or distributing the software (or *
22// * any work based on the software) you agree to acknowledge its *
23// * use in resulting scientific publications, and indicate your *
24// * acceptance of all terms of the Geant4 Software license. *
25// ********************************************************************
26//
27// G4QuadrangularFacet class implementation.
28//
29// 31 October 2004 P R Truscott, QinetiQ Ltd, UK - Created.
30// 12 October 2012 M Gayer, CERN
31// New implementation reducing memory requirements by 50%,
32// and considerable CPU speedup together with the new
33// implementation of G4TessellatedSolid.
34// 29 February 2016 E Tcherniaev, CERN
35// Added exhaustive tests to catch various problems with a
36// quadrangular facet: collinear vertices, non planar surface,
37// degenerate, concave or self intersecting quadrilateral.
38// --------------------------------------------------------------------
39
41#include "geomdefs.hh"
42#include "Randomize.hh"
43
44using namespace std;
45
46///////////////////////////////////////////////////////////////////////////////
47//
48// Constructing two adjacent G4TriangularFacet
49// Not efficient, but practical...
50//
52 const G4ThreeVector& vt1,
53 const G4ThreeVector& vt2,
54 const G4ThreeVector& vt3,
55 G4FacetVertexType vertexType)
56 : G4VFacet()
57{
58 G4double delta = 1.0 * kCarTolerance; // dimension tolerance
59 G4double epsilon = 0.01 * kCarTolerance; // planarity tolerance
60
61 G4ThreeVector e1, e2, e3;
62 SetVertex(0, vt0);
63 if (vertexType == ABSOLUTE)
64 {
65 SetVertex(1, vt1);
66 SetVertex(2, vt2);
67 SetVertex(3, vt3);
68
69 e1 = vt1 - vt0;
70 e2 = vt2 - vt0;
71 e3 = vt3 - vt0;
72 }
73 else
74 {
75 SetVertex(1, vt0 + vt1);
76 SetVertex(2, vt0 + vt2);
77 SetVertex(3, vt0 + vt3);
78
79 e1 = vt1;
80 e2 = vt2;
81 e3 = vt3;
82 }
83
84 // Check length of sides and diagonals
85 //
86 G4double leng1 = e1.mag();
87 G4double leng2 = (e2-e1).mag();
88 G4double leng3 = (e3-e2).mag();
89 G4double leng4 = e3.mag();
90
91 G4double diag1 = e2.mag();
92 G4double diag2 = (e3-e1).mag();
93
94 if (leng1 <= delta || leng2 <= delta || leng3 <= delta || leng4 <= delta ||
95 diag1 <= delta || diag2 <= delta)
96 {
97 ostringstream message;
98 message << "Sides/diagonals of facet are too small." << G4endl
99 << "P0 = " << GetVertex(0) << G4endl
100 << "P1 = " << GetVertex(1) << G4endl
101 << "P2 = " << GetVertex(2) << G4endl
102 << "P3 = " << GetVertex(3) << G4endl
103 << "Side1 length (P0->P1) = " << leng1 << G4endl
104 << "Side2 length (P1->P2) = " << leng2 << G4endl
105 << "Side3 length (P2->P3) = " << leng3 << G4endl
106 << "Side4 length (P3->P0) = " << leng4 << G4endl
107 << "Diagonal1 length (P0->P2) = " << diag1 << G4endl
108 << "Diagonal2 length (P1->P3) = " << diag2;
109 G4Exception("G4QuadrangularFacet::G4QuadrangularFacet()",
110 "GeomSolids1001", JustWarning, message);
111 return;
112 }
113
114 // Check that vertices are not collinear
115 //
116 G4double s1 = (e1.cross(e2)).mag()*0.5;
117 G4double s2 = ((e2-e1).cross(e3-e2)).mag()*0.5;
118 G4double s3 = (e2.cross(e3)).mag()*0.5;
119 G4double s4 = (e1.cross(e3)).mag()*0.5;
120
121 G4double h1 = 2.*s1 / std::max(std::max(leng1,leng2),diag1);
122 G4double h2 = 2.*s2 / std::max(std::max(leng2,leng3),diag2);
123 G4double h3 = 2.*s3 / std::max(std::max(leng3,leng4),diag1);
124 G4double h4 = 2.*s4 / std::max(std::max(leng4,leng1),diag2);
125
126 if (h1 <= delta || h2 <= delta || h3 <= delta || h4 <= delta )
127 {
128 ostringstream message;
129 message << "Facet has three or more collinear vertices." << G4endl
130 << "P0 = " << GetVertex(0) << G4endl
131 << "P1 = " << GetVertex(1) << G4endl
132 << "P2 = " << GetVertex(2) << G4endl
133 << "P3 = " << GetVertex(3) << G4endl
134 << "Smallest heights:" << G4endl
135 << " in triangle P0-P1-P2 = " << h1 << G4endl
136 << " in triangle P1-P2-P3 = " << h2 << G4endl
137 << " in triangle P2-P3-P0 = " << h3 << G4endl
138 << " in triangle P3-P0-P1 = " << h4;
139 G4Exception("G4QuadrangularFacet::G4QuadrangularFacet()",
140 "GeomSolids1001", JustWarning, message);
141 return;
142 }
143
144 // Check that vertices are coplanar by computing minimal
145 // height of tetrahedron comprising of vertices
146 //
147 G4double smax = std::max( std::max(s1,s2), std::max(s3,s4) );
148 G4double hmin = 0.5 * std::fabs( e1.dot(e2.cross(e3)) ) / smax;
149 if (hmin >= epsilon)
150 {
151 ostringstream message;
152 message << "Facet is not planar." << G4endl
153 << "Disrepancy = " << hmin << G4endl
154 << "P0 = " << GetVertex(0) << G4endl
155 << "P1 = " << GetVertex(1) << G4endl
156 << "P2 = " << GetVertex(2) << G4endl
157 << "P3 = " << GetVertex(3);
158 G4Exception("G4QuadrangularFacet::G4QuadrangularFacet()",
159 "GeomSolids1001", JustWarning, message);
160 return;
161 }
162
163 // Check that facet is convex by computing crosspoint
164 // of diagonals
165 //
166 G4ThreeVector normal = e2.cross(e3-e1);
167 G4double s = kInfinity, t = kInfinity, magnitude2 = normal.mag2();
168 if (magnitude2 > delta*delta) // check: magnitude2 != 0.
169 {
170 s = normal.dot(e1.cross(e3-e1)) / magnitude2;
171 t = normal.dot(e1.cross(e2)) / magnitude2;
172 }
173 if (s <= 0. || s >= 1. || t <= 0. || t >= 1.)
174 {
175 ostringstream message;
176 message << "Facet is not convex." << G4endl
177 << "Parameters of crosspoint of diagonals: "
178 << s << " and " << t << G4endl
179 << "should both be within (0,1) range" << G4endl
180 << "P0 = " << GetVertex(0) << G4endl
181 << "P1 = " << GetVertex(1) << G4endl
182 << "P2 = " << GetVertex(2) << G4endl
183 << "P3 = " << GetVertex(3);
184 G4Exception("G4QuadrangularFacet::G4QuadrangularFacet()",
185 "GeomSolids1001", JustWarning, message);
186 return;
187 }
188
189 // Define facet
190 //
193
194 normal = normal.unit();
195 fFacet1.SetSurfaceNormal(normal);
196 fFacet2.SetSurfaceNormal(normal);
197
198 G4ThreeVector vtmp = 0.5 * (e1 + e2);
199 fCircumcentre = GetVertex(0) + vtmp;
200 G4double radiusSqr = vtmp.mag2();
201 fRadius = std::sqrt(radiusSqr);
202 // 29.02.2016 Remark by E.Tcherniaev: computation
203 // of fCircumcenter and fRadius is wrong, however
204 // it did not create any problem till now.
205 // Bizarre! Need to investigate!
206}
207
208///////////////////////////////////////////////////////////////////////////////
209//
211{
212}
213
214///////////////////////////////////////////////////////////////////////////////
215//
217 : G4VFacet(rhs)
218{
219 fFacet1 = rhs.fFacet1;
220 fFacet2 = rhs.fFacet2;
221 fRadius = 0.0;
222}
223
224///////////////////////////////////////////////////////////////////////////////
225//
228{
229 if (this == &rhs) return *this;
230
231 fFacet1 = rhs.fFacet1;
232 fFacet2 = rhs.fFacet2;
233 fRadius = 0.0;
234
235 return *this;
236}
237
238///////////////////////////////////////////////////////////////////////////////
239//
241{
243 GetVertex(2), GetVertex(3),
244 ABSOLUTE);
245 return c;
246}
247
248///////////////////////////////////////////////////////////////////////////////
249//
251{
252 G4ThreeVector v1 = fFacet1.Distance(p);
253 G4ThreeVector v2 = fFacet2.Distance(p);
254
255 if (v1.mag2() < v2.mag2()) return v1;
256 else return v2;
257}
258
259///////////////////////////////////////////////////////////////////////////////
260//
262 G4double)
263{
264 G4double dist = Distance(p).mag();
265 return dist;
266}
267
268///////////////////////////////////////////////////////////////////////////////
269//
271 const G4bool outgoing)
272{
273 G4double dist;
274
275 G4ThreeVector v = Distance(p);
276 G4double dir = v.dot(GetSurfaceNormal());
277 if ( ((dir > dirTolerance) && (!outgoing))
278 || ((dir < -dirTolerance) && outgoing))
279 dist = kInfinity;
280 else
281 dist = v.mag();
282 return dist;
283}
284
285///////////////////////////////////////////////////////////////////////////////
286//
288{
289 G4double ss = 0;
290
291 for (G4int i = 0; i <= 3; ++i)
292 {
293 G4double sp = GetVertex(i).dot(axis);
294 if (sp > ss) ss = sp;
295 }
296 return ss;
297}
298
299///////////////////////////////////////////////////////////////////////////////
300//
302 const G4ThreeVector& v,
303 G4bool outgoing,
304 G4double& distance,
305 G4double& distFromSurface,
306 G4ThreeVector& normal)
307{
308 G4bool intersect =
309 fFacet1.Intersect(p,v,outgoing,distance,distFromSurface,normal);
310 if (!intersect) intersect =
311 fFacet2.Intersect(p,v,outgoing,distance,distFromSurface,normal);
312 if (!intersect)
313 {
314 distance = distFromSurface = kInfinity;
315 normal.set(0,0,0);
316 }
317 return intersect;
318}
319
320///////////////////////////////////////////////////////////////////////////////
321//
322// Auxiliary method to get a uniform random point on the facet
323//
325{
326 G4double s1 = fFacet1.GetArea();
327 G4double s2 = fFacet2.GetArea();
328 return ((s1+s2)*G4UniformRand() < s1) ?
329 fFacet1.GetPointOnFace() : fFacet2.GetPointOnFace();
330}
331
332///////////////////////////////////////////////////////////////////////////////
333//
334// Auxiliary method for returning the surface area
335//
337{
338 G4double area = fFacet1.GetArea() + fFacet2.GetArea();
339 return area;
340}
341
342///////////////////////////////////////////////////////////////////////////////
343//
345{
346 return "G4QuadrangularFacet";
347}
348
349///////////////////////////////////////////////////////////////////////////////
350//
352{
353 return fFacet1.GetSurfaceNormal();
354}
G4double epsilon(G4double density, G4double temperature)
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4FacetVertexType
Definition: G4VFacet.hh:48
@ ABSOLUTE
Definition: G4VFacet.hh:48
#define G4endl
Definition: G4ios.hh:57
#define G4UniformRand()
Definition: Randomize.hh:52
Hep3Vector unit() const
double mag2() const
Hep3Vector cross(const Hep3Vector &) const
double dot(const Hep3Vector &) const
double mag() const
void set(double x, double y, double z)
G4ThreeVector Distance(const G4ThreeVector &p)
G4bool Intersect(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool outgoing, G4double &distance, G4double &distFromSurface, G4ThreeVector &normal)
G4QuadrangularFacet(const G4ThreeVector &Pt0, const G4ThreeVector &vt1, const G4ThreeVector &vt2, const G4ThreeVector &vt3, G4FacetVertexType)
void SetVertex(G4int i, const G4ThreeVector &val)
G4ThreeVector GetSurfaceNormal() const
G4QuadrangularFacet & operator=(const G4QuadrangularFacet &right)
G4ThreeVector GetVertex(G4int i) const
G4double GetArea() const
G4GeometryType GetEntityType() const
G4double Extent(const G4ThreeVector axis)
G4ThreeVector GetPointOnFace() const
G4double GetArea() const
void SetSurfaceNormal(G4ThreeVector normal)
G4ThreeVector GetPointOnFace() const
G4bool Intersect(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool outgoing, G4double &distance, G4double &distFromSurface, G4ThreeVector &normal)
G4ThreeVector Distance(const G4ThreeVector &p)
G4ThreeVector GetSurfaceNormal() const
static const G4double dirTolerance
Definition: G4VFacet.hh:92
G4double kCarTolerance
Definition: G4VFacet.hh:93