source: trunk/source/geometry/solids/BREPS/src/G4FCylindricalSurface.cc @ 1058

Last change on this file since 1058 was 1058, checked in by garnier, 15 years ago

file release beta

File size: 9.4 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: G4FCylindricalSurface.cc,v 1.16 2006/06/29 18:42:14 gunter Exp $
28// GEANT4 tag $Name: geant4-09-02-ref-02 $
29//
30// ----------------------------------------------------------------------
31// GEANT 4 class source file
32//
33// G4FCylindricalSurface.cc
34//
35// ----------------------------------------------------------------------
36
37#include "G4FCylindricalSurface.hh"
38#include "G4Sort.hh"
39
40
41G4FCylindricalSurface::G4FCylindricalSurface()
42  : length(1.)
43{
44}
45
46
47G4FCylindricalSurface::~G4FCylindricalSurface()
48{
49}
50
51
52G4FCylindricalSurface::G4FCylindricalSurface( const G4Point3D& o, 
53                                              const G4Vector3D& a,
54                                              G4double r, 
55                                              G4double l
56                                            ) 
57{ 
58  //  make a G4FCylindricalSurface with origin o, axis a,
59  //  radius r, and length l
60  G4Vector3D dir(1,1,1);
61  Position.Init(dir, a, o);
62
63  origin = o;
64  radius = r;
65 
66  //  Require length to be positive or zero
67  if ( l >= 0.0 )
68    length = l;
69  else 
70  {
71    G4cerr << "Error in G4FCylindricalSurface::G4FCylindricalSurface"
72           << "--asked for negative length\n"
73           << "\tDefault length of 0.0 is used.\n";
74
75    length = 0.0;
76  }
77
78  //  Require radius to be non-negative (i.e., allow zero)
79  if ( r >= 0.0 )
80    radius = r;
81  else 
82  {
83    G4cerr << "Error in G4FCylindricalSurface::G4FCylindricalSurface"
84           << "--asked for negative radius\n"
85           << "\tDefault value of 0.0 is used.\n";
86   
87    radius = 0.0;
88  }
89}
90
91
92const char* G4FCylindricalSurface::NameOf() const 
93{
94  return "G4FCylindricalSurface"; 
95}
96
97
98void G4FCylindricalSurface::PrintOn( std::ostream& os ) const
99{ 
100  os << "G4FCylindricalSurface with origin: " << origin << "\t"
101     << "and axis: " << Position.GetAxis() << "\n"
102     << "\t radius: " << radius << "\t and length: "
103     << length << "\n";
104}
105
106
107G4double G4FCylindricalSurface::Area() const 
108{
109  return ( 2.0 * pi * radius * length );
110}
111
112
113// Added 18.7-95
114// Modified by L. Broglia (01/12/98)
115void G4FCylindricalSurface::CalcBBox()
116{
117  // Finds the bounds of the surface iow
118  // calculates the bounds for a bounding box
119  // to the surface. The bounding box is used
120  // for a preliminary check of intersection.
121  G4Point3D Max = G4Point3D(-PINFINITY);
122  G4Point3D Min = G4Point3D( PINFINITY);
123
124  G4Point3D Tmp; 
125  G4Point3D Origin    = Position.GetLocation();
126  G4Point3D EndOrigin = G4Point3D( Origin + (length*Position.GetAxis()) );
127  G4Point3D Radius(radius, radius, 0);
128 
129  // Default BBox
130  G4Point3D Tolerance(kCarTolerance, kCarTolerance, kCarTolerance);
131  G4Point3D BoxMin(Origin-Tolerance);
132  G4Point3D BoxMax(Origin+Tolerance);
133
134  bbox = new G4BoundingBox3D();
135  bbox->Init(BoxMin, BoxMax);
136
137
138  Tmp = (Origin - Radius);
139  bbox->Extend(Tmp);
140 
141  Tmp = Origin + Radius;
142  bbox->Extend(Tmp);
143
144  Tmp = EndOrigin - Radius;
145  bbox->Extend(Tmp);
146 
147  Tmp = EndOrigin + Radius;
148  bbox->Extend(Tmp);
149}
150
151
152G4int G4FCylindricalSurface::Intersect( const G4Ray& ry ) 
153{
154  // This function count the number of intersections of a
155  // bounded cylindrical surface by a ray.
156  // At first, calculates the intersections with the infinite
157  // cylindrical surfsace. After, count the intersections within the
158  // finite cylindrical surface boundaries, and set "distance" to the
159  // closest distance from the start point to the nearest intersection
160  // If the point is on the surface it returns or the intersection with
161  // the opposite surface or kInfinity
162
163  // If no intersection is founded, set distance = kInfinity and
164  // return 0
165
166  distance    = kInfinity;
167  closest_hit = PINFINITY;
168
169  // origin and direction of the ray
170  G4Point3D  x    = ry.GetStart();
171  G4Vector3D dhat = ry.GetDir();
172
173  // cylinder axis
174  G4Vector3D ahat  = Position.GetAxis();
175 
176  //  array of solutions in distance along the ray
177  G4double s[2];
178  s[0]=-1.0;
179  s[1]=-1.0;
180
181  // calculate the two intersections (quadratic equation)   
182  G4Vector3D gamma =  G4Vector3D( x - Position.GetLocation() );
183 
184  G4double ga = gamma * ahat;
185  G4double da = dhat * ahat;
186
187  G4double A = da * da - dhat * dhat;
188  G4double B = 2 * ( -gamma * dhat + ga * da );
189  G4double C =  -gamma * gamma + ga * ga  + radius * radius ;
190
191  G4double radical = B * B  -  4.0 * A * C; 
192
193  if ( radical < 0.0 ) 
194    // no intersection
195    return 0;
196  else 
197  {
198    G4double root = std::sqrt( radical );
199    s[0] = ( - B + root ) / ( 2. * A );
200    s[1] = ( - B - root ) / ( 2. * A );
201  }
202 
203  // validity of the solutions
204  // the hit point must be into the bounding box of the cylindrical surface
205  G4Point3D p0 = G4Point3D( x + s[0]*dhat );
206  G4Point3D p1 = G4Point3D( x + s[1]*dhat );
207
208  if( !GetBBox()->Inside(p0) )
209    s[0] = kInfinity;
210
211  if( !GetBBox()->Inside(p1) )
212    s[1] = kInfinity;
213 
214  //  now loop over each positive solution, keeping the first one (smallest
215  //  distance along the Ray) which is within the boundary of the sub-shape
216  G4int nbinter = 0;
217  distance = kInfinity;
218
219  for ( G4int i = 0; i < 2; i++ ) 
220  { 
221    if(s[i] < kInfinity) {
222      if ( s[i] >= kCarTolerance*0.5 ) {
223        nbinter ++;
224        // real intersection
225        // set the distance if it is the smallest
226        if( distance > s[i]*s[i]) {
227          distance = s[i]*s[i];
228        }
229      }
230    }   
231  }
232
233  return nbinter;
234}
235
236
237G4double G4FCylindricalSurface::HowNear( const G4Vector3D& x ) const
238{
239  // Shortest distance from the point x to the G4FCylindricalSurface.
240  // The distance will be always positive
241
242  G4double   hownear;
243
244  G4Vector3D upcorner = G4Vector3D ( radius, 0 , origin.z()+length);
245  G4Vector3D downcorner = G4Vector3D ( radius, 0 , origin.z());
246  G4Vector3D xd; 
247 
248  xd = G4Vector3D ( std::sqrt ( x.x()*x.x() + x.y()*x.y() ) , 0 , x.z() );
249   
250 
251  G4double Zinter = (xd.z()) ;
252 
253  if ( ((Zinter >= downcorner.z()) && (Zinter <=upcorner.z())) ) {
254    hownear = std::fabs( radius - xd.x() );
255  } else {
256    hownear = std::min ( (xd-upcorner).mag() , (xd-downcorner).mag() );
257  }
258
259  return hownear;
260}
261
262G4int G4FCylindricalSurface::WithinBoundary( const G4Vector3D& x ) const
263{
264  //  return 1 if point x is within the boundaries of the G4FCylindricalSurface
265  //  return 0 otherwise (assume it is on the cylinder)
266  if ( std::fabs( ( x - Position.GetLocation()) * Position.GetAxis() )
267       <= 0.5 * length )
268    return 1;
269  else
270    return 0;
271}
272
273
274G4double G4FCylindricalSurface::Scale() const
275{
276  //  Returns the radius of a G4FCylindricalSurface unless it is zero,
277  //  in which case returns the length.
278  //  Used for Scale-invariant tests of surface thickness.
279  if ( radius == 0.0 )
280    return length;
281  else
282    return radius;
283}
284
285
286G4Vector3D G4FCylindricalSurface::SurfaceNormal( const G4Point3D& p ) const
287{
288  //  return the Normal unit vector to the G4CylindricalSurface at a point
289  //  p on (or nearly on) the G4CylindricalSurface
290 
291  G4Vector3D n = G4Vector3D( ( p - Position.GetLocation() ) - 
292                           ( ( p - Position.GetLocation()) *
293                               Position.GetAxis() ) * Position.GetAxis() );
294  G4double nmag = n.mag();
295 
296  if ( nmag != 0.0 )
297    n = n * (1/nmag);
298
299  if( !sameSense )
300    n = -n;
301 
302  return n;
303}
304
305G4int G4FCylindricalSurface::Inside ( const G4Vector3D& x ) const
306{ 
307  //  Return 0 if point x is outside G4CylindricalSurface, 1 if Inside.
308  //  Outside means that the distance to the G4CylindricalSurface would
309  //  be negative.
310  //  Use the HowNear function to calculate this distance.
311  if ( HowNear( x ) >= -0.5*kCarTolerance )
312    return 1;
313  else
314    return 0; 
315}
316
317
318void G4FCylindricalSurface::resize( G4double r, G4double l )
319{
320  //  Resize a G4FCylindricalSurface to a new radius r and new length l
321  //  Require radius to be non-negative
322  if ( r >= 0.0 )
323    radius = r;
324  else 
325  {
326    G4cerr << "Error in G4FCylindricalSurface::resize"
327           << "--asked for negative radius\n"
328           << "\tOriginal value of " << radius << " is retained.\n";
329  }
330
331  //  Require length to be positive
332  if ( l > 0.0 )
333    length = l;
334  else 
335  {
336    G4cerr << "Error in G4FCylindricalSurface::resize"
337           << "--asked for negative or zero length\n"
338           << "\tOriginal value of " << length << " is retained.\n";
339  }
340}
Note: See TracBrowser for help on using the repository browser.