Geant4  10.02.p02
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 //
27 // $Id:$
28 //
29 //
30 // Implementation of G4UGenericPolycone wrapper class
31 // --------------------------------------------------------------------
32 
33 #include "G4GenericPolycone.hh"
34 #include "G4UGenericPolycone.hh"
35 
36 #if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
37 
38 #include "G4Polyhedron.hh"
39 
40 using CLHEP::twopi;
41 
43 //
44 // Constructor (generic parameters)
45 //
46 G4UGenericPolycone::G4UGenericPolycone(const G4String& name,
47  G4double phiStart,
48  G4double phiTotal,
49  G4int numRZ,
50  const G4double r[],
51  const G4double z[] )
52  : G4USolid(name, new UGenericPolycone(name, phiStart, phiTotal, numRZ, r, z))
53 {
54 }
55 
56 
58 //
59 // Fake default constructor - sets only member data and allocates memory
60 // for usage restricted to object persistency.
61 //
62 G4UGenericPolycone::G4UGenericPolycone(__void__& a)
63  : G4USolid(a)
64 {
65 }
66 
67 
69 //
70 // Destructor
71 //
72 G4UGenericPolycone::~G4UGenericPolycone()
73 {
74 }
75 
76 
78 //
79 // Copy constructor
80 //
81 G4UGenericPolycone::G4UGenericPolycone(const G4UGenericPolycone &source)
82  : G4USolid(source)
83 {
84 }
85 
86 
88 //
89 // Assignment operator
90 //
91 G4UGenericPolycone&
92 G4UGenericPolycone::operator=(const G4UGenericPolycone &source)
93 {
94  if (this == &source) return *this;
95 
96  G4USolid::operator=( source );
97 
98  return *this;
99 }
100 
101 G4double G4UGenericPolycone::GetStartPhi() const
102 {
103  return GetShape()->GetStartPhi();
104 }
105 G4double G4UGenericPolycone::GetEndPhi() const
106 {
107  return GetShape()->GetEndPhi();
108 }
109 G4bool G4UGenericPolycone::IsOpen() const
110 {
111  return GetShape()->IsOpen();
112 }
113 G4int G4UGenericPolycone::GetNumRZCorner() const
114 {
115  return GetShape()->GetNumRZCorner();
116 }
117 G4PolyconeSideRZ G4UGenericPolycone::GetCorner(G4int index) const
118 {
119  UPolyconeSideRZ pside = GetShape()->GetCorner(index);
120  G4PolyconeSideRZ psiderz = { pside.r, pside.z };
121 
122  return psiderz;
123 }
124 
125 G4Polyhedron* G4UGenericPolycone::CreatePolyhedron() const
126 {
127 
128 
129  // The following code prepares for:
130  // HepPolyhedron::createPolyhedron(int Nnodes, int Nfaces,
131  // const double xyz[][3],
132  // const int faces_vec[][4])
133  // Here is an extract from the header file HepPolyhedron.h:
151  const G4int numSide =
152  G4int(G4Polyhedron::GetNumberOfRotationSteps()
153  * (GetEndPhi() - GetStartPhi()) / twopi) + 1;
154  G4int nNodes;
155  G4int nFaces;
156  typedef G4double double3[3];
157  double3* xyz;
158  typedef G4int int4[4];
159  int4* faces_vec;
160  if (IsOpen())
161  {
162  // Triangulate open ends. Simple ear-chopping algorithm...
163  // I'm not sure how robust this algorithm is (J.Allison).
164  //
165  std::vector<G4bool> chopped(GetNumRZCorner(), false);
166  std::vector<G4int*> triQuads;
167  G4int remaining = GetNumRZCorner();
168  G4int iStarter = 0;
169  while (remaining >= 3) // Loop checking, 13.08.2015, G.Cosmo
170  {
171  // Find unchopped corners...
172  //
173  G4int A = -1, B = -1, C = -1;
174  G4int iStepper = iStarter;
175  do // Loop checking, 13.08.2015, G.Cosmo
176  {
177  if (A < 0) { A = iStepper; }
178  else if (B < 0) { B = iStepper; }
179  else if (C < 0) { C = iStepper; }
180  do // Loop checking, 13.08.2015, G.Cosmo
181  {
182  if (++iStepper >= GetNumRZCorner()) { iStepper = 0; }
183  }
184  while (chopped[iStepper]);
185  }
186  while (C < 0 && iStepper != iStarter);
187 
188  // Check triangle at B is pointing outward (an "ear").
189  // Sign of z cross product determines...
190  //
191  G4double BAr = GetCorner(A).r - GetCorner(B).r;
192  G4double BAz = GetCorner(A).z - GetCorner(B).z;
193  G4double BCr = GetCorner(C).r - GetCorner(B).r;
194  G4double BCz = GetCorner(C).z - GetCorner(B).z;
195  if (BAr * BCz - BAz * BCr < kCarTolerance)
196  {
197  G4int* tq = new G4int[3];
198  tq[0] = A + 1;
199  tq[1] = B + 1;
200  tq[2] = C + 1;
201  triQuads.push_back(tq);
202  chopped[B] = true;
203  --remaining;
204  }
205  else
206  {
207  do // Loop checking, 13.08.2015, G.Cosmo
208  {
209  if (++iStarter >= GetNumRZCorner()) { iStarter = 0; }
210  }
211  while (chopped[iStarter]);
212  }
213  }
214  // Transfer to faces...
215  //
216  nNodes = (numSide + 1) * GetNumRZCorner();
217  nFaces = numSide * GetNumRZCorner() + 2 * triQuads.size();
218  faces_vec = new int4[nFaces];
219  G4int iface = 0;
220  G4int addition = GetNumRZCorner() * numSide;
221  G4int d = GetNumRZCorner() - 1;
222  for (G4int iEnd = 0; iEnd < 2; ++iEnd)
223  {
224  for (size_t i = 0; i < triQuads.size(); ++i)
225  {
226  // Negative for soft/auxiliary/normally invisible edges...
227  //
228  G4int a, b, c;
229  if (iEnd == 0)
230  {
231  a = triQuads[i][0];
232  b = triQuads[i][1];
233  c = triQuads[i][2];
234  }
235  else
236  {
237  a = triQuads[i][0] + addition;
238  b = triQuads[i][2] + addition;
239  c = triQuads[i][1] + addition;
240  }
241  G4int ab = std::abs(b - a);
242  G4int bc = std::abs(c - b);
243  G4int ca = std::abs(a - c);
244  faces_vec[iface][0] = (ab == 1 || ab == d)? a: -a;
245  faces_vec[iface][1] = (bc == 1 || bc == d)? b: -b;
246  faces_vec[iface][2] = (ca == 1 || ca == d)? c: -c;
247  faces_vec[iface][3] = 0;
248  ++iface;
249  }
250  }
251 
252  // Continue with sides...
253 
254  xyz = new double3[nNodes];
255  const G4double dPhi = (GetEndPhi() - GetStartPhi()) / numSide;
256  G4double phi = GetStartPhi();
257  G4int ixyz = 0;
258  for (G4int iSide = 0; iSide < numSide; ++iSide)
259  {
260  for (G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner)
261  {
262  xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi);
263  xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi);
264  xyz[ixyz][2] = GetCorner(iCorner).z;
265  if (iSide == 0) // startPhi
266  {
267  if (iCorner < GetNumRZCorner() - 1)
268  {
269  faces_vec[iface][0] = ixyz + 1;
270  faces_vec[iface][1] = -(ixyz + GetNumRZCorner() + 1);
271  faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2;
272  faces_vec[iface][3] = ixyz + 2;
273  }
274  else
275  {
276  faces_vec[iface][0] = ixyz + 1;
277  faces_vec[iface][1] = -(ixyz + GetNumRZCorner() + 1);
278  faces_vec[iface][2] = ixyz + 2;
279  faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2;
280  }
281  }
282  else if (iSide == numSide - 1) // endPhi
283  {
284  if (iCorner < GetNumRZCorner() - 1)
285  {
286  faces_vec[iface][0] = ixyz + 1;
287  faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
288  faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2;
289  faces_vec[iface][3] = -(ixyz + 2);
290  }
291  else
292  {
293  faces_vec[iface][0] = ixyz + 1;
294  faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
295  faces_vec[iface][2] = ixyz + 2;
296  faces_vec[iface][3] = -(ixyz - GetNumRZCorner() + 2);
297  }
298  }
299  else
300  {
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  }
316  ++iface;
317  ++ixyz;
318  }
319  phi += dPhi;
320  }
321 
322  // Last corners...
323 
324  for (G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner)
325  {
326  xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi);
327  xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi);
328  xyz[ixyz][2] = GetCorner(iCorner).z;
329  ++ixyz;
330  }
331  }
332  else // !phiIsOpen - i.e., a complete 360 degrees.
333  {
334  nNodes = numSide * GetNumRZCorner();
335  nFaces = numSide * GetNumRZCorner();;
336  xyz = new double3[nNodes];
337  faces_vec = new int4[nFaces];
338  const G4double dPhi = (GetEndPhi() - GetStartPhi()) / numSide;
339  G4double phi = GetStartPhi();
340  G4int ixyz = 0, iface = 0;
341  for (G4int iSide = 0; iSide < numSide; ++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 
349  if (iSide < numSide - 1)
350  {
351  if (iCorner < GetNumRZCorner() - 1)
352  {
353  faces_vec[iface][0] = ixyz + 1;
354  faces_vec[iface][1] = -(ixyz + GetNumRZCorner() + 1);
355  faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2;
356  faces_vec[iface][3] = -(ixyz + 2);
357  }
358  else
359  {
360  faces_vec[iface][0] = ixyz + 1;
361  faces_vec[iface][1] = -(ixyz + GetNumRZCorner() + 1);
362  faces_vec[iface][2] = ixyz + 2;
363  faces_vec[iface][3] = -(ixyz - GetNumRZCorner() + 2);
364  }
365  }
366  else // Last side joins ends...
367  {
368  if (iCorner < GetNumRZCorner() - 1)
369  {
370  faces_vec[iface][0] = ixyz + 1;
371  faces_vec[iface][1] = -(ixyz + GetNumRZCorner() - nFaces + 1);
372  faces_vec[iface][2] = ixyz + GetNumRZCorner() - nFaces + 2;
373  faces_vec[iface][3] = -(ixyz + 2);
374  }
375  else
376  {
377  faces_vec[iface][0] = ixyz + 1;
378  faces_vec[iface][1] = -(ixyz - nFaces + GetNumRZCorner() + 1);
379  faces_vec[iface][2] = ixyz - nFaces + 2;
380  faces_vec[iface][3] = -(ixyz - GetNumRZCorner() + 2);
381  }
382  }
383  ++ixyz;
384  ++iface;
385  }
386  phi += dPhi;
387  }
388  }
389  G4Polyhedron* polyhedron = new G4Polyhedron;
390  G4int problem = polyhedron->createPolyhedron(nNodes, nFaces, xyz, faces_vec);
391  delete [] faces_vec;
392  delete [] xyz;
393  if (problem)
394  {
395  std::ostringstream message;
396  message << "Problem creating G4Polyhedron for: " << GetName();
397  G4Exception("G4GenericPolycone::CreatePolyhedron()", "GeomSolids1002",
398  JustWarning, message);
399  delete polyhedron;
400  return 0;
401  }
402  else
403  {
404  return polyhedron;
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)
bool G4bool
Definition: G4Types.hh:79
static const double twopi
Definition: G4SIunits.hh:75
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
static const G4double ab
double G4double
Definition: G4Types.hh:76