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

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

tag geant4.9.4 beta 1 + modifs locales

File size: 9.4 KB
RevLine 
[831]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 $
[1337]28// GEANT4 tag $Name: geant4-09-04-beta-01 $
[831]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.