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
G4VCSGfaceted.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// the GEANT4 collaboration.
27//
28// By copying, distributing or modifying the Program (or any work
29// based on the Program) you indicate your acceptance of this statement,
30// and all its terms.
31//
32// $Id$
33//
34//
35// --------------------------------------------------------------------
36// GEANT 4 class source file
37//
38//
39// G4VCSGfaceted.cc
40//
41// Implementation of the virtual class of a CSG type shape that is built
42// entirely out of G4VCSGface faces.
43//
44// --------------------------------------------------------------------
45
46#include "G4VCSGfaceted.hh"
47#include "G4VCSGface.hh"
48#include "G4SolidExtentList.hh"
49
50#include "G4VoxelLimits.hh"
51#include "G4AffineTransform.hh"
52
53#include "Randomize.hh"
54
55#include "G4Polyhedron.hh"
56#include "G4VGraphicsScene.hh"
57#include "G4NURBS.hh"
58#include "G4NURBSbox.hh"
59#include "G4VisExtent.hh"
60
61//
62// Constructor
63//
65 : G4VSolid(name),
66 numFace(0), faces(0), fCubicVolume(0.), fSurfaceArea(0.), fpPolyhedron(0),
67 fStatistics(1000000), fCubVolEpsilon(0.001), fAreaAccuracy(-1.)
68{
69}
70
71
72//
73// Fake default constructor - sets only member data and allocates memory
74// for usage restricted to object persistency.
75//
77 : G4VSolid(a),
78 numFace(0), faces(0), fCubicVolume(0.), fSurfaceArea(0.), fpPolyhedron(0),
79 fStatistics(1000000), fCubVolEpsilon(0.001), fAreaAccuracy(-1.)
80{
81}
82
83//
84// Destructor
85//
87{
89 delete fpPolyhedron;
90}
91
92
93//
94// Copy constructor
95//
97 : G4VSolid( source )
98{
99 fStatistics = source.fStatistics;
100 fCubVolEpsilon = source.fCubVolEpsilon;
101 fAreaAccuracy = source.fAreaAccuracy;
102
103 CopyStuff( source );
104}
105
106
107//
108// Assignment operator
109//
111{
112 if (&source == this) { return *this; }
113
114 // Copy base class data
115 //
116 G4VSolid::operator=(source);
117
118 // Copy data
119 //
120 fStatistics = source.fStatistics;
121 fCubVolEpsilon = source.fCubVolEpsilon;
122 fAreaAccuracy = source.fAreaAccuracy;
123
124 DeleteStuff();
125 CopyStuff( source );
126
127 return *this;
128}
129
130
131//
132// CopyStuff (protected)
133//
134// Copy the contents of source
135//
137{
138 numFace = source.numFace;
139 if (numFace == 0) { return; } // odd, but permissable?
140
141 faces = new G4VCSGface*[numFace];
142
143 G4VCSGface **face = faces,
144 **sourceFace = source.faces;
145 do
146 {
147 *face = (*sourceFace)->Clone();
148 } while( ++sourceFace, ++face < faces+numFace );
149 fCubicVolume = source.fCubicVolume;
150 fSurfaceArea = source.fSurfaceArea;
151 fpPolyhedron = 0;
152}
153
154
155//
156// DeleteStuff (protected)
157//
158// Delete all allocated objects
159//
161{
162 if (numFace)
163 {
164 G4VCSGface **face = faces;
165 do
166 {
167 delete *face;
168 } while( ++face < faces + numFace );
169
170 delete [] faces;
171 }
172}
173
174
175//
176// CalculateExtent
177//
179 const G4VoxelLimits &voxelLimit,
180 const G4AffineTransform &transform,
181 G4double &min,
182 G4double &max ) const
183{
184 G4SolidExtentList extentList( axis, voxelLimit );
185
186 //
187 // Loop over all faces, checking min/max extent as we go.
188 //
189 G4VCSGface **face = faces;
190 do
191 {
192 (*face)->CalculateExtent( axis, voxelLimit, transform, extentList );
193 } while( ++face < faces + numFace );
194
195 //
196 // Return min/max value
197 //
198 return extentList.GetExtent( min, max );
199}
200
201
202//
203// Inside
204//
205// It could be a good idea to override this virtual
206// member to add first a simple test (such as spherical
207// test or whatnot) and to call this version only if
208// the simplier test fails.
209//
211{
212 EInside answer=kOutside;
213 G4VCSGface **face = faces;
214 G4double best = kInfinity;
215 do
216 {
217 G4double distance;
218 EInside result = (*face)->Inside( p, kCarTolerance/2, &distance );
219 if (result == kSurface) { return kSurface; }
220 if (distance < best)
221 {
222 best = distance;
223 answer = result;
224 }
225 } while( ++face < faces + numFace );
226
227 return answer;
228}
229
230
231//
232// SurfaceNormal
233//
235{
236 G4ThreeVector answer;
237 G4VCSGface **face = faces;
238 G4double best = kInfinity;
239 do
240 {
241 G4double distance;
242 G4ThreeVector normal = (*face)->Normal( p, &distance );
243 if (distance < best)
244 {
245 best = distance;
246 answer = normal;
247 }
248 } while( ++face < faces + numFace );
249
250 return answer;
251}
252
253
254//
255// DistanceToIn(p,v)
256//
258 const G4ThreeVector &v ) const
259{
260 G4double distance = kInfinity;
261 G4double distFromSurface = kInfinity;
262 G4VCSGface **face = faces;
263 G4VCSGface *bestFace = *face;
264 do
265 {
266 G4double faceDistance,
267 faceDistFromSurface;
268 G4ThreeVector faceNormal;
269 G4bool faceAllBehind;
270 if ((*face)->Intersect( p, v, false, kCarTolerance/2,
271 faceDistance, faceDistFromSurface,
272 faceNormal, faceAllBehind ) )
273 {
274 //
275 // Intersecting face
276 //
277 if (faceDistance < distance)
278 {
279 distance = faceDistance;
280 distFromSurface = faceDistFromSurface;
281 bestFace = *face;
282 if (distFromSurface <= 0) { return 0; }
283 }
284 }
285 } while( ++face < faces + numFace );
286
287 if (distance < kInfinity && distFromSurface<kCarTolerance/2)
288 {
289 if (bestFace->Distance(p,false) < kCarTolerance/2) { distance = 0; }
290 }
291
292 return distance;
293}
294
295
296//
297// DistanceToIn(p)
298//
300{
301 return DistanceTo( p, false );
302}
303
304
305//
306// DistanceToOut(p,v)
307//
309 const G4ThreeVector &v,
310 const G4bool calcNorm,
311 G4bool *validNorm,
312 G4ThreeVector *n ) const
313{
314 G4bool allBehind = true;
315 G4double distance = kInfinity;
316 G4double distFromSurface = kInfinity;
317 G4ThreeVector normal;
318
319 G4VCSGface **face = faces;
320 G4VCSGface *bestFace = *face;
321 do
322 {
323 G4double faceDistance,
324 faceDistFromSurface;
325 G4ThreeVector faceNormal;
326 G4bool faceAllBehind;
327 if ((*face)->Intersect( p, v, true, kCarTolerance/2,
328 faceDistance, faceDistFromSurface,
329 faceNormal, faceAllBehind ) )
330 {
331 //
332 // Intersecting face
333 //
334 if ( (distance < kInfinity) || (!faceAllBehind) ) { allBehind = false; }
335 if (faceDistance < distance)
336 {
337 distance = faceDistance;
338 distFromSurface = faceDistFromSurface;
339 normal = faceNormal;
340 bestFace = *face;
341 if (distFromSurface <= 0) { break; }
342 }
343 }
344 } while( ++face < faces + numFace );
345
346 if (distance < kInfinity)
347 {
348 if (distFromSurface <= 0)
349 {
350 distance = 0;
351 }
352 else if (distFromSurface<kCarTolerance/2)
353 {
354 if (bestFace->Distance(p,true) < kCarTolerance/2) { distance = 0; }
355 }
356
357 if (calcNorm)
358 {
359 *validNorm = allBehind;
360 *n = normal;
361 }
362 }
363 else
364 {
365 if (Inside(p) == kSurface) { distance = 0; }
366 if (calcNorm) { *validNorm = false; }
367 }
368
369 return distance;
370}
371
372
373//
374// DistanceToOut(p)
375//
377{
378 return DistanceTo( p, true );
379}
380
381
382//
383// DistanceTo
384//
385// Protected routine called by DistanceToIn and DistanceToOut
386//
388 const G4bool outgoing ) const
389{
390 G4VCSGface **face = faces;
391 G4double best = kInfinity;
392 do
393 {
394 G4double distance = (*face)->Distance( p, outgoing );
395 if (distance < best) { best = distance; }
396 } while( ++face < faces + numFace );
397
398 return (best < 0.5*kCarTolerance) ? 0 : best;
399}
400
401
402//
403// DescribeYourselfTo
404//
406{
407 scene.AddSolid( *this );
408}
409
410
411//
412// GetExtent
413//
414// Define the sides of the box into which our solid instance would fit.
415//
417{
418 static const G4ThreeVector xMax(1,0,0), xMin(-1,0,0),
419 yMax(0,1,0), yMin(0,-1,0),
420 zMax(0,0,1), zMin(0,0,-1);
421 static const G4ThreeVector *axes[6] =
422 { &xMin, &xMax, &yMin, &yMax, &zMin, &zMax };
423
424 G4double answers[6] =
425 {-kInfinity, -kInfinity, -kInfinity, -kInfinity, -kInfinity, -kInfinity};
426
427 G4VCSGface **face = faces;
428 do
429 {
430 const G4ThreeVector **axis = axes+5 ;
431 G4double *answer = answers+5;
432 do
433 {
434 G4double testFace = (*face)->Extent( **axis );
435 if (testFace > *answer) { *answer = testFace; }
436 }
437 while( --axis, --answer >= answers );
438
439 } while( ++face < faces + numFace );
440
441 return G4VisExtent( -answers[0], answers[1],
442 -answers[2], answers[3],
443 -answers[4], answers[5] );
444}
445
446
447//
448// GetEntityType
449//
451{
452 return G4String("G4CSGfaceted");
453}
454
455
456//
457// Stream object contents to an output stream
458//
459std::ostream& G4VCSGfaceted::StreamInfo( std::ostream& os ) const
460{
461 os << "-----------------------------------------------------------\n"
462 << " *** Dump for solid - " << GetName() << " ***\n"
463 << " ===================================================\n"
464 << " Solid type: G4VCSGfaceted\n"
465 << " Parameters: \n"
466 << " number of faces: " << numFace << "\n"
467 << "-----------------------------------------------------------\n";
468
469 return os;
470}
471
472
473//
474// GetCubVolStatistics
475//
477{
478 return fStatistics;
479}
480
481
482//
483// GetCubVolEpsilon
484//
486{
487 return fCubVolEpsilon;
488}
489
490
491//
492// SetCubVolStatistics
493//
495{
496 fCubicVolume=0.;
497 fStatistics=st;
498}
499
500
501//
502// SetCubVolEpsilon
503//
505{
506 fCubicVolume=0.;
507 fCubVolEpsilon=ep;
508}
509
510
511//
512// GetAreaStatistics
513//
515{
516 return fStatistics;
517}
518
519
520//
521// GetAreaAccuracy
522//
524{
525 return fAreaAccuracy;
526}
527
528
529//
530// SetAreaStatistics
531//
533{
534 fSurfaceArea=0.;
535 fStatistics=st;
536}
537
538
539//
540// SetAreaAccuracy
541//
543{
544 fSurfaceArea=0.;
545 fAreaAccuracy=ep;
546}
547
548
549//
550// GetCubicVolume
551//
553{
554 if(fCubicVolume != 0.) {;}
555 else { fCubicVolume = EstimateCubicVolume(fStatistics,fCubVolEpsilon); }
556 return fCubicVolume;
557}
558
559
560//
561// GetSurfaceArea
562//
564{
565 if(fSurfaceArea != 0.) {;}
566 else { fSurfaceArea = EstimateSurfaceArea(fStatistics,fAreaAccuracy); }
567 return fSurfaceArea;
568}
569
570
571//
572// GetPolyhedron
573//
575{
576 if (!fpPolyhedron ||
579 {
580 delete fpPolyhedron;
582 }
583 return fpPolyhedron;
584}
585
586
587//
588// GetPointOnSurfaceGeneric proportional to Areas of faces
589// in case of GenericPolycone or GenericPolyhedra
590//
592{
593 // Preparing variables
594 //
595 G4ThreeVector answer=G4ThreeVector(0.,0.,0.);
596 G4VCSGface **face = faces;
597 G4double area = 0;
598 G4int i;
599 std::vector<G4double> areas;
600
601 // First step: calculate surface areas
602 //
603 do
604 {
605 G4double result = (*face)->SurfaceArea( );
606 areas.push_back(result);
607 area=area+result;
608 } while( ++face < faces + numFace );
609
610 // Second Step: choose randomly one surface
611 //
612 G4VCSGface **face1 = faces;
613 G4double chose = area*G4UniformRand();
614 G4double Achose1, Achose2;
615 Achose1=0; Achose2=0.;
616 i=0;
617
618 do
619 {
620 Achose2+=areas[i];
621 if(chose>=Achose1 && chose<Achose2)
622 {
623 G4ThreeVector point;
624 point= (*face1)->GetPointOnFace();
625 return point;
626 }
627 i++;
628 Achose1=Achose2;
629 } while( ++face1 < faces + numFace );
630
631 return answer;
632}
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4UniformRand()
Definition: Randomize.hh:53
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
G4bool GetExtent(G4double &min, G4double &max) const
virtual G4VCSGface * Clone()=0
virtual G4double Distance(const G4ThreeVector &p, G4bool outgoing)=0
virtual void CalculateExtent(const EAxis axis, const G4VoxelLimits &voxelLimit, const G4AffineTransform &tranform, G4SolidExtentList &extentList)=0
virtual EInside Inside(const G4ThreeVector &p, G4double tolerance, G4double *bestDistance)=0
virtual G4double SurfaceArea()=0
void CopyStuff(const G4VCSGfaceted &source)
G4double GetCubVolEpsilon() const
virtual G4double GetSurfaceArea()
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4double fCubicVolume
virtual EInside Inside(const G4ThreeVector &p) const
G4int GetCubVolStatistics() const
void SetAreaStatistics(G4int st)
virtual void DescribeYourselfTo(G4VGraphicsScene &scene) const
virtual G4Polyhedron * CreatePolyhedron() const =0
G4VCSGface ** faces
void SetAreaAccuracy(G4double ep)
const G4VCSGfaceted & operator=(const G4VCSGfaceted &source)
virtual G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
G4VCSGfaceted(const G4String &name)
G4Polyhedron * fpPolyhedron
virtual G4GeometryType GetEntityType() const
G4int GetAreaStatistics() const
G4double GetAreaAccuracy() const
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const
G4double fSurfaceArea
virtual std::ostream & StreamInfo(std::ostream &os) const
virtual G4double GetCubicVolume()
G4ThreeVector GetPointOnSurfaceGeneric() const
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
virtual G4double DistanceTo(const G4ThreeVector &p, const G4bool outgoing) const
virtual G4Polyhedron * GetPolyhedron() const
void SetCubVolEpsilon(G4double ep)
void SetCubVolStatistics(G4int st)
virtual ~G4VCSGfaceted()
virtual G4VisExtent GetExtent() const
virtual void AddSolid(const G4Box &)=0
G4double EstimateSurfaceArea(G4int nStat, G4double ell) const
Definition: G4VSolid.cc:261
G4String GetName() const
G4double EstimateCubicVolume(G4int nStat, G4double epsilon) const
Definition: G4VSolid.cc:203
G4double kCarTolerance
Definition: G4VSolid.hh:307
G4VSolid & operator=(const G4VSolid &rhs)
Definition: G4VSolid.cc:110
static G4int GetNumberOfRotationSteps()
EAxis
Definition: geomdefs.hh:54
EInside
Definition: geomdefs.hh:58
@ kOutside
Definition: geomdefs.hh:58
@ kSurface
Definition: geomdefs.hh:58