41 double pRmin1,
double pRmax1,
42 double pRmin2,
double pRmax2,
44 double pSPhi,
double pDPhi)
45 :
VUSolid(pName.c_str()), fRmin1(pRmin1), fRmin2(pRmin2),
46 fRmax1(pRmax1), fRmax2(pRmax2), fDz(pDz), fSPhi(0.), fDPhi(0.)
54 std::ostringstream message;
55 message <<
"Invalid Z half-length for Solid: " <<
GetName() << std::endl
63 if (((pRmin1 >= pRmax1) || (pRmin2 >= pRmax2) || (pRmin1 < 0)) && (pRmin2 < 0))
65 std::ostringstream message;
66 message <<
"Invalid values of radii for Solid: " <<
GetName() << std::endl
67 <<
" pRmin1 = " << pRmin1 <<
", pRmin2 = " << pRmin2
68 <<
", pRmax1 = " << pRmax1 <<
", pRmax2 = " << pRmax2;
72 if ((pRmin1 == 0.0) && (pRmin2 > 0.0))
76 if ((pRmin2 == 0.0) && (pRmin1 > 0.0))
94 :
VUSolid(
""), kRadTolerance(0.), kAngTolerance(0.),
95 fRmin1(0.), fRmin2(0.), fRmax1(0.), fRmax2(0.), fDz(0.),
96 fSPhi(0.), fDPhi(0.), sinCPhi(0.), cosCPhi(0.), cosHDPhiOT(0.),
97 cosHDPhiIT(0.), sinSPhi(0.), cosSPhi(0.), sinEPhi(0.), cosEPhi(0.),
116 :
VUSolid(rhs), kRadTolerance(rhs.kRadTolerance),
117 kAngTolerance(rhs.kAngTolerance), fRmin1(rhs.fRmin1), fRmin2(rhs.fRmin2),
118 fRmax1(rhs.fRmax1), fRmax2(rhs.fRmax2), fDz(rhs.fDz), fSPhi(rhs.fSPhi),
119 fDPhi(rhs.fDPhi), sinCPhi(rhs.sinCPhi), cosCPhi(rhs.cosCPhi),
120 cosHDPhiOT(rhs.cosHDPhiOT), cosHDPhiIT(rhs.cosHDPhiIT),
121 sinSPhi(rhs.sinSPhi), cosSPhi(rhs.cosSPhi), sinEPhi(rhs.sinEPhi),
122 cosEPhi(rhs.cosEPhi), fPhiFullCone(rhs.fPhiFullCone)
142 VUSolid::operator=(rhs);
179 double distZ, distRMin, distRMax;
181 double pRMin, widRMin;
182 double pRMax, widRMax;
188 UVector3 nR, nr(0., 0., 0.), nPs, nPe;
190 distZ = std::fabs(std::fabs(p.
z) -
fDz);
191 rho = std::sqrt(p.
x * p.
x + p.
y * p.
y);
195 distRMin = std::fabs(pRMin - widRMin) /
secRMin;
199 distRMax = std::fabs(pRMax - widRMax) /
secRMax;
205 pPhi = std::atan2(p.
y, p.
x);
207 if (pPhi <
fSPhi - delta)
216 distSPhi = std::fabs(pPhi -
fSPhi);
236 if (distRMax <= delta)
248 if (distSPhi <= dAngle)
253 if (distEPhi <= dAngle)
276 Warning, 1,
"Point p is not on surface !?");
280 else if (noSurfaces == 1)
286 norm = sumnorm.
Unit();
291 return (
bool) noSurfaces;
304 double distZ, distRMin, distRMax, distSPhi, distEPhi, distMin;
305 double pRMin, widRMin;
306 double pRMax, widRMax;
308 distZ = std::fabs(std::fabs(p.
z) -
fDz);
309 rho = std::sqrt(p.
x * p.
x + p.
y * p.
y);
313 distRMin = std::fabs(pRMin - widRMin) /
secRMin;
317 distRMax = std::fabs(pRMax - widRMax) /
secRMax;
319 if (distRMin < distRMax)
321 if (distZ < distRMin)
334 if (distZ < distRMax)
347 phi = std::atan2(p.
y, p.
x);
360 distSPhi = std::fabs(phi -
fSPhi) * rho;
363 distEPhi = std::fabs(phi -
fSPhi -
fDPhi) * rho;
367 if (distSPhi < distEPhi)
369 if (distSPhi < distMin)
376 if (distEPhi < distMin)
411 "Undefined side for valid surface normal to solid.");
449 double rMaxAv, rMaxOAv;
450 double rMinAv, rMinOAv;
453 double tolORMin, tolORMin2, tolIRMin, tolIRMin2;
454 double tolORMax2, tolIRMax, tolIRMax2;
455 double tolODz, tolIDz;
457 double Dist, sd, xi, yi, zi, ri = 0., risec, rhoi2, cosPsi;
459 double t1, t2, t3, b, c, d;
460 double nt1, nt2, nt3;
468 if (rMinAv > halfRadTolerance)
470 rMinOAv = rMinAv - halfRadTolerance;
477 rMaxOAv = rMaxAv + halfRadTolerance;
481 tolIDz =
fDz - halfCarTolerance;
482 tolODz =
fDz + halfCarTolerance;
484 if (std::fabs(p.
z) >= tolIDz)
488 sd = (std::fabs(p.
z) -
fDz) / std::fabs(v.
z);
497 rhoi2 = xi * xi + yi * yi ;
520 tolORMin2 = tolORMin * tolORMin;
521 tolIRMin2 = tolIRMin * tolIRMin;
530 tolIRMax2 = tolIRMax * tolIRMax;
537 if ((tolIRMin2 <= rhoi2) && (rhoi2 <= tolIRMax2))
581 t1 = 1.0 - v.
z * v.
z;
582 t2 = p.
x * v.
x + p.
y * v.
y;
583 t3 = p.
x * p.
x + p.
y * p.
y;
592 nt3 = t3 - rout * rout;
608 if ((rout < 0) && (nt3 <= 0))
615 sd = c / (-b - std::sqrt(d));
619 sd = -b + std::sqrt(d);
624 if ((b <= 0) && (c >= 0))
626 sd = c / (-b + std::sqrt(d));
632 sd = -b + std::sqrt(d);
645 double fTerm = sd - std::fmod(sd, dRmax);
650 if (std::fabs(zi) <= tolODz)
679 if ((t3 > (rin + halfRadTolerance *
secRMin)*
680 (rin + halfRadTolerance * secRMin))
681 && (nt2 < 0) && (d >= 0) && (std::fabs(p.
z) <= tolIDz))
688 risec = std::sqrt(xi * xi + yi * yi) *
secRMax;
695 if (norm.
Dot(v) <= 0)
703 if (norm.
Dot(v) <= 0)
715 sd = -0.5 * nt3 / nt2;
725 if ((std::fabs(zi) <= tolODz) && (nt2 < 0))
767 nt3 = t3 - rin * rin;
783 sd = c / (-b - std::sqrt(d));
787 sd = -b + std::sqrt(d);
795 double fTerm = sd - std::fmod(sd, dRmax);
800 if (std::fabs(zi) <= tolODz)
811 if (sd > halfRadTolerance)
819 risec = std::sqrt(xi * xi + yi * yi) *
secRMin;
820 norm =
UVector3(-xi / risec, -yi / risec, tanRMin / secRMin);
821 if (norm.
Dot(v) <= 0)
830 if (sd > halfRadTolerance)
840 risec = std::sqrt(xi * xi + yi * yi) *
secRMin;
842 if (norm.
Dot(v) <= 0)
867 sd = c / (-b - std::sqrt(d));
871 sd = -b + std::sqrt(d);
878 if ((sd >= 0) && (std::fabs(zi) <= tolODz))
883 double fTerm = sd - std::fmod(sd, dRmax);
894 if (sd > halfRadTolerance)
902 risec = std::sqrt(xi * xi + yi * yi) *
secRMin;
903 norm =
UVector3(-xi / risec, -yi / risec, tanRMin / secRMin);
904 if (norm.
Dot(v) <= 0)
913 if (sd > halfRadTolerance)
923 risec = std::sqrt(xi * xi + yi * yi) *
secRMin;
924 norm =
UVector3(-xi / risec, -yi / risec, tanRMin / secRMin);
925 if (norm.
Dot(v) <= 0)
937 sd = -b - std::sqrt(d);
941 sd = c / (-b + std::sqrt(d));
946 if ((sd >= 0) && (ri > 0) && (std::fabs(zi) <= tolODz))
951 double fTerm = sd - std::fmod(sd, dRmax);
962 if (sd > halfRadTolerance)
970 risec = std::sqrt(xi * xi + yi * yi) *
secRMin;
971 norm =
UVector3(-xi / risec, -yi / risec, tanRMin / secRMin);
972 if (norm.
Dot(v) <= 0)
981 if (sd > halfRadTolerance)
991 risec = std::sqrt(xi * xi + yi * yi) *
secRMin;
992 norm =
UVector3(-xi / risec, -yi / risec, tanRMin / secRMin);
993 if (norm.
Dot(v) <= 0)
1010 if (std::fabs(p.
z) <= tolODz)
1043 sd = -b - std::sqrt(d);
1047 sd = c / (-b + std::sqrt(d));
1049 zi = p.
z + sd * v.
z;
1056 sd = c / (-b - std::sqrt(d));
1060 sd = -b + std::sqrt(d);
1063 zi = p.
z + sd * v.
z;
1065 if ((sd >= 0) && (std::fabs(zi) <= tolODz))
1070 double fTerm = sd - std::fmod(sd, dRmax);
1075 xi = p.
x + sd * v.
x;
1076 yi = p.
y + sd * v.
y;
1108 sd = c / (-b - std::sqrt(d));
1112 sd = -b + std::sqrt(d);
1114 zi = p.
z + sd * v.
z;
1116 if ((sd >= 0) && (std::fabs(zi) <= tolODz))
1121 double fTerm = sd - std::fmod(sd, dRmax);
1126 xi = p.
x + sd * v.
x;
1127 yi = p.
y + sd * v.
y;
1166 if (Dist < halfCarTolerance)
1177 zi = p.
z + sd * v.
z;
1179 if (std::fabs(zi) <= tolODz)
1181 xi = p.
x + sd * v.
x;
1182 yi = p.
y + sd * v.
y;
1183 rhoi2 = xi * xi + yi * yi;
1187 if ((rhoi2 >= tolORMin2) && (rhoi2 <= tolORMax2))
1209 if (Dist < halfCarTolerance)
1220 zi = p.
z + sd * v.
z;
1222 if (std::fabs(zi) <= tolODz)
1224 xi = p.
x + sd * v.
x;
1225 yi = p.
y + sd * v.
y;
1226 rhoi2 = xi * xi + yi * yi;
1230 if ((rhoi2 >= tolORMin2) && (rhoi2 <= tolORMax2))
1245 if (snxt < halfCarTolerance)
1262 double safe = 0.0, rho, safeR1, safeR2, safeZ, safePhi, cosPsi;
1263 double pRMin, pRMax;
1265 rho = std::sqrt(p.
x * p.
x + p.
y * p.
y);
1266 safeZ = std::fabs(p.
z) -
fDz;
1267 safeR1 = 0; safeR2 = 0;
1272 safeR1 = (pRMin - rho) /
secRMin;
1275 safeR2 = (rho - pRMax) /
secRMax;
1277 if (safeR1 > safeR2)
1289 safe = (rho - pRMax) /
secRMax;
1302 if (cosPsi < std::cos(
fDPhi * 0.5))
1306 safePhi = std::fabs(p.
x * std::sin(
fSPhi) - p.
y * std::cos(
fSPhi));
1320 safe = 0.0;
return safe;
1322 if (!aAccurate)
return safe;
1328 safsq += safeR1 * safeR1;
1333 safsq += safeR2 * safeR2;
1338 safsq += safeZ * safeZ;
1341 if (count == 1)
return safe;
1342 return std::sqrt(safsq);
1367 double snxt, srd, sphi, pdist;
1372 double t1, t2, t3, rout, rin, nt1, nt2, nt3;
1373 double b, c, d, sr2, sr3;
1382 double pDistS, compS, pDistE, compE, sphi2, xi, yi, risec, vphi;
1383 double zi, ri, deltaRoi2;
1391 if (pdist > halfCarTolerance)
1407 if (pdist > halfCarTolerance)
1409 snxt = -pdist / v.
z;
1414 aNormalVector =
UVector3(0, 0, -1);
1444 t1 = 1.0 - v.
z * v.
z;
1445 t2 = p.
x * v.
x + p.
y * v.
y;
1446 t3 = p.
x * p.
x + p.
y * p.
y;
1451 nt3 = t3 - rout * rout;
1455 deltaRoi2 = snxt * snxt * t1 + 2 * snxt * t2 + t3
1460 deltaRoi2 = snxt * snxt * t1 + 2 * snxt * t2 + t3
1468 if (nt1 && (deltaRoi2 > 0.0))
1481 if (nt3 > -halfRadTolerance && nt2 >= 0)
1483 risec = std::sqrt(t3) *
secRMax;
1493 srd = -b - std::sqrt(d);
1497 srd = c / (-b + std::sqrt(d));
1500 zi = p.
z + srd * v.
z;
1503 if ((ri >= 0) && (-halfRadTolerance <= srd) && (srd <= halfRadTolerance))
1511 if ((ri < 0) || (srd < halfRadTolerance))
1518 sr2 = c / (-b - std::sqrt(d));
1522 sr2 = -b + std::sqrt(d);
1524 zi = p.
z + sr2 * v.
z;
1527 if ((ri >= 0) && (sr2 > halfRadTolerance))
1535 if ((-halfRadTolerance <= sr2) && (sr2 <= halfRadTolerance))
1552 risec = std::sqrt(t3) *
secRMax;
1558 else if (nt2 && (deltaRoi2 > 0.0))
1562 risec = std::sqrt(t3) *
secRMax;
1577 if (slentol <= halfCarTolerance)
1588 xi = p.
x + slentol * v.
x;
1589 yi = p.
y + slentol * v.
y;
1590 risec = std::sqrt(xi * xi + yi * yi) *
secRMax;
1593 if (norm.
Dot(v) > 0)
1595 aNormalVector = norm.
Unit();
1617 nt3 = t3 - rin * rin;
1642 sr2 = -b - std::sqrt(d);
1646 sr2 = c / (-b + std::sqrt(d));
1648 zi = p.
z + sr2 * v.
z;
1651 if ((ri >= 0.0) && (-halfRadTolerance <= sr2) && (sr2 <= halfRadTolerance))
1659 if ((ri < 0) || (sr2 < halfRadTolerance))
1663 sr3 = c / (-b - std::sqrt(d));
1667 sr3 = -b + std::sqrt(d);
1673 if (sr3 > halfRadTolerance)
1677 zi = p.
z + sr3 * v.
z;
1687 else if (sr3 > -halfRadTolerance)
1695 else if ((sr2 < srd) && (sr2 > halfCarTolerance))
1700 else if (sr2 > -halfCarTolerance)
1707 if (slentol <= halfCarTolerance)
1716 xi = p.
x + slentol * v.
x;
1717 yi = p.
y + slentol * v.
y;
1718 if (sidetol ==
kRMax)
1720 risec = std::sqrt(xi * xi + yi * yi) *
secRMax;
1725 risec = std::sqrt(xi * xi + yi * yi) *
secRMin;
1728 if (norm.
Dot(v) > 0)
1732 aNormalVector = norm.
Unit();
1758 vphi = std::atan2(v.
y, v.
x);
1760 if (vphi <
fSPhi - halfAngTolerance)
1764 else if (vphi >
fSPhi +
fDPhi + halfAngTolerance)
1784 && (pDistE <= halfCarTolerance)))
1786 && (pDistE > halfCarTolerance))))
1791 sphi = pDistS / compS;
1792 if (sphi >= -halfCarTolerance)
1794 xi = p.
x + sphi * v.
x;
1795 yi = p.
y + sphi * v.
y;
1804 if ((
fSPhi - halfAngTolerance <= vphi)
1805 && (
fSPhi +
fDPhi + halfAngTolerance >= vphi))
1817 if (pDistS > -halfCarTolerance)
1835 sphi2 = pDistE / compE;
1839 if ((sphi2 > -halfCarTolerance) && (sphi2 < sphi))
1841 xi = p.
x + sphi2 * v.
x;
1842 yi = p.
y + sphi2 * v.
y;
1851 if (!((
fSPhi - halfAngTolerance <= vphi)
1852 && (
fSPhi +
fDPhi + halfAngTolerance >= vphi)))
1855 if (pDistE <= -halfCarTolerance)
1871 if (pDistE <= -halfCarTolerance)
1893 if ((
fSPhi - halfAngTolerance <= vphi)
1894 && (vphi <=
fSPhi +
fDPhi + halfAngTolerance))
1920 xi = p.
x + snxt * v.
x;
1921 yi = p.
y + snxt * v.
y;
1922 risec = std::sqrt(xi * xi + yi * yi) *
secRMax;
1956 aNormalVector =
UVector3(0, 0, -1);
1962 std::ostringstream message;
1963 int oldprc = message.precision(16);
1964 message <<
"Undefined side for valid surface normal to solid."
1966 <<
"Position:" << std::endl << std::endl
1967 <<
"p.x = " << p.
x <<
" mm" << std::endl
1968 <<
"p.y = " << p.
y <<
" mm" << std::endl
1969 <<
"p.z = " << p.
z <<
" mm" << std::endl << std::endl
1970 <<
"pho at z = " << std::sqrt(p.
x * p.
x + p.
y * p.
y)
1971 <<
" mm" << std::endl << std::endl;
1972 if (p.
x != 0. || p.
y != 0.)
1974 message <<
"point phi = " << std::atan2(p.
y, p.
x) / (
UUtils::kPi / 180.0)
1975 <<
" degree" << std::endl << std::endl;
1977 message <<
"Direction:" << std::endl << std::endl
1978 <<
"v.x = " << v.
x << std::endl
1979 <<
"v.y = " << v.
y << std::endl
1980 <<
"v.z = " << v.
z << std::endl << std::endl
1981 <<
"Proposed distance :" << std::endl << std::endl
1982 <<
"snxt = " << snxt <<
" mm" << std::endl;
1983 message.precision(oldprc);
1987 if (snxt < halfCarTolerance)
2001 double safe = 0.0, rho, safeR1, safeR2, safeZ, safePhi;
2008 int oldprc = cout.precision(16);
2011 cout <<
"Position:" << std::endl << std::endl;
2012 cout <<
"p.x = " << p.
x <<
" mm" << std::endl;
2013 cout <<
"p.y = " << p.
y <<
" mm" << std::endl;
2014 cout <<
"p.z = " << p.
z <<
" mm" << std::endl << std::endl;
2015 cout <<
"pho at z = " << std::sqrt(p.
x * p.
x + p.
y * p.
y)
2016 <<
" mm" << std::endl << std::endl;
2017 if ((p.
x != 0.) || (p.
x != 0.))
2019 cout <<
"point phi = " << std::atan2(p.
y, p.
x) /
degree
2020 <<
" degree" << std::endl << std::endl;
2022 cout.precision(oldprc);
2028 rho = std::sqrt(p.
x * p.
x + p.
y * p.
y);
2029 safeZ =
fDz - std::fabs(p.
z);
2034 safeR1 = (rho - pRMin) /
secRMin;
2042 safeR2 = (pRMax - rho) /
secRMax;
2044 if (safeR1 < safeR2)
2091 return std::string(
"Cons");
2101 return new UCons(*
this);
2110 int oldprc = os.precision(16);
2111 os <<
"-----------------------------------------------------------\n"
2112 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
2113 <<
" ===================================================\n"
2114 <<
" Solid type: UCons\n"
2115 <<
" Parameters: \n"
2116 <<
" inside -fDz radius: " <<
fRmin1 <<
" mm \n"
2117 <<
" outside -fDz radius: " <<
fRmax1 <<
" mm \n"
2118 <<
" inside +fDz radius: " <<
fRmin2 <<
" mm \n"
2119 <<
" outside +fDz radius: " <<
fRmax2 <<
" mm \n"
2120 <<
" half length in Z : " <<
fDz <<
" mm \n"
2121 <<
" starting angle of segment: " <<
fSPhi / (
UUtils::kPi / 180.0) <<
" degrees \n"
2122 <<
" delta angle of segment : " <<
fDPhi / (
UUtils::kPi / 180.0) <<
" degrees \n"
2123 <<
"-----------------------------------------------------------\n";
2124 os.precision(oldprc);
2139 double Aone, Atwo, Athree, Afour, Afive, slin, slout, phi;
2140 double zRand, cosu, sinu, rRand1, rRand2, chose, rone, rtwo, qone, qtwo;
2162 cosu = std::cos(phi);
2163 sinu = std::sin(phi);
2171 chose =
UUtils::Random(0., Aone + Atwo + Athree + Afour + 2.*Afive);
2173 if ((chose >= 0.) && (chose < Aone))
2178 return UVector3(rtwo * cosu * (qtwo - zRand),
2179 rtwo * sinu * (qtwo - zRand), zRand);
2187 else if ((chose >= Aone) && (chose <= Aone + Atwo))
2192 return UVector3(rone * cosu * (qone - zRand),
2193 rone * sinu * (qone - zRand), zRand);
2201 else if ((chose >= Aone + Atwo) && (chose < Aone + Atwo + Athree))
2203 return UVector3(rRand1 * cosu, rRand1 * sinu, -1 *
fDz);
2205 else if ((chose >= Aone + Atwo + Athree)
2206 && (chose < Aone + Atwo + Athree + Afour))
2208 return UVector3(rRand2 * cosu, rRand2 * sinu,
fDz);
2210 else if ((chose >= Aone + Atwo + Athree + Afour)
2211 && (chose < Aone + Atwo + Athree + Afour + Afive))
2217 rRand1 * std::sin(
fSPhi), zRand);
double SafetyFromOutside(const UVector3 &p, bool precise) const
static double frTolerance
VUSolid::EnumInside Inside(const UVector3 &p) const
UGeometryType GetEntityType() const
std::ostream & StreamInfo(std::ostream &os) const
double DistanceToIn(const UVector3 &p, const UVector3 &v, double aPstep=UUtils::kInfinity) const
UCons & operator=(const UCons &rhs)
const std::string & GetName() const
double SafetyFromInside(const UVector3 &p, bool precise) const
double GetOuterRadiusPlusZ() const
static double Tolerance()
static const double kInfinity
double GetStartPhiAngle() const
bool Normal(const UVector3 &p, UVector3 &n) const
double GetZHalfLength() const
static double faTolerance
double Dot(const UVector3 &) const
double GetInnerRadiusPlusZ() const
double GetRadiusInRing(double rmin, double rmax)
double GetOuterRadiusMinusZ() const
void Extent(UVector3 &aMin, UVector3 &aMax) const
virtual void GetParametersList(int, double *) const
T max(const T t1, const T t2)
brief Return the largest of the two arguments
void CheckPhiAngles(double sPhi, double dPhi)
double GetDeltaPhiAngle() const
static const double degree
std::string UGeometryType
double GetInnerRadiusMinusZ() const
UVector3 GetPointOnSurface() const
void Exception(const char *originOfException, const char *exceptionCode, ExceptionSeverity severity, int level, const char *description)
UVector3 ApproxSurfaceNormal(const UVector3 &p) const
double Random(double min=0.0, double max=1.0)
double DistanceToOut(const UVector3 &aPoint, const UVector3 &aDirection, UVector3 &aNormalVector, bool &aConvex, double aPstep=UUtils::kInfinity) const