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