53 using namespace CLHEP;
63 :
G4VSolid(pName), fpPolyhedron(0), fSurfaceArea(0.), fCubicVolume(0.)
66 if( (pDz <= 0.) || (pR2 <= pR1) || (pR1 < 0.) )
68 std::ostringstream message;
69 message <<
"Invalid dimensions. Negative Input Values or R1>=R2 - "
71 G4Exception(
"G4Paraboloid::G4Paraboloid()",
"GeomSolids0002",
73 "Z half-length must be larger than zero or R1>=R2.");
85 k1 = (r2 * r2 - r1 * r1) / 2 / dz;
86 k2 = (r2 * r2 + r1 * r1) / 2;
95 :
G4VSolid(a), fpPolyhedron(0), fSurfaceArea(0.), fCubicVolume(0.),
96 dz(0.), r1(0.), r2(0.), k1(0.), k2(0.)
114 fSurfaceArea(rhs.fSurfaceArea), fCubicVolume(rhs.fCubicVolume),
115 dz(rhs.dz), r1(rhs.r1), r2(rhs.r2), k1(rhs.k1), k2(rhs.k2)
128 if (
this == &rhs) {
return *
this; }
137 fSurfaceArea = rhs.fSurfaceArea; fCubicVolume = rhs.fCubicVolume;
138 dz = rhs.dz; r1 = rhs.r1; r2 = rhs.r2; k1 = rhs.k1; k2 = rhs.k2;
255 G4bool existsAfterClip=
true;
259 G4int noPolygonVertices=0;
261 = CreateRotatedVertices(pTransform,noPolygonVertices);
269 for(G4ThreeVectorList::iterator it = vertices->begin();
270 it < vertices->end(); it++)
272 if(pMin > (*it)[pAxis]) pMin = (*it)[pAxis];
277 if(pMax < (*it)[pAxis])
288 || pMax < pVoxelLimit.
GetMinExtent(pAxis)) { existsAfterClip =
false; }
294 existsAfterClip =
false;
297 return existsAfterClip;
316 if(A < 0 &&
sqr(A) > rhoSurfTimesTol2)
321 if(std::fabs(p.
z()) > dz - 0.5 * kCarTolerance)
333 else if(A <= 0 ||
sqr(A) < rhoSurfTimesTol2)
406 if(A < 0 &&
sqr(A) > rhoSurfTimesTol2)
413 else if(A <= 0 ||
sqr(A) < rhoSurfTimesTol2)
427 std::ostringstream message;
428 message <<
"No normal defined for this point p." <<
G4endl
429 <<
" p = " << 1 /
mm * p <<
" mm";
430 G4Exception(
"G4Paraboloid::SurfaceNormal(p)",
"GeomSolids1002",
449 if(r2 && p.
z() > - tolh + dz)
456 if(
sqr(p.
x() + v.
x()*intersection)
457 +
sqr(p.
y() + v.
y()*intersection) <
sqr(r2 + 0.5 * kCarTolerance))
459 if(p.
z() < tolh + dz)
462 {
return intersection; }
470 else if(r1 && p.
z() < tolh - dz)
476 G4double intersection = (-dz - p.
z()) / v.
z();
477 if(
sqr(p.
x() + v.
x()*intersection)
478 +
sqr(p.
y() + v.
y()*intersection) <
sqr(r1 + 0.5 * kCarTolerance))
480 if(p.
z() > -tolh - dz)
497 vRho2 = v.
perp2(), intersection,
498 B = (k1 * p.
z() + k2 - rho2) * vRho2;
500 if ( ( (rho2 > paraRho2) && (
sqr(rho2-paraRho2-0.25*tol2) > tol2*paraRho2) )
508 intersection = ((rho2 - k2)/k1 - p.
z())/v.
z();
509 if(intersection < 0) {
return kInfinity; }
510 else if(std::fabs(p.
z() + v.
z() * intersection) <= dz)
525 intersection = (A - std::sqrt(B +
sqr(A))) / vRho2;
530 else if(std::fabs(p.
z() + intersection * v.
z()) < dz + tolh)
540 else if(
sqr(rho2 - paraRho2 - .25 * tol2) <= tol2 * paraRho2)
545 if(normal.dot(v) <= 0)
548 {
return kInfinity; }
552 std::ostringstream message;
559 message <<
"Likely a problem in this function, for solid: " <<
GetName()
562 message <<
" p = " << p * (1/
mm) <<
" mm" <<
G4endl
563 <<
" v = " << v * (1/
mm) <<
" mm";
564 G4Exception(
"G4Paraboloid::DistanceToIn(p,v)",
"GeomSolids1002",
578 if(safz<0) { safz=0; }
588 if(safr>safz) { safz=safr; }
592 G4double sqprho = std::sqrt(paraRho);
594 if(dRho<0) {
return safz; }
598 if(tmp<0.) {
return safz; }
600 G4double salf = talf/std::sqrt(tmp);
601 safr = std::fabs(dRho*salf);
602 if(safr>safz) { safz=safr; }
622 if(calcNorm) { *validNorm =
false; }
636 G4double B = (-rho2 + paraRho2) * vRho2;
638 if ( rho2 < paraRho2 &&
sqr(rho2 - paraRho2 - 0.25 * tol2) > tol2 * paraRho2
639 && std::fabs(p.
z()) < dz - kCarTolerance)
650 intersection = (dz - p.
z()) / v.
z();
653 if(ip.
perp2() <
sqr(r2 + kCarTolerance))
658 if(r2 < tolh || ip.
perp2() >
sqr(r2 - tolh))
675 intersection = (-dz - p.
z()) / v.
z();
683 if(r1 < tolh || ip.
perp2() >
sqr(r1 - tolh))
698 intersection = ((rho2 - k2)/k1 - p.
z())/v.
z();
709 else if( ((A <= 0) && (B >=
sqr(A) * (
sqr(vRho2) - 1))) || (A >= 0))
716 B = (k1 * p.
z() + k2 - rho2)/vRho2;
717 intersection = B/(-A + std::sqrt(B +
sqr(A)));
727 std::ostringstream message;
728 message <<
"There is no intersection between given line and solid!"
732 G4Exception(
"G4Paraboloid::DistanceToOut(p,v,...)",
"GeomSolids1002",
737 else if ( (rho2 < paraRho2 + kCarTolerance
738 ||
sqr(rho2 - paraRho2 - 0.25 * tol2) < tol2 * paraRho2 )
739 && std::fabs(p.
z()) < dz + tolh)
745 if(std::fabs(p.
z()) > dz - tolh)
749 if( ((v.
z() > 0) && (p.
z() > 0)) || ((v.
z() < 0) && (p.
z() < 0)) )
771 intersection = (-pDotV + std::sqrt(A +
sqr(pDotV))) / vRho2;
779 * intersection, -k1/2).unit()).unit();
809 intersection = (dz - p.
z()) / v.
z();
821 else if(ip.
perp2() <
sqr(r2 + tolh))
837 intersection = (-dz - p.
z()) / v.
z();
849 else if(ip.
perp2() <
sqr(r1 + tolh))
864 if(std::fabs(vRho2) > tol2)
867 B = (k1 * p.
z() + k2 - rho2);
871 intersection = B/(-A + std::sqrt(B +
sqr(A)));
875 if(normal.
dot(v) >= 0)
889 intersection = ((rho2 - k2) / k1 - p.
z()) / v.
z();
896 + intersection * v.
y(), - k1 / 2);
906 G4Exception(
"G4Paraboloid::DistanceToOut(p,v,...)",
"GeomSolids1002",
910 G4Exception(
"G4Paraboloid::DistanceToOut(p,v,...)",
"GeomSolids1002",
911 JustWarning,
"There's an error in this functions code.");
932 std::ostringstream message;
933 G4int oldprc = message.precision(16);
934 message <<
"Point p is outside !?" << G4endl
935 <<
"Position:" << G4endl
936 <<
" p.x() = " << p.
x()/
mm <<
" mm" << G4endl
937 <<
" p.y() = " << p.
y()/
mm <<
" mm" << G4endl
938 <<
" p.z() = " << p.
z()/
mm <<
" mm";
939 message.precision(oldprc) ;
940 G4Exception(
"G4Paraboloid::DistanceToOut(p)",
"GeomSolids1002",
946 safeZ = dz - std::fabs(p.
z()) ;
948 tanRMax = (r2 - r1)*0.5/dz ;
949 secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
950 pRMax = tanRMax*p.
z() + (r1+r2)*0.5 ;
951 safeR = (pRMax - rho)/secRMax ;
953 if (safeZ < safeR) { safe = safeZ; }
954 else { safe = safeR; }
983 G4int oldprc = os.precision(16);
984 os <<
"-----------------------------------------------------------\n"
985 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
986 <<
" ===================================================\n"
987 <<
" Solid type: G4Paraboloid\n"
989 <<
" z half-axis: " << dz/
mm <<
" mm \n"
990 <<
" radius at -dz: " << r1/
mm <<
" mm \n"
991 <<
" radius at dz: " << r2/
mm <<
" mm \n"
992 <<
"-----------------------------------------------------------\n";
993 os.precision(oldprc);
1010 if(
pi *
sqr(r1) / A > z)
1012 rho = r1 * std::sqrt(RandFlat::shoot(0., 1.));
1013 return G4ThreeVector(rho * std::cos(phi), rho * std::sin(phi), -dz);
1017 rho = r2 * std::sqrt(RandFlat::shoot(0., 1));
1018 return G4ThreeVector(rho * std::cos(phi), rho * std::sin(phi), dz);
1023 z = RandFlat::shoot(0., 1.)*2*dz - dz;
1025 std::sqrt(z*k1 + k2)*std::sin(phi), z);
1031 G4int& noPolygonVertices)
const
1035 G4double meshAnglePhi, cosMeshAnglePhiPer2,
1036 crossAnglePhi, coscrossAnglePhi, sincrossAnglePhi, sAnglePhi,
1037 sRho, dRho, rho, lastRho = 0., swapRho;
1039 G4int crossSectionPhi, noPhiCrossSections, noRhoSections;
1054 meshAnglePhi=
twopi/(noPhiCrossSections-1);
1056 sAnglePhi = -meshAnglePhi*0.5*0;
1057 cosMeshAnglePhiPer2 = std::cos(meshAnglePhi / 2.);
1073 dRho = (r2 - r1) /
double(noRhoSections - 1);
1079 for (crossSectionPhi=0; crossSectionPhi<noPhiCrossSections;
1082 crossAnglePhi=sAnglePhi+crossSectionPhi*meshAnglePhi;
1083 coscrossAnglePhi=std::cos(crossAnglePhi);
1084 sincrossAnglePhi=std::sin(crossAnglePhi);
1086 for (
int iRho=0; iRho < noRhoSections;
1091 if(iRho == noRhoSections - 1)
1097 rho = iRho * dRho + sRho;
1102 k3 = k1 / (2*rho + dRho);
1103 k4 = rho - k3 * (
sqr(rho) - k2) / k1;
1104 zm = (
sqr(k1 / (2 * k3)) - k2) / k1;
1105 rho += std::sqrt(k1 * zm + k2) - zm * k3 - k4;
1108 rho += (1 / cosMeshAnglePhiPer2 - 1) * (iRho * dRho + sRho);
1113 lastRho = rho + dRho;
1118 lastRho = rho + dRho;
1121 rx = coscrossAnglePhi*rho;
1122 ry = sincrossAnglePhi*rho;
1123 rz = (
sqr(iRho * dRho + sRho) - k2) / k1;
1128 noPolygonVertices = noRhoSections ;
1133 G4Exception(
"G4Paraboloid::CreateRotatedVertices()",
1135 "Error in allocation of vertices. Out of memory !");