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
G4SubtractionSolid.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//
27// $Id$
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 <sstream>
43
44#include "G4SubtractionSolid.hh"
45
46#include "G4SystemOfUnits.hh"
47#include "G4VoxelLimits.hh"
50
51#include "G4VGraphicsScene.hh"
52#include "G4Polyhedron.hh"
54#include "G4NURBS.hh"
55// #include "G4NURBSbox.hh"
56
57///////////////////////////////////////////////////////////////////
58//
59// Transfer all data members to G4BooleanSolid which is responsible
60// for them. pName will be in turn sent to G4VSolid
61
63 G4VSolid* pSolidA ,
64 G4VSolid* pSolidB )
65 : G4BooleanSolid(pName,pSolidA,pSolidB)
66{
67}
68
69///////////////////////////////////////////////////////////////
70//
71// Constructor
72
74 G4VSolid* pSolidA ,
75 G4VSolid* pSolidB ,
76 G4RotationMatrix* rotMatrix,
77 const G4ThreeVector& transVector )
78 : G4BooleanSolid(pName,pSolidA,pSolidB,rotMatrix,transVector)
79{
80}
81
82///////////////////////////////////////////////////////////////
83//
84// Constructor
85
87 G4VSolid* pSolidA ,
88 G4VSolid* pSolidB ,
89 const G4Transform3D& transform )
90 : G4BooleanSolid(pName,pSolidA,pSolidB,transform)
91{
92}
93
94//////////////////////////////////////////////////////////////////
95//
96// Fake default constructor - sets only member data and allocates memory
97// for usage restricted to object persistency.
98
100 : G4BooleanSolid(a)
101{
102}
103
104///////////////////////////////////////////////////////////////
105//
106// Destructor
107
109{
110}
111
112///////////////////////////////////////////////////////////////
113//
114// Copy constructor
115
117 : G4BooleanSolid (rhs)
118{
119}
120
121///////////////////////////////////////////////////////////////
122//
123// Assignment operator
124
127{
128 // Check assignment to self
129 //
130 if (this == &rhs) { return *this; }
131
132 // Copy base class data
133 //
135
136 return *this;
137}
138
139///////////////////////////////////////////////////////////////
140//
141// CalculateExtent
142
143G4bool
145 const G4VoxelLimits& pVoxelLimit,
146 const G4AffineTransform& pTransform,
147 G4double& pMin,
148 G4double& pMax ) const
149{
150 // Since we cannot be sure how much the second solid subtracts
151 // from the first, we must use the first solid's extent!
152
153 return fPtrSolidA->CalculateExtent( pAxis, pVoxelLimit,
154 pTransform, pMin, pMax );
155}
156
157/////////////////////////////////////////////////////
158//
159// Touching ? Empty subtraction ?
160
162{
163 EInside positionA = fPtrSolidA->Inside(p);
164 if (positionA == kOutside) return kOutside;
165
166 EInside positionB = fPtrSolidB->Inside(p);
167
168 if(positionA == kInside && positionB == kOutside)
169 {
170 return kInside ;
171 }
172 else
173 {
174 if(( positionA == kInside && positionB == kSurface) ||
175 ( positionB == kOutside && positionA == kSurface) ||
176 ( positionA == kSurface && positionB == kSurface &&
178 fPtrSolidB->SurfaceNormal(p) ).mag2() >
180 {
181 return kSurface;
182 }
183 else
184 {
185 return kOutside;
186 }
187 }
188}
189
190//////////////////////////////////////////////////////////////
191//
192// SurfaceNormal
193
196{
197 G4ThreeVector normal;
198 if( Inside(p) == kOutside )
199 {
200#ifdef G4BOOLDEBUG
201 G4cout << "WARNING - Invalid call [1] in "
202 << "G4SubtractionSolid::SurfaceNormal(p)" << G4endl
203 << " Point p is inside !" << G4endl;
204 G4cout << " p = " << p << G4endl;
205 G4cerr << "WARNING - Invalid call [1] in "
206 << "G4SubtractionSolid::SurfaceNormal(p)" << G4endl
207 << " Point p is inside !" << G4endl;
208 G4cerr << " p = " << p << G4endl;
209#endif
210 }
211 else
212 {
213 if( fPtrSolidA->Inside(p) == kSurface &&
214 fPtrSolidB->Inside(p) != kInside )
215 {
216 normal = fPtrSolidA->SurfaceNormal(p) ;
217 }
218 else if( fPtrSolidA->Inside(p) == kInside &&
219 fPtrSolidB->Inside(p) != kOutside )
220 {
221 normal = -fPtrSolidB->SurfaceNormal(p) ;
222 }
223 else
224 {
226 {
227 normal = fPtrSolidA->SurfaceNormal(p) ;
228 }
229 else
230 {
231 normal = -fPtrSolidB->SurfaceNormal(p) ;
232 }
233#ifdef G4BOOLDEBUG
234 if(Inside(p) == kInside)
235 {
236 G4cout << "WARNING - Invalid call [2] in "
237 << "G4SubtractionSolid::SurfaceNormal(p)" << G4endl
238 << " Point p is inside !" << G4endl;
239 G4cout << " p = " << p << G4endl;
240 G4cerr << "WARNING - Invalid call [2] in "
241 << "G4SubtractionSolid::SurfaceNormal(p)" << G4endl
242 << " Point p is inside !" << G4endl;
243 G4cerr << " p = " << p << G4endl;
244 }
245#endif
246 }
247 }
248 return normal;
249}
250
251/////////////////////////////////////////////////////////////
252//
253// The same algorithm as in DistanceToIn(p)
254
257 const G4ThreeVector& v ) const
258{
259 G4double dist = 0.0,disTmp = 0.0 ;
260
261#ifdef G4BOOLDEBUG
262 if( Inside(p) == kInside )
263 {
264 G4cout << "WARNING - Invalid call in "
265 << "G4SubtractionSolid::DistanceToIn(p,v)" << G4endl
266 << " Point p is inside !" << G4endl;
267 G4cout << " p = " << p << G4endl;
268 G4cout << " v = " << v << G4endl;
269 G4cerr << "WARNING - Invalid call in "
270 << "G4SubtractionSolid::DistanceToIn(p,v)" << G4endl
271 << " Point p is inside !" << G4endl;
272 G4cerr << " p = " << p << G4endl;
273 G4cerr << " v = " << v << G4endl;
274 }
275#endif
276
277 // if( // ( fPtrSolidA->Inside(p) != kOutside) && // case1:p in both A&B
278 if ( fPtrSolidB->Inside(p) != kOutside ) // start: out of B
279 {
280 dist = fPtrSolidB->DistanceToOut(p,v) ; // ,calcNorm,validNorm,n) ;
281
282 if( fPtrSolidA->Inside(p+dist*v) != kInside )
283 {
284 G4int count1=0;
285 do
286 {
287 disTmp = fPtrSolidA->DistanceToIn(p+dist*v,v) ;
288
289 if(disTmp == kInfinity)
290 {
291 return kInfinity ;
292 }
293 dist += disTmp ;
294
295 if( Inside(p+dist*v) == kOutside )
296 {
297 disTmp = fPtrSolidB->DistanceToOut(p+dist*v,v) ;
298 dist += disTmp ;
299 count1++;
300 if( count1 > 1000 ) // Infinite loop detected
301 {
302 G4String nameB = fPtrSolidB->GetName();
303 if(fPtrSolidB->GetEntityType()=="G4DisplacedSolid")
304 {
305 nameB = (dynamic_cast<G4DisplacedSolid*>(fPtrSolidB))
306 ->GetConstituentMovedSolid()->GetName();
307 }
308 std::ostringstream message;
309 message << "Illegal condition caused by solids: "
310 << fPtrSolidA->GetName() << " and " << nameB << G4endl;
311 message.precision(16);
312 message << "Looping detected in point " << p+dist*v
313 << ", from original point " << p
314 << " and direction " << v << G4endl
315 << "Computed candidate distance: " << dist << "*mm.";
316 message.precision(6);
317 DumpInfo();
318 G4Exception("G4SubtractionSolid::DistanceToIn(p,v)",
319 "GeomSolids1001", JustWarning, message,
320 "Returning candidate distance.");
321 return dist;
322 }
323 }
324 }
325 while( Inside(p+dist*v) == kOutside ) ;
326 }
327 }
328 else // p outside A, start in A
329 {
330 dist = fPtrSolidA->DistanceToIn(p,v) ;
331
332 if( dist == kInfinity ) // past A, hence past A\B
333 {
334 return kInfinity ;
335 }
336 else
337 {
338 G4int count2=0;
339 while( Inside(p+dist*v) == kOutside ) // pushing loop
340 {
341 disTmp = fPtrSolidB->DistanceToOut(p+dist*v,v) ;
342 dist += disTmp ;
343
344 if( Inside(p+dist*v) == kOutside )
345 {
346 disTmp = fPtrSolidA->DistanceToIn(p+dist*v,v) ;
347
348 if(disTmp == kInfinity) // past A, hence past A\B
349 {
350 return kInfinity ;
351 }
352 dist += disTmp ;
353 count2++;
354 if( count2 > 1000 ) // Infinite loop detected
355 {
356 G4String nameB = fPtrSolidB->GetName();
357 if(fPtrSolidB->GetEntityType()=="G4DisplacedSolid")
358 {
359 nameB = (dynamic_cast<G4DisplacedSolid*>(fPtrSolidB))
360 ->GetConstituentMovedSolid()->GetName();
361 }
362 std::ostringstream message;
363 message << "Illegal condition caused by solids: "
364 << fPtrSolidA->GetName() << " and " << nameB << G4endl;
365 message.precision(16);
366 message << "Looping detected in point " << p+dist*v
367 << ", from original point " << p
368 << " and direction " << v << G4endl
369 << "Computed candidate distance: " << dist << "*mm.";
370 message.precision(6);
371 DumpInfo();
372 G4Exception("G4SubtractionSolid::DistanceToIn(p,v)",
373 "GeomSolids1001", JustWarning, message);
374 return dist;
375
376 }
377 }
378 }
379 }
380 }
381
382 return dist ;
383}
384
385////////////////////////////////////////////////////////
386//
387// Approximate nearest distance from the point p to the intersection of
388// two solids. It is usually underestimated from the point of view of
389// isotropic safety
390
393{
394 G4double dist=0.0;
395
396#ifdef G4BOOLDEBUG
397 if( Inside(p) == kInside )
398 {
399 G4cout << "WARNING - Invalid call in "
400 << "G4SubtractionSolid::DistanceToIn(p)" << G4endl
401 << " Point p is inside !" << G4endl;
402 G4cout << " p = " << p << G4endl;
403 G4cerr << "WARNING - Invalid call in "
404 << "G4SubtractionSolid::DistanceToIn(p)" << G4endl
405 << " Point p is inside !" << G4endl;
406 G4cerr << " p = " << p << G4endl;
407 }
408#endif
409
410 if( ( fPtrSolidA->Inside(p) != kOutside) && // case 1
411 ( fPtrSolidB->Inside(p) != kOutside) )
412 {
413 dist= fPtrSolidB->DistanceToOut(p) ;
414 }
415 else
416 {
417 dist= fPtrSolidA->DistanceToIn(p) ;
418 }
419
420 return dist;
421}
422
423//////////////////////////////////////////////////////////
424//
425// The same algorithm as DistanceToOut(p)
426
429 const G4ThreeVector& v,
430 const G4bool calcNorm,
431 G4bool *validNorm,
432 G4ThreeVector *n ) const
433{
434#ifdef G4BOOLDEBUG
435 if( Inside(p) == kOutside )
436 {
437 G4cout << "Position:" << G4endl << G4endl;
438 G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl;
439 G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl;
440 G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl;
441 G4cout << "Direction:" << G4endl << G4endl;
442 G4cout << "v.x() = " << v.x() << G4endl;
443 G4cout << "v.y() = " << v.y() << G4endl;
444 G4cout << "v.z() = " << v.z() << G4endl << G4endl;
445 G4cout << "WARNING - Invalid call in "
446 << "G4SubtractionSolid::DistanceToOut(p,v)" << G4endl
447 << " Point p is outside !" << G4endl;
448 G4cout << " p = " << p << G4endl;
449 G4cout << " v = " << v << G4endl;
450 G4cerr << "WARNING - Invalid call in "
451 << "G4SubtractionSolid::DistanceToOut(p,v)" << G4endl
452 << " Point p is outside !" << G4endl;
453 G4cerr << " p = " << p << G4endl;
454 G4cerr << " v = " << v << G4endl;
455 }
456#endif
457
458 G4double distout;
459 G4double distA = fPtrSolidA->DistanceToOut(p,v,calcNorm,validNorm,n) ;
460 G4double distB = fPtrSolidB->DistanceToIn(p,v) ;
461 if(distB < distA)
462 {
463 if(calcNorm)
464 {
465 *n = -(fPtrSolidB->SurfaceNormal(p+distB*v)) ;
466 *validNorm = false ;
467 }
468 distout= distB ;
469 }
470 else
471 {
472 distout= distA ;
473 }
474 return distout;
475}
476
477//////////////////////////////////////////////////////////////
478//
479// Inverted algorithm of DistanceToIn(p)
480
483{
484 G4double dist=0.0;
485
486 if( Inside(p) == kOutside )
487 {
488#ifdef G4BOOLDEBUG
489 G4cout << "WARNING - Invalid call in "
490 << "G4SubtractionSolid::DistanceToOut(p)" << G4endl
491 << " Point p is outside" << G4endl;
492 G4cout << " p = " << p << G4endl;
493 G4cerr << "WARNING - Invalid call in "
494 << "G4SubtractionSolid::DistanceToOut(p)" << G4endl
495 << " Point p is outside" << G4endl;
496 G4cerr << " p = " << p << G4endl;
497#endif
498 }
499 else
500 {
501 dist= std::min(fPtrSolidA->DistanceToOut(p),
502 fPtrSolidB->DistanceToIn(p) ) ;
503 }
504 return dist;
505}
506
507//////////////////////////////////////////////////////////////
508//
509//
510
512{
513 return G4String("G4SubtractionSolid");
514}
515
516//////////////////////////////////////////////////////////////////////////
517//
518// Make a clone of the object
519
521{
522 return new G4SubtractionSolid(*this);
523}
524
525//////////////////////////////////////////////////////////////
526//
527//
528
529void
531 const G4int,
532 const G4VPhysicalVolume* )
533{
534}
535
536/////////////////////////////////////////////////
537//
538//
539
540void
542{
543 scene.AddSolid (*this);
544}
545
546////////////////////////////////////////////////////
547//
548//
549
552{
554 // Stack components and components of components recursively
555 // See G4BooleanSolid::StackPolyhedron
557 G4Polyhedron* result = new G4Polyhedron(*top);
558 if (processor.execute(*result)) { return result; }
559 else { return 0; }
560}
561
562/////////////////////////////////////////////////////////
563//
564//
565
566G4NURBS*
568{
569 // Take into account boolean operation - see CreatePolyhedron.
570 // return new G4NURBSbox (1.0, 1.0, 1.0);
571 return 0;
572}
@ JustWarning
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cerr
G4DLLIMPORT std::ostream G4cout
double z() const
double x() const
double y() const
G4VSolid * fPtrSolidA
G4BooleanSolid & operator=(const G4BooleanSolid &rhs)
G4VSolid * fPtrSolidB
G4Polyhedron * StackPolyhedron(HepPolyhedronProcessor &, const G4VSolid *) const
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
G4SubtractionSolid & operator=(const G4SubtractionSolid &rhs)
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4NURBS * CreateNURBS() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4Polyhedron * CreatePolyhedron() const
G4GeometryType GetEntityType() const
G4SubtractionSolid(const G4String &pName, G4VSolid *pSolidA, G4VSolid *pSolidB)
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const
EInside Inside(const G4ThreeVector &p) const
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4VSolid * Clone() const
virtual void AddSolid(const G4Box &)=0
G4String GetName() const
virtual G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const =0
virtual EInside Inside(const G4ThreeVector &p) const =0
void DumpInfo() const
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const =0
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const =0
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const =0
virtual G4GeometryType GetEntityType() const =0
EAxis
Definition: geomdefs.hh:54
EInside
Definition: geomdefs.hh:58
@ kInside
Definition: geomdefs.hh:58
@ kOutside
Definition: geomdefs.hh:58
@ kSurface
Definition: geomdefs.hh:58
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
#define processor
Definition: xmlparse.cc:600