44#if !defined(G4GEOM_USE_UPOLYHEDRA)
84 std::ostringstream message;
85 message <<
"Solid must have at least one side - " <<
GetName() <<
G4endl
86 <<
" No sides specified !";
87 G4Exception(
"G4Polyhedra::G4Polyhedra()",
"GeomSolids0002",
95 if ( (phiTotal <=0) || (phiTotal >= twopi*(1-
DBL_EPSILON)) )
97 G4double convertRad = std::cos(0.5*phiTotal/theNumSide);
104 original_parameters->
numSide = theNumSide;
105 original_parameters->Start_angle = phiStart;
106 original_parameters->Opening_angle = phiTotal;
107 original_parameters->Num_z_planes = numZPlanes;
108 original_parameters->Z_values =
new G4double[numZPlanes];
109 original_parameters->Rmin =
new G4double[numZPlanes];
110 original_parameters->Rmax =
new G4double[numZPlanes];
112 for (
G4int i=0; i<numZPlanes; ++i)
114 if (( i < numZPlanes-1) && ( zPlane[i] == zPlane[i+1] ))
116 if( (rInner[i] > rOuter[i+1])
117 ||(rInner[i+1] > rOuter[i]) )
120 std::ostringstream message;
121 message <<
"Cannot create a Polyhedra with no contiguous segments."
123 <<
" Segments are not contiguous !" <<
G4endl
124 <<
" rMin[" << i <<
"] = " << rInner[i]
125 <<
" -- rMax[" << i+1 <<
"] = " << rOuter[i+1] <<
G4endl
126 <<
" rMin[" << i+1 <<
"] = " << rInner[i+1]
127 <<
" -- rMax[" << i <<
"] = " << rOuter[i];
128 G4Exception(
"G4Polyhedra::G4Polyhedra()",
"GeomSolids0002",
132 original_parameters->Z_values[i] = zPlane[i];
133 original_parameters->Rmin[i] = rInner[i]/convertRad;
134 original_parameters->Rmax[i] = rOuter[i]/convertRad;
142 rz->ScaleA( 1/convertRad );
147 Create( phiStart, phiTotal, theNumSide, rz );
165 std::ostringstream message;
166 message <<
"Solid must have at least one side - " <<
GetName() <<
G4endl
167 <<
" No sides specified !";
168 G4Exception(
"G4Polyhedra::G4Polyhedra()",
"GeomSolids0002",
174 Create( phiStart, phiTotal, theNumSide, rz );
188void G4Polyhedra::Create(
G4double phiStart,
196 if (rz->
Amin() < 0.0)
198 std::ostringstream message;
199 message <<
"Illegal input parameters - " <<
GetName() <<
G4endl
200 <<
" All R values must be >= 0 !";
201 G4Exception(
"G4Polyhedra::Create()",
"GeomSolids0002",
212 std::ostringstream message;
213 message <<
"Illegal input parameters - " <<
GetName() <<
G4endl
214 <<
" R/Z cross section is zero or near zero: " << rzArea;
215 G4Exception(
"G4Polyhedra::Create()",
"GeomSolids0002",
222 std::ostringstream message;
223 message <<
"Illegal input parameters - " <<
GetName() <<
G4endl
224 <<
" Too few unique R/Z values !";
225 G4Exception(
"G4Polyhedra::Create()",
"GeomSolids0002",
231 std::ostringstream message;
232 message <<
"Illegal input parameters - " <<
GetName() <<
G4endl
233 <<
" R/Z segments cross !";
234 G4Exception(
"G4Polyhedra::Create()",
"GeomSolids0002",
242 while( startPhi < 0 )
251 if ( (phiTotal <= 0) || (phiTotal > twopi*(1-
DBL_EPSILON)) )
254 endPhi = startPhi + twopi;
259 endPhi = startPhi + phiTotal;
265 numSide = theNumSide;
270 corners =
new G4PolyhedraSideRZ[numCorner];
275 G4ReduciblePolygonIterator iterRZ(rz);
277 G4PolyhedraSideRZ *next = corners;
281 next->
r = iterRZ.GetA();
282 next->
z = iterRZ.GetB();
283 }
while( ++next, iterRZ.Next() );
288 numFace = phiIsOpen ? numCorner+2 : numCorner;
299 G4PolyhedraSideRZ* corner = corners,
300 * prev = corners + numCorner-1,
302 G4VCSGface** face =
faces;
306 if (next >= corners+numCorner) { next = corners; }
308 if (nextNext >= corners+numCorner) { nextNext = corners; }
310 if (corner->
r < 1/kInfinity && next->
r < 1/kInfinity) {
continue; }
312 *face++ =
new G4PolyhedraSide( prev, corner, next, nextNext,
313 numSide, startPhi, endPhi-startPhi, phiIsOpen );
314 }
while( prev=corner, corner=next, corner > corners );
321 *face++ =
new G4PolyPhiFace( rz, startPhi, phiTotal/numSide, endPhi );
322 *face++ =
new G4PolyPhiFace( rz, endPhi, phiTotal/numSide, startPhi );
334 new G4EnclosingCylinder( rz, phiIsOpen, phiStart, phiTotal );
350 delete original_parameters;
351 delete enclosingCylinder;
355 original_parameters =
nullptr;
356 enclosingCylinder =
nullptr;
373 if (
this == &source) {
return *
this; }
378 delete original_parameters;
379 delete enclosingCylinder;
388void G4Polyhedra::CopyStuff(
const G4Polyhedra& source )
393 numSide = source.numSide;
394 startPhi = source.startPhi;
395 endPhi = source.endPhi;
396 phiIsOpen = source.phiIsOpen;
397 numCorner = source.numCorner;
398 genericPgon= source.genericPgon;
406 * sourceCorn = source.corners;
410 }
while( ++sourceCorn, ++corn < corners+numCorner );
415 if (source.original_parameters !=
nullptr)
417 original_parameters =
418 new G4PolyhedraHistorical( *source.original_parameters );
424 enclosingCylinder =
new G4EnclosingCylinder( *source.enclosingCylinder );
449 std::ostringstream message;
450 message <<
"Solid " <<
GetName() <<
" built using generic construct."
451 <<
G4endl <<
"Not applicable to the generic construct !";
452 G4Exception(
"G4Polyhedra::Reset()",
"GeomSolids1001",
462 delete enclosingCylinder;
466 enclosingCylinder =
nullptr;
472 original_parameters->Rmax,
473 original_parameters->Z_values,
474 original_parameters->Num_z_planes );
475 Create( original_parameters->Start_angle,
476 original_parameters->Opening_angle,
477 original_parameters->numSide, rz );
493 if (enclosingCylinder->MustBeOutside(p)) {
return kOutside; }
512 if (enclosingCylinder->ShouldMiss(p,v)) {
return kInfinity; }
532 G4double rmin = kInfinity, rmax = -kInfinity;
533 G4double zmin = kInfinity, zmax = -kInfinity;
537 if (corner.
r < rmin) { rmin = corner.
r; }
538 if (corner.
r > rmax) { rmax = corner.
r; }
539 if (corner.
z < zmin) { zmin = corner.
z; }
540 if (corner.
z > zmax) { zmax = corner.
z; }
553 if (!
IsOpen()) { rmin = 0.; }
554 G4double xmin = rmin*cosCur, xmax = xmin;
555 G4double ymin = rmin*sinCur, ymax = ymin;
556 for (
G4int k=0; k<ksteps+1; ++k)
559 if (x < xmin) { xmin = x; }
560 if (x > xmax) { xmax = x; }
562 if (y < ymin) { ymin = y; }
563 if (y > ymax) { ymax = y; }
567 if (xx < xmin) { xmin = xx; }
568 if (xx > xmax) { xmax = xx; }
570 if (yy < ymin) { ymin = yy; }
571 if (yy > ymax) { ymax = yy; }
574 sinCur = sinCur*cosStep + cosCur*sinStep;
575 cosCur = cosCur*cosStep - sinTmp*sinStep;
577 pMin.
set(xmin,ymin,zmin);
578 pMax.
set(xmax,ymax,zmax);
582 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
584 std::ostringstream message;
585 message <<
"Bad bounding box (min >= max) for solid: "
587 <<
"\npMin = " << pMin
588 <<
"\npMax = " << pMax;
589 G4Exception(
"G4Polyhedra::BoundingLimits()",
"GeomMgt0001",
614 return exist = pMin < pMax;
623 std::vector<G4int> iout;
631 contourRZ.emplace_back(corner.
r,corner.
z);
635 if (area < 0.) { std::reverse(contourRZ.begin(),contourRZ.end()); }
640 std::ostringstream message;
641 message <<
"Triangulation of RZ contour has failed for solid: "
643 <<
"\nExtent has been calculated using boundary box";
661 std::vector<const G4ThreeVectorList *> polygons;
662 polygons.resize(ksteps+1);
663 for (
G4int k=0; k<ksteps+1; ++k)
672 for (
G4int i=0; i<ntria; ++i)
677 for (
G4int k=0; k<ksteps+1; ++k)
680 auto iter = ptr->begin();
681 iter->set(triangles[i3+0].x()*cosCur,
682 triangles[i3+0].x()*sinCur,
683 triangles[i3+0].y());
685 iter->set(triangles[i3+1].x()*cosCur,
686 triangles[i3+1].x()*sinCur,
687 triangles[i3+1].y());
689 iter->set(triangles[i3+2].x()*cosCur,
690 triangles[i3+2].x()*sinCur,
691 triangles[i3+2].y());
694 sinCur = sinCur*cosStep + cosCur*sinStep;
695 cosCur = cosCur*cosStep - sinTmp*sinStep;
705 if (emin < pMin) { pMin = emin; }
706 if (emax > pMax) { pMax = emax; }
707 if (eminlim > pMin && emaxlim < pMax) {
break; }
710 for (
G4int k=0; k<ksteps+1; ++k)
715 return (pMin < pMax);
731 return {
"G4Polyhedra"};
752 G4long oldprc = os.precision(16);
753 os <<
"-----------------------------------------------------------\n"
754 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
755 <<
" ===================================================\n"
756 <<
" Solid type: G4Polyhedra\n"
758 <<
" starting phi angle : " << startPhi/degree <<
" degrees \n"
759 <<
" ending phi angle : " << endPhi/degree <<
" degrees \n"
760 <<
" number of sides : " << numSide <<
" \n";
764 G4int numPlanes = original_parameters->Num_z_planes;
765 os <<
" number of Z planes: " << numPlanes <<
"\n"
767 for (i=0; i<numPlanes; ++i)
769 os <<
" Z plane " << i <<
": "
770 << original_parameters->Z_values[i] <<
"\n";
772 os <<
" Tangent distances to inner surface (Rmin): \n";
773 for (i=0; i<numPlanes; ++i)
775 os <<
" Z plane " << i <<
": "
776 << original_parameters->Rmin[i] <<
"\n";
778 os <<
" Tangent distances to outer surface (Rmax): \n";
779 for (i=0; i<numPlanes; ++i)
781 os <<
" Z plane " << i <<
": "
782 << original_parameters->Rmax[i] <<
"\n";
785 os <<
" number of RZ points: " << numCorner <<
"\n"
786 <<
" RZ values (corners): \n";
787 for (i=0; i<numCorner; ++i)
790 << corners[i].r <<
", " << corners[i].z <<
"\n";
792 os <<
"-----------------------------------------------------------\n";
793 os.precision(oldprc);
810 for (
G4int i=0; i<nrz; ++i)
813 total += (b.
r*b.
r + b.
r*a.
r + a.
r*a.
r)*(b.
z - a.
z);
837 for (
G4int i=0; i<nrz; ++i)
840 total += a.
r*b.
z - a.
z*b.
r;
843 total = std::abs(total);
849 for (
G4int i=0; i<nrz; ++i)
870void G4Polyhedra::SetSurfaceElements()
const
872 fElements =
new std::vector<G4Polyhedra::surface_element>;
881 for (
G4int ib=0; ib<nrz; ++ib)
885 G4Polyhedra::surface_element selem;
889 if (a.
r == 0. && b.
r == 0.) {
continue; }
899 fElements->push_back(selem);
906 fElements->push_back(selem);
914 std::vector<G4int> triangles;
915 for (
G4int i=0; i<nrz; ++i)
918 contourRZ.emplace_back(corner.
r, corner.
z);
921 auto ntria = (
G4int)triangles.size();
922 for (
G4int i=0; i<ntria; i+=3)
924 G4Polyhedra::surface_element selem;
925 selem.i0 = triangles[i];
926 selem.i1 = triangles[i+1];
927 selem.i2 = triangles[i+2];
928 G4PolyhedraSideRZ a =
GetCorner(selem.i0);
929 G4PolyhedraSideRZ b =
GetCorner(selem.i1);
930 G4PolyhedraSideRZ c =
GetCorner(selem.i2);
935 fElements->push_back(selem);
939 fElements->push_back(selem);
951 if (fElements ==
nullptr)
954 SetSurfaceElements();
959 G4Polyhedra::surface_element selem;
960 selem = fElements->back();
962 auto it = std::lower_bound(fElements->begin(), fElements->end(), select,
963 [](
const G4Polyhedra::surface_element& x,
G4double val)
964 ->
G4bool { return x.area < val; });
970 if (u + v > 1.) { u = 1. - u; v = 1. - v; }
986 if (i2 == -1) { p1.
set(a.
r*cosa, a.
r*sina, a.
z); }
987 p0 += (p1 - p0)*u + (p2 - p0)*v;
990 G4double sprev = (it == fElements->begin()) ? 0. : (*(--it)).area;
991 G4int iside = nside*(select - sprev)/(scurr - sprev);
1000 if (iside == nside) { --iside; }
1004 x = p0.
x()*cosphi - p0.
y()*sinphi;
1005 y = p0.
x()*sinphi + p0.
y()*cosphi;
1013 if (i0 >= nrz) { i0 -= nrz; }
1018 x = r*std::cos(phi);
1019 y = r*std::sin(phi);
1020 z = (p1.
z - p0.
z)*u + (p2.
z - p0.
z)*v + p0.
z;
1031 std::vector<G4TwoVector> rz(numCorner);
1032 for (
G4int i = 0; i < numCorner; ++i)
1034 rz[i].set(corners[i].r, corners[i].z);
1038 G4double wrDelta = endPhi - startPhi;
1039 if (wrDelta <= 0. || wrDelta >= twopi*(1-
DBL_EPSILON))
1050 G4int numPlanes = numCorner;
1051 G4bool isConvertible =
true;
1057 std::vector<G4double> Z;
1058 std::vector<G4double> Rmin;
1059 std::vector<G4double> Rmax;
1061 G4int countPlanes=1;
1067 Z.push_back(corners[0].z);
1069 if (Zprev == corners[1].z)
1071 Rmin.push_back(corners[0].r);
1072 Rmax.push_back (corners[1].r);icurr=1;
1074 else if (Zprev == corners[numPlanes-1].z)
1076 Rmin.push_back(corners[numPlanes-1].r);
1077 Rmax.push_back (corners[0].r);
1082 Rmin.push_back(corners[0].r);
1083 Rmax.push_back (corners[0].r);
1088 G4int inextr=0, inextl=0;
1089 for (
G4int i=0; i < numPlanes-2; ++i)
1092 inextl=(icurl <= 0)? numPlanes-1 : icurl-1;
1094 if((
static_cast<int>(corners[inextr].z >= Zmax) &
static_cast<int>(corners[inextl].z >= Zmax)) != 0) {
break; }
1096 G4double Zleft = corners[inextl].z;
1097 G4double Zright = corners[inextr].z;
1102 G4double difZr=corners[inextr].z - corners[icurr].z;
1103 G4double difZl=corners[inextl].z - corners[icurl].z;
1109 Rmin.push_back(corners[inextl].r);
1110 Rmax.push_back(corners[icurr].r);
1114 Rmin.push_back(corners[inextl].r);
1115 Rmax.push_back(corners[icurr].r + (Zleft-corners[icurr].z)/difZr
1116 *(corners[inextr].r - corners[icurr].r));
1123 Rmin.push_back(corners[icurl].r);
1124 Rmax.push_back(corners[icurr].r);
1128 Rmin.push_back(corners[icurl].r);
1129 Rmax.push_back(corners[icurr].r + (Zleft-corners[icurr].z)/difZr
1130 *(corners[inextr].r - corners[icurr].r));
1135 isConvertible=
false;
break;
1137 icurl=(icurl == 0)? numPlanes-1 : icurl-1;
1145 icurl=(icurl == 0)? numPlanes-1 : icurl-1;
1147 Rmin.push_back(corners[inextl].r);
1148 Rmax.push_back (corners[inextr].r);
1152 Z.push_back(Zright);
1155 G4double difZr=corners[inextr].z - corners[icurr].z;
1156 G4double difZl=corners[inextl].z - corners[icurl].z;
1161 Rmax.push_back(corners[inextr].r);
1162 Rmin.push_back(corners[icurr].r);
1166 Rmin.push_back(corners[icurl].r + (Zright-corners[icurl].z)/difZl
1167 * (corners[inextl].r - corners[icurl].r));
1168 Rmax.push_back(corners[inextr].r);
1176 Rmax.push_back(corners[inextr].r);
1177 Rmin.push_back (corners[icurr].r);
1181 Rmax.push_back(corners[inextr].r);
1182 Rmin.push_back (corners[icurl].r+(Zright-corners[icurl].z)/difZl
1183 * (corners[inextl].r - corners[icurl].r));
1189 isConvertible=
false;
break;
1199 inextl=(icurl <= 0)? numPlanes-1 : icurl-1;
1201 Rmax.push_back(corners[inextr].r);
1202 Rmin.push_back(corners[inextl].r);
1208 original_parameters =
new G4PolyhedraHistorical;
1209 original_parameters->numSide = numSide;
1210 original_parameters->Z_values =
new G4double[countPlanes];
1211 original_parameters->Rmin =
new G4double[countPlanes];
1212 original_parameters->Rmax =
new G4double[countPlanes];
1214 for(
G4int j=0; j < countPlanes; ++j)
1216 original_parameters->Z_values[j] = Z[j];
1217 original_parameters->Rmax[j] = Rmax[j];
1218 original_parameters->Rmin[j] = Rmin[j];
1220 original_parameters->Start_angle = startPhi;
1221 original_parameters->Opening_angle = endPhi-startPhi;
1222 original_parameters->Num_z_planes = countPlanes;
1228 std::ostringstream message;
1230 <<
"cannot be converted to Polyhedra with (Rmin,Rmaz,Z) parameters!";
1231 G4Exception(
"G4Polyhedra::SetOriginalParameters()",
1234 original_parameters =
new G4PolyhedraHistorical;
1235 original_parameters->numSide = numSide;
1236 original_parameters->Z_values =
new G4double[numPlanes];
1237 original_parameters->Rmin =
new G4double[numPlanes];
1238 original_parameters->Rmax =
new G4double[numPlanes];
1240 for(
G4int j=0; j < numPlanes; ++j)
1242 original_parameters->Z_values[j] = corners[j].z;
1243 original_parameters->Rmax[j] = corners[j].r;
1244 original_parameters->Rmin[j] = 0.0;
1246 original_parameters->Start_angle = startPhi;
1247 original_parameters->Opening_angle = endPhi-startPhi;
1248 original_parameters->Num_z_planes = numPlanes;
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
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
G4PolyhedraHistorical is a data structure for use in G4Polyhedra.
G4Polyhedra represents a composed closed polyhedra (PGON) made of planar sizes along the Z axis,...
EInside Inside(const G4ThreeVector &p) const override
G4Polyhedra & operator=(const G4Polyhedra &source)
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep) override
G4GeometryType GetEntityType() const override
G4double GetSurfaceArea() override
G4Polyhedra(const G4String &name, G4double phiStart, G4double phiTotal, G4int numSide, G4int numZPlanes, const G4double zPlane[], const G4double rInner[], const G4double rOuter[])
G4int GetNumRZCorner() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const override
G4ThreeVector GetPointOnSurface() const override
G4double GetSinStartPhi() const
G4double GetEndPhi() const
void SetOriginalParameters(G4PolyhedraHistorical *pars)
G4VSolid * Clone() const override
G4Polyhedron * CreatePolyhedron() const override
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4bool IsFaceted() const override
G4PolyhedraSideRZ GetCorner(const G4int index) const
std::ostream & StreamInfo(std::ostream &os) const override
G4double GetStartPhi() const
G4double GetCosStartPhi() const
G4double GetCubicVolume() override
G4ReduciblePolygon is a utility class used to specify, test, reduce, and/or otherwise manipulate a 2D...
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)