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