Geant4-11
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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
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
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
86//
87// Destructor
88//
89G4UGenericPolycone::~G4UGenericPolycone()
90{
91}
92
93
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
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
173//
174// Make a clone of the object
175
176G4VSolid* G4UGenericPolycone::Clone() const
177{
178 return new G4UGenericPolycone(*this);
179}
180
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
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
372//
373// CreatePolyhedron
374
375G4Polyhedron* G4UGenericPolycone::CreatePolyhedron() const
376{
377 return new G4PolyhedronPcon(wrStart, wrDelta, rzcorners);
378}
379
380#endif // G4GEOM_USE_USOLIDS
static const G4double e1[44]
const G4double kCarTolerance
std::vector< G4ThreeVector > G4ThreeVectorList
static const G4double emax
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:35
std::vector< G4TwoVector > G4TwoVectorList
Definition: G4GeomTools.hh:42
static const G4double pMax
static const G4double pMin
static constexpr double twopi
Definition: G4SIunits.hh:56
static constexpr double deg
Definition: G4SIunits.hh:132
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
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
static const G4double kInfinity
Definition: geomdefs.hh:41
Definition: DoubConv.h:17
const char * name(G4int ptype)
#define DBL_EPSILON
Definition: templates.hh:66