35 #if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
42 using namespace CLHEP;
58 : G4USolid(name, new UPolyhedra(name,phiStart, phiTotal, numSide,
59 numZPlanes, zPlane, rInner, rOuter))
61 wrStart = phiStart;
while (wrStart < 0) wrStart +=
twopi;
68 G4double convertRad = 1./std::cos(0.5*wrDelta/wrNumSide);
70 for (
G4int i=0; i<numZPlanes; ++i)
76 for (
G4int i=numZPlanes-1; i>=0; --i)
82 std::vector<G4int> iout;
91 G4UPolyhedra::G4UPolyhedra(
const G4String& name,
98 : G4USolid(name, new UPolyhedra(name, phiStart, phiTotal, numSide,
101 wrStart = phiStart;
while (wrStart < 0) wrStart +=
twopi;
108 G4double convertRad = 1./std::cos(0.5*wrDelta/wrNumSide);
110 for (
G4int i=0; i<numRZ; ++i)
112 rzcorners.push_back(
G4TwoVector(r[i]*convertRad,z[i]));
114 std::vector<G4int> iout;
124 G4UPolyhedra::G4UPolyhedra( __void__&
a )
134 G4UPolyhedra::~G4UPolyhedra()
143 G4UPolyhedra::G4UPolyhedra(
const G4UPolyhedra &source )
146 wrStart = source.wrStart;
147 wrDelta = source.wrDelta;
148 wrNumSide = source.wrNumSide;
149 rzcorners = source.rzcorners;
157 G4UPolyhedra& G4UPolyhedra::operator=(
const G4UPolyhedra &source )
159 if (
this == &source)
return *
this;
161 G4USolid::operator=( source );
162 wrStart = source.wrStart;
163 wrDelta = source.wrDelta;
164 wrNumSide = source.wrNumSide;
165 rzcorners = source.rzcorners;
175 G4int G4UPolyhedra::GetNumSide()
const
179 G4double G4UPolyhedra::GetStartPhi()
const
183 G4double G4UPolyhedra::GetEndPhi()
const
185 return (wrStart + wrDelta);
187 G4double G4UPolyhedra::GetSinStartPhi()
const
190 return std::sin(phi);
192 G4double G4UPolyhedra::GetCosStartPhi()
const
195 return std::cos(phi);
197 G4double G4UPolyhedra::GetSinEndPhi()
const
200 return std::sin(phi);
202 G4double G4UPolyhedra::GetCosEndPhi()
const
205 return std::cos(phi);
207 G4bool G4UPolyhedra::IsOpen()
const
209 return (wrDelta <
twopi);
211 G4bool G4UPolyhedra::IsGeneric()
const
213 return GetShape()->IsGeneric();
215 G4int G4UPolyhedra::GetNumRZCorner()
const
217 return rzcorners.size();
228 UPolyhedraHistorical* pars = GetShape()->GetOriginalParameters();
232 pdata->
numSide = pars->fNumSide;
233 for (
G4int i=0; i<pars->fNumZPlanes; ++i)
235 pdata->
Z_values[i] = pars->fZValues[i];
236 pdata->
Rmin[i] = pars->Rmin[i];
237 pdata->
Rmax[i] = pars->Rmax[i];
243 UPolyhedraHistorical* pdata = GetShape()->GetOriginalParameters();
246 pdata->fNumSide = pars->
numSide;
248 for (
G4int i=0; i<pdata->fNumZPlanes; ++i)
250 pdata->fZValues[i] = pars->
Z_values[i];
251 pdata->Rmin[i] = pars->
Rmin[i];
252 pdata->Rmax[i] = pars->
Rmax[i];
254 fRebuildPolyhedron =
true;
256 wrStart = pdata->fStartAngle;
while (wrStart < 0) wrStart +=
twopi;
257 wrDelta = pdata->fOpeningAngle;
262 wrNumSide = pdata->fNumSide;
263 G4double convertRad = 1./std::cos(0.5*wrDelta/wrNumSide);
265 for (
G4int i=0; i<pdata->fNumZPlanes; ++i)
268 G4double r = pdata->Rmax[i]*convertRad;
271 for (
G4int i=pdata->fNumZPlanes-1; i>=0; --i)
274 G4double r = pdata->Rmin[i]*convertRad;
277 std::vector<G4int> iout;
280 G4bool G4UPolyhedra::Reset()
282 return GetShape()->Reset();
303 G4VSolid* G4UPolyhedra::Clone()
const
305 return new G4UPolyhedra(*
this);
315 static G4bool checkBBox =
true;
316 static G4bool checkPhi =
true;
320 for (
G4int i=0; i<GetNumRZCorner(); ++i)
323 if (corner.
r < rmin) rmin = corner.
r;
324 if (corner.
r > rmax) rmax = corner.
r;
325 if (corner.
z < zmin) zmin = corner.
z;
326 if (corner.
z > zmax) zmax = corner.
z;
332 G4int ksteps = GetNumSide();
339 if (!IsOpen()) rmin = 0;
340 G4double xmin = rmin*cosCur, xmax = xmin;
341 G4double ymin = rmin*sinCur, ymax = ymin;
342 for (
G4int k=0; k<ksteps+1; ++k)
345 if (x < xmin) xmin =
x;
346 if (x > xmax) xmax =
x;
348 if (y < ymin) ymin = y;
349 if (y > ymax) ymax = y;
353 if (xx < xmin) xmin = xx;
354 if (xx > xmax) xmax = xx;
356 if (yy < ymin) ymin = yy;
357 if (yy > ymax) ymax = yy;
360 sinCur = sinCur*cosStep + cosCur*sinStep;
361 cosCur = cosCur*cosStep - sinTmp*sinStep;
363 pMin.
set(xmin,ymin,zmin);
364 pMax.
set(xmax,ymax,zmax);
368 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
370 std::ostringstream message;
371 message <<
"Bad bounding box (min >= max) for solid: "
373 <<
"\npMin = " << pMin
374 <<
"\npMax = " << pMax;
384 GetShape()->Extent(vmin,vmax);
392 std::ostringstream message;
393 message <<
"Inconsistency in bounding boxes for solid: "
395 <<
"\nBBox min: wrapper = " << pMin <<
" solid = " << vmin
396 <<
"\nBBox max: wrapper = " << pMax <<
" solid = " << vmax;
406 if (GetStartPhi() != GetShape()->GetStartPhi() ||
407 GetEndPhi() != GetShape()->GetEndPhi() ||
408 IsOpen() != GetShape()->IsOpen() ||
409 GetNumSide() != GetShape()->GetNumSide())
411 std::ostringstream message;
412 message <<
"Inconsistency in Phi angles or # of sides for solid: "
414 <<
"\nPhi start : wrapper = " << GetStartPhi()
415 <<
" solid = " << GetShape()->GetStartPhi()
416 <<
"\nPhi end : wrapper = " << GetEndPhi()
417 <<
" solid = " << GetShape()->GetEndPhi()
418 <<
"\nPhi is open: wrapper = " << (IsOpen() ?
"true" :
"false")
419 <<
" solid = " << (GetShape()->IsOpen() ?
"true" :
"false")
420 <<
"\nPhi # sides: wrapper = " << GetNumSide()
421 <<
" solid = " << GetShape()->GetNumSide();
433 G4UPolyhedra::CalculateExtent(
const EAxis pAxis,
446 if (
true)
return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
448 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
450 return exist = (pMin < pMax) ?
true :
false;
459 std::vector<G4int> iout;
464 for (
G4int i=0; i<GetNumRZCorner(); ++i)
471 if (area < 0.)
std::reverse(contourRZ.begin(),contourRZ.end());
476 std::ostringstream message;
477 message <<
"Triangulation of RZ contour has failed for solid: "
479 <<
"\nExtent has been calculated using boundary box";
482 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
489 G4int ksteps = GetNumSide();
493 G4double sinStart = GetSinStartPhi();
494 G4double cosStart = GetCosStartPhi();
497 std::vector<const G4ThreeVectorList *> polygons;
498 polygons.resize(ksteps+1);
499 for (
G4int k=0; k<ksteps+1; ++k) {
506 G4int ntria = triangles.size()/3;
507 for (
G4int i=0; i<ntria; ++i)
512 for (
G4int k=0; k<ksteps+1; ++k)
515 G4ThreeVectorList::iterator iter = ptr->begin();
516 iter->set(triangles[i3+0].
x()*cosCur,
517 triangles[i3+0].
x()*sinCur,
518 triangles[i3+0].y());
520 iter->set(triangles[i3+1].
x()*cosCur,
521 triangles[i3+1].
x()*sinCur,
522 triangles[i3+1].y());
524 iter->set(triangles[i3+2].
x()*cosCur,
525 triangles[i3+2].
x()*sinCur,
526 triangles[i3+2].y());
529 sinCur = sinCur*cosStep + cosCur*sinStep;
530 cosCur = cosCur*cosStep - sinTmp*sinStep;
536 if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax))
continue;
537 if (emin < pMin) pMin = emin;
538 if (emax > pMax) pMax =
emax;
539 if (eminlim > pMin && emaxlim < pMax)
break;
542 for (
G4int k=0; k<ksteps+1; ++k) {
delete polygons[k]; polygons[k]=0;}
543 return (pMin < pMax);
558 GetOriginalParameters()->Opening_angle,
559 GetOriginalParameters()->numSide,
560 GetOriginalParameters()->Num_z_planes,
561 GetOriginalParameters()->Z_values,
562 GetOriginalParameters()->Rmin,
563 GetOriginalParameters()->Rmax);
564 delete original_parameters;
595 typedef G4int int4[4];
602 std::vector<G4bool> chopped(GetNumRZCorner(),
false);
603 std::vector<G4int*> triQuads;
604 G4int remaining = GetNumRZCorner();
606 while (remaining >= 3)
611 G4int iStepper = iStarter;
614 if (A < 0) { A = iStepper; }
615 else if (
B < 0) {
B = iStepper; }
616 else if (
C < 0) {
C = iStepper; }
619 if (++iStepper >= GetNumRZCorner()) iStepper = 0;
621 while (chopped[iStepper]);
623 while (
C < 0 && iStepper != iStarter);
628 G4double BAr = GetCorner(A).r - GetCorner(
B).r;
629 G4double BAz = GetCorner(A).z - GetCorner(
B).z;
630 G4double BCr = GetCorner(
C).r - GetCorner(
B).r;
631 G4double BCz = GetCorner(
C).z - GetCorner(
B).z;
638 triQuads.push_back(tq);
646 if (++iStarter >= GetNumRZCorner()) { iStarter = 0; }
648 while (chopped[iStarter]);
653 G4int numSide=GetNumSide();
654 nNodes = (numSide + 1) * GetNumRZCorner();
655 nFaces = numSide * GetNumRZCorner() + 2 * triQuads.size();
656 faces_vec =
new int4[nFaces];
658 G4int addition = GetNumRZCorner() * numSide;
659 G4int d = GetNumRZCorner() - 1;
660 for (
G4int iEnd = 0; iEnd < 2; ++iEnd)
662 for (
size_t i = 0; i < triQuads.size(); ++i)
675 a = triQuads[i][0] + addition;
676 b = triQuads[i][2] + addition;
677 c = triQuads[i][1] + addition;
680 G4int bc = std::abs(c - b);
681 G4int ca = std::abs(a - c);
682 faces_vec[iface][0] = (ab == 1 || ab == d)? a: -a;
683 faces_vec[iface][1] = (bc == 1 || bc == d)? b: -b;
684 faces_vec[iface][2] = (ca == 1 || ca == d)? c: -c;
685 faces_vec[iface][3] = 0;
692 xyz =
new double3[nNodes];
693 const G4double dPhi = (GetEndPhi() - GetStartPhi()) / numSide;
696 for (
G4int iSide = 0; iSide < numSide; ++iSide)
698 for (
G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner)
700 xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi);
701 xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi);
702 xyz[ixyz][2] = GetCorner(iCorner).z;
703 if (iCorner < GetNumRZCorner() - 1)
705 faces_vec[iface][0] = ixyz + 1;
706 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
707 faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2;
708 faces_vec[iface][3] = ixyz + 2;
712 faces_vec[iface][0] = ixyz + 1;
713 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
714 faces_vec[iface][2] = ixyz + 2;
715 faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2;
725 for (
G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner)
727 xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi);
728 xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi);
729 xyz[ixyz][2] = GetCorner(iCorner).z;
735 nNodes = GetNumSide() * GetNumRZCorner();
736 nFaces = GetNumSide() * GetNumRZCorner();;
737 xyz =
new double3[nNodes];
738 faces_vec =
new int4[nFaces];
743 G4int ixyz = 0, iface = 0;
744 for (
G4int iSide = 0; iSide < GetNumSide(); ++iSide)
746 for (
G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner)
748 xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi);
749 xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi);
750 xyz[ixyz][2] = GetCorner(iCorner).z;
751 if (iSide < GetNumSide() - 1)
753 if (iCorner < GetNumRZCorner() - 1)
755 faces_vec[iface][0] = ixyz + 1;
756 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
757 faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2;
758 faces_vec[iface][3] = ixyz + 2;
762 faces_vec[iface][0] = ixyz + 1;
763 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1;
764 faces_vec[iface][2] = ixyz + 2;
765 faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2;
770 if (iCorner < GetNumRZCorner() - 1)
772 faces_vec[iface][0] = ixyz + 1;
773 faces_vec[iface][1] = ixyz + GetNumRZCorner() - nFaces + 1;
774 faces_vec[iface][2] = ixyz + GetNumRZCorner() - nFaces + 2;
775 faces_vec[iface][3] = ixyz + 2;
779 faces_vec[iface][0] = ixyz + 1;
780 faces_vec[iface][1] = ixyz - nFaces + GetNumRZCorner() + 1;
781 faces_vec[iface][2] = ixyz - nFaces + 2;
782 faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2;
797 std::ostringstream message;
798 message <<
"Problem creating G4Polyhedron for: " << GetName();
799 G4Exception(
"G4Polyhedra::CreatePolyhedron()",
"GeomSolids1002",
811 #endif // G4GEOM_USE_USOLIDS
void set(double x, double y, double z)
static const G4double kInfinity
std::vector< ExP01TrackerHit * > a
G4int createPolyhedron(G4int Nnodes, G4int Nfaces, const G4double xyz[][3], const G4int faces[][4])
double B(double temperature)
static constexpr double twopi
G4GLOB_DLL std::ostream G4cout
double A(double temperature)
const G4double kCarTolerance
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
static const G4double emax
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
CLHEP::Hep2Vector G4TwoVector
G4double GetMaxExtent(const EAxis pAxis) const
G4double GetMinExtent(const EAxis pAxis) const