34#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
50G4UPolyhedra::G4UPolyhedra(
const G4String& name,
58 : Base_t(
name, phiStart, phiTotal, numSide,
59 numZPlanes, zPlane, rInner, rOuter)
62 SetOriginalParameters();
69 if (wrDelta <= 0. || wrDelta >= twopi*(1-
DBL_EPSILON))
74 G4double convertRad = 1./std::cos(0.5*wrDelta/wrNumSide);
76 for (
G4int i=0; i<numZPlanes; ++i)
80 rzcorners.emplace_back(r,z);
82 for (
G4int i=numZPlanes-1; i>=0; --i)
86 rzcorners.emplace_back(r,z);
88 std::vector<G4int> iout;
97G4UPolyhedra::G4UPolyhedra(
const G4String& name,
104 : Base_t(
name, phiStart, phiTotal, numSide, numRZ, r, z)
107 SetOriginalParameters();
114 if (wrDelta <= 0. || wrDelta >= twopi*(1-
DBL_EPSILON))
120 for (
G4int i=0; i<numRZ; ++i)
122 rzcorners.emplace_back(r[i],z[i]);
124 std::vector<G4int> iout;
133G4UPolyhedra::G4UPolyhedra(
const G4UPolyhedra& source )
136 fGenericPgon = source.fGenericPgon;
137 fOriginalParameters = source.fOriginalParameters;
138 wrStart = source.wrStart;
139 wrDelta = source.wrDelta;
140 wrNumSide = source.wrNumSide;
141 rzcorners = source.rzcorners;
149G4UPolyhedra& G4UPolyhedra::operator=(
const G4UPolyhedra& source )
151 if (
this == &source)
return *
this;
153 Base_t::operator=( source );
154 fGenericPgon = source.fGenericPgon;
155 fOriginalParameters = source.fOriginalParameters;
156 wrStart = source.wrStart;
157 wrDelta = source.wrDelta;
158 wrNumSide = source.wrNumSide;
159 rzcorners = source.rzcorners;
169G4int G4UPolyhedra::GetNumSide()
const
173G4double G4UPolyhedra::GetStartPhi()
const
177G4double G4UPolyhedra::GetEndPhi()
const
179 return (wrStart + wrDelta);
181G4double G4UPolyhedra::GetSinStartPhi()
const
184 return std::sin(phi);
186G4double G4UPolyhedra::GetCosStartPhi()
const
189 return std::cos(phi);
191G4double G4UPolyhedra::GetSinEndPhi()
const
194 return std::sin(phi);
196G4double G4UPolyhedra::GetCosEndPhi()
const
199 return std::cos(phi);
201G4bool G4UPolyhedra::IsOpen()
const
203 return (wrDelta < twopi);
205G4bool G4UPolyhedra::IsGeneric()
const
209G4int G4UPolyhedra::GetNumRZCorner()
const
211 return rzcorners.size();
224void G4UPolyhedra::SetOriginalParameters()
228 G4int numPlanes = GetZSegmentCount() + 1;
229 G4int numSides = GetSideCount();
231 fOriginalParameters.Start_angle = startPhi;
232 fOriginalParameters.Opening_angle = deltaPhi;
233 fOriginalParameters.Num_z_planes = numPlanes;
234 fOriginalParameters.numSide = numSides;
236 delete [] fOriginalParameters.Z_values;
237 delete [] fOriginalParameters.Rmin;
238 delete [] fOriginalParameters.Rmax;
239 fOriginalParameters.Z_values =
new G4double[numPlanes];
240 fOriginalParameters.Rmin =
new G4double[numPlanes];
241 fOriginalParameters.Rmax =
new G4double[numPlanes];
244 ? 1.0 : std::cos(0.5*deltaPhi/numSides);
245 for (
G4int i=0; i<numPlanes; ++i)
247 fOriginalParameters.Z_values[i] = GetZPlanes()[i];
248 fOriginalParameters.Rmax[i] = GetRMax()[i]/convertRad;
249 fOriginalParameters.Rmin[i] = GetRMin()[i]/convertRad;
254 fOriginalParameters = *pars;
255 fRebuildPolyhedron =
true;
259G4bool G4UPolyhedra::Reset()
263 std::ostringstream message;
264 message <<
"Solid " << GetName() <<
" built using generic construct."
265 <<
G4endl <<
"Not applicable to the generic construct !";
266 G4Exception(
"G4UPolyhedra::Reset()",
"GeomSolids1001",
274 wrStart = fOriginalParameters.Start_angle;
279 wrDelta = fOriginalParameters.Opening_angle;
280 if (wrDelta <= 0. || wrDelta >= twopi*(1-
DBL_EPSILON))
284 wrNumSide = fOriginalParameters.numSide;
286 for (
G4int i=0; i<fOriginalParameters.Num_z_planes; ++i)
288 G4double z = fOriginalParameters.Z_values[i];
289 G4double r = fOriginalParameters.Rmax[i];
290 rzcorners.emplace_back(r,z);
292 for (
G4int i=fOriginalParameters.Num_z_planes-1; i>=0; --i)
294 G4double z = fOriginalParameters.Z_values[i];
295 G4double r = fOriginalParameters.Rmin[i];
296 rzcorners.emplace_back(r,z);
298 std::vector<G4int> iout;
322G4VSolid* G4UPolyhedra::Clone()
const
324 return new G4UPolyhedra(*
this);
335 static G4bool checkBBox =
true;
336 static G4bool checkPhi =
true;
338 G4double rmin = kInfinity, rmax = -kInfinity;
339 G4double zmin = kInfinity, zmax = -kInfinity;
340 for (
G4int i=0; i<GetNumRZCorner(); ++i)
343 if (corner.
r < rmin) rmin = corner.
r;
344 if (corner.
r > rmax) rmax = corner.
r;
345 if (corner.
z < zmin) zmin = corner.
z;
346 if (corner.
z > zmax) zmax = corner.
z;
351 G4double dphi = IsOpen() ? ephi-sphi : twopi;
352 G4int ksteps = GetNumSide();
359 if (!IsOpen()) rmin = 0.;
360 G4double xmin = rmin*cosCur, xmax = xmin;
361 G4double ymin = rmin*sinCur, ymax = ymin;
362 for (
G4int k=0; k<ksteps+1; ++k)
365 if (x < xmin) xmin = x;
366 if (x > xmax) xmax = x;
368 if (y < ymin) ymin = y;
369 if (y > ymax) ymax = y;
373 if (xx < xmin) xmin = xx;
374 if (xx > xmax) xmax = xx;
376 if (yy < ymin) ymin = yy;
377 if (yy > ymax) ymax = yy;
380 sinCur = sinCur*cosStep + cosCur*sinStep;
381 cosCur = cosCur*cosStep - sinTmp*sinStep;
383 pMin.
set(xmin,ymin,zmin);
384 pMax.
set(xmax,ymax,zmax);
388 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
390 std::ostringstream message;
391 message <<
"Bad bounding box (min >= max) for solid: "
393 <<
"\npMin = " << pMin
394 <<
"\npMax = " << pMax;
395 G4Exception(
"G4UPolyhedra::BoundingLimits()",
"GeomMgt0001",
413 std::ostringstream message;
414 message <<
"Inconsistency in bounding boxes for solid: "
416 <<
"\nBBox min: wrapper = " << pMin <<
" solid = " << vmin
417 <<
"\nBBox max: wrapper = " << pMax <<
" solid = " << vmax;
418 G4Exception(
"G4UPolyhedra::BoundingLimits()",
"GeomMgt0001",
428 if (GetStartPhi() != GetPhiStart() ||
429 GetEndPhi() != GetPhiEnd() ||
430 GetNumSide() != GetSideCount() ||
431 IsOpen() != (Base_t::GetPhiDelta() < twopi))
433 std::ostringstream message;
434 message <<
"Inconsistency in Phi angles or # of sides for solid: "
436 <<
"\nPhi start : wrapper = " << GetStartPhi()
437 <<
" solid = " << GetPhiStart()
438 <<
"\nPhi end : wrapper = " << GetEndPhi()
439 <<
" solid = " << GetPhiEnd()
440 <<
"\nPhi # sides: wrapper = " << GetNumSide()
441 <<
" solid = " << GetSideCount()
442 <<
"\nPhi is open: wrapper = " << (IsOpen() ?
"true" :
"false")
444 << ((Base_t::GetPhiDelta() < twopi) ?
"true" :
"false");
445 G4Exception(
"G4UPolyhedra::BoundingLimits()",
"GeomMgt0001",
457G4UPolyhedra::CalculateExtent(
const EAxis pAxis,
467 BoundingLimits(bmin,bmax);
470 if (
true)
return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
472 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
474 return exist = pMin < pMax;
483 std::vector<G4int> iout;
488 for (
G4int i=0; i<GetNumRZCorner(); ++i)
491 contourRZ.emplace_back(corner.
r,corner.
z);
495 if (area < 0.) std::reverse(contourRZ.begin(),contourRZ.end());
500 std::ostringstream message;
501 message <<
"Triangulation of RZ contour has failed for solid: "
503 <<
"\nExtent has been calculated using boundary box";
506 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
512 G4double dphi = IsOpen() ? ephi-sphi : twopi;
513 G4int ksteps = GetNumSide();
517 G4double sinStart = GetSinStartPhi();
518 G4double cosStart = GetCosStartPhi();
521 std::vector<const G4ThreeVectorList *> polygons;
522 polygons.resize(ksteps+1);
523 for (
G4int k=0; k<ksteps+1; ++k)
531 G4int ntria = triangles.size()/3;
532 for (
G4int i=0; i<ntria; ++i)
537 for (
G4int k=0; k<ksteps+1; ++k)
540 auto iter = ptr->begin();
541 iter->set(triangles[i3+0].x()*cosCur,
542 triangles[i3+0].x()*sinCur,
543 triangles[i3+0].y());
545 iter->set(triangles[i3+1].x()*cosCur,
546 triangles[i3+1].x()*sinCur,
547 triangles[i3+1].y());
549 iter->set(triangles[i3+2].x()*cosCur,
550 triangles[i3+2].x()*sinCur,
551 triangles[i3+2].y());
554 sinCur = sinCur*cosStep + cosCur*sinStep;
555 cosCur = cosCur*cosStep - sinTmp*sinStep;
561 if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax))
continue;
562 if (emin < pMin) pMin = emin;
563 if (emax > pMax) pMax = emax;
564 if (eminlim > pMin && emaxlim < pMax)
break;
567 for (
G4int k=0; k<ksteps+1; ++k) {
delete polygons[k]; polygons[k]=
nullptr;}
568 return (pMin < pMax);
580 if (deltaPhi <= 0. || deltaPhi >= twopi*(1-
DBL_EPSILON))
const G4double kCarTolerance
std::vector< G4ThreeVector > G4ThreeVectorList
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
G4GLOB_DLL std::ostream G4cout
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...
G4PolyhedraHistorical is a data structure for use in G4Polyhedra.
G4Polyhedra represents a composed closed polyhedra (PGON) made of planar sizes along the Z axis,...
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 is an abstract base class for solids, physical shapes that can be tracked through....
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMaxExtent(const EAxis pAxis) const
const char * name(G4int ptype)