Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4IntersectingCone.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// --------------------------------------------------------------------
31// GEANT 4 class source file
32//
33//
34// G4IntersectingCone.cc
35//
36// Implementation of a utility class which calculates the intersection
37// of an arbitrary line with a fixed cone
38// --------------------------------------------------------------------
39
40#include "G4IntersectingCone.hh"
42
43//
44// Constructor
45//
47 const G4double z[2] )
48{
49 static const G4double halfCarTolerance
51
52 //
53 // What type of cone are we?
54 //
55 type1 = (std::fabs(z[1]-z[0]) > std::fabs(r[1]-r[0]));
56
57 if (type1)
58 {
59 B = (r[1]-r[0])/(z[1]-z[0]); // tube like
60 A = 0.5*( r[1]+r[0] - B*(z[1]+z[0]) );
61 }
62 else
63 {
64 B = (z[1]-z[0])/(r[1]-r[0]); // disk like
65 A = 0.5*( z[1]+z[0] - B*(r[1]+r[0]) );
66 }
67 //
68 // Calculate extent
69 //
70 if (r[0] < r[1])
71 {
72 rLo = r[0]-halfCarTolerance; rHi = r[1]+halfCarTolerance;
73 }
74 else
75 {
76 rLo = r[1]-halfCarTolerance; rHi = r[0]+halfCarTolerance;
77 }
78
79 if (z[0] < z[1])
80 {
81 zLo = z[0]-halfCarTolerance; zHi = z[1]+halfCarTolerance;
82 }
83 else
84 {
85 zLo = z[1]-halfCarTolerance; zHi = z[0]+halfCarTolerance;
86 }
87}
88
89
90//
91// Fake default constructor - sets only member data and allocates memory
92// for usage restricted to object persistency.
93//
95 : zLo(0.), zHi(0.), rLo(0.), rHi(0.), type1(false), A(0.), B(0.)
96{
97}
98
99
100//
101// Destructor
102//
104{
105}
106
107
108//
109// HitOn
110//
111// Check r or z extent, as appropriate, to see if the point is possibly
112// on the cone.
113//
115 const G4double z )
116{
117 //
118 // Be careful! The inequalities cannot be "<=" and ">=" here without
119 // punching a tiny hole in our shape!
120 //
121 if (type1)
122 {
123 if (z < zLo || z > zHi) return false;
124 }
125 else
126 {
127 if (r < rLo || r > rHi) return false;
128 }
129
130 return true;
131}
132
133
134//
135// LineHitsCone
136//
137// Calculate the intersection of a line with our conical surface, ignoring
138// any phi division
139//
141 const G4ThreeVector &v,
142 G4double *s1, G4double *s2 )
143{
144 if (type1)
145 {
146 return LineHitsCone1( p, v, s1, s2 );
147 }
148 else
149 {
150 return LineHitsCone2( p, v, s1, s2 );
151 }
152}
153
154
155//
156// LineHitsCone1
157//
158// Calculate the intersections of a line with a conical surface. Only
159// suitable if zPlane[0] != zPlane[1].
160//
161// Equation of a line:
162//
163// x = x0 + s*tx y = y0 + s*ty z = z0 + s*tz
164//
165// Equation of a conical surface:
166//
167// x**2 + y**2 = (A + B*z)**2
168//
169// Solution is quadratic:
170//
171// a*s**2 + b*s + c = 0
172//
173// where:
174//
175// a = x0**2 + y0**2 - (A + B*z0)**2
176//
177// b = 2*( x0*tx + y0*ty - (A*B - B*B*z0)*tz)
178//
179// c = tx**2 + ty**2 - (B*tz)**2
180//
181// Notice, that if a < 0, this indicates that the two solutions (assuming
182// they exist) are in opposite cones (that is, given z0 = -A/B, one z < z0
183// and the other z > z0). For our shapes, the invalid solution is one
184// which produces A + Bz < 0, or the one where Bz is smallest (most negative).
185// Since Bz = B*s*tz, if B*tz > 0, we want the largest s, otherwise,
186// the smaller.
187//
188// If there are two solutions on one side of the cone, we want to make
189// sure that they are on the "correct" side, that is A + B*z0 + s*B*tz >= 0.
190//
191// If a = 0, we have a linear problem: s = c/b, which again gives one solution.
192// This should be rare.
193//
194// For b*b - 4*a*c = 0, we also have one solution, which is almost always
195// a line just grazing the surface of a the cone, which we want to ignore.
196// However, there are two other, very rare, possibilities:
197// a line intersecting the z axis and either:
198// 1. At the same angle std::atan(B) to just miss one side of the cone, or
199// 2. Intersecting the cone apex (0,0,-A/B)
200// We *don't* want to miss these! How do we identify them? Well, since
201// this case is rare, we can at least swallow a little more CPU than we would
202// normally be comfortable with. Intersection with the z axis means
203// x0*ty - y0*tx = 0. Case (1) means a==0, and we've already dealt with that
204// above. Case (2) means a < 0.
205//
206// Now: x0*tx + y0*ty = 0 in terms of roundoff error. We can write:
207// Delta = x0*tx + y0*ty
208// b = 2*( Delta - (A*B + B*B*z0)*tz )
209// For:
210// b*b - 4*a*c = epsilon
211// where epsilon is small, then:
212// Delta = epsilon/2/B
213//
215 const G4ThreeVector &v,
216 G4double *s1, G4double *s2 )
217{
218 G4double x0 = p.x(), y0 = p.y(), z0 = p.z();
219 G4double tx = v.x(), ty = v.y(), tz = v.z();
220
221 G4double a = tx*tx + ty*ty - sqr(B*tz);
222 G4double b = 2*( x0*tx + y0*ty - (A*B + B*B*z0)*tz);
223 G4double c = x0*x0 + y0*y0 - sqr(A + B*z0);
224
225 G4double radical = b*b - 4*a*c;
226
227 if (radical < -1E-6*std::fabs(b)) { return 0; } // No solution
228
229 if (radical < 1E-6*std::fabs(b))
230 {
231 //
232 // The radical is roughly zero: check for special, very rare, cases
233 //
234 if (std::fabs(a) > 1/kInfinity)
235 {
236 if(B==0.) { return 0; }
237 if ( std::fabs(x0*ty - y0*tx) < std::fabs(1E-6/B) )
238 {
239 *s1 = -0.5*b/a;
240 return 1;
241 }
242 return 0;
243 }
244 }
245 else
246 {
247 radical = std::sqrt(radical);
248 }
249
250 if (a > 1/kInfinity)
251 {
252 G4double sa, sb, q = -0.5*( b + (b < 0 ? -radical : +radical) );
253 sa = q/a;
254 sb = c/q;
255 if (sa < sb) { *s1 = sa; *s2 = sb; } else { *s1 = sb; *s2 = sa; }
256 if (A + B*(z0+(*s1)*tz) < 0) { return 0; }
257 return 2;
258 }
259 else if (a < -1/kInfinity)
260 {
261 G4double sa, sb, q = -0.5*( b + (b < 0 ? -radical : +radical) );
262 sa = q/a;
263 sb = c/q;
264 *s1 = (B*tz > 0)^(sa > sb) ? sb : sa;
265 return 1;
266 }
267 else if (std::fabs(b) < 1/kInfinity)
268 {
269 return 0;
270 }
271 else
272 {
273 *s1 = -c/b;
274 if (A + B*(z0+(*s1)*tz) < 0) { return 0; }
275 return 1;
276 }
277}
278
279
280//
281// LineHitsCone2
282//
283// See comments under LineHitsCone1. In this routine, case2, we have:
284//
285// Z = A + B*R
286//
287// The solution is still quadratic:
288//
289// a = tz**2 - B*B*(tx**2 + ty**2)
290//
291// b = 2*( (z0-A)*tz - B*B*(x0*tx+y0*ty) )
292//
293// c = ( (z0-A)**2 - B*B*(x0**2 + y0**2) )
294//
295// The rest is much the same, except some details.
296//
297// a > 0 now means we intersect only once in the correct hemisphere.
298//
299// a > 0 ? We only want solution which produces R > 0.
300// since R = (z0+s*tz-A)/B, for tz/B > 0, this is the largest s
301// for tz/B < 0, this is the smallest s
302// thus, same as in case 1 ( since sign(tz/B) = sign(tz*B) )
303//
305 const G4ThreeVector &v,
306 G4double *s1, G4double *s2 )
307{
308 G4double x0 = p.x(), y0 = p.y(), z0 = p.z();
309 G4double tx = v.x(), ty = v.y(), tz = v.z();
310
311
312 // Special case which might not be so rare: B = 0 (precisely)
313 //
314 if (B==0)
315 {
316 if (std::fabs(tz) < 1/kInfinity) { return 0; }
317
318 *s1 = (A-z0)/tz;
319 return 1;
320 }
321
322 G4double B2 = B*B;
323
324 G4double a = tz*tz - B2*(tx*tx + ty*ty);
325 G4double b = 2*( (z0-A)*tz - B2*(x0*tx + y0*ty) );
326 G4double c = sqr(z0-A) - B2*( x0*x0 + y0*y0 );
327
328 G4double radical = b*b - 4*a*c;
329
330 if (radical < -1E-6*std::fabs(b)) { return 0; } // No solution
331
332 if (radical < 1E-6*std::fabs(b))
333 {
334 //
335 // The radical is roughly zero: check for special, very rare, cases
336 //
337 if (std::fabs(a) > 1/kInfinity)
338 {
339 if ( std::fabs(x0*ty - y0*tx) < std::fabs(1E-6/B) )
340 {
341 *s1 = -0.5*b/a;
342 return 1;
343 }
344 return 0;
345 }
346 }
347 else
348 {
349 radical = std::sqrt(radical);
350 }
351
352 if (a < -1/kInfinity)
353 {
354 G4double sa, sb, q = -0.5*( b + (b < 0 ? -radical : +radical) );
355 sa = q/a;
356 sb = c/q;
357 if (sa < sb) { *s1 = sa; *s2 = sb; } else { *s1 = sb; *s2 = sa; }
358 if ((z0 + (*s1)*tz - A)/B < 0) { return 0; }
359 return 2;
360 }
361 else if (a > 1/kInfinity)
362 {
363 G4double sa, sb, q = -0.5*( b + (b < 0 ? -radical : +radical) );
364 sa = q/a;
365 sb = c/q;
366 *s1 = (tz*B > 0)^(sa > sb) ? sb : sa;
367 return 1;
368 }
369 else if (std::fabs(b) < 1/kInfinity)
370 {
371 return 0;
372 }
373 else
374 {
375 *s1 = -c/b;
376 if ((z0 + (*s1)*tz - A)/B < 0) { return 0; }
377 return 1;
378 }
379}
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
double z() const
double x() const
double y() const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
G4bool HitOn(const G4double r, const G4double z)
G4int LineHitsCone(const G4ThreeVector &p, const G4ThreeVector &v, G4double *s1, G4double *s2)
G4int LineHitsCone1(const G4ThreeVector &p, const G4ThreeVector &v, G4double *s1, G4double *s2)
G4IntersectingCone(const G4double r[2], const G4double z[2])
G4int LineHitsCone2(const G4ThreeVector &p, const G4ThreeVector &v, G4double *s1, G4double *s2)
T sqr(const T &x)
Definition: templates.hh:145