Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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// Implementation of methods for the class G4IntersectionSolid
27//
28// 12.09.98 V.Grichine: first implementation
29// --------------------------------------------------------------------
30
31#include <sstream>
32
34
35#include "G4SystemOfUnits.hh"
36#include "G4VoxelLimits.hh"
38
39#include "G4VGraphicsScene.hh"
40#include "G4Polyhedron.hh"
43
44//////////////////////////////////////////////////////////////////////////
45//
46// Transfer all data members to G4BooleanSolid which is responsible
47// for them. pName will be in turn sent to G4VSolid
48//
49
51 G4VSolid* pSolidA ,
52 G4VSolid* pSolidB )
53 : G4BooleanSolid(pName,pSolidA,pSolidB)
54{
55}
56
57//////////////////////////////////////////////////////////////////////////
58//
59
61 G4VSolid* pSolidA,
62 G4VSolid* pSolidB,
63 G4RotationMatrix* rotMatrix,
64 const G4ThreeVector& transVector )
65 : G4BooleanSolid(pName,pSolidA,pSolidB,rotMatrix,transVector)
66{
67}
68
69//////////////////////////////////////////////////////////////////////////
70//
71//
72
74 G4VSolid* pSolidA,
75 G4VSolid* pSolidB,
76 const G4Transform3D& transform )
77 : G4BooleanSolid(pName,pSolidA,pSolidB,transform)
78{
79}
80
81//////////////////////////////////////////////////////////////////////////
82//
83// Fake default constructor - sets only member data and allocates memory
84// for usage restricted to object persistency.
85
90
91//////////////////////////////////////////////////////////////////////////
92//
93//
94
96
97//////////////////////////////////////////////////////////////////////////
98//
99// Copy constructor
100
102
103//////////////////////////////////////////////////////////////////////////
104//
105// Assignment operator
106
109{
110 // Check assignment to self
111 //
112 if (this == &rhs) { return *this; }
113
114 // Copy base class data
115 //
117
118 return *this;
119}
120
121//////////////////////////////////////////////////////////////////////////
122//
123// Get bounding box
124
125void
127 G4ThreeVector& pMax) const
128{
129 G4ThreeVector minA,maxA, minB,maxB;
130 fPtrSolidA->BoundingLimits(minA,maxA);
131 fPtrSolidB->BoundingLimits(minB,maxB);
132
133 pMin.set(std::max(minA.x(),minB.x()),
134 std::max(minA.y(),minB.y()),
135 std::max(minA.z(),minB.z()));
136
137 pMax.set(std::min(maxA.x(),maxB.x()),
138 std::min(maxA.y(),maxB.y()),
139 std::min(maxA.z(),maxB.z()));
140
141 // Check correctness of the bounding box
142 //
143 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
144 {
145 std::ostringstream message;
146 message << "Bad bounding box (min >= max) for solid: "
147 << GetName() << " !"
148 << "\npMin = " << pMin
149 << "\npMax = " << pMax;
150 G4Exception("G4IntersectionSolid::BoundingLimits()", "GeomMgt0001",
151 JustWarning, message);
152 DumpInfo();
153 }
154}
155
156//////////////////////////////////////////////////////////////////////////
157//
158// Calculate extent under transform and specified limit
159
160G4bool
162 const G4VoxelLimits& pVoxelLimit,
163 const G4AffineTransform& pTransform,
164 G4double& pMin,
165 G4double& pMax) const
166{
167 G4bool retA, retB, out;
168 G4double minA, minB, maxA, maxB;
169
170 retA = fPtrSolidA
171 ->CalculateExtent( pAxis, pVoxelLimit, pTransform, minA, maxA);
172 retB = fPtrSolidB
173 ->CalculateExtent( pAxis, pVoxelLimit, pTransform, minB, maxB);
174
175 if( retA && retB )
176 {
177 pMin = std::max( minA, minB );
178 pMax = std::min( maxA, maxB );
179 out = (pMax > pMin); // true;
180 }
181 else
182 {
183 out = false;
184 }
185
186 return out; // It exists in this slice only if both exist in it.
187}
188
189//////////////////////////////////////////////////////////////////////////
190//
191// Touching ? Empty intersection ?
192
194{
195 EInside positionA = fPtrSolidA->Inside(p);
196 if(positionA == kOutside) return positionA; // outside A
197
198 EInside positionB = fPtrSolidB->Inside(p);
199 if(positionA == kInside) return positionB;
200
201 if(positionB == kOutside) return positionB; // outside B
202 return kSurface; // surface A & B
203}
204
205//////////////////////////////////////////////////////////////////////////
206//
207
210{
211 G4ThreeVector normal;
212 EInside insideA, insideB;
213
214 insideA = fPtrSolidA->Inside(p);
215 insideB = fPtrSolidB->Inside(p);
216
217#ifdef G4BOOLDEBUG
218 if( (insideA == kOutside) || (insideB == kOutside) )
219 {
220 G4cout << "WARNING - Invalid call in "
221 << "G4IntersectionSolid::SurfaceNormal(p)" << G4endl
222 << " Point p is outside !" << G4endl;
223 G4cout << " p = " << p << G4endl;
224 G4cerr << "WARNING - Invalid call in "
225 << "G4IntersectionSolid::SurfaceNormal(p)" << G4endl
226 << " Point p is outside !" << G4endl;
227 G4cerr << " p = " << p << G4endl;
228 }
229#endif
230
231 // On the surface of both is difficult ... treat it like on A now!
232 //
233 if( insideA == kSurface )
234 {
235 normal = fPtrSolidA->SurfaceNormal(p) ;
236 }
237 else if( insideB == kSurface )
238 {
239 normal = fPtrSolidB->SurfaceNormal(p) ;
240 }
241 else // We are on neither surface, so we should generate an exception
242 {
244 {
245 normal= fPtrSolidA->SurfaceNormal(p) ;
246 }
247 else
248 {
249 normal= fPtrSolidB->SurfaceNormal(p) ;
250 }
251#ifdef G4BOOLDEBUG
252 G4cout << "WARNING - Invalid call in "
253 << "G4IntersectionSolid::SurfaceNormal(p)" << G4endl
254 << " Point p is out of surface !" << G4endl;
255 G4cout << " p = " << p << G4endl;
256 G4cerr << "WARNING - Invalid call in "
257 << "G4IntersectionSolid::SurfaceNormal(p)" << G4endl
258 << " Point p is out of surface !" << G4endl;
259 G4cerr << " p = " << p << G4endl;
260#endif
261 }
262
263 return normal;
264}
265
266//////////////////////////////////////////////////////////////////////////
267//
268// The same algorithm as in DistanceToIn(p)
269
272 const G4ThreeVector& v ) const
273{
274 G4double dist = 0.0;
275 if( Inside(p) == kInside )
276 {
277#ifdef G4BOOLDEBUG
278 G4cout << "WARNING - Invalid call in "
279 << "G4IntersectionSolid::DistanceToIn(p,v)" << G4endl
280 << " Point p is inside !" << G4endl;
281 G4cout << " p = " << p << G4endl;
282 G4cout << " v = " << v << G4endl;
283 G4cerr << "WARNING - Invalid call in "
284 << "G4IntersectionSolid::DistanceToIn(p,v)" << G4endl
285 << " Point p is inside !" << G4endl;
286 G4cerr << " p = " << p << G4endl;
287 G4cerr << " v = " << v << G4endl;
288#endif
289 }
290 else // if( Inside(p) == kSurface )
291 {
292 EInside wA = fPtrSolidA->Inside(p);
293 EInside wB = fPtrSolidB->Inside(p);
294
295 G4ThreeVector pA = p, pB = p;
296 G4double dA = 0., dA1=0., dA2=0.;
297 G4double dB = 0., dB1=0., dB2=0.;
298 G4bool doA = true, doB = true;
299
300 static const std::size_t max_trials=10000;
301 for (std::size_t trial=0; trial<max_trials; ++trial)
302 {
303 if(doA)
304 {
305 // find next valid range for A
306
307 dA1 = 0.;
308
309 if( wA != kInside )
310 {
311 dA1 = fPtrSolidA->DistanceToIn(pA, v);
312
313 if( dA1 == kInfinity ) return kInfinity;
314
315 pA += dA1*v;
316 }
317 dA2 = dA1 + fPtrSolidA->DistanceToOut(pA, v);
318 }
319 dA1 += dA;
320 dA2 += dA;
321
322 if(doB)
323 {
324 // find next valid range for B
325
326 dB1 = 0.;
327 if(wB != kInside)
328 {
329 dB1 = fPtrSolidB->DistanceToIn(pB, v);
330
331 if(dB1 == kInfinity) return kInfinity;
332
333 pB += dB1*v;
334 }
335 dB2 = dB1 + fPtrSolidB->DistanceToOut(pB, v);
336 }
337 dB1 += dB;
338 dB2 += dB;
339
340 // check if they overlap
341
342 if( dA1 < dB1 )
343 {
344 if( dB1 < dA2 ) return dB1;
345
346 dA = dA2;
347 pA = p + dA*v; // continue from here
348 wA = kSurface;
349 doA = true;
350 doB = false;
351 }
352 else
353 {
354 if( dA1 < dB2 ) return dA1;
355
356 dB = dB2;
357 pB = p + dB*v; // continue from here
358 wB = kSurface;
359 doB = true;
360 doA = false;
361 }
362 }
363 }
364#ifdef G4BOOLDEBUG
365 G4Exception("G4IntersectionSolid::DistanceToIn(p,v)",
366 "GeomSolids0001", JustWarning,
367 "Reached maximum number of iterations! Returning zero.");
368#endif
369 return dist ;
370}
371
372//////////////////////////////////////////////////////////////////////////
373//
374// Approximate nearest distance from the point p to the intersection of
375// two solids
376
379{
380#ifdef G4BOOLDEBUG
381 if( Inside(p) == kInside )
382 {
383 G4cout << "WARNING - Invalid call in "
384 << "G4IntersectionSolid::DistanceToIn(p)" << G4endl
385 << " Point p is inside !" << G4endl;
386 G4cout << " p = " << p << G4endl;
387 G4cerr << "WARNING - Invalid call in "
388 << "G4IntersectionSolid::DistanceToIn(p)" << G4endl
389 << " Point p is inside !" << G4endl;
390 G4cerr << " p = " << p << G4endl;
391 }
392#endif
393 EInside sideA = fPtrSolidA->Inside(p) ;
394 EInside sideB = fPtrSolidB->Inside(p) ;
395 G4double dist=0.0 ;
396
397 if( sideA != kInside && sideB != kOutside )
398 {
399 dist = fPtrSolidA->DistanceToIn(p) ;
400 }
401 else
402 {
403 if( sideB != kInside && sideA != kOutside )
404 {
405 dist = fPtrSolidB->DistanceToIn(p) ;
406 }
407 else
408 {
409 dist = std::min(fPtrSolidA->DistanceToIn(p),
410 fPtrSolidB->DistanceToIn(p) ) ;
411 }
412 }
413 return dist ;
414}
415
416//////////////////////////////////////////////////////////////////////////
417//
418// The same algorithm as DistanceToOut(p)
419
422 const G4ThreeVector& v,
423 const G4bool calcNorm,
424 G4bool* validNorm,
425 G4ThreeVector* n ) const
426{
427 G4bool validNormA, validNormB;
428 G4ThreeVector nA, nB;
429
430#ifdef G4BOOLDEBUG
431 if( Inside(p) == kOutside )
432 {
433 G4cout << "Position:" << G4endl << G4endl;
434 G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl;
435 G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl;
436 G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl;
437 G4cout << "Direction:" << G4endl << G4endl;
438 G4cout << "v.x() = " << v.x() << G4endl;
439 G4cout << "v.y() = " << v.y() << G4endl;
440 G4cout << "v.z() = " << v.z() << G4endl << G4endl;
441 G4cout << "WARNING - Invalid call in "
442 << "G4IntersectionSolid::DistanceToOut(p,v)" << G4endl
443 << " Point p is outside !" << G4endl;
444 G4cout << " p = " << p << G4endl;
445 G4cout << " v = " << v << G4endl;
446 G4cerr << "WARNING - Invalid call in "
447 << "G4IntersectionSolid::DistanceToOut(p,v)" << G4endl
448 << " Point p is outside !" << G4endl;
449 G4cerr << " p = " << p << G4endl;
450 G4cerr << " v = " << v << G4endl;
451 }
452#endif
453 G4double distA = fPtrSolidA->DistanceToOut(p,v,calcNorm,&validNormA,&nA) ;
454 G4double distB = fPtrSolidB->DistanceToOut(p,v,calcNorm,&validNormB,&nB) ;
455
456 G4double dist = std::min(distA,distB) ;
457
458 if( calcNorm )
459 {
460 if ( distA < distB )
461 {
462 *validNorm = validNormA;
463 *n = nA;
464 }
465 else
466 {
467 *validNorm = validNormB;
468 *n = nB;
469 }
470 }
471
472 return dist ;
473}
474
475//////////////////////////////////////////////////////////////////////////
476//
477// Inverted algorithm of DistanceToIn(p)
478
481{
482#ifdef G4BOOLDEBUG
483 if( Inside(p) == kOutside )
484 {
485 G4cout << "WARNING - Invalid call in "
486 << "G4IntersectionSolid::DistanceToOut(p)" << G4endl
487 << " Point p is outside !" << G4endl;
488 G4cout << " p = " << p << G4endl;
489 G4cerr << "WARNING - Invalid call in "
490 << "G4IntersectionSolid::DistanceToOut(p)" << G4endl
491 << " Point p is outside !" << G4endl;
492 G4cerr << " p = " << p << G4endl;
493 }
494#endif
495
496 return std::min(fPtrSolidA->DistanceToOut(p),
498
499}
500
501//////////////////////////////////////////////////////////////////////////
502//
503// ComputeDimensions
504
505void
511
512//////////////////////////////////////////////////////////////////////////
513//
514// GetEntityType
515
517{
518 return {"G4IntersectionSolid"};
519}
520
521//////////////////////////////////////////////////////////////////////////
522//
523// Make a clone of the object
524
526{
527 return new G4IntersectionSolid(*this);
528}
529
530//////////////////////////////////////////////////////////////////////////
531//
532// DescribeYourselfTo
533
534void
536{
537 scene.AddSolid (*this);
538}
539
540//////////////////////////////////////////////////////////////////////////
541//
542// CreatePolyhedron
543
546{
547 if (fExternalBoolProcessor == nullptr)
548 {
549 HepPolyhedronProcessor processor;
550 // Stack components and components of components recursively
551 // See G4BooleanSolid::StackPolyhedron
552 G4Polyhedron* top = StackPolyhedron(processor, this);
553 auto result = new G4Polyhedron(*top);
554 if (processor.execute(*result))
555 {
556 return result;
557 }
558 else
559 {
560 return nullptr;
561 }
562 }
563 else
564 {
568 }
569}
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
double z() const
double x() const
double y() const
void set(double x, double y, double z)
G4VSolid * fPtrSolidA
G4BooleanSolid & operator=(const G4BooleanSolid &rhs)
G4Polyhedron * GetPolyhedron() const override
G4VSolid * fPtrSolidB
const G4VSolid * GetConstituentSolid(G4int no) const override
static G4VBooleanProcessor * fExternalBoolProcessor
G4Polyhedron * StackPolyhedron(HepPolyhedronProcessor &, const G4VSolid *) const
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4GeometryType GetEntityType() const override
G4Polyhedron * CreatePolyhedron() const override
~G4IntersectionSolid() override
G4IntersectionSolid & operator=(const G4IntersectionSolid &rhs)
G4IntersectionSolid(const G4String &pName, G4VSolid *pSolidA, G4VSolid *pSolidB)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const override
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
EInside Inside(const G4ThreeVector &p) const override
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep) override
G4VSolid * Clone() const override
virtual G4PolyhedronArbitrary * Intersection(G4Polyhedron *, G4Polyhedron *)
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
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const =0
void DumpInfo() const
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const =0
virtual void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
Definition G4VSolid.cc:665
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const =0
bool execute(HepPolyhedron &)
EAxis
Definition geomdefs.hh:54
EInside
Definition geomdefs.hh:67
@ kInside
Definition geomdefs.hh:70
@ kOutside
Definition geomdefs.hh:68
@ kSurface
Definition geomdefs.hh:69