Geant4  10.00.p02
UPolycone.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 // UPolycone
12 //
13 // 19.04.13 Marek Gayer
14 // Created from original implementation in Geant4
15 // --------------------------------------------------------------------
16 
17 #include "UUtils.hh"
18 #include <string>
19 #include <cmath>
20 #include <sstream>
21 #include "UPolycone.hh"
22 
23 #include "UEnclosingCylinder.hh"
24 #include "UReduciblePolygon.hh"
25 
26 #include "UTubs.hh"
27 #include "UCons.hh"
28 #include "UTransform3D.hh"
29 
30 using namespace std;
31 
32 UPolycone::UPolycone(const std::string& name,
33  double phiStart,
34  double phiTotal,
35  int numZPlanes,
36  const double zPlane[],
37  const double rInner[],
38  const double rOuter[])
39  : VUSolid(name) //, fNumSides(0)
40 {
41  fCubicVolume = 0;
42  fSurfaceArea = 0;
43  Init(phiStart, phiTotal, numZPlanes, zPlane, rInner, rOuter);
44 
45 }
46 
47 UPolycone::UPolycone(const std::string& name,
48  double phiStart,
49  double phiTotal,
50  int numRZ,
51  const double r[],
52  const double z[])
53  : VUSolid(name)
54 {
55  UReduciblePolygon* rz = new UReduciblePolygon(r, z, numRZ);
56 
57  // Create( phiStart, phiTotal, rz );
58 
59  // Set original_parameters struct for consistency
60  //
61 
62  bool convertible = SetOriginalParameters(rz);
63 
64  if (!convertible)
65  {
66  std::ostringstream message;
67  message << "Polycone " << GetName() << "cannot be converted" << std::endl
68  << "to Polycone with (Rmin,Rmaz,Z) parameters! Use GenericPolycone" ;
69  UUtils::Exception("UPolycone::UPolycone()", "GeomSolids0002",
70  FatalError, 1, message.str().c_str());
71  // JustWarning, message, "Use G4GenericPolycone instead!");
72 
73  }
74  else
75  {
76  std::cout << "INFO: Converting polycone " << GetName() << std::endl
77  << "to optimized polycone with (Rmin,Rmaz,Z) parameters !"
78  << std::endl;
79  double* Z, *R1, *R2;
81  Z = new double[num];
82  R1 = new double[num];
83  R2 = new double[num];
84  for (int i = 0; i < num; i++)
85  {
86  Z[i] = fOriginalParameters->fZValues[i];
87  R1[i] = fOriginalParameters->Rmin[i];
88  R2[i] = fOriginalParameters->Rmax[i];
89  }
90 
91  delete(fOriginalParameters);
92  Init(phiStart, phiTotal, num, Z, R1, R2);
93  delete [] R1;
94  delete [] Z;
95  delete [] R2;
96  }
97 
98  delete rz;
99 }
100 
101 
102 //
103 // Constructor (GEANT3 style parameters)
104 //
105 void UPolycone::Init(double phiStart,
106  double phiTotal,
107  int numZPlanes,
108  const double zPlane[],
109  const double rInner[],
110  const double rOuter[])
111 {
112  //Convertion for angles
113 
114  if (phiTotal <= 0 || phiTotal > UUtils::kTwoPi-1E-10)
115  {
116  phiIsOpen=false;
117  startPhi = 0;
119  }
120  else
121  {
122  //
123  // Convert phi into our convention
124  //
125  phiIsOpen=true;
126  startPhi = phiStart;
127  while( startPhi < 0 ) startPhi += UUtils::kTwoPi;
128 
129  endPhi = phiStart+phiTotal;
130  while( endPhi < startPhi ) endPhi += UUtils::kTwoPi;
131  }
132  // Set Parameters
136  fOriginalParameters->fNumZPlanes = numZPlanes;
137  fOriginalParameters->fZValues.resize(numZPlanes);
138  fOriginalParameters->Rmin.resize(numZPlanes);
139  fOriginalParameters->Rmax.resize(numZPlanes);
140 
141  // Calculate RMax of Polycone in order to determine convexity of sections
142  //
143  double RMaxextent=rOuter[0];
144  for (int j=1; j < numZPlanes; j++)
145  {
146  if (rOuter[j] > RMaxextent) RMaxextent=rOuter[j];
147  if (rInner[j]>rOuter[j])
148  {
149  std::ostringstream message;
150  message << "Cannot create Polycone with rInner > rOuter for the same Z"
151  << std::endl
152  << " rInner > rOuter for the same Z !" << std::endl
153  << " rMin[" << j << "] = " << rInner[j]
154  << " -- rMax[" << j << "] = " << rOuter[j];
155  UUtils::Exception("UPolycone::UPolycone()", "GeomSolids0002",
156  FatalErrorInArguments, 1, message.str().c_str());
157  }
158  }
159  //
160  double prevZ = 0, prevRmax = 0, prevRmin = 0;
161  int dirZ = 1;
162  if (zPlane[1] < zPlane[0])dirZ = -1;
163 // int curSolid = 0;
164 
165  int i;
166  for (i = 0; i < numZPlanes; i++)
167  {
168  if ((i < numZPlanes - 1) && (zPlane[i] == zPlane[i + 1]))
169  {
170  if ((rInner[i] > rOuter[i + 1])
171  || (rInner[i + 1] > rOuter[i]))
172  {
173 
174  std::ostringstream message;
175  message << "Cannot create a Polycone with no contiguous segments."
176  << std::endl
177  << "Segments are not contiguous !" << std::endl
178  << " rMin[" << i << "] = " << rInner[i]
179  << " -- rMax[" << i + 1 << "] = " << rOuter[i + 1] << std::endl
180  << " rMin[" << i + 1 << "] = " << rInner[i + 1]
181  << " -- rMax[" << i << "] = " << rOuter[i];
182  UUtils::Exception("UPolycone::UPolycone()", "GeomSolids0002",
183  FatalErrorInArguments, 1, message.str().c_str());
184  }
185  }
186 
187 
188 
189  double rMin = rInner[i];
190  double rMax = rOuter[i];
191  double z = zPlane[i];
192 
193  if (i > 0)
194  {
195  if (z > prevZ)
196  {
197  if (dirZ < 0)
198  {
199  std::ostringstream message;
200  message << "Cannot create a Polycone with different Z directions.Use GenericPolycone."
201  << std::endl
202  << "ZPlane is changing direction !" << std::endl
203  << " zPlane[0] = " << zPlane[0]
204  << " -- zPlane[1] = " << zPlane[1] << std::endl
205  << " zPlane[" << i - 1 << "] = " << zPlane[i - 1]
206  << " -- rPlane[" << i << "] = " << zPlane[i];
207  UUtils::Exception("UPolycone::UPolycone()", "GeomSolids0002",
208  FatalErrorInArguments, 1, message.str().c_str());
209 
210 
211 
212  }
213  VUSolid* solid;
214  double dz = (z - prevZ) / 2;
215 
216  bool tubular = (rMin == prevRmin && prevRmax == rMax);
217 
218 // if (fNumSides == 0)
219  {
220  if (tubular)
221  {
222  solid = new UTubs("", rMin, rMax, dz, phiStart, phiTotal);
223  }
224  else
225  {
226  solid = new UCons("", prevRmin, prevRmax, rMin, rMax, dz, phiStart, phiTotal);
227  }
228  }
229 // else
230 // {
231 // solid = new UHedra("", prevRmin, prevRmax, rMin, rMax, dz, phiStart, phiTotal, fNumSides);
232 // }
233 
234  fZs.push_back(z);
235 
236  int zi = fZs.size() - 1;
237  double shift = fZs[zi - 1] + 0.5 * (fZs[zi] - fZs[zi - 1]);
238 
239  UPolyconeSection section;
240  section.shift = shift;
241  section.tubular = tubular;
242  section.solid = solid;
243  if(tubular)
244  {
245  if (rMax < RMaxextent) { section.convex = false;}
246  else { section.convex = true;}
247  }
248  else
249  {
250  if ((rMax<prevRmax)||(rMax < RMaxextent)||(prevRmax < RMaxextent))
251  { section.convex = false;}
252  else
253  { section.convex = true;}
254  }
255  fSections.push_back(section);
256  }
257  else
258  {
259  ;// i = i;
260  }
261  }
262  else fZs.push_back(z);
263 
264  fOriginalParameters->fZValues[i] = zPlane[i];
265  fOriginalParameters->Rmin[i] = rInner[i];
266  fOriginalParameters->Rmax[i] = rOuter[i];
267 
268  prevZ = z;
269  prevRmin = rMin;
270  prevRmax = rMax;
271  }
272 
273  fMaxSection = fZs.size() - 2;
274 
275  //
276  // Build RZ polygon using special PCON/PGON GEANT3 constructor
277  //
278  UReduciblePolygon* rz = new UReduciblePolygon(rInner, rOuter, zPlane, numZPlanes);
279 
280  double mxy = rz->Amax();
281 // double alfa = UUtils::kPi / fNumSides;
282 
283  double r = rz->Amax();
284 //
285 // Perform checks of rz values
286 //
287  if (rz->Amin() < 0.0)
288  {
289  std::ostringstream message;
290  message << "Illegal input parameters - " << GetName() << std::endl
291  << " All R values must be >= 0 !";
292  UUtils::Exception("UPolycone::Init()", "GeomSolids0002",
293  FatalErrorInArguments,1, message.str().c_str());
294  }
295 
296 
297  /*
298  if (fNumSides != 0)
299  {
300  // mxy *= std::sqrt(2.0); // this is old and wrong, works only for n = 4
301  // double k = std::tan(alfa) * mxy;
302  double l = mxy / std::cos(alfa);
303  mxy = l;
304  r = l;
305  }
306  */
307 
308  mxy += fgTolerance;
309 
310  fBox.Set(mxy, mxy, (rz->Bmax() - rz->Bmin()) / 2);
311 
312  //
313  // Make enclosingCylinder
314  //
315 
316  enclosingCylinder = new UEnclosingCylinder(r, rz->Bmax(), rz->Bmin(), phiIsOpen, phiStart, phiTotal);
317 
318  delete rz;
319 }
320 
321 
322 /*
323 //
324 // Constructor (generic parameters)
325 //
326 UPolycone3::UPolycone3( const std::string& name,
327  double phiStart,
328  double phiTotal,
329  int numRZ,
330  const double r[],
331  const double z[] )
332  : VUSolid( name )
333 {
334  UReduciblePolygon *rz = new UReduciblePolygon( r, z, numRZ );
335 
336  box.Set(rz->Amax(), rz->Amax(), (rz->Bmax() - rz->Bmin()) /2);
337 
338  // Set fOriginalParameters struct for consistency
339  //
340  SetOriginalParameters();
341 
342  delete rz;
343 }
344 */
345 
346 
347 //
348 // Destructor
349 //
351 {
352  //delete [] corners;
353  //delete fOriginalParameters;
354 }
355 
356 
357 
358 //
359 // Stream object contents to an output stream
360 //
361 std::ostream& UPolycone::StreamInfo(std::ostream& os) const
362 {
363  int oldprc = os.precision(16);
364  os << "-----------------------------------------------------------\n"
365  << " *** Dump for solid - " << GetName() << " ***\n"
366  << " ===================================================\n"
367  << " Solid type: UPolycone3\n"
368  << " Parameters: \n"
369  << " starting phi angle : " << startPhi / (UUtils::kPi / 180.0) << " degrees \n"
370  << " ending phi angle : " << endPhi / (UUtils::kPi / 180.0) << " degrees \n";
371  int i = 0;
372  int numPlanes = fOriginalParameters->fNumZPlanes;
373  os << " number of Z planes: " << numPlanes << "\n"
374  << " Z values: \n";
375  for (i = 0; i < numPlanes; i++)
376  {
377  os << " Z plane " << i << ": "
378  << fOriginalParameters->fZValues[i] << "\n";
379  }
380  os << " Tangent distances to inner surface (Rmin): \n";
381  for (i = 0; i < numPlanes; i++)
382  {
383  os << " Z plane " << i << ": "
384  << fOriginalParameters->Rmin[i] << "\n";
385  }
386  os << " Tangent distances to outer surface (Rmax): \n";
387  for (i = 0; i < numPlanes; i++)
388  {
389  os << " Z plane " << i << ": "
390  << fOriginalParameters->Rmax[i] << "\n";
391  }
392  os << "-----------------------------------------------------------\n";
393  os.precision(oldprc);
394 
395  return os;
396 }
397 
398 
400 {
401  const UPolyconeSection& section = fSections[index];
402  UVector3 ps(p.x, p.y, p.z - section.shift);
403 
404 // if (fNumSides) return section.solid->Inside(ps);
405 
406  double rMinPlus, rMaxPlus; //, rMinMinus, rMaxMinus;
407  double dz;
408  static double halfTolerance = fgTolerance * 0.5;
409 
410  if (section.tubular)
411  {
412  UTubs* tubs = (UTubs*) section.solid;
413  rMinPlus = tubs->GetRMin() + halfTolerance;
414  rMaxPlus = tubs->GetRMax() + halfTolerance;
415  dz = tubs->GetDz();//GetZHalfLength();
416  }
417  else
418  {
419  UCons* cons = (UCons*) section.solid;
420 
421  double rMax1 = cons->GetRmax1();
422  double rMax2 = cons->GetRmax2();
423  double rMin1 = cons->GetRmin1();
424  double rMin2 = cons->GetRmin2();
425 
426  dz = cons->GetDz();
427  double ratio = (ps.z + dz) / (2 * dz);
428  rMinPlus = rMin1 + (rMin2 - rMin1) * ratio + halfTolerance;
429  rMaxPlus = rMax1 + (rMax2 - rMax1) * ratio + halfTolerance;
430  }
431 
432  double rMinMinus = rMinPlus - fgTolerance;
433  double rMaxMinus = rMaxPlus - fgTolerance;
434 
435  double r2 = p.x * p.x + p.y * p.y;
436 
437  if (r2 < rMinMinus * rMinMinus || r2 > rMaxPlus * rMaxPlus) return eOutside;
438  if (r2 < rMinPlus * rMinPlus || r2 > rMaxMinus * rMaxMinus) return eSurface;
439 
440  if (! phiIsOpen )
441  {
442  if (ps.z < -dz + halfTolerance || ps.z > dz - halfTolerance)
443  return eSurface;
444  return eInside;
445  }
446 
447  if (r2 < 1e-10) return eInside;
448 
449  double phi = std::atan2(p.y, p.x); // * UUtils::kTwoPi;
450  if ((phi < 0)||(endPhi > UUtils::kTwoPi)) phi += UUtils::kTwoPi;
451 
452  double ddp = phi - startPhi;
453  if (ddp < 0) ddp += UUtils::kTwoPi;
454  if ((phi <= endPhi + frTolerance)&&(phi>= startPhi-frTolerance))
455  {
456  if (ps.z < -dz + halfTolerance || ps.z > dz - halfTolerance)
457  return eSurface;
458 
459  if (std::fabs(endPhi - phi) < frTolerance)
460  return eSurface;
461  if (std::fabs(startPhi - phi) < frTolerance)
462  return eSurface;
463 
464  return eInside;
465  }
466  return eOutside;
467 }
468 
469 
471 {
472  double shift = fZs[0] + fBox.GetZHalfLength();
473  UVector3 pb(p.x, p.y, p.z - shift);
474  if (fBox.Inside(pb) == eOutside)
475  return eOutside;
476 
477  static const double htolerance = 0.5 * fgTolerance;
478  int index = GetSection(p.z);
479 
480  EnumInside pos = InsideSection(index, p);
481  if (pos == eInside) return eInside;
482 
483  int nextSection;
484  EnumInside nextPos;
485 
486  if (index > 0 && p.z - fZs[index] < htolerance)
487  {
488  nextSection = index - 1;
489  nextPos = InsideSection(nextSection, p);
490  }
491  else if (index < fMaxSection && fZs[index + 1] - p.z < htolerance)
492  {
493  nextSection = index + 1;
494  nextPos = InsideSection(nextSection, p);
495  }
496  else
497  return pos;
498 
499  if (nextPos == eInside) return eInside;
500 
501  if (pos == eSurface && nextPos == eSurface)
502  {
503  UVector3 n, n2;
504  NormalSection(index, p, n);
505  NormalSection(nextSection, p, n2);
506  if ((n + n2).Mag2() < 1000 * frTolerance)
507  return eInside;
508  }
509 
510  return (nextPos == eSurface || pos == eSurface) ? eSurface : eOutside;
511 
512 // return (res == VUSolid::eOutside) ? nextPos : res;
513 }
514 
515 /*
516 if (p.z < fZs.front() - htolerance || p.z > fZs.back() + htolerance) return VUSolid::eOutside;
517 */
518 
520  const UVector3& v, double) const
521 {
522  double shift = fZs[0] + fBox.GetZHalfLength();
523  UVector3 pb(p.x, p.y, p.z - shift);
524 
525  double idistance;
526 
527  idistance = fBox.DistanceToIn(pb, v);
528  // using only box, this appears
529  // to be faster than: idistance = enclosingCylinder->DistanceTo(pb, v);
530  if (idistance >= UUtils::kInfinity) return idistance;
531 
532  // this line can be here or not. not a big difference in performance
533  // TODO: fix enclosingCylinder for polyhedra!!! - the current radius
534  // appears to be too small
535  // if (enclosingCylinder->ShouldMiss(p, v)) return UUtils::kInfinity;
536 
537  // this just takes too much time
538  // idistance = enclosingCylinder->DistanceTo(pb, v);
539  // if (idistance == UUtils::kInfinity) return idistance;
540 
541  pb = p + idistance * v;
542  int index = GetSection(pb.z);
543  pb = p;
544  int increment = (v.z > 0) ? 1 : -1;
545  if (std::fabs(v.z) < fgTolerance) increment = 0;
546 
547  double distance = UUtils::kInfinity;
548  do
549  {
550  const UPolyconeSection& section = fSections[index];
551  pb.z -= section.shift;
552  distance = section.solid->DistanceToIn(pb, v);
553  if (distance < UUtils::kInfinity || !increment)
554  break;
555  index += increment;
556  pb.z += section.shift;
557  }
558  while (index >= 0 && index <= fMaxSection);
559  //if(Inside(p)==eInside)return UUtils::kInfinity;
560  return distance;
561 }
562 
563 double UPolycone::DistanceToOut(const UVector3& p, const UVector3& v,
564  UVector3& n, bool& convex, double /*aPstep*/) const
565 {
566  UVector3 pn(p);
567 
569  {
570  const UPolyconeSection& section = fSections[0];
571  pn.z -= section.shift;
572  return section.solid->DistanceToOut(pn, v, n, convex);
573  }
574 
575  int indexLow = GetSection(p.z-fgTolerance);
576  int indexHigh = GetSection(p.z+fgTolerance);
577  int index = 0;
578 
579  if ( indexLow != indexHigh )
580  { //we are close to Surface, section has to be identified
581  const UPolyconeSection& section = fSections[indexLow];
582  pn.z -= section.shift;
583  if(section.solid->Inside(pn) == eOutside){index=indexHigh;}
584  else{index=indexLow;}
585  pn.z=p.z;
586  }
587  else{index=indexLow;}
588  double totalDistance = 0;
589  int increment = (v.z > 0) ? 1 : -1;
590  bool convexloc=true;
591 
592  UVector3 section_norm;
593  section_norm.Set(0);
594  do
595  {
596  const UPolyconeSection& section = fSections[index];
597 
598  if (totalDistance != 0)
599  {
600  pn = p + (totalDistance /*+ 0 * 1e-8*/) * v; // point must be shifted, so it could eventually get into another solid
601  pn.z -= section.shift;
602  if (section.solid->Inside(pn) == eOutside)
603  {
604  break;
605  }
606  }
607  else pn.z -= section.shift;
608 
609  double distance = section.solid-> DistanceToOut(pn, v, n, convexloc); //section.solid->DistanceToOut(pn, v, n, convexloc);
610  //Section Surface case
611  if(std::fabs(distance) < 0.5*fgTolerance)
612  { int index1 = index;
613  if(( index > 0) && ( index < fMaxSection )){index1 += increment;}
614  else{
615  if((index == 0) && ( increment > 0 ))index1 += increment;
616  if((index == fMaxSection) && (increment<0 ))index1 += increment;
617  }
618  UVector3 pte = p+(totalDistance+distance)*v;
619  const UPolyconeSection& section1 = fSections[index1];
620  pte.z -= section1.shift;
621  if (section1.solid->Inside(pte) == eOutside)
622  {
623  break;
624  }
625  }
626  //Convexity
627  if((index < fMaxSection) && (index > 0 )){
628  if((convexloc) && (section.convex)) {convexloc=true;}
629  else{convexloc=false;}
630  }
631 
632  totalDistance += distance;
633 
634  index += increment;
635 
636  }
637  while (index >= 0 && index <= fMaxSection);
638 
639  convex=convexloc;
640  if(convex){
641  //Check final convexity for dz
642  pn = p + (totalDistance) * v;
643  double halfTolerance = 0.5*fgTolerance;
644  if((index < fMaxSection) && (index > 0 ))
645  {
646  double dz1 = std::fabs(pn.z-fZs[index]);
647  double dz2 = std::fabs(pn.z-fZs[index+1]);
648  if(dz1 < halfTolerance)convex=false;
649  if(dz2 < halfTolerance)convex=false;
650 
651  }else{
652  if(index>=fMaxSection){
653  if(std::fabs(pn.z-fZs[fMaxSection]) < halfTolerance)convex=false;
654  }else{
655  if(index<=0){if(std::fabs(pn.z-fZs[1]) < halfTolerance)convex=false;}
656  }
657  }
658  }
659  return totalDistance;
660 }
661 
662 double UPolycone::SafetyFromInside(const UVector3& p, bool) const
663 {
664  int index = UVoxelizer::BinarySearch(fZs, p.z);
665  if (index < 0 || index > fMaxSection) return 0;
666 
667  double rho=std::sqrt(p.x*p.x+p.y*p.y);
668  double safeR = SafetyFromInsideSection(index,rho, p);
669  double safeDown = p.z-fZs[index];
670  double safeUp = fZs[index+1]-p.z;
671 
672  double minSafety =safeR;
673 
674  if (minSafety == UUtils::kInfinity) return 0;
675  if (minSafety < 1e-6) return 0;
676 
677  for (int i = index + 1; i <= fMaxSection; ++i)
678  {
679  double dz1 = fZs[i] - p.z;
680  double dz2 = fZs[i+1] - p.z;
681  safeR = SafetyFromOutsideSection(i,rho, p);
682  if (safeR < 0.) { safeUp=dz1; break; }
683  if (dz1 < dz2) { safeR = std::sqrt(safeR*safeR+dz1*dz1); }
684  else {safeR = std::sqrt(safeR*safeR+dz1*dz1); }
685  if (safeR < dz1) { safeUp = safeR; break; }
686  if (safeR < dz2) { safeUp = safeR; break; }
687  safeUp=dz2;
688  }
689 
690  if (index > 0)
691  {
692  for (int i = index - 1; i >= 0; --i)
693  {
694  double dz1 = p.z-fZs[i+1];
695  double dz2 = p.z-fZs[i];
696  safeR = SafetyFromOutsideSection(i,rho, p);
697  if (safeR < 0.) { safeDown=dz1; break; }
698  if(dz1 < dz2) { safeR = std::sqrt(safeR*safeR+dz1*dz1); }
699  else { safeR = std::sqrt(safeR*safeR+dz1*dz1); }
700  if (safeR < dz1) { safeDown = safeR; break; }
701  if (safeR < dz2) { safeDown = safeR; break; }
702  safeDown=dz2;
703  }
704  }
705  if (safeUp < minSafety) minSafety=safeUp;
706  if (safeDown < minSafety) minSafety=safeDown;
707 
708  return minSafety;
709 }
710 
711 double UPolycone::SafetyFromOutside(const UVector3& p, bool aAccurate) const
712 {
713  if (!aAccurate)
715 
716  int index = GetSection(p.z);
717  double minSafety = SafetyFromOutsideSection(index, p);
718  if (minSafety < 1e-6) return minSafety;
719 
720  double zbase = fZs[index + 1];
721  for (int i = index + 1; i <= fMaxSection; ++i)
722  {
723  double dz = fZs[i] - zbase;
724  if (dz >= minSafety) break;
725  double safety = SafetyFromOutsideSection(i, p);
726  if (safety < minSafety) minSafety = safety;
727  }
728 
729  zbase = fZs[index - 1];
730  for (int i = index - 1; i >= 0; --i)
731  {
732  double dz = zbase - fZs[i];
733  if (dz >= minSafety) break;
734  double safety = SafetyFromOutsideSection(i, p);
735  if (safety < minSafety) minSafety = safety;
736  }
737  return minSafety;
738 }
739 
740 bool UPolycone::Normal(const UVector3& p, UVector3& n) const
741 {
742  double htolerance = 0.5 * fgTolerance;
743  int index = GetSection(p.z);
744 
745  EnumInside nextPos;
746  int nextSection;
747 
748  if (index > 0 && p.z - fZs[index] < htolerance)
749  {
750  nextSection = index - 1;
751  nextPos = InsideSection(nextSection, p);
752  }
753  else if (index < fMaxSection && fZs[index + 1] - p.z < htolerance)
754  {
755  nextSection = index + 1;
756  nextPos = InsideSection(nextSection, p);
757  }
758  else
759  {
760  const UPolyconeSection& section = fSections[index];
761  UVector3 ps(p.x, p.y, p.z - section.shift);
762  bool res = section.solid->Normal(ps, n);
763 
764  return res;
765 
766  // the code bellow is not used can be deleted
767 
768  nextPos = section.solid->Inside(ps);
769  if (nextPos == eSurface)
770  {
771  return res;
772  }
773  else
774  {
775  //TODO: here should be implementation for case point was not on surface. We would have to look also at other sections. It is not clear if it is possible to solve this problem at all, since we would need precise safety... If it is outside, than it might be OK, but if it is inside..., than I beleive we do not have precise safety
776 
777  // ... or we should at least warn that this case is not supported. actually,
778  // i do not see any algorithm which would obtain right normal of point closest to surface.;
779 
780  return false;
781  }
782  }
783 
784  // even if it says we are on the surface, actually it do not have to be
785 
786 // "TODO special case when point is on the border of two z-sections",
787 // "we should implement this after safety's";
788 
789  EnumInside pos = InsideSection(index, p);
790 
791  if (nextPos == eInside)
792  {
793  //UVector3 n;
794  NormalSection(index, p, n);
795  return false;
796  }
797 
798  if (pos == eSurface && nextPos == eSurface)
799  {
800  //UVector3 n, n2;
801  UVector3 n2;
802  NormalSection(index, p, n);
803  NormalSection(nextSection, p, n2);
804  if ((n + n2).Mag2() < 1000 * frTolerance)
805  {
806  // "we are inside. see TODO above";
807  NormalSection(index, p, n);
808  return false;
809  }
810  }
811 
812  if (nextPos == eSurface || pos == eSurface)
813  {
814  if (pos != eSurface) index = nextSection;
815  bool res = NormalSection(index, p, n);
816  return res;
817  }
818 
819  NormalSection(index, p, n);
820  // "we are outside. see TODO above";
821  return false;
822 }
823 
824 
825 void UPolycone::Extent(UVector3& aMin, UVector3& aMax) const
826 {
827  double r = enclosingCylinder->radius;
828  aMin.Set(-r, -r, fZs.front());
829  aMax.Set(r, r, fZs.back());
830 }
831 
833 {
834  if (fCubicVolume != 0.)
835  {
836  ;
837  }
838  else
839  {
840  for (int i = 0; i < fMaxSection; i++)
841  {
842  UPolyconeSection& section = fSections[i];
843  fCubicVolume += section.solid->Capacity();
844  }
845  }
846  return fCubicVolume;
847 }
848 
850 {
851  if (fSurfaceArea != 0)
852  {
853  ;
854  }
855  else
856  {
857  double Area = 0, totArea = 0;
858  int i = 0;
859  int numPlanes = fOriginalParameters->fNumZPlanes;
860 
861 
862  std::vector<double> areas; // (numPlanes+1);
863  std::vector<UVector3> points; // (numPlanes-1);
864 
865  areas.push_back(UUtils::kPi * (UUtils::sqr(fOriginalParameters->Rmax[0])
867 
868  for (i = 0; i < numPlanes - 1; i++)
869  {
870  Area = (fOriginalParameters->Rmin[i] + fOriginalParameters->Rmin[i + 1])
871  * std::sqrt(UUtils::sqr(fOriginalParameters->Rmin[i]
872  - fOriginalParameters->Rmin[i + 1]) +
875 
876  Area += (fOriginalParameters->Rmax[i] + fOriginalParameters->Rmax[i + 1])
877  * std::sqrt(UUtils::sqr(fOriginalParameters->Rmax[i]
878  - fOriginalParameters->Rmax[i + 1]) +
881 
882  Area *= 0.5 * (endPhi - startPhi);
883 
884  if (startPhi == 0. && endPhi == 2 * UUtils::kPi)
885  {
886  Area += std::fabs(fOriginalParameters->fZValues[i + 1]
889  + fOriginalParameters->Rmax[i + 1]
891  - fOriginalParameters->Rmin[i + 1]);
892  }
893  areas.push_back(Area);
894  totArea += Area;
895  }
896 
897  areas.push_back(UUtils::kPi * (UUtils::sqr(fOriginalParameters->Rmax[numPlanes - 1]) -
898  UUtils::sqr(fOriginalParameters->Rmin[numPlanes - 1])));
899 
900  totArea += (areas[0] + areas[numPlanes]);
901  fSurfaceArea = totArea;
902 
903  }
904 
905  return fSurfaceArea;
906 }
907 
909 //
910 // GetPointOnSurface
911 //
912 // GetPointOnCone
913 //
914 // Auxiliary method for Get Point On Surface
915 //
916 UVector3 UPolycone::GetPointOnCone(double fRmin1, double fRmax1,
917  double fRmin2, double fRmax2,
918  double zOne, double zTwo,
919  double& totArea) const
920 {
921  // declare working variables
922  //
923  double Aone, Atwo, Afive, phi, zRand, fDPhi, cosu, sinu;
924  double rRand1, rmin, rmax, chose, rone, rtwo, qone, qtwo;
925  double fDz = (zTwo - zOne) / 2., afDz = std::fabs(fDz);
926  UVector3 point, offset = UVector3(0., 0., 0.5 * (zTwo + zOne));
927  fDPhi = endPhi - startPhi;
928  rone = (fRmax1 - fRmax2) / (2.*fDz);
929  rtwo = (fRmin1 - fRmin2) / (2.*fDz);
930  if (fRmax1 == fRmax2)
931  {
932  qone = 0.;
933  }
934  else
935  {
936  qone = fDz * (fRmax1 + fRmax2) / (fRmax1 - fRmax2);
937  }
938  if (fRmin1 == fRmin2)
939  {
940  qtwo = 0.;
941  }
942  else
943  {
944  qtwo = fDz * (fRmin1 + fRmin2) / (fRmin1 - fRmin2);
945  }
946  Aone = 0.5 * fDPhi * (fRmax2 + fRmax1) * (UUtils::sqr(fRmin1 - fRmin2) + UUtils::sqr(zTwo - zOne));
947  Atwo = 0.5 * fDPhi * (fRmin2 + fRmin1) * (UUtils::sqr(fRmax1 - fRmax2) + UUtils::sqr(zTwo - zOne));
948  Afive = fDz * (fRmax1 - fRmin1 + fRmax2 - fRmin2);
949  totArea = Aone + Atwo + 2.*Afive;
950 
951  phi = UUtils::Random(startPhi, endPhi);
952  cosu = std::cos(phi);
953  sinu = std::sin(phi);
954 
955 
956  if ((startPhi == 0) && (endPhi == 2 * UUtils::kPi))
957  {
958  Afive = 0;
959  }
960  chose = UUtils::Random(0., Aone + Atwo + 2.*Afive);
961  if ((chose >= 0) && (chose < Aone))
962  {
963  if (fRmax1 != fRmax2)
964  {
965  zRand = UUtils::Random(-1.*afDz, afDz);
966  point = UVector3(rone * cosu * (qone - zRand),
967  rone * sinu * (qone - zRand), zRand);
968  }
969  else
970  {
971  point = UVector3(fRmax1 * cosu, fRmax1 * sinu,
972  UUtils::Random(-1.*afDz, afDz));
973 
974  }
975  }
976  else if (chose >= Aone && chose < Aone + Atwo)
977  {
978  if (fRmin1 != fRmin2)
979  {
980  zRand = UUtils::Random(-1.*afDz, afDz);
981  point = UVector3(rtwo * cosu * (qtwo - zRand),
982  rtwo * sinu * (qtwo - zRand), zRand);
983 
984  }
985  else
986  {
987  point = UVector3(fRmin1 * cosu, fRmin1 * sinu,
988  UUtils::Random(-1.*afDz, afDz));
989  }
990  }
991  else if ((chose >= Aone + Atwo + Afive) && (chose < Aone + Atwo + 2.*Afive))
992  {
993  zRand = UUtils::Random(-1.*afDz, afDz);
994  rmin = fRmin2 - ((zRand - fDz) / (2.*fDz)) * (fRmin1 - fRmin2);
995  rmax = fRmax2 - ((zRand - fDz) / (2.*fDz)) * (fRmax1 - fRmax2);
996  rRand1 = std::sqrt(UUtils::Random() * (UUtils::sqr(rmax) - UUtils::sqr(rmin)) + UUtils::sqr(rmin));
997  point = UVector3(rRand1 * std::cos(startPhi),
998  rRand1 * std::sin(startPhi), zRand);
999  }
1000  else
1001  {
1002  zRand = UUtils::Random(-1.*afDz, afDz);
1003  rmin = fRmin2 - ((zRand - fDz) / (2.*fDz)) * (fRmin1 - fRmin2);
1004  rmax = fRmax2 - ((zRand - fDz) / (2.*fDz)) * (fRmax1 - fRmax2);
1005  rRand1 = std::sqrt(UUtils::Random() * (UUtils::sqr(rmax) - UUtils::sqr(rmin)) + UUtils::sqr(rmin));
1006  point = UVector3(rRand1 * std::cos(endPhi),
1007  rRand1 * std::sin(endPhi), zRand);
1008 
1009  }
1010 
1011  return point + offset;
1012 }
1013 
1014 
1015 //
1016 // GetPointOnTubs
1017 //
1018 // Auxiliary method for GetPoint On Surface
1019 //
1020 UVector3 UPolycone::GetPointOnTubs(double fRMin, double fRMax,
1021  double zOne, double zTwo,
1022  double& totArea) const
1023 {
1024  double xRand, yRand, zRand, phi, cosphi, sinphi, chose,
1025  aOne, aTwo, aFou, rRand, fDz, fSPhi, fDPhi;
1026  fDz = std::fabs(0.5 * (zTwo - zOne));
1027  fSPhi = startPhi;
1028  fDPhi = endPhi - startPhi;
1029 
1030  aOne = 2.*fDz * fDPhi * fRMax;
1031  aTwo = 2.*fDz * fDPhi * fRMin;
1032  aFou = 2.*fDz * (fRMax - fRMin);
1033  totArea = aOne + aTwo + 2.*aFou;
1034  phi = UUtils::Random(startPhi, endPhi);
1035  cosphi = std::cos(phi);
1036  sinphi = std::sin(phi);
1037  rRand = fRMin + (fRMax - fRMin) * std::sqrt(UUtils::Random());
1038 
1039  if (startPhi == 0 && endPhi == 2 * UUtils::kPi)
1040  aFou = 0;
1041 
1042  chose = UUtils::Random(0., aOne + aTwo + 2.*aFou);
1043  if ((chose >= 0) && (chose < aOne))
1044  {
1045  xRand = fRMax * cosphi;
1046  yRand = fRMax * sinphi;
1047  zRand = UUtils::Random(-1.*fDz, fDz);
1048  return UVector3(xRand, yRand, zRand + 0.5 * (zTwo + zOne));
1049  }
1050  else if ((chose >= aOne) && (chose < aOne + aTwo))
1051  {
1052  xRand = fRMin * cosphi;
1053  yRand = fRMin * sinphi;
1054  zRand = UUtils::Random(-1.*fDz, fDz);
1055  return UVector3(xRand, yRand, zRand + 0.5 * (zTwo + zOne));
1056  }
1057  else if ((chose >= aOne + aTwo) && (chose < aOne + aTwo + aFou))
1058  {
1059  xRand = rRand * std::cos(fSPhi + fDPhi);
1060  yRand = rRand * std::sin(fSPhi + fDPhi);
1061  zRand = UUtils::Random(-1.*fDz, fDz);
1062  return UVector3(xRand, yRand, zRand + 0.5 * (zTwo + zOne));
1063  }
1064 
1065  // else
1066 
1067  xRand = rRand * std::cos(fSPhi + fDPhi);
1068  yRand = rRand * std::sin(fSPhi + fDPhi);
1069  zRand = UUtils::Random(-1.*fDz, fDz);
1070  return UVector3(xRand, yRand, zRand + 0.5 * (zTwo + zOne));
1071 }
1072 
1073 
1074 //
1075 // GetPointOnRing
1076 //
1077 // Auxiliary method for GetPoint On Surface
1078 //
1079 UVector3 UPolycone::GetPointOnRing(double fRMin1, double fRMax1,
1080  double fRMin2, double fRMax2,
1081  double zOne) const
1082 {
1083  double xRand, yRand, phi, cosphi, sinphi, rRand1, rRand2, A1, Atot, rCh;
1084  phi = UUtils::Random(startPhi, endPhi);
1085  cosphi = std::cos(phi);
1086  sinphi = std::sin(phi);
1087 
1088  if (fRMin1 == fRMin2)
1089  {
1090  rRand1 = fRMin1;
1091  A1 = 0.;
1092  }
1093  else
1094  {
1095  rRand1 = UUtils::Random(fRMin1, fRMin2);
1096  A1 = std::fabs(fRMin2 * fRMin2 - fRMin1 * fRMin1);
1097  }
1098  if (fRMax1 == fRMax2)
1099  {
1100  rRand2 = fRMax1;
1101  Atot = A1;
1102  }
1103  else
1104  {
1105  rRand2 = UUtils::Random(fRMax1, fRMax2);
1106  Atot = A1 + std::fabs(fRMax2 * fRMax2 - fRMax1 * fRMax1);
1107  }
1108  rCh = UUtils::Random(0., Atot);
1109 
1110  if (rCh > A1)
1111  {
1112  rRand1 = rRand2;
1113  }
1114 
1115  xRand = rRand1 * cosphi;
1116  yRand = rRand1 * sinphi;
1117 
1118  return UVector3(xRand, yRand, zOne);
1119 }
1120 
1121 
1122 //
1123 // GetPointOnCut
1124 //
1125 // Auxiliary method for Get Point On Surface
1126 //
1127 UVector3 UPolycone::GetPointOnCut(double fRMin1, double fRMax1,
1128  double fRMin2, double fRMax2,
1129  double zOne, double zTwo,
1130  double& totArea) const
1131 {
1132  if (zOne == zTwo)
1133  {
1134  return GetPointOnRing(fRMin1, fRMax1, fRMin2, fRMax2, zOne);
1135  }
1136  if ((fRMin1 == fRMin2) && (fRMax1 == fRMax2))
1137  {
1138  return GetPointOnTubs(fRMin1, fRMax1, zOne, zTwo, totArea);
1139  }
1140  return GetPointOnCone(fRMin1, fRMax1, fRMin2, fRMax2, zOne, zTwo, totArea);
1141 }
1142 
1143 
1144 //
1145 // GetPointOnSurface
1146 //
1148 {
1149  double Area = 0, totArea = 0, Achose1 = 0, Achose2 = 0, phi, cosphi, sinphi, rRand;
1150  int i = 0;
1151  int numPlanes = fOriginalParameters->fNumZPlanes;
1152 
1153  phi = UUtils::Random(startPhi, endPhi);
1154  cosphi = std::cos(phi);
1155  sinphi = std::sin(phi);
1156 
1157  rRand = fOriginalParameters->Rmin[0] +
1159  * std::sqrt(UUtils::Random()));
1160 
1161  std::vector<double> areas; // (numPlanes+1);
1162  std::vector<UVector3> points; // (numPlanes-1);
1163 
1164  areas.push_back(UUtils::kPi * (UUtils::sqr(fOriginalParameters->Rmax[0])
1166 
1167  for (i = 0; i < numPlanes - 1; i++)
1168  {
1169  Area = (fOriginalParameters->Rmin[i] + fOriginalParameters->Rmin[i + 1])
1170  * std::sqrt(UUtils::sqr(fOriginalParameters->Rmin[i]
1171  - fOriginalParameters->Rmin[i + 1]) +
1173  - fOriginalParameters->fZValues[i]));
1174 
1175  Area += (fOriginalParameters->Rmax[i] + fOriginalParameters->Rmax[i + 1])
1176  * std::sqrt(UUtils::sqr(fOriginalParameters->Rmax[i]
1177  - fOriginalParameters->Rmax[i + 1]) +
1179  - fOriginalParameters->fZValues[i]));
1180 
1181  Area *= 0.5 * (endPhi - startPhi);
1182 
1183  if (startPhi == 0. && endPhi == 2 * UUtils::kPi)
1184  {
1185  Area += std::fabs(fOriginalParameters->fZValues[i + 1]
1186  - fOriginalParameters->fZValues[i]) *
1188  + fOriginalParameters->Rmax[i + 1]
1190  - fOriginalParameters->Rmin[i + 1]);
1191  }
1192  areas.push_back(Area);
1193  totArea += Area;
1194  }
1195 
1196  areas.push_back(UUtils::kPi * (UUtils::sqr(fOriginalParameters->Rmax[numPlanes - 1]) -
1197  UUtils::sqr(fOriginalParameters->Rmin[numPlanes - 1])));
1198 
1199  totArea += (areas[0] + areas[numPlanes]);
1200  double chose = UUtils::Random(0., totArea);
1201 
1202  if ((chose >= 0.) && (chose < areas[0]))
1203  {
1204  return UVector3(rRand * cosphi, rRand * sinphi,
1206  }
1207 
1208  for (i = 0; i < numPlanes - 1; i++)
1209  {
1210  Achose1 += areas[i];
1211  Achose2 = (Achose1 + areas[i + 1]);
1212  if (chose >= Achose1 && chose < Achose2)
1213  {
1216  fOriginalParameters->Rmin[i + 1],
1217  fOriginalParameters->Rmax[i + 1],
1219  fOriginalParameters->fZValues[i + 1], Area);
1220  }
1221  }
1222 
1223  rRand = fOriginalParameters->Rmin[numPlanes - 1] +
1224  ((fOriginalParameters->Rmax[numPlanes - 1] - fOriginalParameters->Rmin[numPlanes - 1])
1225  * std::sqrt(UUtils::Random()));
1226 
1227  return UVector3(rRand * cosphi, rRand * sinphi,
1228  fOriginalParameters->fZValues[numPlanes - 1]);
1229 
1230 }
1231 
1232 //
1233 // UPolyconeHistorical stuff
1234 //
1235 
1237  : fStartAngle(0.), fOpeningAngle(0.), fNumZPlanes(0),
1238  fZValues(0), Rmin(0), Rmax(0)
1239 {
1240 }
1241 
1243 {
1244 }
1245 
1248 {
1249  fStartAngle = source.fStartAngle;
1250  fOpeningAngle = source.fOpeningAngle;
1251  fNumZPlanes = source.fNumZPlanes;
1252 
1253  fZValues.resize(fNumZPlanes);
1254  Rmin.resize(fNumZPlanes);
1255  Rmax.resize(fNumZPlanes);
1256 
1257  for (int i = 0; i < fNumZPlanes; i++)
1258  {
1259  fZValues[i] = source.fZValues[i];
1260  Rmin[i] = source.Rmin[i];
1261  Rmax[i] = source.Rmax[i];
1262  }
1263 }
1264 
1267 {
1268  if (&right == this) return *this;
1269 
1270  if (&right)
1271  {
1272  fStartAngle = right.fStartAngle;
1273  fOpeningAngle = right.fOpeningAngle;
1274  fNumZPlanes = right.fNumZPlanes;
1275 
1276  fZValues.resize(fNumZPlanes);
1277  Rmin.resize(fNumZPlanes);
1278  Rmax.resize(fNumZPlanes);
1279 
1280  for (int i = 0; i < fNumZPlanes; i++)
1281  {
1282  fZValues[i] = right.fZValues[i];
1283  Rmin[i] = right.Rmin[i];
1284  Rmax[i] = right.Rmax[i];
1285  }
1286  }
1287  return *this;
1288 }
1289 
1291 {
1292  return new UPolycone(*this);
1293 }
1294 //
1295 // Copy constructor
1296 //
1297 UPolycone::UPolycone(const UPolycone& source): VUSolid(source)
1298 {
1299  CopyStuff(source);
1300 }
1301 
1302 
1303 //
1304 // Assignment operator
1305 //
1307 {
1308  if (this == &source) return *this;
1309 
1310  //VUSolid::operator=( source );
1311 
1312  //delete [] corners;
1313 
1314  delete enclosingCylinder;
1315 
1316  CopyStuff(source);
1317 
1318  return *this;
1319 }
1320 //
1321 // CopyStuff
1322 //
1323 void UPolycone::CopyStuff(const UPolycone& source)
1324 {
1325  //
1326  // Simple stuff
1327  //
1328 
1329  startPhi = source.startPhi;
1330  endPhi = source.endPhi;
1331  phiIsOpen = source.phiIsOpen;
1332  fCubicVolume = source.fCubicVolume;
1333  fSurfaceArea = source.fSurfaceArea;
1334  fBox = source.fBox;
1335  //
1336  // The array of planes
1337  //
1339  //
1340  // Enclosing cylinder
1341  //
1343 }
1344 //
1345 // Get Entity Type
1346 //
1348 {
1349  return "Polycone";
1350 }
1351 //
1352 // Set Original Parameters
1353 //
1355 {
1356  int numPlanes = (int)numCorner;
1357  bool isConvertible = true;
1358  double Zmax = rz->Bmax();
1359  rz->StartWithZMin();
1360 
1361  // Prepare vectors for storage
1362  //
1363  std::vector<double> Z;
1364  std::vector<double> Rmin;
1365  std::vector<double> Rmax;
1366 
1367  int countPlanes = 1;
1368  int icurr = 0;
1369  int icurl = 0;
1370 
1371  // first plane Z=Z[0]
1372  //
1373  Z.push_back(corners[0].z);
1374  double Zprev = Z[0];
1375  if (Zprev == corners[1].z)
1376  {
1377  Rmin.push_back(corners[0].r);
1378  Rmax.push_back(corners[1].r);
1379  icurr = 1;
1380  }
1381  else if (Zprev == corners[numPlanes - 1].z)
1382  {
1383  Rmin.push_back(corners[numPlanes - 1].r);
1384  Rmax.push_back(corners[0].r);
1385  icurl = numPlanes - 1;
1386  }
1387  else
1388  {
1389  Rmin.push_back(corners[0].r);
1390  Rmax.push_back(corners[0].r);
1391  }
1392 
1393  // next planes until last
1394  //
1395  int inextr = 0, inextl = 0;
1396  for (int i = 0; i < numPlanes - 2; i++)
1397  {
1398  inextr = 1 + icurr;
1399  inextl = (icurl <= 0) ? numPlanes - 1 : icurl - 1;
1400 
1401  if ((corners[inextr].z >= Zmax) & (corners[inextl].z >= Zmax))
1402  {
1403  break;
1404  }
1405 
1406  double Zleft = corners[inextl].z;
1407  double Zright = corners[inextr].z;
1408  if (Zright > Zleft)
1409  {
1410  Z.push_back(Zleft);
1411  countPlanes++;
1412  double difZr = corners[inextr].z - corners[icurr].z;
1413  double difZl = corners[inextl].z - corners[icurl].z;
1414 
1415  if (std::fabs(difZl) < frTolerance)
1416  {
1417  if (corners[inextl].r >= corners[icurl].r)
1418  {
1419  Rmin.push_back(corners[icurl].r);
1420  Rmax.push_back(Rmax[countPlanes - 2]);
1421  Rmax[countPlanes - 2] = corners[icurl].r;
1422  }
1423  else
1424  {
1425  Rmin.push_back(corners[inextl].r);
1426  Rmax.push_back(corners[icurl].r);
1427  }
1428  }
1429  else if (difZl >= frTolerance)
1430  {
1431  Rmin.push_back(corners[inextl].r);
1432  Rmax.push_back(corners[icurr].r + (Zleft - corners[icurr].z) / difZr
1433  * (corners[inextr].r - corners[icurr].r));
1434  }
1435  else
1436  {
1437  isConvertible = false;
1438  break;
1439  }
1440  icurl = (icurl == 0) ? numPlanes - 1 : icurl - 1;
1441  }
1442  else if (std::fabs(Zright - Zleft) < frTolerance) // Zright=Zleft
1443  {
1444  Z.push_back(Zleft);
1445  countPlanes++;
1446  icurr++;
1447 
1448  icurl = (icurl == 0) ? numPlanes - 1 : icurl - 1;
1449 
1450  Rmin.push_back(corners[inextl].r);
1451  Rmax.push_back(corners[inextr].r);
1452  }
1453  else // Zright<Zleft
1454  {
1455  Z.push_back(Zright);
1456  countPlanes++;
1457 
1458  double difZr = corners[inextr].z - corners[icurr].z;
1459  double difZl = corners[inextl].z - corners[icurl].z;
1460  if (std::fabs(difZr) < frTolerance)
1461  {
1462  if (corners[inextr].r >= corners[icurr].r)
1463  {
1464  Rmin.push_back(corners[icurr].r);
1465  Rmax.push_back(corners[inextr].r);
1466  }
1467  else
1468  {
1469  Rmin.push_back(corners[inextr].r);
1470  Rmax.push_back(corners[icurr].r);
1471  Rmax[countPlanes - 2] = corners[inextr].r;
1472  }
1473  icurr++;
1474  } // plate
1475  else if (difZr >= frTolerance)
1476  {
1477  if (std::fabs(difZl) < frTolerance)
1478  {
1479  Rmax.push_back(corners[inextr].r);
1480  Rmin.push_back(corners[icurr].r);
1481  }
1482  else
1483  {
1484  Rmax.push_back(corners[inextr].r);
1485  Rmin.push_back(corners[icurl].r + (Zright - corners[icurl].z) / difZl
1486  * (corners[inextl].r - corners[icurl].r));
1487  }
1488  icurr++;
1489  }
1490  else
1491  {
1492  isConvertible = false;
1493  break;
1494  }
1495  }
1496  } // end for loop
1497 
1498  // last plane Z=Zmax
1499  //
1500  Z.push_back(Zmax);
1501  countPlanes++;
1502  inextr = 1 + icurr;
1503  inextl = (icurl <= 0) ? numPlanes - 1 : icurl - 1;
1504 
1505  if (corners[inextr].z == corners[inextl].z)
1506  {
1507  Rmax.push_back(corners[inextr].r);
1508  Rmin.push_back(corners[inextl].r);
1509  }
1510  else
1511  {
1512  Rmax.push_back(corners[inextr].r);
1513  Rmin.push_back(corners[inextl].r);
1514  }
1515 
1516  // Set original parameters Rmin,Rmax,Z
1517  //
1518  if (isConvertible)
1519  {
1521  fOriginalParameters->fZValues.resize(numPlanes);
1522  fOriginalParameters->Rmin.resize(numPlanes);
1523  fOriginalParameters->Rmax.resize(numPlanes);
1524 
1525  for (int j = 0; j < countPlanes; j++)
1526  {
1527  fOriginalParameters->fZValues[j] = Z[j];
1528  fOriginalParameters->Rmax[j] = Rmax[j];
1529  fOriginalParameters->Rmin[j] = Rmin[j];
1530  }
1533  fOriginalParameters->fNumZPlanes = countPlanes;
1534 
1535  }
1536  else // Set parameters(r,z) with Rmin==0 as convention
1537  {
1538  std::ostringstream message;
1539  message << "Polycone " << GetName() << std::endl
1540  << "cannot be converted to Polycone with (Rmin,Rmaz,Z) parameters!";
1541  UUtils::Exception("G4Polycone::SetOriginalParameters()", "GeomSolids0002",
1542  Warning, 1, "can not convert");
1543 
1545 
1546  fOriginalParameters->fZValues.resize(numPlanes);
1547  fOriginalParameters->Rmin.resize(numPlanes);
1548  fOriginalParameters->Rmax.resize(numPlanes);
1549 
1550  for (int j = 0; j < numPlanes; j++)
1551  {
1553  fOriginalParameters->Rmax[j] = corners[j].r;
1554  fOriginalParameters->Rmin[j] = 0.0;
1555  }
1558  fOriginalParameters->fNumZPlanes = numPlanes;
1559  }
1560  return isConvertible;
1561 }
1562 //
1563 // Reset
1564 //
1566 {
1567  //
1568  // Clear old setup
1569  //
1570  delete enclosingCylinder;
1571 
1572  fCubicVolume = 0;
1573  fSurfaceArea = 0;
1574  double phiStart=fOriginalParameters->fStartAngle;
1575  double* Z, *R1, *R2;
1576  int num = fOriginalParameters->fNumZPlanes;
1577  Z = new double[num];
1578  R1 = new double[num];
1579  R2 = new double[num];
1580  for (int i = 0; i < num; i++)
1581  {
1582  Z[i] = fOriginalParameters->fZValues[i];
1583  R1[i] = fOriginalParameters->Rmin[i];
1584  R2[i] = fOriginalParameters->Rmax[i];
1585  }
1586 
1587  Init(phiStart, phiStart+ fOriginalParameters->fOpeningAngle, num, Z, R1, R2);
1588  delete [] R1;
1589  delete [] Z;
1590  delete [] R2;
1591 }
Definition: UTubs.hh:47
double SafetyFromOutside(const UVector3 &p) const
double GetRMin() const
double Amin() const
double GetRmin1() const
double DistanceToIn(const UVector3 &p, const UVector3 &v, double aPstep=UUtils::kInfinity) const
Definition: UPolycone.cc:519
std::vector< double > Rmin
Definition: UPolycone.hh:65
static double frTolerance
Definition: VUSolid.hh:31
double GetRmax2() const
std::vector< double > fZValues
Definition: UPolycone.hh:64
UVector3 GetPointOnTubs(double fRMin, double fRMax, double zOne, double zTwo, double &totArea) const
Definition: UPolycone.cc:1020
bool NormalSection(int index, const UVector3 &p, UVector3 &n) const
Definition: UPolycone.hh:319
int GetSection(double z) const
Definition: UPolycone.hh:327
G4double z
Definition: TRTMaterials.hh:39
const std::string & GetName() const
Definition: VUSolid.hh:103
double fCubicVolume
Definition: UPolycone.hh:222
static double fgTolerance
Definition: VUSolid.hh:30
G4String name
Definition: TRTMaterials.hh:40
void CopyStuff(const UPolycone &source)
Definition: UPolycone.cc:1323
std::vector< UPolyconeSection > fSections
Definition: UPolycone.hh:260
UVector3 GetPointOnCut(double fRMin1, double fRMax1, double fRMin2, double fRMax2, double zOne, double zTwo, double &totArea) const
Definition: UPolycone.cc:1127
double SafetyFromOutsideSection(int index, const double rho, const UVector3 &p) const
Definition: UPolycone.hh:287
std::ostream & StreamInfo(std::ostream &os) const
Definition: UPolycone.cc:361
UPolyconeHistorical & operator=(const UPolyconeHistorical &right)
Definition: UPolycone.cc:1266
virtual bool Normal(const UVector3 &aPoint, UVector3 &aNormal) const =0
double GetRMax() const
virtual EnumInside Inside(const UVector3 &aPoint) const =0
double x
Definition: UVector3.hh:136
Definition: UCons.hh:49
int numCorner
Definition: UPolycone.hh:219
VUSolid::EnumInside Inside(const UVector3 &p) const
Definition: UPolycone.cc:470
std::vector< double > Rmax
Definition: UPolycone.hh:66
int fMaxSection
Definition: UPolycone.hh:261
bool Normal(const UVector3 &aPoint, UVector3 &aNormal) const
Definition: UPolycone.cc:740
static int BinarySearch(const std::vector< T > &vec, T value)
Definition: UVoxelizer.hh:57
static const double kInfinity
Definition: UUtils.hh:53
double GetDz() const
bool phiIsOpen
Definition: UPolycone.hh:218
virtual double DistanceToIn(const UVector3 &aPoint, const UVector3 &aDirection, double aPstep=UUtils::kInfinity) const =0
static const double kTwoPi
Definition: UUtils.hh:49
UVector3 GetPointOnSurface() const
Definition: UPolycone.cc:1147
void Init(double phiStart, double phiTotal, int numZPlanes, const double zPlane[], const double rInner[], const double rOuter[])
Definition: UPolycone.cc:105
double endPhi
Definition: UPolycone.hh:217
UPolyconeHistorical * fOriginalParameters
Definition: UPolycone.hh:221
double GetDz() const
UPolyconeSideRZ * corners
Definition: UPolycone.hh:220
UGeometryType GetEntityType() const
Definition: UPolycone.cc:1347
void Reset()
Definition: UPolycone.cc:1565
double Bmin() const
EnumInside
Definition: VUSolid.hh:23
const G4int n
double DistanceToIn(const UVector3 &aPoint, const UVector3 &aDirection, double aPstep=UUtils::kInfinity) const
Definition: UBox.cc:117
double SurfaceArea()
Definition: UPolycone.cc:849
T sqr(const T &x)
Definition: UUtils.hh:137
double Capacity()
Definition: UPolycone.cc:832
double GetZHalfLength() const
Definition: UBox.hh:121
double Amax() const
void SetOriginalParameters()
Definition: UPolycone.hh:226
VUSolid::EnumInside InsideSection(int index, const UVector3 &p) const
Definition: UPolycone.cc:399
void Set(double xx, double yy, double zz)
Definition: UVector3.hh:245
double GetRmax1() const
static const double kPi
Definition: UUtils.hh:48
double SafetyFromOutside(const UVector3 &aPoint, bool aAccurate=false) const
Definition: UPolycone.cc:711
double fSurfaceArea
Definition: UPolycone.hh:223
VUSolid * Clone() const
Definition: UPolycone.cc:1290
double SafetyFromInside(const UVector3 &aPoint, bool aAccurate=false) const
Definition: UPolycone.cc:662
void Set(double dx, double dy, double dz)
Definition: UBox.cc:43
std::string UGeometryType
Definition: UTypes.hh:70
EnumInside Inside(const UVector3 &aPoint) const
Definition: UBox.cc:97
UVector3 GetPointOnRing(double fRMin, double fRMax, double fRMin2, double fRMax2, double zOne) const
Definition: UPolycone.cc:1079
double Bmax() const
UVector3 GetPointOnCone(double fRmin1, double fRmax1, double fRmin2, double fRmax2, double zOne, double zTwo, double &totArea) const
Definition: UPolycone.cc:916
virtual double DistanceToOut(const UVector3 &aPoint, const UVector3 &aDirection, UVector3 &aNormalVector, bool &aConvex, double aPstep=UUtils::kInfinity) const =0
virtual ~UPolycone()
Definition: UPolycone.cc:350
UPolycone & operator=(const UPolycone &source)
Definition: UPolycone.cc:1306
void Exception(const char *originOfException, const char *exceptionCode, ExceptionSeverity severity, int level, const char *description)
Definition: UUtils.cc:122
double z
Definition: UVector3.hh:138
double startPhi
Definition: UPolycone.hh:216
double SafetyFromInsideSection(int index, const double rho, const UVector3 &p) const
Definition: UPolycone.hh:265
std::vector< double > fZs
Definition: UPolycone.hh:259
UEnclosingCylinder * enclosingCylinder
Definition: UPolycone.hh:248
void Extent(UVector3 &aMin, UVector3 &aMax) const
Definition: UPolycone.cc:825
double Random(double min=0.0, double max=1.0)
Definition: UUtils.cc:69
double DistanceToOut(const UVector3 &aPoint, const UVector3 &aDirection, UVector3 &aNormalVector, bool &aConvex, double aPstep=UUtils::kInfinity) const
Definition: UPolycone.cc:563
double y
Definition: UVector3.hh:137
UPolycone(const std::string &name)
Definition: UPolycone.hh:82
static const G4double pos
UBox fBox
Definition: UPolycone.hh:224
virtual double Capacity()=0
Definition: VUSolid.cc:199
double GetRmin2() const