34 #if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
42 using namespace CLHEP;
58 : Base_t(name, phiStart, phiTotal, numSide,
59 numZPlanes, zPlane, rInner, rOuter)
62 SetOriginalParameters();
74 G4double convertRad = 1./std::cos(0.5*wrDelta/wrNumSide);
76 for (
G4int i=0; i<numZPlanes; ++i)
82 for (
G4int i=numZPlanes-1; i>=0; --i)
88 std::vector<G4int> iout;
97 G4UPolyhedra::G4UPolyhedra(
const G4String& name,
104 : Base_t(name, phiStart, phiTotal, numSide, numRZ, r, z)
107 SetOriginalParameters();
119 G4double convertRad = 1./std::cos(0.5*wrDelta/wrNumSide);
121 for (
G4int i=0; i<numRZ; ++i)
123 rzcorners.push_back(
G4TwoVector(r[i]*convertRad,z[i]));
125 std::vector<G4int> iout;
135 G4UPolyhedra::G4UPolyhedra( __void__&
a )
145 G4UPolyhedra::~G4UPolyhedra()
154 G4UPolyhedra::G4UPolyhedra(
const G4UPolyhedra& source )
157 fGenericPgon = source.fGenericPgon;
158 fOriginalParameters = source.fOriginalParameters;
159 wrStart = source.wrStart;
160 wrDelta = source.wrDelta;
161 wrNumSide = source.wrNumSide;
162 rzcorners = source.rzcorners;
170 G4UPolyhedra& G4UPolyhedra::operator=(
const G4UPolyhedra& source )
172 if (
this == &source)
return *
this;
174 Base_t::operator=( source );
175 fGenericPgon = source.fGenericPgon;
176 fOriginalParameters = source.fOriginalParameters;
177 wrStart = source.wrStart;
178 wrDelta = source.wrDelta;
179 wrNumSide = source.wrNumSide;
180 rzcorners = source.rzcorners;
190 G4int G4UPolyhedra::GetNumSide()
const
194 G4double G4UPolyhedra::GetStartPhi()
const
198 G4double G4UPolyhedra::GetEndPhi()
const
200 return (wrStart + wrDelta);
202 G4double G4UPolyhedra::GetSinStartPhi()
const
205 return std::sin(phi);
207 G4double G4UPolyhedra::GetCosStartPhi()
const
210 return std::cos(phi);
212 G4double G4UPolyhedra::GetSinEndPhi()
const
215 return std::sin(phi);
217 G4double G4UPolyhedra::GetCosEndPhi()
const
220 return std::cos(phi);
222 G4bool G4UPolyhedra::IsOpen()
const
224 return (wrDelta <
twopi);
226 G4bool G4UPolyhedra::IsGeneric()
const
230 G4int G4UPolyhedra::GetNumRZCorner()
const
232 return rzcorners.size();
245 void G4UPolyhedra::SetOriginalParameters()
249 G4int numPlanes = GetZSegmentCount() + 1;
250 G4int numSides = GetSideCount();
252 fOriginalParameters.Start_angle = startPhi;
253 fOriginalParameters.Opening_angle = deltaPhi;
254 fOriginalParameters.Num_z_planes = numPlanes;
255 fOriginalParameters.numSide = numSides;
257 delete [] fOriginalParameters.Z_values;
258 delete [] fOriginalParameters.Rmin;
259 delete [] fOriginalParameters.Rmax;
260 fOriginalParameters.Z_values =
new G4double[numPlanes];
261 fOriginalParameters.Rmin =
new G4double[numPlanes];
262 fOriginalParameters.Rmax =
new G4double[numPlanes];
264 G4double convertRad = std::cos(0.5*deltaPhi/numSides);
265 for (
G4int i=0; i<numPlanes; ++i)
267 fOriginalParameters.Z_values[i] = GetZPlanes()[i];
268 fOriginalParameters.Rmax[i] = GetRMax()[i]/convertRad;
269 fOriginalParameters.Rmin[i] = GetRMin()[i]/convertRad;
274 fOriginalParameters = *pars;
275 fRebuildPolyhedron =
true;
284 message <<
"Solid " << GetName() <<
" built using generic construct."
285 <<
G4endl <<
"Not applicable to the generic construct !";
286 G4Exception(
"G4UPolyhedra::Reset()",
"GeomSolids1001",
294 wrStart = fOriginalParameters.Start_angle;
299 wrDelta = fOriginalParameters.Opening_angle;
304 wrNumSide = fOriginalParameters.numSide;
306 for (
G4int i=0; i<fOriginalParameters.Num_z_planes; ++i)
308 G4double z = fOriginalParameters.Z_values[i];
309 G4double r = fOriginalParameters.Rmax[i];
312 for (
G4int i=fOriginalParameters.Num_z_planes-1; i>=0; --i)
314 G4double z = fOriginalParameters.Z_values[i];
315 G4double r = fOriginalParameters.Rmin[i];
318 std::vector<G4int> iout;
342 G4VSolid* G4UPolyhedra::Clone()
const
344 return new G4UPolyhedra(*
this);
355 static G4bool checkBBox =
true;
356 static G4bool checkPhi =
true;
360 for (
G4int i=0; i<GetNumRZCorner(); ++i)
363 if (corner.
r < rmin) rmin = corner.
r;
364 if (corner.
r > rmax) rmax = corner.
r;
365 if (corner.
z < zmin) zmin = corner.
z;
366 if (corner.
z > zmax) zmax = corner.
z;
372 G4int ksteps = GetNumSide();
379 if (!IsOpen()) rmin = 0.;
385 if (x < xmin) xmin =
x;
386 if (x > xmax) xmax =
x;
388 if (y < ymin) ymin =
y;
389 if (y > ymax) ymax =
y;
393 if (xx < xmin) xmin =
xx;
394 if (xx > xmax) xmax =
xx;
396 if (yy < ymin) ymin = yy;
397 if (yy > ymax) ymax = yy;
400 sinCur = sinCur*cosStep + cosCur*sinStep;
401 cosCur = cosCur*cosStep - sinTmp*sinStep;
403 pMin.
set(xmin,ymin,zmin);
404 pMax.
set(xmax,ymax,zmax);
408 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
411 message <<
"Bad bounding box (min >= max) for solid: "
413 <<
"\npMin = " << pMin
414 <<
"\npMax = " <<
pMax;
415 G4Exception(
"G4UPolyhedra::BoundingLimits()",
"GeomMgt0001",
434 message <<
"Inconsistency in bounding boxes for solid: "
436 <<
"\nBBox min: wrapper = " << pMin <<
" solid = " << vmin
437 <<
"\nBBox max: wrapper = " << pMax <<
" solid = " << vmax;
438 G4Exception(
"G4UPolyhedra::BoundingLimits()",
"GeomMgt0001",
448 if (GetStartPhi() != GetPhiStart() ||
449 GetEndPhi() != GetPhiEnd() ||
450 GetNumSide() != GetSideCount() ||
451 IsOpen() != (Base_t::GetPhiDelta() <
twopi))
454 message <<
"Inconsistency in Phi angles or # of sides for solid: "
456 <<
"\nPhi start : wrapper = " << GetStartPhi()
457 <<
" solid = " << GetPhiStart()
458 <<
"\nPhi end : wrapper = " << GetEndPhi()
459 <<
" solid = " << GetPhiEnd()
460 <<
"\nPhi # sides: wrapper = " << GetNumSide()
461 <<
" solid = " << GetSideCount()
462 <<
"\nPhi is open: wrapper = " << (IsOpen() ?
"true" :
"false")
464 << ((Base_t::GetPhiDelta() <
twopi) ?
"true" :
"false");
465 G4Exception(
"G4UPolyhedra::BoundingLimits()",
"GeomMgt0001",
477 G4UPolyhedra::CalculateExtent(
const EAxis pAxis,
487 BoundingLimits(bmin,bmax);
490 if (
true)
return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
492 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
494 return exist = (pMin <
pMax) ?
true :
false;
503 std::vector<G4int> iout;
508 for (
G4int i=0; i<GetNumRZCorner(); ++i)
515 if (area < 0.)
std::reverse(contourRZ.begin(),contourRZ.end());
521 message <<
"Triangulation of RZ contour has failed for solid: "
523 <<
"\nExtent has been calculated using boundary box";
526 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
533 G4int ksteps = GetNumSide();
537 G4double sinStart = GetSinStartPhi();
538 G4double cosStart = GetCosStartPhi();
541 std::vector<const G4ThreeVectorList *> polygons;
542 polygons.resize(ksteps+1);
551 G4int ntria = triangles.size()/3;
552 for (
G4int i=0; i<ntria; ++i)
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];
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;
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;
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