33#if !defined(G4GEOM_USE_UPOLYCONE)
73 original_parameters->Start_angle = phiStart;
74 original_parameters->Opening_angle = phiTotal;
75 original_parameters->Num_z_planes = numZPlanes;
76 original_parameters->Z_values =
new G4double[numZPlanes];
77 original_parameters->Rmin =
new G4double[numZPlanes];
78 original_parameters->Rmax =
new G4double[numZPlanes];
80 for (
G4int i=0; i<numZPlanes; ++i)
82 if(rInner[i]>rOuter[i])
85 std::ostringstream message;
86 message <<
"Cannot create a Polycone with rInner > rOuter for the same Z"
88 <<
" rInner > rOuter for the same Z !" <<
G4endl
89 <<
" rMin[" << i <<
"] = " << rInner[i]
90 <<
" -- rMax[" << i <<
"] = " << rOuter[i];
91 G4Exception(
"G4Polycone::G4Polycone()",
"GeomSolids0002",
94 if (( i < numZPlanes-1) && ( zPlane[i] == zPlane[i+1] ))
96 if( (rInner[i] > rOuter[i+1])
97 ||(rInner[i+1] > rOuter[i]) )
100 std::ostringstream message;
101 message <<
"Cannot create a Polycone with no contiguous segments."
103 <<
" Segments are not contiguous !" <<
G4endl
104 <<
" rMin[" << i <<
"] = " << rInner[i]
105 <<
" -- rMax[" << i+1 <<
"] = " << rOuter[i+1] <<
G4endl
106 <<
" rMin[" << i+1 <<
"] = " << rInner[i+1]
107 <<
" -- rMax[" << i <<
"] = " << rOuter[i];
108 G4Exception(
"G4Polycone::G4Polycone()",
"GeomSolids0002",
112 original_parameters->Z_values[i] = zPlane[i];
113 original_parameters->Rmin[i] = rInner[i];
114 original_parameters->Rmax[i] = rOuter[i];
125 Create( phiStart, phiTotal, rz );
143 Create( phiStart, phiTotal, rz );
152 std::ostringstream message;
153 message <<
"Polycone " <<
GetName() <<
"cannot be converted" <<
G4endl
154 <<
"to Polycone with (Rmin,Rmaz,Z) parameters!";
155 G4Exception(
"G4Polycone::G4Polycone()",
"GeomSolids0002",
161 <<
"to optimized polycone with (Rmin,Rmaz,Z) parameters !"
172void G4Polycone::Create(
G4double phiStart,
179 if (rz->
Amin() < 0.0)
181 std::ostringstream message;
182 message <<
"Illegal input parameters - " <<
GetName() <<
G4endl
183 <<
" All R values must be >= 0 !";
184 G4Exception(
"G4Polycone::Create()",
"GeomSolids0002",
195 std::ostringstream message;
196 message <<
"Illegal input parameters - " <<
GetName() <<
G4endl
197 <<
" R/Z cross section is zero or near zero: " << rzArea;
198 G4Exception(
"G4Polycone::Create()",
"GeomSolids0002",
205 std::ostringstream message;
206 message <<
"Illegal input parameters - " <<
GetName() <<
G4endl
207 <<
" Too few unique R/Z values !";
208 G4Exception(
"G4Polycone::Create()",
"GeomSolids0002",
214 std::ostringstream message;
215 message <<
"Illegal input parameters - " <<
GetName() <<
G4endl
216 <<
" R/Z segments cross !";
217 G4Exception(
"G4Polycone::Create()",
"GeomSolids0002",
224 while( startPhi < 0. )
232 if ( (phiTotal <= 0) || (phiTotal > twopi*(1-
DBL_EPSILON)) )
241 endPhi = startPhi + phiTotal;
247 corners =
new G4PolyconeSideRZ[numCorner];
252 G4ReduciblePolygonIterator iterRZ(rz);
254 G4PolyconeSideRZ *next = corners;
258 next->
r = iterRZ.GetA();
259 next->
z = iterRZ.GetB();
260 }
while( ++next, iterRZ.Next() );
265 numFace = phiIsOpen ? numCorner+2 : numCorner;
273 G4PolyconeSideRZ* corner = corners,
274 * prev = corners + numCorner-1,
276 G4VCSGface **face =
faces;
280 if (next >= corners+numCorner) { next = corners; }
282 if (nextNext >= corners+numCorner) { nextNext = corners; }
284 if (corner->
r < 1/kInfinity && next->
r < 1/kInfinity) {
continue; }
292 if (corner->
z > next->
z)
307 *face++ =
new G4PolyconeSide( prev, corner, next, nextNext,
308 startPhi, endPhi-startPhi, phiIsOpen, allBehind );
309 }
while( prev=corner, corner=next, corner > corners );
316 *face++ =
new G4PolyPhiFace( rz, startPhi, 0, endPhi );
317 *face++ =
new G4PolyPhiFace( rz, endPhi, 0, startPhi );
329 new G4EnclosingCylinder( rz, phiIsOpen, phiStart, phiTotal );
347 delete original_parameters;
348 delete enclosingCylinder;
352 original_parameters =
nullptr;
353 enclosingCylinder =
nullptr;
370 if (
this == &source) {
return *
this; }
375 delete original_parameters;
377 delete enclosingCylinder;
386void G4Polycone::CopyStuff(
const G4Polycone& source )
391 startPhi = source.startPhi;
392 endPhi = source.endPhi;
393 phiIsOpen = source.phiIsOpen;
394 numCorner = source.numCorner;
402 * sourceCorn = source.corners;
406 }
while( ++sourceCorn, ++corn < corners+numCorner );
411 if (source.original_parameters !=
nullptr)
413 original_parameters =
414 new G4PolyconeHistorical( *source.original_parameters );
420 enclosingCylinder =
new G4EnclosingCylinder( *source.enclosingCylinder );
445 delete enclosingCylinder;
449 enclosingCylinder =
nullptr;
455 original_parameters->Rmax,
456 original_parameters->Z_values,
457 original_parameters->Num_z_planes );
458 Create( original_parameters->Start_angle,
459 original_parameters->Opening_angle, rz );
475 if (enclosingCylinder->MustBeOutside(p)) {
return kOutside; }
494 if (enclosingCylinder->ShouldMiss(p,v)) {
return kInfinity; }
514 G4double rmin = kInfinity, rmax = -kInfinity;
515 G4double zmin = kInfinity, zmax = -kInfinity;
520 if (corner.
r < rmin) { rmin = corner.
r; }
521 if (corner.
r > rmax) { rmax = corner.
r; }
522 if (corner.
z < zmin) { zmin = corner.
z; }
523 if (corner.
z > zmax) { zmax = corner.
z; }
533 pMin.
set(vmin.
x(),vmin.
y(),zmin);
534 pMax.
set(vmax.
x(),vmax.
y(),zmax);
538 pMin.
set(-rmax,-rmax, zmin);
539 pMax.
set( rmax, rmax, zmax);
544 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
546 std::ostringstream message;
547 message <<
"Bad bounding box (min >= max) for solid: "
549 <<
"\npMin = " << pMin
550 <<
"\npMax = " << pMax;
551 G4Exception(
"G4Polycone::BoundingLimits()",
"GeomMgt0001",
576 return exist = pMin < pMax;
585 std::vector<G4int> iout;
593 contourRZ.emplace_back(corner.
r,corner.
z);
597 if (area < 0.) { std::reverse(contourRZ.begin(),contourRZ.end()); }
602 std::ostringstream message;
603 message <<
"Triangulation of RZ contour has failed for solid: "
605 <<
"\nExtent has been calculated using boundary box";
612 const G4int NSTEPS = 24;
618 G4int ksteps = (dphi <= astep) ? 1 : (
G4int)((dphi-deg)/astep) + 1;
621 G4double sinHalf = std::sin(0.5*ang);
622 G4double cosHalf = std::cos(0.5*ang);
623 G4double sinStep = 2.*sinHalf*cosHalf;
624 G4double cosStep = 1. - 2.*sinHalf*sinHalf;
632 std::vector<const G4ThreeVectorList *> polygons;
633 polygons.resize(ksteps+2);
635 for (
G4int k=0; k<ksteps+2; ++k)
639 for (
G4int k=0; k<ksteps+2; ++k)
641 polygons[k] = &pols[k];
650 for (
G4int i=0; i<ntria; ++i)
653 for (
G4int k=0; k<3; ++k)
655 G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3;
658 r0[k2+0] = triangles[e0].x(); z0[k2+0] = triangles[e0].y();
659 r0[k2+1] = triangles[e1].x(); z0[k2+1] = triangles[e1].y();
663 if (z0[k2+1] - z0[k2+0] <= 0) {
continue; }
669 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
670 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
671 for (
G4int j=0; j<6; ++j)
673 pols[0][j].set(r0[j]*cosStart,r0[j]*sinStart,z0[j]);
675 for (
G4int k=1; k<ksteps+1; ++k)
677 for (
G4int j=0; j<6; ++j)
679 pols[k][j].set(r1[j]*cosCur,r1[j]*sinCur,z0[j]);
682 sinCur = sinCur*cosStep + cosCur*sinStep;
683 cosCur = cosCur*cosStep - sinTmp*sinStep;
685 for (
G4int j=0; j<6; ++j)
687 pols[ksteps+1][j].set(r0[j]*cosEnd,r0[j]*sinEnd,z0[j]);
697 if (emin < pMin) { pMin = emin; }
698 if (emax > pMax) { pMax = emax; }
699 if (eminlim > pMin && emaxlim < pMax) {
return true; }
701 return (pMin < pMax);
717 return {
"G4Polycone"};
732 G4long oldprc = os.precision(16);
733 os <<
"-----------------------------------------------------------\n"
734 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
735 <<
" ===================================================\n"
736 <<
" Solid type: G4Polycone\n"
738 <<
" starting phi angle : " << startPhi/degree <<
" degrees \n"
739 <<
" ending phi angle : " << endPhi/degree <<
" degrees \n";
742 G4int numPlanes = original_parameters->Num_z_planes;
743 os <<
" number of Z planes: " << numPlanes <<
"\n"
745 for (i=0; i<numPlanes; ++i)
747 os <<
" Z plane " << i <<
": "
748 << original_parameters->Z_values[i] <<
"\n";
750 os <<
" Tangent distances to inner surface (Rmin): \n";
751 for (i=0; i<numPlanes; ++i)
753 os <<
" Z plane " << i <<
": "
754 << original_parameters->Rmin[i] <<
"\n";
756 os <<
" Tangent distances to outer surface (Rmax): \n";
757 for (i=0; i<numPlanes; ++i)
759 os <<
" Z plane " << i <<
": "
760 << original_parameters->Rmax[i] <<
"\n";
763 os <<
" number of RZ points: " << numCorner <<
"\n"
764 <<
" RZ values (corners): \n";
765 for (i=0; i<numCorner; ++i)
768 << corners[i].r <<
", " << corners[i].z <<
"\n";
770 os <<
"-----------------------------------------------------------\n";
771 os.precision(oldprc);
788 for (
G4int i=0; i<nrz; ++i)
791 total += (b.
r*b.
r + b.
r*a.
r + a.
r*a.
r)*(b.
z - a.
z);
815 for (
G4int i=0; i<nrz; ++i)
818 scut += a.
r*b.
z - a.
z*b.
r;
821 scut = std::abs(scut);
826 for (
G4int i=0; i<nrz; ++i)
830 slat += (b.
r + a.
r)*h;
845void G4Polycone::SetSurfaceElements()
const
847 fElements =
new std::vector<G4Polycone::surface_element>;
854 for (
G4int ib=0; ib<nrz; ++ib)
858 G4Polycone::surface_element selem;
863 if (a.
r == 0. && b.
r == 0.) {
continue; }
865 total += 0.5*dphi*(b.
r + a.
r)*h;
867 fElements->push_back(selem);
874 std::vector<G4int> triangles;
875 for (
G4int i=0; i<nrz; ++i)
878 contourRZ.emplace_back(corner.
r, corner.
z);
881 auto ntria = (
G4int)triangles.size();
882 for (
G4int i=0; i<ntria; i+=3)
884 G4Polycone::surface_element selem;
885 selem.i0 = triangles[i];
886 selem.i1 = triangles[i+1];
887 selem.i2 = triangles[i+2];
888 G4PolyconeSideRZ a =
GetCorner(selem.i0);
889 G4PolyconeSideRZ b =
GetCorner(selem.i1);
890 G4PolyconeSideRZ c =
GetCorner(selem.i2);
895 fElements->push_back(selem);
899 fElements->push_back(selem);
911 if (fElements ==
nullptr)
914 SetSurfaceElements();
919 G4Polycone::surface_element selem;
920 selem = fElements->back();
922 auto it = std::lower_bound(fElements->begin(), fElements->end(), select,
923 [](
const G4Polycone::surface_element& x,
G4double val)
924 ->
G4bool { return x.area < val; });
944 r = (p1.
r - p0.
r)*u + p0.
r;
945 z = (p1.
z - p0.
z)*u + p0.
z;
949 r = std::sqrt(p1.
r*p1.
r*u + p0.
r*p0.
r*(1. - u));
950 z = p0.
z + (p1.
z - p0.
z)*(r - p0.
r)/(p1.
r - p0.
r);
958 if (i0 >= nrz) { i0 -= nrz; }
962 if (u + v > 1.) { u = 1. - u; v = 1. - v; }
963 r = (p1.
r - p0.
r)*u + (p2.
r - p0.
r)*v + p0.
r;
964 z = (p1.
z - p0.
z)*u + (p2.
z - p0.
z)*v + p0.
z;
966 return { r*std::cos(phi), r*std::sin(phi), z };
975 std::vector<G4TwoVector> rz(numCorner);
976 for (
G4int i = 0; i < numCorner; ++i)
978 rz[i].set(corners[i].r, corners[i].z);
987 G4int numPlanes = numCorner;
988 G4bool isConvertible =
true;
994 std::vector<G4double> Z;
995 std::vector<G4double> Rmin;
996 std::vector<G4double> Rmax;
1004 Z.push_back(corners[0].z);
1006 if (Zprev == corners[1].z)
1008 Rmin.push_back(corners[0].r);
1009 Rmax.push_back (corners[1].r);icurr=1;
1011 else if (Zprev == corners[numPlanes-1].z)
1013 Rmin.push_back(corners[numPlanes-1].r);
1014 Rmax.push_back (corners[0].r);
1019 Rmin.push_back(corners[0].r);
1020 Rmax.push_back (corners[0].r);
1025 G4int inextr=0, inextl=0;
1026 for (
G4int i=0; i < numPlanes-2; ++i)
1029 inextl=(icurl <= 0)? numPlanes-1 : icurl-1;
1031 if((
static_cast<int>(corners[inextr].z >= Zmax) &
static_cast<int>(corners[inextl].z >= Zmax)) != 0) {
break; }
1033 G4double Zleft = corners[inextl].z;
1034 G4double Zright = corners[inextr].z;
1039 G4double difZr=corners[inextr].z - corners[icurr].z;
1040 G4double difZl=corners[inextl].z - corners[icurl].z;
1046 Rmin.push_back(corners[inextl].r);
1047 Rmax.push_back(corners[icurr].r);
1051 Rmin.push_back(corners[inextl].r);
1052 Rmax.push_back(corners[icurr].r + (Zleft-corners[icurr].z)/difZr
1053 *(corners[inextr].r - corners[icurr].r));
1060 Rmin.push_back(corners[icurl].r);
1061 Rmax.push_back(corners[icurr].r);
1065 Rmin.push_back(corners[icurl].r);
1066 Rmax.push_back(corners[icurr].r + (Zleft-corners[icurr].z)/difZr
1067 *(corners[inextr].r - corners[icurr].r));
1072 isConvertible=
false;
break;
1074 icurl=(icurl == 0)? numPlanes-1 : icurl-1;
1082 icurl=(icurl == 0)? numPlanes-1 : icurl-1;
1084 Rmin.push_back(corners[inextl].r);
1085 Rmax.push_back(corners[inextr].r);
1089 Z.push_back(Zright);
1092 G4double difZr=corners[inextr].z - corners[icurr].z;
1093 G4double difZl=corners[inextl].z - corners[icurl].z;
1098 Rmax.push_back(corners[inextr].r);
1099 Rmin.push_back(corners[icurr].r);
1103 Rmin.push_back(corners[icurl].r + (Zright-corners[icurl].z)/difZl
1104 *(corners[inextl].r - corners[icurl].r));
1105 Rmax.push_back(corners[inextr].r);
1113 Rmax.push_back(corners[inextr].r);
1114 Rmin.push_back (corners[icurr].r);
1118 Rmax.push_back(corners[inextr].r);
1119 Rmin.push_back (corners[icurl].r+(Zright-corners[icurl].z)/difZl
1120 * (corners[inextl].r - corners[icurl].r));
1126 isConvertible=
false;
break;
1136 inextl=(icurl <= 0)? numPlanes-1 : icurl-1;
1138 Rmax.push_back(corners[inextr].r);
1139 Rmin.push_back(corners[inextl].r);
1145 original_parameters =
new G4PolyconeHistorical;
1146 original_parameters->Z_values =
new G4double[countPlanes];
1147 original_parameters->Rmin =
new G4double[countPlanes];
1148 original_parameters->Rmax =
new G4double[countPlanes];
1150 for(
G4int j=0; j < countPlanes; ++j)
1152 original_parameters->Z_values[j] = Z[j];
1153 original_parameters->Rmax[j] = Rmax[j];
1154 original_parameters->Rmin[j] = Rmin[j];
1156 original_parameters->Start_angle = startPhi;
1157 original_parameters->Opening_angle = endPhi-startPhi;
1158 original_parameters->Num_z_planes = countPlanes;
1164 std::ostringstream message;
1166 <<
"cannot be converted to Polycone with (Rmin,Rmaz,Z) parameters!";
1167 G4Exception(
"G4Polycone::SetOriginalParameters()",
"GeomSolids0002",
1170 original_parameters =
new G4PolyconeHistorical;
1171 original_parameters->Z_values =
new G4double[numPlanes];
1172 original_parameters->Rmin =
new G4double[numPlanes];
1173 original_parameters->Rmax =
new G4double[numPlanes];
1175 for(
G4int j=0; j < numPlanes; ++j)
1177 original_parameters->Z_values[j] = corners[j].z;
1178 original_parameters->Rmax[j] = corners[j].r;
1179 original_parameters->Rmin[j] = 0.0;
1181 original_parameters->Start_angle = startPhi;
1182 original_parameters->Opening_angle = endPhi-startPhi;
1183 original_parameters->Num_z_planes = numPlanes;
1185 return isConvertible;
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
G4GLOB_DLL std::ostream G4cout
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
G4PolyconeHistorical is a data structure for use in G4Polycone.
G4Polycone represents a composed closed shape (PCON) made of cones and cylinders, along the Z axis wi...
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4double GetCosEndPhi() const
G4Polyhedron * CreatePolyhedron() const override
G4GeometryType GetEntityType() const override
G4Polycone(const G4String &name, G4double phiStart, G4double phiTotal, G4int numZPlanes, const G4double zPlane[], const G4double rInner[], const G4double rOuter[])
G4double GetSurfaceArea() override
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep) override
G4double GetEndPhi() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const override
G4double GetSinEndPhi() const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
EInside Inside(const G4ThreeVector &p) const override
G4double GetCosStartPhi() const
void SetOriginalParameters(G4PolyconeHistorical *pars)
G4double GetCubicVolume() override
G4double GetStartPhi() const
G4Polycone & operator=(const G4Polycone &source)
G4VSolid * Clone() const override
std::ostream & StreamInfo(std::ostream &os) const override
G4ThreeVector GetPointOnSurface() const override
G4double GetSinStartPhi() const
G4int GetNumRZCorner() const
G4PolyconeSideRZ GetCorner(G4int index) 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
G4VPVParameterisation ia an abstract base class for Parameterisation, able to compute the transformat...
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4VPhysicalVolume is an abstract base class for the representation of a positioned volume....
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
G4double total(Particle const *const p1, Particle const *const p2)