2 // ********************************************************************
3 // * This Software is part of the AIDA Unified Solids Library package *
4 // * See: https://aidasoft.web.cern.ch/USolids *
5 // ********************************************************************
9 // --------------------------------------------------------------------
13 // Implementation of inline methods of UTubs
15 // 19.10.12 Marek Gayer
16 // Created from original implementation in Geant4
17 // --------------------------------------------------------------------
20 double UTubs::GetInnerRadius() const
26 double UTubs::GetOuterRadius() const
32 double UTubs::GetZHalfLength() const
38 double UTubs::GetStartPhiAngle() const
44 double UTubs::GetDeltaPhiAngle() const
50 void UTubs::Initialize()
57 void UTubs::InitializeTrigonometry()
59 double hDPhi = 0.5 * fDPhi; // half delta phi
60 double cPhi = fSPhi + hDPhi;
61 double ePhi = fSPhi + fDPhi;
63 fSinCPhi = std::sin(cPhi);
64 fCosCPhi = std::cos(cPhi);
65 fCosHDPhiIT = std::cos(hDPhi - 0.5 * kAngTolerance); // inner/outer tol half dphi
66 fCosHDPhiOT = std::cos(hDPhi + 0.5 * kAngTolerance);
67 fSinSPhi = std::sin(fSPhi);
68 fCosSPhi = std::cos(fSPhi);
69 fSinEPhi = std::sin(ePhi);
70 fCosEPhi = std::cos(ePhi);
72 fSinSPhiDPhi = std::sin(fSPhi + fDPhi);
73 fCosSPhiDPhi = std::cos(fSPhi + fDPhi);
76 inline void UTubs::CheckSPhiAngle(double sPhi)
78 // Ensure fSphi in 0-2PI or -2PI-0 range if shape crosses 0
82 fSPhi = 2 * UUtils::kPi - std::fmod(std::fabs(sPhi), 2 * UUtils::kPi);
86 fSPhi = std::fmod(sPhi, 2 * UUtils::kPi) ;
88 if (fSPhi + fDPhi > 2 * UUtils::kPi)
90 fSPhi -= 2 * UUtils::kPi ;
94 inline void UTubs::CheckDPhiAngle(double dPhi)
97 if (dPhi >= 2 * UUtils::kPi - kAngTolerance * 0.5)
99 fDPhi = 2 * UUtils::kPi;
104 fPhiFullTube = false;
111 std::ostringstream message;
112 message << "Invalid dphi." << std::endl
113 << "Negative or zero delta-Phi (" << dPhi << "), for solid: "
115 UUtils::Exception("UTubs::CheckDPhiAngle()", "GeomSolids0002",
116 UFatalError, 1, message.str().c_str());
121 inline void UTubs::CheckPhiAngles(double sPhi, double dPhi)
123 CheckDPhiAngle(dPhi);
124 if ((fDPhi < 2 * UUtils::kPi) && (sPhi))
126 CheckSPhiAngle(sPhi);
128 InitializeTrigonometry();
132 void UTubs::SetInnerRadius(double newRMin)
134 if (newRMin < 0) // Check radii
136 std::ostringstream message;
137 message << "Invalid radii." << std::endl
138 << "Invalid values for radii in solid " << GetName() << std::endl
139 << " newRMin = " << newRMin
140 << ", fRMax = " << fRMax << std::endl
141 << " Negative inner radius!";
142 UUtils::Exception("UTubs::SetInnerRadius()", "GeomSolids0002",
143 UFatalError, 1, message.str().c_str());
150 void UTubs::SetOuterRadius(double newRMax)
152 if (newRMax <= 0) // Check radii
154 std::ostringstream message;
155 message << "Invalid radii." << std::endl
156 << "Invalid values for radii in solid " << GetName() << std::endl
157 << " fRMin = " << fRMin
158 << ", newRMax = " << newRMax << std::endl
159 << " Invalid outer radius!";
160 UUtils::Exception("UTubs::SetOuterRadius()", "GeomSolids0002",
161 UFatalError, 1, message.str().c_str());
168 void UTubs::SetZHalfLength(double newDz)
170 if (newDz <= 0) // Check z-len
172 std::ostringstream message;
173 message << "Invalid Z half-length." << std::endl
174 << "Negative Z half-length (" << newDz << "), for solid: "
176 UUtils::Exception("UTubs::SetZHalfLength()", "GeomSolids0002",
177 UFatalError, 1, message.str().c_str());
184 void UTubs::SetStartPhiAngle(double newSPhi, bool compute)
186 // Flag 'compute' can be used to explicitely avoid recomputation of
187 // trigonometry in case SetDeltaPhiAngle() is invoked afterwards
189 CheckSPhiAngle(newSPhi);
190 fPhiFullTube = false;
193 InitializeTrigonometry();
199 void UTubs::SetDeltaPhiAngle(double newDPhi)
201 CheckPhiAngles(fSPhi, newDPhi);
205 // Older names for access functions
208 double UTubs::GetRMin() const
210 return GetInnerRadius();
214 double UTubs::GetRMax() const
216 return GetOuterRadius();
220 double UTubs::GetDz() const
222 return GetZHalfLength() ;
226 double UTubs::GetSPhi() const
228 return GetStartPhiAngle();
232 double UTubs::GetDPhi() const
234 return GetDeltaPhiAngle();
238 double UTubs::Capacity()
240 if (fCubicVolume != 0.)
246 fCubicVolume = fDPhi * fDz * (fRMax * fRMax - fRMin * fRMin);
252 double UTubs::SurfaceArea()
254 if (fSurfaceArea != 0.)
260 fSurfaceArea = fDPhi * (fRMin + fRMax) * (2 * fDz + fRMax - fRMin);
263 fSurfaceArea = fSurfaceArea + 4 * fDz * (fRMax - fRMin);
270 double UTubs::SafetyFromInsideR(const UVector3& p,
271 const double rho, bool) const
273 // Safety From Inside R, used for UPolycone Section
275 double safe = 0.0, safeR1, safeR2, safePhi;
279 safeR1 = rho - fRMin;
280 safeR2 = fRMax - rho;
296 // Check if phi divided, Calc distances closest phi plane
300 if (p.y() * fCosCPhi - p.x() * fSinCPhi <= 0)
302 safePhi = -(p.x() * fSinSPhi - p.y() * fCosSPhi);
306 safePhi = (p.x() * fSinEPhi - p.y() * fCosEPhi);
318 double UTubs::SafetyFromOutsideR(const UVector3& p,
319 const double rho, bool) const
321 // Safety for R ,used in UPolycone for sections
323 double safe = 0.0, safe1, safe2;
326 safe1 = rho-fRMin; //fRMin - rho;
338 if ((!fPhiFullTube) && (rho))
340 safePhi = SafetyToPhi(p,rho,outside);
341 if ((outside) && (safePhi > safe))
347 return safe; // not accurate safety
351 double UTubs::SafetyToPhi(const UVector3& p,
352 const double rho, bool& outside) const
354 double cosPsi, safePhi = 0.0;
356 // Psi=angle from central phi to point
358 cosPsi = (p.x() * fCosCPhi + p.y() * fSinCPhi) / rho;
360 if (cosPsi < std::cos(fDPhi * 0.5))
362 // Point lies outside phi range
365 if ((p.y() * fCosCPhi - p.x() * fSinCPhi) <= 0)
367 safePhi = std::fabs(p.x() * fSinSPhi - p.y() * fCosSPhi);
371 safePhi = std::fabs(p.x() * fSinEPhi - p.y() * fCosEPhi);