36#if !(defined(G4GEOM_USE_UHYPE) && defined(G4GEOM_USE_SYS_USOLIDS))
79 std::ostringstream message;
81 <<
" Invalid Z half-length: "
82 << newHalfLenZ/mm <<
" mm";
90 if (newInnerRadius<0 || newOuterRadius<0)
92 std::ostringstream message;
94 <<
" Invalid radii ! Inner radius: "
95 << newInnerRadius/mm <<
" mm" <<
G4endl
97 << newOuterRadius/mm <<
" mm";
101 if (newInnerRadius >= newOuterRadius)
103 std::ostringstream message;
105 <<
" Invalid radii ! Inner radius: "
106 << newInnerRadius/mm <<
" mm" <<
G4endl
108 << newOuterRadius/mm <<
" mm";
127 :
G4VSolid(a), innerRadius(0.), outerRadius(0.), halfLenZ(0.), innerStereo(0.),
128 outerStereo(0.), tanInnerStereo(0.), tanOuterStereo(0.), tanInnerStereo2(0.),
129 tanOuterStereo2(0.), innerRadius2(0.), outerRadius2(0.), endInnerRadius2(0.),
130 endOuterRadius2(0.), endInnerRadius(0.), endOuterRadius(0.), fHalfTol(0.)
138 delete fpPolyhedron; fpPolyhedron =
nullptr;
144 :
G4VSolid(rhs), innerRadius(rhs.innerRadius),
145 outerRadius(rhs.outerRadius), halfLenZ(rhs.halfLenZ),
146 innerStereo(rhs.innerStereo), outerStereo(rhs.outerStereo),
147 tanInnerStereo(rhs.tanInnerStereo), tanOuterStereo(rhs.tanOuterStereo),
148 tanInnerStereo2(rhs.tanInnerStereo2), tanOuterStereo2(rhs.tanOuterStereo2),
149 innerRadius2(rhs.innerRadius2), outerRadius2(rhs.outerRadius2),
150 endInnerRadius2(rhs.endInnerRadius2), endOuterRadius2(rhs.endOuterRadius2),
151 endInnerRadius(rhs.endInnerRadius), endOuterRadius(rhs.endOuterRadius),
152 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
153 fHalfTol(rhs.fHalfTol)
163 if (
this == &rhs) {
return *
this; }
179 fCubicVolume = rhs.fCubicVolume; fSurfaceArea = rhs.fSurfaceArea;
180 fHalfTol = rhs.fHalfTol;
181 fRebuildPolyhedron =
false;
182 delete fpPolyhedron; fpPolyhedron =
nullptr;
206 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
208 std::ostringstream message;
209 message <<
"Bad bounding box (min >= max) for solid: "
211 <<
"\npMin = " << pMin
212 <<
"\npMax = " << pMax;
213 G4Exception(
"G4Hype::BoundingLimits()",
"GeomMgt0001",
297 if (dist2Inner < dist2Z && dist2Inner < dist2Outer)
304 if (dist2Z < dist2Outer)
305 return { 0.0, 0.0, (
G4double)(p.
z() < 0 ? -1.0 : 1.0) };
355 G4bool couldMissOuter(
true),
356 couldMissInner(
true),
357 cantMissInnerCylinder(
false);
364 if (sigz > -fHalfTol)
376 if (sigz > 0)
return kInfinity;
407 yi = p.
y() + q*v.
y();
435 cantMissInnerCylinder =
true;
440 return (sigz < fHalfTol) ? 0 : q;
501 for(
G4int i=0; i<n; ++i )
513 if (zi > +
halfLenZ && couldMissOuter)
continue;
519 yi = p.
y() + q[i]*v.
y();
537 if (cantMissInnerCylinder)
return (sigz < fHalfTol) ? 0 : -sigz/vz;
562 for(
G4int i=0; i<n; ++i )
564 if (q[i] > best)
break;
575 if (zi > +
halfLenZ && couldMissInner)
continue;
581 yi = p.
y() + q[i]*v.
y();
628 if (sigz > -fHalfTol)
633 return sigz < fHalfTol ? 0 : sigz;
641 G4double answer = std::sqrt( dr*dr + sigz*sigz );
642 return answer < fHalfTol ? 0 : answer;
650 return sigz < fHalfTol ? 0 : sigz;
662 G4double answer = std::sqrt( dr*dr + sigz*sigz );
663 return answer < fHalfTol ? 0 : answer;
675 return answer < fHalfTol ? 0 : answer;
683 return answer < fHalfTol ? 0 : answer;
728 if (calcNorm) { *norm = *nBest; *validNorm =
true; }
760 if (normHere.
dot(v) > 0)
762 if (calcNorm) { *norm = normHere.
unit(); *validNorm =
false; }
770 for(
G4int i=0; i<n; ++i )
772 if (q[i] > sBest)
break;
781 if (norm1.
dot(v) > 0)
807 if (normHere.
dot(v) > 0)
811 *norm = normHere.
unit();
821 for(
G4int i=0; i<n; ++i )
823 if (q[i] > sBest)
break;
828 if (norm2.
dot(v) > 0)
847 if (nBest == &norm1 || nBest == &norm2)
848 *norm = nBest->
unit();
871 if (tryOuter < sBest)
877 if (tryInner < sBest) sBest = tryInner;
927 G4double a = tx*tx + ty*ty - tz*tz*tan2Phi;
928 G4double b = 2*( x0*tx + y0*ty - z0*tz*tan2Phi );
929 G4double c = x0*x0 + y0*y0 - r2 - z0*z0*tan2Phi;
937 if (std::fabs(b) <
DBL_MIN)
return 0;
946 if (radical < -
DBL_MIN)
return 0;
957 radical = std::sqrt(radical);
959 G4double q = -0.5*( b + (b < 0 ? -radical : +radical) );
962 if (sa < sb) { ss[0] = sa; ss[1] = sb; }
else { ss[0] = sb; ss[1] = sa; }
989 if (tanPhi <
DBL_MIN)
return pr-r0;
997 G4double r1 = std::sqrt( r0*r0 + z1*z1*tan2Phi );
1002 G4double z2 = (pr*tanPhi + pz)/(1 + tan2Phi);
1003 G4double r2 = std::sqrt( r0*r0 + z2*z2*tan2Phi );
1011 G4double len = std::sqrt(dr*dr + dz*dz);
1020 return std::sqrt( dr*dr + dz*dz );
1026 return std::fabs((pr-r1)*dz - (pz-z1)*dr)/len;
1046 if (tan2Phi <
DBL_MIN)
return r0 - pr;
1051 G4double rh = std::sqrt( r0*r0 + pz*pz*tan2Phi );
1055 G4double len = std::sqrt(dr*dr + dz*dz);
1060 return std::fabs((pr-rh)*dr)/len;
1074 return new G4Hype(*
this);
1083 if (fCubicVolume == 0.)
1085 fCubicVolume = CLHEP::twopi*
halfLenZ*
1088 return fCubicVolume;
1095 if (fSurfaceArea == 0.)
1105 G4double K = std::sqrt(AA + CC)/CC;
1107 innS =
A*(h*std::sqrt(1. + Kh*Kh) + std::asinh(Kh)/K);
1116 G4double K = std::sqrt(AA + CC)/CC;
1118 outS =
A*(h*std::sqrt(1. + Kh*Kh) + std::asinh(Kh)/K);
1122 return fSurfaceArea;
1129 G4long oldprc = os.precision(16);
1130 os <<
"-----------------------------------------------------------\n"
1131 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1132 <<
" ===================================================\n"
1133 <<
" Solid type: G4Hype\n"
1134 <<
" Parameters: \n"
1135 <<
" half length Z: " <<
halfLenZ/mm <<
" mm \n"
1136 <<
" inner radius : " <<
innerRadius/mm <<
" mm \n"
1137 <<
" outer radius : " <<
outerRadius/mm <<
" mm \n"
1138 <<
" inner stereo angle : " <<
innerStereo/degree <<
" degrees \n"
1139 <<
" outer stereo angle : " <<
outerStereo/degree <<
" degrees \n"
1140 <<
"-----------------------------------------------------------\n";
1141 os.precision(oldprc);
1150 G4double xRand, yRand, zRand, r2 , aOne, aTwo, aThree, chose, sinhu;
1151 G4double phi, cosphi, sinphi, rBar2Out, rBar2In, alpha, t, rOut, rIn2, rOut2;
1160 t = std::log(t+std::sqrt(
sqr(t)+1));
1161 aOne = std::fabs(2.*alpha*(std::sinh(2.*t)/4.+t/2.));
1167 t = std::log(t+std::sqrt(
sqr(t)+1));
1168 aTwo = std::fabs(2.*alpha*(std::sinh(2.*t)/4.+t/2.));
1176 phi = G4RandFlat::shoot(0.,2.*pi);
1177 cosphi = std::cos(phi);
1178 sinphi = std::sin(phi);
1182 chose = G4RandFlat::shoot(0.,aOne+aTwo+2.*aThree);
1183 if(chose>=0. && chose < aOne)
1190 return { xRand, yRand, zRand };
1198 else if(chose>=aOne && chose<aOne+aTwo)
1207 return { xRand, yRand, zRand };
1215 else if(chose>=aOne+aTwo && chose<aOne+aTwo+aThree)
1219 rOut = std::sqrt(rOut2) ;
1223 xRand = G4RandFlat::shoot(-rOut,rOut) ;
1224 yRand = G4RandFlat::shoot(-rOut,rOut) ;
1225 r2 = xRand*xRand + yRand*yRand ;
1226 }
while ( r2 < rIn2 || r2 > rOut2 ) ;
1229 return { xRand, yRand, zRand };
1235 rOut = std::sqrt(rOut2) ;
1239 xRand = G4RandFlat::shoot(-rOut,rOut) ;
1240 yRand = G4RandFlat::shoot(-rOut,rOut) ;
1241 r2 = xRand*xRand + yRand*yRand ;
1242 }
while ( r2 < rIn2 || r2 > rOut2 ) ;
1245 return { xRand, yRand, zRand };
1279 if (fpPolyhedron ==
nullptr ||
1280 fRebuildPolyhedron ||
1285 delete fpPolyhedron;
1287 fRebuildPolyhedron =
false;
1290 return fpPolyhedron;
1297 return std::log(arg+std::sqrt(
sqr(arg)+1));
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
double dot(const Hep3Vector &) const
void set(double x, double y, double z)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep) override
G4Hype(const G4String &pName, G4double newInnerRadius, G4double newOuterRadius, G4double newInnerStereo, G4double newOuterStereo, G4double newHalfLenZ)
EInside Inside(const G4ThreeVector &p) const override
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
G4GeometryType GetEntityType() const override
static G4int IntersectHype(const G4ThreeVector &p, const G4ThreeVector &v, G4double r2, G4double tan2Phi, G4double s[2])
G4Hype & operator=(const G4Hype &rhs)
G4VisExtent GetExtent() const override
static G4double ApproxDistOutside(G4double pr, G4double pz, G4double r0, G4double tanPhi)
G4VSolid * Clone() const override
void SetOuterStereo(G4double newOSte)
G4Polyhedron * CreatePolyhedron() const override
G4ThreeVector GetPointOnSurface() const override
G4Polyhedron * GetPolyhedron() const override
G4bool InnerSurfaceExists() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const override
G4double GetSurfaceArea() override
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
G4double HypeOuterRadius2(G4double zVal) const
std::ostream & StreamInfo(std::ostream &os) const override
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
static G4double ApproxDistInside(G4double pr, G4double pz, G4double r0, G4double tan2Phi)
G4double HypeInnerRadius2(G4double zVal) const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
void SetInnerStereo(G4double newISte)
G4double GetCubicVolume() override
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
virtual void AddSolid(const G4Box &)=0
virtual void ComputeDimensions(G4Box &, const G4int, const G4VPhysicalVolume *) const
G4VSolid & operator=(const G4VSolid &rhs)
static G4int GetNumberOfRotationSteps()