Geant4  10.02
G4UPolyhedra.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 "G4Polyhedra.hh"
33 #include "G4UPolyhedra.hh"
34 
35 #if defined(G4GEOM_USE_USOLIDS)
36 
37 #include "G4VPVParameterisation.hh"
38 
39 using CLHEP::twopi;
40 
42 //
43 // Constructor (GEANT3 style parameters)
44 //
45 // GEANT3 PGON radii are specified in the distance to the norm of each face.
46 //
47 G4UPolyhedra::G4UPolyhedra(const G4String& name,
48  G4double phiStart,
49  G4double phiTotal,
50  G4int numSide,
51  G4int numZPlanes,
52  const G4double zPlane[],
53  const G4double rInner[],
54  const G4double rOuter[] )
55  : G4USolid(name, new UPolyhedra(name,phiStart, phiTotal, numSide,
56  numZPlanes, zPlane, rInner, rOuter))
57 {
58 }
59 
60 
62 //
63 // Constructor (generic parameters)
64 //
65 G4UPolyhedra::G4UPolyhedra(const G4String& name,
66  G4double phiStart,
67  G4double phiTotal,
68  G4int numSide,
69  G4int numRZ,
70  const G4double r[],
71  const G4double z[] )
72  : G4USolid(name, new UPolyhedra(name, phiStart, phiTotal, numSide,
73  numRZ, r, z))
74 {
75 }
76 
77 
79 //
80 // Fake default constructor - sets only member data and allocates memory
81 // for usage restricted to object persistency.
82 //
83 G4UPolyhedra::G4UPolyhedra( __void__& a )
84  : G4USolid(a)
85 {
86 }
87 
88 
90 //
91 // Destructor
92 //
93 G4UPolyhedra::~G4UPolyhedra()
94 {
95 }
96 
97 
99 //
100 // Copy constructor
101 //
102 G4UPolyhedra::G4UPolyhedra( const G4UPolyhedra &source )
103  : G4USolid( source )
104 {
105 }
106 
107 
109 //
110 // Assignment operator
111 //
112 G4UPolyhedra& G4UPolyhedra::operator=( const G4UPolyhedra &source )
113 {
114  if (this == &source) return *this;
115 
116  G4USolid::operator=( source );
117 
118  return *this;
119 }
120 
121 
123 //
124 // Dispatch to parameterisation for replication mechanism dimension
125 // computation & modification.
126 //
127 void G4UPolyhedra::ComputeDimensions(G4VPVParameterisation* p,
128  const G4int n,
129  const G4VPhysicalVolume* pRep)
130 {
131  p->ComputeDimensions(*(G4Polyhedra*)this,n,pRep);
132 }
133 
134 
136 //
137 // Make a clone of the object
138 
139 G4VSolid* G4UPolyhedra::Clone() const
140 {
141  return new G4UPolyhedra(*this);
142 }
143 
144 
146 //
147 // CreatePolyhedron
148 //
149 G4Polyhedron* G4UPolyhedra::CreatePolyhedron() const
150 {
151  if (!IsGeneric())
152  {
153  G4PolyhedraHistorical* original_parameters = GetOriginalParameters();
155  polyhedron = new G4PolyhedronPgon( GetOriginalParameters()->Start_angle,
156  GetOriginalParameters()->Opening_angle,
157  GetOriginalParameters()->numSide,
158  GetOriginalParameters()->Num_z_planes,
159  GetOriginalParameters()->Z_values,
160  GetOriginalParameters()->Rmin,
161  GetOriginalParameters()->Rmax);
162  delete original_parameters; // delete local copy
163  return polyhedron;
164  }
165  else
166  {
167  // The following code prepares for:
168  // HepPolyhedron::createPolyhedron(int Nnodes, int Nfaces,
169  // const double xyz[][3],
170  // const int faces_vec[][4])
171  // Here is an extract from the header file HepPolyhedron.h:
189  G4int nNodes;
190  G4int nFaces;
191  typedef G4double double3[3];
192  double3* xyz;
193  typedef G4int int4[4];
194  int4* faces_vec;
195  if (IsOpen())
196  {
197  // Triangulate open ends. Simple ear-chopping algorithm...
198  // I'm not sure how robust this algorithm is (J.Allison).
199  //
200  std::vector<G4bool> chopped(GetNumRZCorner(), false);
201  std::vector<G4int*> triQuads;
202  G4int remaining = GetNumRZCorner();
203  G4int iStarter = 0;
204  while (remaining >= 3) // Loop checking, 13.08.2015, G.Cosmo
205  {
206  // Find unchopped corners...
207  //
208  G4int A = -1, B = -1, C = -1;
209  G4int iStepper = iStarter;
210  do // Loop checking, 13.08.2015, G.Cosmo
211  {
212  if (A < 0) { A = iStepper; }
213  else if (B < 0) { B = iStepper; }
214  else if (C < 0) { C = iStepper; }
215  do // Loop checking, 13.08.2015, G.Cosmo
216  {
217  if (++iStepper >= GetNumRZCorner()) iStepper = 0;
218  }
219  while (chopped[iStepper]);
220  }
221  while (C < 0 && iStepper != iStarter);
222 
223  // Check triangle at B is pointing outward (an "ear").
224  // Sign of z cross product determines...
225 
226  G4double BAr = GetCorner(A).r - GetCorner(B).r;
227  G4double BAz = GetCorner(A).z - GetCorner(B).z;
228  G4double BCr = GetCorner(C).r - GetCorner(B).r;
229  G4double BCz = GetCorner(C).z - GetCorner(B).z;
230  if (BAr * BCz - BAz * BCr < kCarTolerance)
231  {
232  G4int* tq = new G4int[3];
233  tq[0] = A + 1;
234  tq[1] = B + 1;
235  tq[2] = C + 1;
236  triQuads.push_back(tq);
237  chopped[B] = true;
238  --remaining;
239  }
240  else
241  {
242  do // Loop checking, 13.08.2015, G.Cosmo
243  {
244  if (++iStarter >= GetNumRZCorner()) { iStarter = 0; }
245  }
246  while (chopped[iStarter]);
247  }
248  }
249 
250  // Transfer to faces...
251  G4int numSide=GetNumSide();
252  nNodes = (numSide + 1) * GetNumRZCorner();
253  nFaces = numSide * GetNumRZCorner() + 2 * triQuads.size();
254  faces_vec = new int4[nFaces];
255  G4int iface = 0;
256  G4int addition = GetNumRZCorner() * numSide;
257  G4int d = GetNumRZCorner() - 1;
258  for (G4int iEnd = 0; iEnd < 2; ++iEnd)
259  {
260  for (size_t i = 0; i < triQuads.size(); ++i)
261  {
262  // Negative for soft/auxiliary/normally invisible edges...
263  //
264  G4int a, b, c;
265  if (iEnd == 0)
266  {
267  a = triQuads[i][0];
268  b = triQuads[i][1];
269  c = triQuads[i][2];
270  }
271  else
272  {
273  a = triQuads[i][0] + addition;
274  b = triQuads[i][2] + addition;
275  c = triQuads[i][1] + addition;
276  }
277  G4int ab = std::abs(b - a);
278  G4int bc = std::abs(c - b);
279  G4int ca = std::abs(a - c);
280  faces_vec[iface][0] = (ab == 1 || ab == d)? a: -a;
281  faces_vec[iface][1] = (bc == 1 || bc == d)? b: -b;
282  faces_vec[iface][2] = (ca == 1 || ca == d)? c: -c;
283  faces_vec[iface][3] = 0;
284  ++iface;
285  }
286  }
287 
288  // Continue with sides...
289 
290  xyz = new double3[nNodes];
291  const G4double dPhi = (GetEndPhi() - GetStartPhi()) / numSide;
292  G4double phi = GetStartPhi();
293  G4int ixyz = 0;
294  for (G4int iSide = 0; iSide < numSide; ++iSide)
295  {
296  for (G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner)
297  {
298  xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi);
299  xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi);
300  xyz[ixyz][2] = GetCorner(iCorner).z;
301  if (iCorner < GetNumRZCorner() - 1)
302  {
303  faces_vec[iface][0] = ixyz + 1;
304  faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
305  faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2;
306  faces_vec[iface][3] = ixyz + 2;
307  }
308  else
309  {
310  faces_vec[iface][0] = ixyz + 1;
311  faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
312  faces_vec[iface][2] = ixyz + 2;
313  faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2;
314  }
315  ++iface;
316  ++ixyz;
317  }
318  phi += dPhi;
319  }
320 
321  // Last GetCorner...
322 
323  for (G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner)
324  {
325  xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi);
326  xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi);
327  xyz[ixyz][2] = GetCorner(iCorner).z;
328  ++ixyz;
329  }
330  }
331  else // !phiIsOpen - i.e., a complete 360 degrees.
332  {
333  nNodes = GetNumSide() * GetNumRZCorner();
334  nFaces = GetNumSide() * GetNumRZCorner();;
335  xyz = new double3[nNodes];
336  faces_vec = new int4[nFaces];
337  // const G4double dPhi = (endPhi - startPhi) / numSide;
338  const G4double dPhi = twopi / GetNumSide(); // !phiIsOpen endPhi-startPhi = 360 degrees.
339  G4double phi = GetStartPhi();
340  G4int ixyz = 0, iface = 0;
341  for (G4int iSide = 0; iSide < GetNumSide(); ++iSide)
342  {
343  for (G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner)
344  {
345  xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi);
346  xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi);
347  xyz[ixyz][2] = GetCorner(iCorner).z;
348  if (iSide < GetNumSide() - 1)
349  {
350  if (iCorner < GetNumRZCorner() - 1)
351  {
352  faces_vec[iface][0] = ixyz + 1;
353  faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
354  faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2;
355  faces_vec[iface][3] = ixyz + 2;
356  }
357  else
358  {
359  faces_vec[iface][0] = ixyz + 1;
360  faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
361  faces_vec[iface][2] = ixyz + 2;
362  faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2;
363  }
364  }
365  else // Last side joins ends...
366  {
367  if (iCorner < GetNumRZCorner() - 1)
368  {
369  faces_vec[iface][0] = ixyz + 1;
370  faces_vec[iface][1] = ixyz + GetNumRZCorner() - nFaces + 1;
371  faces_vec[iface][2] = ixyz + GetNumRZCorner() - nFaces + 2;
372  faces_vec[iface][3] = ixyz + 2;
373  }
374  else
375  {
376  faces_vec[iface][0] = ixyz + 1;
377  faces_vec[iface][1] = ixyz - nFaces + GetNumRZCorner() + 1;
378  faces_vec[iface][2] = ixyz - nFaces + 2;
379  faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2;
380  }
381  }
382  ++ixyz;
383  ++iface;
384  }
385  phi += dPhi;
386  }
387  }
388  G4Polyhedron* polyhedron = new G4Polyhedron;
389  G4int problem = polyhedron->createPolyhedron(nNodes, nFaces, xyz, faces_vec);
390  delete [] faces_vec;
391  delete [] xyz;
392  if (problem)
393  {
394  std::ostringstream message;
395  message << "Problem creating G4Polyhedron for: " << GetName();
396  G4Exception("G4Polyhedra::CreatePolyhedron()", "GeomSolids1002",
397  JustWarning, message);
398  delete polyhedron;
399  return 0;
400  }
401  else
402  {
403  return polyhedron;
404  }
405  }
406 }
407 
408 #endif // G4GEOM_USE_USOLIDS
G4double z
Definition: TRTMaterials.hh:39
G4String name
Definition: TRTMaterials.hh:40
G4double a
Definition: TRTMaterials.hh:39
double C(double temp)
double B(double temperature)
int G4int
Definition: G4Types.hh:78
double A(double temperature)
static const double twopi
Definition: G4SIunits.hh:75
const G4int n
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
static const G4double ab
double G4double
Definition: G4Types.hh:76