#include "Riostream.h"
#include "TGeoManager.h"
#include "TGeoVolume.h"
#include "TVirtualGeoPainter.h"
#include "TGeoHype.h"
#include "TVirtualPad.h"
#include "TBuffer3D.h"
#include "TBuffer3DTypes.h"
#include "TMath.h"
ClassImp(TGeoHype)
   
TGeoHype::TGeoHype()
{
   SetShapeBit(TGeoShape::kGeoHype);
   fStIn = 0.;
   fStOut = 0.;
   fTin = 0.;
   fTinsq = 0.;
   fTout = 0.;
   fToutsq = 0.;
}   
TGeoHype::TGeoHype(Double_t rin, Double_t stin, Double_t rout, Double_t stout, Double_t dz)
         :TGeoTube(rin, rout, dz)
{
   SetShapeBit(TGeoShape::kGeoHype);
   SetHypeDimensions(rin, stin, rout, stout, dz);
   
   if (fDz<0) SetShapeBit(kGeoRunTimeShape); 
   ComputeBBox();
}
TGeoHype::TGeoHype(const char *name,Double_t rin, Double_t stin, Double_t rout, Double_t stout, Double_t dz)
         :TGeoTube(name, rin, rout, dz)
{
   SetShapeBit(TGeoShape::kGeoHype);
   SetHypeDimensions(rin, stin, rout, stout, dz);
   
   if (fDz<0) SetShapeBit(kGeoRunTimeShape); 
   ComputeBBox();
}
TGeoHype::TGeoHype(Double_t *param)
         :TGeoTube(param[1],param[3],param[0])
{
   SetShapeBit(TGeoShape::kGeoHype);
   SetDimensions(param);
   
   if (fDz<0) SetShapeBit(kGeoRunTimeShape); 
   ComputeBBox();
}
TGeoHype::~TGeoHype()
{
}
Double_t TGeoHype::Capacity() const
{
   Double_t capacity = 2.*TMath::Pi()*fDz*(fRmax*fRmax-fRmin*fRmin) +
                       (2.*TMath::Pi()/3.)*fDz*fDz*fDz*(fToutsq-fTinsq);
   return capacity;                    
}   
void TGeoHype::ComputeBBox()
{
   if (fRmin<0.) {
      Warning("ComputeBBox", "Shape %s has invalid rmin=%g ! SET TO 0.", fRmin);
      fRmin = 0.;
   }
   if ((fRmin>fRmax) || (fRmin*fRmin+fTinsq*fDz*fDz > fRmax*fRmax+fToutsq*fDz*fDz)) {
      SetShapeBit(kGeoInvalidShape);
      Error("ComputeBBox", "Shape %s hyperbolic surfaces are malformed: rin=%g, stin=%g, rout=%g, stout=%g",
             GetName(), fRmin, fStIn, fRmax, fStOut);
      return;       
   }   
   
   fDX = fDY = TMath::Sqrt(RadiusHypeSq(fDz, kFALSE));
   fDZ = fDz;
}   
void TGeoHype::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
{
   Double_t saf[3];
   Double_t rsq = point[0]*point[0]+point[1]*point[1];
   Double_t r = TMath::Sqrt(rsq);
   Double_t rin = (HasInner())?(TMath::Sqrt(RadiusHypeSq(point[2],kTRUE))):0.;
   Double_t rout = TMath::Sqrt(RadiusHypeSq(point[2],kFALSE));
   saf[0] = TMath::Abs(fDz-TMath::Abs(point[2])); 
   saf[1] = (HasInner())?TMath::Abs(rin-r):TGeoShape::Big();
   saf[2] = TMath::Abs(rout-r);
   Int_t i = TMath::LocMin(3,saf);
   if (i==0 || r<1.E-10) {
      norm[0] = norm[1] = 0.;
      norm[2] = TMath::Sign(1.,dir[2]);
      return;
   }
   Double_t t = (i==1)?fTinsq:fToutsq;;
   t *= -point[2]/r;
   Double_t ct = TMath::Sqrt(1./(1.+t*t));
   Double_t st = t * ct;
   Double_t phi = TMath::ATan2(point[1], point[0]);
   Double_t cphi = TMath::Cos(phi);
   Double_t sphi = TMath::Sin(phi);
   
   norm[0] = ct*cphi;
   norm[1] = ct*sphi;
   norm[2] = st;
   if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
      norm[0] = -norm[0];
      norm[1] = -norm[1];
      norm[2] = -norm[2];
   }   
}
Bool_t TGeoHype::Contains(Double_t *point) const
{
   if (TMath::Abs(point[2]) > fDz) return kFALSE;
   Double_t r2 = point[0]*point[0]+point[1]*point[1];
   Double_t routsq = RadiusHypeSq(point[2], kFALSE);
   if (r2>routsq) return kFALSE;
   if (!HasInner()) return kTRUE;
   Double_t rinsq = RadiusHypeSq(point[2], kTRUE);
   if (r2<rinsq) return kFALSE;
   return kTRUE;
}
Int_t TGeoHype::DistancetoPrimitive(Int_t px, Int_t py)
{
   Int_t numPoints = GetNmeshVertices();
   return ShapeDistancetoPrimitive(numPoints, px, py);
}
Double_t TGeoHype::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
{
   if (iact<3 && safe) {
      *safe = Safety(point, kTRUE);
      if (iact==0) return TGeoShape::Big();
      if ((iact==1) && (*safe>step)) return TGeoShape::Big();
   }
   
   
   Double_t sz = TGeoShape::Big();
   if (dir[2]>0) { 
      sz = (fDz-point[2])/dir[2];
      if (sz<=0.) return 0.;      
   } else {
      if (dir[2]<0) {
         sz = -(fDz+point[2])/dir[2];
         if (sz<=0.) return 0.; 
      }
   }           
   
   
   
   Double_t srin = TGeoShape::Big();
   Double_t srout = TGeoShape::Big();
   Double_t sr;
   
   Double_t s[2];
   Int_t npos;
   npos = DistToHype(point, dir, s, kTRUE);
   if (npos) srin = s[0];
   npos = DistToHype(point, dir, s, kFALSE);
   if (npos) srout = s[0];
   sr = TMath::Min(srin, srout);
   return TMath::Min(sz,sr);
}
Double_t TGeoHype::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
{
   if (iact<3 && safe) {
      *safe = Safety(point, kFALSE);
      if (iact==0) return TGeoShape::Big();
      if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
   }
   
   
   Double_t xi, yi, zi;
   Double_t sz = TGeoShape::Big();
   if (TMath::Abs(point[2])>=fDz) { 
      
      if ((point[2]*dir[2]) < 0) {
         
         sz = (TMath::Abs(point[2])-fDz)/TMath::Abs(dir[2]);
         
         xi = point[0]+sz*dir[0];
         yi = point[1]+sz*dir[1];
         Double_t r2 = xi*xi + yi*yi;
         Double_t rmin2 = RadiusHypeSq(fDz, kTRUE);
         if (r2 >= rmin2) {
            Double_t rmax2 = RadiusHypeSq(fDz, kFALSE);
            if (r2 <= rmax2) return sz;
         }
      }
   }
   
   Double_t sin = TGeoShape::Big();
   Double_t sout = TGeoShape::Big();
   Double_t s[2];
   Int_t npos;
   npos = DistToHype(point, dir, s, kTRUE);
   if (npos) {
      zi = point[2] + s[0]*dir[2];
      if (TMath::Abs(zi) <= fDz) sin = s[0];
      else if (npos==2) {
         zi = point[2] + s[1]*dir[2];
         if (TMath::Abs(zi) <= fDz) sin = s[1];
      }
   }      
   npos = DistToHype(point, dir, s, kFALSE);
   if (npos) {
      zi = point[2] + s[0]*dir[2]; 
      if (TMath::Abs(zi) <= fDz) sout = s[0];
      else if (npos==2) {
         zi = point[2] + s[1]*dir[2];
         if (TMath::Abs(zi) <= fDz) sout = s[1];
      }      
   }   
   return TMath::Min(sin, sout);
}
Int_t TGeoHype::DistToHype(Double_t *point, Double_t *dir, Double_t *s, Bool_t inner) const
{
   Double_t r0, t0, snext;
   if (inner) {
      if (!HasInner()) return 0;
      r0 = fRmin;
      t0 = fTinsq;
   } else {
      r0 = fRmax;
      t0 = fToutsq;
   }
   Double_t a = dir[0]*dir[0] + dir[1]*dir[1] - t0*dir[2]*dir[2];
   Double_t b = t0*point[2]*dir[2] - point[0]*dir[0] - point[1]*dir[1];
   Double_t c = point[0]*point[0] + point[1]*point[1] - t0*point[2]*point[2] - r0*r0;      
   if (a == 0.) {
      if (b == 0.) return 0;
      snext = 0.5*c/b;
      if (snext < 0.) return 0;
      s[0] = snext;
      return 1;
   }
   
   Double_t delta = b*b - a*c;
   Double_t ainv = 1./a;
   Int_t npos = 0;
   if (delta < 0.) return 0;
   delta = TMath::Sqrt(delta); 
   Double_t sone = TMath::Sign(1.,ainv);
   snext = (b - sone*delta)*ainv;
   if (snext >= 0.) s[npos++] = snext;
   snext = (b + sone*delta)*ainv;
   if (snext >= 0.) s[npos++] = snext;
   return npos;
}
   
TGeoVolume *TGeoHype::Divide(TGeoVolume * , const char *divname, Int_t , Int_t , 
                             Double_t , Double_t ) 
{
   Error("Divide", "Hyperboloids cannot be divided. Division volume %s not created", divname);
   return 0;
}   
Double_t TGeoHype::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
{
   xlo = 0;
   xhi = 0;
   Double_t dx = 0;
   switch (iaxis) {
      case 1: 
         xlo = fRmin;
         xhi = TMath::Sqrt(RadiusHypeSq(fDz, kFALSE));
         dx = xhi-xlo;
         return dx;
      case 2: 
         xlo = 0;
         xhi = 360;
         dx = 360;
         return dx;
      case 3: 
         xlo = -fDz;
         xhi = fDz;
         dx = xhi-xlo;
         return dx;
   }
   return dx;
}         
            
void TGeoHype::GetBoundingCylinder(Double_t *param) const
{
   param[0] = fRmin; 
   param[0] *= param[0];
   param[1] = TMath::Sqrt(RadiusHypeSq(fDz, kFALSE)); 
   param[1] *= param[1];
   param[2] = 0.;    
   param[3] = 360.;  
}
TGeoShape *TGeoHype::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * ) const
{
   if (!TestShapeBit(kGeoRunTimeShape)) return 0;
   Double_t rmin, rmax, dz;
   Double_t zmin,zmax;
   rmin = fRmin;
   rmax = fRmax;
   dz = fDz;
   if (fDz<0) {
      mother->GetAxisRange(3,zmin,zmax);
      if (zmax<0) return 0;
      dz=zmax;
   } else {
      Error("GetMakeRuntimeShape", "Shape %s does not have negative Z range", GetName());   
      return 0;
   }   
   TGeoShape *hype = new TGeoHype(GetName(), dz, fRmax, fStOut, fRmin, fStIn);
   return hype;
}
void TGeoHype::InspectShape() const
{
   printf("*** Shape %s: TGeoHype ***\n", GetName());
   printf("    Rin  = %11.5f\n", fRmin);
   printf("    sin  = %11.5f\n", fStIn);
   printf("    Rout = %11.5f\n", fRmax);
   printf("    sout = %11.5f\n", fStOut);
   printf("    dz   = %11.5f\n", fDz);
   
   printf(" Bounding box:\n");
   TGeoBBox::InspectShape();
}
TBuffer3D *TGeoHype::MakeBuffer3D() const
{ 
   
   
   Int_t n = gGeoManager->GetNsegments();
   Bool_t hasRmin = HasInner();
   Int_t nbPnts = (hasRmin)?(2*n*n):(n*n+2);
   Int_t nbSegs = (hasRmin)?(4*n*n):(n*(2*n+1));
   Int_t nbPols = (hasRmin)?(2*n*n):(n*(n+1)); 
   TBuffer3D* buff = new TBuffer3D(TBuffer3DTypes::kGeneric,
                                   nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols);
   if (buff)
   {
      SetPoints(buff->fPnts);
      SetSegsAndPols(*buff);
   }
   return buff; 
}
void TGeoHype::SetSegsAndPols(TBuffer3D &buff) const
{
   Int_t c = GetBasicColor();
   Int_t i, j, n;
   n = gGeoManager->GetNsegments();
   Bool_t hasRmin = HasInner();
   Int_t irin = 0;
   Int_t irout = (hasRmin)?(n*n):2;
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   Int_t isin = 0;
   Int_t isgenin = (hasRmin)?(isin+n*n):0;
   Int_t isout = (hasRmin)?(isgenin+n*(n-1)):0;
   Int_t isgenout  = isout+n*n;
   Int_t islo = isgenout+n*(n-1);
   Int_t ishi = islo + n;
   Int_t npt = 0;
   
   if (hasRmin) {
      for (i=0; i<n; i++) {
         for (j=0; j<n; j++) {
            npt = 3*(isin+n*i+j);
            buff.fSegs[npt]   = c;
            buff.fSegs[npt+1] = irin+n*i+j;
            buff.fSegs[npt+2] = irin+n*i+((j+1)%n);
         }
      }
      
      for (i=0; i<n-1; i++) {
         for (j=0; j<n; j++) {
            npt = 3*(isgenin+n*i+j);
            buff.fSegs[npt]   = c;
            buff.fSegs[npt+1] = irin+n*i+j;
            buff.fSegs[npt+2] = irin+n*(i+1)+j;
         }
      }      
   }
   
   for (i=0; i<n; i++) {   
      for (j=0; j<n; j++) { 
         npt = 3*(isout + n*i+j);     
         buff.fSegs[npt]   = c;
         buff.fSegs[npt+1] = irout+n*i+j;
         buff.fSegs[npt+2] = irout+n*i+((j+1)%n);
      }
   }      
   
   for (i=0; i<n-1; i++) {
      for (j=0; j<n; j++) {
         npt = 3*(isgenout+n*i+j);
         buff.fSegs[npt]   = c;
         buff.fSegs[npt+1] = irout+n*i+j;
         buff.fSegs[npt+2] = irout+n*(i+1)+j;
      }
   }      
   
   for (j=0; j<n; j++) {
      npt = 3*(islo+j);
      buff.fSegs[npt]   = c;
      buff.fSegs[npt+1] = irin;
      if (hasRmin) buff.fSegs[npt+1] += j;
      buff.fSegs[npt+2] = irout + j;
   }   
   
   for (j=0; j<n; j++) {
      npt = 3*(ishi+j);
      buff.fSegs[npt]   = c;
      buff.fSegs[npt+1] = irin+1;
      if (hasRmin) buff.fSegs[npt+1] += n*(n-1)+j-1;
      buff.fSegs[npt+2] = irout + n*(n-1)+j;
   }   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   Int_t ipin = 0;
   Int_t ipout = (hasRmin)?(ipin+n*(n-1)):0;
   Int_t iplo = ipout+n*(n-1);
   Int_t ipup = iplo+n;
   
   if (hasRmin) {
      for (i=0; i<n-1; i++) {
         for (j=0; j<n; j++) {
            npt = 6*(ipin+n*i+j);
            buff.fPols[npt]   = c;
            buff.fPols[npt+1] = 4;
            buff.fPols[npt+2] = isin+n*i+j;
            buff.fPols[npt+3] = isgenin+i*n+((j+1)%n);
            buff.fPols[npt+4] = isin+n*(i+1)+j;
            buff.fPols[npt+5] = isgenin+i*n+j;
         }
      }
   }
   
   for (i=0; i<n-1; i++) {        
      for (j=0; j<n; j++) {
         npt = 6*(ipout+n*i+j);
         buff.fPols[npt]   = c;
         buff.fPols[npt+1] = 4;
         buff.fPols[npt+2] = isout+n*i+j;
         buff.fPols[npt+3] = isgenout+i*n+j;
         buff.fPols[npt+4] = isout+n*(i+1)+j;
         buff.fPols[npt+5] = isgenout+i*n+((j+1)%n);
      }
   }
   
   if (hasRmin) {
      for (j=0; j<n; j++) {  
         npt = 6*(iplo+j);
         buff.fPols[npt]   = c+1;
         buff.fPols[npt+1] = 4;
         buff.fPols[npt+2] = isin+j;
         buff.fPols[npt+3] = islo+j;
         buff.fPols[npt+4] = isout+j;
         buff.fPols[npt+5] = islo+((j+1)%n);
      }
      for (j=0; j<n; j++) {  
         npt = 6*(ipup+j);
         buff.fPols[npt]   = c+2;
         buff.fPols[npt+1] = 4;
         buff.fPols[npt+2] = isin+n*(n-1)+j;
         buff.fPols[npt+3] = ishi+((j+1)%n);
         buff.fPols[npt+4] = isout+n*(n-1)+j;
         buff.fPols[npt+5] = ishi+j;
      }
   } else {      
      for (j=0; j<n; j++) {  
         npt = 6*iplo+5*j;
         buff.fPols[npt]   = c+1;
         buff.fPols[npt+1] = 3;
         buff.fPols[npt+2] = isout+j;
         buff.fPols[npt+3] = islo+((j+1)%n);
         buff.fPols[npt+4] = islo+j;
      }
      for (j=0; j<n; j++) {  
         npt = 6*iplo+5*(n+j);
         buff.fPols[npt]   = c+2;
         buff.fPols[npt+1] = 3;
         buff.fPols[npt+2] = isout+n*(n-1)+j;
         buff.fPols[npt+3] = ishi+j;
         buff.fPols[npt+4] = ishi+((j+1)%n);
      }
   }   
}
Double_t TGeoHype::RadiusHypeSq(Double_t z, Bool_t inner) const
{
   Double_t r0, tsq;
   if (inner) {
      r0 = fRmin;
      tsq = fTinsq;
   } else {
      r0 = fRmax;
      tsq = fToutsq;
   }
   return (r0*r0+tsq*z*z);
}
         
Double_t TGeoHype::ZHypeSq(Double_t r, Bool_t inner) const
{
   Double_t r0, tsq;
   if (inner) {
      r0 = fRmin;
      tsq = fTinsq;
   } else {
      r0 = fRmax;
      tsq = fToutsq;
   }
   if (tsq==0) return TGeoShape::Big();
   return ((r*r-r0*r0)/tsq);
}     
Double_t TGeoHype::Safety(Double_t *point, Bool_t in) const
{
   Double_t safe, safrmin, safrmax;
   if (in) {
      safe    = fDz-TMath::Abs(point[2]); 
      safrmin = SafetyToHype(point, kTRUE, in);
      if (safrmin < safe) safe = safrmin;
      safrmax = SafetyToHype(point, kFALSE,in);
      if (safrmax < safe) safe = safrmax;
   } else {
      safe    = -fDz+TMath::Abs(point[2]);
      safrmin = SafetyToHype(point, kTRUE, in);
      if (safrmin > safe) safe = safrmin;
      safrmax = SafetyToHype(point, kFALSE,in);
      if (safrmax > safe) safe = safrmax;      
   }   
   return safe;
}
Double_t TGeoHype::SafetyToHype(Double_t *point, Bool_t inner, Bool_t in) const
{
   Double_t r, rsq, rhsq, rh, dr, tsq, saf;
   if (inner && !HasInner()) return (in)?TGeoShape::Big():-TGeoShape::Big();
   rsq = point[0]*point[0]+point[1]*point[1];
   r = TMath::Sqrt(rsq);
   rhsq = RadiusHypeSq(point[2], inner);
   rh = TMath::Sqrt(rhsq);
   dr = r - rh;
   if (inner) {
      if (!in && dr>0) return -TGeoShape::Big();
      if (fStIn == 0) return TMath::Abs(dr);
      if (fRmin==0) return TMath::Abs(dr/TMath::Sqrt(1.+ fTinsq));
      tsq = fTinsq;
   } else {
      if (!in && dr<0) return -TGeoShape::Big();
      if (fStOut == 0) return TMath::Abs(dr);
      tsq = fToutsq;
   }
   if (dr==0) return 0.;
   
   Double_t m;
   if (dr<0) {
      m = rh/(tsq*TMath::Abs(point[2]));
      saf = -m*dr/TMath::Sqrt(1.+m*m);
      return saf;
   }
   
   m = (TMath::Sqrt(ZHypeSq(r,inner)) - TMath::Abs(point[2]))/dr;
   saf = m*dr/TMath::Sqrt(1.+m*m);        
   return saf;
}
void TGeoHype::SavePrimitive(ostream &out, Option_t *  )
{
   if (TObject::TestBit(kGeoSavePrimitive)) return;
   out << "   // Shape: " << GetName() << " type: " << ClassName() << endl;
   out << "   rin   = " << fRmin << ";" << endl;
   out << "   stin  = " << fStIn << ";" << endl;
   out << "   rout  = " << fRmax << ";" << endl;
   out << "   stout = " << fStOut << ";" << endl;
   out << "   dz    = " << fDz << ";" << endl;
   out << "   TGeoShape *" << GetPointerName() << " = new TGeoHype(\"" << GetName() << "\",rin,stin,rout,stout,dz);" << endl;
   TObject::SetBit(TGeoShape::kGeoSavePrimitive);  
}
void TGeoHype::SetHypeDimensions(Double_t rin, Double_t stin, Double_t rout, Double_t stout, Double_t dz)
{
   fRmin = rin;
   fRmax = rout;
   fDz   = dz;
   fStIn = stin;
   fStOut = stout;
   fTin = TMath::Tan(fStIn*TMath::DegToRad());
   fTinsq = fTin*fTin;
   fTout = TMath::Tan(fStOut*TMath::DegToRad());
   fToutsq = fTout*fTout;
   if ((fRmin==0) && (fStIn==0)) SetShapeBit(kGeoRSeg, kTRUE);
   else                          SetShapeBit(kGeoRSeg, kFALSE);
}   
void TGeoHype::SetDimensions(Double_t *param)
{
   Double_t dz = param[0];
   Double_t rin = param[1];
   Double_t stin = param[2];
   Double_t rout = param[3];
   Double_t stout = param[4];
   SetHypeDimensions(rin, stin, rout, stout, dz);
}   
void TGeoHype::SetPoints(Double_t *points) const
{
   Double_t z,dz,r;
   Int_t i,j, n;
   if (!points) return;
   n = gGeoManager->GetNsegments();
   Double_t dphi = 360./n;
   Double_t phi = 0;
   dz = 2.*fDz/(n-1);
   Int_t indx = 0;
   if (HasInner()) {
      
      for (i=0; i<n; i++) {
         z = -fDz+i*dz;
         r = TMath::Sqrt(RadiusHypeSq(z, kTRUE));
         for (j=0; j<n; j++) {
            phi = j*dphi*TMath::DegToRad();
            points[indx++] = r * TMath::Cos(phi);
            points[indx++] = r * TMath::Sin(phi);
            points[indx++] = z;
         }
      }
   } else {
      points[indx++] = 0.;
      points[indx++] = 0.;
      points[indx++] = -fDz;
      points[indx++] = 0.;         
      points[indx++] = 0.;
      points[indx++] = fDz;
   }   
   
   for (i=0; i<n; i++) {
      z = -fDz + i*dz;
      r = TMath::Sqrt(RadiusHypeSq(z, kFALSE));
      for (j=0; j<n; j++) {
         phi = j*dphi*TMath::DegToRad();
         points[indx++] = r * TMath::Cos(phi);
         points[indx++] = r * TMath::Sin(phi);
         points[indx++] = z;
      }
   }
}
void TGeoHype::SetPoints(Float_t *points) const
{
   Double_t z,dz,r;
   Int_t i,j, n;
   if (!points) return;
   n = gGeoManager->GetNsegments();
   Double_t dphi = 360./n;
   Double_t phi = 0;
   dz = 2.*fDz/(n-1);
   Int_t indx = 0;
   if (HasInner()) {
      
      for (i=0; i<n; i++) {
         z = -fDz+i*dz;
         r = TMath::Sqrt(RadiusHypeSq(z, kTRUE));
         for (j=0; j<n; j++) {
            phi = j*dphi*TMath::DegToRad();
            points[indx++] = r * TMath::Cos(phi);
            points[indx++] = r * TMath::Sin(phi);
            points[indx++] = z;
         }
      }
   } else {
      points[indx++] = 0.;
      points[indx++] = 0.;
      points[indx++] = -fDz;
      points[indx++] = 0.;         
      points[indx++] = 0.;
      points[indx++] = fDz;
   }   
   
   for (i=0; i<n; i++) {
      z = -fDz + i*dz;
      r = TMath::Sqrt(RadiusHypeSq(z, kFALSE));
      for (j=0; j<n; j++) {
         phi = j*dphi*TMath::DegToRad();
         points[indx++] = r * TMath::Cos(phi);
         points[indx++] = r * TMath::Sin(phi);
         points[indx++] = z;
      }
   }
}
void TGeoHype::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
{
   Int_t n = gGeoManager->GetNsegments();
   Bool_t hasRmin = HasInner();
   nvert = (hasRmin)?(2*n*n):(n*n+2);
   nsegs = (hasRmin)?(4*n*n):(n*(2*n+1));
   npols = (hasRmin)?(2*n*n):(n*(n+1)); 
}
Int_t TGeoHype::GetNmeshVertices() const
{
   Int_t n = gGeoManager->GetNsegments();
   Int_t numPoints = (HasRmin())?(2*n*n):(n*n+2);
   return numPoints;
}
void TGeoHype::Sizeof3D() const
{
}
const TBuffer3D & TGeoHype::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
{
   static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
   TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
   if (reqSections & TBuffer3D::kRawSizes) {
      Int_t n = gGeoManager->GetNsegments();
      Bool_t hasRmin = HasInner();
      Int_t nbPnts = (hasRmin)?(2*n*n):(n*n+2);
      Int_t nbSegs = (hasRmin)?(4*n*n):(n*(2*n+1));
      Int_t nbPols = (hasRmin)?(2*n*n):(n*(n+1)); 
      if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
         buffer.SetSectionsValid(TBuffer3D::kRawSizes);
      }
   }
   if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
      SetPoints(buffer.fPnts);
      if (!buffer.fLocalFrame) {
         TransformPoints(buffer.fPnts, buffer.NbPnts());
      }
      SetSegsAndPols(buffer);      
      buffer.SetSectionsValid(TBuffer3D::kRaw);
   }
      
   return buffer;
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.