Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4ToroidalSurface.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. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
27// $Id$
28//
29// ----------------------------------------------------------------------
30// GEANT 4 class source file
31//
32// G4ToroidalSurface.cc
33//
34// ----------------------------------------------------------------------
35
36#include "G4ToroidalSurface.hh"
38
40 : MinRadius(0.), MaxRadius(0.), TransMatrix(0), EQN_EPS(1e-9)
41{
42}
43
45 const G4Vector3D& Ax,
46 const G4Vector3D& Dir,
47 G4double MinRad,
48 G4double MaxRad)
49 : EQN_EPS(1e-9)
50{
51 Placement.Init(Dir, Ax, Location);
52
53 MinRadius = MinRad;
54 MaxRadius = MaxRad;
55 TransMatrix= new G4PointMatrix(4,4);
56}
57
58
60{
61 delete TransMatrix;
62}
63
64
66{
67 // L. Broglia
68 // G4Point3D Origin = Placement.GetSrfPoint();
69 G4Point3D Origin = Placement.GetLocation();
70
71 G4Point3D Min(Origin.x()-MaxRadius,
72 Origin.y()-MaxRadius,
73 Origin.z()-MaxRadius);
74 G4Point3D Max(Origin.x()+MaxRadius,
75 Origin.y()+MaxRadius,
76 Origin.z()+MaxRadius);
77
78 bbox = new G4BoundingBox3D(Min,Max);
79}
80
81
83{
84 return G4Vector3D(0,0,0);
85}
86
87
89{
90 // L. Broglia
91 // G4Point3D Origin = Placement.GetSrfPoint();
92 G4Point3D Origin = Placement.GetLocation();
93
94 G4double Dist = Pt.distance(Origin);
95
96 return ((Dist - MaxRadius)*(Dist - MaxRadius));
97}
98
99
101{
102 // ---- inttor - Intersect a ray with a torus. ------------------------
103 // from GraphicsGems II by
104
105 // Description:
106 // Inttor determines the intersection of a ray with a torus.
107 //
108 // On entry:
109 // raybase = The coordinate defining the base of the
110 // intersecting ray.
111 // raycos = The G4Vector3D cosines of the above ray.
112 // center = The center location of the torus.
113 // radius = The major radius of the torus.
114 // rplane = The minor radius in the G4Plane of the torus.
115 // rnorm = The minor radius Normal to the G4Plane of the torus.
116 // tran = A 4x4 transformation matrix that will position
117 // the torus at the origin and orient it such that
118 // the G4Plane of the torus lyes in the x-z G4Plane.
119 //
120 // On return:
121 // nhits = The number of intersections the ray makes with
122 // the torus.
123 // rhits = The entering/leaving distances of the
124 // intersections.
125 //
126 // Returns: True if the ray intersects the torus.
127 //
128 // --------------------------------------------------------------------
129
130 // Variables. Should be optimized later...
131 G4Point3D Base = Ray.GetStart(); // Base of the intersection ray
132 G4Vector3D DCos = Ray.GetDir(); // Direction cosines of the ray
133 G4int nhits=0; // Number of intersections
134 G4double rhits[4]; // Intersection distances
135 G4double hits[4] = {0.,0.,0.,0.}; // Ordered intersection distances
136 G4double rho, a0, b0; // Related constants
137 G4double f, l, t, g1, q, m1, u; // Ray dependent terms
138 G4double C[5]; // Quartic coefficients
139
140 // Transform the intersection ray
141
142
143 // MultiplyPointByMatrix (Base); // Matriisi puuttuu viela!
144 // MultiplyVectorByMatrix (DCos);
145
146 // Compute constants related to the torus.
147 G4double rnorm = MaxRadius - MinRadius; // ei tietoa onko oikein...
148 rho = MinRadius*MinRadius / (rnorm*rnorm);
149 a0 = 4. * MaxRadius*MaxRadius;
150 b0 = MaxRadius*MaxRadius - MinRadius*MinRadius;
151
152 // Compute ray dependent terms.
153 f = 1. - DCos.y()*DCos.y();
154 l = 2. * (Base.x()*DCos.x() + Base.z()*DCos.z());
155 t = Base.x()*Base.x() + Base.z()*Base.z();
156 g1 = f + rho * DCos.y()*DCos.y();
157 q = a0 / (g1*g1);
158 m1 = (l + 2.*rho*DCos.y()*Base.y()) / g1;
159 u = (t + rho*Base.y()*Base.y() + b0) / g1;
160
161 // Compute the coefficients of the quartic.
162
163 C[4] = 1.0;
164 C[3] = 2. * m1;
165 C[2] = m1*m1 + 2.*u - q*f;
166 C[1] = 2.*m1*u - q*l;
167 C[0] = u*u - q*t;
168
169 // Use quartic root solver found in "Graphics Gems" by Jochen Schwarze.
170 nhits = SolveQuartic (C,rhits);
171
172 // SolveQuartic returns root pairs in reversed order.
173 m1 = rhits[0]; u = rhits[1]; rhits[0] = u; rhits[1] = m1;
174 m1 = rhits[2]; u = rhits[3]; rhits[2] = u; rhits[3] = m1;
175
176 // return (*nhits != 0);
177
178 if(nhits != 0)
179 {
180 // Convert Hit distances to intersection points
181 /*
182 G4Point3D** IntersectionPoints = new G4Point3D*[nhits];
183 for(G4int a=0;a<nhits;a++)
184 {
185 G4double Dist = rhits[a];
186 IntersectionPoints[a] = new G4Point3D((Base - Dist * DCos));
187 }
188 // Check wether any of the hits are on the actual surface
189 // Start with checking for the intersections that are Inside the bbox
190
191 G4Point3D* Hit;
192 G4int InsideBox[2]; // Max 2 intersections on the surface
193 G4int Counter=0;
194 */
195
196 G4Point3D BoxMin = bbox->GetBoxMin();
197 G4Point3D BoxMax = bbox->GetBoxMax();
198 G4Point3D Hit;
199 G4int c1 = 0;
200 G4int c2;
201 G4double tempVec[4];
202
203 for(G4int a=0;a<nhits;a++)
204 {
205 while ( (c1 < 4) && (hits[c1] <= rhits[a]) )
206 {
207 tempVec[c1]=hits[c1];
208 c1++;
209 }
210
211 for(c2=c1+1;c2<4;c2++)
212 tempVec[c2]=hits[c2-1];
213
214 if(c1<4)
215 {
216 tempVec[c1]=rhits[a];
217
218 for(c2=0;c2<4;c2++)
219 hits[c2]=tempVec[c2];
220 }
221 }
222
223 for(G4int b=0;b<nhits;b++)
224 {
225 // Hit = IntersectionPoints[b];
226 if(hits[b] >=kCarTolerance*0.5)
227 {
228 Hit = Base + (hits[b]*DCos);
229 // InsideBox[Counter]=b;
230 if( (Hit.x() > BoxMin.x()) &&
231 (Hit.x() < BoxMax.x()) &&
232 (Hit.y() > BoxMin.y()) &&
233 (Hit.y() < BoxMax.y()) &&
234 (Hit.z() > BoxMin.z()) &&
235 (Hit.z() < BoxMax.z()) )
236 {
237 closest_hit = Hit;
238 distance = hits[b]*hits[b];
239 return 1;
240 }
241
242 // Counter++;
243 }
244 }
245
246 // If two Inside bbox, find closest
247 // G4int Closest=0;
248
249 // if(Counter>1)
250 // if(rhits[InsideBox[0]] > rhits[InsideBox[1]])
251 // Closest=1;
252
253 // Project polygon and do point in polygon
254 // Projection also for curves etc.
255 // Should probably be implemented in the curve class.
256 // G4Plane Plane1 = Ray.GetPlane(1);
257 // G4Plane Plane2 = Ray.GetPlane(2);
258
259 // Point in polygon
260 return 1;
261 }
262 return 0;
263}
264
265
266G4int G4ToroidalSurface::SolveQuartic(G4double cc[], G4double ss[] )
267{
268 // From Graphics Gems I by Jochen Schwartz
269
270 G4double coeffs[ 4 ];
271 G4double z, u, v, sub;
272 G4double A, B, C, D;
273 G4double sq_A, p, q, r;
274 G4int i, num;
275
276 // Normal form: x^4 + Ax^3 + Bx^2 + Cx + D = 0
277
278 A = cc[ 3 ] / cc[ 4 ];
279 B = cc[ 2 ] / cc[ 4 ];
280 C = cc[ 1 ] / cc[ 4 ];
281 D = cc[ 0 ] / cc[ 4 ];
282
283 // substitute x = y - A/4 to eliminate cubic term:
284 // x^4 + px^2 + qx + r = 0
285
286 sq_A = A * A;
287 p = - 3.0/8 * sq_A + B;
288 q = 1.0/8 * sq_A * A - 1.0/2 * A * B + C;
289 r = - 3.0/256*sq_A*sq_A + 1.0/16*sq_A*B - 1.0/4*A*C + D;
290
291 if (IsZero(r))
292 {
293 // no absolute term: y(y^3 + py + q) = 0
294
295 coeffs[ 0 ] = q;
296 coeffs[ 1 ] = p;
297 coeffs[ 2 ] = 0;
298 coeffs[ 3 ] = 1;
299
300 num = SolveCubic(coeffs, ss);
301
302 ss[ num++ ] = 0;
303 }
304 else
305 {
306 // solve the resolvent cubic ...
307 coeffs[ 0 ] = 1.0/2 * r * p - 1.0/8 * q * q;
308 coeffs[ 1 ] = - r;
309 coeffs[ 2 ] = - 1.0/2 * p;
310 coeffs[ 3 ] = 1;
311
312 (void) SolveCubic(coeffs, ss);
313
314 // ... and take the one real solution ...
315 z = ss[ 0 ];
316
317 // ... to Build two quadric equations
318 u = z * z - r;
319 v = 2 * z - p;
320
321 if (IsZero(u))
322 u = 0;
323 else if (u > 0)
324 u = std::sqrt(u);
325 else
326 return 0;
327
328 if (IsZero(v))
329 v = 0;
330 else if (v > 0)
331 v = std::sqrt(v);
332 else
333 return 0;
334
335 coeffs[ 0 ] = z - u;
336 coeffs[ 1 ] = q < 0 ? -v : v;
337 coeffs[ 2 ] = 1;
338
339 num = SolveQuadric(coeffs, ss);
340
341 coeffs[ 0 ]= z + u;
342 coeffs[ 1 ] = q < 0 ? v : -v;
343 coeffs[ 2 ] = 1;
344
345 num += SolveQuadric(coeffs, ss + num);
346 }
347
348 // resubstitute
349
350 sub = 1.0/4 * A;
351
352 for (i = 0; i < num; ++i)
353 ss[ i ] -= sub;
354
355 return num;
356}
357
358
359G4int G4ToroidalSurface::SolveCubic(G4double cc[], G4double ss[] )
360{
361 // From Graphics Gems I bu Jochen Schwartz
362 G4int i, num;
363 G4double sub;
364 G4double A, B, C;
365 G4double sq_A, p, q;
366 G4double cb_p, D;
367
368 // Normal form: x^3 + Ax^2 + Bx + C = 0
369 A = cc[ 2 ] / cc[ 3 ];
370 B = cc[ 1 ] / cc[ 3 ];
371 C = cc[ 0 ] / cc[ 3 ];
372
373 // substitute x = y - A/3 to eliminate quadric term:
374 // x^3 +px + q = 0
375 sq_A = A * A;
376 p = 1.0/3 * (- 1.0/3 * sq_A + B);
377 q = 1.0/2 * (2.0/27 * A * sq_A - 1.0/3 * A * B + C);
378
379 // use Cardano's formula
380 cb_p = p * p * p;
381 D = q * q + cb_p;
382
383 if (IsZero(D))
384 {
385 if (IsZero(q)) // one triple solution
386 {
387 ss[ 0 ] = 0;
388 num = 1;
389 }
390 else // one single and one G4double solution
391 {
392 G4double u = std::pow(-q,1./3.);
393 ss[ 0 ] = 2 * u;
394 ss[ 1 ] = - u;
395 num = 2;
396 }
397 }
398 else if (D < 0) // Casus irreducibilis: three real solutions
399 {
400 G4double phi = 1.0/3 * std::acos(-q / std::sqrt(-cb_p));
401 G4double t = 2 * std::sqrt(-p);
402
403 ss[ 0 ] = t * std::cos(phi);
404 ss[ 1 ] = - t * std::cos(phi + pi / 3);
405 ss[ 2 ] = - t * std::cos(phi - pi / 3);
406 num = 3;
407 }
408 else // one real solution
409 {
410 G4double sqrt_D = std::sqrt(D);
411 G4double u = std::pow(sqrt_D - q,1./3.);
412 G4double v = - std::pow(sqrt_D + q,1./3.);
413
414 ss[ 0 ] = u + v;
415 num = 1;
416 }
417
418 // resubstitute
419 sub = 1.0/3 * A;
420
421 for (i = 0; i < num; ++i)
422 ss[ i ] -= sub;
423
424 return num;
425}
426
427
428G4int G4ToroidalSurface::SolveQuadric(G4double cc[], G4double ss[] )
429{
430 // From Graphics Gems I by Jochen Schwartz
431 G4double p, q, D;
432
433 // Normal form: x^2 + px + q = 0
434 p = cc[ 1 ] / (2 * cc[ 2 ]);
435 q = cc[ 0 ] / cc[ 2 ];
436
437 D = p * p - q;
438
439 if (IsZero(D))
440 {
441 ss[ 0 ] = - p;
442 return 1;
443 }
444 else if (D < 0)
445 {
446 return 0;
447 }
448 else if (D > 0)
449 {
450 G4double sqrt_D = std::sqrt(D);
451
452 ss[ 0 ] = sqrt_D - p;
453 ss[ 1 ] = - sqrt_D - p;
454 return 2;
455 }
456
457 return 0;
458}
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
HepGeom::Vector3D< G4double > G4Vector3D
Definition: G4Vector3D.hh:35
void Init(const G4Vector3D &refDirection0, const G4Vector3D &axis0, const G4Point3D &location0)
G4Point3D GetLocation() const
G4Point3D GetBoxMin() const
G4Point3D GetBoxMax() const
Definition: G4Ray.hh:49
const G4Vector3D & GetDir() const
const G4Point3D & GetStart() const
G4double distance
Definition: G4Surface.hh:203
G4BoundingBox3D * bbox
Definition: G4Surface.hh:185
G4Point3D closest_hit
Definition: G4Surface.hh:186
G4double kCarTolerance
Definition: G4Surface.hh:192
G4int Intersect(const G4Ray &)
G4double ClosestDistanceToPoint(const G4Point3D &x)
virtual ~G4ToroidalSurface()
virtual G4Vector3D SurfaceNormal(const G4Point3D &Pt) const