33#if !defined(G4GEOM_USE_UGENERICPOLYCONE)
71 Create( phiStart, phiTotal, rz );
84void G4GenericPolycone::Create(
G4double phiStart,
93 std::ostringstream message;
94 message <<
"Illegal input parameters - " <<
GetName() <<
G4endl
95 <<
" All R values must be >= 0 !";
96 G4Exception(
"G4GenericPolycone::Create()",
"GeomSolids0002",
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",
117 std::ostringstream message;
118 message <<
"Illegal input parameters - " <<
GetName() <<
G4endl
119 <<
" Too few unique R/Z values !";
120 G4Exception(
"G4GenericPolycone::Create()",
"GeomSolids0002",
126 std::ostringstream message;
127 message <<
"Illegal input parameters - " <<
GetName() <<
G4endl
128 <<
" R/Z segments cross !";
129 G4Exception(
"G4GenericPolycone::Create()",
"GeomSolids0002",
139 if (phiTotal <= 0 || phiTotal > twopi-1E-10)
153 while( startPhi < 0 )
158 endPhi = phiStart+phiTotal;
159 while( endPhi < startPhi )
168 corners =
new G4PolyconeSideRZ[numCorner];
173 G4ReduciblePolygonIterator iterRZ(rz);
175 G4PolyconeSideRZ* next = corners;
179 next->
r = iterRZ.GetA();
180 next->
z = iterRZ.GetB();
181 }
while( ++next, iterRZ.Next() );
186 numFace = phiIsOpen ? numCorner+2 : numCorner;
194 G4PolyconeSideRZ *corner = corners,
195 *prev = corners + numCorner-1,
197 G4VCSGface** face =
faces;
201 if (next >= corners+numCorner) { next = corners; }
203 if (nextNext >= corners+numCorner) { nextNext = corners; }
205 if (corner->
r < 1/kInfinity && next->
r < 1/kInfinity) {
continue; }
213 if (corner->
z > next->
z)
228 *face++ =
new G4PolyconeSide( prev, corner, next, nextNext,
229 startPhi, endPhi-startPhi, phiIsOpen, allBehind );
230 }
while( prev=corner, corner=next, corner > corners );
237 *face++ =
new G4PolyPhiFace( rz, startPhi, 0, endPhi );
238 *face++ =
new G4PolyPhiFace( rz, endPhi, 0, startPhi );
250 new G4EnclosingCylinder( rz, phiIsOpen, phiStart, phiTotal );
266 delete enclosingCylinder;
270 enclosingCylinder =
nullptr;
288 if (
this == &source) {
return *
this; }
295 delete enclosingCylinder;
309 startPhi = source.startPhi;
310 endPhi = source.endPhi;
311 phiIsOpen = source.phiIsOpen;
312 numCorner = source.numCorner;
320 *sourceCorn = source.corners;
324 }
while( ++sourceCorn, ++corn < corners+numCorner );
329 enclosingCylinder =
new G4EnclosingCylinder( *source.enclosingCylinder );
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",
366 if (enclosingCylinder->MustBeOutside(p)) {
return kOutside;
386 if (enclosingCylinder->ShouldMiss(p,v)) {
return kInfinity; }
409 G4double rmin = kInfinity, rmax = -kInfinity;
410 G4double zmin = kInfinity, zmax = -kInfinity;
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; }
428 pMin.
set(vmin.
x(),vmin.
y(),zmin);
429 pMax.
set(vmax.
x(),vmax.
y(),zmax);
433 pMin.
set(-rmax,-rmax, zmin);
434 pMax.
set( rmax, rmax, zmax);
439 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
441 std::ostringstream message;
442 message <<
"Bad bounding box (min >= max) for solid: "
444 <<
"\npMin = " << pMin
445 <<
"\npMax = " << pMax;
446 G4Exception(
"GenericG4Polycone::BoundingLimits()",
"GeomMgt0001",
474 return exist = pMin < pMax;
490 contourRZ.emplace_back(corner.
r,corner.
z);
493 if (area < 0.) { std::reverse(contourRZ.begin(),contourRZ.end()); }
498 std::ostringstream message;
499 message <<
"Triangulation of RZ contour has failed for solid: "
501 <<
"\nExtent has been calculated using boundary box";
502 G4Exception(
"G4GenericPolycone::CalculateExtent()",
508 const G4int NSTEPS = 24;
514 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-deg)/astep) + 1;
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;
528 std::vector<const G4ThreeVectorList *> polygons;
529 polygons.resize(ksteps+2);
531 for (
G4int k=0; k<ksteps+2; ++k)
535 for (
G4int k=0; k<ksteps+2; ++k)
537 polygons[k] = &pols[k];
546 for (
G4int i=0; i<ntria; ++i)
549 for (
G4int k=0; k<3; ++k)
551 G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3;
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();
559 if (z0[k2+1] - z0[k2+0] <= 0) {
continue; }
565 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
566 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
567 for (
G4int j=0; j<6; ++j)
569 pols[0][j].set(r0[j]*cosStart,r0[j]*sinStart,z0[j]);
571 for (
G4int k=1; k<ksteps+1; ++k)
573 for (
G4int j=0; j<6; ++j)
575 pols[k][j].set(r1[j]*cosCur,r1[j]*sinCur,z0[j]);
578 sinCur = sinCur*cosStep + cosCur*sinStep;
579 cosCur = cosCur*cosStep - sinTmp*sinStep;
581 for (
G4int j=0; j<6; ++j)
583 pols[ksteps+1][j].set(r0[j]*cosEnd,r0[j]*sinEnd,z0[j]);
593 if (emin < pMin) { pMin = emin; }
594 if (emax > pMax) { pMax = emax; }
595 if (eminlim > pMin && emaxlim < pMax) {
return true; }
597 return (pMin < pMax);
604 return {
"G4GenericPolycone"};
622 G4long oldprc = os.precision(16);
623 os <<
"-----------------------------------------------------------\n"
624 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
625 <<
" ===================================================\n"
626 <<
" Solid type: G4GenericPolycone\n"
628 <<
" starting phi angle : " << startPhi/degree <<
" degrees \n"
629 <<
" ending phi angle : " << endPhi/degree <<
" degrees \n";
632 os <<
" number of RZ points: " << numCorner <<
"\n"
633 <<
" RZ values (corners): \n";
634 for (i=0; i<numCorner; ++i)
637 << corners[i].r <<
", " << corners[i].z <<
"\n";
639 os <<
"-----------------------------------------------------------\n";
640 os.precision(oldprc);
657 for (
G4int i=0; i<nrz; ++i)
660 total += (b.
r*b.
r + b.
r*a.
r + a.
r*a.
r)*(b.
z - a.
z);
684 for (
G4int i=0; i<nrz; ++i)
687 scut += a.
r*b.
z - a.
z*b.
r;
690 scut = std::abs(scut);
695 for (
G4int i=0; i<nrz; ++i)
699 slat += (b.
r + a.
r)*h;
714void G4GenericPolycone::SetSurfaceElements()
const
716 fElements =
new std::vector<G4GenericPolycone::surface_element>;
723 for (
G4int ib=0; ib<nrz; ++ib)
727 G4GenericPolycone::surface_element selem;
732 if (a.
r == 0. && b.
r == 0.) {
continue; }
734 sarea += 0.5*dphi*(b.
r + a.
r)*h;
736 fElements->push_back(selem);
743 std::vector<G4int> triangles;
744 for (
G4int i=0; i<nrz; ++i)
747 contourRZ.emplace_back(corner.
r, corner.
z);
750 auto ntria = (
G4int)triangles.size();
751 for (
G4int i=0; i<ntria; i+=3)
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);
764 fElements->push_back(selem);
768 fElements->push_back(selem);
780 if (fElements ==
nullptr)
783 SetSurfaceElements();
788 G4GenericPolycone::surface_element selem;
789 selem = fElements->back();
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; });
813 r = (p1.
r - p0.
r)*u + p0.
r;
814 z = (p1.
z - p0.
z)*u + p0.
z;
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);
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;
835 return {r*std::cos(phi), r*std::sin(phi), z};
844 std::vector<G4TwoVector> rz(numCorner);
845 for (
G4int i = 0; i < numCorner; ++i)
847 rz[i].set(corners[i].r, corners[i].z);
G4TemplateAutoLock< G4Mutex > G4AutoLock
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4double G4QuickRand(uint32_t seed=0)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
void set(double x, double y, double z)
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
G4ThreeVector GetPointOnSurface() const override
G4Polyhedron * CreatePolyhedron() const override
G4double GetStartPhi() const
G4double GetSurfaceArea() override
~G4GenericPolycone() 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
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)
G4bool RemoveDuplicateVertices(G4double tolerance)
G4int NumVertices() const
G4bool RemoveRedundantVertices(G4double tolerance)
G4bool CrossesItself(G4double tolerance)
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4VCSGfaceted & operator=(const G4VCSGfaceted &source)
EInside Inside(const G4ThreeVector &p) const override
G4VCSGfaceted(const G4String &name)
G4Polyhedron * fpPolyhedron
G4bool fRebuildPolyhedron
G4VSolid(const G4String &name)
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMaxExtent(const EAxis pAxis) const