Geant4-11
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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
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
57//
58// Fake default constructor - sets only member data and allocates memory
59// for usage restricted to object persistency.
60
61G4UTorus::G4UTorus( __void__& a )
62 : Base_t(a)
63{ }
64
66//
67// Destructor
68
69G4UTorus::~G4UTorus() { }
70
72//
73// Copy constructor
74
75G4UTorus::G4UTorus(const G4UTorus& rhs)
76 : Base_t(rhs)
77{ }
78
80//
81// Assignment operator
82
83G4UTorus& G4UTorus::operator = (const G4UTorus& rhs)
84{
85 // Check assignment to self
86 //
87 if (this == &rhs) { return *this; }
88
89 // Copy base class data
90 //
91 Base_t::operator=(rhs);
92
93 return *this;
94}
95
97//
98// Accessors & modifiers
99
100G4double G4UTorus::GetRmin() const
101{
102 return rmin();
103}
104
105G4double G4UTorus::GetRmax() const
106{
107 return rmax();
108}
109
110G4double G4UTorus::GetRtor() const
111{
112 return rtor();
113}
114
115G4double G4UTorus::GetSPhi() const
116{
117 return sphi();
118}
119
120G4double G4UTorus::GetDPhi() const
121{
122 return dphi();
123}
124
125G4double G4UTorus::GetSinStartPhi() const
126{
127 return std::sin(sphi());
128}
129
130G4double G4UTorus::GetCosStartPhi() const
131{
132 return std::cos(sphi());
133}
134
135G4double G4UTorus::GetSinEndPhi() const
136{
137 return std::sin(sphi()+dphi());
138}
139
140G4double G4UTorus::GetCosEndPhi() const
141{
142 return std::cos(sphi()+dphi());
143}
144
145void G4UTorus::SetRmin(G4double arg)
146{
147 Base_t::SetRMin(arg);
148 fRebuildPolyhedron = true;
149}
150
151void G4UTorus::SetRmax(G4double arg)
152{
153 Base_t::SetRMax(arg);
154 fRebuildPolyhedron = true;
155}
156
157void G4UTorus::SetRtor(G4double arg)
158{
159 Base_t::SetRTor(arg);
160 fRebuildPolyhedron = true;
161}
162
163void G4UTorus::SetSPhi(G4double arg)
164{
165 Base_t::SetSPhi(arg);
166 fRebuildPolyhedron = true;
167}
168
169void G4UTorus::SetDPhi(G4double arg)
170{
171 Base_t::SetDPhi(arg);
172 fRebuildPolyhedron = true;
173}
174
175void G4UTorus::SetAllParameters(G4double arg1, G4double arg2,
176 G4double arg3, G4double arg4, G4double arg5)
177{
178 SetRmin(arg1);
179 SetRmax(arg2);
180 SetRtor(arg3);
181 SetSPhi(arg4);
182 SetDPhi(arg5);
183 fRebuildPolyhedron = true;
184}
185
187//
188// Dispatch to parameterisation for replication mechanism dimension
189// computation & modification.
190
191void G4UTorus::ComputeDimensions(G4VPVParameterisation* p,
192 const G4int n,
193 const G4VPhysicalVolume* pRep)
194{
195 p->ComputeDimensions(*(G4Torus*)this,n,pRep);
196}
197
199//
200// Make a clone of the object
201
202G4VSolid* G4UTorus::Clone() const
203{
204 return new G4UTorus(*this);
205}
206
208//
209// Get bounding box
210
211void G4UTorus::BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const
212{
213 static G4bool checkBBox = true;
214
215 G4double rmax = GetRmax();
216 G4double rtor = GetRtor();
217 G4double rint = rtor - rmax;
218 G4double rext = rtor + rmax;
219 G4double dz = rmax;
220
221 // Find bounding box
222 //
223 if (GetDPhi() >= twopi)
224 {
225 pMin.set(-rext,-rext,-dz);
226 pMax.set( rext, rext, dz);
227 }
228 else
229 {
230 G4TwoVector vmin,vmax;
231 G4GeomTools::DiskExtent(rint,rext,
232 GetSinStartPhi(),GetCosStartPhi(),
233 GetSinEndPhi(),GetCosEndPhi(),
234 vmin,vmax);
235 pMin.set(vmin.x(),vmin.y(),-dz);
236 pMax.set(vmax.x(),vmax.y(), dz);
237 }
238
239 // Check correctness of the bounding box
240 //
241 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
242 {
243 std::ostringstream message;
244 message << "Bad bounding box (min >= max) for solid: "
245 << GetName() << " !"
246 << "\npMin = " << pMin
247 << "\npMax = " << pMax;
248 G4Exception("G4UTorus::BoundingLimits()", "GeomMgt0001",
249 JustWarning, message);
250 StreamInfo(G4cout);
251 }
252
253 // Check consistency of bounding boxes
254 //
255 if (checkBBox)
256 {
257 U3Vector vmin, vmax;
258 Base_t::Extent(vmin,vmax);
259 if (std::abs(pMin.x()-vmin.x()) > kCarTolerance ||
260 std::abs(pMin.y()-vmin.y()) > kCarTolerance ||
261 std::abs(pMin.z()-vmin.z()) > kCarTolerance ||
262 std::abs(pMax.x()-vmax.x()) > kCarTolerance ||
263 std::abs(pMax.y()-vmax.y()) > kCarTolerance ||
264 std::abs(pMax.z()-vmax.z()) > kCarTolerance)
265 {
266 std::ostringstream message;
267 message << "Inconsistency in bounding boxes for solid: "
268 << GetName() << " !"
269 << "\nBBox min: wrapper = " << pMin << " solid = " << vmin
270 << "\nBBox max: wrapper = " << pMax << " solid = " << vmax;
271 G4Exception("G4UTorus::BoundingLimits()", "GeomMgt0001",
272 JustWarning, message);
273 checkBBox = false;
274 }
275 }
276}
277
279//
280// Calculate extent under transform and specified limit
281
282G4bool
283G4UTorus::CalculateExtent(const EAxis pAxis,
284 const G4VoxelLimits& pVoxelLimit,
285 const G4AffineTransform& pTransform,
286 G4double& pMin, G4double& pMax) const
287{
288 G4ThreeVector bmin, bmax;
289 G4bool exist;
290
291 // Get bounding box
292 BoundingLimits(bmin,bmax);
293
294 // Check bounding box
295 G4BoundingEnvelope bbox(bmin,bmax);
296#ifdef G4BBOX_EXTENT
297 if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
298#endif
299 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
300 {
301 return exist = (pMin < pMax) ? true : false;
302 }
303
304 // Get parameters of the solid
305 G4double rmin = GetRmin();
306 G4double rmax = GetRmax();
307 G4double rtor = GetRtor();
308 G4double dphi = GetDPhi();
309 G4double sinStart = GetSinStartPhi();
310 G4double cosStart = GetCosStartPhi();
311 G4double sinEnd = GetSinEndPhi();
312 G4double cosEnd = GetCosEndPhi();
313 G4double rint = rtor - rmax;
314 G4double rext = rtor + rmax;
315
316 // Find bounding envelope and calculate extent
317 //
318 static const G4int NPHI = 24; // number of steps for whole torus
319 static const G4int NDISK = 16; // number of steps for disk
320 static const G4double sinHalfDisk = std::sin(pi/NDISK);
321 static const G4double cosHalfDisk = std::cos(pi/NDISK);
322 static const G4double sinStepDisk = 2.*sinHalfDisk*cosHalfDisk;
323 static const G4double cosStepDisk = 1. - 2.*sinHalfDisk*sinHalfDisk;
324
325 G4double astep = (360/NPHI)*deg; // max angle for one slice in phi
326 G4int kphi = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
327 G4double ang = dphi/kphi;
328
329 G4double sinHalf = std::sin(0.5*ang);
330 G4double cosHalf = std::cos(0.5*ang);
331 G4double sinStep = 2.*sinHalf*cosHalf;
332 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
333
334 // define vectors for bounding envelope
335 G4ThreeVectorList pols[NDISK+1];
336 for (G4int k=0; k<NDISK+1; ++k) pols[k].resize(4);
337
338 std::vector<const G4ThreeVectorList *> polygons;
339 polygons.resize(NDISK+1);
340 for (G4int k=0; k<NDISK+1; ++k) polygons[k] = &pols[k];
341
342 // set internal and external reference circles
343 G4TwoVector rzmin[NDISK];
344 G4TwoVector rzmax[NDISK];
345
346 if ((rtor-rmin*sinHalfDisk)/cosHalf > (rtor+rmin*sinHalfDisk)) rmin = 0;
347 rmax /= cosHalfDisk;
348 G4double sinCurDisk = sinHalfDisk;
349 G4double cosCurDisk = cosHalfDisk;
350 for (G4int k=0; k<NDISK; ++k)
351 {
352 G4double rmincur = rtor + rmin*cosCurDisk;
353 if (cosCurDisk < 0 && rmin > 0) rmincur /= cosHalf;
354 rzmin[k].set(rmincur,rmin*sinCurDisk);
355
356 G4double rmaxcur = rtor + rmax*cosCurDisk;
357 if (cosCurDisk > 0) rmaxcur /= cosHalf;
358 rzmax[k].set(rmaxcur,rmax*sinCurDisk);
359
360 G4double sinTmpDisk = sinCurDisk;
361 sinCurDisk = sinCurDisk*cosStepDisk + cosCurDisk*sinStepDisk;
362 cosCurDisk = cosCurDisk*cosStepDisk - sinTmpDisk*sinStepDisk;
363 }
364
365 // Loop along slices in Phi. The extent is calculated as cumulative
366 // extent of the slices
367 pMin = kInfinity;
368 pMax = -kInfinity;
369 G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
370 G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
371 G4double sinCur1 = 0, cosCur1 = 0, sinCur2 = 0, cosCur2 = 0;
372 for (G4int i=0; i<kphi+1; ++i)
373 {
374 if (i == 0)
375 {
376 sinCur1 = sinStart;
377 cosCur1 = cosStart;
378 sinCur2 = sinCur1*cosHalf + cosCur1*sinHalf;
379 cosCur2 = cosCur1*cosHalf - sinCur1*sinHalf;
380 }
381 else
382 {
383 sinCur1 = sinCur2;
384 cosCur1 = cosCur2;
385 sinCur2 = (i == kphi) ? sinEnd : sinCur1*cosStep + cosCur1*sinStep;
386 cosCur2 = (i == kphi) ? cosEnd : cosCur1*cosStep - sinCur1*sinStep;
387 }
388 for (G4int k=0; k<NDISK; ++k)
389 {
390 G4double r1 = rzmin[k].x(), r2 = rzmax[k].x();
391 G4double z1 = rzmin[k].y(), z2 = rzmax[k].y();
392 pols[k][0].set(r1*cosCur1,r1*sinCur1,z1);
393 pols[k][1].set(r2*cosCur1,r2*sinCur1,z2);
394 pols[k][2].set(r2*cosCur2,r2*sinCur2,z2);
395 pols[k][3].set(r1*cosCur2,r1*sinCur2,z1);
396 }
397 pols[NDISK] = pols[0];
398
399 // get bounding box of current slice
400 G4TwoVector vmin,vmax;
402 DiskExtent(rint,rext,sinCur1,cosCur1,sinCur2,cosCur2,vmin,vmax);
403 bmin.setX(vmin.x()); bmin.setY(vmin.y());
404 bmax.setX(vmax.x()); bmax.setY(vmax.y());
405
406 // set bounding envelope for current slice and adjust extent
407 G4double emin,emax;
408 G4BoundingEnvelope benv(bmin,bmax,polygons);
409 if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
410 if (emin < pMin) pMin = emin;
411 if (emax > pMax) pMax = emax;
412 if (eminlim > pMin && emaxlim < pMax) break; // max possible extent
413 }
414 return (pMin < pMax);
415}
416
418//
419// Create polyhedron for visualization
420
421G4Polyhedron* G4UTorus::CreatePolyhedron() const
422{
423 return new G4PolyhedronTorus(GetRmin(),
424 GetRmax(),
425 GetRtor(),
426 GetSPhi(),
427 GetDPhi());
428}
429
430#endif // G4GEOM_USE_USOLIDS
const G4double kCarTolerance
std::vector< G4ThreeVector > G4ThreeVectorList
static const G4double emax
@ JustWarning
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
static constexpr double twopi
Definition: G4SIunits.hh:56
static constexpr double pi
Definition: G4SIunits.hh:55
static constexpr double deg
Definition: G4SIunits.hh:132
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)
void setY(double)
void setX(double)
static G4bool DiskExtent(G4double rmin, G4double rmax, G4double startPhi, G4double delPhi, G4TwoVector &pmin, G4TwoVector &pmax)
Definition: G4GeomTools.cc:390
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMaxExtent(const EAxis pAxis) const
EAxis
Definition: geomdefs.hh:54
static const G4double kInfinity
Definition: geomdefs.hh:41
Definition: DoubConv.h:17