Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4FConicalSurface.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 // G4FConicalSurface.cc
33 //
34 // ----------------------------------------------------------------------
35 
36 #include "G4FConicalSurface.hh"
37 #include "G4PhysicalConstants.hh"
38 #include "G4Sort.hh"
39 #include "G4CircularCurve.hh"
40 
41 
43 {
44  length = 1.0;
45  small_radius = 0.0;
46  large_radius = 1.0;
48 }
49 
51 {
52 }
53 
55  const G4Vector3D& a,
56  G4double l,
57  G4double srad,
58  G4double lr
59  )
60 {
61  // Make a G4FConicalSurface with origin o, axis a, length l, small radius
62  // srad, and large radius lr. The angle is calculated below and the SetAngle
63  // function of G4ConicalSurface is used to set it properly from the default
64  // value used above in the initialization.
65 
66  // Create the position with origin o, axis a, and a direction
67 
68  G4Vector3D dir(1,1,1);
69  Position.Init(dir, a, o);
70  origin = o;
71 
72  // Require length to be nonnegative
73  if (l >=0)
74  length = l;
75  else
76  {
77  std::ostringstream message;
78  message << "Negative length." << G4endl
79  << "Default length of 0.0 is used.";
80  G4Exception("G4FConicalSurface::G4FConicalSurface()",
81  "GeomSolids1001", JustWarning, message);
82 
83  length = 0.0;
84  }
85 
86  // Require small radius to be non-negative (i.e., allow zero)
87  if ( srad >= 0.0 )
88  small_radius = srad;
89  else
90  {
91  std::ostringstream message;
92  message << "Negative small radius." << G4endl
93  << "Default value of 0.0 is used.";
94  G4Exception("G4FConicalSurface::G4FConicalSurface()",
95  "GeomSolids1001", JustWarning, message);
96 
97  small_radius = 0.0;
98  }
99 
100  // Require large radius to exceed small radius
101  if ( lr > small_radius )
102  large_radius = lr;
103  else
104  {
105  std::ostringstream message;
106  message << "Large radius must exceed small radius" << G4endl
107  << "Default value of small radius +1 is used.";
108  G4Exception("G4FConicalSurface::G4FConicalSurface()",
109  "GeomSolids1001", JustWarning, message);
110 
111  large_radius = small_radius + 1.0;
112  }
113 
114  // Calculate the angle of the G4ConicalSurface from the length and radii
116 }
117 
118 
119 const char* G4FConicalSurface::Name() const
120 {
121  return "G4FConicalSurface";
122 }
123 
124 // Modified by L. Broglia (01/12/98)
126 {
127  G4Point3D Max = G4Point3D(-PINFINITY);
128  G4Point3D Min = G4Point3D( PINFINITY);
129  G4Point3D Tmp;
130 
131  G4Point3D Origin = Position.GetLocation();
132  G4Point3D EndOrigin = G4Point3D( Origin + (length * Position.GetAxis()) );
133 
134  G4double radius = large_radius;
135  G4Point3D Radius(radius, radius, 0);
136 
137  // Default BBox
139  G4Point3D BoxMin(Origin-Tolerance);
140  G4Point3D BoxMax(Origin+Tolerance);
141 
142  bbox = new G4BoundingBox3D();
143  bbox->Init(BoxMin, BoxMax);
144 
145  Tmp = (Origin - Radius);
146  bbox->Extend(Tmp);
147 
148  Tmp = Origin + Radius;
149  bbox->Extend(Tmp);
150 
151  Tmp = EndOrigin - Radius;
152  bbox->Extend(Tmp);
153 
154  Tmp = EndOrigin + Radius;
155  bbox->Extend(Tmp);
156 }
157 
158 
159 void G4FConicalSurface::PrintOn( std::ostream& os ) const
160 {
161  // printing function using C++ std::ostream class
162  os << "G4FConicalSurface with origin: " << origin << "\t"
163  << "and axis: " << Position.GetAxis() << "\n"
164  << "\t small radius: " << small_radius
165  << "\t large radius: " << large_radius
166  << "\t and length: " << length << "\n";
167 }
168 
169 
171 {
172  return ( origin == c.origin &&
173  Position.GetAxis() == c.Position.GetAxis() &&
174  small_radius == c.small_radius &&
175  large_radius == c.large_radius &&
176  length == c.length &&
177  tan_angle == c.tan_angle );
178 }
179 
180 
182 {
183  // return 1 if point x is within the boundaries of the G4FConicalSurface
184  // return 0 otherwise (assume it is on the G4ConicalSurface)
185  G4Vector3D q = G4Vector3D( x - origin );
186 
187  G4double qmag = q.mag();
188  G4double ss = std::sin( std::atan2(large_radius-small_radius, length) );
189  G4double ls = small_radius / ss;
190  G4double ll = large_radius / ss;
191 
192  if ( ( qmag >= ls ) && ( qmag <= ll ) )
193  return 1;
194  else
195  return 0;
196 }
197 
198 
200 {
201  // Returns the small radius of a G4FConicalSurface unless it is zero, in
202  // which case returns the large radius.
203  // Used for Scale-invariant tests of surface thickness.
204  if ( small_radius == 0.0 )
205  return large_radius;
206  else
207  return small_radius;
208 }
209 
210 
212 {
213  // Returns the Area of a G4FConicalSurface
215 
216  return ( pi * ( small_radius + large_radius ) *
217  std::sqrt( length * length + rdif * rdif ) );
218 }
219 
220 
222 {
223  // Resize a G4FConicalSurface to a new length l, and new radii srad and lr.
224  // Must Reset angle of the G4ConicalSurface as well based on these new
225  // values.
226  // Require length to be non-negative
227 
228  // if ( l > 0.0 )
229  if ( l >= 0.0 )
230  length = l;
231  else
232  {
233  std::ostringstream message;
234  message << "Negative length." << G4endl
235  << "Original value of " << length << " is retained.";
236  G4Exception("G4FConicalSurface::resize()",
237  "GeomSolids1001", JustWarning, message);
238  }
239 
240  // Require small radius to be non-negative (i.e., allow zero)
241  if ( srad >= 0.0 )
242  small_radius = srad;
243  else
244  {
245  std::ostringstream message;
246  message << "Negative small radius." << G4endl
247  << "Original value of " << small_radius << " is retained.";
248  G4Exception("G4FConicalSurface::resize()",
249  "GeomSolids1001", JustWarning, message);
250  }
251 
252  // Require large radius to exceed small radius
253  if ( lr > small_radius )
254  large_radius = lr;
255  else
256  {
257  G4double r = small_radius + 1.0;
258  lr = ( large_radius <= small_radius ) ? r : large_radius;
259  large_radius = lr;
260 
261  std::ostringstream message;
262  message << "Large radius must exceed small radius." << G4endl
263  << "Default value of " << large_radius << " is used.";
264  G4Exception("G4FConicalSurface::resize()",
265  "GeomSolids1001", JustWarning, message);
266  }
267 
268  // Calculate the angle of the G4ConicalSurface from the length and radii
270 
271 }
272 
273 
275 {
276  // This function count the number of intersections of a
277  // bounded conical surface by a ray.
278  // At first, calculates the intersections with the semi-infinite
279  // conical surfsace. After, count the intersections within the
280  // finite conical surface boundaries, and set "distance" to the
281  // closest distance from the start point to the nearest intersection
282  // If the point is on the surface it returns or the intersection with
283  // the opposite surface or kInfinity
284  // If no intersection is founded, set distance = kInfinity and
285  // return 0
286 
287  distance = kInfinity;
289 
290  // origin and direction of the ray
291  G4Point3D x = ry.GetStart();
292  G4Vector3D dhat = ry.GetDir();
293 
294  // cone angle and axis
295  G4double ta = tan_angle;
296  G4Vector3D ahat = Position.GetAxis();
297 
298  // array of solutions in distance along the ray
299  G4double sol[2];
300  sol[0]=-1.0;
301  sol[1]=-1.0;
302 
303  // calculate the two intersections (quadratic equation)
304  G4Vector3D gamma = G4Vector3D( x - Position.GetLocation() );
305 
306  G4double t = 1 + ta * ta;
307  G4double ga = gamma * ahat;
308  G4double da = dhat * ahat;
309 
310  G4double A = t * da * da - dhat * dhat;
311  G4double B = 2 * ( -gamma * dhat + t * ga * da - large_radius * ta * da);
312  G4double C = ( -gamma * gamma + t * ga * ga
313  - 2 * large_radius * ta * ga
315 
316  G4double radical = B * B - 4.0 * A * C;
317 
318  if ( radical < 0.0 )
319  // no intersection
320  return 0;
321  else
322  {
323  G4double root = std::sqrt( radical );
324  sol[0] = ( - B + root ) / ( 2. * A );
325  sol[1] = ( - B - root ) / ( 2. * A );
326  }
327 
328  // validity of the solutions
329  // the hit point must be into the bounding box of the conical surface
330  G4Point3D p0 = G4Point3D( x + sol[0]*dhat );
331  G4Point3D p1 = G4Point3D( x + sol[1]*dhat );
332 
333  if( !GetBBox()->Inside(p0) )
334  sol[0] = kInfinity;
335 
336  if( !GetBBox()->Inside(p1) )
337  sol[1] = kInfinity;
338 
339  // now loop over each positive solution, keeping the first one (smallest
340  // distance along the ray) which is within the boundary of the sub-shape
341  G4int nbinter = 0;
342  distance = kInfinity;
343 
344  for ( G4int i = 0; i < 2; i++ )
345  {
346  if(sol[i] < kInfinity) {
347  if ( (sol[i] > kCarTolerance*0.5) ) {
348  nbinter++;
349  if ( distance > (sol[i]*sol[i]) ) {
350  distance = sol[i]*sol[i];
351  }
352  }
353  }
354  }
355 
356  return nbinter;
357 }
358 
359 
361 {
362 // Shortest distance from the point x to the G4FConicalSurface.
363 // The distance will be always positive
364 // This function works only with Cone axis equal (0,0,1) or (0,0,-1), it project
365 // the surface and the point on the x,z plane and compute the distance in analytical
366 // way
367 
368  G4double hownear ;
369 
370  G4Vector3D upcorner = G4Vector3D ( small_radius, 0 , origin.z()+Position.GetAxis().z()*length);
371  G4Vector3D downcorner = G4Vector3D ( large_radius, 0 , origin.z());
372  G4Vector3D xd;
373 
374  xd = G4Vector3D ( std::sqrt ( x.x()*x.x() + x.y()*x.y() ) , 0 , x.z() );
375 
376  G4double r = (upcorner.z() - downcorner.z()) / (upcorner.x() - downcorner.x());
377  G4double q = (downcorner.z()*upcorner.x() - upcorner.z()*downcorner.x()) /
378  (upcorner.x() - downcorner.x());
379 
380  G4double Zinter = (xd.z()*r*r + xd.x()*r +q)/(1+r*r) ;
381 
382  if ( ((Zinter >= downcorner.z()) && (Zinter <=upcorner.z())) ||
383  ((Zinter >= upcorner.z()) && (Zinter <=downcorner.z())) ) {
384  hownear = std::fabs(r*xd.x()-xd.z()+q)/std::sqrt(1+r*r);
385  return hownear;
386  } else {
387  hownear = std::min ( (xd-upcorner).mag() , (xd-downcorner).mag() );
388  return hownear;
389  }
390 }
391 
392 
394 {
395  // return the Normal unit vector to the G4ConicalSurface at a point p
396  // on (or nearly on) the G4ConicalSurface
397  G4Vector3D ss = G4Vector3D( p - origin );
398  G4double da = ss * Position.GetAxis();
399  G4double r = std::sqrt( ss*ss - da*da);
400  G4double z = tan_angle * r;
401 
402  if (Position.GetAxis().z() < 0)
403  z = -z;
404 
405  G4Vector3D n(p.x(), p.y(), z);
406  n = n.unit();
407 
408  if( !sameSense )
409  n = -n;
410 
411  return n;
412 }
413 
415 {
416  // Return 0 if point x is outside G4ConicalSurface, 1 if Inside.
417  if ( HowNear( x ) >= -0.5*kCarTolerance )
418  return 1;
419  else
420  return 0;
421 }
422