510 lines
9.6 KiB
Plaintext
510 lines
9.6 KiB
Plaintext
//
|
|
// ********************************************************************
|
|
// * This Software is part of the AIDA Unified Solids Library package *
|
|
// * See: https://aidasoft.web.cern.ch/USolids *
|
|
// ********************************************************************
|
|
//
|
|
// $Id:$
|
|
//
|
|
// --------------------------------------------------------------------
|
|
//
|
|
// UCons.icc
|
|
//
|
|
// Implementation of inline methods of UCons
|
|
//
|
|
// 19.10.12 Marek Gayer
|
|
// Created from original implementation in Geant4
|
|
// --------------------------------------------------------------------
|
|
|
|
inline
|
|
double UCons::GetInnerRadiusMinusZ() const
|
|
{
|
|
return fRmin1 ;
|
|
}
|
|
|
|
inline
|
|
double UCons::GetOuterRadiusMinusZ() const
|
|
{
|
|
return fRmax1 ;
|
|
}
|
|
|
|
inline
|
|
double UCons::GetInnerRadiusPlusZ() const
|
|
{
|
|
return fRmin2 ;
|
|
}
|
|
|
|
inline
|
|
double UCons::GetOuterRadiusPlusZ() const
|
|
{
|
|
return fRmax2 ;
|
|
}
|
|
|
|
inline
|
|
double UCons::GetZHalfLength() const
|
|
{
|
|
return fDz ;
|
|
}
|
|
|
|
inline
|
|
double UCons::GetStartPhiAngle() const
|
|
{
|
|
return fSPhi ;
|
|
}
|
|
|
|
inline
|
|
double UCons::GetDeltaPhiAngle() const
|
|
{
|
|
return fDPhi;
|
|
}
|
|
|
|
inline
|
|
void UCons::Initialize()
|
|
{
|
|
fCubicVolume = 0.;
|
|
fSurfaceArea = 0.;
|
|
|
|
tanRMin = (fRmin2 - fRmin1) * 0.5 / fDz;
|
|
secRMin = std::sqrt(1.0 + tanRMin * tanRMin);
|
|
|
|
tanRMax = (fRmax2 - fRmax1) * 0.5 / fDz;
|
|
secRMax = std::sqrt(1.0 + tanRMax * tanRMax);
|
|
}
|
|
|
|
inline
|
|
void UCons::InitializeTrigonometry()
|
|
{
|
|
double hDPhi = 0.5 * fDPhi; // half delta phi
|
|
double cPhi = fSPhi + hDPhi;
|
|
double ePhi = fSPhi + fDPhi;
|
|
|
|
sinCPhi = std::sin(cPhi);
|
|
cosCPhi = std::cos(cPhi);
|
|
cosHDPhiIT = std::cos(hDPhi - 0.5 * kAngTolerance); // inner/outer tol half dphi
|
|
cosHDPhiOT = std::cos(hDPhi + 0.5 * kAngTolerance);
|
|
sinSPhi = std::sin(fSPhi);
|
|
cosSPhi = std::cos(fSPhi);
|
|
sinEPhi = std::sin(ePhi);
|
|
cosEPhi = std::cos(ePhi);
|
|
}
|
|
|
|
inline void UCons::CheckSPhiAngle(double sPhi)
|
|
{
|
|
// Ensure fSphi in 0-2PI or -2PI-0 range if shape crosses 0
|
|
|
|
if (sPhi < 0)
|
|
{
|
|
fSPhi = 2 * UUtils::kPi - std::fmod(std::fabs(sPhi), 2 * UUtils::kPi);
|
|
}
|
|
else
|
|
{
|
|
fSPhi = std::fmod(sPhi, 2 * UUtils::kPi) ;
|
|
}
|
|
if (fSPhi + fDPhi > 2 * UUtils::kPi)
|
|
{
|
|
fSPhi -= 2 * UUtils::kPi ;
|
|
}
|
|
}
|
|
|
|
inline void UCons::CheckDPhiAngle(double dPhi)
|
|
{
|
|
fPhiFullCone = true;
|
|
if (dPhi >= 2 * UUtils::kPi - kAngTolerance * 0.5)
|
|
{
|
|
fDPhi = 2 * UUtils::kPi;
|
|
fSPhi = 0;
|
|
}
|
|
else
|
|
{
|
|
fPhiFullCone = false;
|
|
if (dPhi > 0)
|
|
{
|
|
fDPhi = dPhi;
|
|
}
|
|
else
|
|
{
|
|
std::ostringstream message;
|
|
message << "Invalid dphi." << std::endl
|
|
<< "Negative or zero delta-Phi (" << dPhi << ") in solid: "
|
|
<< GetName();
|
|
UUtils::Exception("UCons::CheckDPhiAngle()", "GeomSolids0002",
|
|
FatalErrorInArguments, 1, message.str().c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
inline void UCons::CheckPhiAngles(double sPhi, double dPhi)
|
|
{
|
|
CheckDPhiAngle(dPhi);
|
|
if ((fDPhi < 2 * UUtils::kPi) && (sPhi))
|
|
{
|
|
CheckSPhiAngle(sPhi);
|
|
}
|
|
InitializeTrigonometry();
|
|
}
|
|
|
|
inline
|
|
void UCons::SetInnerRadiusMinusZ(double Rmin1)
|
|
{
|
|
fRmin1 = Rmin1 ;
|
|
Initialize();
|
|
}
|
|
|
|
inline
|
|
void UCons::SetOuterRadiusMinusZ(double Rmax1)
|
|
{
|
|
fRmax1 = Rmax1 ;
|
|
Initialize();
|
|
}
|
|
|
|
inline
|
|
void UCons::SetInnerRadiusPlusZ(double Rmin2)
|
|
{
|
|
fRmin2 = Rmin2 ;
|
|
Initialize();
|
|
}
|
|
|
|
inline
|
|
void UCons::SetOuterRadiusPlusZ(double Rmax2)
|
|
{
|
|
fRmax2 = Rmax2 ;
|
|
Initialize();
|
|
}
|
|
|
|
inline
|
|
void UCons::SetZHalfLength(double newDz)
|
|
{
|
|
fDz = newDz ;
|
|
Initialize();
|
|
}
|
|
|
|
inline
|
|
void UCons::SetStartPhiAngle(double newSPhi, bool compute)
|
|
{
|
|
// Flag 'compute' can be used to explicitely avoid recomputation of
|
|
// trigonometry in case SetDeltaPhiAngle() is invoked afterwards
|
|
|
|
CheckSPhiAngle(newSPhi);
|
|
fPhiFullCone = false;
|
|
if (compute)
|
|
{
|
|
InitializeTrigonometry();
|
|
}
|
|
Initialize();
|
|
}
|
|
|
|
void UCons::SetDeltaPhiAngle(double newDPhi)
|
|
{
|
|
CheckPhiAngles(fSPhi, newDPhi);
|
|
Initialize();
|
|
}
|
|
|
|
// Old access methods ...
|
|
|
|
inline
|
|
double UCons::GetRmin1() const
|
|
{
|
|
return GetInnerRadiusMinusZ();
|
|
}
|
|
|
|
inline
|
|
double UCons::GetRmax1() const
|
|
{
|
|
return GetOuterRadiusMinusZ();
|
|
}
|
|
|
|
inline
|
|
double UCons::GetRmin2() const
|
|
{
|
|
return GetInnerRadiusPlusZ();
|
|
}
|
|
|
|
inline
|
|
double UCons::GetRmax2() const
|
|
{
|
|
return GetOuterRadiusPlusZ();
|
|
}
|
|
|
|
inline
|
|
double UCons::GetDz() const
|
|
{
|
|
return GetZHalfLength();
|
|
}
|
|
|
|
inline
|
|
double UCons::GetSPhi() const
|
|
{
|
|
return GetStartPhiAngle();
|
|
}
|
|
|
|
inline
|
|
double UCons::GetDPhi() const
|
|
{
|
|
return GetDeltaPhiAngle();
|
|
}
|
|
|
|
inline
|
|
double UCons::Capacity()
|
|
{
|
|
if (fCubicVolume != 0.)
|
|
{
|
|
;
|
|
}
|
|
else
|
|
{
|
|
double Rmean, rMean, deltaR, deltar;
|
|
|
|
Rmean = 0.5 * (fRmax1 + fRmax2);
|
|
deltaR = fRmax1 - fRmax2;
|
|
|
|
rMean = 0.5 * (fRmin1 + fRmin2);
|
|
deltar = fRmin1 - fRmin2;
|
|
fCubicVolume = fDPhi * fDz * (Rmean * Rmean - rMean * rMean
|
|
+ (deltaR * deltaR - deltar * deltar) / 12);
|
|
}
|
|
return fCubicVolume;
|
|
}
|
|
|
|
inline
|
|
double UCons::SurfaceArea()
|
|
{
|
|
if (fSurfaceArea != 0.)
|
|
{
|
|
;
|
|
}
|
|
else
|
|
{
|
|
double mmin, mmax, dmin, dmax;
|
|
|
|
mmin = (fRmin1 + fRmin2) * 0.5;
|
|
mmax = (fRmax1 + fRmax2) * 0.5;
|
|
dmin = (fRmin2 - fRmin1);
|
|
dmax = (fRmax2 - fRmax1);
|
|
|
|
fSurfaceArea = fDPhi * (mmin * std::sqrt(dmin * dmin + 4 * fDz * fDz)
|
|
+ mmax * std::sqrt(dmax * dmax + 4 * fDz * fDz)
|
|
+ 0.5 * (fRmax1 * fRmax1 - fRmin1 * fRmin1
|
|
+ fRmax2 * fRmax2 - fRmin2 * fRmin2));
|
|
if (!fPhiFullCone)
|
|
{
|
|
fSurfaceArea = fSurfaceArea + 4 * fDz * (mmax - mmin);
|
|
}
|
|
}
|
|
return fSurfaceArea;
|
|
}
|
|
|
|
inline
|
|
double UCons::SafetyToPhi(const UVector3& p,
|
|
const double rho, bool& outside) const
|
|
{
|
|
double cosPsi, safePhi = 0.0;
|
|
outside = false;
|
|
|
|
cosPsi = (p.x * cosCPhi + p.y * sinCPhi) / rho;
|
|
|
|
if (cosPsi < std::cos(fDPhi * 0.5)) // Point lies outside phi range
|
|
{
|
|
outside = true;
|
|
if ((p.y * cosCPhi - p.x * sinCPhi) <= 0.0)
|
|
{
|
|
safePhi = std::fabs(p.x * std::sin(fSPhi) - p.y * std::cos(fSPhi));
|
|
}
|
|
else
|
|
{
|
|
safePhi = std::fabs(p.x * sinEPhi - p.y * cosEPhi);
|
|
}
|
|
}
|
|
return safePhi;
|
|
}
|
|
|
|
inline
|
|
double UCons::SafetyFromInsideR(const UVector3& p,
|
|
const double rho, bool) const
|
|
{
|
|
double safe = 0.0, safeR1, safeR2, safePhi;
|
|
double pRMin;
|
|
double pRMax;
|
|
|
|
if (fRmin1 || fRmin2)
|
|
{
|
|
pRMin = tanRMin * p.z + (fRmin1 + fRmin2) * 0.5;
|
|
safeR1 = (rho - pRMin) / secRMin;
|
|
}
|
|
else
|
|
{
|
|
safeR1 = UUtils::kInfinity;
|
|
}
|
|
|
|
pRMax = tanRMax * p.z + (fRmax1 + fRmax2) * 0.5;
|
|
safeR2 = (pRMax - rho) / secRMax;
|
|
|
|
if (safeR1 < safeR2)
|
|
{
|
|
safe = safeR1;
|
|
}
|
|
else
|
|
{
|
|
safe = safeR2;
|
|
}
|
|
|
|
// Check if phi divided, Calc distances closest phi plane
|
|
//
|
|
if (!fPhiFullCone)
|
|
{
|
|
// Above/below central phi of UCons?
|
|
|
|
if ((p.y * cosCPhi - p.x * sinCPhi) <= 0)
|
|
{
|
|
safePhi = -(p.x * sinSPhi - p.y * cosSPhi);
|
|
}
|
|
else
|
|
{
|
|
safePhi = (p.x * sinEPhi - p.y * cosEPhi);
|
|
}
|
|
if (safePhi < safe)
|
|
{
|
|
safe = safePhi;
|
|
}
|
|
}
|
|
|
|
if (safe < 0)
|
|
{
|
|
safe = 0;
|
|
}
|
|
|
|
return safe;
|
|
}
|
|
|
|
inline
|
|
double UCons::SafetyFromOutsideR(const UVector3& p,
|
|
const double rho, bool) const
|
|
{
|
|
double safe = 0.0, safeR1, safeR2;
|
|
double safePhi;
|
|
double pRMin, pRMax;
|
|
bool outside;
|
|
if (fRmin1 || fRmin2)
|
|
{
|
|
pRMin = tanRMin * p.z + (fRmin1 + fRmin2) * 0.5;
|
|
safeR1 = (rho-pRMin ) / secRMin;
|
|
|
|
pRMax = tanRMax * p.z + (fRmax1 + fRmax2) * 0.5;
|
|
safeR2 = (rho - pRMax) / secRMax;
|
|
|
|
if (safeR1 > safeR2)
|
|
{
|
|
safe = safeR1;
|
|
}
|
|
else
|
|
{
|
|
safe = safeR2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pRMax = tanRMax * p.z + (fRmax1 + fRmax2) * 0.5;
|
|
safe = (rho - pRMax) / secRMax;
|
|
}
|
|
if (!fPhiFullCone)
|
|
{
|
|
safePhi=SafetyToPhi(p,rho,outside);
|
|
if ((outside) && (safePhi > safe))
|
|
{
|
|
safe = safePhi;
|
|
}
|
|
}
|
|
|
|
if (safe < 0.0)
|
|
{
|
|
safe = 0.0;
|
|
}
|
|
return safe; // not accurate safety
|
|
}
|
|
|
|
inline
|
|
VUSolid::EnumInside UCons::Inside(const UVector3& p) const
|
|
{
|
|
double r2, rl, rh, pPhi, tolRMin, tolRMax; // rh2, rl2;
|
|
VUSolid::EnumInside in;
|
|
static const double halfCarTolerance = VUSolid::Tolerance() * 0.5;
|
|
static const double halfRadTolerance = kRadTolerance * 0.5;
|
|
static const double halfAngTolerance = kAngTolerance * 0.5;
|
|
|
|
if (std::fabs(p.z) > fDz + halfCarTolerance)
|
|
{
|
|
return in = eOutside;
|
|
}
|
|
else if (std::fabs(p.z) >= fDz - halfCarTolerance)
|
|
{
|
|
in = eSurface;
|
|
}
|
|
else
|
|
{
|
|
in = eInside;
|
|
}
|
|
r2 = p.x * p.x + p.y * p.y;
|
|
rl = 0.5 * (fRmin2 * (p.z + fDz) + fRmin1 * (fDz - p.z)) / fDz;
|
|
rh = 0.5 * (fRmax2 * (p.z + fDz) + fRmax1 * (fDz - p.z)) / fDz;
|
|
|
|
tolRMin = rl - halfRadTolerance;
|
|
if (tolRMin < 0)
|
|
{
|
|
tolRMin = 0;
|
|
}
|
|
tolRMax = rh + halfRadTolerance;
|
|
|
|
if ((r2 < tolRMin * tolRMin) || (r2 > tolRMax * tolRMax))
|
|
{
|
|
return in = eOutside;
|
|
}
|
|
if (rl)
|
|
{
|
|
tolRMin = rl + halfRadTolerance;
|
|
}
|
|
else
|
|
{
|
|
tolRMin = 0.0;
|
|
}
|
|
|
|
tolRMax = rh - halfRadTolerance;
|
|
if (in == eInside) // else it's eSurface already
|
|
{
|
|
if ((r2 < tolRMin * tolRMin) || (r2 >= tolRMax * tolRMax))
|
|
{
|
|
in = eSurface;
|
|
}
|
|
}
|
|
if (!fPhiFullCone && ((p.x != 0.0) || (p.y != 0.0)))
|
|
{
|
|
pPhi = std::atan2(p.y, p.x);
|
|
if (pPhi < fSPhi - halfAngTolerance)
|
|
{
|
|
pPhi += 2 * UUtils::kPi;
|
|
}
|
|
else if (pPhi > fSPhi + fDPhi + halfAngTolerance)
|
|
{
|
|
pPhi -= 2 * UUtils::kPi;
|
|
}
|
|
|
|
if ((pPhi < fSPhi - halfAngTolerance) ||
|
|
(pPhi > fSPhi + fDPhi + halfAngTolerance))
|
|
{
|
|
return in = eOutside;
|
|
}
|
|
else if (in == eInside) // else it's eSurface anyway already
|
|
{
|
|
if ((pPhi < fSPhi + halfAngTolerance) ||
|
|
(pPhi > fSPhi + fDPhi - halfAngTolerance))
|
|
{
|
|
in = eSurface;
|
|
}
|
|
}
|
|
}
|
|
else if (!fPhiFullCone)
|
|
{
|
|
in = eSurface;
|
|
}
|
|
|
|
return in;
|
|
}
|