Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4Orb.cc
Go to the documentation of this file.
1// ********************************************************************
2// * License and Disclaimer *
3// * *
4// * The Geant4 software is copyright of the Copyright Holders of *
5// * the Geant4 Collaboration. It is provided under the terms and *
6// * conditions of the Geant4 Software License, included in the file *
7// * LICENSE and available at http://cern.ch/geant4/license . These *
8// * include a list of copyright holders. *
9// * *
10// * Neither the authors of this software system, nor their employing *
11// * institutes,nor the agencies providing financial support for this *
12// * work make any representation or warranty, express or implied, *
13// * regarding this software system or assume any liability for its *
14// * use. Please see the license in the file LICENSE and URL above *
15// * for the full disclaimer and the limitation of liability. *
16// * *
17// * This code implementation is the result of the scientific and *
18// * technical work of the GEANT4 collaboration. *
19// * By using, copying, modifying or distributing the software (or *
20// * any work based on the software) you agree to acknowledge its *
21// * use in resulting scientific publications, and indicate your *
22// * acceptance of all terms of the Geant4 Software license. *
23// ********************************************************************
24//
25// Implementation for G4Orb class
26//
27// 20.08.03 V.Grichine - created
28// 08.08.17 E.Tcherniaev - complete revision, speed-up
29// --------------------------------------------------------------------
30
31#include "G4Orb.hh"
32
33#if !defined(G4GEOM_USE_UORB)
34
35#include "G4TwoVector.hh"
36#include "G4VoxelLimits.hh"
37#include "G4AffineTransform.hh"
39#include "G4BoundingEnvelope.hh"
40
42
43#include "G4RandomDirection.hh"
44#include "Randomize.hh"
45
46#include "G4VGraphicsScene.hh"
47#include "G4VisExtent.hh"
48
49using namespace CLHEP;
50
51//////////////////////////////////////////////////////////////////////////
52//
53// Constructor
54
55G4Orb::G4Orb( const G4String& pName, G4double pRmax )
56 : G4CSGSolid(pName), fRmax(pRmax)
57{
58 Initialize();
59}
60
61//////////////////////////////////////////////////////////////////////////
62//
63// Fake default constructor - sets only member data and allocates memory
64// for usage restricted to object persistency
65
66G4Orb::G4Orb( __void__& a )
67 : G4CSGSolid(a)
68{
69}
70
71//////////////////////////////////////////////////////////////////////////
72//
73// Destructor
74
75G4Orb::~G4Orb() = default;
76
77//////////////////////////////////////////////////////////////////////////
78//
79// Copy constructor
80
81G4Orb::G4Orb(const G4Orb&) = default;
82
83//////////////////////////////////////////////////////////////////////////
84//
85// Assignment operator
86
88{
89 // Check assignment to self
90 //
91 if (this == &rhs) { return *this; }
92
93 // Copy base class data
94 //
96
97 // Copy data
98 //
99 fRmax = rhs.fRmax;
100 halfRmaxTol = rhs.halfRmaxTol;
101 sqrRmaxPlusTol = rhs.sqrRmaxPlusTol;
102 sqrRmaxMinusTol = rhs.sqrRmaxMinusTol;
103
104 return *this;
105}
106
107//////////////////////////////////////////////////////////////////////////
108//
109// Check radius and initialize dada members
110
112{
113 const G4double fEpsilon = 2.e-11; // relative tolerance of fRmax
114
115 // Check radius
116 //
117 if ( fRmax < 10*kCarTolerance )
118 {
119 G4Exception("G4Orb::Initialize()", "GeomSolids0002", FatalException,
120 "Invalid radius < 10*kCarTolerance.");
121 }
122 halfRmaxTol = 0.5 * std::max(kCarTolerance, fEpsilon*fRmax);
123 G4double rmaxPlusTol = fRmax + halfRmaxTol;
124 G4double rmaxMinusTol = fRmax - halfRmaxTol;
125 sqrRmaxPlusTol = rmaxPlusTol*rmaxPlusTol;
126 sqrRmaxMinusTol = rmaxMinusTol*rmaxMinusTol;
127}
128
129//////////////////////////////////////////////////////////////////////////
130//
131// Dispatch to parameterisation for replication mechanism dimension
132// computation & modification
133
135 const G4int n,
136 const G4VPhysicalVolume* pRep )
137{
138 p->ComputeDimensions(*this,n,pRep);
139}
140
141//////////////////////////////////////////////////////////////////////////
142//
143// Get bounding box
144
146{
147 G4double radius = GetRadius();
148 pMin.set(-radius,-radius,-radius);
149 pMax.set( radius, radius, radius);
150
151 // Check correctness of the bounding box
152 //
153 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
154 {
155 std::ostringstream message;
156 message << "Bad bounding box (min >= max) for solid: "
157 << GetName() << " !"
158 << "\npMin = " << pMin
159 << "\npMax = " << pMax;
160 G4Exception("G4Orb::BoundingLimits()", "GeomMgt0001",
161 JustWarning, message);
162 DumpInfo();
163 }
164}
165
166//////////////////////////////////////////////////////////////////////////
167//
168// Calculate extent under transform and specified limit
169
171 const G4VoxelLimits& pVoxelLimit,
172 const G4AffineTransform& pTransform,
173 G4double& pMin, G4double& pMax) const
174{
175 G4ThreeVector bmin, bmax;
176 G4bool exist;
177
178 // Get bounding box
179 BoundingLimits(bmin,bmax);
180
181 // Check bounding box
182 G4BoundingEnvelope bbox(bmin,bmax);
183#ifdef G4BBOX_EXTENT
184 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
185#endif
186 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
187 {
188 return exist = pMin < pMax;
189 }
190
191 // Find bounding envelope and calculate extent
192 //
193 static const G4int NTHETA = 8; // number of steps along Theta
194 static const G4int NPHI = 16; // number of steps along Phi
195 static const G4double sinHalfTheta = std::sin(halfpi/NTHETA);
196 static const G4double cosHalfTheta = std::cos(halfpi/NTHETA);
197 static const G4double sinHalfPhi = std::sin(pi/NPHI);
198 static const G4double cosHalfPhi = std::cos(pi/NPHI);
199 static const G4double sinStepTheta = 2.*sinHalfTheta*cosHalfTheta;
200 static const G4double cosStepTheta = 1. - 2.*sinHalfTheta*sinHalfTheta;
201 static const G4double sinStepPhi = 2.*sinHalfPhi*cosHalfPhi;
202 static const G4double cosStepPhi = 1. - 2.*sinHalfPhi*sinHalfPhi;
203
204 G4double radius = GetRadius();
205 G4double rtheta = radius/cosHalfTheta;
206 G4double rphi = rtheta/cosHalfPhi;
207
208 // set reference circle
209 G4TwoVector xy[NPHI];
210 G4double sinCurPhi = sinHalfPhi;
211 G4double cosCurPhi = cosHalfPhi;
212 for (auto & k : xy)
213 {
214 k.set(cosCurPhi,sinCurPhi);
215 G4double sinTmpPhi = sinCurPhi;
216 sinCurPhi = sinCurPhi*cosStepPhi + cosCurPhi*sinStepPhi;
217 cosCurPhi = cosCurPhi*cosStepPhi - sinTmpPhi*sinStepPhi;
218 }
219
220 // set bounding circles
221 G4ThreeVectorList circles[NTHETA];
222 for (auto & circle : circles) { circle.resize(NPHI); }
223
224 G4double sinCurTheta = sinHalfTheta;
225 G4double cosCurTheta = cosHalfTheta;
226 for (auto & circle : circles)
227 {
228 G4double z = rtheta*cosCurTheta;
229 G4double rho = rphi*sinCurTheta;
230 for (G4int k=0; k<NPHI; ++k)
231 {
232 circle[k].set(rho*xy[k].x(),rho*xy[k].y(),z);
233 }
234 G4double sinTmpTheta = sinCurTheta;
235 sinCurTheta = sinCurTheta*cosStepTheta + cosCurTheta*sinStepTheta;
236 cosCurTheta = cosCurTheta*cosStepTheta - sinTmpTheta*sinStepTheta;
237 }
238
239 // set envelope and calculate extent
240 std::vector<const G4ThreeVectorList *> polygons;
241 polygons.resize(NTHETA);
242 for (G4int i=0; i<NTHETA; ++i) { polygons[i] = &circles[i]; }
243
244 G4BoundingEnvelope benv(bmin,bmax,polygons);
245 exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
246 return exist;
247}
248
249//////////////////////////////////////////////////////////////////////////
250//
251// Return whether point is inside/outside/on surface
252
254{
255 G4double rr = p.mag2();
256 if (rr > sqrRmaxPlusTol) return kOutside;
257 return (rr > sqrRmaxMinusTol) ? kSurface : kInside;
258}
259
260//////////////////////////////////////////////////////////////////////////
261//
262// Return unit normal of surface closest to p
263
265{
266 return (1/p.mag())*p;
267}
268
269//////////////////////////////////////////////////////////////////////////
270//
271// Calculate distance to the surface of the orb from outside
272// - return kInfinity if no intersection or
273// intersection distance <= tolerance
274
276 const G4ThreeVector& v ) const
277{
278 // Check if point is on the surface and traveling away
279 //
280 G4double rr = p.mag2();
281 G4double pv = p.dot(v);
282 if (rr >= sqrRmaxMinusTol && pv >= 0) return kInfinity;
283
284 // Find intersection
285 //
286 // Sphere eqn: x^2 + y^2 + z^2 = R^2
287 //
288 // => (px + t*vx)^2 + (py + t*vy)^2 + (pz + t*vz)^2 = R^2
289 // => r^2 + 2t(p.v) + t^2 = R^2
290 // => tmin = -(p.v) - Sqrt((p.v)^2 - (r^2 - R^2))
291 //
292 G4double D = pv*pv - rr + fRmax*fRmax;
293 if (D < 0) return kInfinity; // no intersection
294
295 G4double sqrtD = std::sqrt(D);
296 G4double dist = -pv - sqrtD;
297
298 // Avoid rounding errors due to precision issues seen on 64 bits systems.
299 // Split long distances and recompute
300 //
301 G4double Dmax = 32*fRmax;
302 if (dist > Dmax)
303 {
304 dist = dist - 1.e-8*dist - fRmax; // to stay outside after the move
305 dist += DistanceToIn(p + dist*v, v);
306 return (dist >= kInfinity) ? kInfinity : dist;
307 }
308
309 if (sqrtD*2 <= halfRmaxTol) return kInfinity; // touch
310 return (dist < halfRmaxTol) ? 0. : dist;
311}
312
313//////////////////////////////////////////////////////////////////////////
314//
315// Calculate shortest distance to the boundary from outside
316// - Return 0 if point is inside
317
319{
320 G4double dist = p.mag() - fRmax;
321 return (dist > 0) ? dist : 0.;
322}
323
324//////////////////////////////////////////////////////////////////////////
325//
326// Calculate distance to the surface of the orb from inside and
327// find normal at exit point, if required
328// - when leaving the surface, return 0
329
331 const G4ThreeVector& v,
332 const G4bool calcNorm,
333 G4bool* validNorm,
334 G4ThreeVector* n ) const
335{
336 // Check if point is on the surface and traveling away
337 //
338 G4double rr = p.mag2();
339 G4double pv = p.dot(v);
340 if (rr >= sqrRmaxMinusTol && pv > 0)
341 {
342 if (calcNorm)
343 {
344 *validNorm = true;
345 *n = p*(1./std::sqrt(rr));
346 }
347 return 0.;
348 }
349
350 // Find intersection
351 //
352 // Sphere eqn: x^2 + y^2 + z^2 = R^2
353 //
354 // => (px + t*vx)^2 + (py + t*vy)^2 + (pz + t*vz)^2 = R^2
355 // => r^2 + 2t(p.v) + t^2 = R^2
356 // => tmax = -(p.v) + Sqrt((p.v)^2 - (r^2 - R^2))
357 //
358 G4double D = pv*pv - rr + fRmax*fRmax;
359 G4double tmax = (D <= 0) ? 0. : std::sqrt(D) - pv;
360 if (tmax < halfRmaxTol) tmax = 0.;
361 if (calcNorm)
362 {
363 *validNorm = true;
364 G4ThreeVector ptmax = p + tmax*v;
365 *n = ptmax*(1./ptmax.mag());
366 }
367 return tmax;
368}
369
370//////////////////////////////////////////////////////////////////////////
371//
372// Calculate distance (<=actual) to closest surface of shape from inside
373
375{
376#ifdef G4CSGDEBUG
377 if( Inside(p) == kOutside )
378 {
379 std::ostringstream message;
380 G4int oldprc = message.precision(16);
381 message << "Point p is outside (!?) of solid: " << GetName() << "\n";
382 message << "Position:\n";
383 message << " p.x() = " << p.x()/mm << " mm\n";
384 message << " p.y() = " << p.y()/mm << " mm\n";
385 message << " p.z() = " << p.z()/mm << " mm";
386 G4cout.precision(oldprc);
387 G4Exception("G4Trap::DistanceToOut(p)", "GeomSolids1002",
388 JustWarning, message );
389 DumpInfo();
390 }
391#endif
392 G4double dist = fRmax - p.mag();
393 return (dist > 0) ? dist : 0.;
394}
395
396//////////////////////////////////////////////////////////////////////////
397//
398// G4EntityType
399
401{
402 return {"G4Orb"};
403}
404
405//////////////////////////////////////////////////////////////////////////
406//
407// Make a clone of the object
408
410{
411 return new G4Orb(*this);
412}
413
414//////////////////////////////////////////////////////////////////////////
415//
416// Stream object contents to an output stream
417
418std::ostream& G4Orb::StreamInfo( std::ostream& os ) const
419{
420 G4long oldprc = os.precision(16);
421 os << "-----------------------------------------------------------\n"
422 << " *** Dump for solid - " << GetName() << " ***\n"
423 << " ===================================================\n"
424 << " Solid type: G4Orb\n"
425 << " Parameters: \n"
426 << " outer radius: " << fRmax/mm << " mm \n"
427 << "-----------------------------------------------------------\n";
428 os.precision(oldprc);
429 return os;
430}
431
432//////////////////////////////////////////////////////////////////////////
433//
434// GetPointOnSurface
435
437{
438 return fRmax * G4RandomDirection();
439}
440
441//////////////////////////////////////////////////////////////////////////
442//
443// Methods for visualisation
444
446{
447 scene.AddSolid (*this);
448}
449
451{
452 return {-fRmax, fRmax, -fRmax, fRmax, -fRmax, fRmax};
453}
454
456{
457 return new G4PolyhedronSphere (0., fRmax, 0., 2*pi, 0., pi);
458}
459
460#endif
std::vector< G4ThreeVector > G4ThreeVectorList
G4double D(G4double temp)
@ JustWarning
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4ThreeVector G4RandomDirection()
double G4double
Definition G4Types.hh:83
long G4long
Definition G4Types.hh:87
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
G4GLOB_DLL std::ostream G4cout
double z() const
double x() const
double mag2() const
double y() const
double dot(const Hep3Vector &) const
double mag() const
void set(double x, double y, double z)
G4bool BoundingBoxVsVoxelLimits(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4CSGSolid & operator=(const G4CSGSolid &rhs)
Definition G4CSGSolid.cc:89
Definition G4Orb.hh:56
G4Polyhedron * CreatePolyhedron() const override
Definition G4Orb.cc:455
void Initialize()
Definition G4Orb.cc:111
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep) override
Definition G4Orb.cc:134
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
Definition G4Orb.cc:275
EInside Inside(const G4ThreeVector &p) const override
Definition G4Orb.cc:253
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const override
Definition G4Orb.cc:170
~G4Orb() override
G4double GetRadius() const
std::ostream & StreamInfo(std::ostream &os) const override
Definition G4Orb.cc:418
G4Orb(const G4String &pName, G4double pRmax)
Definition G4Orb.cc:55
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
Definition G4Orb.cc:330
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
Definition G4Orb.cc:264
G4ThreeVector GetPointOnSurface() const override
Definition G4Orb.cc:436
G4GeometryType GetEntityType() const override
Definition G4Orb.cc:400
G4VisExtent GetExtent() const override
Definition G4Orb.cc:450
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
Definition G4Orb.cc:445
G4VSolid * Clone() const override
Definition G4Orb.cc:409
G4Orb & operator=(const G4Orb &rhs)
Definition G4Orb.cc:87
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
Definition G4Orb.cc:145
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