31 double pRMin,
double pRMax,
33 double pSPhi,
double pDPhi)
34 :
VUSolid(pName.c_str()), fRMin(pRMin), fRMax(pRMax), fDz(pDz), fSPhi(0), fDPhi(0)
43 std::ostringstream message;
44 message <<
"Negative Z half-length (" << pDz <<
") in solid: " <<
GetName();
47 if ((pRMin >= pRMax) || (pRMin < 0))
49 std::ostringstream message;
50 message <<
"Invalid values for radii in solid: " <<
GetName()
52 <<
"pRMin = " << pRMin <<
", pRMax = " << pRMax;
67 :
VUSolid(
""), fCubicVolume(0.), fSurfaceArea(0.),
68 kRadTolerance(0.), kAngTolerance(0.),
69 fRMin(0.), fRMax(0.), fDz(0.), fSPhi(0.), fDPhi(0.),
70 fSinCPhi(0.), fCosCPhi(0.), fCosHDPhiOT(0.), fCosHDPhiIT(0.),
71 fSinSPhi(0.), fCosSPhi(0.), fSinEPhi(0.), fCosEPhi(0.),
72 fSinSPhiDPhi(0.), fCosSPhiDPhi(0.),
91 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
92 kRadTolerance(rhs.kRadTolerance), kAngTolerance(rhs.kAngTolerance),
93 fRMin(rhs.fRMin), fRMax(rhs.fRMax), fDz(rhs.fDz),
94 fSPhi(rhs.fSPhi), fDPhi(rhs.fDPhi),
95 fSinCPhi(rhs.fSinCPhi), fCosCPhi(rhs.fSinCPhi),
96 fCosHDPhiOT(rhs.fCosHDPhiOT), fCosHDPhiIT(rhs.fCosHDPhiOT),
97 fSinSPhi(rhs.fSinSPhi), fCosSPhi(rhs.fCosSPhi),
98 fSinEPhi(rhs.fSinEPhi), fCosEPhi(rhs.fCosEPhi),
99 fSinSPhiDPhi(rhs.fSinSPhiDPhi), fCosSPhiDPhi(rhs.fCosSPhiDPhi),
100 fPhiFullTube(rhs.fPhiFullTube)
119 VUSolid::operator=(rhs);
155 double r2, pPhi, tolRMin, tolRMax;
161 if (std::fabs(p.
z) <=
fDz - halfCarTolerance)
163 r2 = p.
x * p.
x + p.
y * p.
y;
167 tolRMin =
fRMin + halfRadTolerance;
174 tolRMax =
fRMax - halfRadTolerance;
176 if ((r2 >= tolRMin * tolRMin) && (r2 <= tolRMax * tolRMax))
187 if ((tolRMin == 0) && (std::fabs(p.
x) <= halfCarTolerance)
188 && (std::fabs(p.
y) <= halfCarTolerance))
194 pPhi = std::atan2(p.
y, p.
x);
195 if (pPhi < -halfAngTolerance)
202 if ((std::fabs(pPhi) < halfAngTolerance)
207 if ((pPhi >=
fSPhi + halfAngTolerance)
208 && (pPhi <=
fSPhi +
fDPhi - halfAngTolerance))
212 else if ((pPhi >=
fSPhi - halfAngTolerance)
213 && (pPhi <=
fSPhi +
fDPhi + halfAngTolerance))
221 && (pPhi >=
fSPhi +
fDPhi + halfAngTolerance))
226 && (pPhi >=
fSPhi +
fDPhi - halfAngTolerance))
240 tolRMin =
fRMin - halfRadTolerance;
241 tolRMax =
fRMax + halfRadTolerance;
248 if ((r2 >= tolRMin * tolRMin) && (r2 <= tolRMax * tolRMax))
250 if (
fPhiFullTube || (r2 <= halfRadTolerance * halfRadTolerance))
257 pPhi = std::atan2(p.
y, p.
x);
259 if (pPhi < -halfAngTolerance)
265 if ((std::fabs(pPhi) < halfAngTolerance)
270 if ((pPhi >=
fSPhi - halfAngTolerance)
271 && (pPhi <=
fSPhi +
fDPhi + halfAngTolerance))
279 && (pPhi >=
fSPhi +
fDPhi + halfAngTolerance))
292 else if (std::fabs(p.
z) <=
fDz + halfCarTolerance)
295 r2 = p.
x * p.
x + p.
y * p.
y;
296 tolRMin =
fRMin - halfRadTolerance;
297 tolRMax =
fRMax + halfRadTolerance;
304 if ((r2 >= tolRMin * tolRMin) && (r2 <= tolRMax * tolRMax))
306 if (
fPhiFullTube || (r2 <= halfRadTolerance * halfRadTolerance))
313 pPhi = std::atan2(p.
y, p.
x);
315 if (pPhi < -halfAngTolerance)
321 if ((std::fabs(pPhi) < halfAngTolerance)
326 if ((pPhi >=
fSPhi - halfAngTolerance)
327 && (pPhi <=
fSPhi +
fDPhi + halfAngTolerance))
335 && (pPhi >=
fSPhi +
fDPhi + halfAngTolerance))
360 double distZ, distRMin, distRMax;
370 rho = std::sqrt(p.
x * p.
x + p.
y * p.
y);
372 distRMin = std::fabs(rho -
fRMin);
373 distRMax = std::fabs(rho -
fRMax);
374 distZ = std::fabs(std::fabs(p.
z) -
fDz);
378 if (rho > halfCarTolerance)
380 pPhi = std::atan2(p.
y, p.
x);
382 if (pPhi <
fSPhi - halfCarTolerance)
386 else if (pPhi >
fSPhi +
fDPhi + halfCarTolerance)
391 distSPhi = std::fabs(pPhi -
fSPhi);
402 if (rho > halfCarTolerance)
407 if (distRMax <= halfCarTolerance)
412 if (
fRMin && (distRMin <= halfCarTolerance))
419 if (distSPhi <= halfAngTolerance)
424 if (distEPhi <= halfAngTolerance)
430 if (distZ <= halfCarTolerance)
446 Warning, 1,
"Point p is not on surface !?");
447 int oldprc = cout.precision(20);
448 cout <<
"UTubs::SN ( " << p.
x <<
", " << p.
y <<
", " << p.
z <<
" ); "
449 << std::endl << std::endl;
450 cout.precision(oldprc);
454 else if (noSurfaces == 1)
460 norm = sumnorm.
Unit();
478 double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin;
480 rho = std::sqrt(p.
x * p.
x + p.
y * p.
y);
482 distRMin = std::fabs(rho -
fRMin);
483 distRMax = std::fabs(rho -
fRMax);
484 distZ = std::fabs(std::fabs(p.
z) -
fDz);
486 if (distRMin < distRMax)
488 if (distZ < distRMin)
501 if (distZ < distRMax)
514 phi = std::atan2(p.
y, p.
x);
527 distSPhi = std::fabs(phi -
fSPhi) * rho;
529 distEPhi = std::fabs(phi -
fSPhi -
fDPhi) * rho;
531 if (distSPhi < distEPhi)
533 if (distSPhi < distMin)
540 if (distEPhi < distMin)
585 "Undefined side for valid surface normal to solid.");
617 double tolORMin2, tolIRMax2;
618 double tolORMax2, tolIRMin2, tolODz, tolIDz;
619 const double dRmax = 100.*
fRMax;
626 double Dist, sd, xi, yi, zi, rho2, inum, iden, cosPsi, Comp;
627 double t1, t2, t3, b, c, d;
633 tolORMin2 = (
fRMin - halfRadTolerance) * (
fRMin - halfRadTolerance);
634 tolIRMin2 = (
fRMin + halfRadTolerance) * (
fRMin + halfRadTolerance);
641 tolORMax2 = (
fRMax + halfRadTolerance) * (
fRMax + halfRadTolerance);
642 tolIRMax2 = (
fRMax - halfRadTolerance) * (
fRMax - halfRadTolerance);
646 tolIDz =
fDz - halfCarTolerance;
647 tolODz =
fDz + halfCarTolerance;
649 if (std::fabs(p.
z) >= tolIDz)
653 sd = (std::fabs(p.
z) -
fDz) / std::fabs(v.
z);
662 rho2 = xi * xi + yi * yi;
666 if ((tolIRMin2 <= rho2) && (rho2 <= tolIRMax2))
673 iden = std::sqrt(rho2);
674 cosPsi = inum / iden;
688 if (snxt < halfCarTolerance)
708 t1 = 1.0 - v.
z * v.
z;
709 t2 = p.
x * v.
x + p.
y * v.
y;
710 t3 = p.
x * p.
x + p.
y * p.
y;
716 if ((t3 >= tolORMax2) && (t2 < 0))
726 sd = c / (-b + std::sqrt(d));
732 double fTerm = sd - std::fmod(sd, dRmax);
738 if (std::fabs(zi) <= tolODz)
765 if ((t3 > tolIRMin2) && (t2 < 0) && (std::fabs(p.
z) <= tolIDz))
772 iden = std::sqrt(t3);
773 cosPsi = inum / iden;
782 c = t3 - fRMax *
fRMax;
793 snxt = c / (-b + std::sqrt(d));
795 if (snxt < halfCarTolerance)
816 c = t3 - fRMax *
fRMax;
827 snxt = c / (-b + std::sqrt(d));
829 if (snxt < halfCarTolerance)
852 sd = (b > 0.) ? c / (-b - std::sqrt(d)) : (-b + std::sqrt(d));
853 if (sd >= -halfCarTolerance)
864 double fTerm = sd - std::fmod(sd, dRmax);
868 if (std::fabs(zi) <= tolODz)
914 if (Dist < halfCarTolerance)
925 if (std::fabs(zi) <= tolODz)
929 rho2 = xi * xi + yi * yi;
931 if (((rho2 >= tolIRMin2) && (rho2 <= tolIRMax2))
932 || ((rho2 > tolORMin2) && (rho2 < tolIRMin2)
935 || ((rho2 > tolIRMax2) && (rho2 < tolORMax2)
960 if (Dist < halfCarTolerance)
971 if (std::fabs(zi) <= tolODz)
975 rho2 = xi * xi + yi * yi;
976 if (((rho2 >= tolIRMin2) && (rho2 <= tolIRMax2))
977 || ((rho2 > tolORMin2) && (rho2 < tolIRMin2)
980 || ((rho2 > tolIRMax2) && (rho2 < tolORMax2)
997 if (snxt < halfCarTolerance)
1032 double safe = 0.0, rho, safe1, safe2, safe3;
1036 rho = std::sqrt(p.
x * p.
x + p.
y * p.
y);
1037 safe1 =
fRMin - rho;
1038 safe2 = rho -
fRMax;
1039 safe3 = std::fabs(p.
z) -
fDz;
1057 if ((outside) && (safePhi > safe))
1065 safe = 0;
return safe;
1067 if (!aAccurate)
return safe;
1072 safsq += safe1 * safe1;
1077 safsq += safe2 * safe2;
1082 safsq += safe3 * safe3;
1085 if (count == 1)
return safe;
1086 return std::sqrt(safsq);
1099 double deltaR, t1, t2, t3, b, c,
d2, roMin2;
1106 double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2;
1113 if (pdist > halfCarTolerance)
1129 if (pdist > halfCarTolerance)
1131 snxt = -pdist / v.
z;
1158 t1 = 1.0 - v.
z * v.
z;
1159 t2 = p.
x * v.
x + p.
y * v.
y;
1160 t3 = p.
x * p.
x + p.
y * p.
y;
1168 roi2 = snxt * snxt * t1 + 2 * snxt * t2 + t3;
1191 srd = c / (-b - std::sqrt(d2));
1210 roMin2 = t3 - t2 * t2 / t1;
1226 srd = c / (-b + std::sqrt(d2));
1243 srd = -b + std::sqrt(d2);
1264 srd = -b + std::sqrt(d2);
1284 vphi = std::atan2(v.
y, v.
x);
1286 if (vphi <
fSPhi - halfAngTolerance)
1290 else if (vphi >
fSPhi +
fDPhi + halfAngTolerance)
1311 && (pDistE <= halfCarTolerance)))
1313 && (pDistE > halfCarTolerance))))
1319 sphi = pDistS / compS;
1321 if (sphi >= -halfCarTolerance)
1323 xi = p.
x + sphi * v.
x;
1324 yi = p.
y + sphi * v.
y;
1332 if (((
fSPhi - halfAngTolerance) <= vphi)
1333 && ((
fSPhi +
fDPhi + halfAngTolerance) >= vphi))
1345 if (pDistS > -halfCarTolerance)
1363 sphi2 = pDistE / compE;
1367 if ((sphi2 > -halfCarTolerance) && (sphi2 < sphi))
1369 xi = p.
x + sphi2 * v.
x;
1370 yi = p.
y + sphi2 * v.
y;
1376 if (!((
fSPhi - halfAngTolerance <= vphi)
1377 && (
fSPhi +
fDPhi + halfAngTolerance >= vphi)))
1380 if (pDistE <= -halfCarTolerance)
1397 if (pDistE <= -halfCarTolerance)
1419 if ((
fSPhi - halfAngTolerance <= vphi)
1420 && (vphi <=
fSPhi +
fDPhi + halfAngTolerance))
1450 xi = p.
x + snxt * v.
x;
1451 yi = p.
y + snxt * v.
y;
1457 xi = p.
x + snxt * v.
x;
1458 yi = p.
y + snxt * v.
y;
1502 std::ostringstream message;
1503 int oldprc = message.precision(16);
1504 message <<
"Undefined side for valid surface normal to solid."
1506 <<
"Position:" << std::endl << std::endl
1507 <<
"p.x = " << p.
x <<
" mm" << std::endl
1508 <<
"p.y = " << p.
y <<
" mm" << std::endl
1509 <<
"p.z = " << p.
z <<
" mm" << std::endl << std::endl
1510 <<
"Direction:" << std::endl << std::endl
1511 <<
"v.x = " << v.
x << std::endl
1512 <<
"v.y = " << v.
y << std::endl
1513 <<
"v.z = " << v.
z << std::endl << std::endl
1514 <<
"Proposed distance :" << std::endl << std::endl
1515 <<
"snxt = " << snxt <<
" mm" << std::endl;
1516 message.precision(oldprc);
1518 Warning, 1, message.str().c_str());
1522 if (snxt < halfCarTolerance)
1536 double safe = 0.0, rho, safeZ;
1537 rho = std::sqrt(p.
x * p.
x + p.
y * p.
y);
1542 int oldprc = cout.precision(16);
1545 cout <<
"Position:" << std::endl << std::endl;
1546 cout <<
"p.x = " << p.
x <<
" mm" << std::endl;
1547 cout <<
"p.y = " << p.
y <<
" mm" << std::endl;
1548 cout <<
"p.z = " << p.
z <<
" mm" << std::endl << std::endl;
1549 cout.precision(oldprc);
1551 Warning, 1,
"Point p is outside !?");
1555 safeZ =
fDz - std::fabs(p.
z);
1576 return std::string(
"Tubs");
1585 return new UTubs(*
this);
1594 int oldprc = os.precision(16);
1595 os <<
"-----------------------------------------------------------\n"
1596 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1597 <<
" ===================================================\n"
1598 <<
" Solid type: UTubs\n"
1599 <<
" Parameters: \n"
1600 <<
" inner radius : " <<
fRMin <<
" mm \n"
1601 <<
" outer radius : " <<
fRMax <<
" mm \n"
1602 <<
" half length Z: " <<
fDz <<
" mm \n"
1605 <<
"-----------------------------------------------------------\n";
1606 os.precision(oldprc);
1617 double xRand, yRand, zRand, phi, cosphi, sinphi, chose,
1618 aOne, aTwo, aThr, aFou;
1623 aThr = 0.5 *
fDPhi * (fRMax * fRMax - fRMin *
fRMin);
1627 cosphi = std::cos(phi);
1628 sinphi = std::sin(phi);
1639 if ((chose >= 0) && (chose < aOne))
1641 xRand = fRMax * cosphi;
1642 yRand = fRMax * sinphi;
1644 return UVector3(xRand, yRand, zRand);
1646 else if ((chose >= aOne) && (chose < aOne + aTwo))
1648 xRand = fRMin * cosphi;
1649 yRand = fRMin * sinphi;
1651 return UVector3(xRand, yRand, zRand);
1653 else if ((chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr))
1655 xRand = rRand * cosphi;
1656 yRand = rRand * sinphi;
1658 return UVector3(xRand, yRand, zRand);
1660 else if ((chose >= aOne + aTwo + aThr) && (chose < aOne + aTwo + 2.*aThr))
1662 xRand = rRand * cosphi;
1663 yRand = rRand * sinphi;
1665 return UVector3(xRand, yRand, zRand);
1667 else if ((chose >= aOne + aTwo + 2.*aThr)
1668 && (chose < aOne + aTwo + 2.*aThr + aFou))
1673 return UVector3(xRand, yRand, zRand);
1680 return UVector3(xRand, yRand, zRand);
double GetStartPhiAngle() const
static double frTolerance
double GetZHalfLength() const
double SafetyFromOutside(const UVector3 &p, bool precise=false) const
double SafetyFromInside(const UVector3 &p, bool precise=false) const
virtual void GetParametersList(int, double *) const
const std::string & GetName() const
double GetInnerRadius() const
VUSolid::EnumInside Inside(const UVector3 &p) const
static double Tolerance()
void CheckPhiAngles(double sPhi, double dPhi)
static const double kInfinity
double DistanceToOut(const UVector3 &p, const UVector3 &v, UVector3 &n, bool &validNorm, double aPstep=UUtils::kInfinity) const
double GetDeltaPhiAngle() const
UGeometryType GetEntityType() const
bool Normal(const UVector3 &p, UVector3 &normal) const
virtual UVector3 ApproxSurfaceNormal(const UVector3 &p) const
UTubs & operator=(const UTubs &rhs)
static double faTolerance
UVector3 GetPointOnSurface() const
void Extent(UVector3 &aMin, UVector3 &aMax) const
double GetRadiusInRing(double rmin, double rmax)
std::ostream & StreamInfo(std::ostream &os) const
double GetOuterRadius() const
std::string UGeometryType
double SafetyToPhi(const UVector3 &p, const double rho, bool &outside) const
void Exception(const char *originOfException, const char *exceptionCode, ExceptionSeverity severity, int level, const char *description)
double DistanceToIn(const UVector3 &p, const UVector3 &v, double aPstep=UUtils::kInfinity) const
double Random(double min=0.0, double max=1.0)
double SafetyFromInsideR(const UVector3 &p, const double rho, bool precise=false) const