35 #if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
43 using namespace CLHEP;
59 : Base_t(name, phiStart, phiTotal, numSide,
60 numZPlanes, zPlane, rInner, rOuter)
63 SetOriginalParameters();
75 G4double convertRad = 1./std::cos(0.5*wrDelta/wrNumSide);
77 for (
G4int i=0; i<numZPlanes; ++i)
83 for (
G4int i=numZPlanes-1; i>=0; --i)
89 std::vector<G4int> iout;
98 G4UPolyhedra::G4UPolyhedra(
const G4String& name,
105 : Base_t(name, phiStart, phiTotal, numSide, numRZ, r, z)
108 SetOriginalParameters();
120 G4double convertRad = 1./std::cos(0.5*wrDelta/wrNumSide);
122 for (
G4int i=0; i<numRZ; ++i)
124 rzcorners.push_back(
G4TwoVector(r[i]*convertRad,z[i]));
126 std::vector<G4int> iout;
136 G4UPolyhedra::G4UPolyhedra( __void__&
a )
146 G4UPolyhedra::~G4UPolyhedra()
155 G4UPolyhedra::G4UPolyhedra(
const G4UPolyhedra &source )
158 fGenericPgon = source.fGenericPgon;
159 fOriginalParameters = source.fOriginalParameters;
160 wrStart = source.wrStart;
161 wrDelta = source.wrDelta;
162 wrNumSide = source.wrNumSide;
163 rzcorners = source.rzcorners;
171 G4UPolyhedra& G4UPolyhedra::operator=(
const G4UPolyhedra &source )
173 if (
this == &source)
return *
this;
175 Base_t::operator=( source );
176 fGenericPgon = source.fGenericPgon;
177 fOriginalParameters = source.fOriginalParameters;
178 wrStart = source.wrStart;
179 wrDelta = source.wrDelta;
180 wrNumSide = source.wrNumSide;
181 rzcorners = source.rzcorners;
191 G4int G4UPolyhedra::GetNumSide()
const
195 G4double G4UPolyhedra::GetStartPhi()
const
199 G4double G4UPolyhedra::GetEndPhi()
const
201 return (wrStart + wrDelta);
203 G4double G4UPolyhedra::GetSinStartPhi()
const
206 return std::sin(phi);
208 G4double G4UPolyhedra::GetCosStartPhi()
const
211 return std::cos(phi);
213 G4double G4UPolyhedra::GetSinEndPhi()
const
216 return std::sin(phi);
218 G4double G4UPolyhedra::GetCosEndPhi()
const
221 return std::cos(phi);
223 G4bool G4UPolyhedra::IsOpen()
const
225 return (wrDelta <
twopi);
227 G4bool G4UPolyhedra::IsGeneric()
const
231 G4int G4UPolyhedra::GetNumRZCorner()
const
233 return rzcorners.size();
246 void G4UPolyhedra::SetOriginalParameters()
250 G4int numPlanes = GetZSegmentCount() + 1;
251 G4int numSides = GetSideCount();
253 fOriginalParameters.Start_angle = startPhi;
254 fOriginalParameters.Opening_angle = deltaPhi;
255 fOriginalParameters.Num_z_planes = numPlanes;
256 fOriginalParameters.numSide = numSides;
258 delete [] fOriginalParameters.Z_values;
259 delete [] fOriginalParameters.Rmin;
260 delete [] fOriginalParameters.Rmax;
261 fOriginalParameters.Z_values =
new G4double[numPlanes];
262 fOriginalParameters.Rmin =
new G4double[numPlanes];
263 fOriginalParameters.Rmax =
new G4double[numPlanes];
265 G4double convertRad = std::cos(0.5*deltaPhi/numSides);
266 for (
G4int i=0; i<numPlanes; ++i)
268 fOriginalParameters.Z_values[i] = GetZPlanes()[i];
269 fOriginalParameters.Rmax[i] = GetRMax()[i]/convertRad;
270 fOriginalParameters.Rmin[i] = GetRMin()[i]/convertRad;
275 fOriginalParameters = *pars;
276 fRebuildPolyhedron =
true;
285 message <<
"Solid " << GetName() <<
" built using generic construct."
286 <<
G4endl <<
"Not applicable to the generic construct !";
287 G4Exception(
"G4UPolyhedra::Reset()",
"GeomSolids1001",
295 wrStart = fOriginalParameters.Start_angle;
300 wrDelta = fOriginalParameters.Opening_angle;
305 wrNumSide = fOriginalParameters.numSide;
307 for (
G4int i=0; i<fOriginalParameters.Num_z_planes; ++i)
309 G4double z = fOriginalParameters.Z_values[i];
310 G4double r = fOriginalParameters.Rmax[i];
313 for (
G4int i=fOriginalParameters.Num_z_planes-1; i>=0; --i)
315 G4double z = fOriginalParameters.Z_values[i];
316 G4double r = fOriginalParameters.Rmin[i];
319 std::vector<G4int> iout;
343 G4VSolid* G4UPolyhedra::Clone()
const
345 return new G4UPolyhedra(*
this);
356 static G4bool checkBBox =
true;
357 static G4bool checkPhi =
true;
361 for (
G4int i=0; i<GetNumRZCorner(); ++i)
364 if (corner.
r < rmin) rmin = corner.
r;
365 if (corner.
r > rmax) rmax = corner.
r;
366 if (corner.
z < zmin) zmin = corner.
z;
367 if (corner.
z > zmax) zmax = corner.
z;
373 G4int ksteps = GetNumSide();
380 if (!IsOpen()) rmin = 0;
381 G4double xmin = rmin*cosCur, xmax = xmin;
383 for (
G4int k=0; k<ksteps+1; ++k)
386 if (x < xmin) xmin =
x;
387 if (x > xmax) xmax =
x;
389 if (y < ymin) ymin =
y;
390 if (y > ymax) ymax =
y;
394 if (xx < xmin) xmin =
xx;
395 if (xx > xmax) xmax =
xx;
397 if (yy < ymin) ymin = yy;
398 if (yy > ymax) ymax = yy;
401 sinCur = sinCur*cosStep + cosCur*sinStep;
402 cosCur = cosCur*cosStep - sinTmp*sinStep;
404 pMin.
set(xmin,ymin,zmin);
405 pMax.
set(xmax,ymax,zmax);
409 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
412 message <<
"Bad bounding box (min >= max) for solid: "
414 <<
"\npMin = " << pMin
415 <<
"\npMax = " << pMax;
416 G4Exception(
"G4UPolyhedra::BoundingLimits()",
"GeomMgt0001",
435 message <<
"Inconsistency in bounding boxes for solid: "
437 <<
"\nBBox min: wrapper = " << pMin <<
" solid = " << vmin
438 <<
"\nBBox max: wrapper = " << pMax <<
" solid = " << vmax;
439 G4Exception(
"G4UPolyhedra::BoundingLimits()",
"GeomMgt0001",
449 if (GetStartPhi() != GetPhiStart() ||
450 GetEndPhi() != GetPhiEnd() ||
451 GetNumSide() != GetSideCount() ||
452 IsOpen() != (Base_t::GetPhiDelta() <
twopi))
455 message <<
"Inconsistency in Phi angles or # of sides for solid: "
457 <<
"\nPhi start : wrapper = " << GetStartPhi()
458 <<
" solid = " << GetPhiStart()
459 <<
"\nPhi end : wrapper = " << GetEndPhi()
460 <<
" solid = " << GetPhiEnd()
461 <<
"\nPhi # sides: wrapper = " << GetNumSide()
462 <<
" solid = " << GetSideCount()
463 <<
"\nPhi is open: wrapper = " << (IsOpen() ?
"true" :
"false")
465 << ((Base_t::GetPhiDelta() <
twopi) ?
"true" :
"false");
466 G4Exception(
"G4UPolyhedra::BoundingLimits()",
"GeomMgt0001",
478 G4UPolyhedra::CalculateExtent(
const EAxis pAxis,
488 BoundingLimits(bmin,bmax);
491 if (
true)
return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
493 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
495 return exist = (pMin < pMax) ?
true :
false;
504 std::vector<G4int> iout;
509 for (
G4int i=0; i<GetNumRZCorner(); ++i)
516 if (area < 0.)
std::reverse(contourRZ.begin(),contourRZ.end());
522 message <<
"Triangulation of RZ contour has failed for solid: "
524 <<
"\nExtent has been calculated using boundary box";
527 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
534 G4int ksteps = GetNumSide();
538 G4double sinStart = GetSinStartPhi();
539 G4double cosStart = GetCosStartPhi();
542 std::vector<const G4ThreeVectorList *> polygons;
543 polygons.resize(ksteps+1);
544 for (
G4int k=0; k<ksteps+1; ++k) {
551 G4int ntria = triangles.size()/3;
552 for (
G4int i=0; i<ntria; ++i)
557 for (
G4int k=0; k<ksteps+1; ++k)
560 G4ThreeVectorList::iterator iter = ptr->begin();
561 iter->set(triangles[i3+0].
x()*cosCur,
562 triangles[i3+0].
x()*sinCur,
563 triangles[i3+0].
y());
565 iter->set(triangles[i3+1].
x()*cosCur,
566 triangles[i3+1].
x()*sinCur,
567 triangles[i3+1].
y());
569 iter->set(triangles[i3+2].
x()*cosCur,
570 triangles[i3+2].
x()*sinCur,
571 triangles[i3+2].
y());
574 sinCur = sinCur*cosStep + cosCur*sinStep;
575 cosCur = cosCur*cosStep - sinTmp*sinStep;
581 if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax))
continue;
582 if (emin < pMin) pMin = emin;
583 if (emax > pMax) pMax =
emax;
584 if (eminlim > pMin && emaxlim < pMax)
break;
587 for (
G4int k=0; k<ksteps+1; ++k) {
delete polygons[k]; polygons[k]=0;}
588 return (pMin < pMax);
601 fOriginalParameters.Opening_angle,
602 fOriginalParameters.numSide,
603 fOriginalParameters.Num_z_planes,
604 fOriginalParameters.Z_values,
605 fOriginalParameters.Rmin,
606 fOriginalParameters.Rmax);
636 typedef G4int int4[4];
643 std::vector<G4bool> chopped(GetNumRZCorner(),
false);
644 std::vector<G4int*> triQuads;
645 G4int remaining = GetNumRZCorner();
647 while (remaining >= 3)
652 G4int iStepper = iStarter;
655 if (A < 0) { A = iStepper; }
656 else if (
B < 0) {
B = iStepper; }
657 else if (
C < 0) {
C = iStepper; }
660 if (++iStepper >= GetNumRZCorner()) iStepper = 0;
662 while (chopped[iStepper]);
664 while (
C < 0 && iStepper != iStarter);
669 G4double BAr = GetCorner(A).r - GetCorner(
B).r;
670 G4double BAz = GetCorner(A).z - GetCorner(
B).z;
671 G4double BCr = GetCorner(
C).r - GetCorner(
B).r;
672 G4double BCz = GetCorner(
C).z - GetCorner(
B).z;
679 triQuads.push_back(tq);
687 if (++iStarter >= GetNumRZCorner()) { iStarter = 0; }
689 while (chopped[iStarter]);
694 G4int numSide=GetNumSide();
695 nNodes = (numSide + 1) * GetNumRZCorner();
696 nFaces = numSide * GetNumRZCorner() + 2 * triQuads.size();
697 faces_vec =
new int4[nFaces];
699 G4int addition = GetNumRZCorner() * numSide;
700 G4int d = GetNumRZCorner() - 1;
701 for (
G4int iEnd = 0; iEnd < 2; ++iEnd)
703 for (
size_t i = 0; i < triQuads.size(); ++i)
716 a = triQuads[i][0] + addition;
717 b = triQuads[i][2] + addition;
718 c = triQuads[i][1] + addition;
721 G4int bc = std::abs(c - b);
722 G4int ca = std::abs(a - c);
723 faces_vec[iface][0] = (ab == 1 || ab ==
d)? a: -a;
724 faces_vec[iface][1] = (bc == 1 || bc ==
d)? b: -b;
725 faces_vec[iface][2] = (ca == 1 || ca ==
d)? c: -c;
726 faces_vec[iface][3] = 0;
733 xyz =
new double3[nNodes];
734 const G4double dPhi = (GetEndPhi() - GetStartPhi()) / numSide;
737 for (
G4int iSide = 0; iSide < numSide; ++iSide)
739 for (
G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner)
741 xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi);
742 xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi);
743 xyz[ixyz][2] = GetCorner(iCorner).z;
744 if (iCorner < GetNumRZCorner() - 1)
746 faces_vec[iface][0] = ixyz + 1;
747 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
748 faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2;
749 faces_vec[iface][3] = ixyz + 2;
753 faces_vec[iface][0] = ixyz + 1;
754 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
755 faces_vec[iface][2] = ixyz + 2;
756 faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2;
766 for (
G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner)
768 xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi);
769 xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi);
770 xyz[ixyz][2] = GetCorner(iCorner).z;
776 nNodes = GetNumSide() * GetNumRZCorner();
777 nFaces = GetNumSide() * GetNumRZCorner();;
778 xyz =
new double3[nNodes];
779 faces_vec =
new int4[nFaces];
784 G4int ixyz = 0, iface = 0;
785 for (
G4int iSide = 0; iSide < GetNumSide(); ++iSide)
787 for (
G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner)
789 xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi);
790 xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi);
791 xyz[ixyz][2] = GetCorner(iCorner).z;
792 if (iSide < GetNumSide() - 1)
794 if (iCorner < GetNumRZCorner() - 1)
796 faces_vec[iface][0] = ixyz + 1;
797 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
798 faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2;
799 faces_vec[iface][3] = ixyz + 2;
803 faces_vec[iface][0] = ixyz + 1;
804 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
805 faces_vec[iface][2] = ixyz + 2;
806 faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2;
811 if (iCorner < GetNumRZCorner() - 1)
813 faces_vec[iface][0] = ixyz + 1;
814 faces_vec[iface][1] = ixyz + GetNumRZCorner() - nFaces + 1;
815 faces_vec[iface][2] = ixyz + GetNumRZCorner() - nFaces + 2;
816 faces_vec[iface][3] = ixyz + 2;
820 faces_vec[iface][0] = ixyz + 1;
821 faces_vec[iface][1] = ixyz - nFaces + GetNumRZCorner() + 1;
822 faces_vec[iface][2] = ixyz - nFaces + 2;
823 faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2;
839 message <<
"Problem creating G4Polyhedron for: " << GetName();
840 G4Exception(
"G4Polyhedra::CreatePolyhedron()",
"GeomSolids1002",
852 #endif // G4GEOM_USE_USOLIDS
void set(double x, double y, double z)
G4int createPolyhedron(G4int Nnodes, G4int Nfaces, const G4double xyz[][3], const G4int faces[][4])
G4double GetMaxExtent(const EAxis pAxis) const
std::vector< ExP01TrackerHit * > a
static const G4double kInfinity
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
CLHEP::Hep2Vector G4TwoVector
void message(RunManager *runmanager)
static const G4double emax
const G4double kCarTolerance
std::vector< G4ThreeVector > G4ThreeVectorList
G4double GetMinExtent(const EAxis pAxis) const
ntupleExperimental Reset()
static constexpr double twopi
double A(double temperature)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4GLOB_DLL std::ostream G4cout
double B(double temperature)