Geant4  v4-10.4-release
 모두 클래스 네임스페이스들 파일들 함수 변수 타입정의 열거형 타입 열거형 멤버 Friends 매크로 그룹들 페이지들
G4SubtractionSolid.cc
이 파일의 문서화 페이지로 가기
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: G4SubtractionSolid.cc 104316 2017-05-24 13:04:23Z gcosmo $
28 //
29 // Implementation of methods for the class G4IntersectionSolid
30 //
31 // History:
32 //
33 // 14.10.98 V.Grichine: implementation of the first version
34 // 19.10.98 V.Grichine: new algorithm of DistanceToIn(p,v)
35 // 02.08.99 V.Grichine: bugs fixed in DistanceToOut(p,v,...)
36 // while -> do-while & surfaceA limitations
37 // 13.09.00 V.Grichine: bug fixed in SurfaceNormal(p), p can be inside
38 // 22.07.11 T.Nikitina: add detection of Infinite Loop in DistanceToIn(p,v)
39 //
40 // --------------------------------------------------------------------
41 
42 #include "G4SubtractionSolid.hh"
43 
44 #include "G4SystemOfUnits.hh"
45 #include "G4VoxelLimits.hh"
46 #include "G4VPVParameterisation.hh"
47 #include "G4GeometryTolerance.hh"
48 
49 #include "G4VGraphicsScene.hh"
50 #include "G4Polyhedron.hh"
51 #include "HepPolyhedronProcessor.h"
52 
53 #include <sstream>
54 
56 //
57 // Transfer all data members to G4BooleanSolid which is responsible
58 // for them. pName will be in turn sent to G4VSolid
59 
61  G4VSolid* pSolidA ,
62  G4VSolid* pSolidB )
63  : G4BooleanSolid(pName,pSolidA,pSolidB)
64 {
65 }
66 
68 //
69 // Constructor
70 
72  G4VSolid* pSolidA ,
73  G4VSolid* pSolidB ,
74  G4RotationMatrix* rotMatrix,
75  const G4ThreeVector& transVector )
76  : G4BooleanSolid(pName,pSolidA,pSolidB,rotMatrix,transVector)
77 {
78 }
79 
81 //
82 // Constructor
83 
85  G4VSolid* pSolidA ,
86  G4VSolid* pSolidB ,
87  const G4Transform3D& transform )
88  : G4BooleanSolid(pName,pSolidA,pSolidB,transform)
89 {
90 }
91 
93 //
94 // Fake default constructor - sets only member data and allocates memory
95 // for usage restricted to object persistency.
96 
98  : G4BooleanSolid(a)
99 {
100 }
101 
103 //
104 // Destructor
105 
107 {
108 }
109 
111 //
112 // Copy constructor
113 
115  : G4BooleanSolid (rhs)
116 {
117 }
118 
120 //
121 // Assignment operator
122 
125 {
126  // Check assignment to self
127  //
128  if (this == &rhs) { return *this; }
129 
130  // Copy base class data
131  //
133 
134  return *this;
135 }
136 
138 //
139 // Get bounding box
140 
141 void
143  G4ThreeVector& pMax) const
144 {
145  // Since it is unclear how the shape of the first solid will be changed
146  // after subtraction, just return its original bounding box.
147  //
148  fPtrSolidA->BoundingLimits(pMin,pMax);
149 
150  // Check correctness of the bounding box
151  //
152  if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
153  {
154  std::ostringstream message;
155  message << "Bad bounding box (min >= max) for solid: "
156  << GetName() << " !"
157  << "\npMin = " << pMin
158  << "\npMax = " << pMax;
159  G4Exception("G4SubtractionSolid::BoundingLimits()", "GeomMgt0001",
160  JustWarning, message);
161  DumpInfo();
162  }
163 }
164 
166 //
167 // Calculate extent under transform and specified limit
168 
169 G4bool
171  const G4VoxelLimits& pVoxelLimit,
172  const G4AffineTransform& pTransform,
173  G4double& pMin,
174  G4double& pMax ) const
175 {
176  // Since we cannot be sure how much the second solid subtracts
177  // from the first, we must use the first solid's extent!
178 
179  return fPtrSolidA->CalculateExtent( pAxis, pVoxelLimit,
180  pTransform, pMin, pMax );
181 }
182 
184 //
185 // Touching ? Empty subtraction ?
186 
188 {
189  EInside positionA = fPtrSolidA->Inside(p);
190  if (positionA == kOutside) return kOutside;
191 
192  EInside positionB = fPtrSolidB->Inside(p);
193 
194  if(positionA == kInside && positionB == kOutside)
195  {
196  return kInside ;
197  }
198  else
199  {
200  static const G4double rtol
202  if(( positionA == kInside && positionB == kSurface) ||
203  ( positionB == kOutside && positionA == kSurface) ||
204  ( positionA == kSurface && positionB == kSurface &&
205  ( fPtrSolidA->SurfaceNormal(p) -
206  fPtrSolidB->SurfaceNormal(p) ).mag2() > rtol ) )
207  {
208  return kSurface;
209  }
210  else
211  {
212  return kOutside;
213  }
214  }
215 }
216 
218 //
219 // SurfaceNormal
220 
223 {
225 
226  EInside InsideA = fPtrSolidA->Inside(p);
227  EInside InsideB = fPtrSolidB->Inside(p);
228 
229  if( InsideA == kOutside )
230  {
231 #ifdef G4BOOLDEBUG
232  G4cout << "WARNING - Invalid call [1] in "
233  << "G4SubtractionSolid::SurfaceNormal(p)" << G4endl
234  << " Point p is outside !" << G4endl;
235  G4cout << " p = " << p << G4endl;
236  G4cerr << "WARNING - Invalid call [1] in "
237  << "G4SubtractionSolid::SurfaceNormal(p)" << G4endl
238  << " Point p is outside !" << G4endl;
239  G4cerr << " p = " << p << G4endl;
240 #endif
241  normal = fPtrSolidA->SurfaceNormal(p) ;
242  }
243  else if( InsideA == kSurface &&
244  InsideB != kInside )
245  {
246  normal = fPtrSolidA->SurfaceNormal(p) ;
247  }
248  else if( InsideA == kInside &&
249  InsideB != kOutside )
250  {
251  normal = -fPtrSolidB->SurfaceNormal(p) ;
252  }
253  else
254  {
256  {
257  normal = fPtrSolidA->SurfaceNormal(p) ;
258  }
259  else
260  {
261  normal = -fPtrSolidB->SurfaceNormal(p) ;
262  }
263 #ifdef G4BOOLDEBUG
264  if(Inside(p) == kInside)
265  {
266  G4cout << "WARNING - Invalid call [2] in "
267  << "G4SubtractionSolid::SurfaceNormal(p)" << G4endl
268  << " Point p is inside !" << G4endl;
269  G4cout << " p = " << p << G4endl;
270  G4cerr << "WARNING - Invalid call [2] in "
271  << "G4SubtractionSolid::SurfaceNormal(p)" << G4endl
272  << " Point p is inside !" << G4endl;
273  G4cerr << " p = " << p << G4endl;
274  }
275 #endif
276  }
277  return normal;
278 }
279 
281 //
282 // The same algorithm as in DistanceToIn(p)
283 
284 G4double
286  const G4ThreeVector& v ) const
287 {
288  G4double dist = 0.0, dist2 = 0.0, disTmp = 0.0;
289 
290 #ifdef G4BOOLDEBUG
291  if( Inside(p) == kInside )
292  {
293  G4cout << "WARNING - Invalid call in "
294  << "G4SubtractionSolid::DistanceToIn(p,v)" << G4endl
295  << " Point p is inside !" << G4endl;
296  G4cout << " p = " << p << G4endl;
297  G4cout << " v = " << v << G4endl;
298  G4cerr << "WARNING - Invalid call in "
299  << "G4SubtractionSolid::DistanceToIn(p,v)" << G4endl
300  << " Point p is inside !" << G4endl;
301  G4cerr << " p = " << p << G4endl;
302  G4cerr << " v = " << v << G4endl;
303  }
304 #endif
305 
306  // if( // ( fPtrSolidA->Inside(p) != kOutside) && // case1:p in both A&B
307  if ( fPtrSolidB->Inside(p) != kOutside ) // start: out of B
308  {
309  dist = fPtrSolidB->DistanceToOut(p,v) ; // ,calcNorm,validNorm,n) ;
310 
311  if( fPtrSolidA->Inside(p+dist*v) != kInside )
312  {
313  G4int count1=0;
314  do // Loop checking, 13.08.2015, G.Cosmo
315  {
316  disTmp = fPtrSolidA->DistanceToIn(p+dist*v,v) ;
317 
318  if(disTmp == kInfinity)
319  {
320  return kInfinity ;
321  }
322  dist += disTmp ;
323 
324  if( Inside(p+dist*v) == kOutside )
325  {
326  disTmp = fPtrSolidB->DistanceToOut(p+dist*v,v) ;
327  dist2 = dist+disTmp;
328  if (dist == dist2) { return dist; } // no progress
329  dist = dist2 ;
330  count1++;
331  if( count1 > 1000 ) // Infinite loop detected
332  {
333  G4String nameB = fPtrSolidB->GetName();
334  if(fPtrSolidB->GetEntityType()=="G4DisplacedSolid")
335  {
336  nameB = (dynamic_cast<G4DisplacedSolid*>(fPtrSolidB))
337  ->GetConstituentMovedSolid()->GetName();
338  }
339  std::ostringstream message;
340  message << "Illegal condition caused by solids: "
341  << fPtrSolidA->GetName() << " and " << nameB << G4endl;
342  message.precision(16);
343  message << "Looping detected in point " << p+dist*v
344  << ", from original point " << p
345  << " and direction " << v << G4endl
346  << "Computed candidate distance: " << dist << "*mm. ";
347  message.precision(6);
348  DumpInfo();
349  G4Exception("G4SubtractionSolid::DistanceToIn(p,v)",
350  "GeomSolids1001", JustWarning, message,
351  "Returning candidate distance.");
352  return dist;
353  }
354  }
355  }
356  while( Inside(p+dist*v) == kOutside ) ;
357  }
358  }
359  else // p outside A, start in A
360  {
361  dist = fPtrSolidA->DistanceToIn(p,v) ;
362 
363  if( dist == kInfinity ) // past A, hence past A\B
364  {
365  return kInfinity ;
366  }
367  else
368  {
369  G4int count2=0;
370  while( Inside(p+dist*v) == kOutside ) // pushing loop
371  {
372  disTmp = fPtrSolidB->DistanceToOut(p+dist*v,v) ;
373  dist += disTmp ;
374 
375  if( Inside(p+dist*v) == kOutside )
376  {
377  disTmp = fPtrSolidA->DistanceToIn(p+dist*v,v) ;
378 
379  if(disTmp == kInfinity) // past A, hence past A\B
380  {
381  return kInfinity ;
382  }
383  dist2 = dist+disTmp;
384  if (dist == dist2) { return dist; } // no progress
385  dist = dist2 ;
386  count2++;
387  if( count2 > 1000 ) // Infinite loop detected
388  {
389  G4String nameB = fPtrSolidB->GetName();
390  if(fPtrSolidB->GetEntityType()=="G4DisplacedSolid")
391  {
392  nameB = (dynamic_cast<G4DisplacedSolid*>(fPtrSolidB))
393  ->GetConstituentMovedSolid()->GetName();
394  }
395  std::ostringstream message;
396  message << "Illegal condition caused by solids: "
397  << fPtrSolidA->GetName() << " and " << nameB << G4endl;
398  message.precision(16);
399  message << "Looping detected in point " << p+dist*v
400  << ", from original point " << p
401  << " and direction " << v << G4endl
402  << "Computed candidate distance: " << dist << "*mm. ";
403  message.precision(6);
404  DumpInfo();
405  G4Exception("G4SubtractionSolid::DistanceToIn(p,v)",
406  "GeomSolids1001", JustWarning, message,
407  "Returning candidate distance.");
408  return dist;
409  }
410  }
411  } // Loop checking, 13.08.2015, G.Cosmo
412  }
413  }
414 
415  return dist ;
416 }
417 
419 //
420 // Approximate nearest distance from the point p to the intersection of
421 // two solids. It is usually underestimated from the point of view of
422 // isotropic safety
423 
424 G4double
426 {
427  G4double dist=0.0;
428 
429 #ifdef G4BOOLDEBUG
430  if( Inside(p) == kInside )
431  {
432  G4cout << "WARNING - Invalid call in "
433  << "G4SubtractionSolid::DistanceToIn(p)" << G4endl
434  << " Point p is inside !" << G4endl;
435  G4cout << " p = " << p << G4endl;
436  G4cerr << "WARNING - Invalid call in "
437  << "G4SubtractionSolid::DistanceToIn(p)" << G4endl
438  << " Point p is inside !" << G4endl;
439  G4cerr << " p = " << p << G4endl;
440  }
441 #endif
442 
443  if( ( fPtrSolidA->Inside(p) != kOutside) && // case 1
444  ( fPtrSolidB->Inside(p) != kOutside) )
445  {
446  dist= fPtrSolidB->DistanceToOut(p) ;
447  }
448  else
449  {
450  dist= fPtrSolidA->DistanceToIn(p) ;
451  }
452 
453  return dist;
454 }
455 
457 //
458 // The same algorithm as DistanceToOut(p)
459 
460 G4double
462  const G4ThreeVector& v,
463  const G4bool calcNorm,
464  G4bool *validNorm,
465  G4ThreeVector *n ) const
466 {
467 #ifdef G4BOOLDEBUG
468  if( Inside(p) == kOutside )
469  {
470  G4cout << "Position:" << G4endl << G4endl;
471  G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl;
472  G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl;
473  G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl;
474  G4cout << "Direction:" << G4endl << G4endl;
475  G4cout << "v.x() = " << v.x() << G4endl;
476  G4cout << "v.y() = " << v.y() << G4endl;
477  G4cout << "v.z() = " << v.z() << G4endl << G4endl;
478  G4cout << "WARNING - Invalid call in "
479  << "G4SubtractionSolid::DistanceToOut(p,v)" << G4endl
480  << " Point p is outside !" << G4endl;
481  G4cout << " p = " << p << G4endl;
482  G4cout << " v = " << v << G4endl;
483  G4cerr << "WARNING - Invalid call in "
484  << "G4SubtractionSolid::DistanceToOut(p,v)" << G4endl
485  << " Point p is outside !" << G4endl;
486  G4cerr << " p = " << p << G4endl;
487  G4cerr << " v = " << v << G4endl;
488  }
489 #endif
490 
491  G4double distout;
492  G4double distA = fPtrSolidA->DistanceToOut(p,v,calcNorm,validNorm,n) ;
494  if(distB < distA)
495  {
496  if(calcNorm)
497  {
498  *n = -(fPtrSolidB->SurfaceNormal(p+distB*v)) ;
499  *validNorm = false ;
500  }
501  distout= distB ;
502  }
503  else
504  {
505  distout= distA ;
506  }
507  return distout;
508 }
509 
511 //
512 // Inverted algorithm of DistanceToIn(p)
513 
514 G4double
516 {
517  G4double dist=0.0;
518 
519  if( Inside(p) == kOutside )
520  {
521 #ifdef G4BOOLDEBUG
522  G4cout << "WARNING - Invalid call in "
523  << "G4SubtractionSolid::DistanceToOut(p)" << G4endl
524  << " Point p is outside" << G4endl;
525  G4cout << " p = " << p << G4endl;
526  G4cerr << "WARNING - Invalid call in "
527  << "G4SubtractionSolid::DistanceToOut(p)" << G4endl
528  << " Point p is outside" << G4endl;
529  G4cerr << " p = " << p << G4endl;
530 #endif
531  }
532  else
533  {
535  fPtrSolidB->DistanceToIn(p) ) ;
536  }
537  return dist;
538 }
539 
541 //
542 //
543 
545 {
546  return G4String("G4SubtractionSolid");
547 }
548 
550 //
551 // Make a clone of the object
552 
554 {
555  return new G4SubtractionSolid(*this);
556 }
557 
559 //
560 //
561 
562 void
564  const G4int,
565  const G4VPhysicalVolume* )
566 {
567 }
568 
570 //
571 //
572 
573 void
575 {
576  scene.AddSolid (*this);
577 }
578 
580 //
581 //
582 
583 G4Polyhedron*
585 {
587  // Stack components and components of components recursively
588  // See G4BooleanSolid::StackPolyhedron
589  G4Polyhedron* top = StackPolyhedron(processor, this);
590  G4Polyhedron* result = new G4Polyhedron(*top);
591  if (processor.execute(*result)) { return result; }
592  else { return 0; }
593 }
std::vector< ExP01TrackerHit * > a
Definition: ExP01Classes.hh:33
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
virtual void AddSolid(const G4Box &)=0
static const G4double kInfinity
Definition: geomdefs.hh:42
virtual G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const =0
G4Polyhedron * CreatePolyhedron() const
static constexpr double mm
Definition: G4SIunits.hh:115
EInside Inside(const G4ThreeVector &p) const
virtual void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
Definition: G4VSolid.cc:625
#define G4endl
Definition: G4ios.hh:61
const char * p
Definition: xmltok.h:285
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
void message(RunManager *runmanager)
Definition: ts_scorers.cc:72
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
G4BooleanSolid & operator=(const G4BooleanSolid &rhs)
double z() const
static double normal(HepRandomEngine *eptr)
Definition: RandPoisson.cc:77
G4double GetRadialTolerance() const
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const =0
G4VSolid * Clone() const
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const =0
G4SubtractionSolid & operator=(const G4SubtractionSolid &rhs)
virtual EInside Inside(const G4ThreeVector &p) const =0
double G4double
Definition: G4Types.hh:76
bool G4bool
Definition: G4Types.hh:79
G4SubtractionSolid(const G4String &pName, G4VSolid *pSolidA, G4VSolid *pSolidB)
bool execute(HepPolyhedron &)
Float_t distB
Definition: plotDend.C:22
G4GLOB_DLL std::ostream G4cerr
G4double G4ParticleHPJENDLHEData::G4double result
#define processor
Definition: xmlparse.cc:617
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.hh:65
G4Polyhedron * StackPolyhedron(HepPolyhedronProcessor &, const G4VSolid *) const
int G4int
Definition: G4Types.hh:78
EInside
Definition: geomdefs.hh:58
G4VSolid * fPtrSolidA
G4VSolid * fPtrSolidB
EAxis
Definition: geomdefs.hh:54
G4String GetName() const
void DumpInfo() const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4GeometryType GetEntityType() const
G4GLOB_DLL std::ostream G4cout
double x() const
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const =0
static G4GeometryTolerance * GetInstance()
Char_t n[5]
double y() const
virtual G4GeometryType GetEntityType() const =0
Float_t distA
Definition: plotDend.C:22
T min(const T t1, const T t2)
brief Return the smallest of the two arguments