44#if !defined(G4GEOM_USE_UPOLYHEDRA)
83 std::ostringstream message;
84 message <<
"Solid must have at least one side - " <<
GetName() <<
G4endl
85 <<
" No sides specified !";
86 G4Exception(
"G4Polyhedra::G4Polyhedra()",
"GeomSolids0002",
94 if ( (phiTotal <=0) || (phiTotal >= twopi*(1-
DBL_EPSILON)) )
96 G4double convertRad = std::cos(0.5*phiTotal/theNumSide);
111 for (
G4int i=0; i<numZPlanes; ++i)
113 if (( i < numZPlanes-1) && ( zPlane[i] == zPlane[i+1] ))
115 if( (rInner[i] > rOuter[i+1])
116 ||(rInner[i+1] > rOuter[i]) )
119 std::ostringstream message;
120 message <<
"Cannot create a Polyhedra with no contiguous segments."
122 <<
" Segments are not contiguous !" <<
G4endl
123 <<
" rMin[" << i <<
"] = " << rInner[i]
124 <<
" -- rMax[" << i+1 <<
"] = " << rOuter[i+1] <<
G4endl
125 <<
" rMin[" << i+1 <<
"] = " << rInner[i+1]
126 <<
" -- rMax[" << i <<
"] = " << rOuter[i];
127 G4Exception(
"G4Polyhedra::G4Polyhedra()",
"GeomSolids0002",
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 );
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",
248 if ( (phiTotal <= 0) || (phiTotal > twopi*(1-
DBL_EPSILON)) )
260 endPhi = phiStart+phiTotal;
284 next->
r = iterRZ.
GetA();
285 next->
z = iterRZ.
GetB();
286 }
while( ++next, iterRZ.
Next() );
313 if (corner->
r < 1/kInfinity && next->
r < 1/kInfinity)
continue;
338 }
while( prev=corner, corner=next, corner >
corners );
397 if (
this == &source)
return *
this;
473 std::ostringstream message;
474 message <<
"Solid " <<
GetName() <<
" built using generic construct."
475 <<
G4endl <<
"Not applicable to the generic construct !";
476 G4Exception(
"G4Polyhedra::Reset()",
"GeomSolids1001",
558 G4double rmin = kInfinity, rmax = -kInfinity;
559 G4double zmin = kInfinity, zmax = -kInfinity;
563 if (corner.
r < rmin) rmin = corner.
r;
564 if (corner.
r > rmax) rmax = corner.
r;
565 if (corner.
z < zmin) zmin = corner.
z;
566 if (corner.
z > zmax) zmax = corner.
z;
580 G4double xmin = rmin*cosCur, xmax = xmin;
581 G4double ymin = rmin*sinCur, ymax = ymin;
582 for (
G4int k=0; k<ksteps+1; ++k)
585 if (x < xmin) xmin = x;
586 if (x > xmax) xmax = x;
588 if (y < ymin) ymin = y;
589 if (y > ymax) ymax = y;
593 if (xx < xmin) xmin = xx;
594 if (xx > xmax) xmax = xx;
596 if (yy < ymin) ymin = yy;
597 if (yy > ymax) ymax = yy;
600 sinCur = sinCur*cosStep + cosCur*sinStep;
601 cosCur = cosCur*cosStep - sinTmp*sinStep;
603 pMin.
set(xmin,ymin,zmin);
604 pMax.
set(xmax,ymax,zmax);
608 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
610 std::ostringstream message;
611 message <<
"Bad bounding box (min >= max) for solid: "
613 <<
"\npMin = " << pMin
614 <<
"\npMax = " << pMax;
615 G4Exception(
"G4Polyhedra::BoundingLimits()",
"GeomMgt0001",
640 return exist = (pMin < pMax) ?
true :
false;
649 std::vector<G4int> iout;
661 if (area < 0.) std::reverse(contourRZ.begin(),contourRZ.end());
666 std::ostringstream message;
667 message <<
"Triangulation of RZ contour has failed for solid: "
669 <<
"\nExtent has been calculated using boundary box";
687 std::vector<const G4ThreeVectorList *> polygons;
688 polygons.resize(ksteps+1);
689 for (
G4int k=0; k<ksteps+1; ++k)
697 G4int ntria = triangles.size()/3;
698 for (
G4int i=0; i<ntria; ++i)
703 for (
G4int k=0; k<ksteps+1; ++k)
706 G4ThreeVectorList::iterator iter = ptr->begin();
707 iter->set(triangles[i3+0].x()*cosCur,
708 triangles[i3+0].x()*sinCur,
709 triangles[i3+0].y());
711 iter->set(triangles[i3+1].x()*cosCur,
712 triangles[i3+1].x()*sinCur,
713 triangles[i3+1].y());
715 iter->set(triangles[i3+2].x()*cosCur,
716 triangles[i3+2].x()*sinCur,
717 triangles[i3+2].y());
720 sinCur = sinCur*cosStep + cosCur*sinStep;
721 cosCur = cosCur*cosStep - sinTmp*sinStep;
727 if (!benv.
CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax))
continue;
728 if (emin < pMin) pMin = emin;
729 if (emax > pMax) pMax = emax;
730 if (eminlim > pMin && emaxlim < pMax)
break;
733 for (
G4int k=0; k<ksteps+1; ++k) {
delete polygons[k]; polygons[k]=0;}
734 return (pMin < pMax);
764 G4int oldprc = os.precision(16);
765 os <<
"-----------------------------------------------------------\n"
766 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
767 <<
" ===================================================\n"
768 <<
" Solid type: G4Polyhedra\n"
770 <<
" starting phi angle : " <<
startPhi/degree <<
" degrees \n"
771 <<
" ending phi angle : " <<
endPhi/degree <<
" degrees \n"
772 <<
" number of sides : " <<
numSide <<
" \n";
777 os <<
" number of Z planes: " << numPlanes <<
"\n"
779 for (i=0; i<numPlanes; ++i)
781 os <<
" Z plane " << i <<
": "
784 os <<
" Tangent distances to inner surface (Rmin): \n";
785 for (i=0; i<numPlanes; ++i)
787 os <<
" Z plane " << i <<
": "
790 os <<
" Tangent distances to outer surface (Rmax): \n";
791 for (i=0; i<numPlanes; ++i)
793 os <<
" Z plane " << i <<
": "
797 os <<
" number of RZ points: " <<
numCorner <<
"\n"
798 <<
" RZ values (corners): \n";
804 os <<
"-----------------------------------------------------------\n";
805 os.precision(oldprc);
821 for (
G4int i=0; i<nrz; ++i)
824 total += (b.
r*b.
r + b.
r*a.
r + a.
r*a.
r)*(b.
z - a.
z);
846 for (
G4int i=0; i<nrz; ++i)
849 total += a.
r*b.
z - a.
z*b.
r;
852 total = std::abs(total);
858 for (
G4int i=0; i<nrz; ++i)
880 fElements =
new std::vector<G4Polyhedra::surface_element>;
889 for (
G4int ib=0; ib<nrz; ++ib)
897 if (a.
r == 0. && b.
r == 0.)
continue;
922 std::vector<G4int> triangles;
923 for (
G4int i=0; i<nrz; ++i)
929 G4int ntria = triangles.size();
930 for (
G4int i=0; i<ntria; i+=3)
933 selem.
i0 = triangles[i];
934 selem.
i1 = triangles[i+1];
935 selem.
i2 = triangles[i+2];
972 ->
G4bool { return x.area < val; });
978 if (u + v > 1.) { u = 1. - u; v = 1. - v; }
994 if (i2 == -1) p1.
set(a.
r*cosa, a.
r*sina, a.
z);
995 p0 += (p1 - p0)*u + (p2 - p0)*v;
999 G4int iside = nside*(select - sprev)/(scurr - sprev);
1008 if (iside == nside) --iside;
1012 x = p0.
x()*cosphi - p0.
y()*sinphi;
1013 y = p0.
x()*sinphi + p0.
y()*cosphi;
1021 if (i0 >= nrz) { i0 -= nrz; }
1026 x = r*std::cos(phi);
1027 y = r*std::sin(phi);
1028 z = (p1.
z - p0.
z)*u + (p2.
z - p0.
z)*v + p0.
z;
1077 typedef G4int int4[4];
1084 std::vector<G4bool> chopped(
numCorner,
false);
1085 std::vector<G4int*> triQuads;
1088 while (remaining >= 3)
1093 G4int iStepper = iStarter;
1096 if (
A < 0) {
A = iStepper; }
1097 else if (
B < 0) {
B = iStepper; }
1098 else if (
C < 0) {
C = iStepper; }
1101 if (++iStepper >=
numCorner) iStepper = 0;
1103 while (chopped[iStepper]);
1105 while (
C < 0 && iStepper != iStarter);
1120 triQuads.push_back(tq);
1128 if (++iStarter >=
numCorner) { iStarter = 0; }
1130 while (chopped[iStarter]);
1138 faces_vec =
new int4[nFaces];
1142 for (
G4int iEnd = 0; iEnd < 2; ++iEnd)
1144 for (
size_t i = 0; i < triQuads.size(); ++i)
1157 a = triQuads[i][0] + addition;
1158 b = triQuads[i][2] + addition;
1159 c = triQuads[i][1] + addition;
1161 G4int ab = std::abs(b - a);
1162 G4int bc = std::abs(c - b);
1163 G4int ca = std::abs(a - c);
1164 faces_vec[iface][0] = (ab == 1 || ab == d)? a: -a;
1165 faces_vec[iface][1] = (bc == 1 || bc == d)? b: -b;
1166 faces_vec[iface][2] = (ca == 1 || ca == d)? c: -c;
1167 faces_vec[iface][3] = 0;
1174 xyz =
new double3[nNodes];
1182 xyz[ixyz][0] =
corners[iCorner].
r * std::cos(phi);
1183 xyz[ixyz][1] =
corners[iCorner].
r * std::sin(phi);
1187 faces_vec[iface][0] = ixyz + 1;
1188 faces_vec[iface][1] = ixyz +
numCorner + 1;
1189 faces_vec[iface][2] = ixyz +
numCorner + 2;
1190 faces_vec[iface][3] = ixyz + 2;
1194 faces_vec[iface][0] = ixyz + 1;
1195 faces_vec[iface][1] = ixyz +
numCorner + 1;
1196 faces_vec[iface][2] = ixyz + 2;
1197 faces_vec[iface][3] = ixyz -
numCorner + 2;
1209 xyz[ixyz][0] =
corners[iCorner].
r * std::cos(phi);
1210 xyz[ixyz][1] =
corners[iCorner].
r * std::sin(phi);
1219 xyz =
new double3[nNodes];
1220 faces_vec =
new int4[nFaces];
1225 G4int ixyz = 0, iface = 0;
1230 xyz[ixyz][0] =
corners[iCorner].
r * std::cos(phi);
1231 xyz[ixyz][1] =
corners[iCorner].
r * std::sin(phi);
1237 faces_vec[iface][0] = ixyz + 1;
1238 faces_vec[iface][1] = ixyz +
numCorner + 1;
1239 faces_vec[iface][2] = ixyz +
numCorner + 2;
1240 faces_vec[iface][3] = ixyz + 2;
1244 faces_vec[iface][0] = ixyz + 1;
1245 faces_vec[iface][1] = ixyz +
numCorner + 1;
1246 faces_vec[iface][2] = ixyz + 2;
1247 faces_vec[iface][3] = ixyz -
numCorner + 2;
1254 faces_vec[iface][0] = ixyz + 1;
1255 faces_vec[iface][1] = ixyz +
numCorner - nFaces + 1;
1256 faces_vec[iface][2] = ixyz +
numCorner - nFaces + 2;
1257 faces_vec[iface][3] = ixyz + 2;
1261 faces_vec[iface][0] = ixyz + 1;
1262 faces_vec[iface][1] = ixyz - nFaces +
numCorner + 1;
1263 faces_vec[iface][2] = ixyz - nFaces + 2;
1264 faces_vec[iface][3] = ixyz -
numCorner + 2;
1275 delete [] faces_vec;
1279 std::ostringstream message;
1280 message <<
"Problem creating G4Polyhedron for: " <<
GetName();
1281 G4Exception(
"G4Polyhedra::CreatePolyhedron()",
"GeomSolids1002",
1298 G4bool isConvertible =
true;
1304 std::vector<G4double> Z;
1305 std::vector<G4double> Rmin;
1306 std::vector<G4double> Rmax;
1308 G4int countPlanes=1;
1319 Rmax.push_back (
corners[1].r);icurr=1;
1321 else if (Zprev ==
corners[numPlanes-1].z)
1323 Rmin.push_back(
corners[numPlanes-1].r);
1324 Rmax.push_back (
corners[0].r);
1330 Rmax.push_back (
corners[0].r);
1335 G4int inextr=0, inextl=0;
1336 for (
G4int i=0; i < numPlanes-2; ++i)
1339 inextl=(icurl <= 0)? numPlanes-1 : icurl-1;
1341 if((
corners[inextr].z >= Zmax) & (
corners[inextl].
z >= Zmax)) {
break; }
1356 Rmin.push_back(
corners[inextl].r);
1357 Rmax.push_back(
corners[icurr].r);
1361 Rmin.push_back(
corners[inextl].r);
1370 Rmin.push_back(
corners[icurl].r);
1371 Rmax.push_back(
corners[icurr].r);
1375 Rmin.push_back(
corners[icurl].r);
1382 isConvertible=
false;
break;
1384 icurl=(icurl == 0)? numPlanes-1 : icurl-1;
1392 icurl=(icurl == 0)? numPlanes-1 : icurl-1;
1394 Rmin.push_back(
corners[inextl].r);
1395 Rmax.push_back (
corners[inextr].r);
1399 Z.push_back(Zright);
1408 Rmax.push_back(
corners[inextr].r);
1409 Rmin.push_back(
corners[icurr].r);
1413 Rmin.push_back(
corners[icurl].r + (Zright-
corners[icurl].z)/difZl
1415 Rmax.push_back(
corners[inextr].r);
1423 Rmax.push_back(
corners[inextr].r);
1424 Rmin.push_back (
corners[icurr].r);
1428 Rmax.push_back(
corners[inextr].r);
1436 isConvertible=
false;
break;
1446 inextl=(icurl <= 0)? numPlanes-1 : icurl-1;
1448 Rmax.push_back(
corners[inextr].r);
1449 Rmin.push_back(
corners[inextl].r);
1461 for(
G4int j=0; j < countPlanes; ++j)
1475 std::ostringstream message;
1477 <<
"cannot be converted to Polyhedra with (Rmin,Rmaz,Z) parameters!";
1478 G4Exception(
"G4Polyhedra::SetOriginalParameters()",
1487 for(
G4int j=0; j < numPlanes; ++j)
std::vector< G4ThreeVector > G4ThreeVectorList
double B(double temperature)
double A(double temperature)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
void set(double x, double y, double z)
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
G4bool ShouldMiss(const G4ThreeVector &p, const G4ThreeVector &v) const
G4bool MustBeOutside(const G4ThreeVector &p) const
G4ThreeVector GetPointOnSurface() const
G4Polyhedra & operator=(const G4Polyhedra &source)
std::ostream & StreamInfo(std::ostream &os) const
G4PolyhedraHistorical * original_parameters
G4double GetCubicVolume()
G4PolyhedraSideRZ * corners
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
G4Polyhedra(const G4String &name, G4double phiStart, G4double phiTotal, G4int numSide, G4int numZPlanes, const G4double zPlane[], const G4double rInner[], const G4double rOuter[])
G4int GetNumRZCorner() const
void CopyStuff(const G4Polyhedra &source)
G4double GetSinStartPhi() const
void Create(G4double phiStart, G4double phiTotal, G4int numSide, G4ReduciblePolygon *rz)
G4GeometryType GetEntityType() const
G4double GetSurfaceArea()
G4double GetEndPhi() const
std::vector< surface_element > * fElements
void SetOriginalParameters(G4PolyhedraHistorical *pars)
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
G4PolyhedraSideRZ GetCorner(const G4int index) const
G4double GetStartPhi() const
G4EnclosingCylinder * enclosingCylinder
G4double GetCosStartPhi() const
void SetSurfaceElements() const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
EInside Inside(const G4ThreeVector &p) const
G4Polyhedron * CreatePolyhedron() const
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
G4bool RemoveDuplicateVertices(G4double tolerance)
G4int NumVertices() const
G4bool RemoveRedundantVertices(G4double tolerance)
G4bool CrossesItself(G4double tolerance)
void ScaleA(G4double scale)
G4VCSGfaceted & operator=(const G4VCSGfaceted &source)
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
virtual EInside Inside(const G4ThreeVector &p) const
G4Polyhedron * fpPolyhedron
G4bool fRebuildPolyhedron
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMaxExtent(const EAxis pAxis) const
G4int createPolyhedron(G4int Nnodes, G4int Nfaces, const G4double xyz[][3], const G4int faces[][4])