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)
197 pPhi += 2 * UUtils::kPi;
202 if ((std::fabs(pPhi) < halfAngTolerance)
203 && (std::fabs(
fSPhi +
fDPhi - 2 * UUtils::kPi) < halfAngTolerance))
205 pPhi += 2 * UUtils::kPi;
207 if ((pPhi >=
fSPhi + halfAngTolerance)
208 && (pPhi <=
fSPhi +
fDPhi - halfAngTolerance))
212 else if ((pPhi >=
fSPhi - halfAngTolerance)
213 && (pPhi <=
fSPhi +
fDPhi + halfAngTolerance))
220 if ((pPhi <=
fSPhi + 2 * UUtils::kPi - halfAngTolerance)
221 && (pPhi >=
fSPhi +
fDPhi + halfAngTolerance))
225 else if ((pPhi <=
fSPhi + 2 * UUtils::kPi + 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)
261 pPhi += 2 * UUtils::kPi;
265 if ((std::fabs(pPhi) < halfAngTolerance)
266 && (std::fabs(
fSPhi +
fDPhi - 2 * UUtils::kPi) < halfAngTolerance))
268 pPhi += 2 * UUtils::kPi;
270 if ((pPhi >=
fSPhi - halfAngTolerance)
271 && (pPhi <=
fSPhi +
fDPhi + halfAngTolerance))
278 if ((pPhi <=
fSPhi + 2 * UUtils::kPi - 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)
317 pPhi += 2 * UUtils::kPi;
321 if ((std::fabs(pPhi) < halfAngTolerance)
322 && (std::fabs(
fSPhi +
fDPhi - 2 * UUtils::kPi) < halfAngTolerance))
324 pPhi += 2 * UUtils::kPi;
326 if ((pPhi >=
fSPhi - halfAngTolerance)
327 && (pPhi <=
fSPhi +
fDPhi + halfAngTolerance))
334 if ((pPhi <=
fSPhi + 2 * UUtils::kPi - halfAngTolerance)
335 && (pPhi >=
fSPhi +
fDPhi + halfAngTolerance))
360 double distZ, distRMin, distRMax;
361 double distSPhi = UUtils::kInfinity, distEPhi = UUtils::kInfinity;
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)
384 pPhi += 2 * UUtils::kPi;
386 else if (pPhi >
fSPhi +
fDPhi + halfCarTolerance)
388 pPhi -= 2 * UUtils::kPi;
391 distSPhi = std::fabs(pPhi -
fSPhi);
402 if (rho > halfCarTolerance)
407 if (distRMax <= halfCarTolerance)
412 if (
fRMin && (distRMin <= halfCarTolerance))
417 if (
fDPhi < 2 * UUtils::kPi)
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);
518 phi += 2 * UUtils::kPi;
523 distSPhi = std::fabs(phi - (
fSPhi + 2 * UUtils::kPi)) * rho;
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.");
616 double snxt = UUtils::kInfinity;
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;
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)
803 return UUtils::kInfinity;
816 c = t3 - fRMax *
fRMax;
827 snxt = c / (-b + std::sqrt(d));
829 if (snxt < halfCarTolerance)
837 return UUtils::kInfinity;
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;
1033 double safePhi, cosPsi;
1035 rho = std::sqrt(p.
x * p.
x + p.
y * p.
y);
1036 safe1 =
fRMin - rho;
1037 safe2 = rho -
fRMax;
1038 safe3 = std::fabs(p.
z) -
fDz;
1059 if (cosPsi < std::cos(
fDPhi * 0.5))
1093 double snxt, srd = UUtils::kInfinity, sphi = UUtils::kInfinity, pdist;
1094 double deltaR,
t1,
t2, t3,
b,
c, d2, roMin2;
1101 double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2;
1108 if (pdist > halfCarTolerance)
1127 if (pdist > halfCarTolerance)
1129 snxt = -pdist / v.
z;
1144 snxt = UUtils::kInfinity;
1159 t1 = 1.0 - v.
z * v.
z;
1160 t2 = p.
x * v.
x + p.
y * v.
y;
1161 t3 = p.
x * p.
x + p.
y * p.
y;
1169 roi2 = snxt * snxt * t1 + 2 * snxt * t2 + t3;
1192 srd = c / (-b - std::sqrt(d2));
1215 roMin2 = t3 - t2 * t2 /
t1;
1231 srd = c / (-b + std::sqrt(d2));
1250 srd = -b + std::sqrt(d2);
1274 srd = -b + std::sqrt(d2);
1297 vphi = std::atan2(v.
y, v.
x);
1299 if (vphi <
fSPhi - halfAngTolerance)
1301 vphi += 2 * UUtils::kPi;
1303 else if (vphi >
fSPhi +
fDPhi + halfAngTolerance)
1305 vphi -= 2 * UUtils::kPi;
1323 if (((
fDPhi <= UUtils::kPi) && ((pDistS <= halfCarTolerance)
1324 && (pDistE <= halfCarTolerance)))
1325 || ((
fDPhi > UUtils::kPi) && !((pDistS > halfCarTolerance)
1326 && (pDistE > halfCarTolerance))))
1332 sphi = pDistS / compS;
1334 if (sphi >= -halfCarTolerance)
1336 xi = p.
x + sphi * v.
x;
1337 yi = p.
y + sphi * v.
y;
1345 if (((
fSPhi - halfAngTolerance) <= vphi)
1346 && ((
fSPhi +
fDPhi + halfAngTolerance) >= vphi))
1348 sphi = UUtils::kInfinity;
1353 sphi = UUtils::kInfinity;
1358 if (pDistS > -halfCarTolerance)
1366 sphi = UUtils::kInfinity;
1371 sphi = UUtils::kInfinity;
1376 sphi2 = pDistE / compE;
1380 if ((sphi2 > -halfCarTolerance) && (sphi2 < sphi))
1382 xi = p.
x + sphi2 * v.
x;
1383 yi = p.
y + sphi2 * v.
y;
1389 if (!((
fSPhi - halfAngTolerance <= vphi)
1390 && (
fSPhi +
fDPhi + halfAngTolerance >= vphi)))
1393 if (pDistE <= -halfCarTolerance)
1410 if (pDistE <= -halfCarTolerance)
1424 sphi = UUtils::kInfinity;
1432 if ((
fSPhi - halfAngTolerance <= vphi)
1433 && (vphi <=
fSPhi +
fDPhi + halfAngTolerance))
1435 sphi = UUtils::kInfinity;
1463 xi = p.
x + snxt * v.
x;
1464 yi = p.
y + snxt * v.
y;
1474 if (
fDPhi <= UUtils::kPi)
1486 if (
fDPhi <= UUtils::kPi)
1510 std::ostringstream message;
1511 int oldprc = message.precision(16);
1512 message <<
"Undefined side for valid surface normal to solid."
1514 <<
"Position:" << std::endl << std::endl
1515 <<
"p.x = " << p.
x <<
" mm" << std::endl
1516 <<
"p.y = " << p.
y <<
" mm" << std::endl
1517 <<
"p.z = " << p.
z <<
" mm" << std::endl << std::endl
1518 <<
"Direction:" << std::endl << std::endl
1519 <<
"v.x = " << v.
x << std::endl
1520 <<
"v.y = " << v.
y << std::endl
1521 <<
"v.z = " << v.
z << std::endl << std::endl
1522 <<
"Proposed distance :" << std::endl << std::endl
1523 <<
"snxt = " << snxt <<
" mm" << std::endl;
1524 message.precision(oldprc);
1526 Warning, 1, message.str().c_str());
1530 if (snxt < halfCarTolerance)
1545 double safe = 0.0, rho, safeR1, safeR2, safeZ, safePhi;
1546 rho = std::sqrt(p.
x * p.
x + p.
y * p.
y);
1551 int oldprc = cout.precision(16);
1554 cout <<
"Position:" << std::endl << std::endl;
1555 cout <<
"p.x = " << p.
x <<
" mm" << std::endl;
1556 cout <<
"p.y = " << p.
y <<
" mm" << std::endl;
1557 cout <<
"p.z = " << p.
z <<
" mm" << std::endl << std::endl;
1558 cout.precision(oldprc);
1560 Warning, 1,
"Point p is outside !?");
1566 safeR1 = rho -
fRMin;
1567 safeR2 =
fRMax - rho;
1569 if (safeR1 < safeR2)
1582 safeZ =
fDz - std::fabs(p.
z);
1621 return std::string(
"Tubs");
1630 return new UTubs(*
this);
1639 int oldprc = os.precision(16);
1640 os <<
"-----------------------------------------------------------\n"
1641 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1642 <<
" ===================================================\n"
1643 <<
" Solid type: UTubs\n"
1644 <<
" Parameters: \n"
1645 <<
" inner radius : " <<
fRMin <<
" mm \n"
1646 <<
" outer radius : " <<
fRMax <<
" mm \n"
1647 <<
" half length Z: " <<
fDz <<
" mm \n"
1648 <<
" starting phi : " <<
fSPhi / (UUtils::kPi / 180.0) <<
" degrees \n"
1649 <<
" delta phi : " <<
fDPhi / (UUtils::kPi / 180.0) <<
" degrees \n"
1650 <<
"-----------------------------------------------------------\n";
1651 os.precision(oldprc);
1662 double xRand, yRand, zRand, phi, cosphi, sinphi, chose,
1663 aOne, aTwo, aThr, aFou;
1668 aThr = 0.5 *
fDPhi * (fRMax * fRMax - fRMin *
fRMin);
1672 cosphi = std::cos(phi);
1673 sinphi = std::sin(phi);
1677 if ((
fSPhi == 0) && (
fDPhi == 2 * UUtils::kPi))
1684 if ((chose >= 0) && (chose < aOne))
1686 xRand = fRMax * cosphi;
1687 yRand = fRMax * sinphi;
1689 return UVector3(xRand, yRand, zRand);
1691 else if ((chose >= aOne) && (chose < aOne + aTwo))
1693 xRand = fRMin * cosphi;
1694 yRand = fRMin * sinphi;
1696 return UVector3(xRand, yRand, zRand);
1698 else if ((chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr))
1700 xRand = rRand * cosphi;
1701 yRand = rRand * sinphi;
1703 return UVector3(xRand, yRand, zRand);
1705 else if ((chose >= aOne + aTwo + aThr) && (chose < aOne + aTwo + 2.*aThr))
1707 xRand = rRand * cosphi;
1708 yRand = rRand * sinphi;
1710 return UVector3(xRand, yRand, zRand);
1712 else if ((chose >= aOne + aTwo + 2.*aThr)
1713 && (chose < aOne + aTwo + 2.*aThr + aFou))
1718 return UVector3(xRand, yRand, zRand);
1725 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)
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
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)