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                         FatalError, 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                       FatalError, 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                       FatalError, 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                       FatalError, 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);