source: trunk/source/geometry/solids/BREPS/src/G4FConicalSurface.cc @ 1358

Last change on this file since 1358 was 1337, checked in by garnier, 14 years ago

tag geant4.9.4 beta 1 + modifs locales

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