Files
geant4/source/externals/usolids/include/UCons.icc
T
2016-06-10 12:08:39 +02:00

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;
}