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
G4UnionSolid.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// 12.09.98 V.Grichine: first implementation
34// 28.11.98 V.Grichine: fix while loops in DistToIn/Out
35// 27.07.99 V.Grichine: modifications in DistToOut(p,v,...), while -> do-while
36// 16.03.01 V.Grichine: modifications in CalculateExtent()
37//
38// --------------------------------------------------------------------
39
40#include <sstream>
41
42#include "G4UnionSolid.hh"
43
44#include "G4SystemOfUnits.hh"
45#include "G4VoxelLimits.hh"
48
49#include "G4VGraphicsScene.hh"
50#include "G4Polyhedron.hh"
52#include "G4NURBS.hh"
53// #include "G4NURBSbox.hh"
54
55///////////////////////////////////////////////////////////////////
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
67/////////////////////////////////////////////////////////////////////
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}
80
81///////////////////////////////////////////////////////////
82//
83// Constructor
84
86 G4VSolid* pSolidA ,
87 G4VSolid* pSolidB ,
88 const G4Transform3D& transform )
89 : G4BooleanSolid(pName,pSolidA,pSolidB,transform)
90{
91}
92
93//////////////////////////////////////////////////////////////////
94//
95// Fake default constructor - sets only member data and allocates memory
96// for usage restricted to object persistency.
97
100{
101}
102
103///////////////////////////////////////////////////////////
104//
105// Destructor
106
108{
109}
110
111///////////////////////////////////////////////////////////////
112//
113// Copy constructor
114
116 : G4BooleanSolid (rhs)
117{
118}
119
120///////////////////////////////////////////////////////////////
121//
122// Assignment operator
123
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
137///////////////////////////////////////////////////////////////
138//
139//
140
141G4bool
143 const G4VoxelLimits& pVoxelLimit,
144 const G4AffineTransform& pTransform,
145 G4double& pMin,
146 G4double& pMax ) const
147{
148 G4bool touchesA, touchesB, out ;
149 G4double minA = kInfinity, minB = kInfinity,
150 maxA = -kInfinity, maxB = -kInfinity;
151
152 touchesA = fPtrSolidA->CalculateExtent( pAxis, pVoxelLimit,
153 pTransform, minA, maxA);
154 touchesB= fPtrSolidB->CalculateExtent( pAxis, pVoxelLimit,
155 pTransform, minB, maxB);
156 if( touchesA || touchesB )
157 {
158 pMin = std::min( minA, minB );
159 pMax = std::max( maxA, maxB );
160 out = true ;
161 }
162 else out = false ;
163
164 return out ; // It exists in this slice if either one does.
165}
166
167/////////////////////////////////////////////////////
168//
169// Important comment: When solids A and B touch together along flat
170// surface the surface points will be considered as kSurface, while points
171// located around will correspond to kInside
172
174{
175 EInside positionA = fPtrSolidA->Inside(p);
176 if (positionA == kInside) { return kInside; }
177
178 EInside positionB = fPtrSolidB->Inside(p);
179
180 if( positionB == kInside ||
181 ( positionA == kSurface && positionB == kSurface &&
183 fPtrSolidB->SurfaceNormal(p) ).mag2() <
185 {
186 return kInside;
187 }
188 else
189 {
190 if( ( positionB == kSurface ) || ( positionA == kSurface ) )
191 { return kSurface; }
192 else
193 { return kOutside; }
194 }
195}
196
197//////////////////////////////////////////////////////////////
198//
199//
200
203{
204 G4ThreeVector normal;
205
206#ifdef G4BOOLDEBUG
207 if( Inside(p) == kOutside )
208 {
209 G4cout << "WARNING - Invalid call in "
210 << "G4UnionSolid::SurfaceNormal(p)" << G4endl
211 << " Point p is outside !" << G4endl;
212 G4cout << " p = " << p << G4endl;
213 G4cerr << "WARNING - Invalid call in "
214 << "G4UnionSolid::SurfaceNormal(p)" << G4endl
215 << " Point p is outside !" << G4endl;
216 G4cerr << " p = " << p << G4endl;
217 }
218#endif
219
220 if(fPtrSolidA->Inside(p) == kSurface && fPtrSolidB->Inside(p) != kInside)
221 {
222 normal= fPtrSolidA->SurfaceNormal(p) ;
223 }
224 else if(fPtrSolidB->Inside(p) == kSurface &&
226 {
227 normal= fPtrSolidB->SurfaceNormal(p) ;
228 }
229 else
230 {
231 normal= fPtrSolidA->SurfaceNormal(p) ;
232#ifdef G4BOOLDEBUG
233 if(Inside(p)==kInside)
234 {
235 G4cout << "WARNING - Invalid call in "
236 << "G4UnionSolid::SurfaceNormal(p)" << G4endl
237 << " Point p is inside !" << G4endl;
238 G4cout << " p = " << p << G4endl;
239 G4cerr << "WARNING - Invalid call in "
240 << "G4UnionSolid::SurfaceNormal(p)" << G4endl
241 << " Point p is inside !" << G4endl;
242 G4cerr << " p = " << p << G4endl;
243 }
244#endif
245 }
246 return normal;
247}
248
249/////////////////////////////////////////////////////////////
250//
251// The same algorithm as in DistanceToIn(p)
252
255 const G4ThreeVector& v ) const
256{
257#ifdef G4BOOLDEBUG
258 if( Inside(p) == kInside )
259 {
260 G4cout << "WARNING - Invalid call in "
261 << "G4UnionSolid::DistanceToIn(p,v)" << G4endl
262 << " Point p is inside !" << G4endl;
263 G4cout << " p = " << p << G4endl;
264 G4cout << " v = " << v << G4endl;
265 G4cerr << "WARNING - Invalid call in "
266 << "G4UnionSolid::DistanceToIn(p,v)" << G4endl
267 << " Point p is inside !" << G4endl;
268 G4cerr << " p = " << p << G4endl;
269 G4cerr << " v = " << v << G4endl;
270 }
271#endif
272
273 return std::min(fPtrSolidA->DistanceToIn(p,v),
274 fPtrSolidB->DistanceToIn(p,v) ) ;
275}
276
277////////////////////////////////////////////////////////
278//
279// Approximate nearest distance from the point p to the union of
280// two solids
281
284{
285#ifdef G4BOOLDEBUG
286 if( Inside(p) == kInside )
287 {
288 G4cout << "WARNING - Invalid call in "
289 << "G4UnionSolid::DistanceToIn(p)" << G4endl
290 << " Point p is inside !" << G4endl;
291 G4cout << " p = " << p << G4endl;
292 G4cerr << "WARNING - Invalid call in "
293 << "G4UnionSolid::DistanceToIn(p)" << G4endl
294 << " Point p is inside !" << G4endl;
295 G4cerr << " p = " << p << G4endl;
296 }
297#endif
298 G4double distA = fPtrSolidA->DistanceToIn(p) ;
299 G4double distB = fPtrSolidB->DistanceToIn(p) ;
300 G4double safety = std::min(distA,distB) ;
301 if(safety < 0.0) safety = 0.0 ;
302 return safety ;
303}
304
305//////////////////////////////////////////////////////////
306//
307// The same algorithm as DistanceToOut(p)
308
311 const G4ThreeVector& v,
312 const G4bool calcNorm,
313 G4bool *validNorm,
314 G4ThreeVector *n ) const
315{
316 G4double dist = 0.0, disTmp = 0.0 ;
317 G4ThreeVector normTmp;
318 G4ThreeVector* nTmp= &normTmp;
319
320 if( Inside(p) == kOutside )
321 {
322#ifdef G4BOOLDEBUG
323 G4cout << "Position:" << G4endl << G4endl;
324 G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl;
325 G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl;
326 G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl;
327 G4cout << "Direction:" << G4endl << G4endl;
328 G4cout << "v.x() = " << v.x() << G4endl;
329 G4cout << "v.y() = " << v.y() << G4endl;
330 G4cout << "v.z() = " << v.z() << G4endl << G4endl;
331 G4cout << "WARNING - Invalid call in "
332 << "G4UnionSolid::DistanceToOut(p,v)" << G4endl
333 << " Point p is outside !" << G4endl;
334 G4cout << " p = " << p << G4endl;
335 G4cout << " v = " << v << G4endl;
336 G4cerr << "WARNING - Invalid call in "
337 << "G4UnionSolid::DistanceToOut(p,v)" << G4endl
338 << " Point p is outside !" << G4endl;
339 G4cerr << " p = " << p << G4endl;
340 G4cerr << " v = " << v << G4endl;
341#endif
342 }
343 else
344 {
345 EInside positionA = fPtrSolidA->Inside(p) ;
346 // EInside positionB = fPtrSolidB->Inside(p) ;
347
348 if( positionA != kOutside )
349 {
350 do
351 {
352 disTmp = fPtrSolidA->DistanceToOut(p+dist*v,v,calcNorm,
353 validNorm,nTmp) ;
354 dist += disTmp ;
355
356 if(fPtrSolidB->Inside(p+dist*v) != kOutside)
357 {
358 disTmp = fPtrSolidB->DistanceToOut(p+dist*v,v,calcNorm,
359 validNorm,nTmp) ;
360 dist += disTmp ;
361 }
362 }
363 // while( Inside(p+dist*v) == kInside ) ;
364 while( fPtrSolidA->Inside(p+dist*v) != kOutside &&
365 disTmp > 0.5*kCarTolerance ) ;
366 }
367 else // if( positionB != kOutside )
368 {
369 do
370 {
371 disTmp = fPtrSolidB->DistanceToOut(p+dist*v,v,calcNorm,
372 validNorm,nTmp) ;
373 dist += disTmp ;
374
375 if(fPtrSolidA->Inside(p+dist*v) != kOutside)
376 {
377 disTmp = fPtrSolidA->DistanceToOut(p+dist*v,v,calcNorm,
378 validNorm,nTmp) ;
379 dist += disTmp ;
380 }
381 }
382 // while( Inside(p+dist*v) == kInside ) ;
383 while( (fPtrSolidB->Inside(p+dist*v) != kOutside)
384 && (disTmp > 0.5*kCarTolerance) ) ;
385 }
386 }
387 if( calcNorm )
388 {
389 *validNorm = false ;
390 *n = *nTmp ;
391 }
392 return dist ;
393}
394
395//////////////////////////////////////////////////////////////
396//
397// Inverted algorithm of DistanceToIn(p)
398
401{
402 G4double distout = 0.0;
403 if( Inside(p) == kOutside )
404 {
405#ifdef G4BOOLDEBUG
406 G4cout << "WARNING - Invalid call in "
407 << "G4UnionSolid::DistanceToOut(p)" << G4endl
408 << " Point p is outside !" << G4endl;
409 G4cout << " p = " << p << G4endl;
410 G4cerr << "WARNING - Invalid call in "
411 << "G4UnionSolid::DistanceToOut(p)" << G4endl
412 << " Point p is outside !" << G4endl;
413 G4cerr << " p = " << p << G4endl;
414#endif
415 }
416 else
417 {
418 EInside positionA = fPtrSolidA->Inside(p) ;
419 EInside positionB = fPtrSolidB->Inside(p) ;
420
421 // Is this equivalent ??
422 // if( ! ( (positionA == kOutside)) &&
423 // (positionB == kOutside)) )
424 if((positionA == kInside && positionB == kInside ) ||
425 (positionA == kInside && positionB == kSurface ) ||
426 (positionA == kSurface && positionB == kInside ) )
427 {
428 distout= std::max(fPtrSolidA->DistanceToOut(p),
430 }
431 else
432 {
433 if(positionA == kOutside)
434 {
435 distout= fPtrSolidB->DistanceToOut(p) ;
436 }
437 else
438 {
439 distout= fPtrSolidA->DistanceToOut(p) ;
440 }
441 }
442 }
443 return distout;
444}
445
446//////////////////////////////////////////////////////////////
447//
448//
449
451{
452 return G4String("G4UnionSolid");
453}
454
455//////////////////////////////////////////////////////////////////////////
456//
457// Make a clone of the object
458
460{
461 return new G4UnionSolid(*this);
462}
463
464//////////////////////////////////////////////////////////////
465//
466//
467
468void
470 const G4int,
471 const G4VPhysicalVolume* )
472{
473}
474
475/////////////////////////////////////////////////
476//
477//
478
479void
481{
482 scene.AddSolid (*this);
483}
484
485////////////////////////////////////////////////////
486//
487//
488
491{
493 // Stack components and components of components recursively
494 // See G4BooleanSolid::StackPolyhedron
496 G4Polyhedron* result = new G4Polyhedron(*top);
497 if (processor.execute(*result)) { return result; }
498 else { return 0; }
499}
500
501/////////////////////////////////////////////////////////
502//
503//
504
505G4NURBS*
507{
508 // Take into account boolean operation - see CreatePolyhedron.
509 // return new G4NURBSbox (1.0, 1.0, 1.0);
510 return 0;
511}
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()
G4UnionSolid(const G4String &pName, G4VSolid *pSolidA, G4VSolid *pSolidB)
Definition: G4UnionSolid.cc:60
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const
virtual ~G4UnionSolid()
G4NURBS * CreateNURBS() const
EInside Inside(const G4ThreeVector &p) const
G4UnionSolid & operator=(const G4UnionSolid &rhs)
G4GeometryType GetEntityType() const
G4Polyhedron * CreatePolyhedron() const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
void DescribeYourselfTo(G4VGraphicsScene &scene) const
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
G4VSolid * Clone() const
virtual void AddSolid(const G4Box &)=0
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
G4double kCarTolerance
Definition: G4VSolid.hh:307
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
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
#define processor
Definition: xmlparse.cc:600