source: trunk/source/geometry/solids/specific/src/G4VCSGfaceted.cc @ 1228

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

update geant4.9.3 tag

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