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