Geant4-11
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
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
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
81//
82// Destructor
83
85{
86}
87
89//
90// Copy constructor
91
93 : G4CSGSolid(rhs), fDx(rhs.fDx), fDy(rhs.fDy), fDz(rhs.fDz), delta(rhs.delta)
94{
95}
96
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
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
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
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
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
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
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
246//
247// Return whether point inside/outside/on surface, using tolerance
248
250{
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
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
301//
302// Algorithm for SurfaceNormal() following the original specification
303// for points not on the surface
304
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
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
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{
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
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
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
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
468//
469// GetEntityType
470
472{
473 return G4String("G4Box");
474}
475
477//
478// Stream object contents to an output stream
479
480std::ostream& G4Box::StreamInfo(std::ostream& os) const
481{
482 G4int 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
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
522//
523// Make a clone of the object
524//
526{
527 return new G4Box(*this);
528}
529
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:35
static const G4double pMax
static const G4double pMin
G4double G4QuickRand()
Definition: G4QuickRand.hh:34
static constexpr double mm
Definition: G4SIunits.hh:95
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:83
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 setX(double)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
Definition: G4Box.hh:56
G4double fDx
Definition: G4Box.hh:132
G4double fDz
Definition: G4Box.hh:132
G4double fDy
Definition: G4Box.hh:132
G4ThreeVector ApproxSurfaceNormal(const G4ThreeVector &p) const
Definition: G4Box.cc:305
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
G4double delta
Definition: G4Box.hh:133
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
static const G4double kInfinity
Definition: geomdefs.hh:41
T max(const T t1, const T t2)
brief Return the largest of the two arguments
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
#define DBL_MAX
Definition: templates.hh:62