Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4UGenericPolycone.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 G4UGenericPolycone wrapper class
27//
28// 30.10.13 G.Cosmo, CERN
29// --------------------------------------------------------------------
30
31#include "G4GenericPolycone.hh"
32#include "G4UGenericPolycone.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
41#include "G4Polyhedron.hh"
42
43using namespace CLHEP;
44
45////////////////////////////////////////////////////////////////////////
46//
47// Constructor (generic parameters)
48//
49G4UGenericPolycone::G4UGenericPolycone(const G4String& name,
50 G4double phiStart,
51 G4double phiTotal,
52 G4int numRZ,
53 const G4double r[],
54 const G4double z[] )
55 : Base_t(name, phiStart, phiTotal, numRZ, r, z)
56{
57 wrStart = phiStart; while (wrStart < 0) wrStart += twopi;
58 wrDelta = phiTotal;
59 if (wrDelta <= 0 || wrDelta >= twopi*(1-DBL_EPSILON))
60 {
61 wrStart = 0;
62 wrDelta = twopi;
63 }
64 rzcorners.resize(0);
65 for (G4int i=0; i<numRZ; ++i)
66 {
67 rzcorners.push_back(G4TwoVector(r[i],z[i]));
68 }
69 std::vector<G4int> iout;
71}
72
73
74////////////////////////////////////////////////////////////////////////
75//
76// Fake default constructor - sets only member data and allocates memory
77// for usage restricted to object persistency.
78//
79G4UGenericPolycone::G4UGenericPolycone(__void__& a)
80 : Base_t(a)
81{
82}
83
84
85//////////////////////////////////////////////////////////////////////////
86//
87// Destructor
88//
89G4UGenericPolycone::~G4UGenericPolycone()
90{
91}
92
93
94//////////////////////////////////////////////////////////////////////////
95//
96// Copy constructor
97//
98G4UGenericPolycone::G4UGenericPolycone(const G4UGenericPolycone& source)
99 : Base_t(source)
100{
101 wrStart = source.wrStart;
102 wrDelta = source.wrDelta;
103 rzcorners = source.rzcorners;
104}
105
106
107//////////////////////////////////////////////////////////////////////////
108//
109// Assignment operator
110//
111G4UGenericPolycone&
112G4UGenericPolycone::operator=(const G4UGenericPolycone& source)
113{
114 if (this == &source) return *this;
115
116 Base_t::operator=( source );
117 wrStart = source.wrStart;
118 wrDelta = source.wrDelta;
119 rzcorners = source.rzcorners;
120
121 return *this;
122}
123
124G4double G4UGenericPolycone::GetStartPhi() const
125{
126 return wrStart;
127}
128G4double G4UGenericPolycone::GetEndPhi() const
129{
130 return (wrStart + wrDelta);
131}
132G4double G4UGenericPolycone::GetSinStartPhi() const
133{
134 if (IsOpen()) return 0.;
135 G4double phi = GetStartPhi();
136 return std::sin(phi);
137}
138G4double G4UGenericPolycone::GetCosStartPhi() const
139{
140 if (IsOpen()) return 1.;
141 G4double phi = GetStartPhi();
142 return std::cos(phi);
143}
144G4double G4UGenericPolycone::GetSinEndPhi() const
145{
146 if (IsOpen()) return 0.;
147 G4double phi = GetEndPhi();
148 return std::sin(phi);
149}
150G4double G4UGenericPolycone::GetCosEndPhi() const
151{
152 if (IsOpen()) return 1.;
153 G4double phi = GetEndPhi();
154 return std::cos(phi);
155}
156G4bool G4UGenericPolycone::IsOpen() const
157{
158 return (wrDelta < twopi);
159}
160G4int G4UGenericPolycone::GetNumRZCorner() const
161{
162 return rzcorners.size();
163}
164G4PolyconeSideRZ G4UGenericPolycone::GetCorner(G4int index) const
165{
166 G4TwoVector rz = rzcorners.at(index);
167 G4PolyconeSideRZ psiderz = { rz.x(), rz.y() };
168
169 return psiderz;
170}
171
172//////////////////////////////////////////////////////////////////////////
173//
174// Make a clone of the object
175
176G4VSolid* G4UGenericPolycone::Clone() const
177{
178 return new G4UGenericPolycone(*this);
179}
180
181//////////////////////////////////////////////////////////////////////////
182//
183// Get bounding box
184
185void
186G4UGenericPolycone::BoundingLimits(G4ThreeVector& pMin,
187 G4ThreeVector& pMax) const
188{
189 G4double rmin = kInfinity, rmax = -kInfinity;
190 G4double zmin = kInfinity, zmax = -kInfinity;
191
192 for (G4int i=0; i<GetNumRZCorner(); ++i)
193 {
194 G4PolyconeSideRZ corner = GetCorner(i);
195 if (corner.r < rmin) rmin = corner.r;
196 if (corner.r > rmax) rmax = corner.r;
197 if (corner.z < zmin) zmin = corner.z;
198 if (corner.z > zmax) zmax = corner.z;
199 }
200
201 if (IsOpen())
202 {
203 G4TwoVector vmin,vmax;
204 G4GeomTools::DiskExtent(rmin,rmax,
205 GetSinStartPhi(),GetCosStartPhi(),
206 GetSinEndPhi(),GetCosEndPhi(),
207 vmin,vmax);
208 pMin.set(vmin.x(),vmin.y(),zmin);
209 pMax.set(vmax.x(),vmax.y(),zmax);
210 }
211 else
212 {
213 pMin.set(-rmax,-rmax, zmin);
214 pMax.set( rmax, rmax, zmax);
215 }
216
217 // Check correctness of the bounding box
218 //
219 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
220 {
221 std::ostringstream message;
222 message << "Bad bounding box (min >= max) for solid: "
223 << GetName() << " !"
224 << "\npMin = " << pMin
225 << "\npMax = " << pMax;
226 G4Exception("G4UGenericPolycone::BoundingLimits()", "GeomMgt0001",
227 JustWarning, message);
228 StreamInfo(G4cout);
229 }
230}
231
232//////////////////////////////////////////////////////////////////////////
233//
234// Calculate extent under transform and specified limit
235
236G4bool
237G4UGenericPolycone::CalculateExtent(const EAxis pAxis,
238 const G4VoxelLimits& pVoxelLimit,
239 const G4AffineTransform& pTransform,
240 G4double& pMin, G4double& pMax) const
241{
242 G4ThreeVector bmin, bmax;
243 G4bool exist;
244
245 // Check bounding box (bbox)
246 //
247 BoundingLimits(bmin,bmax);
248 G4BoundingEnvelope bbox(bmin,bmax);
249#ifdef G4BBOX_EXTENT
250 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
251#endif
252 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
253 {
254 return exist = (pMin < pMax) ? true : false;
255 }
256
257 // To find the extent, RZ contour of the polycone is subdivided
258 // in triangles. The extent is calculated as cumulative extent of
259 // all sub-polycones formed by rotation of triangles around Z
260 //
261 G4TwoVectorList contourRZ;
262 G4TwoVectorList triangles;
263 G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
264 G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
265
266 // get RZ contour, ensure anticlockwise order of corners
267 for (G4int i=0; i<GetNumRZCorner(); ++i)
268 {
269 G4PolyconeSideRZ corner = GetCorner(i);
270 contourRZ.push_back(G4TwoVector(corner.r,corner.z));
271 }
272 G4double area = G4GeomTools::PolygonArea(contourRZ);
273 if (area < 0.) std::reverse(contourRZ.begin(),contourRZ.end());
274
275 // triangulate RZ countour
276 if (!G4GeomTools::TriangulatePolygon(contourRZ,triangles))
277 {
278 std::ostringstream message;
279 message << "Triangulation of RZ contour has failed for solid: "
280 << GetName() << " !"
281 << "\nExtent has been calculated using boundary box";
282 G4Exception("G4UGenericPolycone::CalculateExtent()",
283 "GeomMgt1002", JustWarning, message);
284 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
285 }
286
287 // set trigonometric values
288 const G4int NSTEPS = 24; // number of steps for whole circle
289 G4double astep = twopi/NSTEPS; // max angle for one step
290
291 G4double sphi = GetStartPhi();
292 G4double ephi = GetEndPhi();
293 G4double dphi = IsOpen() ? ephi-sphi : twopi;
294 G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
295 G4double ang = dphi/ksteps;
296
297 G4double sinHalf = std::sin(0.5*ang);
298 G4double cosHalf = std::cos(0.5*ang);
299 G4double sinStep = 2.*sinHalf*cosHalf;
300 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
301
302 G4double sinStart = GetSinStartPhi();
303 G4double cosStart = GetCosStartPhi();
304 G4double sinEnd = GetSinEndPhi();
305 G4double cosEnd = GetCosEndPhi();
306
307 // define vectors and arrays
308 std::vector<const G4ThreeVectorList *> polygons;
309 polygons.resize(ksteps+2);
310 G4ThreeVectorList pols[NSTEPS+2];
311 for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(6);
312 for (G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
313 G4double r0[6],z0[6]; // contour with original edges of triangle
314 G4double r1[6]; // shifted radii of external edges of triangle
315
316 // main loop along triangles
317 pMin = kInfinity;
318 pMax =-kInfinity;
319 G4int ntria = triangles.size()/3;
320 for (G4int i=0; i<ntria; ++i)
321 {
322 G4int i3 = i*3;
323 for (G4int k=0; k<3; ++k)
324 {
325 G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3;
326 G4int k2 = k*2;
327 // set contour with original edges of triangle
328 r0[k2+0] = triangles[e0].x(); z0[k2+0] = triangles[e0].y();
329 r0[k2+1] = triangles[e1].x(); z0[k2+1] = triangles[e1].y();
330 // set shifted radii
331 r1[k2+0] = r0[k2+0];
332 r1[k2+1] = r0[k2+1];
333 if (z0[k2+1] - z0[k2+0] <= 0) continue;
334 r1[k2+0] /= cosHalf;
335 r1[k2+1] /= cosHalf;
336 }
337
338 // rotate countour, set sequence of 6-sided polygons
339 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
340 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
341 for (G4int j=0; j<6; ++j)
342 {
343 pols[0][j].set(r0[j]*cosStart,r0[j]*sinStart,z0[j]);
344 }
345 for (G4int k=1; k<ksteps+1; ++k)
346 {
347 for (G4int j=0; j<6; ++j)
348 {
349 pols[k][j].set(r1[j]*cosCur,r1[j]*sinCur,z0[j]);
350 }
351 G4double sinTmp = sinCur;
352 sinCur = sinCur*cosStep + cosCur*sinStep;
353 cosCur = cosCur*cosStep - sinTmp*sinStep;
354 }
355 for (G4int j=0; j<6; ++j)
356 {
357 pols[ksteps+1][j].set(r0[j]*cosEnd,r0[j]*sinEnd,z0[j]);
358 }
359
360 // set sub-envelope and adjust extent
361 G4double emin,emax;
362 G4BoundingEnvelope benv(polygons);
363 if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
364 if (emin < pMin) pMin = emin;
365 if (emax > pMax) pMax = emax;
366 if (eminlim > pMin && emaxlim < pMax) return true; // max possible extent
367 }
368 return (pMin < pMax);
369}
370
371////////////////////////////////////////////////////////////////////////
372//
373// CreatePolyhedron
374
375G4Polyhedron* G4UGenericPolycone::CreatePolyhedron() const
376{
377 return new G4PolyhedronPcon(wrStart, wrDelta, rzcorners);
378}
379
380#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
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
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