Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4GenericPolycone.cc
Go to the documentation of this file.
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// G4GenericPolycone implementation
27//
28// Authors: T.Nikitina, G.Cosmo - CERN
29// --------------------------------------------------------------------
30
31#include "G4GenericPolycone.hh"
32
33#if !defined(G4GEOM_USE_UGENERICPOLYCONE)
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 "G4QuickRand.hh"
44
45#include "G4Polyhedron.hh"
47#include "G4ReduciblePolygon.hh"
49
50namespace
51{
52 G4Mutex surface_elementsMutex = G4MUTEX_INITIALIZER;
53 G4Mutex genpolyMutex = G4MUTEX_INITIALIZER;
54}
55
56using namespace CLHEP;
57
58// Constructor (generic parameters)
59//
61 G4double phiStart,
62 G4double phiTotal,
63 G4int numRZ,
64 const G4double r[],
65 const G4double z[] )
66 : G4VCSGfaceted( name )
67{
68
69 auto rz = new G4ReduciblePolygon( r, z, numRZ );
70
71 Create( phiStart, phiTotal, rz );
72
73 // Set original_parameters struct for consistency
74 //
75 //SetOriginalParameters(rz);
76
77 delete rz;
78}
79
80// Create
81//
82// Generic create routine, called by constructor after conversion of arguments
83//
84void G4GenericPolycone::Create( G4double phiStart,
85 G4double phiTotal,
87{
88 //
89 // Perform checks of rz values
90 //
91 if (rz->Amin() < 0.0)
92 {
93 std::ostringstream message;
94 message << "Illegal input parameters - " << GetName() << G4endl
95 << " All R values must be >= 0 !";
96 G4Exception("G4GenericPolycone::Create()", "GeomSolids0002",
97 FatalErrorInArgument, message);
98 }
99
100 G4double rzArea = rz->Area();
101 if (rzArea < -kCarTolerance)
102 {
103 rz->ReverseOrder();
104 }
105 else if (rzArea < kCarTolerance)
106 {
107 std::ostringstream message;
108 message << "Illegal input parameters - " << GetName() << G4endl
109 << " R/Z cross section is zero or near zero: " << rzArea;
110 G4Exception("G4GenericPolycone::Create()", "GeomSolids0002",
111 FatalErrorInArgument, message);
112 }
113
116 {
117 std::ostringstream message;
118 message << "Illegal input parameters - " << GetName() << G4endl
119 << " Too few unique R/Z values !";
120 G4Exception("G4GenericPolycone::Create()", "GeomSolids0002",
121 FatalErrorInArgument, message);
122 }
123
124 if (rz->CrossesItself(1/kInfinity))
125 {
126 std::ostringstream message;
127 message << "Illegal input parameters - " << GetName() << G4endl
128 << " R/Z segments cross !";
129 G4Exception("G4GenericPolycone::Create()", "GeomSolids0002",
130 FatalErrorInArgument, message);
131 }
132
133 numCorner = rz->NumVertices();
134
135 //
136 // Phi opening? Account for some possible roundoff, and interpret
137 // nonsense value as representing no phi opening
138 //
139 if (phiTotal <= 0 || phiTotal > twopi-1E-10)
140 {
141 phiIsOpen = false;
142 startPhi = 0;
143 endPhi = twopi;
144 }
145 else
146 {
147 phiIsOpen = true;
148
149 //
150 // Convert phi into our convention
151 //
152 startPhi = phiStart;
153 while( startPhi < 0 ) // Loop checking, 13.08.2015, G.Cosmo
154 {
155 startPhi += twopi;
156 }
157
158 endPhi = phiStart+phiTotal;
159 while( endPhi < startPhi ) // Loop checking, 13.08.2015, G.Cosmo
160 {
161 endPhi += twopi;
162 }
163 }
164
165 //
166 // Allocate corner array.
167 //
168 corners = new G4PolyconeSideRZ[numCorner];
169
170 //
171 // Copy corners
172 //
173 G4ReduciblePolygonIterator iterRZ(rz);
174
175 G4PolyconeSideRZ* next = corners;
176 iterRZ.Begin();
177 do // Loop checking, 13.08.2015, G.Cosmo
178 {
179 next->r = iterRZ.GetA();
180 next->z = iterRZ.GetB();
181 } while( ++next, iterRZ.Next() );
182
183 //
184 // Allocate face pointer array
185 //
186 numFace = phiIsOpen ? numCorner+2 : numCorner;
187 faces = new G4VCSGface*[numFace];
188
189 //
190 // Construct conical faces
191 //
192 // But! Don't construct a face if both points are at zero radius!
193 //
194 G4PolyconeSideRZ *corner = corners,
195 *prev = corners + numCorner-1,
196 *nextNext;
197 G4VCSGface** face = faces;
198 do // Loop checking, 13.08.2015, G.Cosmo
199 {
200 next = corner+1;
201 if (next >= corners+numCorner) { next = corners; }
202 nextNext = next+1;
203 if (nextNext >= corners+numCorner) { nextNext = corners; }
204
205 if (corner->r < 1/kInfinity && next->r < 1/kInfinity) { continue; }
206
207 //
208 // We must decide here if we can dare declare one of our faces
209 // as having a "valid" normal (i.e. allBehind = true). This
210 // is never possible if the face faces "inward" in r.
211 //
212 G4bool allBehind;
213 if (corner->z > next->z)
214 {
215 allBehind = false;
216 }
217 else
218 {
219 //
220 // Otherwise, it is only true if the line passing
221 // through the two points of the segment do not
222 // split the r/z cross section
223 //
224 allBehind = !rz->BisectedBy( corner->r, corner->z,
225 next->r, next->z, kCarTolerance );
226 }
227
228 *face++ = new G4PolyconeSide( prev, corner, next, nextNext,
229 startPhi, endPhi-startPhi, phiIsOpen, allBehind );
230 } while( prev=corner, corner=next, corner > corners );
231
232 if (phiIsOpen)
233 {
234 //
235 // Construct phi open edges
236 //
237 *face++ = new G4PolyPhiFace( rz, startPhi, 0, endPhi );
238 *face++ = new G4PolyPhiFace( rz, endPhi, 0, startPhi );
239 }
240
241 //
242 // We might have dropped a face or two: recalculate numFace
243 //
244 numFace = (G4int)(face-faces);
245
246 //
247 // Make enclosingCylinder
248 //
249 enclosingCylinder =
250 new G4EnclosingCylinder( rz, phiIsOpen, phiStart, phiTotal );
251}
252
253// Fake default constructor - sets only member data and allocates memory
254// for usage restricted to object persistency.
255//
257 : G4VCSGfaceted(a), startPhi(0.), endPhi(0.), numCorner(0)
258{
259}
260
261// Destructor
262//
264{
265 delete [] corners;
266 delete enclosingCylinder;
267 delete fElements;
268 delete fpPolyhedron;
269 corners = nullptr;
270 enclosingCylinder = nullptr;
271 fElements = nullptr;
272 fpPolyhedron = nullptr;
273}
274
275// Copy constructor
276//
278 : G4VCSGfaceted( source )
279{
280 CopyStuff( source );
281}
282
283// Assignment operator
284//
287{
288 if (this == &source) { return *this; }
289
290 G4VCSGfaceted::operator=( source );
291
292 delete [] corners;
293 // if (original_parameters) delete original_parameters;
294
295 delete enclosingCylinder;
296
297 CopyStuff( source );
298
299 return *this;
300}
301
302// CopyStuff
303//
304void G4GenericPolycone::CopyStuff( const G4GenericPolycone& source )
305{
306 //
307 // Simple stuff
308 //
309 startPhi = source.startPhi;
310 endPhi = source.endPhi;
311 phiIsOpen = source.phiIsOpen;
312 numCorner = source.numCorner;
313
314 //
315 // The corner array
316 //
317 corners = new G4PolyconeSideRZ[numCorner];
318
319 G4PolyconeSideRZ *corn = corners,
320 *sourceCorn = source.corners;
321 do // Loop checking, 13.08.2015, G.Cosmo
322 {
323 *corn = *sourceCorn;
324 } while( ++sourceCorn, ++corn < corners+numCorner );
325
326 //
327 // Enclosing cylinder
328 //
329 enclosingCylinder = new G4EnclosingCylinder( *source.enclosingCylinder );
330
331 //
332 // Surface elements
333 //
334 delete fElements;
335 fElements = nullptr;
336
337 // Polyhedron
338 //
339 fRebuildPolyhedron = false;
340 delete fpPolyhedron;
341 fpPolyhedron = nullptr;
342}
343
344// Reset
345//
347{
348 std::ostringstream message;
349 message << "Solid " << GetName() << " built using generic construct."
350 << G4endl << "Not applicable to the generic construct !";
351 G4Exception("G4GenericPolycone::Reset()", "GeomSolids1001",
352 JustWarning, message, "Parameters NOT resetted.");
353 return true;
354}
355
356// Inside
357//
358// This is an override of G4VCSGfaceted::Inside, created in order
359// to speed things up by first checking with G4EnclosingCylinder.
360//
362{
363 //
364 // Quick test
365 //
366 if (enclosingCylinder->MustBeOutside(p)) { return kOutside;
367}
368
369 //
370 // Long answer
371 //
372 return G4VCSGfaceted::Inside(p);
373}
374
375// DistanceToIn
376//
377// This is an override of G4VCSGfaceted::Inside, created in order
378// to speed things up by first checking with G4EnclosingCylinder.
379//
381 const G4ThreeVector& v ) const
382{
383 //
384 // Quick test
385 //
386 if (enclosingCylinder->ShouldMiss(p,v)) { return kInfinity; }
387
388 //
389 // Long answer
390 //
391 return G4VCSGfaceted::DistanceToIn( p, v );
392}
393
394// DistanceToIn
395//
400
401// BoundingLimits
402//
403// Get bounding box
404//
405void
407 G4ThreeVector& pMax) const
408{
409 G4double rmin = kInfinity, rmax = -kInfinity;
410 G4double zmin = kInfinity, zmax = -kInfinity;
411
412 for (G4int i=0; i<GetNumRZCorner(); ++i)
413 {
414 G4PolyconeSideRZ corner = GetCorner(i);
415 if (corner.r < rmin) { rmin = corner.r; }
416 if (corner.r > rmax) { rmax = corner.r; }
417 if (corner.z < zmin) { zmin = corner.z; }
418 if (corner.z > zmax) { zmax = corner.z; }
419 }
420
421 if (IsOpen())
422 {
423 G4TwoVector vmin,vmax;
424 G4GeomTools::DiskExtent(rmin,rmax,
427 vmin,vmax);
428 pMin.set(vmin.x(),vmin.y(),zmin);
429 pMax.set(vmax.x(),vmax.y(),zmax);
430 }
431 else
432 {
433 pMin.set(-rmax,-rmax, zmin);
434 pMax.set( rmax, rmax, zmax);
435 }
436
437 // Check correctness of the bounding box
438 //
439 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
440 {
441 std::ostringstream message;
442 message << "Bad bounding box (min >= max) for solid: "
443 << GetName() << " !"
444 << "\npMin = " << pMin
445 << "\npMax = " << pMax;
446 G4Exception("GenericG4Polycone::BoundingLimits()", "GeomMgt0001",
447 JustWarning, message);
448 DumpInfo();
449 }
450}
451
452// CalculateExtent
453//
454// Calculate extent under transform and specified limit
455//
456G4bool
458 const G4VoxelLimits& pVoxelLimit,
459 const G4AffineTransform& pTransform,
460 G4double& pMin, G4double& pMax) const
461{
462 G4ThreeVector bmin, bmax;
463 G4bool exist;
464
465 // Check bounding box (bbox)
466 //
467 BoundingLimits(bmin,bmax);
468 G4BoundingEnvelope bbox(bmin,bmax);
469#ifdef G4BBOX_EXTENT
470 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
471#endif
472 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
473 {
474 return exist = pMin < pMax;
475 }
476
477 // To find the extent, RZ contour of the polycone is subdivided
478 // in triangles. The extent is calculated as cumulative extent of
479 // all sub-polycones formed by rotation of triangles around Z
480 //
481 G4TwoVectorList contourRZ;
482 G4TwoVectorList triangles;
483 G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
484 G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
485
486 // get RZ contour, ensure anticlockwise order of corners
487 for (G4int i=0; i<GetNumRZCorner(); ++i)
488 {
489 G4PolyconeSideRZ corner = GetCorner(i);
490 contourRZ.emplace_back(corner.r,corner.z);
491 }
492 G4double area = G4GeomTools::PolygonArea(contourRZ);
493 if (area < 0.) { std::reverse(contourRZ.begin(),contourRZ.end()); }
494
495 // triangulate RZ countour
496 if (!G4GeomTools::TriangulatePolygon(contourRZ,triangles))
497 {
498 std::ostringstream message;
499 message << "Triangulation of RZ contour has failed for solid: "
500 << GetName() << " !"
501 << "\nExtent has been calculated using boundary box";
502 G4Exception("G4GenericPolycone::CalculateExtent()",
503 "GeomMgt1002", JustWarning, message);
504 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
505 }
506
507 // set trigonometric values
508 const G4int NSTEPS = 24; // number of steps for whole circle
509 G4double astep = twopi/NSTEPS; // max angle for one step
510
511 G4double sphi = GetStartPhi();
512 G4double ephi = GetEndPhi();
513 G4double dphi = IsOpen() ? ephi-sphi : twopi;
514 G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
515 G4double ang = dphi/ksteps;
516
517 G4double sinHalf = std::sin(0.5*ang);
518 G4double cosHalf = std::cos(0.5*ang);
519 G4double sinStep = 2.*sinHalf*cosHalf;
520 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
521
522 G4double sinStart = GetSinStartPhi();
523 G4double cosStart = GetCosStartPhi();
524 G4double sinEnd = GetSinEndPhi();
525 G4double cosEnd = GetCosEndPhi();
526
527 // define vectors and arrays
528 std::vector<const G4ThreeVectorList *> polygons;
529 polygons.resize(ksteps+2);
530 G4ThreeVectorList pols[NSTEPS+2];
531 for (G4int k=0; k<ksteps+2; ++k)
532 {
533 pols[k].resize(6);
534 }
535 for (G4int k=0; k<ksteps+2; ++k)
536 {
537 polygons[k] = &pols[k];
538 }
539 G4double r0[6],z0[6]; // contour with original edges of triangle
540 G4double r1[6]; // shifted radii of external edges of triangle
541
542 // main loop along triangles
543 pMin = kInfinity;
544 pMax =-kInfinity;
545 G4int ntria = (G4int)triangles.size()/3;
546 for (G4int i=0; i<ntria; ++i)
547 {
548 G4int i3 = i*3;
549 for (G4int k=0; k<3; ++k)
550 {
551 G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3;
552 G4int k2 = k*2;
553 // set contour with original edges of triangle
554 r0[k2+0] = triangles[e0].x(); z0[k2+0] = triangles[e0].y();
555 r0[k2+1] = triangles[e1].x(); z0[k2+1] = triangles[e1].y();
556 // set shifted radii
557 r1[k2+0] = r0[k2+0];
558 r1[k2+1] = r0[k2+1];
559 if (z0[k2+1] - z0[k2+0] <= 0) { continue; }
560 r1[k2+0] /= cosHalf;
561 r1[k2+1] /= cosHalf;
562 }
563
564 // rotate countour, set sequence of 6-sided polygons
565 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
566 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
567 for (G4int j=0; j<6; ++j)
568 {
569 pols[0][j].set(r0[j]*cosStart,r0[j]*sinStart,z0[j]);
570 }
571 for (G4int k=1; k<ksteps+1; ++k)
572 {
573 for (G4int j=0; j<6; ++j)
574 {
575 pols[k][j].set(r1[j]*cosCur,r1[j]*sinCur,z0[j]);
576 }
577 G4double sinTmp = sinCur;
578 sinCur = sinCur*cosStep + cosCur*sinStep;
579 cosCur = cosCur*cosStep - sinTmp*sinStep;
580 }
581 for (G4int j=0; j<6; ++j)
582 {
583 pols[ksteps+1][j].set(r0[j]*cosEnd,r0[j]*sinEnd,z0[j]);
584 }
585
586 // set sub-envelope and adjust extent
587 G4double emin,emax;
588 G4BoundingEnvelope benv(polygons);
589 if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax))
590 {
591 continue;
592 }
593 if (emin < pMin) { pMin = emin; }
594 if (emax > pMax) { pMax = emax; }
595 if (eminlim > pMin && emaxlim < pMax) { return true; } // max possible extent
596 }
597 return (pMin < pMax);
598}
599
600// GetEntityType
601//
603{
604 return {"G4GenericPolycone"};
605}
606
607// Clone
608//
609// Make a clone of the object
610//
612{
613 return new G4GenericPolycone(*this);
614}
615
616// StreamInfo
617//
618// Stream object contents to an output stream
619//
620std::ostream& G4GenericPolycone::StreamInfo( std::ostream& os ) const
621{
622 G4long oldprc = os.precision(16);
623 os << "-----------------------------------------------------------\n"
624 << " *** Dump for solid - " << GetName() << " ***\n"
625 << " ===================================================\n"
626 << " Solid type: G4GenericPolycone\n"
627 << " Parameters: \n"
628 << " starting phi angle : " << startPhi/degree << " degrees \n"
629 << " ending phi angle : " << endPhi/degree << " degrees \n";
630 G4int i=0;
631
632 os << " number of RZ points: " << numCorner << "\n"
633 << " RZ values (corners): \n";
634 for (i=0; i<numCorner; ++i)
635 {
636 os << " "
637 << corners[i].r << ", " << corners[i].z << "\n";
638 }
639 os << "-----------------------------------------------------------\n";
640 os.precision(oldprc);
641
642 return os;
643}
644
645//////////////////////////////////////////////////////////////////////////
646//
647// Return volume
648
650{
651 if (fCubicVolume == 0)
652 {
653 G4AutoLock l(&genpolyMutex);
654 G4double total = 0.;
655 G4int nrz = GetNumRZCorner();
656 G4PolyconeSideRZ a = GetCorner(nrz - 1);
657 for (G4int i=0; i<nrz; ++i)
658 {
660 total += (b.r*b.r + b.r*a.r + a.r*a.r)*(b.z - a.z);
661 a = b;
662 }
663 fCubicVolume = std::abs(total)*(GetEndPhi() - GetStartPhi())/6.;
664 l.unlock();
665 }
666 return fCubicVolume;
667}
668
669//////////////////////////////////////////////////////////////////////////
670//
671// Return surface area
672
674{
675 if (fSurfaceArea == 0)
676 {
677 G4AutoLock l(&genpolyMutex);
678 // phi cut area
679 G4int nrz = GetNumRZCorner();
680 G4double scut = 0.;
681 if (IsOpen())
682 {
683 G4PolyconeSideRZ a = GetCorner(nrz - 1);
684 for (G4int i=0; i<nrz; ++i)
685 {
687 scut += a.r*b.z - a.z*b.r;
688 a = b;
689 }
690 scut = std::abs(scut);
691 }
692 // lateral surface area
693 G4double slat = 0;
694 G4PolyconeSideRZ a = GetCorner(nrz - 1);
695 for (G4int i=0; i<nrz; ++i)
696 {
698 G4double h = std::sqrt((b.r - a.r)*(b.r - a.r) + (b.z - a.z)*(b.z - a.z));
699 slat += (b.r + a.r)*h;
700 a = b;
701 }
702 slat *= (GetEndPhi() - GetStartPhi())/2.;
703 fSurfaceArea = scut + slat;
704 l.unlock();
705 }
706 return fSurfaceArea;
707}
708
709//////////////////////////////////////////////////////////////////////////
710//
711// Set vector of surface elements, auxiliary method for sampling
712// random points on surface
713
714void G4GenericPolycone::SetSurfaceElements() const
715{
716 fElements = new std::vector<G4GenericPolycone::surface_element>;
717 G4double sarea = 0.;
718 G4int nrz = GetNumRZCorner();
719
720 // set lateral surface elements
721 G4double dphi = GetEndPhi() - GetStartPhi();
722 G4int ia = nrz - 1;
723 for (G4int ib=0; ib<nrz; ++ib)
724 {
727 G4GenericPolycone::surface_element selem;
728 selem.i0 = ia;
729 selem.i1 = ib;
730 selem.i2 = -1;
731 ia = ib;
732 if (a.r == 0. && b.r == 0.) { continue; }
733 G4double h = std::sqrt((b.r - a.r)*(b.r - a.r) + (b.z - a.z)*(b.z - a.z));
734 sarea += 0.5*dphi*(b.r + a.r)*h;
735 selem.area = sarea;
736 fElements->push_back(selem);
737 }
738
739 // set elements for phi cuts
740 if (IsOpen())
741 {
742 G4TwoVectorList contourRZ;
743 std::vector<G4int> triangles;
744 for (G4int i=0; i<nrz; ++i)
745 {
746 G4PolyconeSideRZ corner = GetCorner(i);
747 contourRZ.emplace_back(corner.r, corner.z);
748 }
749 G4GeomTools::TriangulatePolygon(contourRZ, triangles);
750 auto ntria = (G4int)triangles.size();
751 for (G4int i=0; i<ntria; i+=3)
752 {
753 G4GenericPolycone::surface_element selem;
754 selem.i0 = triangles[i];
755 selem.i1 = triangles[i+1];
756 selem.i2 = triangles[i+2];
757 G4PolyconeSideRZ a = GetCorner(selem.i0);
758 G4PolyconeSideRZ b = GetCorner(selem.i1);
759 G4PolyconeSideRZ c = GetCorner(selem.i2);
760 G4double stria =
761 std::abs(G4GeomTools::TriangleArea(a.r, a.z, b.r, b.z, c.r, c.z));
762 sarea += stria;
763 selem.area = sarea;
764 fElements->push_back(selem); // start phi
765 sarea += stria;
766 selem.area = sarea;
767 selem.i0 += nrz;
768 fElements->push_back(selem); // end phi
769 }
770 }
771}
772
773//////////////////////////////////////////////////////////////////////////
774//
775// Generate random point on surface
776
778{
779 // Set surface elements
780 if (fElements == nullptr)
781 {
782 G4AutoLock l(&surface_elementsMutex);
783 SetSurfaceElements();
784 l.unlock();
785 }
786
787 // Select surface element
788 G4GenericPolycone::surface_element selem;
789 selem = fElements->back();
790 G4double select = selem.area*G4QuickRand();
791 auto it = std::lower_bound(fElements->begin(), fElements->end(), select,
792 [](const G4GenericPolycone::surface_element& x, G4double val)
793 -> G4bool { return x.area < val; });
794
795 // Generate random point
796 G4double r = 0, z = 0, phi = 0;
797 G4double u = G4QuickRand();
798 G4double v = G4QuickRand();
799 G4int i0 = (*it).i0;
800 G4int i1 = (*it).i1;
801 G4int i2 = (*it).i2;
802 if (i2 < 0) // lateral surface
803 {
806 if (p1.r < p0.r)
807 {
808 p0 = GetCorner(i1);
809 p1 = GetCorner(i0);
810 }
811 if (p1.r - p0.r < kCarTolerance) // cylindrical surface
812 {
813 r = (p1.r - p0.r)*u + p0.r;
814 z = (p1.z - p0.z)*u + p0.z;
815 }
816 else // conical surface
817 {
818 r = std::sqrt(p1.r*p1.r*u + p0.r*p0.r*(1. - u));
819 z = p0.z + (p1.z - p0.z)*(r - p0.r)/(p1.r - p0.r);
820 }
821 phi = (GetEndPhi() - GetStartPhi())*v + GetStartPhi();
822 }
823 else // phi cut
824 {
825 G4int nrz = GetNumRZCorner();
826 phi = (i0 < nrz) ? GetStartPhi() : GetEndPhi();
827 if (i0 >= nrz) { i0 -= nrz; }
831 if (u + v > 1.) { u = 1. - u; v = 1. - v; }
832 r = (p1.r - p0.r)*u + (p2.r - p0.r)*v + p0.r;
833 z = (p1.z - p0.z)*u + (p2.z - p0.z)*v + p0.z;
834 }
835 return {r*std::cos(phi), r*std::sin(phi), z};
836}
837
838//////////////////////////////////////////////////////////////////////////
839//
840// CreatePolyhedron
841
843{
844 std::vector<G4TwoVector> rz(numCorner);
845 for (G4int i = 0; i < numCorner; ++i)
846 {
847 rz[i].set(corners[i].r, corners[i].z);
848 }
849 return new G4PolyhedronPcon(startPhi, endPhi - startPhi, rz);
850}
851
852#endif
G4TemplateAutoLock< G4Mutex > G4AutoLock
std::vector< G4ThreeVector > G4ThreeVectorList
@ JustWarning
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::vector< G4TwoVector > G4TwoVectorList
G4double G4QuickRand(uint32_t seed=0)
#define G4MUTEX_INITIALIZER
std::mutex G4Mutex
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
double G4double
Definition G4Types.hh:83
long G4long
Definition G4Types.hh:87
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
G4String G4GeometryType
Definition G4VSolid.hh:70
#define G4endl
Definition G4ios.hh:67
double x() const
double y() const
double z() const
double x() const
double y() const
void set(double x, double y, double z)
G4AffineTransform is a class for geometric affine transformations. It supports efficient arbitrary ro...
G4BoundingEnvelope is a helper class to facilitate calculation of the extent of a solid within the li...
G4bool BoundingBoxVsVoxelLimits(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4GenericPolycone is a Polycone shape where the composing Z planes positions, in their order of defin...
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4bool IsOpen() const
G4ThreeVector GetPointOnSurface() const override
G4Polyhedron * CreatePolyhedron() const override
G4double GetStartPhi() const
G4double GetSurfaceArea() override
G4GenericPolycone & operator=(const G4GenericPolycone &source)
G4double GetEndPhi() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const override
G4int GetNumRZCorner() const
G4double GetCubicVolume() override
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4double GetCosEndPhi() const
G4double GetSinStartPhi() const
G4PolyconeSideRZ GetCorner(G4int index) const
std::ostream & StreamInfo(std::ostream &os) const override
G4double GetSinEndPhi() const
G4GeometryType GetEntityType() const override
EInside Inside(const G4ThreeVector &p) const override
G4GenericPolycone(const G4String &name, G4double phiStart, G4double phiTotal, G4int numRZ, const G4double r[], const G4double z[])
G4VSolid * Clone() const override
G4double GetCosStartPhi() const
static G4bool DiskExtent(G4double rmin, G4double rmax, G4double startPhi, G4double delPhi, G4TwoVector &pmin, G4TwoVector &pmax)
static G4double TriangleArea(G4double Ax, G4double Ay, G4double Bx, G4double By, G4double Cx, G4double Cy)
static G4double PolygonArea(const G4TwoVectorList &polygon)
static G4bool TriangulatePolygon(const G4TwoVectorList &polygon, std::vector< G4int > &result)
G4ReduciblePolygon is a utility class used to specify, test, reduce, and/or otherwise manipulate a 2D...
G4bool BisectedBy(G4double a1, G4double b1, G4double a2, G4double b2, G4double tolerance)
G4double Amin() const
G4bool RemoveDuplicateVertices(G4double tolerance)
G4bool RemoveRedundantVertices(G4double tolerance)
G4bool CrossesItself(G4double tolerance)
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4VCSGfaceted & operator=(const G4VCSGfaceted &source)
G4double fCubicVolume
EInside Inside(const G4ThreeVector &p) const override
G4VCSGface ** faces
G4VCSGfaceted(const G4String &name)
G4Polyhedron * fpPolyhedron
G4bool fRebuildPolyhedron
G4double fSurfaceArea
G4String GetName() const
G4VSolid(const G4String &name)
Definition G4VSolid.cc:59
void DumpInfo() const
G4double kCarTolerance
Definition G4VSolid.hh:418
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMaxExtent(const EAxis pAxis) const
EAxis
Definition geomdefs.hh:54
EInside
Definition geomdefs.hh:67
@ kOutside
Definition geomdefs.hh:68