Geant4  10.03
G4UPolycone.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 //
27 // $Id:$
28 //
29 // Implementation of G4UPolycone wrapper class
30 // --------------------------------------------------------------------
31 
32 #include "G4Polycone.hh"
33 #include "G4UPolycone.hh"
34 
35 #if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
36 
37 #include "G4GeomTools.hh"
38 #include "G4AffineTransform.hh"
39 #include "G4VPVParameterisation.hh"
40 #include "G4BoundingEnvelope.hh"
41 
42 using namespace CLHEP;
43 
45 //
46 // Constructor (GEANT3 style parameters)
47 //
48 G4UPolycone::G4UPolycone( const G4String& name,
49  G4double phiStart,
50  G4double phiTotal,
51  G4int numZPlanes,
52  const G4double zPlane[],
53  const G4double rInner[],
54  const G4double rOuter[] )
55  : G4USolid(name, new UPolycone(name, phiStart, phiTotal,
56  numZPlanes, zPlane, rInner, rOuter))
57 {
58  wrStart = phiStart; while (wrStart < 0) wrStart += twopi;
59  wrDelta = phiTotal;
60  if (wrDelta <= 0 || wrDelta >= twopi*(1-DBL_EPSILON))
61  {
62  wrStart = 0;
63  wrDelta = twopi;
64  }
65  rzcorners.resize(0);
66  for (G4int i=0; i<numZPlanes; ++i)
67  {
68  G4double z = zPlane[i];
69  G4double r = rOuter[i];
70  rzcorners.push_back(G4TwoVector(r,z));
71  }
72  for (G4int i=numZPlanes-1; i>=0; --i)
73  {
74  G4double z = zPlane[i];
75  G4double r = rInner[i];
76  rzcorners.push_back(G4TwoVector(r,z));
77  }
78  std::vector<G4int> iout;
80 }
81 
82 
84 //
85 // Constructor (generic parameters)
86 //
87 G4UPolycone::G4UPolycone(const G4String& name,
88  G4double phiStart,
89  G4double phiTotal,
90  G4int numRZ,
91  const G4double r[],
92  const G4double z[] )
93  : G4USolid(name, new UPolycone(name, phiStart, phiTotal, numRZ, r, z))
94 {
95  wrStart = phiStart; while (wrStart < 0) wrStart += twopi;
96  wrDelta = phiTotal;
97  if (wrDelta <= 0 || wrDelta >= twopi*(1-DBL_EPSILON))
98  {
99  wrStart = 0;
100  wrDelta = twopi;
101  }
102  rzcorners.resize(0);
103  for (G4int i=0; i<numRZ; ++i)
104  {
105  rzcorners.push_back(G4TwoVector(r[i],z[i]));
106  }
107  std::vector<G4int> iout;
109 }
110 
111 
113 //
114 // Fake default constructor - sets only member data and allocates memory
115 // for usage restricted to object persistency.
116 //
117 G4UPolycone::G4UPolycone( __void__& a )
118  : G4USolid(a)
119 {
120 }
121 
122 
124 //
125 // Destructor
126 //
127 G4UPolycone::~G4UPolycone()
128 {
129 }
130 
131 
133 //
134 // Copy constructor
135 //
136 G4UPolycone::G4UPolycone( const G4UPolycone &source )
137  : G4USolid( source )
138 {
139  wrStart = source.wrStart;
140  wrDelta = source.wrDelta;
141  rzcorners = source.rzcorners;
142 }
143 
144 
146 //
147 // Assignment operator
148 //
149 G4UPolycone &G4UPolycone::operator=( const G4UPolycone &source )
150 {
151  if (this == &source) return *this;
152 
153  G4USolid::operator=( source );
154  wrStart = source.wrStart;
155  wrDelta = source.wrDelta;
156  rzcorners = source.rzcorners;
157 
158  return *this;
159 }
160 
161 
163 //
164 // Accessors & modifiers
165 //
166 G4double G4UPolycone::GetStartPhi() const
167 {
168  return wrStart;
169 }
170 G4double G4UPolycone::GetEndPhi() const
171 {
172  return (wrStart + wrDelta);
173 }
174 G4double G4UPolycone::GetSinStartPhi() const
175 {
176  if (!IsOpen()) return 0;
177  G4double phi = GetStartPhi();
178  return std::sin(phi);
179 }
180 G4double G4UPolycone::GetCosStartPhi() const
181 {
182  if (!IsOpen()) return 1;
183  G4double phi = GetStartPhi();
184  return std::cos(phi);
185 }
186 G4double G4UPolycone::GetSinEndPhi() const
187 {
188  if (!IsOpen()) return 0;
189  G4double phi = GetEndPhi();
190  return std::sin(phi);
191 }
192 G4double G4UPolycone::GetCosEndPhi() const
193 {
194  if (!IsOpen()) return 1;
195  G4double phi = GetEndPhi();
196  return std::cos(phi);
197 }
198 G4bool G4UPolycone::IsOpen() const
199 {
200  return (wrDelta < twopi);
201 }
202 G4int G4UPolycone::GetNumRZCorner() const
203 {
204  return rzcorners.size();
205 }
206 G4PolyconeSideRZ G4UPolycone::GetCorner(G4int index) const
207 {
208  G4TwoVector rz = rzcorners.at(index);
209  G4PolyconeSideRZ psiderz = { rz.x(), rz.y() };
210 
211  return psiderz;
212 }
213 G4PolyconeHistorical* G4UPolycone::GetOriginalParameters() const
214 {
215  UPolyconeHistorical* pars = GetShape()->GetOriginalParameters();
216  G4PolyconeHistorical* pdata = new G4PolyconeHistorical(pars->fNumZPlanes);
217  pdata->Start_angle = pars->fStartAngle;
218  pdata->Opening_angle = pars->fOpeningAngle;
219  for (G4int i=0; i<pars->fNumZPlanes; ++i)
220  {
221  pdata->Z_values[i] = pars->fZValues[i];
222  pdata->Rmin[i] = pars->Rmin[i];
223  pdata->Rmax[i] = pars->Rmax[i];
224  }
225  return pdata;
226 }
227 void G4UPolycone::SetOriginalParameters(G4PolyconeHistorical* pars)
228 {
229  UPolyconeHistorical* pdata = GetShape()->GetOriginalParameters();
230  pdata->fStartAngle = pars->Start_angle;
231  pdata->fOpeningAngle = pars->Opening_angle;
232  pdata->fNumZPlanes = pars->Num_z_planes;
233  for (G4int i=0; i<pdata->fNumZPlanes; ++i)
234  {
235  pdata->fZValues[i] = pars->Z_values[i];
236  pdata->Rmin[i] = pars->Rmin[i];
237  pdata->Rmax[i] = pars->Rmax[i];
238  }
239  fRebuildPolyhedron = true;
240 
241  wrStart = pdata->fStartAngle; while (wrStart < 0) wrStart += twopi;
242  wrDelta = pdata->fOpeningAngle;
243  if (wrDelta <= 0 || wrDelta >= twopi*(1-DBL_EPSILON))
244  {
245  wrStart = 0;
246  wrDelta = twopi;
247  }
248  rzcorners.resize(0);
249  for (G4int i=0; i<pdata->fNumZPlanes; ++i)
250  {
251  G4double z = pdata->fZValues[i];
252  G4double r = pdata->Rmax[i];
253  rzcorners.push_back(G4TwoVector(r,z));
254  }
255  for (G4int i=pdata->fNumZPlanes-1; i>=0; --i)
256  {
257  G4double z = pdata->fZValues[i];
258  G4double r = pdata->Rmin[i];
259  rzcorners.push_back(G4TwoVector(r,z));
260  }
261  std::vector<G4int> iout;
263 }
264 G4bool G4UPolycone::Reset()
265 {
266  GetShape()->Reset();
267  return 0;
268 }
269 
271 //
272 // Dispatch to parameterisation for replication mechanism dimension
273 // computation & modification.
274 //
275 void G4UPolycone::ComputeDimensions(G4VPVParameterisation* p,
276  const G4int n,
277  const G4VPhysicalVolume* pRep)
278 {
279  p->ComputeDimensions(*(G4Polycone*)this,n,pRep);
280 }
281 
282 
284 //
285 // Make a clone of the object
286 
287 G4VSolid* G4UPolycone::Clone() const
288 {
289  return new G4UPolycone(*this);
290 }
291 
293 //
294 // Get bounding box
295 
296 void G4UPolycone::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
297 {
298  static G4bool checkBBox = true;
299  static G4bool checkPhi = true;
300 
301  G4double rmin = kInfinity, rmax = -kInfinity;
302  G4double zmin = kInfinity, zmax = -kInfinity;
303 
304  for (G4int i=0; i<GetNumRZCorner(); ++i)
305  {
306  G4PolyconeSideRZ corner = GetCorner(i);
307  if (corner.r < rmin) rmin = corner.r;
308  if (corner.r > rmax) rmax = corner.r;
309  if (corner.z < zmin) zmin = corner.z;
310  if (corner.z > zmax) zmax = corner.z;
311  }
312 
313  if (IsOpen())
314  {
315  G4TwoVector vmin,vmax;
316  G4GeomTools::DiskExtent(rmin,rmax,
317  GetSinStartPhi(),GetCosStartPhi(),
318  GetSinEndPhi(),GetCosEndPhi(),
319  vmin,vmax);
320  pMin.set(vmin.x(),vmin.y(),zmin);
321  pMax.set(vmax.x(),vmax.y(),zmax);
322  }
323  else
324  {
325  pMin.set(-rmax,-rmax, zmin);
326  pMax.set( rmax, rmax, zmax);
327  }
328 
329  // Check correctness of the bounding box
330  //
331  if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
332  {
333  std::ostringstream message;
334  message << "Bad bounding box (min >= max) for solid: "
335  << GetName() << " !"
336  << "\npMin = " << pMin
337  << "\npMax = " << pMax;
338  G4Exception("G4UPolycone::Extent()", "GeomMgt0001", JustWarning, message);
339  StreamInfo(G4cout);
340  }
341 
342  // Check consistency of bounding boxes
343  //
344  if (checkBBox)
345  {
346  UVector3 vmin, vmax;
347  GetShape()->Extent(vmin,vmax);
348  if (std::abs(pMin.x()-vmin.x()) > kCarTolerance ||
349  std::abs(pMin.y()-vmin.y()) > kCarTolerance ||
350  std::abs(pMin.z()-vmin.z()) > kCarTolerance ||
351  std::abs(pMax.x()-vmax.x()) > kCarTolerance ||
352  std::abs(pMax.y()-vmax.y()) > kCarTolerance ||
353  std::abs(pMax.z()-vmax.z()) > kCarTolerance)
354  {
355  std::ostringstream message;
356  message << "Inconsistency in bounding boxes for solid: "
357  << GetName() << " !"
358  << "\nBBox min: wrapper = " << pMin << " solid = " << vmin
359  << "\nBBox max: wrapper = " << pMax << " solid = " << vmax;
360  G4Exception("G4UPolycone::Extent()", "GeomMgt0001", JustWarning, message);
361  checkBBox = false;
362  }
363  }
364 
365  // Check consistency of angles
366  //
367  if (checkPhi)
368  {
369  if (GetStartPhi() != GetShape()->GetStartPhi() ||
370  GetEndPhi() != GetShape()->GetEndPhi() ||
371  IsOpen() != GetShape()->IsOpen())
372  {
373  std::ostringstream message;
374  message << "Inconsistency in Phi angles or # of sides for solid: "
375  << GetName() << " !"
376  << "\nPhi start : wrapper = " << GetStartPhi()
377  << " solid = " << GetShape()->GetStartPhi()
378  << "\nPhi end : wrapper = " << GetEndPhi()
379  << " solid = " << GetShape()->GetEndPhi()
380  << "\nPhi is open: wrapper = " << (IsOpen() ? "true" : "false")
381  << " solid = " << (GetShape()->IsOpen() ? "true" : "false");
382  G4Exception("G4UPolycone::Extent()", "GeomMgt0001", JustWarning, message);
383  checkPhi = false;
384  }
385  }
386 }
387 
389 //
390 // Calculate extent under transform and specified limit
391 
392 G4bool G4UPolycone::CalculateExtent(const EAxis pAxis,
393  const G4VoxelLimits& pVoxelLimit,
394  const G4AffineTransform& pTransform,
395  G4double& pMin, G4double& pMax) const
396 {
397  G4ThreeVector bmin, bmax;
398  G4bool exist;
399 
400  // Check bounding box (bbox)
401  //
402  Extent(bmin,bmax);
403  G4BoundingEnvelope bbox(bmin,bmax);
404 #ifdef G4BBOX_EXTENT
405  if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
406 #endif
407  if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
408  {
409  return exist = (pMin < pMax) ? true : false;
410  }
411 
412  // To find the extent, RZ contour of the polycone is subdivided
413  // in triangles. The extent is calculated as cumulative extent of
414  // all sub-polycones formed by rotation of triangles around Z
415  //
416  G4TwoVectorList contourRZ;
417  G4TwoVectorList triangles;
418  std::vector<G4int> iout;
419  G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
420  G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
421 
422  // get RZ contour, ensure anticlockwise order of corners
423  for (G4int i=0; i<GetNumRZCorner(); ++i)
424  {
425  G4PolyconeSideRZ corner = GetCorner(i);
426  contourRZ.push_back(G4TwoVector(corner.r,corner.z));
427  }
429  G4double area = G4GeomTools::PolygonArea(contourRZ);
430  if (area < 0.) std::reverse(contourRZ.begin(),contourRZ.end());
431 
432  // triangulate RZ countour
433  if (!G4GeomTools::TriangulatePolygon(contourRZ,triangles))
434  {
435  std::ostringstream message;
436  message << "Triangulation of RZ contour has failed for solid: "
437  << GetName() << " !"
438  << "\nExtent has been calculated using boundary box";
439  G4Exception("G4UPolycone::CalculateExtent()",
440  "GeomMgt1002", JustWarning, message);
441  return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
442  }
443 
444  // set trigonometric values
445  const G4int NSTEPS = 24; // number of steps for whole circle
446  G4double astep = (360/NSTEPS)*deg; // max angle for one step
447 
448  G4double sphi = GetStartPhi();
449  G4double ephi = GetEndPhi();
450  G4double dphi = IsOpen() ? ephi-sphi : twopi;
451  G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
452  G4double ang = dphi/ksteps;
453 
454  G4double sinHalf = std::sin(0.5*ang);
455  G4double cosHalf = std::cos(0.5*ang);
456  G4double sinStep = 2.*sinHalf*cosHalf;
457  G4double cosStep = 1. - 2.*sinHalf*sinHalf;
458 
459  G4double sinStart = GetSinStartPhi();
460  G4double cosStart = GetCosStartPhi();
461  G4double sinEnd = GetSinEndPhi();
462  G4double cosEnd = GetCosEndPhi();
463 
464  // define vectors and arrays
465  std::vector<const G4ThreeVectorList *> polygons;
466  polygons.resize(ksteps+2);
467  G4ThreeVectorList pols[NSTEPS+2];
468  for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(6);
469  for (G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
470  G4double r0[6],z0[6]; // contour with original edges of triangle
471  G4double r1[6]; // shifted radii of external edges of triangle
472 
473  // main loop along triangles
474  pMin = kInfinity;
475  pMax =-kInfinity;
476  G4int ntria = triangles.size()/3;
477  for (G4int i=0; i<ntria; ++i)
478  {
479  G4int i3 = i*3;
480  for (G4int k=0; k<3; ++k)
481  {
482  G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3;
483  G4int k2 = k*2;
484  // set contour with original edges of triangle
485  r0[k2+0] = triangles[e0].x(); z0[k2+0] = triangles[e0].y();
486  r0[k2+1] = triangles[e1].x(); z0[k2+1] = triangles[e1].y();
487  // set shifted radii
488  r1[k2+0] = r0[k2+0];
489  r1[k2+1] = r0[k2+1];
490  if (z0[k2+1] - z0[k2+0] <= 0) continue;
491  r1[k2+0] /= cosHalf;
492  r1[k2+1] /= cosHalf;
493  }
494 
495  // rotate countour, set sequence of 6-sided polygons
496  G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
497  G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
498  for (G4int j=0; j<6; ++j) pols[0][j].set(r0[j]*cosStart,r0[j]*sinStart,z0[j]);
499  for (G4int k=1; k<ksteps+1; ++k)
500  {
501  for (G4int j=0; j<6; ++j) pols[k][j].set(r1[j]*cosCur,r1[j]*sinCur,z0[j]);
502  G4double sinTmp = sinCur;
503  sinCur = sinCur*cosStep + cosCur*sinStep;
504  cosCur = cosCur*cosStep - sinTmp*sinStep;
505  }
506  for (G4int j=0; j<6; ++j) pols[ksteps+1][j].set(r0[j]*cosEnd,r0[j]*sinEnd,z0[j]);
507 
508  // set sub-envelope and adjust extent
509  G4double emin,emax;
510  G4BoundingEnvelope benv(polygons);
511  if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
512  if (emin < pMin) pMin = emin;
513  if (emax > pMax) pMax = emax;
514  if (eminlim > pMin && emaxlim < pMax) return true; // max possible extent
515  }
516  return (pMin < pMax);
517 }
518 
520 //
521 // CreatePolyhedron
522 //
523 G4Polyhedron* G4UPolycone::CreatePolyhedron() const
524 {
525  G4PolyconeHistorical* original_parameters = GetOriginalParameters();
527  polyhedron = new G4PolyhedronPcon( original_parameters->Start_angle,
528  original_parameters->Opening_angle,
529  original_parameters->Num_z_planes,
530  original_parameters->Z_values,
531  original_parameters->Rmin,
532  original_parameters->Rmax );
533 
534  delete original_parameters; // delete local copy
535 
536  return polyhedron;
537 }
538 
539 #endif // G4GEOM_USE_USOLIDS
static const G4double kInfinity
Definition: geomdefs.hh:42
CLHEP::Hep3Vector G4ThreeVector
std::vector< ExP01TrackerHit * > a
Definition: ExP01Classes.hh:33
std::vector< G4TwoVector > G4TwoVectorList
Definition: G4GeomTools.hh:50
static G4double PolygonArea(const G4TwoVectorList &polygon)
Definition: G4GeomTools.cc:82
const char * name(G4int ptype)
int G4int
Definition: G4Types.hh:78
static constexpr double twopi
Definition: G4SIunits.hh:76
G4GLOB_DLL std::ostream G4cout
bool G4bool
Definition: G4Types.hh:79
#define DBL_EPSILON
Definition: templates.hh:87
const G4double kCarTolerance
const G4int n
static G4bool TriangulatePolygon(const G4TwoVectorList &polygon, G4TwoVectorList &result)
Definition: G4GeomTools.cc:178
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
static const G4double emax
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
EAxis
Definition: geomdefs.hh:54
CLHEP::Hep2Vector G4TwoVector
Definition: G4TwoVector.hh:42
double G4double
Definition: G4Types.hh:76
static constexpr double deg
Definition: G4SIunits.hh:152
G4double GetMaxExtent(const EAxis pAxis) const
G4double GetMinExtent(const EAxis pAxis) const
static G4bool DiskExtent(G4double rmin, G4double rmax, G4double startPhi, G4double delPhi, G4TwoVector &pmin, G4TwoVector &pmax)
Definition: G4GeomTools.cc:378
static void RemoveRedundantVertices(G4TwoVectorList &polygon, std::vector< G4int > &iout, G4double tolerance=0)
Definition: G4GeomTools.cc:293