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