Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4Box.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 for G4Box class
27//
28// 30.06.95 - P.Kent: First version
29// 20.09.98 - V.Grichine: new algorithm of DistanceToIn(p,v)
30// 18.04.17 - E.Tcherniaev: complete revision, speed-up
31// --------------------------------------------------------------------
32
33#include "G4Box.hh"
34
35#if !defined(G4GEOM_USE_UBOX)
36
37#include "G4SystemOfUnits.hh"
38#include "G4VoxelLimits.hh"
39#include "G4AffineTransform.hh"
40#include "G4BoundingEnvelope.hh"
41#include "G4QuickRand.hh"
42
44
45#include "G4VGraphicsScene.hh"
46#include "G4VisExtent.hh"
47
48////////////////////////////////////////////////////////////////////////
49//
50// Constructor - check & set half widths
51
53 G4double pX,
54 G4double pY,
55 G4double pZ)
56 : G4CSGSolid(pName), fDx(pX), fDy(pY), fDz(pZ)
57{
58 delta = 0.5*kCarTolerance;
59 if (pX < 2*kCarTolerance ||
60 pY < 2*kCarTolerance ||
61 pZ < 2*kCarTolerance) // limit to thickness of surfaces
62 {
63 std::ostringstream message;
64 message << "Dimensions too small for Solid: " << GetName() << "!" << G4endl
65 << " hX, hY, hZ = " << pX << ", " << pY << ", " << pZ;
66 G4Exception("G4Box::G4Box()", "GeomSolids0002", FatalException, message);
67 }
68}
69
70//////////////////////////////////////////////////////////////////////////
71//
72// Fake default constructor - sets only member data and allocates memory
73// for usage restricted to object persistency
74
75G4Box::G4Box( __void__& a )
76 : G4CSGSolid(a), delta(0.)
77{
78}
79
80//////////////////////////////////////////////////////////////////////////
81//
82// Destructor
83
85{
86}
87
88//////////////////////////////////////////////////////////////////////////
89//
90// Copy constructor
91
93 : G4CSGSolid(rhs), fDx(rhs.fDx), fDy(rhs.fDy), fDz(rhs.fDz), delta(rhs.delta)
94{
95}
96
97//////////////////////////////////////////////////////////////////////////
98//
99// Assignment operator
100
102{
103 // Check assignment to self
104 //
105 if (this == &rhs) { return *this; }
106
107 // Copy base class data
108 //
110
111 // Copy data
112 //
113 fDx = rhs.fDx;
114 fDy = rhs.fDy;
115 fDz = rhs.fDz;
116 delta = rhs.delta;
117
118 return *this;
119}
120
121//////////////////////////////////////////////////////////////////////////
122//
123// Set X dimension
124
126{
127 if(dx > 2*kCarTolerance) // limit to thickness of surfaces
128 {
129 fDx = dx;
130 }
131 else
132 {
133 std::ostringstream message;
134 message << "Dimension X too small for solid: " << GetName() << "!"
135 << G4endl
136 << " hX = " << dx;
137 G4Exception("G4Box::SetXHalfLength()", "GeomSolids0002",
138 FatalException, message);
139 }
140 fCubicVolume = 0.;
141 fSurfaceArea = 0.;
142 fRebuildPolyhedron = true;
143}
144
145//////////////////////////////////////////////////////////////////////////
146//
147// Set Y dimension
148
150{
151 if(dy > 2*kCarTolerance) // limit to thickness of surfaces
152 {
153 fDy = dy;
154 }
155 else
156 {
157 std::ostringstream message;
158 message << "Dimension Y too small for solid: " << GetName() << "!\n"
159 << " hY = " << dy;
160 G4Exception("G4Box::SetYHalfLength()", "GeomSolids0002",
161 FatalException, message);
162 }
163 fCubicVolume = 0.;
164 fSurfaceArea = 0.;
165 fRebuildPolyhedron = true;
166}
167
168//////////////////////////////////////////////////////////////////////////
169//
170// Set Z dimension
171
173{
174 if(dz > 2*kCarTolerance) // limit to thickness of surfaces
175 {
176 fDz = dz;
177 }
178 else
179 {
180 std::ostringstream message;
181 message << "Dimension Z too small for solid: " << GetName() << "!\n"
182 << " hZ = " << dz;
183 G4Exception("G4Box::SetZHalfLength()", "GeomSolids0002",
184 FatalException, message);
185 }
186 fCubicVolume = 0.;
187 fSurfaceArea = 0.;
188 fRebuildPolyhedron = true;
189}
190
191//////////////////////////////////////////////////////////////////////////
192//
193// Dispatch to parameterisation for replication mechanism dimension
194// computation & modification.
195
197 const G4int n,
198 const G4VPhysicalVolume* pRep)
199{
200 p->ComputeDimensions(*this,n,pRep);
201}
202
203//////////////////////////////////////////////////////////////////////////
204//
205// Get bounding box
206
208{
209 pMin.set(-fDx,-fDy,-fDz);
210 pMax.set( fDx, fDy, fDz);
211
212 // Check correctness of the bounding box
213 //
214 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
215 {
216 std::ostringstream message;
217 message << "Bad bounding box (min >= max) for solid: "
218 << GetName() << " !"
219 << "\npMin = " << pMin
220 << "\npMax = " << pMax;
221 G4Exception("G4Box::BoundingLimits()", "GeomMgt0001", JustWarning, message);
222 DumpInfo();
223 }
224}
225
226//////////////////////////////////////////////////////////////////////////
227//
228// Calculate extent under transform and specified limit
229
231 const G4VoxelLimits& pVoxelLimit,
232 const G4AffineTransform& pTransform,
233 G4double& pMin, G4double& pMax) const
234{
235 G4ThreeVector bmin, bmax;
236
237 // Get bounding box
238 BoundingLimits(bmin,bmax);
239
240 // Find extent
241 G4BoundingEnvelope bbox(bmin,bmax);
242 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
243}
244
245//////////////////////////////////////////////////////////////////////////
246//
247// Return whether point inside/outside/on surface, using tolerance
248
250{
251 G4double dist = std::max(std::max(
252 std::abs(p.x())-fDx,
253 std::abs(p.y())-fDy),
254 std::abs(p.z())-fDz);
255 return (dist > delta) ? kOutside :
256 ((dist > -delta) ? kSurface : kInside);
257}
258
259//////////////////////////////////////////////////////////////////////////
260//
261// Detect the side(s) and return corresponding normal
262
264{
265 G4ThreeVector norm(0,0,0);
266 G4double px = p.x();
267 if (std::abs(std::abs(px) - fDx) <= delta) norm.setX(px < 0 ? -1. : 1.);
268 G4double py = p.y();
269 if (std::abs(std::abs(py) - fDy) <= delta) norm.setY(py < 0 ? -1. : 1.);
270 G4double pz = p.z();
271 if (std::abs(std::abs(pz) - fDz) <= delta) norm.setZ(pz < 0 ? -1. : 1.);
272
273 G4double nside = norm.mag2(); // number of sides = magnitude squared
274 if (nside == 1)
275 return norm;
276 else if (nside > 1)
277 return norm.unit(); // edge or corner
278 else
279 {
280 // Point is not on the surface
281 //
282#ifdef G4CSGDEBUG
283 std::ostringstream message;
284 G4int oldprc = message.precision(16);
285 message << "Point p is not on surface (!?) of solid: "
286 << GetName() << G4endl;
287 message << "Position:\n";
288 message << " p.x() = " << p.x()/mm << " mm\n";
289 message << " p.y() = " << p.y()/mm << " mm\n";
290 message << " p.z() = " << p.z()/mm << " mm";
291 G4cout.precision(oldprc);
292 G4Exception("G4Box::SurfaceNormal(p)", "GeomSolids1002",
293 JustWarning, message );
294 DumpInfo();
295#endif
296 return ApproxSurfaceNormal(p);
297 }
298}
299
300//////////////////////////////////////////////////////////////////////////
301//
302// Algorithm for SurfaceNormal() following the original specification
303// for points not on the surface
304
305G4ThreeVector G4Box::ApproxSurfaceNormal(const G4ThreeVector& p) const
306{
307 G4double distx = std::abs(p.x()) - fDx;
308 G4double disty = std::abs(p.y()) - fDy;
309 G4double distz = std::abs(p.z()) - fDz;
310
311 if (distx >= disty && distx >= distz)
312 return G4ThreeVector(std::copysign(1.,p.x()), 0., 0.);
313 if (disty >= distx && disty >= distz)
314 return G4ThreeVector(0., std::copysign(1.,p.y()), 0.);
315 else
316 return G4ThreeVector(0., 0., std::copysign(1.,p.z()));
317}
318
319//////////////////////////////////////////////////////////////////////////
320//
321// Calculate distance to box from an outside point
322// - return kInfinity if no intersection
323//
324
326 const G4ThreeVector& v) const
327{
328 // Check if point is on the surface and traveling away
329 //
330 if ((std::abs(p.x()) - fDx) >= -delta && p.x()*v.x() >= 0) return kInfinity;
331 if ((std::abs(p.y()) - fDy) >= -delta && p.y()*v.y() >= 0) return kInfinity;
332 if ((std::abs(p.z()) - fDz) >= -delta && p.z()*v.z() >= 0) return kInfinity;
333
334 // Find intersection
335 //
336 G4double invx = (v.x() == 0) ? DBL_MAX : -1./v.x();
337 G4double dx = std::copysign(fDx,invx);
338 G4double txmin = (p.x() - dx)*invx;
339 G4double txmax = (p.x() + dx)*invx;
340
341 G4double invy = (v.y() == 0) ? DBL_MAX : -1./v.y();
342 G4double dy = std::copysign(fDy,invy);
343 G4double tymin = std::max(txmin,(p.y() - dy)*invy);
344 G4double tymax = std::min(txmax,(p.y() + dy)*invy);
345
346 G4double invz = (v.z() == 0) ? DBL_MAX : -1./v.z();
347 G4double dz = std::copysign(fDz,invz);
348 G4double tmin = std::max(tymin,(p.z() - dz)*invz);
349 G4double tmax = std::min(tymax,(p.z() + dz)*invz);
350
351 if (tmax <= tmin + delta) return kInfinity; // touch or no hit
352 return (tmin < delta) ? 0. : tmin;
353}
354
355//////////////////////////////////////////////////////////////////////////
356//
357// Appoximate distance to box.
358// Returns largest perpendicular distance to the closest x/y/z sides of
359// the box, which is the most fast estimation of the shortest distance to box
360// - If inside return 0
361
363{
364 G4double dist = std::max(std::max(
365 std::abs(p.x())-fDx,
366 std::abs(p.y())-fDy),
367 std::abs(p.z())-fDz);
368 return (dist > 0) ? dist : 0.;
369}
370
371//////////////////////////////////////////////////////////////////////////
372//
373// Calculate distance to surface of the box from inside and
374// find normal at exit point, if required
375// - when leaving the surface, return 0
376
378 const G4ThreeVector& v,
379 const G4bool calcNorm,
380 G4bool* validNorm, G4ThreeVector* n) const
381{
382 // Check if point is on the surface and traveling away
383 //
384 if ((std::abs(p.x()) - fDx) >= -delta && p.x()*v.x() > 0)
385 {
386 if (calcNorm)
387 {
388 *validNorm = true;
389 n->set((p.x() < 0) ? -1. : 1., 0., 0.);
390 }
391 return 0.;
392 }
393 if ((std::abs(p.y()) - fDy) >= -delta && p.y()*v.y() > 0)
394 {
395 if (calcNorm)
396 {
397 *validNorm = true;
398 n->set(0., (p.y() < 0) ? -1. : 1., 0.);
399 }
400 return 0.;
401 }
402 if ((std::abs(p.z()) - fDz) >= -delta && p.z()*v.z() > 0)
403 {
404 if (calcNorm)
405 {
406 *validNorm = true;
407 n->set(0., 0., (p.z() < 0) ? -1. : 1.);
408 }
409 return 0.;
410 }
411
412 // Find intersection
413 //
414 G4double vx = v.x();
415 G4double tx = (vx == 0) ? DBL_MAX : (std::copysign(fDx,vx) - p.x())/vx;
416
417 G4double vy = v.y();
418 G4double ty = (vy == 0) ? tx : (std::copysign(fDy,vy) - p.y())/vy;
419 G4double txy = std::min(tx,ty);
420
421 G4double vz = v.z();
422 G4double tz = (vz == 0) ? txy : (std::copysign(fDz,vz) - p.z())/vz;
423 G4double tmax = std::min(txy,tz);
424
425 // Set normal, if required, and return distance
426 //
427 if (calcNorm)
428 {
429 *validNorm = true;
430 if (tmax == tx) n->set((v.x() < 0) ? -1. : 1., 0., 0.);
431 else if (tmax == ty) n->set(0., (v.y() < 0) ? -1. : 1., 0.);
432 else n->set(0., 0., (v.z() < 0) ? -1. : 1.);
433 }
434 return tmax;
435}
436
437////////////////////////////////////////////////////////////////////////////
438//
439// Calculate exact shortest distance to any boundary from inside
440// - if outside return 0
441
443{
444#ifdef G4CSGDEBUG
445 if( Inside(p) == kOutside )
446 {
447 std::ostringstream message;
448 G4int oldprc = message.precision(16);
449 message << "Point p is outside (!?) of solid: " << GetName() << G4endl;
450 message << "Position:\n";
451 message << " p.x() = " << p.x()/mm << " mm\n";
452 message << " p.y() = " << p.y()/mm << " mm\n";
453 message << " p.z() = " << p.z()/mm << " mm";
454 G4cout.precision(oldprc);
455 G4Exception("G4Box::DistanceToOut(p)", "GeomSolids1002",
456 JustWarning, message );
457 DumpInfo();
458 }
459#endif
460 G4double dist = std::min(std::min(
461 fDx-std::abs(p.x()),
462 fDy-std::abs(p.y())),
463 fDz-std::abs(p.z()));
464 return (dist > 0) ? dist : 0.;
465}
466
467//////////////////////////////////////////////////////////////////////////
468//
469// GetEntityType
470
472{
473 return G4String("G4Box");
474}
475
476//////////////////////////////////////////////////////////////////////////
477//
478// Stream object contents to an output stream
479
480std::ostream& G4Box::StreamInfo(std::ostream& os) const
481{
482 G4long oldprc = os.precision(16);
483 os << "-----------------------------------------------------------\n"
484 << " *** Dump for solid - " << GetName() << " ***\n"
485 << " ===================================================\n"
486 << "Solid type: G4Box\n"
487 << "Parameters: \n"
488 << " half length X: " << fDx/mm << " mm \n"
489 << " half length Y: " << fDy/mm << " mm \n"
490 << " half length Z: " << fDz/mm << " mm \n"
491 << "-----------------------------------------------------------\n";
492 os.precision(oldprc);
493 return os;
494}
495
496//////////////////////////////////////////////////////////////////////////
497//
498// Return a point randomly and uniformly selected on the surface
499
501{
502 G4double sxy = fDx*fDy, sxz = fDx*fDz, syz = fDy*fDz;
503 G4double select = (sxy + sxz + syz)*G4QuickRand();
504 G4double u = 2.*G4QuickRand() - 1.;
505 G4double v = 2.*G4QuickRand() - 1.;
506
507 if (select < sxy)
508 return G4ThreeVector(u*fDx,
509 v*fDy,
510 ((select < 0.5*sxy) ? -fDz : fDz));
511 else if (select < sxy + sxz)
512 return G4ThreeVector(u*fDx,
513 ((select < sxy + 0.5*sxz) ? -fDy : fDy),
514 v*fDz);
515 else
516 return G4ThreeVector(((select < sxy + sxz + 0.5*syz) ? -fDx : fDx),
517 u*fDy,
518 v*fDz);
519}
520
521//////////////////////////////////////////////////////////////////////////
522//
523// Make a clone of the object
524//
526{
527 return new G4Box(*this);
528}
529
530//////////////////////////////////////////////////////////////////////////
531//
532// Methods for visualisation
533
535{
536 scene.AddSolid (*this);
537}
538
540{
541 return G4VisExtent (-fDx, fDx, -fDy, fDy, -fDz, fDz);
542}
543
545{
546 return new G4PolyhedronBox (fDx, fDy, fDz);
547}
548#endif
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
G4double G4QuickRand()
Definition: G4QuickRand.hh:34
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:83
long G4long
Definition: G4Types.hh:87
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
double z() const
Hep3Vector unit() const
double x() const
void setY(double)
double mag2() const
double y() const
void setZ(double)
void set(double x, double y, double z)
void setX(double)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
Definition: G4Box.hh:56
G4Box(const G4String &pName, G4double pX, G4double pY, G4double pZ)
Definition: G4Box.cc:52
virtual ~G4Box()
Definition: G4Box.cc:84
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
Definition: G4Box.cc:230
G4Box & operator=(const G4Box &rhs)
Definition: G4Box.cc:101
std::ostream & StreamInfo(std::ostream &os) const
Definition: G4Box.cc:480
G4VisExtent GetExtent() const
Definition: G4Box.cc:539
G4ThreeVector GetPointOnSurface() const
Definition: G4Box.cc:500
void SetZHalfLength(G4double dz)
Definition: G4Box.cc:172
G4GeometryType GetEntityType() const
Definition: G4Box.cc:471
void DescribeYourselfTo(G4VGraphicsScene &scene) const
Definition: G4Box.cc:534
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
Definition: G4Box.cc:263
void SetYHalfLength(G4double dy)
Definition: G4Box.cc:149
void SetXHalfLength(G4double dx)
Definition: G4Box.cc:125
EInside Inside(const G4ThreeVector &p) const
Definition: G4Box.cc:249
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
Definition: G4Box.cc:207
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
Definition: G4Box.cc:325
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const
Definition: G4Box.cc:377
G4VSolid * Clone() const
Definition: G4Box.cc:525
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
Definition: G4Box.cc:196
G4Polyhedron * CreatePolyhedron() const
Definition: G4Box.cc:544
G4double fSurfaceArea
Definition: G4CSGSolid.hh:71
G4double fCubicVolume
Definition: G4CSGSolid.hh:70
G4bool fRebuildPolyhedron
Definition: G4CSGSolid.hh:72
G4CSGSolid & operator=(const G4CSGSolid &rhs)
Definition: G4CSGSolid.cc:89
virtual void AddSolid(const G4Box &)=0
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4String GetName() const
void DumpInfo() const
G4double kCarTolerance
Definition: G4VSolid.hh:299
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
#define DBL_MAX
Definition: templates.hh:62