Geant4  10.01.p02
UGenericPolycone.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * This Software is part of the AIDA Unified Solids Library package *
4 // * See: https://aidasoft.web.cern.ch/USolids *
5 // ********************************************************************
6 //
7 // $Id:$
8 //
9 // --------------------------------------------------------------------
10 //
11 // UGenericPolycone
12 //
13 // 19.10.13 Tatiana Nikitina
14 // Created from original implementation in Geant4
15 // --------------------------------------------------------------------
16 
17 #include "UUtils.hh"
18 #include <string>
19 #include <cmath>
20 #include <sstream>
21 
22 #include "UGenericPolycone.hh"
23 #include "UPolyconeSide.hh"
24 #include "UPolyPhiFace.hh"
25 #include "UEnclosingCylinder.hh"
26 #include "UReduciblePolygon.hh"
27 
28 using namespace std;
29 //
30 // Constructor (generic parameters)
31 //
33  double phiStart,
34  double phiTotal,
35  int numRZ,
36  const double r[],
37  const double z[])
38  : UVCSGfaceted(name)
39 {
40  UReduciblePolygon* rz = new UReduciblePolygon(r, z, numRZ);
41 
42  Create(phiStart, phiTotal, rz);
43 
44  delete rz;
45 }
46 
47 
48 //
49 // Create
50 //
51 // Generic create routine, called by each constructor after
52 // conversion of arguments
53 //
54 void UGenericPolycone::Create(double phiStart,
55  double phiTotal,
57 {
58  //
59  // Perform checks of rz values
60  //
61  if (rz->Amin() < 0.0)
62  {
63  std::ostringstream message;
64  message << "Illegal input parameters - " << GetName() << std::endl
65  << " All R values must be >= 0 !";
66  UUtils::Exception("UGenericPolycone::Create()", "GeomSolids0002",
67  UFatalErrorInArguments, 1, message.str().c_str());
68  }
69 
70  double rzArea = rz->Area();
71  if (rzArea < -VUSolid::Tolerance())
72  rz->ReverseOrder();
73 
74  else if (rzArea < -VUSolid::Tolerance())
75  {
76  std::ostringstream message;
77  message << "Illegal input parameters - " << GetName() << std::endl
78  << " R/Z Cross section is zero or near zero: " << rzArea;
79  UUtils::Exception("UGenericPolycone::Create()", "GeomSolids0002",
80  UFatalErrorInArguments, 1, message.str().c_str());
81  }
82 
85  {
86  std::ostringstream message;
87  message << "Illegal input parameters - " << GetName() << std::endl
88  << " Too few unique R/Z values !";
89  UUtils::Exception("UGenericPolycone::Create()", "GeomSolids0002",
90  UFatalErrorInArguments, 1, message.str().c_str());
91  }
92 
93  if (rz->CrossesItself(1 / UUtils::kInfinity))
94  {
95  std::ostringstream message;
96  message << "Illegal input parameters - " << GetName() << std::endl
97  << " R/Z segments Cross !";
98  UUtils::Exception("UGenericPolycone::Create()", "GeomSolids0002",
99  UFatalErrorInArguments, 1, message.str().c_str());
100  }
101 
102  numCorner = rz->NumVertices();
103 
104  //
105  // Phi opening? Account for some possible roundoff, and interpret
106  // nonsense value as representing no phi opening
107  //
108  if (phiTotal <= 0 || phiTotal > 2 * UUtils::kPi - 1E-10)
109  {
110  phiIsOpen = false;
111  startPhi = 0;
112  endPhi = 2 * UUtils::kPi;
113  }
114  else
115  {
116  phiIsOpen = true;
117 
118  //
119  // Convert phi into our convention
120  //
121  startPhi = phiStart;
122  while (startPhi < 0) startPhi += 2 * UUtils::kPi;
123 
124  endPhi = phiStart + phiTotal;
125  while (endPhi < startPhi) endPhi += 2 * UUtils::kPi;
126  }
127 
128  //
129  // Allocate corner array.
130  //
132 
133  //
134  // Copy corners
135  //
136  UReduciblePolygonIterator iterRZ(rz);
137 
138  UPolyconeSideRZ* next = corners;
139  iterRZ.Begin();
140  do
141  {
142  next->r = iterRZ.GetA();
143  next->z = iterRZ.GetB();
144  }
145  while (++next, iterRZ.Next());
146 
147  //
148  // Allocate face pointer array
149  //
151  faces = new UVCSGface*[numFace];
152 
153  //
154  // Construct conical faces
155  //
156  // But! Don't construct a face if both points are at zero radius!
157  //
158  UPolyconeSideRZ* corner = corners,
159  *prev = corners + numCorner - 1,
160  *nextNext;
161  UVCSGface** face = faces;
162  do
163  {
164  next = corner + 1;
165  if (next >= corners + numCorner) next = corners;
166  nextNext = next + 1;
167  if (nextNext >= corners + numCorner) nextNext = corners;
168 
169  if (corner->r < 1 / UUtils::kInfinity && next->r < 1 / UUtils::kInfinity) continue;
170 
171  //
172  // We must decide here if we can dare declare one of our faces
173  // as having a "valid" normal (i.e. allBehind = true). This
174  // is never possible if the face faces "inward" in r.
175  //
176  bool allBehind;
177  if (corner->z > next->z)
178  {
179  allBehind = false;
180  }
181  else
182  {
183  //
184  // Otherwise, it is only true if the line passing
185  // through the two points of the segment do not
186  // split the r/z Cross section
187  //
188  allBehind = !rz->BisectedBy(corner->r, corner->z,
189  next->r, next->z, VUSolid::Tolerance());
190  }
191 
192  *face++ = new UPolyconeSide(prev, corner, next, nextNext,
193  startPhi, endPhi - startPhi, phiIsOpen, allBehind);
194  }
195  while (prev = corner, corner = next, corner > corners);
196 
197  if (phiIsOpen)
198  {
199  //
200  // Construct phi open edges
201  //
202  *face++ = new UPolyPhiFace(rz, startPhi, 0, endPhi);
203  *face++ = new UPolyPhiFace(rz, endPhi, 0, startPhi);
204  }
205 
206  //
207  // We might have dropped a face or two: recalculate numFace
208  //
209  numFace = face - faces;
210 
211  //
212  // Make enclosingCylinder
213  //
215  new UEnclosingCylinder(rz->Amax(), rz->Bmax(), rz->Bmin(), phiIsOpen, phiStart, phiTotal);
216 
218 
219  fNoVoxels = fMaxSection < 2;
220 
221 }
222 
223 
224 //
225 // Fake default constructor - sets only member data and allocates memory
226 // for usage restricted to object persistency.
227 //
228 
229 /*
230 UGenericPolycone::UGenericPolycone( __void__& a )
231  : UVCSGfaceted(a), startPhi(0.), endPhi(0.), phiIsOpen(false),
232  genericPcon(false), numCorner(0), corners(0),
233  fOriginalParameters(0), enclosingCylinder(0)
234 {
235 }
236 */
237 
238 
239 //
240 // Destructor
241 //
243 {
244  delete [] corners;
245  delete enclosingCylinder;
246 }
247 
248 
249 //
250 // Copy constructor
251 //
253  : UVCSGfaceted(source)
254 {
255  CopyStuff(source);
256 }
257 
258 
259 //
260 // Assignment operator
261 //
263 {
264  if (this == &source) return *this;
265 
266  UVCSGfaceted::operator=(source);
267 
268  delete [] corners;
269 
270  delete enclosingCylinder;
271 
272  CopyStuff(source);
273 
274  return *this;
275 }
276 
277 
278 //
279 // CopyStuff
280 //
282 {
283  //
284  // Simple stuff
285  //
286  startPhi = source.startPhi;
287  endPhi = source.endPhi;
288  phiIsOpen = source.phiIsOpen;
289  numCorner = source.numCorner;
290 
291  //
292  // The corner array
293  //
295 
296  UPolyconeSideRZ* corn = corners,
297  *sourceCorn = source.corners;
298  do
299  {
300  *corn = *sourceCorn;
301  }
302  while (++sourceCorn, ++corn < corners + numCorner);
303 
304  //
305  // Enclosing cylinder
306  //
308 }
309 
310 
311 //
312 // Reset
313 //
315 {
316 
317  std::ostringstream message;
318  message << "Solid " << GetName() << " built using generic construct."
319  << std::endl << "Not applicable to the generic construct !";
320  // UException("UGenericPolycone::Reset(,,)", "GeomSolids1001",
321  // JustWarning, message, "Parameters NOT resetted.");
322  return 1;
323 
324 }
325 
326 
327 //
328 // Inside
329 //
330 // This is an override of UVCSGfaceted::Inside, created in order
331 // to speed things up by first checking with UEnclosingCylinder.
332 //
334 {
335  //
336  // Quick test
337  //
338  if (enclosingCylinder->MustBeOutside(p)) return eOutside;
339 
340  //
341  // Long answer
342  //
343  return UVCSGfaceted::Inside(p);
344 }
345 
346 
347 //
348 // DistanceToIn
349 //
350 // This is an override of UVCSGfaceted::Inside, created in order
351 // to speed things up by first checking with UEnclosingCylinder.
352 //
354  const UVector3& v, double aPstep) const
355 {
356  //
357  // Quick test
358  //
359  if (enclosingCylinder->ShouldMiss(p, v))
360  return UUtils::kInfinity;
361 
362  //
363  // Long answer
364  //
365  return UVCSGfaceted::DistanceToIn(p, v, aPstep);
366 }
367 
368 //
369 // GetEntityType
370 //
372 {
373  return std::string("GenericPolycone");
374 }
375 
376 //
377 // Make a clone of the object
378 //
380 {
381  return new UGenericPolycone(*this);
382 }
383 
384 //
385 // Stream object contents to an output stream
386 //
387 std::ostream& UGenericPolycone::StreamInfo(std::ostream& os) const
388 {
389  int oldprc = os.precision(16);
390  os << "-----------------------------------------------------------\n"
391  << " *** Dump for solid - " << GetName() << " ***\n"
392  << " ===================================================\n"
393  << " Solid type: UGenericPolycone\n"
394  << " Parameters: \n"
395  << " starting phi angle : " << startPhi / (UUtils::kPi / 180.0) << " degrees \n"
396  << " ending phi angle : " << endPhi / (UUtils::kPi / 180.0) << " degrees \n";
397  int i = 0;
398 
399  os << " number of RZ points: " << numCorner << "\n"
400  << " RZ values (corners): \n";
401  for (i = 0; i < numCorner; i++)
402  {
403  os << " "
404  << corners[i].r << ", " << corners[i].z << "\n";
405  }
406 
407  os << "-----------------------------------------------------------\n";
408  os.precision(oldprc);
409 
410  return os;
411 }
412 
413 //
414 // GetPointOnSurface
415 //
417 {
418  return GetPointOnSurfaceGeneric();
419 
420 }
421 
423 {
424  enclosingCylinder->Extent(aMin, aMax);
425 }
426 
std::ostream & StreamInfo(std::ostream &os) const
double Amin() const
UPolyconeSideRZ * corners
UVector3 GetPointOnSurface() const
bool RemoveRedundantVertices(double tolerance)
UGeometryType GetEntityType() const
bool MustBeOutside(const UVector3 &p) const
G4double z
Definition: TRTMaterials.hh:39
const std::string & GetName() const
Definition: VUSolid.hh:103
VUSolid::EnumInside Inside(const UVector3 &p) const
G4String name
Definition: TRTMaterials.hh:40
UGenericPolycone(const std::string &name, double phiStart, double phiTotal, int numZPlanes, const double zPlane[], const double rInner[], const double rOuter[])
void Create(double phiStart, double phiTotal, UReduciblePolygon *rz)
bool RemoveDuplicateVertices(double tolerance)
bool BisectedBy(double a1, double b1, double a2, double b2, double tolerance)
static double Tolerance()
Definition: VUSolid.hh:127
UEnclosingCylinder * enclosingCylinder
void Extent(UVector3 &aMin, UVector3 &aMax) const
static const double kInfinity
Definition: UUtils.hh:54
void InitVoxels(UReduciblePolygon &z, double radius)
UVCSGfaceted & operator=(const UVCSGfaceted &source)
Definition: UVCSGfaceted.cc:63
int NumVertices() const
virtual ~UGenericPolycone()
void CopyStuff(const UGenericPolycone &source)
double Bmin() const
EnumInside
Definition: VUSolid.hh:23
bool ShouldMiss(const UVector3 &p, const UVector3 &v) const
bool CrossesItself(double tolerance)
UGenericPolycone & operator=(const UGenericPolycone &source)
void Exception(const char *originOfException, const char *exceptionCode, UExceptionSeverity severity, int level, const char *description)
Definition: UUtils.cc:122
double Amax() const
static const double kPi
Definition: UUtils.hh:49
std::string UGeometryType
Definition: UTypes.hh:39
VUSolid * Clone() const
double Bmax() const
UVCSGface ** faces
void Extent(UVector3 &aMin, UVector3 &aMax) const
UVector3 GetPointOnSurfaceGeneric() const
virtual double DistanceToIn(const UVector3 &p, const UVector3 &v, double aPstep=UUtils::kInfinity) const
virtual VUSolid::EnumInside Inside(const UVector3 &p) const
double DistanceToIn(const UVector3 &p, const UVector3 &v, double aPstep=UUtils::kInfinity) const