// @(#)root/geom:$Id$
// Author: Mihaela Gheata   20/11/04

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/


#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"

//_____________________________________________________________________________
// TGeoHype - Hyperboloid class defined by 5 parameters. Bounded by:
//            - Two z planes at z=+/-dz
//            - Inner and outer lateral surfaces. These represent the surfaces
//              described by the revolution of 2 hyperbolas about the Z axis:
//               r^2 - (t*z)^2 = a^2
//
//            r = distance between hyperbola and Z axis at coordinate z
//            t = tangent of the stereo angle (angle made by hyperbola
//                asimptotic lines and Z axis). t=0 means cylindrical surface.
//            a = distance between hyperbola and Z axis at z=0
//
//          The inner hyperbolic surface is described by:
//              r^2 - (tin*z)^2 = rin^2
//           - absence of the inner surface (filled hyperboloid can be forced
//             by rin=0 and sin=0
//          The outer hyperbolic surface is described by:
//              r^2 - (tout*z)^2 = rout^2
//  TGeoHype parameters: dz[cm], rin[cm], sin[deg], rout[cm], sout[deg].
//    MANDATORY conditions:
//           - rin < rout
//           - rout > 0
//           - rin^2 + (tin*dz)^2 > rout^2 + (tout*dz)^2
//    SUPPORTED CASES:
//           - rin = 0, tin != 0     => inner surface conical
//           - tin=0 AND/OR tout=0   => corresponding surface(s) cyllindrical
//             e.g. tin=0 AND tout=0 => shape becomes a tube with: rmin,rmax,dz
//
//_____________________________________________________________________________


ClassImp(TGeoHype)

//_____________________________________________________________________________
TGeoHype::TGeoHype()
{
// Default constructor
   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)
{
// Constructor specifying hyperboloid parameters.
   SetShapeBit(TGeoShape::kGeoHype);
   SetHypeDimensions(rin, stin, rout, stout, dz);
   // dz<0 can be used to force dz of hyperboloid fit the container volume
   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)
{
// Constructor specifying parameters and name.
   SetShapeBit(TGeoShape::kGeoHype);
   SetHypeDimensions(rin, stin, rout, stout, dz);
   // dz<0 can be used to force dz of hyperboloid fit the container volume
   if (fDz<0) SetShapeBit(kGeoRunTimeShape);
   ComputeBBox();
}

//_____________________________________________________________________________
TGeoHype::TGeoHype(Double_t *param)
         :TGeoTube(param[1],param[3],param[0])
{
// Default constructor specifying a list of parameters
// param[0] = dz
// param[1] = rin
// param[2] = stin
// param[3] = rout
// param[4] = stout
   SetShapeBit(TGeoShape::kGeoHype);
   SetDimensions(param);
   // dz<0 can be used to force dz of hyperboloid fit the container volume
   if (fDz<0) SetShapeBit(kGeoRunTimeShape);
   ComputeBBox();
}

//_____________________________________________________________________________
TGeoHype::~TGeoHype()
{
// destructor
}

//_____________________________________________________________________________
Double_t TGeoHype::Capacity() const
{
// Computes capacity of the shape in [length^3]
   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()
{
// Compute bounding box of the hyperboloid
   if (fRmin<0.) {
      Warning("ComputeBBox", "Shape %s has invalid rmin=%g ! SET TO 0.", GetName(),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(const Double_t *point, const Double_t *dir, Double_t *norm)
{
// Compute normal to closest surface from POINT.
   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(const Double_t *point) const
{
// test if point is inside this tube
   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)
{
// compute closest distance from point px,py to each corner
   Int_t numPoints = GetNmeshVertices();
   return ShapeDistancetoPrimitive(numPoints, px, py);
}

//_____________________________________________________________________________
Double_t TGeoHype::DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
{
// Compute distance from inside point to surface of the hyperboloid.
   if (iact<3 && safe) {
      *safe = Safety(point, kTRUE);
      if (iact==0) return TGeoShape::Big();
      if ((iact==1) && (*safe>step)) return TGeoShape::Big();
   }
   // compute distance to surface
   // Do Z
   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.;
      }
   }


   // Do R
   Double_t srin = TGeoShape::Big();
   Double_t srout = TGeoShape::Big();
   Double_t sr;
   // inner and outer surfaces
   Double_t s[2];
   Int_t npos;
   npos = DistToHype(point, dir, s, kTRUE, kTRUE);
   if (npos) srin = s[0];
   npos = DistToHype(point, dir, s, kFALSE, kTRUE);
   if (npos) srout = s[0];
   sr = TMath::Min(srin, srout);
   return TMath::Min(sz,sr);
}


//_____________________________________________________________________________
Double_t TGeoHype::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
{
// compute distance from outside point to surface of the hyperboloid.
   if (iact<3 && safe) {
      *safe = Safety(point, kFALSE);
      if (iact==0) return TGeoShape::Big();
      if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
   }
// Check if the bounding box is crossed within the requested distance
   Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
   if (sdist>=step) return TGeoShape::Big();
   // find distance to shape
   // Do Z
   Double_t xi, yi, zi;
   Double_t sz = TGeoShape::Big();
   if (TMath::Abs(point[2])>=fDz) {
      // We might find Z plane crossing
      if ((point[2]*dir[2]) < 0) {
         // Compute distance to Z (always positive)
         sz = (TMath::Abs(point[2])-fDz)/TMath::Abs(dir[2]);
         // Extrapolate
         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;
         }
      }
   }
   // We do not cross Z planes.
   Double_t sin = TGeoShape::Big();
   Double_t sout = TGeoShape::Big();
   Double_t s[2];
   Int_t npos;
   npos = DistToHype(point, dir, s, kTRUE, kFALSE);
   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, 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(const Double_t *point, const Double_t *dir, Double_t *s, Bool_t inner, Bool_t in) const
{
// Compute distance from an arbitrary point to inner/outer surface of hyperboloid.
// Returns number of positive solutions. S[2] contains the solutions.
   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 (TMath::Abs(a) < TGeoShape::Tolerance()) {
      if (TMath::Abs(b) < TGeoShape::Tolerance()) 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);
   Int_t i = -1;
   while (i<2) {
      snext = (b + i*sone*delta)*ainv;
      i += 2;
      if (snext<0) continue;
      if (snext<1.E-8) {
         Double_t r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
         Double_t t = (inner)?fTinsq:fToutsq;
         t *= -point[2]/r;
         Double_t phi = TMath::ATan2(point[1], point[0]);
         Double_t ndotd = TMath::Cos(phi)*dir[0]+TMath::Sin(phi)*dir[1]+t*dir[2];
         if (inner) ndotd *= -1;
         if (in) ndotd *= -1;
         if (ndotd<0) s[npos++] = snext;
      } else          s[npos++] = snext;
   }
   return npos;
}

//_____________________________________________________________________________
TGeoVolume *TGeoHype::Divide(TGeoVolume * /*voldiv*/, const char *divname, Int_t /*iaxis*/, Int_t /*ndiv*/,
                             Double_t /*start*/, Double_t /*step*/)
{
// Cannot divide hyperboloids.
   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
{
// Get range of shape for a given axis.
   xlo = 0;
   xhi = 0;
   Double_t dx = 0;
   switch (iaxis) {
      case 1: // R
         xlo = fRmin;
         xhi = TMath::Sqrt(RadiusHypeSq(fDz, kFALSE));
         dx = xhi-xlo;
         return dx;
      case 2: // Phi
         xlo = 0;
         xhi = 360;
         dx = 360;
         return dx;
      case 3: // Z
         xlo = -fDz;
         xhi = fDz;
         dx = xhi-xlo;
         return dx;
   }
   return dx;
}

//_____________________________________________________________________________
void TGeoHype::GetBoundingCylinder(Double_t *param) const
{
//--- Fill vector param[4] with the bounding cylinder parameters. The order
// is the following : Rmin, Rmax, Phi1, Phi2, dZ
   param[0] = fRmin; // Rmin
   param[0] *= param[0];
   param[1] = TMath::Sqrt(RadiusHypeSq(fDz, kFALSE)); // Rmax
   param[1] *= param[1];
   param[2] = 0.;    // Phi1
   param[3] = 360.;  // Phi1
}

//_____________________________________________________________________________
TGeoShape *TGeoHype::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * /*mat*/) const
{
// in case shape has some negative parameters, these has to be computed
// in order to fit the mother
   if (!TestShapeBit(kGeoRunTimeShape)) return 0;
   Double_t dz;
   Double_t zmin,zmax;
   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
{
// print shape parameters
   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
{
   // Creates a TBuffer3D describing *this* shape.
   // Coordinates are in local reference frame.

   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
{
// Fill TBuffer3D structure for segments and polygons.
   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;
   // Fill segments
   // Case hasRmin:
   //   Inner circles:  [isin = 0], n (per circle) * n ( circles)
   //        iseg = isin+n*i+j , i = 0, n-1   , j = 0, n-1
   //        seg(i=1,n; j=1,n) = [irin+n*i+j] and [irin+n*i+(j+1)%n]
   //   Inner generators: [isgenin = isin+n*n], n (per circle) *(n-1) (slices)
   //        iseg = isgenin + i*n + j, i=0,n-2,  j=0,n-1
   //        seg(i,j) = [irin+n*i+j] and [irin+n*(i+1)+j]
   //   Outer circles:  [isout = isgenin+n*(n-1)], n (per circle) * n ( circles)
   //        iseg = isout + i*n + j , iz = 0, n-1   , j = 0, n-1
   //        seg(i=1,n; j=1,n) = [irout+n*i+j] and [irout+n*i+(j+1)%n]
   //   Outer generators: [isgenout = isout+n*n], n (per circle) *(n-1) (slices)
   //        iseg = isgenout + i*n + j, i=0,n-2,  j=0,n-1
   //        seg(i,j) = [irout+n*i+j] and [irout+n*(i+1)+j]
   //   Lower cap : [islow = isgenout + n*(n-1)], n radial segments
   //        iseg = islow + j,  j=0,n-1
   //        seg(j) = [irin + j] and [irout+j]
   //   Upper cap: [ishi = islow + n], nradial segments
   //        iseg = ishi + j, j=0,n-1
   //        seg[j] = [irin + n*(n-1) + j] and [irout+n*(n-1) + j]
   //
   // Case !hasRmin:
   //   Outer circles: [isout=0], same outer circles (n*n)
   // Outer generators: isgenout = isout + n*n
   //   Lower cap: [islow = isgenout+n*(n-1)], n seg.
   //        iseg = islow + j, j=0,n-1
   //        seg[j] = [irin] and [irout+j]
   //   Upper cap: [ishi = islow +n]
   //        iseg = ishi + j, j=0,n-1
   //        seg[j] = [irin+1] and [irout+n*(n-1) + j]

   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;
   // Fill inner circle segments (n*n)
   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);
         }
      }
      // Fill inner generators (n*(n-1))
      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;
         }
      }
   }
   // Fill outer circle segments (n*n)
   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);
      }
   }
   // Fill outer generators (n*(n-1))
   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;
      }
   }
   // Fill lower cap (n)
   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;
   }
   // Fill upper cap (n)
   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;
   }

   // Fill polygons
   // Inner polygons: [ipin = 0] (n-1) slices * n (edges)
   //   ipoly = ipin + n*i + j;  i=0,n-2   j=0,n-1
   //   poly[i,j] = [isin+n*i+j]  [isgenin+i*n+(j+1)%n]  [isin+n*(i+1)+j]  [isgenin+i*n+j]
   // Outer polygons: [ipout = ipin+n*(n-1)]  also (n-1)*n
   //   ipoly = ipout + n*i + j; i=0,n-2   j=0,n-1
   //   poly[i,j] = [isout+n*i+j]  [isgenout+i*n+j]  [isout+n*(i+1)+j]  [isgenout+i*n+(j+1)%n]
   // Lower cap: [iplow = ipout+n*(n-1):  n polygons
   //   ipoly = iplow + j;  j=0,n-1
   //   poly[i=0,j] = [isin+j] [islow+j] [isout+j] [islow+(j+1)%n]
   // Upper cap: [ipup = iplow+n] : n polygons
   //   ipoly = ipup + j;  j=0,n-1
   //   poly[i=n-1, j] = [isin+n*(n-1)+j] [ishi+(j+1)%n] [isout+n*(n-1)+j] [ishi+j]
   //
   // Case !hasRmin:
   // ipin = 0 no inner polygons
   // ipout = 0 same outer polygons
   // Lower cap: iplow = ipout+n*(n-1):  n polygons with 3 segments
   //   poly[i=0,j] = [isout+j] [islow+(j+1)%n] [islow+j]
   // Upper cap: ipup = iplow+n;
   //   poly[i=n-1,j] = [isout+n*(n-1)+j] [ishi+j] [ishi+(j+1)%n]

   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;
   // Inner polygons n*(n-1)
   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;
         }
      }
   }
   // Outer polygons n*(n-1)
   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);
      }
   }
   // End caps
   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
{
// Compute r^2 = x^2 + y^2 at a given z coordinate, for either inner or outer hyperbolas.
   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
{
// Compute z^2 at a given  r^2, for either inner or outer hyperbolas.
   Double_t r0, tsq;
   if (inner) {
      r0 = fRmin;
      tsq = fTinsq;
   } else {
      r0 = fRmax;
      tsq = fToutsq;
   }
   if (TMath::Abs(tsq) < TGeoShape::Tolerance()) return TGeoShape::Big();
   return ((r*r-r0*r0)/tsq);
}

//_____________________________________________________________________________
Double_t TGeoHype::Safety(const Double_t *point, Bool_t in) const
{
// computes the closest distance from given point to this shape, according
// to option. The matching point on the shape is stored in spoint.
   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(const Double_t *point, Bool_t inner, Bool_t in) const
{
// Compute an underestimate of the closest distance from a point to inner or
// outer infinite hyperbolas.
   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 (TMath::Abs(fStIn) < TGeoShape::Tolerance()) return TMath::Abs(dr);
      if (fRmin<TGeoShape::Tolerance()) return TMath::Abs(dr/TMath::Sqrt(1.+ fTinsq));
      tsq = fTinsq;
   } else {
      if (!in && dr<0) return -TGeoShape::Big();
      if (TMath::Abs(fStOut) < TGeoShape::Tolerance()) return TMath::Abs(dr);
      tsq = fToutsq;
   }
   if (TMath::Abs(dr)<TGeoShape::Tolerance()) return 0.;
   // 1. dr<0 => approximate safety with distance to tangent to hyperbola in z = |point[2]|
   Double_t m;
   if (dr<0) {
      m = rh/(tsq*TMath::Abs(point[2]));
      saf = -m*dr/TMath::Sqrt(1.+m*m);
      return saf;
   }
   // 2. dr>0 => approximate safety with distance from point to segment P1(r(z0),z0) and P2(r0, z(r0))
   m = (TMath::Sqrt(ZHypeSq(r,inner)) - TMath::Abs(point[2]))/dr;
   saf = m*dr/TMath::Sqrt(1.+m*m);
   return saf;
}

//_____________________________________________________________________________
void TGeoHype::SavePrimitive(std::ostream &out, Option_t * /*option*/ /*= ""*/)
{
// Save a primitive as a C++ statement(s) on output stream "out".
   if (TObject::TestBit(kGeoSavePrimitive)) return;
   out << "   // Shape: " << GetName() << " type: " << ClassName() << std::endl;
   out << "   rin   = " << fRmin << ";" << std::endl;
   out << "   stin  = " << fStIn << ";" << std::endl;
   out << "   rout  = " << fRmax << ";" << std::endl;
   out << "   stout = " << fStOut << ";" << std::endl;
   out << "   dz    = " << fDz << ";" << std::endl;
   out << "   TGeoShape *" << GetPointerName() << " = new TGeoHype(\"" << GetName() << "\",rin,stin,rout,stout,dz);" << std::endl;
   TObject::SetBit(TGeoShape::kGeoSavePrimitive);
}

//_____________________________________________________________________________
void TGeoHype::SetHypeDimensions(Double_t rin, Double_t stin, Double_t rout, Double_t stout, Double_t dz)
{
// Set dimensions of the hyperboloid.
   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)
{
// Set dimensions of the hyperboloid starting from an array.
// param[0] = dz
// param[1] = rin
// param[2] = stin
// param[3] = rout
// param[4] = stout
   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
{
// create tube mesh points
   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()) {
      // Inner surface points
      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;
   }
   // Outer surface points
   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
{
// create tube mesh points
   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()) {
      // Inner surface points
      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;
   }
   // Outer surface points
   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
{
// Returns numbers of vertices, segments and polygons composing the shape mesh.
   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
{
// Return number of vertices of the mesh representation
   Int_t n = gGeoManager->GetNsegments();
   Int_t numPoints = (HasRmin())?(2*n*n):(n*n+2);
   return numPoints;
}

//_____________________________________________________________________________
void TGeoHype::Sizeof3D() const
{
///// fill size of this 3-D object
///    TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
///    if (!painter) return;
///    Int_t n = gGeoManager->GetNsegments();
///    Int_t numPoints = n*4;
///    Int_t numSegs   = n*8;
///    Int_t numPolys  = n*4;
///    painter->AddSize3D(numPoints, numSegs, numPolys);
}

//_____________________________________________________________________________
const TBuffer3D & TGeoHype::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
{
// Fills a static 3D buffer and returns a reference.
   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;
}

//_____________________________________________________________________________
void TGeoHype::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
{
// Check the inside status for each of the points in the array.
// Input: Array of point coordinates + vector size
// Output: Array of Booleans for the inside of each point
   for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
}

//_____________________________________________________________________________
void TGeoHype::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
{
// Compute the normal for an array o points so that norm.dot.dir is positive
// Input: Arrays of point coordinates and directions + vector size
// Output: Array of normal directions
   for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
}

//_____________________________________________________________________________
void TGeoHype::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
{
// Compute distance from array of input points having directions specisied by dirs. Store output in dists
   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
}

//_____________________________________________________________________________
void TGeoHype::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
{
// Compute distance from array of input points having directions specisied by dirs. Store output in dists
   for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
}

//_____________________________________________________________________________
void TGeoHype::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
{
// Compute safe distance from each of the points in the input array.
// Input: Array of point coordinates, array of statuses for these points, size of the arrays
// Output: Safety values
   for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
}
 TGeoHype.cxx:1
 TGeoHype.cxx:2
 TGeoHype.cxx:3
 TGeoHype.cxx:4
 TGeoHype.cxx:5
 TGeoHype.cxx:6
 TGeoHype.cxx:7
 TGeoHype.cxx:8
 TGeoHype.cxx:9
 TGeoHype.cxx:10
 TGeoHype.cxx:11
 TGeoHype.cxx:12
 TGeoHype.cxx:13
 TGeoHype.cxx:14
 TGeoHype.cxx:15
 TGeoHype.cxx:16
 TGeoHype.cxx:17
 TGeoHype.cxx:18
 TGeoHype.cxx:19
 TGeoHype.cxx:20
 TGeoHype.cxx:21
 TGeoHype.cxx:22
 TGeoHype.cxx:23
 TGeoHype.cxx:24
 TGeoHype.cxx:25
 TGeoHype.cxx:26
 TGeoHype.cxx:27
 TGeoHype.cxx:28
 TGeoHype.cxx:29
 TGeoHype.cxx:30
 TGeoHype.cxx:31
 TGeoHype.cxx:32
 TGeoHype.cxx:33
 TGeoHype.cxx:34
 TGeoHype.cxx:35
 TGeoHype.cxx:36
 TGeoHype.cxx:37
 TGeoHype.cxx:38
 TGeoHype.cxx:39
 TGeoHype.cxx:40
 TGeoHype.cxx:41
 TGeoHype.cxx:42
 TGeoHype.cxx:43
 TGeoHype.cxx:44
 TGeoHype.cxx:45
 TGeoHype.cxx:46
 TGeoHype.cxx:47
 TGeoHype.cxx:48
 TGeoHype.cxx:49
 TGeoHype.cxx:50
 TGeoHype.cxx:51
 TGeoHype.cxx:52
 TGeoHype.cxx:53
 TGeoHype.cxx:54
 TGeoHype.cxx:55
 TGeoHype.cxx:56
 TGeoHype.cxx:57
 TGeoHype.cxx:58
 TGeoHype.cxx:59
 TGeoHype.cxx:60
 TGeoHype.cxx:61
 TGeoHype.cxx:62
 TGeoHype.cxx:63
 TGeoHype.cxx:64
 TGeoHype.cxx:65
 TGeoHype.cxx:66
 TGeoHype.cxx:67
 TGeoHype.cxx:68
 TGeoHype.cxx:69
 TGeoHype.cxx:70
 TGeoHype.cxx:71
 TGeoHype.cxx:72
 TGeoHype.cxx:73
 TGeoHype.cxx:74
 TGeoHype.cxx:75
 TGeoHype.cxx:76
 TGeoHype.cxx:77
 TGeoHype.cxx:78
 TGeoHype.cxx:79
 TGeoHype.cxx:80
 TGeoHype.cxx:81
 TGeoHype.cxx:82
 TGeoHype.cxx:83
 TGeoHype.cxx:84
 TGeoHype.cxx:85
 TGeoHype.cxx:86
 TGeoHype.cxx:87
 TGeoHype.cxx:88
 TGeoHype.cxx:89
 TGeoHype.cxx:90
 TGeoHype.cxx:91
 TGeoHype.cxx:92
 TGeoHype.cxx:93
 TGeoHype.cxx:94
 TGeoHype.cxx:95
 TGeoHype.cxx:96
 TGeoHype.cxx:97
 TGeoHype.cxx:98
 TGeoHype.cxx:99
 TGeoHype.cxx:100
 TGeoHype.cxx:101
 TGeoHype.cxx:102
 TGeoHype.cxx:103
 TGeoHype.cxx:104
 TGeoHype.cxx:105
 TGeoHype.cxx:106
 TGeoHype.cxx:107
 TGeoHype.cxx:108
 TGeoHype.cxx:109
 TGeoHype.cxx:110
 TGeoHype.cxx:111
 TGeoHype.cxx:112
 TGeoHype.cxx:113
 TGeoHype.cxx:114
 TGeoHype.cxx:115
 TGeoHype.cxx:116
 TGeoHype.cxx:117
 TGeoHype.cxx:118
 TGeoHype.cxx:119
 TGeoHype.cxx:120
 TGeoHype.cxx:121
 TGeoHype.cxx:122
 TGeoHype.cxx:123
 TGeoHype.cxx:124
 TGeoHype.cxx:125
 TGeoHype.cxx:126
 TGeoHype.cxx:127
 TGeoHype.cxx:128
 TGeoHype.cxx:129
 TGeoHype.cxx:130
 TGeoHype.cxx:131
 TGeoHype.cxx:132
 TGeoHype.cxx:133
 TGeoHype.cxx:134
 TGeoHype.cxx:135
 TGeoHype.cxx:136
 TGeoHype.cxx:137
 TGeoHype.cxx:138
 TGeoHype.cxx:139
 TGeoHype.cxx:140
 TGeoHype.cxx:141
 TGeoHype.cxx:142
 TGeoHype.cxx:143
 TGeoHype.cxx:144
 TGeoHype.cxx:145
 TGeoHype.cxx:146
 TGeoHype.cxx:147
 TGeoHype.cxx:148
 TGeoHype.cxx:149
 TGeoHype.cxx:150
 TGeoHype.cxx:151
 TGeoHype.cxx:152
 TGeoHype.cxx:153
 TGeoHype.cxx:154
 TGeoHype.cxx:155
 TGeoHype.cxx:156
 TGeoHype.cxx:157
 TGeoHype.cxx:158
 TGeoHype.cxx:159
 TGeoHype.cxx:160
 TGeoHype.cxx:161
 TGeoHype.cxx:162
 TGeoHype.cxx:163
 TGeoHype.cxx:164
 TGeoHype.cxx:165
 TGeoHype.cxx:166
 TGeoHype.cxx:167
 TGeoHype.cxx:168
 TGeoHype.cxx:169
 TGeoHype.cxx:170
 TGeoHype.cxx:171
 TGeoHype.cxx:172
 TGeoHype.cxx:173
 TGeoHype.cxx:174
 TGeoHype.cxx:175
 TGeoHype.cxx:176
 TGeoHype.cxx:177
 TGeoHype.cxx:178
 TGeoHype.cxx:179
 TGeoHype.cxx:180
 TGeoHype.cxx:181
 TGeoHype.cxx:182
 TGeoHype.cxx:183
 TGeoHype.cxx:184
 TGeoHype.cxx:185
 TGeoHype.cxx:186
 TGeoHype.cxx:187
 TGeoHype.cxx:188
 TGeoHype.cxx:189
 TGeoHype.cxx:190
 TGeoHype.cxx:191
 TGeoHype.cxx:192
 TGeoHype.cxx:193
 TGeoHype.cxx:194
 TGeoHype.cxx:195
 TGeoHype.cxx:196
 TGeoHype.cxx:197
 TGeoHype.cxx:198
 TGeoHype.cxx:199
 TGeoHype.cxx:200
 TGeoHype.cxx:201
 TGeoHype.cxx:202
 TGeoHype.cxx:203
 TGeoHype.cxx:204
 TGeoHype.cxx:205
 TGeoHype.cxx:206
 TGeoHype.cxx:207
 TGeoHype.cxx:208
 TGeoHype.cxx:209
 TGeoHype.cxx:210
 TGeoHype.cxx:211
 TGeoHype.cxx:212
 TGeoHype.cxx:213
 TGeoHype.cxx:214
 TGeoHype.cxx:215
 TGeoHype.cxx:216
 TGeoHype.cxx:217
 TGeoHype.cxx:218
 TGeoHype.cxx:219
 TGeoHype.cxx:220
 TGeoHype.cxx:221
 TGeoHype.cxx:222
 TGeoHype.cxx:223
 TGeoHype.cxx:224
 TGeoHype.cxx:225
 TGeoHype.cxx:226
 TGeoHype.cxx:227
 TGeoHype.cxx:228
 TGeoHype.cxx:229
 TGeoHype.cxx:230
 TGeoHype.cxx:231
 TGeoHype.cxx:232
 TGeoHype.cxx:233
 TGeoHype.cxx:234
 TGeoHype.cxx:235
 TGeoHype.cxx:236
 TGeoHype.cxx:237
 TGeoHype.cxx:238
 TGeoHype.cxx:239
 TGeoHype.cxx:240
 TGeoHype.cxx:241
 TGeoHype.cxx:242
 TGeoHype.cxx:243
 TGeoHype.cxx:244
 TGeoHype.cxx:245
 TGeoHype.cxx:246
 TGeoHype.cxx:247
 TGeoHype.cxx:248
 TGeoHype.cxx:249
 TGeoHype.cxx:250
 TGeoHype.cxx:251
 TGeoHype.cxx:252
 TGeoHype.cxx:253
 TGeoHype.cxx:254
 TGeoHype.cxx:255
 TGeoHype.cxx:256
 TGeoHype.cxx:257
 TGeoHype.cxx:258
 TGeoHype.cxx:259
 TGeoHype.cxx:260
 TGeoHype.cxx:261
 TGeoHype.cxx:262
 TGeoHype.cxx:263
 TGeoHype.cxx:264
 TGeoHype.cxx:265
 TGeoHype.cxx:266
 TGeoHype.cxx:267
 TGeoHype.cxx:268
 TGeoHype.cxx:269
 TGeoHype.cxx:270
 TGeoHype.cxx:271
 TGeoHype.cxx:272
 TGeoHype.cxx:273
 TGeoHype.cxx:274
 TGeoHype.cxx:275
 TGeoHype.cxx:276
 TGeoHype.cxx:277
 TGeoHype.cxx:278
 TGeoHype.cxx:279
 TGeoHype.cxx:280
 TGeoHype.cxx:281
 TGeoHype.cxx:282
 TGeoHype.cxx:283
 TGeoHype.cxx:284
 TGeoHype.cxx:285
 TGeoHype.cxx:286
 TGeoHype.cxx:287
 TGeoHype.cxx:288
 TGeoHype.cxx:289
 TGeoHype.cxx:290
 TGeoHype.cxx:291
 TGeoHype.cxx:292
 TGeoHype.cxx:293
 TGeoHype.cxx:294
 TGeoHype.cxx:295
 TGeoHype.cxx:296
 TGeoHype.cxx:297
 TGeoHype.cxx:298
 TGeoHype.cxx:299
 TGeoHype.cxx:300
 TGeoHype.cxx:301
 TGeoHype.cxx:302
 TGeoHype.cxx:303
 TGeoHype.cxx:304
 TGeoHype.cxx:305
 TGeoHype.cxx:306
 TGeoHype.cxx:307
 TGeoHype.cxx:308
 TGeoHype.cxx:309
 TGeoHype.cxx:310
 TGeoHype.cxx:311
 TGeoHype.cxx:312
 TGeoHype.cxx:313
 TGeoHype.cxx:314
 TGeoHype.cxx:315
 TGeoHype.cxx:316
 TGeoHype.cxx:317
 TGeoHype.cxx:318
 TGeoHype.cxx:319
 TGeoHype.cxx:320
 TGeoHype.cxx:321
 TGeoHype.cxx:322
 TGeoHype.cxx:323
 TGeoHype.cxx:324
 TGeoHype.cxx:325
 TGeoHype.cxx:326
 TGeoHype.cxx:327
 TGeoHype.cxx:328
 TGeoHype.cxx:329
 TGeoHype.cxx:330
 TGeoHype.cxx:331
 TGeoHype.cxx:332
 TGeoHype.cxx:333
 TGeoHype.cxx:334
 TGeoHype.cxx:335
 TGeoHype.cxx:336
 TGeoHype.cxx:337
 TGeoHype.cxx:338
 TGeoHype.cxx:339
 TGeoHype.cxx:340
 TGeoHype.cxx:341
 TGeoHype.cxx:342
 TGeoHype.cxx:343
 TGeoHype.cxx:344
 TGeoHype.cxx:345
 TGeoHype.cxx:346
 TGeoHype.cxx:347
 TGeoHype.cxx:348
 TGeoHype.cxx:349
 TGeoHype.cxx:350
 TGeoHype.cxx:351
 TGeoHype.cxx:352
 TGeoHype.cxx:353
 TGeoHype.cxx:354
 TGeoHype.cxx:355
 TGeoHype.cxx:356
 TGeoHype.cxx:357
 TGeoHype.cxx:358
 TGeoHype.cxx:359
 TGeoHype.cxx:360
 TGeoHype.cxx:361
 TGeoHype.cxx:362
 TGeoHype.cxx:363
 TGeoHype.cxx:364
 TGeoHype.cxx:365
 TGeoHype.cxx:366
 TGeoHype.cxx:367
 TGeoHype.cxx:368
 TGeoHype.cxx:369
 TGeoHype.cxx:370
 TGeoHype.cxx:371
 TGeoHype.cxx:372
 TGeoHype.cxx:373
 TGeoHype.cxx:374
 TGeoHype.cxx:375
 TGeoHype.cxx:376
 TGeoHype.cxx:377
 TGeoHype.cxx:378
 TGeoHype.cxx:379
 TGeoHype.cxx:380
 TGeoHype.cxx:381
 TGeoHype.cxx:382
 TGeoHype.cxx:383
 TGeoHype.cxx:384
 TGeoHype.cxx:385
 TGeoHype.cxx:386
 TGeoHype.cxx:387
 TGeoHype.cxx:388
 TGeoHype.cxx:389
 TGeoHype.cxx:390
 TGeoHype.cxx:391
 TGeoHype.cxx:392
 TGeoHype.cxx:393
 TGeoHype.cxx:394
 TGeoHype.cxx:395
 TGeoHype.cxx:396
 TGeoHype.cxx:397
 TGeoHype.cxx:398
 TGeoHype.cxx:399
 TGeoHype.cxx:400
 TGeoHype.cxx:401
 TGeoHype.cxx:402
 TGeoHype.cxx:403
 TGeoHype.cxx:404
 TGeoHype.cxx:405
 TGeoHype.cxx:406
 TGeoHype.cxx:407
 TGeoHype.cxx:408
 TGeoHype.cxx:409
 TGeoHype.cxx:410
 TGeoHype.cxx:411
 TGeoHype.cxx:412
 TGeoHype.cxx:413
 TGeoHype.cxx:414
 TGeoHype.cxx:415
 TGeoHype.cxx:416
 TGeoHype.cxx:417
 TGeoHype.cxx:418
 TGeoHype.cxx:419
 TGeoHype.cxx:420
 TGeoHype.cxx:421
 TGeoHype.cxx:422
 TGeoHype.cxx:423
 TGeoHype.cxx:424
 TGeoHype.cxx:425
 TGeoHype.cxx:426
 TGeoHype.cxx:427
 TGeoHype.cxx:428
 TGeoHype.cxx:429
 TGeoHype.cxx:430
 TGeoHype.cxx:431
 TGeoHype.cxx:432
 TGeoHype.cxx:433
 TGeoHype.cxx:434
 TGeoHype.cxx:435
 TGeoHype.cxx:436
 TGeoHype.cxx:437
 TGeoHype.cxx:438
 TGeoHype.cxx:439
 TGeoHype.cxx:440
 TGeoHype.cxx:441
 TGeoHype.cxx:442
 TGeoHype.cxx:443
 TGeoHype.cxx:444
 TGeoHype.cxx:445
 TGeoHype.cxx:446
 TGeoHype.cxx:447
 TGeoHype.cxx:448
 TGeoHype.cxx:449
 TGeoHype.cxx:450
 TGeoHype.cxx:451
 TGeoHype.cxx:452
 TGeoHype.cxx:453
 TGeoHype.cxx:454
 TGeoHype.cxx:455
 TGeoHype.cxx:456
 TGeoHype.cxx:457
 TGeoHype.cxx:458
 TGeoHype.cxx:459
 TGeoHype.cxx:460
 TGeoHype.cxx:461
 TGeoHype.cxx:462
 TGeoHype.cxx:463
 TGeoHype.cxx:464
 TGeoHype.cxx:465
 TGeoHype.cxx:466
 TGeoHype.cxx:467
 TGeoHype.cxx:468
 TGeoHype.cxx:469
 TGeoHype.cxx:470
 TGeoHype.cxx:471
 TGeoHype.cxx:472
 TGeoHype.cxx:473
 TGeoHype.cxx:474
 TGeoHype.cxx:475
 TGeoHype.cxx:476
 TGeoHype.cxx:477
 TGeoHype.cxx:478
 TGeoHype.cxx:479
 TGeoHype.cxx:480
 TGeoHype.cxx:481
 TGeoHype.cxx:482
 TGeoHype.cxx:483
 TGeoHype.cxx:484
 TGeoHype.cxx:485
 TGeoHype.cxx:486
 TGeoHype.cxx:487
 TGeoHype.cxx:488
 TGeoHype.cxx:489
 TGeoHype.cxx:490
 TGeoHype.cxx:491
 TGeoHype.cxx:492
 TGeoHype.cxx:493
 TGeoHype.cxx:494
 TGeoHype.cxx:495
 TGeoHype.cxx:496
 TGeoHype.cxx:497
 TGeoHype.cxx:498
 TGeoHype.cxx:499
 TGeoHype.cxx:500
 TGeoHype.cxx:501
 TGeoHype.cxx:502
 TGeoHype.cxx:503
 TGeoHype.cxx:504
 TGeoHype.cxx:505
 TGeoHype.cxx:506
 TGeoHype.cxx:507
 TGeoHype.cxx:508
 TGeoHype.cxx:509
 TGeoHype.cxx:510
 TGeoHype.cxx:511
 TGeoHype.cxx:512
 TGeoHype.cxx:513
 TGeoHype.cxx:514
 TGeoHype.cxx:515
 TGeoHype.cxx:516
 TGeoHype.cxx:517
 TGeoHype.cxx:518
 TGeoHype.cxx:519
 TGeoHype.cxx:520
 TGeoHype.cxx:521
 TGeoHype.cxx:522
 TGeoHype.cxx:523
 TGeoHype.cxx:524
 TGeoHype.cxx:525
 TGeoHype.cxx:526
 TGeoHype.cxx:527
 TGeoHype.cxx:528
 TGeoHype.cxx:529
 TGeoHype.cxx:530
 TGeoHype.cxx:531
 TGeoHype.cxx:532
 TGeoHype.cxx:533
 TGeoHype.cxx:534
 TGeoHype.cxx:535
 TGeoHype.cxx:536
 TGeoHype.cxx:537
 TGeoHype.cxx:538
 TGeoHype.cxx:539
 TGeoHype.cxx:540
 TGeoHype.cxx:541
 TGeoHype.cxx:542
 TGeoHype.cxx:543
 TGeoHype.cxx:544
 TGeoHype.cxx:545
 TGeoHype.cxx:546
 TGeoHype.cxx:547
 TGeoHype.cxx:548
 TGeoHype.cxx:549
 TGeoHype.cxx:550
 TGeoHype.cxx:551
 TGeoHype.cxx:552
 TGeoHype.cxx:553
 TGeoHype.cxx:554
 TGeoHype.cxx:555
 TGeoHype.cxx:556
 TGeoHype.cxx:557
 TGeoHype.cxx:558
 TGeoHype.cxx:559
 TGeoHype.cxx:560
 TGeoHype.cxx:561
 TGeoHype.cxx:562
 TGeoHype.cxx:563
 TGeoHype.cxx:564
 TGeoHype.cxx:565
 TGeoHype.cxx:566
 TGeoHype.cxx:567
 TGeoHype.cxx:568
 TGeoHype.cxx:569
 TGeoHype.cxx:570
 TGeoHype.cxx:571
 TGeoHype.cxx:572
 TGeoHype.cxx:573
 TGeoHype.cxx:574
 TGeoHype.cxx:575
 TGeoHype.cxx:576
 TGeoHype.cxx:577
 TGeoHype.cxx:578
 TGeoHype.cxx:579
 TGeoHype.cxx:580
 TGeoHype.cxx:581
 TGeoHype.cxx:582
 TGeoHype.cxx:583
 TGeoHype.cxx:584
 TGeoHype.cxx:585
 TGeoHype.cxx:586
 TGeoHype.cxx:587
 TGeoHype.cxx:588
 TGeoHype.cxx:589
 TGeoHype.cxx:590
 TGeoHype.cxx:591
 TGeoHype.cxx:592
 TGeoHype.cxx:593
 TGeoHype.cxx:594
 TGeoHype.cxx:595
 TGeoHype.cxx:596
 TGeoHype.cxx:597
 TGeoHype.cxx:598
 TGeoHype.cxx:599
 TGeoHype.cxx:600
 TGeoHype.cxx:601
 TGeoHype.cxx:602
 TGeoHype.cxx:603
 TGeoHype.cxx:604
 TGeoHype.cxx:605
 TGeoHype.cxx:606
 TGeoHype.cxx:607
 TGeoHype.cxx:608
 TGeoHype.cxx:609
 TGeoHype.cxx:610
 TGeoHype.cxx:611
 TGeoHype.cxx:612
 TGeoHype.cxx:613
 TGeoHype.cxx:614
 TGeoHype.cxx:615
 TGeoHype.cxx:616
 TGeoHype.cxx:617
 TGeoHype.cxx:618
 TGeoHype.cxx:619
 TGeoHype.cxx:620
 TGeoHype.cxx:621
 TGeoHype.cxx:622
 TGeoHype.cxx:623
 TGeoHype.cxx:624
 TGeoHype.cxx:625
 TGeoHype.cxx:626
 TGeoHype.cxx:627
 TGeoHype.cxx:628
 TGeoHype.cxx:629
 TGeoHype.cxx:630
 TGeoHype.cxx:631
 TGeoHype.cxx:632
 TGeoHype.cxx:633
 TGeoHype.cxx:634
 TGeoHype.cxx:635
 TGeoHype.cxx:636
 TGeoHype.cxx:637
 TGeoHype.cxx:638
 TGeoHype.cxx:639
 TGeoHype.cxx:640
 TGeoHype.cxx:641
 TGeoHype.cxx:642
 TGeoHype.cxx:643
 TGeoHype.cxx:644
 TGeoHype.cxx:645
 TGeoHype.cxx:646
 TGeoHype.cxx:647
 TGeoHype.cxx:648
 TGeoHype.cxx:649
 TGeoHype.cxx:650
 TGeoHype.cxx:651
 TGeoHype.cxx:652
 TGeoHype.cxx:653
 TGeoHype.cxx:654
 TGeoHype.cxx:655
 TGeoHype.cxx:656
 TGeoHype.cxx:657
 TGeoHype.cxx:658
 TGeoHype.cxx:659
 TGeoHype.cxx:660
 TGeoHype.cxx:661
 TGeoHype.cxx:662
 TGeoHype.cxx:663
 TGeoHype.cxx:664
 TGeoHype.cxx:665
 TGeoHype.cxx:666
 TGeoHype.cxx:667
 TGeoHype.cxx:668
 TGeoHype.cxx:669
 TGeoHype.cxx:670
 TGeoHype.cxx:671
 TGeoHype.cxx:672
 TGeoHype.cxx:673
 TGeoHype.cxx:674
 TGeoHype.cxx:675
 TGeoHype.cxx:676
 TGeoHype.cxx:677
 TGeoHype.cxx:678
 TGeoHype.cxx:679
 TGeoHype.cxx:680
 TGeoHype.cxx:681
 TGeoHype.cxx:682
 TGeoHype.cxx:683
 TGeoHype.cxx:684
 TGeoHype.cxx:685
 TGeoHype.cxx:686
 TGeoHype.cxx:687
 TGeoHype.cxx:688
 TGeoHype.cxx:689
 TGeoHype.cxx:690
 TGeoHype.cxx:691
 TGeoHype.cxx:692
 TGeoHype.cxx:693
 TGeoHype.cxx:694
 TGeoHype.cxx:695
 TGeoHype.cxx:696
 TGeoHype.cxx:697
 TGeoHype.cxx:698
 TGeoHype.cxx:699
 TGeoHype.cxx:700
 TGeoHype.cxx:701
 TGeoHype.cxx:702
 TGeoHype.cxx:703
 TGeoHype.cxx:704
 TGeoHype.cxx:705
 TGeoHype.cxx:706
 TGeoHype.cxx:707
 TGeoHype.cxx:708
 TGeoHype.cxx:709
 TGeoHype.cxx:710
 TGeoHype.cxx:711
 TGeoHype.cxx:712
 TGeoHype.cxx:713
 TGeoHype.cxx:714
 TGeoHype.cxx:715
 TGeoHype.cxx:716
 TGeoHype.cxx:717
 TGeoHype.cxx:718
 TGeoHype.cxx:719
 TGeoHype.cxx:720
 TGeoHype.cxx:721
 TGeoHype.cxx:722
 TGeoHype.cxx:723
 TGeoHype.cxx:724
 TGeoHype.cxx:725
 TGeoHype.cxx:726
 TGeoHype.cxx:727
 TGeoHype.cxx:728
 TGeoHype.cxx:729
 TGeoHype.cxx:730
 TGeoHype.cxx:731
 TGeoHype.cxx:732
 TGeoHype.cxx:733
 TGeoHype.cxx:734
 TGeoHype.cxx:735
 TGeoHype.cxx:736
 TGeoHype.cxx:737
 TGeoHype.cxx:738
 TGeoHype.cxx:739
 TGeoHype.cxx:740
 TGeoHype.cxx:741
 TGeoHype.cxx:742
 TGeoHype.cxx:743
 TGeoHype.cxx:744
 TGeoHype.cxx:745
 TGeoHype.cxx:746
 TGeoHype.cxx:747
 TGeoHype.cxx:748
 TGeoHype.cxx:749
 TGeoHype.cxx:750
 TGeoHype.cxx:751
 TGeoHype.cxx:752
 TGeoHype.cxx:753
 TGeoHype.cxx:754
 TGeoHype.cxx:755
 TGeoHype.cxx:756
 TGeoHype.cxx:757
 TGeoHype.cxx:758
 TGeoHype.cxx:759
 TGeoHype.cxx:760
 TGeoHype.cxx:761
 TGeoHype.cxx:762
 TGeoHype.cxx:763
 TGeoHype.cxx:764
 TGeoHype.cxx:765
 TGeoHype.cxx:766
 TGeoHype.cxx:767
 TGeoHype.cxx:768
 TGeoHype.cxx:769
 TGeoHype.cxx:770
 TGeoHype.cxx:771
 TGeoHype.cxx:772
 TGeoHype.cxx:773
 TGeoHype.cxx:774
 TGeoHype.cxx:775
 TGeoHype.cxx:776
 TGeoHype.cxx:777
 TGeoHype.cxx:778
 TGeoHype.cxx:779
 TGeoHype.cxx:780
 TGeoHype.cxx:781
 TGeoHype.cxx:782
 TGeoHype.cxx:783
 TGeoHype.cxx:784
 TGeoHype.cxx:785
 TGeoHype.cxx:786
 TGeoHype.cxx:787
 TGeoHype.cxx:788
 TGeoHype.cxx:789
 TGeoHype.cxx:790
 TGeoHype.cxx:791
 TGeoHype.cxx:792
 TGeoHype.cxx:793
 TGeoHype.cxx:794
 TGeoHype.cxx:795
 TGeoHype.cxx:796
 TGeoHype.cxx:797
 TGeoHype.cxx:798
 TGeoHype.cxx:799
 TGeoHype.cxx:800
 TGeoHype.cxx:801
 TGeoHype.cxx:802
 TGeoHype.cxx:803
 TGeoHype.cxx:804
 TGeoHype.cxx:805
 TGeoHype.cxx:806
 TGeoHype.cxx:807
 TGeoHype.cxx:808
 TGeoHype.cxx:809
 TGeoHype.cxx:810
 TGeoHype.cxx:811
 TGeoHype.cxx:812
 TGeoHype.cxx:813
 TGeoHype.cxx:814
 TGeoHype.cxx:815
 TGeoHype.cxx:816
 TGeoHype.cxx:817
 TGeoHype.cxx:818
 TGeoHype.cxx:819
 TGeoHype.cxx:820
 TGeoHype.cxx:821
 TGeoHype.cxx:822
 TGeoHype.cxx:823
 TGeoHype.cxx:824
 TGeoHype.cxx:825
 TGeoHype.cxx:826
 TGeoHype.cxx:827
 TGeoHype.cxx:828
 TGeoHype.cxx:829
 TGeoHype.cxx:830
 TGeoHype.cxx:831
 TGeoHype.cxx:832
 TGeoHype.cxx:833
 TGeoHype.cxx:834
 TGeoHype.cxx:835
 TGeoHype.cxx:836
 TGeoHype.cxx:837
 TGeoHype.cxx:838
 TGeoHype.cxx:839
 TGeoHype.cxx:840
 TGeoHype.cxx:841
 TGeoHype.cxx:842
 TGeoHype.cxx:843
 TGeoHype.cxx:844
 TGeoHype.cxx:845
 TGeoHype.cxx:846
 TGeoHype.cxx:847
 TGeoHype.cxx:848
 TGeoHype.cxx:849
 TGeoHype.cxx:850
 TGeoHype.cxx:851
 TGeoHype.cxx:852
 TGeoHype.cxx:853
 TGeoHype.cxx:854
 TGeoHype.cxx:855
 TGeoHype.cxx:856
 TGeoHype.cxx:857
 TGeoHype.cxx:858
 TGeoHype.cxx:859
 TGeoHype.cxx:860
 TGeoHype.cxx:861
 TGeoHype.cxx:862
 TGeoHype.cxx:863
 TGeoHype.cxx:864
 TGeoHype.cxx:865
 TGeoHype.cxx:866
 TGeoHype.cxx:867
 TGeoHype.cxx:868
 TGeoHype.cxx:869
 TGeoHype.cxx:870
 TGeoHype.cxx:871
 TGeoHype.cxx:872
 TGeoHype.cxx:873
 TGeoHype.cxx:874
 TGeoHype.cxx:875
 TGeoHype.cxx:876
 TGeoHype.cxx:877
 TGeoHype.cxx:878
 TGeoHype.cxx:879
 TGeoHype.cxx:880
 TGeoHype.cxx:881
 TGeoHype.cxx:882
 TGeoHype.cxx:883
 TGeoHype.cxx:884
 TGeoHype.cxx:885
 TGeoHype.cxx:886
 TGeoHype.cxx:887
 TGeoHype.cxx:888
 TGeoHype.cxx:889
 TGeoHype.cxx:890
 TGeoHype.cxx:891
 TGeoHype.cxx:892
 TGeoHype.cxx:893
 TGeoHype.cxx:894
 TGeoHype.cxx:895
 TGeoHype.cxx:896
 TGeoHype.cxx:897
 TGeoHype.cxx:898
 TGeoHype.cxx:899
 TGeoHype.cxx:900
 TGeoHype.cxx:901
 TGeoHype.cxx:902
 TGeoHype.cxx:903
 TGeoHype.cxx:904
 TGeoHype.cxx:905
 TGeoHype.cxx:906
 TGeoHype.cxx:907
 TGeoHype.cxx:908
 TGeoHype.cxx:909
 TGeoHype.cxx:910
 TGeoHype.cxx:911
 TGeoHype.cxx:912
 TGeoHype.cxx:913
 TGeoHype.cxx:914
 TGeoHype.cxx:915
 TGeoHype.cxx:916
 TGeoHype.cxx:917
 TGeoHype.cxx:918
 TGeoHype.cxx:919
 TGeoHype.cxx:920
 TGeoHype.cxx:921
 TGeoHype.cxx:922
 TGeoHype.cxx:923
 TGeoHype.cxx:924
 TGeoHype.cxx:925
 TGeoHype.cxx:926
 TGeoHype.cxx:927
 TGeoHype.cxx:928
 TGeoHype.cxx:929
 TGeoHype.cxx:930
 TGeoHype.cxx:931
 TGeoHype.cxx:932
 TGeoHype.cxx:933
 TGeoHype.cxx:934
 TGeoHype.cxx:935
 TGeoHype.cxx:936
 TGeoHype.cxx:937
 TGeoHype.cxx:938
 TGeoHype.cxx:939
 TGeoHype.cxx:940
 TGeoHype.cxx:941
 TGeoHype.cxx:942
 TGeoHype.cxx:943
 TGeoHype.cxx:944
 TGeoHype.cxx:945
 TGeoHype.cxx:946
 TGeoHype.cxx:947
 TGeoHype.cxx:948
 TGeoHype.cxx:949
 TGeoHype.cxx:950
 TGeoHype.cxx:951
 TGeoHype.cxx:952
 TGeoHype.cxx:953
 TGeoHype.cxx:954
 TGeoHype.cxx:955
 TGeoHype.cxx:956
 TGeoHype.cxx:957
 TGeoHype.cxx:958
 TGeoHype.cxx:959
 TGeoHype.cxx:960
 TGeoHype.cxx:961
 TGeoHype.cxx:962
 TGeoHype.cxx:963
 TGeoHype.cxx:964
 TGeoHype.cxx:965
 TGeoHype.cxx:966
 TGeoHype.cxx:967
 TGeoHype.cxx:968
 TGeoHype.cxx:969
 TGeoHype.cxx:970
 TGeoHype.cxx:971
 TGeoHype.cxx:972
 TGeoHype.cxx:973
 TGeoHype.cxx:974
 TGeoHype.cxx:975
 TGeoHype.cxx:976
 TGeoHype.cxx:977
 TGeoHype.cxx:978
 TGeoHype.cxx:979
 TGeoHype.cxx:980
 TGeoHype.cxx:981
 TGeoHype.cxx:982
 TGeoHype.cxx:983
 TGeoHype.cxx:984
 TGeoHype.cxx:985
 TGeoHype.cxx:986
 TGeoHype.cxx:987
 TGeoHype.cxx:988
 TGeoHype.cxx:989
 TGeoHype.cxx:990