ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4Polycone.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4Polycone.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 // Implementation of G4Polycone, a CSG polycone
27 //
28 // Author: David C. Williams (davidw@scipp.ucsc.edu)
29 // --------------------------------------------------------------------
30 
31 #include "G4Polycone.hh"
32 
33 #if !defined(G4GEOM_USE_UPOLYCONE)
34 
35 #include "G4PolyconeSide.hh"
36 #include "G4PolyPhiFace.hh"
37 
38 #include "G4GeomTools.hh"
39 #include "G4VoxelLimits.hh"
40 #include "G4AffineTransform.hh"
41 #include "G4BoundingEnvelope.hh"
42 
43 #include "Randomize.hh"
44 
45 #include "G4EnclosingCylinder.hh"
46 #include "G4ReduciblePolygon.hh"
47 #include "G4VPVParameterisation.hh"
48 
49 using namespace CLHEP;
50 
51 // Constructor (GEANT3 style parameters)
52 //
54  G4double phiStart,
55  G4double phiTotal,
56  G4int numZPlanes,
57  const G4double zPlane[],
58  const G4double rInner[],
59  const G4double rOuter[] )
60  : G4VCSGfaceted( name )
61 {
62  //
63  // Some historical ugliness
64  //
66 
67  original_parameters->Start_angle = phiStart;
69  original_parameters->Num_z_planes = numZPlanes;
70  original_parameters->Z_values = new G4double[numZPlanes];
71  original_parameters->Rmin = new G4double[numZPlanes];
72  original_parameters->Rmax = new G4double[numZPlanes];
73 
74  for (G4int i=0; i<numZPlanes; ++i)
75  {
76  if(rInner[i]>rOuter[i])
77  {
78  DumpInfo();
79  std::ostringstream message;
80  message << "Cannot create a Polycone with rInner > rOuter for the same Z"
81  << G4endl
82  << " rInner > rOuter for the same Z !" << G4endl
83  << " rMin[" << i << "] = " << rInner[i]
84  << " -- rMax[" << i << "] = " << rOuter[i];
85  G4Exception("G4Polycone::G4Polycone()", "GeomSolids0002",
86  FatalErrorInArgument, message);
87  }
88  if (( i < numZPlanes-1) && ( zPlane[i] == zPlane[i+1] ))
89  {
90  if( (rInner[i] > rOuter[i+1])
91  ||(rInner[i+1] > rOuter[i]) )
92  {
93  DumpInfo();
94  std::ostringstream message;
95  message << "Cannot create a Polycone with no contiguous segments."
96  << G4endl
97  << " Segments are not contiguous !" << G4endl
98  << " rMin[" << i << "] = " << rInner[i]
99  << " -- rMax[" << i+1 << "] = " << rOuter[i+1] << G4endl
100  << " rMin[" << i+1 << "] = " << rInner[i+1]
101  << " -- rMax[" << i << "] = " << rOuter[i];
102  G4Exception("G4Polycone::G4Polycone()", "GeomSolids0002",
103  FatalErrorInArgument, message);
104  }
105  }
106  original_parameters->Z_values[i] = zPlane[i];
107  original_parameters->Rmin[i] = rInner[i];
108  original_parameters->Rmax[i] = rOuter[i];
109  }
110 
111  //
112  // Build RZ polygon using special PCON/PGON GEANT3 constructor
113  //
114  G4ReduciblePolygon *rz =
115  new G4ReduciblePolygon( rInner, rOuter, zPlane, numZPlanes );
116 
117  //
118  // Do the real work
119  //
120  Create( phiStart, phiTotal, rz );
121 
122  delete rz;
123 }
124 
125 // Constructor (generic parameters)
126 //
128  G4double phiStart,
129  G4double phiTotal,
130  G4int numRZ,
131  const G4double r[],
132  const G4double z[] )
133  : G4VCSGfaceted( name )
134 {
135 
136  G4ReduciblePolygon* rz = new G4ReduciblePolygon( r, z, numRZ );
137 
138  Create( phiStart, phiTotal, rz );
139 
140  // Set original_parameters struct for consistency
141  //
142 
143  G4bool convertible = SetOriginalParameters(rz);
144 
145  if(!convertible)
146  {
147  std::ostringstream message;
148  message << "Polycone " << GetName() << "cannot be converted" << G4endl
149  << "to Polycone with (Rmin,Rmaz,Z) parameters!";
150  G4Exception("G4Polycone::G4Polycone()", "GeomSolids0002",
151  FatalException, message, "Use G4GenericPolycone instead!");
152  }
153  else
154  {
155  G4cout << "INFO: Converting polycone " << GetName() << G4endl
156  << "to optimized polycone with (Rmin,Rmaz,Z) parameters !"
157  << G4endl;
158  }
159  delete rz;
160 }
161 
162 // Create
163 //
164 // Generic create routine, called by each constructor after
165 // conversion of arguments
166 //
168  G4double phiTotal,
169  G4ReduciblePolygon* rz )
170 {
171  //
172  // Perform checks of rz values
173  //
174  if (rz->Amin() < 0.0)
175  {
176  std::ostringstream message;
177  message << "Illegal input parameters - " << GetName() << G4endl
178  << " All R values must be >= 0 !";
179  G4Exception("G4Polycone::Create()", "GeomSolids0002",
180  FatalErrorInArgument, message);
181  }
182 
183  G4double rzArea = rz->Area();
184  if (rzArea < -kCarTolerance)
185  {
186  rz->ReverseOrder();
187  }
188  else if (rzArea < kCarTolerance)
189  {
190  std::ostringstream message;
191  message << "Illegal input parameters - " << GetName() << G4endl
192  << " R/Z cross section is zero or near zero: " << rzArea;
193  G4Exception("G4Polycone::Create()", "GeomSolids0002",
194  FatalErrorInArgument, message);
195  }
196 
198  || (!rz->RemoveRedundantVertices( kCarTolerance )) )
199  {
200  std::ostringstream message;
201  message << "Illegal input parameters - " << GetName() << G4endl
202  << " Too few unique R/Z values !";
203  G4Exception("G4Polycone::Create()", "GeomSolids0002",
204  FatalErrorInArgument, message);
205  }
206 
207  if (rz->CrossesItself(1/kInfinity))
208  {
209  std::ostringstream message;
210  message << "Illegal input parameters - " << GetName() << G4endl
211  << " R/Z segments cross !";
212  G4Exception("G4Polycone::Create()", "GeomSolids0002",
213  FatalErrorInArgument, message);
214  }
215 
216  numCorner = rz->NumVertices();
217 
218  //
219  // Phi opening? Account for some possible roundoff, and interpret
220  // nonsense value as representing no phi opening
221  //
222  if (phiTotal <= 0 || phiTotal > twopi-1E-10)
223  {
224  phiIsOpen = false;
225  startPhi = 0.;
226  endPhi = twopi;
227  }
228  else
229  {
230  phiIsOpen = true;
231 
232  //
233  // Convert phi into our convention
234  //
235  startPhi = phiStart;
236  while( startPhi < 0. ) // Loop checking, 13.08.2015, G.Cosmo
237  startPhi += twopi;
238 
239  endPhi = phiStart+phiTotal;
240  while( endPhi < startPhi ) // Loop checking, 13.08.2015, G.Cosmo
241  endPhi += twopi;
242  }
243 
244  //
245  // Allocate corner array.
246  //
248 
249  //
250  // Copy corners
251  //
252  G4ReduciblePolygonIterator iterRZ(rz);
253 
254  G4PolyconeSideRZ *next = corners;
255  iterRZ.Begin();
256  do // Loop checking, 13.08.2015, G.Cosmo
257  {
258  next->r = iterRZ.GetA();
259  next->z = iterRZ.GetB();
260  } while( ++next, iterRZ.Next() );
261 
262  //
263  // Allocate face pointer array
264  //
266  faces = new G4VCSGface*[numFace];
267 
268  //
269  // Construct conical faces
270  //
271  // But! Don't construct a face if both points are at zero radius!
272  //
273  G4PolyconeSideRZ* corner = corners,
274  * prev = corners + numCorner-1,
275  * nextNext;
276  G4VCSGface **face = faces;
277  do // Loop checking, 13.08.2015, G.Cosmo
278  {
279  next = corner+1;
280  if (next >= corners+numCorner) next = corners;
281  nextNext = next+1;
282  if (nextNext >= corners+numCorner) nextNext = corners;
283 
284  if (corner->r < 1/kInfinity && next->r < 1/kInfinity) continue;
285 
286  //
287  // We must decide here if we can dare declare one of our faces
288  // as having a "valid" normal (i.e. allBehind = true). This
289  // is never possible if the face faces "inward" in r.
290  //
291  G4bool allBehind;
292  if (corner->z > next->z)
293  {
294  allBehind = false;
295  }
296  else
297  {
298  //
299  // Otherwise, it is only true if the line passing
300  // through the two points of the segment do not
301  // split the r/z cross section
302  //
303  allBehind = !rz->BisectedBy( corner->r, corner->z,
304  next->r, next->z, kCarTolerance );
305  }
306 
307  *face++ = new G4PolyconeSide( prev, corner, next, nextNext,
308  startPhi, endPhi-startPhi, phiIsOpen, allBehind );
309  } while( prev=corner, corner=next, corner > corners );
310 
311  if (phiIsOpen)
312  {
313  //
314  // Construct phi open edges
315  //
316  *face++ = new G4PolyPhiFace( rz, startPhi, 0, endPhi );
317  *face++ = new G4PolyPhiFace( rz, endPhi, 0, startPhi );
318  }
319 
320  //
321  // We might have dropped a face or two: recalculate numFace
322  //
323  numFace = face-faces;
324 
325  //
326  // Make enclosingCylinder
327  //
329  new G4EnclosingCylinder( rz, phiIsOpen, phiStart, phiTotal );
330 }
331 
332 // Fake default constructor - sets only member data and allocates memory
333 // for usage restricted to object persistency.
334 //
336  : G4VCSGfaceted(a), startPhi(0.), endPhi(0.), numCorner(0)
337 {
338 }
339 
340 
341 //
342 // Destructor
343 //
345 {
346  delete [] corners;
347  delete original_parameters;
348  delete enclosingCylinder;
349 }
350 
351 // Copy constructor
352 //
354  : G4VCSGfaceted( source )
355 {
356  CopyStuff( source );
357 }
358 
359 // Assignment operator
360 //
362 {
363  if (this == &source) return *this;
364 
365  G4VCSGfaceted::operator=( source );
366 
367  delete [] corners;
369 
370  delete enclosingCylinder;
371 
372  CopyStuff( source );
373 
374  return *this;
375 }
376 
377 // CopyStuff
378 //
379 void G4Polycone::CopyStuff( const G4Polycone& source )
380 {
381  //
382  // Simple stuff
383  //
384  startPhi = source.startPhi;
385  endPhi = source.endPhi;
386  phiIsOpen = source.phiIsOpen;
387  numCorner = source.numCorner;
388 
389  //
390  // The corner array
391  //
393 
394  G4PolyconeSideRZ* corn = corners,
395  * sourceCorn = source.corners;
396  do // Loop checking, 13.08.2015, G.Cosmo
397  {
398  *corn = *sourceCorn;
399  } while( ++sourceCorn, ++corn < corners+numCorner );
400 
401  //
402  // Original parameters
403  //
404  if (source.original_parameters)
405  {
408  }
409 
410  //
411  // Enclosing cylinder
412  //
414 
415  fRebuildPolyhedron = false;
416  fpPolyhedron = nullptr;
417 }
418 
419 // Reset
420 //
422 {
423  //
424  // Clear old setup
425  //
427  delete [] corners;
428  delete enclosingCylinder;
429 
430  //
431  // Rebuild polycone
432  //
433  G4ReduciblePolygon *rz =
440  delete rz;
441 
442  return false;
443 }
444 
445 // Inside
446 //
447 // This is an override of G4VCSGfaceted::Inside, created in order
448 // to speed things up by first checking with G4EnclosingCylinder.
449 //
451 {
452  //
453  // Quick test
454  //
455  if (enclosingCylinder->MustBeOutside(p)) return kOutside;
456 
457  //
458  // Long answer
459  //
460  return G4VCSGfaceted::Inside(p);
461 }
462 
463 // DistanceToIn
464 //
465 // This is an override of G4VCSGfaceted::Inside, created in order
466 // to speed things up by first checking with G4EnclosingCylinder.
467 //
469  const G4ThreeVector& v ) const
470 {
471  //
472  // Quick test
473  //
474  if (enclosingCylinder->ShouldMiss(p,v))
475  return kInfinity;
476 
477  //
478  // Long answer
479  //
480  return G4VCSGfaceted::DistanceToIn( p, v );
481 }
482 
483 // DistanceToIn
484 //
486 {
487  return G4VCSGfaceted::DistanceToIn(p);
488 }
489 
490 // Get bounding box
491 //
493  G4ThreeVector& pMax) const
494 {
495  G4double rmin = kInfinity, rmax = -kInfinity;
496  G4double zmin = kInfinity, zmax = -kInfinity;
497 
498  for (G4int i=0; i<GetNumRZCorner(); ++i)
499  {
500  G4PolyconeSideRZ corner = GetCorner(i);
501  if (corner.r < rmin) rmin = corner.r;
502  if (corner.r > rmax) rmax = corner.r;
503  if (corner.z < zmin) zmin = corner.z;
504  if (corner.z > zmax) zmax = corner.z;
505  }
506 
507  if (IsOpen())
508  {
509  G4TwoVector vmin,vmax;
510  G4GeomTools::DiskExtent(rmin,rmax,
513  vmin,vmax);
514  pMin.set(vmin.x(),vmin.y(),zmin);
515  pMax.set(vmax.x(),vmax.y(),zmax);
516  }
517  else
518  {
519  pMin.set(-rmax,-rmax, zmin);
520  pMax.set( rmax, rmax, zmax);
521  }
522 
523  // Check correctness of the bounding box
524  //
525  if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
526  {
527  std::ostringstream message;
528  message << "Bad bounding box (min >= max) for solid: "
529  << GetName() << " !"
530  << "\npMin = " << pMin
531  << "\npMax = " << pMax;
532  G4Exception("G4Polycone::BoundingLimits()", "GeomMgt0001",
533  JustWarning, message);
534  DumpInfo();
535  }
536 }
537 
538 // Calculate extent under transform and specified limit
539 //
541  const G4VoxelLimits& pVoxelLimit,
542  const G4AffineTransform& pTransform,
543  G4double& pMin, G4double& pMax) const
544 {
545  G4ThreeVector bmin, bmax;
546  G4bool exist;
547 
548  // Check bounding box (bbox)
549  //
550  BoundingLimits(bmin,bmax);
551  G4BoundingEnvelope bbox(bmin,bmax);
552 #ifdef G4BBOX_EXTENT
553  return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
554 #endif
555  if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
556  {
557  return exist = (pMin < pMax) ? true : false;
558  }
559 
560  // To find the extent, RZ contour of the polycone is subdivided
561  // in triangles. The extent is calculated as cumulative extent of
562  // all sub-polycones formed by rotation of triangles around Z
563  //
564  G4TwoVectorList contourRZ;
565  G4TwoVectorList triangles;
566  std::vector<G4int> iout;
567  G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
568  G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
569 
570  // get RZ contour, ensure anticlockwise order of corners
571  for (G4int i=0; i<GetNumRZCorner(); ++i)
572  {
573  G4PolyconeSideRZ corner = GetCorner(i);
574  contourRZ.push_back(G4TwoVector(corner.r,corner.z));
575  }
577  G4double area = G4GeomTools::PolygonArea(contourRZ);
578  if (area < 0.) std::reverse(contourRZ.begin(),contourRZ.end());
579 
580  // triangulate RZ countour
581  if (!G4GeomTools::TriangulatePolygon(contourRZ,triangles))
582  {
583  std::ostringstream message;
584  message << "Triangulation of RZ contour has failed for solid: "
585  << GetName() << " !"
586  << "\nExtent has been calculated using boundary box";
587  G4Exception("G4Polycone::CalculateExtent()",
588  "GeomMgt1002", JustWarning, message);
589  return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
590  }
591 
592  // set trigonometric values
593  const G4int NSTEPS = 24; // number of steps for whole circle
594  G4double astep = twopi/NSTEPS; // max angle for one step
595 
596  G4double sphi = GetStartPhi();
597  G4double ephi = GetEndPhi();
598  G4double dphi = IsOpen() ? ephi-sphi : twopi;
599  G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
600  G4double ang = dphi/ksteps;
601 
602  G4double sinHalf = std::sin(0.5*ang);
603  G4double cosHalf = std::cos(0.5*ang);
604  G4double sinStep = 2.*sinHalf*cosHalf;
605  G4double cosStep = 1. - 2.*sinHalf*sinHalf;
606 
607  G4double sinStart = GetSinStartPhi();
608  G4double cosStart = GetCosStartPhi();
609  G4double sinEnd = GetSinEndPhi();
610  G4double cosEnd = GetCosEndPhi();
611 
612  // define vectors and arrays
613  std::vector<const G4ThreeVectorList *> polygons;
614  polygons.resize(ksteps+2);
615  G4ThreeVectorList pols[NSTEPS+2];
616  for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(6);
617  for (G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
618  G4double r0[6],z0[6]; // contour with original edges of triangle
619  G4double r1[6]; // shifted radii of external edges of triangle
620 
621  // main loop along triangles
622  pMin = kInfinity;
623  pMax =-kInfinity;
624  G4int ntria = triangles.size()/3;
625  for (G4int i=0; i<ntria; ++i)
626  {
627  G4int i3 = i*3;
628  for (G4int k=0; k<3; ++k)
629  {
630  G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3;
631  G4int k2 = k*2;
632  // set contour with original edges of triangle
633  r0[k2+0] = triangles[e0].x(); z0[k2+0] = triangles[e0].y();
634  r0[k2+1] = triangles[e1].x(); z0[k2+1] = triangles[e1].y();
635  // set shifted radii
636  r1[k2+0] = r0[k2+0];
637  r1[k2+1] = r0[k2+1];
638  if (z0[k2+1] - z0[k2+0] <= 0) continue;
639  r1[k2+0] /= cosHalf;
640  r1[k2+1] /= cosHalf;
641  }
642 
643  // rotate countour, set sequence of 6-sided polygons
644  G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
645  G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
646  for (G4int j=0; j<6; ++j) pols[0][j].set(r0[j]*cosStart,r0[j]*sinStart,z0[j]);
647  for (G4int k=1; k<ksteps+1; ++k)
648  {
649  for (G4int j=0; j<6; ++j) pols[k][j].set(r1[j]*cosCur,r1[j]*sinCur,z0[j]);
650  G4double sinTmp = sinCur;
651  sinCur = sinCur*cosStep + cosCur*sinStep;
652  cosCur = cosCur*cosStep - sinTmp*sinStep;
653  }
654  for (G4int j=0; j<6; ++j) pols[ksteps+1][j].set(r0[j]*cosEnd,r0[j]*sinEnd,z0[j]);
655 
656  // set sub-envelope and adjust extent
658  G4BoundingEnvelope benv(polygons);
659  if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
660  if (emin < pMin) pMin = emin;
661  if (emax > pMax) pMax = emax;
662  if (eminlim > pMin && emaxlim < pMax) return true; // max possible extent
663  }
664  return (pMin < pMax);
665 }
666 
667 // ComputeDimensions
668 //
670  const G4int n,
671  const G4VPhysicalVolume* pRep )
672 {
673  p->ComputeDimensions(*this,n,pRep);
674 }
675 
676 // GetEntityType
677 //
679 {
680  return G4String("G4Polycone");
681 }
682 
683 // Make a clone of the object
684 //
686 {
687  return new G4Polycone(*this);
688 }
689 
690 //
691 // Stream object contents to an output stream
692 //
693 std::ostream& G4Polycone::StreamInfo( std::ostream& os ) const
694 {
695  G4int oldprc = os.precision(16);
696  os << "-----------------------------------------------------------\n"
697  << " *** Dump for solid - " << GetName() << " ***\n"
698  << " ===================================================\n"
699  << " Solid type: G4Polycone\n"
700  << " Parameters: \n"
701  << " starting phi angle : " << startPhi/degree << " degrees \n"
702  << " ending phi angle : " << endPhi/degree << " degrees \n";
703  G4int i=0;
704 
706  os << " number of Z planes: " << numPlanes << "\n"
707  << " Z values: \n";
708  for (i=0; i<numPlanes; ++i)
709  {
710  os << " Z plane " << i << ": "
711  << original_parameters->Z_values[i] << "\n";
712  }
713  os << " Tangent distances to inner surface (Rmin): \n";
714  for (i=0; i<numPlanes; ++i)
715  {
716  os << " Z plane " << i << ": "
717  << original_parameters->Rmin[i] << "\n";
718  }
719  os << " Tangent distances to outer surface (Rmax): \n";
720  for (i=0; i<numPlanes; ++i)
721  {
722  os << " Z plane " << i << ": "
723  << original_parameters->Rmax[i] << "\n";
724  }
725 
726  os << " number of RZ points: " << numCorner << "\n"
727  << " RZ values (corners): \n";
728  for (i=0; i<numCorner; ++i)
729  {
730  os << " "
731  << corners[i].r << ", " << corners[i].z << "\n";
732  }
733  os << "-----------------------------------------------------------\n";
734  os.precision(oldprc);
735 
736  return os;
737 }
738 
739 // GetPointOnCone
740 //
741 // Auxiliary method for Get Point On Surface
742 //
744  G4double fRmin2, G4double fRmax2,
745  G4double zOne, G4double zTwo,
746  G4double& totArea) const
747 {
748  // declare working variables
749  //
750  G4double Aone, Atwo, Afive, phi, zRand, fDPhi, cosu, sinu;
751  G4double rRand1, rmin, rmax, chose, rone, rtwo, qone, qtwo;
752  G4double fDz=(zTwo-zOne)/2., afDz=std::fabs(fDz);
753  G4ThreeVector point, offset=G4ThreeVector(0.,0.,0.5*(zTwo+zOne));
754  fDPhi = endPhi - startPhi;
755  rone = (fRmax1-fRmax2)/(2.*fDz);
756  rtwo = (fRmin1-fRmin2)/(2.*fDz);
757  if(fRmax1==fRmax2){qone=0.;}
758  else
759  {
760  qone = fDz*(fRmax1+fRmax2)/(fRmax1-fRmax2);
761  }
762  if(fRmin1==fRmin2){qtwo=0.;}
763  else
764  {
765  qtwo = fDz*(fRmin1+fRmin2)/(fRmin1-fRmin2);
766  }
767  Aone = 0.5*fDPhi*(fRmax2 + fRmax1)*(sqr(fRmin1-fRmin2)+sqr(zTwo-zOne));
768  Atwo = 0.5*fDPhi*(fRmin2 + fRmin1)*(sqr(fRmax1-fRmax2)+sqr(zTwo-zOne));
769  Afive = fDz*(fRmax1-fRmin1+fRmax2-fRmin2);
770  totArea = Aone+Atwo+2.*Afive;
771 
772  phi = G4RandFlat::shoot(startPhi,endPhi);
773  cosu = std::cos(phi);
774  sinu = std::sin(phi);
775 
776 
777  if( (startPhi == 0.) && (endPhi == twopi) ) { Afive = 0.; }
778  chose = G4RandFlat::shoot(0.,Aone+Atwo+2.*Afive);
779  if( (chose >= 0.) && (chose < Aone) )
780  {
781  if(fRmax1 != fRmax2)
782  {
783  zRand = G4RandFlat::shoot(-1.*afDz,afDz);
784  point = G4ThreeVector (rone*cosu*(qone-zRand),
785  rone*sinu*(qone-zRand), zRand);
786  }
787  else
788  {
789  point = G4ThreeVector(fRmax1*cosu, fRmax1*sinu,
790  G4RandFlat::shoot(-1.*afDz,afDz));
791 
792  }
793  }
794  else if(chose >= Aone && chose < Aone + Atwo)
795  {
796  if(fRmin1 != fRmin2)
797  {
798  zRand = G4RandFlat::shoot(-1.*afDz,afDz);
799  point = G4ThreeVector (rtwo*cosu*(qtwo-zRand),
800  rtwo*sinu*(qtwo-zRand), zRand);
801 
802  }
803  else
804  {
805  point = G4ThreeVector(fRmin1*cosu, fRmin1*sinu,
806  G4RandFlat::shoot(-1.*afDz,afDz));
807  }
808  }
809  else if( (chose >= Aone + Atwo + Afive) && (chose < Aone + Atwo + 2.*Afive) )
810  {
811  zRand = G4RandFlat::shoot(-1.*afDz,afDz);
812  rmin = fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2);
813  rmax = fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2);
814  rRand1 = std::sqrt(G4RandFlat::shoot()*(sqr(rmax)-sqr(rmin))+sqr(rmin));
815  point = G4ThreeVector (rRand1*std::cos(startPhi),
816  rRand1*std::sin(startPhi), zRand);
817  }
818  else
819  {
820  zRand = G4RandFlat::shoot(-1.*afDz,afDz);
821  rmin = fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2);
822  rmax = fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2);
823  rRand1 = std::sqrt(G4RandFlat::shoot()*(sqr(rmax)-sqr(rmin))+sqr(rmin));
824  point = G4ThreeVector (rRand1*std::cos(endPhi),
825  rRand1*std::sin(endPhi), zRand);
826 
827  }
828 
829  return point+offset;
830 }
831 
832 // GetPointOnTubs
833 //
834 // Auxiliary method for GetPoint On Surface
835 //
837  G4double zOne, G4double zTwo,
838  G4double& totArea) const
839 {
840  G4double xRand,yRand,zRand,phi,cosphi,sinphi,chose,
841  aOne,aTwo,aFou,rRand,fDz,fSPhi,fDPhi;
842  fDz = std::fabs(0.5*(zTwo-zOne));
843  fSPhi = startPhi;
844  fDPhi = endPhi-startPhi;
845 
846  aOne = 2.*fDz*fDPhi*fRMax;
847  aTwo = 2.*fDz*fDPhi*fRMin;
848  aFou = 2.*fDz*(fRMax-fRMin);
849  totArea = aOne+aTwo+2.*aFou;
850  phi = G4RandFlat::shoot(startPhi,endPhi);
851  cosphi = std::cos(phi);
852  sinphi = std::sin(phi);
853  rRand = fRMin + (fRMax-fRMin)*std::sqrt(G4RandFlat::shoot());
854 
855  if(startPhi == 0. && endPhi == twopi)
856  aFou = 0.;
857 
858  chose = G4RandFlat::shoot(0.,aOne+aTwo+2.*aFou);
859  if( (chose >= 0.) && (chose < aOne) )
860  {
861  xRand = fRMax*cosphi;
862  yRand = fRMax*sinphi;
863  zRand = G4RandFlat::shoot(-1.*fDz,fDz);
864  return G4ThreeVector(xRand, yRand, zRand+0.5*(zTwo+zOne));
865  }
866  else if( (chose >= aOne) && (chose < aOne + aTwo) )
867  {
868  xRand = fRMin*cosphi;
869  yRand = fRMin*sinphi;
870  zRand = G4RandFlat::shoot(-1.*fDz,fDz);
871  return G4ThreeVector(xRand, yRand, zRand+0.5*(zTwo+zOne));
872  }
873  else if( (chose >= aOne+aTwo) && (chose <aOne+aTwo+aFou) )
874  {
875  xRand = rRand*std::cos(fSPhi+fDPhi);
876  yRand = rRand*std::sin(fSPhi+fDPhi);
877  zRand = G4RandFlat::shoot(-1.*fDz,fDz);
878  return G4ThreeVector(xRand, yRand, zRand+0.5*(zTwo+zOne));
879  }
880 
881  // else
882 
883  xRand = rRand*std::cos(fSPhi+fDPhi);
884  yRand = rRand*std::sin(fSPhi+fDPhi);
885  zRand = G4RandFlat::shoot(-1.*fDz,fDz);
886  return G4ThreeVector(xRand, yRand, zRand+0.5*(zTwo+zOne));
887 }
888 
889 // GetPointOnRing
890 //
891 // Auxiliary method for GetPoint On Surface
892 //
894  G4double fRMin2,G4double fRMax2,
895  G4double zOne) const
896 {
897  G4double xRand,yRand,phi,cosphi,sinphi,rRand1,rRand2,A1,Atot,rCh;
899  cosphi = std::cos(phi);
900  sinphi = std::sin(phi);
901 
902  if(fRMin1==fRMin2)
903  {
904  rRand1 = fRMin1; A1=0.;
905  }
906  else
907  {
908  rRand1 = G4RandFlat::shoot(fRMin1,fRMin2);
909  A1=std::fabs(fRMin2*fRMin2-fRMin1*fRMin1);
910  }
911  if(fRMax1==fRMax2)
912  {
913  rRand2=fRMax1; Atot=A1;
914  }
915  else
916  {
917  rRand2 = G4RandFlat::shoot(fRMax1,fRMax2);
918  Atot = A1+std::fabs(fRMax2*fRMax2-fRMax1*fRMax1);
919  }
920  rCh = G4RandFlat::shoot(0.,Atot);
921 
922  if(rCh>A1) { rRand1=rRand2; }
923 
924  xRand = rRand1*cosphi;
925  yRand = rRand1*sinphi;
926 
927  return G4ThreeVector(xRand, yRand, zOne);
928 }
929 
930 // GetPointOnCut
931 //
932 // Auxiliary method for Get Point On Surface
933 //
935  G4double fRMin2, G4double fRMax2,
936  G4double zOne, G4double zTwo,
937  G4double& totArea) const
938 { if(zOne==zTwo)
939  {
940  return GetPointOnRing(fRMin1, fRMax1,fRMin2,fRMax2,zOne);
941  }
942  if( (fRMin1 == fRMin2) && (fRMax1 == fRMax2) )
943  {
944  return GetPointOnTubs(fRMin1, fRMax1,zOne,zTwo,totArea);
945  }
946  return GetPointOnCone(fRMin1,fRMax1,fRMin2,fRMax2,zOne,zTwo,totArea);
947 }
948 
949 // GetPointOnSurface
950 //
952 {
953  G4double Area=0.,totArea=0.,Achose1=0.,Achose2=0.,phi,cosphi,sinphi,rRand;
954  G4int i=0;
956 
958  cosphi = std::cos(phi);
959  sinphi = std::sin(phi);
960 
961  rRand = original_parameters->Rmin[0] +
963  * std::sqrt(G4RandFlat::shoot()) );
964 
965  std::vector<G4double> areas; // (numPlanes+1);
966  std::vector<G4ThreeVector> points; // (numPlanes-1);
967 
968  areas.push_back(pi*(sqr(original_parameters->Rmax[0])
969  -sqr(original_parameters->Rmin[0])));
970 
971  for(i=0; i<numPlanes-1; ++i)
972  {
974  * std::sqrt(sqr(original_parameters->Rmin[i]
975  -original_parameters->Rmin[i+1])+
978 
980  * std::sqrt(sqr(original_parameters->Rmax[i]
981  -original_parameters->Rmax[i+1])+
984 
985  Area *= 0.5*(endPhi-startPhi);
986 
987  if(startPhi==0.&& endPhi == twopi)
988  {
989  Area += std::fabs(original_parameters->Z_values[i+1]
994  -original_parameters->Rmin[i+1]);
995  }
996  areas.push_back(Area);
997  totArea += Area;
998  }
999 
1000  areas.push_back(pi*(sqr(original_parameters->Rmax[numPlanes-1])-
1001  sqr(original_parameters->Rmin[numPlanes-1])));
1002 
1003  totArea += (areas[0]+areas[numPlanes]);
1004  G4double chose = G4RandFlat::shoot(0.,totArea);
1005 
1006  if( (chose>=0.) && (chose<areas[0]) )
1007  {
1008  return G4ThreeVector(rRand*cosphi, rRand*sinphi,
1010  }
1011 
1012  for (i=0; i<numPlanes-1; ++i)
1013  {
1014  Achose1 += areas[i];
1015  Achose2 = (Achose1+areas[i+1]);
1016  if(chose>=Achose1 && chose<Achose2)
1017  {
1020  original_parameters->Rmin[i+1],
1021  original_parameters->Rmax[i+1],
1023  original_parameters->Z_values[i+1], Area);
1024  }
1025  }
1026 
1027  rRand = original_parameters->Rmin[numPlanes-1] +
1028  ( (original_parameters->Rmax[numPlanes-1]-original_parameters->Rmin[numPlanes-1])
1029  * std::sqrt(G4RandFlat::shoot()) );
1030 
1031  return G4ThreeVector(rRand*cosphi,rRand*sinphi,
1032  original_parameters->Z_values[numPlanes-1]);
1033 
1034 }
1035 
1036 // CreatePolyhedron
1037 //
1039 {
1040  //
1041  // This has to be fixed in visualization. Fake it for the moment.
1042  //
1043 
1050 }
1051 
1052 // SetOriginalParameters
1053 //
1055 {
1056  G4int numPlanes = numCorner;
1057  G4bool isConvertible = true;
1058  G4double Zmax=rz->Bmax();
1059  rz->StartWithZMin();
1060 
1061  // Prepare vectors for storage
1062  //
1063  std::vector<G4double> Z;
1064  std::vector<G4double> Rmin;
1065  std::vector<G4double> Rmax;
1066 
1067  G4int countPlanes=1;
1068  G4int icurr=0;
1069  G4int icurl=0;
1070 
1071  // first plane Z=Z[0]
1072  //
1073  Z.push_back(corners[0].z);
1074  G4double Zprev=Z[0];
1075  if (Zprev == corners[1].z)
1076  {
1077  Rmin.push_back(corners[0].r);
1078  Rmax.push_back (corners[1].r);icurr=1;
1079  }
1080  else if (Zprev == corners[numPlanes-1].z)
1081  {
1082  Rmin.push_back(corners[numPlanes-1].r);
1083  Rmax.push_back (corners[0].r);
1084  icurl=numPlanes-1;
1085  }
1086  else
1087  {
1088  Rmin.push_back(corners[0].r);
1089  Rmax.push_back (corners[0].r);
1090  }
1091 
1092  // next planes until last
1093  //
1094  G4int inextr=0, inextl=0;
1095  for (G4int i=0; i < numPlanes-2; ++i)
1096  {
1097  inextr=1+icurr;
1098  inextl=(icurl <= 0)? numPlanes-1 : icurl-1;
1099 
1100  if((corners[inextr].z >= Zmax) & (corners[inextl].z >= Zmax)) { break; }
1101 
1102  G4double Zleft = corners[inextl].z;
1103  G4double Zright = corners[inextr].z;
1104  if(Zright > Zleft) // Next plane will be Zleft
1105  {
1106  Z.push_back(Zleft);
1107  countPlanes++;
1108  G4double difZr=corners[inextr].z - corners[icurr].z;
1109  G4double difZl=corners[inextl].z - corners[icurl].z;
1110 
1111  if(std::fabs(difZl) < kCarTolerance)
1112  {
1113  if(std::fabs(difZr) < kCarTolerance)
1114  {
1115  Rmin.push_back(corners[inextl].r);
1116  Rmax.push_back(corners[icurr].r);
1117  }
1118  else
1119  {
1120  Rmin.push_back(corners[inextl].r);
1121  Rmax.push_back(corners[icurr].r + (Zleft-corners[icurr].z)/difZr
1122  *(corners[inextr].r - corners[icurr].r));
1123  }
1124  }
1125  else if (difZl >= kCarTolerance)
1126  {
1127  if(std::fabs(difZr) < kCarTolerance)
1128  {
1129  Rmin.push_back(corners[icurl].r);
1130  Rmax.push_back(corners[icurr].r);
1131  }
1132  else
1133  {
1134  Rmin.push_back(corners[icurl].r);
1135  Rmax.push_back(corners[icurr].r + (Zleft-corners[icurr].z)/difZr
1136  *(corners[inextr].r - corners[icurr].r));
1137  }
1138  }
1139  else
1140  {
1141  isConvertible=false; break;
1142  }
1143  icurl=(icurl == 0)? numPlanes-1 : icurl-1;
1144  }
1145  else if(std::fabs(Zright-Zleft)<kCarTolerance) // Zright=Zleft
1146  {
1147  Z.push_back(Zleft);
1148  ++countPlanes;
1149  ++icurr;
1150 
1151  icurl=(icurl == 0)? numPlanes-1 : icurl-1;
1152 
1153  Rmin.push_back(corners[inextl].r);
1154  Rmax.push_back(corners[inextr].r);
1155  }
1156  else // Zright<Zleft
1157  {
1158  Z.push_back(Zright);
1159  ++countPlanes;
1160 
1161  G4double difZr=corners[inextr].z - corners[icurr].z;
1162  G4double difZl=corners[inextl].z - corners[icurl].z;
1163  if(std::fabs(difZr) < kCarTolerance)
1164  {
1165  if(std::fabs(difZl) < kCarTolerance)
1166  {
1167  Rmax.push_back(corners[inextr].r);
1168  Rmin.push_back(corners[icurr].r);
1169  }
1170  else
1171  {
1172  Rmin.push_back(corners[icurl].r + (Zright-corners[icurl].z)/difZl
1173  *(corners[inextl].r - corners[icurl].r));
1174  Rmax.push_back(corners[inextr].r);
1175  }
1176  ++icurr;
1177  } // plate
1178  else if (difZr >= kCarTolerance)
1179  {
1180  if(std::fabs(difZl) < kCarTolerance)
1181  {
1182  Rmax.push_back(corners[inextr].r);
1183  Rmin.push_back (corners[icurr].r);
1184  }
1185  else
1186  {
1187  Rmax.push_back(corners[inextr].r);
1188  Rmin.push_back (corners[icurl].r+(Zright-corners[icurl].z)/difZl
1189  * (corners[inextl].r - corners[icurl].r));
1190  }
1191  ++icurr;
1192  }
1193  else
1194  {
1195  isConvertible=false; break;
1196  }
1197  }
1198  } // end for loop
1199 
1200  // last plane Z=Zmax
1201  //
1202  Z.push_back(Zmax);
1203  ++countPlanes;
1204  inextr=1+icurr;
1205  inextl=(icurl <= 0)? numPlanes-1 : icurl-1;
1206 
1207  Rmax.push_back(corners[inextr].r);
1208  Rmin.push_back(corners[inextl].r);
1209 
1210  // Set original parameters Rmin,Rmax,Z
1211  //
1212  if(isConvertible)
1213  {
1215  original_parameters->Z_values = new G4double[countPlanes];
1216  original_parameters->Rmin = new G4double[countPlanes];
1217  original_parameters->Rmax = new G4double[countPlanes];
1218 
1219  for(G4int j=0; j < countPlanes; ++j)
1220  {
1221  original_parameters->Z_values[j] = Z[j];
1222  original_parameters->Rmax[j] = Rmax[j];
1223  original_parameters->Rmin[j] = Rmin[j];
1224  }
1227  original_parameters->Num_z_planes = countPlanes;
1228 
1229  }
1230  else // Set parameters(r,z) with Rmin==0 as convention
1231  {
1232 #ifdef G4SPECSDEBUG
1233  std::ostringstream message;
1234  message << "Polycone " << GetName() << G4endl
1235  << "cannot be converted to Polycone with (Rmin,Rmaz,Z) parameters!";
1236  G4Exception("G4Polycone::SetOriginalParameters()", "GeomSolids0002",
1237  JustWarning, message);
1238 #endif
1240  original_parameters->Z_values = new G4double[numPlanes];
1241  original_parameters->Rmin = new G4double[numPlanes];
1242  original_parameters->Rmax = new G4double[numPlanes];
1243 
1244  for(G4int j=0; j < numPlanes; ++j)
1245  {
1247  original_parameters->Rmax[j] = corners[j].r;
1248  original_parameters->Rmin[j] = 0.0;
1249  }
1252  original_parameters->Num_z_planes = numPlanes;
1253  }
1254  return isConvertible;
1255 }
1256 
1257 #endif