Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4UTorus.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 G4UTorus wrapper class
27//
28// 19.08.15 Guilherme Lima, FNAL
29// --------------------------------------------------------------------
30
31#include "G4Torus.hh"
32#include "G4UTorus.hh"
33
34#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
35
36#include "G4TwoVector.hh"
37#include "G4GeomTools.hh"
38#include "G4AffineTransform.hh"
39#include "G4BoundingEnvelope.hh"
40
42
43using namespace CLHEP;
44
45////////////////////////////////////////////////////////////////////////
46//
47// Constructor - check & set half widths
48
49
50G4UTorus::G4UTorus(const G4String& pName,
51 G4double rmin, G4double rmax, G4double rtor,
52 G4double sphi, G4double dphi)
53 : Base_t(pName, rmin, rmax, rtor, sphi, dphi)
54{ }
55
56//////////////////////////////////////////////////////////////////////////
57//
58// Copy constructor
59
60G4UTorus::G4UTorus(const G4UTorus& rhs)
61 : Base_t(rhs)
62{ }
63
64//////////////////////////////////////////////////////////////////////////
65//
66// Assignment operator
67
68G4UTorus& G4UTorus::operator = (const G4UTorus& rhs)
69{
70 // Check assignment to self
71 //
72 if (this == &rhs) { return *this; }
73
74 // Copy base class data
75 //
76 Base_t::operator=(rhs);
77
78 return *this;
79}
80
81//////////////////////////////////////////////////////////////////////////
82//
83// Accessors & modifiers
84
85G4double G4UTorus::GetRmin() const
86{
87 return rmin();
88}
89
90G4double G4UTorus::GetRmax() const
91{
92 return rmax();
93}
94
95G4double G4UTorus::GetRtor() const
96{
97 return rtor();
98}
99
100G4double G4UTorus::GetSPhi() const
101{
102 return sphi();
103}
104
105G4double G4UTorus::GetDPhi() const
106{
107 return dphi();
108}
109
110G4double G4UTorus::GetSinStartPhi() const
111{
112 return std::sin(sphi());
113}
114
115G4double G4UTorus::GetCosStartPhi() const
116{
117 return std::cos(sphi());
118}
119
120G4double G4UTorus::GetSinEndPhi() const
121{
122 return std::sin(sphi()+dphi());
123}
124
125G4double G4UTorus::GetCosEndPhi() const
126{
127 return std::cos(sphi()+dphi());
128}
129
130void G4UTorus::SetRmin(G4double arg)
131{
132 Base_t::SetRMin(arg);
133 fRebuildPolyhedron = true;
134}
135
136void G4UTorus::SetRmax(G4double arg)
137{
138 Base_t::SetRMax(arg);
139 fRebuildPolyhedron = true;
140}
141
142void G4UTorus::SetRtor(G4double arg)
143{
144 Base_t::SetRTor(arg);
145 fRebuildPolyhedron = true;
146}
147
148void G4UTorus::SetSPhi(G4double arg)
149{
150 Base_t::SetSPhi(arg);
151 fRebuildPolyhedron = true;
152}
153
154void G4UTorus::SetDPhi(G4double arg)
155{
156 Base_t::SetDPhi(arg);
157 fRebuildPolyhedron = true;
158}
159
160void G4UTorus::SetAllParameters(G4double arg1, G4double arg2,
161 G4double arg3, G4double arg4, G4double arg5)
162{
163 SetRmin(arg1);
164 SetRmax(arg2);
165 SetRtor(arg3);
166 SetSPhi(arg4);
167 SetDPhi(arg5);
168 fRebuildPolyhedron = true;
169}
170
171////////////////////////////////////////////////////////////////////////
172//
173// Dispatch to parameterisation for replication mechanism dimension
174// computation & modification.
175
176void G4UTorus::ComputeDimensions(G4VPVParameterisation* p,
177 const G4int n,
178 const G4VPhysicalVolume* pRep)
179{
180 p->ComputeDimensions(*(G4Torus*)this,n,pRep);
181}
182
183//////////////////////////////////////////////////////////////////////////
184//
185// Make a clone of the object
186
187G4VSolid* G4UTorus::Clone() const
188{
189 return new G4UTorus(*this);
190}
191
192//////////////////////////////////////////////////////////////////////////
193//
194// Get bounding box
195
196void G4UTorus::BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const
197{
198 static G4bool checkBBox = true;
199
200 G4double rmax = GetRmax();
201 G4double rtor = GetRtor();
202 G4double rint = rtor - rmax;
203 G4double rext = rtor + rmax;
204 G4double dz = rmax;
205
206 // Find bounding box
207 //
208 if (GetDPhi() >= twopi)
209 {
210 pMin.set(-rext,-rext,-dz);
211 pMax.set( rext, rext, dz);
212 }
213 else
214 {
215 G4TwoVector vmin,vmax;
216 G4GeomTools::DiskExtent(rint,rext,
217 GetSinStartPhi(),GetCosStartPhi(),
218 GetSinEndPhi(),GetCosEndPhi(),
219 vmin,vmax);
220 pMin.set(vmin.x(),vmin.y(),-dz);
221 pMax.set(vmax.x(),vmax.y(), dz);
222 }
223
224 // Check correctness of the bounding box
225 //
226 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
227 {
228 std::ostringstream message;
229 message << "Bad bounding box (min >= max) for solid: "
230 << GetName() << " !"
231 << "\npMin = " << pMin
232 << "\npMax = " << pMax;
233 G4Exception("G4UTorus::BoundingLimits()", "GeomMgt0001",
234 JustWarning, message);
235 StreamInfo(G4cout);
236 }
237
238 // Check consistency of bounding boxes
239 //
240 if (checkBBox)
241 {
242 U3Vector vmin, vmax;
243 Base_t::Extent(vmin,vmax);
244 if (std::abs(pMin.x()-vmin.x()) > kCarTolerance ||
245 std::abs(pMin.y()-vmin.y()) > kCarTolerance ||
246 std::abs(pMin.z()-vmin.z()) > kCarTolerance ||
247 std::abs(pMax.x()-vmax.x()) > kCarTolerance ||
248 std::abs(pMax.y()-vmax.y()) > kCarTolerance ||
249 std::abs(pMax.z()-vmax.z()) > kCarTolerance)
250 {
251 std::ostringstream message;
252 message << "Inconsistency in bounding boxes for solid: "
253 << GetName() << " !"
254 << "\nBBox min: wrapper = " << pMin << " solid = " << vmin
255 << "\nBBox max: wrapper = " << pMax << " solid = " << vmax;
256 G4Exception("G4UTorus::BoundingLimits()", "GeomMgt0001",
257 JustWarning, message);
258 checkBBox = false;
259 }
260 }
261}
262
263//////////////////////////////////////////////////////////////////////////
264//
265// Calculate extent under transform and specified limit
266
267G4bool
268G4UTorus::CalculateExtent(const EAxis pAxis,
269 const G4VoxelLimits& pVoxelLimit,
270 const G4AffineTransform& pTransform,
271 G4double& pMin, G4double& pMax) const
272{
273 G4ThreeVector bmin, bmax;
274 G4bool exist;
275
276 // Get bounding box
277 BoundingLimits(bmin,bmax);
278
279 // Check bounding box
280 G4BoundingEnvelope bbox(bmin,bmax);
281#ifdef G4BBOX_EXTENT
282 if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
283#endif
284 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
285 {
286 return exist = pMin < pMax;
287 }
288
289 // Get parameters of the solid
290 G4double rmin = GetRmin();
291 G4double rmax = GetRmax();
292 G4double rtor = GetRtor();
293 G4double dphi = GetDPhi();
294 G4double sinStart = GetSinStartPhi();
295 G4double cosStart = GetCosStartPhi();
296 G4double sinEnd = GetSinEndPhi();
297 G4double cosEnd = GetCosEndPhi();
298 G4double rint = rtor - rmax;
299 G4double rext = rtor + rmax;
300
301 // Find bounding envelope and calculate extent
302 //
303 static const G4int NPHI = 24; // number of steps for whole torus
304 static const G4int NDISK = 16; // number of steps for disk
305 static const G4double sinHalfDisk = std::sin(pi/NDISK);
306 static const G4double cosHalfDisk = std::cos(pi/NDISK);
307 static const G4double sinStepDisk = 2.*sinHalfDisk*cosHalfDisk;
308 static const G4double cosStepDisk = 1. - 2.*sinHalfDisk*sinHalfDisk;
309
310 G4double astep = (360/NPHI)*deg; // max angle for one slice in phi
311 G4int kphi = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
312 G4double ang = dphi/kphi;
313
314 G4double sinHalf = std::sin(0.5*ang);
315 G4double cosHalf = std::cos(0.5*ang);
316 G4double sinStep = 2.*sinHalf*cosHalf;
317 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
318
319 // define vectors for bounding envelope
320 G4ThreeVectorList pols[NDISK+1];
321 for (auto & pol : pols) pol.resize(4);
322
323 std::vector<const G4ThreeVectorList *> polygons;
324 polygons.resize(NDISK+1);
325 for (G4int k=0; k<NDISK+1; ++k) polygons[k] = &pols[k];
326
327 // set internal and external reference circles
328 G4TwoVector rzmin[NDISK];
329 G4TwoVector rzmax[NDISK];
330
331 if ((rtor-rmin*sinHalfDisk)/cosHalf > (rtor+rmin*sinHalfDisk)) rmin = 0;
332 rmax /= cosHalfDisk;
333 G4double sinCurDisk = sinHalfDisk;
334 G4double cosCurDisk = cosHalfDisk;
335 for (G4int k=0; k<NDISK; ++k)
336 {
337 G4double rmincur = rtor + rmin*cosCurDisk;
338 if (cosCurDisk < 0 && rmin > 0) rmincur /= cosHalf;
339 rzmin[k].set(rmincur,rmin*sinCurDisk);
340
341 G4double rmaxcur = rtor + rmax*cosCurDisk;
342 if (cosCurDisk > 0) rmaxcur /= cosHalf;
343 rzmax[k].set(rmaxcur,rmax*sinCurDisk);
344
345 G4double sinTmpDisk = sinCurDisk;
346 sinCurDisk = sinCurDisk*cosStepDisk + cosCurDisk*sinStepDisk;
347 cosCurDisk = cosCurDisk*cosStepDisk - sinTmpDisk*sinStepDisk;
348 }
349
350 // Loop along slices in Phi. The extent is calculated as cumulative
351 // extent of the slices
352 pMin = kInfinity;
353 pMax = -kInfinity;
354 G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
355 G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
356 G4double sinCur1 = 0, cosCur1 = 0, sinCur2 = 0, cosCur2 = 0;
357 for (G4int i=0; i<kphi+1; ++i)
358 {
359 if (i == 0)
360 {
361 sinCur1 = sinStart;
362 cosCur1 = cosStart;
363 sinCur2 = sinCur1*cosHalf + cosCur1*sinHalf;
364 cosCur2 = cosCur1*cosHalf - sinCur1*sinHalf;
365 }
366 else
367 {
368 sinCur1 = sinCur2;
369 cosCur1 = cosCur2;
370 sinCur2 = (i == kphi) ? sinEnd : sinCur1*cosStep + cosCur1*sinStep;
371 cosCur2 = (i == kphi) ? cosEnd : cosCur1*cosStep - sinCur1*sinStep;
372 }
373 for (G4int k=0; k<NDISK; ++k)
374 {
375 G4double r1 = rzmin[k].x(), r2 = rzmax[k].x();
376 G4double z1 = rzmin[k].y(), z2 = rzmax[k].y();
377 pols[k][0].set(r1*cosCur1,r1*sinCur1,z1);
378 pols[k][1].set(r2*cosCur1,r2*sinCur1,z2);
379 pols[k][2].set(r2*cosCur2,r2*sinCur2,z2);
380 pols[k][3].set(r1*cosCur2,r1*sinCur2,z1);
381 }
382 pols[NDISK] = pols[0];
383
384 // get bounding box of current slice
385 G4TwoVector vmin,vmax;
387 DiskExtent(rint,rext,sinCur1,cosCur1,sinCur2,cosCur2,vmin,vmax);
388 bmin.setX(vmin.x()); bmin.setY(vmin.y());
389 bmax.setX(vmax.x()); bmax.setY(vmax.y());
390
391 // set bounding envelope for current slice and adjust extent
392 G4double emin,emax;
393 G4BoundingEnvelope benv(bmin,bmax,polygons);
394 if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
395 if (emin < pMin) pMin = emin;
396 if (emax > pMax) pMax = emax;
397 if (eminlim > pMin && emaxlim < pMax) break; // max possible extent
398 }
399 return (pMin < pMax);
400}
401
402//////////////////////////////////////////////////////////////////////////
403//
404// Create polyhedron for visualization
405
406G4Polyhedron* G4UTorus::CreatePolyhedron() const
407{
408 return new G4PolyhedronTorus(GetRmin(),
409 GetRmax(),
410 GetRtor(),
411 GetSPhi(),
412 GetDPhi());
413}
414
415#endif // G4GEOM_USE_USOLIDS
const G4double kCarTolerance
std::vector< G4ThreeVector > G4ThreeVectorList
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
G4GLOB_DLL std::ostream G4cout
double x() const
double y() const
void set(double x, double y)
double z() const
double x() const
void setY(double)
double y() const
void set(double x, double y, double z)
void setX(double)
G4AffineTransform is a class for geometric affine transformations. It supports efficient arbitrary ro...
G4BoundingEnvelope is a helper class to facilitate calculation of the extent of a solid within the li...
static G4bool DiskExtent(G4double rmin, G4double rmax, G4double startPhi, G4double delPhi, G4TwoVector &pmin, G4TwoVector &pmax)
G4Torus represents a torus or torus segment with curved sides parallel to the z-axis....
Definition G4Torus.hh:102
G4VPVParameterisation ia an abstract base class for Parameterisation, able to compute the transformat...
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4VPhysicalVolume is an abstract base class for the representation of a positioned volume....
G4VSolid is an abstract base class for solids, physical shapes that can be tracked through....
Definition G4VSolid.hh:80
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMaxExtent(const EAxis pAxis) const
EAxis
Definition geomdefs.hh:54