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