Geant4  10.01.p03
G4IntersectionSolid.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: G4IntersectionSolid.cc 95297 2016-02-04 09:30:14Z gcosmo $
28 //
29 // Implementation of methods for the class G4IntersectionSolid
30 //
31 // History:
32 //
33 // 17.02.05 V.Grichine: bug was fixed in DistanceToIn(p,v) based on algorithm
34 // proposed by Dino Bazzacco <dino.bazzacco@pd.infn.it>
35 // 29.05.01 V.Grichine: bug was fixed in DistanceToIn(p,v)
36 // 16.03.01 V.Grichine: modifications in CalculateExtent() and Inside()
37 // 29.07.99 V.Grichine: modifications in DistanceToIn(p,v)
38 // 12.09.98 V.Grichine: first implementation
39 //
40 // --------------------------------------------------------------------
41 
42 
43 #include <sstream>
44 
45 #include "G4IntersectionSolid.hh"
46 
47 #include "G4SystemOfUnits.hh"
48 #include "G4VoxelLimits.hh"
49 #include "G4VPVParameterisation.hh"
50 
51 #include "G4VGraphicsScene.hh"
52 #include "G4Polyhedron.hh"
53 #include "HepPolyhedronProcessor.h"
54 
56 //
57 // Transfer all data members to G4BooleanSolid which is responsible
58 // for them. pName will be in turn sent to G4VSolid
59 //
60 
62  G4VSolid* pSolidA ,
63  G4VSolid* pSolidB )
64  : G4BooleanSolid(pName,pSolidA,pSolidB)
65 {
66 }
67 
69 //
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 //
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 //
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 //
140 
141 G4bool
143  const G4VoxelLimits& pVoxelLimit,
144  const G4AffineTransform& pTransform,
145  G4double& pMin,
146  G4double& pMax) const
147 {
148  G4bool retA, retB, out;
149  G4double minA, minB, maxA, maxB;
150 
151  retA = fPtrSolidA
152  ->CalculateExtent( pAxis, pVoxelLimit, pTransform, minA, maxA);
153  retB = fPtrSolidB
154  ->CalculateExtent( pAxis, pVoxelLimit, pTransform, minB, maxB);
155 
156  if( retA && retB )
157  {
158  pMin = std::max( minA, minB );
159  pMax = std::min( maxA, maxB );
160  out = (pMax > pMin); // true;
161 #ifdef G4BOOLDEBUG
162  // G4cout.precision(16);
163  // G4cout<<"pMin = "<<pMin<<"; pMax = "<<pMax<<G4endl;
164 #endif
165  }
166  else out = false;
167 
168  return out; // It exists in this slice only if both exist in it.
169 }
170 
172 //
173 // Touching ? Empty intersection ?
174 
176 {
177  EInside positionA = fPtrSolidA->Inside(p) ;
178 
179  if( positionA == kOutside ) return kOutside ;
180 
181  EInside positionB = fPtrSolidB->Inside(p) ;
182 
183  if(positionA == kInside && positionB == kInside)
184  {
185  return kInside ;
186  }
187  else
188  {
189  if((positionA == kInside && positionB == kSurface) ||
190  (positionB == kInside && positionA == kSurface) ||
191  (positionA == kSurface && positionB == kSurface) )
192  {
193  return kSurface ;
194  }
195  else
196  {
197  return kOutside ;
198  }
199  }
200 }
201 
203 //
204 
207 {
209  EInside insideA, insideB;
210 
211  insideA= fPtrSolidA->Inside(p);
212  insideB= fPtrSolidB->Inside(p);
213 
214 #ifdef G4BOOLDEBUG
215  if( (insideA == kOutside) || (insideB == kOutside) )
216  {
217  G4cout << "WARNING - Invalid call in "
218  << "G4IntersectionSolid::SurfaceNormal(p)" << G4endl
219  << " Point p is outside !" << G4endl;
220  G4cout << " p = " << p << G4endl;
221  G4cerr << "WARNING - Invalid call in "
222  << "G4IntersectionSolid::SurfaceNormal(p)" << G4endl
223  << " Point p is outside !" << G4endl;
224  G4cerr << " p = " << p << G4endl;
225  }
226 #endif
227 
228  // OLD: if(fPtrSolidA->DistanceToOut(p) <= fPtrSolidB->DistanceToOut(p) )
229 
230  // On the surface of both is difficult ... treat it like on A now!
231  //
232  // if( (insideA == kSurface) && (insideB == kSurface) )
233  // normal= fPtrSolidA->SurfaceNormal(p) ;
234  // else
235  if( insideA == kSurface )
236  {
237  normal= fPtrSolidA->SurfaceNormal(p) ;
238  }
239  else if( insideB == kSurface )
240  {
241  normal= fPtrSolidB->SurfaceNormal(p) ;
242  }
243  // We are on neither surface, so we should generate an exception
244  else
245  {
247  normal= fPtrSolidA->SurfaceNormal(p) ;
248  else
249  normal= fPtrSolidB->SurfaceNormal(p) ;
250 #ifdef G4BOOLDEBUG
251  G4cout << "WARNING - Invalid call in "
252  << "G4IntersectionSolid::SurfaceNormal(p)" << G4endl
253  << " Point p is out of surface !" << G4endl;
254  G4cout << " p = " << p << G4endl;
255  G4cerr << "WARNING - Invalid call in "
256  << "G4IntersectionSolid::SurfaceNormal(p)" << G4endl
257  << " Point p is out of surface !" << G4endl;
258  G4cerr << " p = " << p << G4endl;
259 #endif
260  }
261 
262  return normal;
263 }
264 
266 //
267 // The same algorithm as in DistanceToIn(p)
268 
269 G4double
271  const G4ThreeVector& v ) const
272 {
273  G4double dist = 0.0;
274  if( Inside(p) == kInside )
275  {
276 #ifdef G4BOOLDEBUG
277  G4cout << "WARNING - Invalid call in "
278  << "G4IntersectionSolid::DistanceToIn(p,v)" << G4endl
279  << " Point p is inside !" << G4endl;
280  G4cout << " p = " << p << G4endl;
281  G4cout << " v = " << v << G4endl;
282  G4cerr << "WARNING - Invalid call in "
283  << "G4IntersectionSolid::DistanceToIn(p,v)" << G4endl
284  << " Point p is inside !" << G4endl;
285  G4cerr << " p = " << p << G4endl;
286  G4cerr << " v = " << v << G4endl;
287 #endif
288  }
289  else // if( Inside(p) == kSurface )
290  {
291  EInside wA = fPtrSolidA->Inside(p);
292  EInside wB = fPtrSolidB->Inside(p);
293 
294  G4ThreeVector pA = p, pB = p;
295  G4double dA = 0., dA1=0., dA2=0.;
296  G4double dB = 0., dB1=0., dB2=0.;
297  G4bool doA = true, doB = true;
298 
299  static const size_t max_trials=10000;
300  for (size_t trial=0; trial<max_trials; ++trial)
301  {
302  if(doA)
303  {
304  // find next valid range for A
305 
306  dA1 = 0.;
307 
308  if( wA != kInside )
309  {
310  dA1 = fPtrSolidA->DistanceToIn(pA, v);
311 
312  if( dA1 == kInfinity ) return kInfinity;
313 
314  pA += dA1*v;
315  }
316  dA2 = dA1 + fPtrSolidA->DistanceToOut(pA, v);
317  }
318  dA1 += dA;
319  dA2 += dA;
320 
321  if(doB)
322  {
323  // find next valid range for B
324 
325  dB1 = 0.;
326  if(wB != kInside)
327  {
328  dB1 = fPtrSolidB->DistanceToIn(pB, v);
329 
330  if(dB1 == kInfinity) return kInfinity;
331 
332  pB += dB1*v;
333  }
334  dB2 = dB1 + fPtrSolidB->DistanceToOut(pB, v);
335  }
336  dB1 += dB;
337  dB2 += dB;
338 
339  // check if they overlap
340 
341  if( dA1 < dB1 )
342  {
343  if( dB1 < dA2 ) return dB1;
344 
345  dA = dA2;
346  pA = p + dA*v; // continue from here
347  wA = kSurface;
348  doA = true;
349  doB = false;
350  }
351  else
352  {
353  if( dA1 < dB2 ) return dA1;
354 
355  dB = dB2;
356  pB = p + dB*v; // continue from here
357  wB = kSurface;
358  doB = true;
359  doA = false;
360  }
361  }
362  }
363 #ifdef G4BOOLDEBUG
364  G4Exception("G4IntersectionSolid::DistanceToIn(p,v)",
365  "GeomSolids0001", JustWarning,
366  "Reached maximum number of iterations! Returning zero.");
367 #endif
368  return dist ;
369 }
370 
372 //
373 // Approximate nearest distance from the point p to the intersection of
374 // two solids
375 
376 G4double
378 {
379 #ifdef G4BOOLDEBUG
380  if( Inside(p) == kInside )
381  {
382  G4cout << "WARNING - Invalid call in "
383  << "G4IntersectionSolid::DistanceToIn(p)" << G4endl
384  << " Point p is inside !" << G4endl;
385  G4cout << " p = " << p << G4endl;
386  G4cerr << "WARNING - Invalid call in "
387  << "G4IntersectionSolid::DistanceToIn(p)" << G4endl
388  << " Point p is inside !" << G4endl;
389  G4cerr << " p = " << p << G4endl;
390  }
391 #endif
392  EInside sideA = fPtrSolidA->Inside(p) ;
393  EInside sideB = fPtrSolidB->Inside(p) ;
394  G4double dist=0.0 ;
395 
396  if( sideA != kInside && sideB != kOutside )
397  {
398  dist = fPtrSolidA->DistanceToIn(p) ;
399  }
400  else
401  {
402  if( sideB != kInside && sideA != kOutside )
403  {
404  dist = fPtrSolidB->DistanceToIn(p) ;
405  }
406  else
407  {
408  dist = std::min(fPtrSolidA->DistanceToIn(p),
409  fPtrSolidB->DistanceToIn(p) ) ;
410  }
411  }
412  return dist ;
413 }
414 
416 //
417 // The same algorithm as DistanceToOut(p)
418 
419 G4double
421  const G4ThreeVector& v,
422  const G4bool calcNorm,
423  G4bool *validNorm,
424  G4ThreeVector *n ) const
425 {
426  G4bool validNormA, validNormB;
427  G4ThreeVector nA, nB;
428 
429 #ifdef G4BOOLDEBUG
430  if( Inside(p) == kOutside )
431  {
432  G4cout << "Position:" << G4endl << G4endl;
433  G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl;
434  G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl;
435  G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl;
436  G4cout << "Direction:" << G4endl << G4endl;
437  G4cout << "v.x() = " << v.x() << G4endl;
438  G4cout << "v.y() = " << v.y() << G4endl;
439  G4cout << "v.z() = " << v.z() << G4endl << G4endl;
440  G4cout << "WARNING - Invalid call in "
441  << "G4IntersectionSolid::DistanceToOut(p,v)" << G4endl
442  << " Point p is outside !" << G4endl;
443  G4cout << " p = " << p << G4endl;
444  G4cout << " v = " << v << G4endl;
445  G4cerr << "WARNING - Invalid call in "
446  << "G4IntersectionSolid::DistanceToOut(p,v)" << G4endl
447  << " Point p is outside !" << G4endl;
448  G4cerr << " p = " << p << G4endl;
449  G4cerr << " v = " << v << G4endl;
450  }
451 #endif
452  G4double distA = fPtrSolidA->DistanceToOut(p,v,calcNorm,&validNormA,&nA) ;
453  G4double distB = fPtrSolidB->DistanceToOut(p,v,calcNorm,&validNormB,&nB) ;
454 
455  G4double dist = std::min(distA,distB) ;
456 
457  if( calcNorm )
458  {
459  if ( distA < distB )
460  {
461  *validNorm = validNormA;
462  *n = nA;
463  }
464  else
465  {
466  *validNorm = validNormB;
467  *n = nB;
468  }
469  }
470 
471  return dist ;
472 }
473 
475 //
476 // Inverted algorithm of DistanceToIn(p)
477 
478 G4double
480 {
481 #ifdef G4BOOLDEBUG
482  if( Inside(p) == kOutside )
483  {
484  G4cout << "WARNING - Invalid call in "
485  << "G4IntersectionSolid::DistanceToOut(p)" << G4endl
486  << " Point p is outside !" << G4endl;
487  G4cout << " p = " << p << G4endl;
488  G4cerr << "WARNING - Invalid call in "
489  << "G4IntersectionSolid::DistanceToOut(p)" << G4endl
490  << " Point p is outside !" << G4endl;
491  G4cerr << " p = " << p << G4endl;
492  }
493 #endif
494 
495  return std::min(fPtrSolidA->DistanceToOut(p),
496  fPtrSolidB->DistanceToOut(p) ) ;
497 
498 }
499 
501 //
502 //
503 
504 void
506  const G4int,
507  const G4VPhysicalVolume* )
508 {
509 }
510 
512 //
513 //
514 
516 {
517  return G4String("G4IntersectionSolid");
518 }
519 
521 //
522 // Make a clone of the object
523 
525 {
526  return new G4IntersectionSolid(*this);
527 }
528 
530 //
531 //
532 
533 void
535 {
536  scene.AddSolid (*this);
537 }
538 
540 //
541 //
542 
543 G4Polyhedron*
545 {
546  HepPolyhedronProcessor processor;
547  // Stack components and components of components recursively
548  // See G4BooleanSolid::StackPolyhedron
549  G4Polyhedron* top = StackPolyhedron(processor, this);
550  G4Polyhedron* result = new G4Polyhedron(*top);
551  if (processor.execute(*result)) { return result; }
552  else { return 0; }
553 }
G4VSolid * fPtrSolidB
virtual G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const =0
static const G4double kInfinity
Definition: geomdefs.hh:42
EInside Inside(const G4ThreeVector &p) const
CLHEP::Hep3Vector G4ThreeVector
CLHEP::HepRotation G4RotationMatrix
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
G4VSolid * Clone() const
G4double a
Definition: TRTMaterials.hh:39
G4IntersectionSolid(const G4String &pName, G4VSolid *pSolidA, G4VSolid *pSolidB)
virtual void AddSolid(const G4Box &)=0
int G4int
Definition: G4Types.hh:78
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
static double normal(HepRandomEngine *eptr)
Definition: RandPoisson.cc:77
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4GLOB_DLL std::ostream G4cout
virtual EInside Inside(const G4ThreeVector &p) const =0
bool G4bool
Definition: G4Types.hh:79
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const =0
G4GeometryType GetEntityType() const
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const =0
HepGeom::Transform3D G4Transform3D
const G4int n
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
#define processor
Definition: xmlparse.cc:600
G4Polyhedron * CreatePolyhedron() const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const
T max(const T t1, const T t2)
brief Return the largest of the two arguments
EInside
Definition: geomdefs.hh:58
EAxis
Definition: geomdefs.hh:54
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
G4VSolid * fPtrSolidA
#define G4endl
Definition: G4ios.hh:61
G4BooleanSolid & operator=(const G4BooleanSolid &rhs)
void DescribeYourselfTo(G4VGraphicsScene &scene) const
double G4double
Definition: G4Types.hh:76
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const =0
G4IntersectionSolid & operator=(const G4IntersectionSolid &rhs)
static const double mm
Definition: G4SIunits.hh:102
G4Polyhedron * StackPolyhedron(HepPolyhedronProcessor &, const G4VSolid *) const
G4GLOB_DLL std::ostream G4cerr