TGeoCone.cxx

Go to the documentation of this file.
00001 // @(#)root/geom:$Id: TGeoCone.cxx 35652 2010-09-23 13:38:30Z agheata $
00002 // Author: Andrei Gheata   31/01/02
00003 // TGeoCone::Contains() and DistFromInside() implemented by Mihaela Gheata
00004 
00005 /*************************************************************************
00006  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00007  * All rights reserved.                                                  *
00008  *                                                                       *
00009  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00010  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00011  *************************************************************************/
00012 
00013 //--------------------------------------------------------------------------
00014 // TGeoCone - conical tube  class. It has 5 parameters :
00015 //            dz - half length in z
00016 //            Rmin1, Rmax1 - inside and outside radii at -dz
00017 //            Rmin2, Rmax2 - inside and outside radii at +dz
00018 //
00019 //--------------------------------------------------------------------------
00020 //Begin_Html
00021 /*
00022 <img src="gif/t_cone.gif">
00023 */
00024 //End_Html
00025 //
00026 //Begin_Html
00027 /*
00028 <img src="gif/t_conedivR.gif">
00029 */
00030 //End_Html
00031 //
00032 //Begin_Html
00033 /*
00034 <img src="gif/t_conedivPHI.gif">
00035 */
00036 //End_Html
00037 //Begin_Html
00038 /*
00039 <img src="gif/t_conedivZ.gif">
00040 */
00041 //End_Html
00042 
00043 //--------------------------------------------------------------------------
00044 // TGeoConeSeg - a phi segment of a conical tube. Has 7 parameters :
00045 //            - the same 5 as a cone;
00046 //            - first phi limit (in degrees)
00047 //            - second phi limit
00048 //
00049 //--------------------------------------------------------------------------
00050 //
00051 //Begin_Html
00052 /*
00053 <img src="gif/t_coneseg.gif">
00054 */
00055 //End_Html
00056 //
00057 //Begin_Html
00058 /*
00059 <img src="gif/t_conesegdivstepZ.gif">
00060 */
00061 //End_Html
00062 
00063 #include "Riostream.h"
00064 
00065 #include "TGeoManager.h"
00066 #include "TGeoVolume.h"
00067 #include "TVirtualGeoPainter.h"
00068 #include "TGeoCone.h"
00069 #include "TVirtualPad.h"
00070 #include "TBuffer3D.h"
00071 #include "TBuffer3DTypes.h"
00072 #include "TMath.h"
00073 
00074 ClassImp(TGeoCone)
00075 
00076 //_____________________________________________________________________________
00077 TGeoCone::TGeoCone()
00078 {
00079 // Default constructor
00080    SetShapeBit(TGeoShape::kGeoCone);
00081    fDz    = 0.0;
00082    fRmin1 = 0.0;
00083    fRmax1 = 0.0;
00084    fRmin2 = 0.0;
00085    fRmax2 = 0.0;
00086 }
00087 
00088 //_____________________________________________________________________________
00089 TGeoCone::TGeoCone(Double_t dz, Double_t rmin1, Double_t rmax1,
00090                    Double_t rmin2, Double_t rmax2)
00091          :TGeoBBox(0, 0, 0)
00092 {
00093 // Default constructor specifying minimum and maximum radius
00094    SetShapeBit(TGeoShape::kGeoCone);
00095    SetConeDimensions(dz, rmin1, rmax1, rmin2, rmax2);
00096    if ((dz<0) || (rmin1<0) || (rmax1<0) || (rmin2<0) || (rmax2<0)) {
00097       SetShapeBit(kGeoRunTimeShape);
00098    }
00099    else ComputeBBox();
00100 }
00101 
00102 //_____________________________________________________________________________
00103 TGeoCone::TGeoCone(const char *name, Double_t dz, Double_t rmin1, Double_t rmax1,
00104                    Double_t rmin2, Double_t rmax2)
00105          :TGeoBBox(name, 0, 0, 0)
00106 {
00107 // Default constructor specifying minimum and maximum radius
00108    SetShapeBit(TGeoShape::kGeoCone);
00109    SetConeDimensions(dz, rmin1, rmax1, rmin2, rmax2);
00110    if ((dz<0) || (rmin1<0) || (rmax1<0) || (rmin2<0) || (rmax2<0)) {
00111       SetShapeBit(kGeoRunTimeShape);
00112    }
00113    else ComputeBBox();
00114 }
00115 
00116 //_____________________________________________________________________________
00117 TGeoCone::TGeoCone(Double_t *param)
00118          :TGeoBBox(0, 0, 0)
00119 {
00120 // Default constructor specifying minimum and maximum radius
00121 // param[0] = dz
00122 // param[1] = Rmin1
00123 // param[2] = Rmax1
00124 // param[3] = Rmin2
00125 // param[4] = Rmax2
00126    SetShapeBit(TGeoShape::kGeoCone);
00127    SetDimensions(param);
00128    if ((fDz<0) || (fRmin1<0) || (fRmax1<0) || (fRmin2<0) || (fRmax2<0))
00129       SetShapeBit(kGeoRunTimeShape);
00130    else ComputeBBox();
00131 }
00132 
00133 //_____________________________________________________________________________
00134 Double_t TGeoCone::Capacity() const
00135 {
00136 // Computes capacity of the shape in [length^3]
00137    return TGeoCone::Capacity(fDz, fRmin1, fRmax1, fRmin2, fRmax2);
00138 }   
00139 
00140 //_____________________________________________________________________________
00141 Double_t TGeoCone::Capacity(Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
00142 {
00143 // Computes capacity of the shape in [length^3]
00144    Double_t capacity = (2.*dz*TMath::Pi()/3.)*(rmax1*rmax1+rmax2*rmax2+rmax1*rmax2-
00145                                                rmin1*rmin1-rmin2*rmin2-rmin1*rmin2);
00146    return capacity;                                            
00147 }   
00148 
00149 //_____________________________________________________________________________
00150 TGeoCone::~TGeoCone()
00151 {
00152 // destructor
00153 }
00154 
00155 //_____________________________________________________________________________
00156 void TGeoCone::ComputeBBox()
00157 {
00158 // compute bounding box of the sphere
00159    TGeoBBox *box = (TGeoBBox*)this;
00160    box->SetBoxDimensions(TMath::Max(fRmax1, fRmax2), TMath::Max(fRmax1, fRmax2), fDz);
00161    memset(fOrigin, 0, 3*sizeof(Double_t));
00162 }
00163 
00164 //_____________________________________________________________________________
00165 void TGeoCone::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00166 {
00167 // Compute normal to closest surface from POINT.
00168    Double_t safr,safe,phi;
00169    memset(norm,0,3*sizeof(Double_t));
00170    phi = TMath::ATan2(point[1],point[0]);
00171    Double_t cphi = TMath::Cos(phi);
00172    Double_t sphi = TMath::Sin(phi);
00173    Double_t ro1 = 0.5*(fRmin1+fRmin2);
00174    Double_t tg1 = 0.5*(fRmin2-fRmin1)/fDz;
00175    Double_t cr1 = 1./TMath::Sqrt(1.+tg1*tg1);
00176    Double_t ro2 = 0.5*(fRmax1+fRmax2);
00177    Double_t tg2 = 0.5*(fRmax2-fRmax1)/fDz;
00178    Double_t cr2 = 1./TMath::Sqrt(1.+tg2*tg2);
00179 
00180    Double_t r=TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
00181    Double_t rin = tg1*point[2]+ro1;
00182    Double_t rout = tg2*point[2]+ro2;
00183    safe = TMath::Abs(fDz-TMath::Abs(point[2]));
00184    norm[2] = 1;
00185 
00186    safr = (ro1>0)?(TMath::Abs((r-rin)*cr1)):TGeoShape::Big();
00187    if (safr<safe) {
00188       safe = safr;
00189       norm[0] = cr1*cphi;
00190       norm[1] = cr1*sphi;
00191       norm[2] = -tg1*cr1;
00192    }
00193    safr = TMath::Abs((rout-r)*cr2);
00194    if (safr<safe) {
00195       norm[0] = cr2*cphi;
00196       norm[1] = cr2*sphi;
00197       norm[2] = -tg2*cr2;
00198    }
00199    if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
00200       norm[0] = -norm[0];
00201       norm[1] = -norm[1];
00202       norm[2] = -norm[2];
00203    }
00204 }
00205 
00206 //_____________________________________________________________________________
00207 void TGeoCone::ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
00208                               Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
00209 {
00210 // Compute normal to closest surface from POINT.
00211    Double_t safe,phi;
00212    memset(norm,0,3*sizeof(Double_t));
00213    phi = TMath::ATan2(point[1],point[0]);
00214    Double_t cphi = TMath::Cos(phi);
00215    Double_t sphi = TMath::Sin(phi);
00216    Double_t ro1 = 0.5*(rmin1+rmin2);
00217    Double_t tg1 = 0.5*(rmin2-rmin1)/dz;
00218    Double_t cr1 = 1./TMath::Sqrt(1.+tg1*tg1);
00219    Double_t ro2 = 0.5*(rmax1+rmax2);
00220    Double_t tg2 = 0.5*(rmax2-rmax1)/dz;
00221    Double_t cr2 = 1./TMath::Sqrt(1.+tg2*tg2);
00222 
00223    Double_t r=TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
00224    Double_t rin = tg1*point[2]+ro1;
00225    Double_t rout = tg2*point[2]+ro2;
00226    safe = (ro1>0)?(TMath::Abs((r-rin)*cr1)):TGeoShape::Big();
00227    norm[0] = cr1*cphi;
00228    norm[1] = cr1*sphi;
00229    norm[2] = -tg1*cr1;
00230    if (TMath::Abs((rout-r)*cr2)<safe) {
00231       norm[0] = cr2*cphi;
00232       norm[1] = cr2*sphi;
00233       norm[2] = -tg2*cr2;
00234    }
00235    if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
00236       norm[0] = -norm[0];
00237       norm[1] = -norm[1];
00238       norm[2] = -norm[2];
00239    }
00240 }
00241 
00242 //_____________________________________________________________________________
00243 Bool_t TGeoCone::Contains(Double_t *point) const
00244 {
00245 // test if point is inside this cone
00246    if (TMath::Abs(point[2]) > fDz) return kFALSE;
00247    Double_t r2 = point[0]*point[0]+point[1]*point[1];
00248    Double_t rl = 0.5*(fRmin2*(point[2]+fDz)+fRmin1*(fDz-point[2]))/fDz;
00249    Double_t rh = 0.5*(fRmax2*(point[2]+fDz)+fRmax1*(fDz-point[2]))/fDz;
00250    if ((r2<rl*rl) || (r2>rh*rh)) return kFALSE;
00251    return kTRUE;
00252 }
00253 
00254 //_____________________________________________________________________________
00255 Double_t TGeoCone::DistFromInsideS(Double_t *point, Double_t *dir, Double_t dz,
00256                               Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
00257 {
00258 // Compute distance from inside point to surface of the cone (static)
00259 // Boundary safe algorithm.
00260    if (dz<=0) return TGeoShape::Big();
00261    // compute distance to surface
00262    // Do Z
00263    Double_t sz = TGeoShape::Big();
00264    if (dir[2]) {
00265       sz = (TMath::Sign(dz, dir[2])-point[2])/dir[2];
00266       if (sz<=0) return 0.0;
00267    }   
00268    Double_t rsq=point[0]*point[0]+point[1]*point[1];
00269    Double_t zinv = 1./dz;
00270    Double_t rin = 0.5*(rmin1+rmin2+(rmin2-rmin1)*point[2]*zinv);
00271    // Do Rmin
00272    Double_t sr = TGeoShape::Big();
00273    Double_t b,delta,zi;
00274    if (rin>0) {
00275       // Protection in case point is actually outside the cone
00276       if (rsq < rin*(rin+TGeoShape::Tolerance())) {
00277          Double_t ddotn = point[0]*dir[0]+point[1]*dir[1]+0.5*(rmin1-rmin2)*dir[2]*zinv*TMath::Sqrt(rsq);
00278          if (ddotn<=0) return 0.0;
00279       } else {         
00280          TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta);
00281          if (delta>0) {
00282             sr = -b-delta;
00283             if (sr>0) {
00284                zi = point[2]+sr*dir[2];
00285                if (TMath::Abs(zi)<=dz) return TMath::Min(sz,sr);
00286             }
00287             sr = -b+delta;   
00288             if (sr>0) {
00289                zi = point[2]+sr*dir[2];
00290                if (TMath::Abs(zi)<=dz) return TMath::Min(sz,sr);
00291             }
00292          }
00293       }
00294    }
00295    // Do Rmax
00296    Double_t rout = 0.5*(rmax1+rmax2+(rmax2-rmax1)*point[2]*zinv);
00297    if (rsq > rout*(rout-TGeoShape::Tolerance())) {
00298       Double_t ddotn = point[0]*dir[0]+point[1]*dir[1]+0.5*(rmax1-rmax2)*dir[2]*zinv*TMath::Sqrt(rsq);
00299       if (ddotn>=0) return 0.0;
00300       TGeoCone::DistToCone(point, dir, dz, rmax1, rmax2, b, delta);
00301       if (delta<0) return 0.0;
00302       sr = -b+delta;
00303       if (sr<0) return sz;
00304       if (TMath::Abs(-b-delta)>sr) return sz;
00305       zi = point[2]+sr*dir[2];
00306       if (TMath::Abs(zi)<=dz) return TMath::Min(sz,sr);
00307       return sz;
00308    }   
00309    TGeoCone::DistToCone(point, dir, dz, rmax1, rmax2, b, delta);
00310    if (delta>0) {
00311       sr = -b-delta;
00312       if (sr>0) {
00313          zi = point[2]+sr*dir[2];
00314          if (TMath::Abs(zi)<=dz) return TMath::Min(sz,sr);
00315       }
00316       sr = -b+delta;   
00317       if (sr>TGeoShape::Tolerance()) {
00318          zi = point[2]+sr*dir[2];
00319          if (TMath::Abs(zi)<=dz) return TMath::Min(sz,sr);
00320       }
00321    }
00322    return sz;   
00323 }
00324 
00325 //_____________________________________________________________________________
00326 Double_t TGeoCone::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00327 {
00328 // Compute distance from inside point to surface of the cone
00329 // Boundary safe algorithm.
00330 
00331    if (iact<3 && safe) {
00332       *safe = Safety(point, kTRUE);
00333       if (iact==0) return TGeoShape::Big();
00334       if ((iact==1) && (*safe>step)) return TGeoShape::Big();
00335    }
00336    // compute distance to surface
00337    return TGeoCone::DistFromInsideS(point, dir, fDz, fRmin1, fRmax1, fRmin2, fRmax2);
00338 }
00339 
00340 //_____________________________________________________________________________
00341 Double_t TGeoCone::DistFromOutsideS(Double_t *point, Double_t *dir, Double_t dz,
00342                              Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2)
00343 {
00344 // Compute distance from outside point to surface of the tube
00345 // Boundary safe algorithm.
00346    // compute distance to Z planes
00347    if (dz<=0) return TGeoShape::Big();
00348    Double_t snxt;
00349    Double_t xp, yp, zp;
00350    Bool_t inz = kTRUE;
00351 
00352    if (point[2]<=-dz) {
00353       if (dir[2]<=0) return TGeoShape::Big();
00354       snxt = (-dz-point[2])/dir[2];
00355       xp = point[0]+snxt*dir[0];
00356       yp = point[1]+snxt*dir[1];
00357       Double_t r2 = xp*xp+yp*yp;
00358       if ((r2>=rmin1*rmin1) && (r2<=rmax1*rmax1)) return snxt;
00359       inz = kFALSE;
00360    } else {
00361       if (point[2]>=dz) {
00362          if (dir[2]>=0) return TGeoShape::Big();
00363          snxt = (dz-point[2])/dir[2];
00364          xp = point[0]+snxt*dir[0];
00365          yp = point[1]+snxt*dir[1];
00366          Double_t r2 = xp*xp+yp*yp;
00367          if ((r2>=rmin2*rmin2) && (r2<=rmax2*rmax2)) return snxt;
00368          inz = kFALSE;
00369       }   
00370    }
00371 
00372    Double_t rsq = point[0]*point[0]+point[1]*point[1];
00373    Double_t dzinv = 1./dz;
00374    Double_t ro1=0.5*(rmin1+rmin2);
00375    Bool_t hasrmin = (ro1>0)?kTRUE:kFALSE;
00376    Double_t tg1 = 0.;
00377    Double_t rin = 0.;
00378    Bool_t inrmin = kTRUE;  // r>=rmin
00379    if (hasrmin) {
00380       tg1=0.5*(rmin2-rmin1)*dzinv;
00381       rin=ro1+tg1*point[2];
00382       if (rin>0 && rsq<rin*(rin-TGeoShape::Tolerance())) inrmin=kFALSE;
00383    }   
00384    Double_t ro2=0.5*(rmax1+rmax2);
00385    Double_t tg2=0.5*(rmax2-rmax1)*dzinv;
00386    Double_t rout=tg2*point[2]+ro2;
00387    Bool_t inrmax = kFALSE;
00388    if (rout>0 && rsq<rout*(rout+TGeoShape::Tolerance())) inrmax=kTRUE;
00389    Bool_t in = inz & inrmin & inrmax;
00390    Double_t b,delta;
00391    // If inside cone, we are most likely on a boundary within machine precision.
00392    if (in) {
00393       Double_t r=TMath::Sqrt(rsq);
00394       Double_t safz = dz-TMath::Abs(point[2]); // positive
00395       Double_t safrmin = (hasrmin)?(r-rin):TGeoShape::Big();
00396       Double_t safrmax = rout - r;
00397       if (safz<=safrmin && safz<=safrmax) {
00398          // on Z boundary
00399          if (point[2]*dir[2]<0) return 0.0;
00400          return TGeoShape::Big();
00401       }
00402       if (safrmax<safrmin) {
00403          // on rmax boundary
00404          Double_t ddotn = point[0]*dir[0]+point[1]*dir[1]-tg2*dir[2]*r;
00405          if (ddotn<=0) return 0.0;
00406          return TGeoShape::Big();
00407       }   
00408       // on rmin boundary
00409       Double_t ddotn = point[0]*dir[0]+point[1]*dir[1]-tg1*dir[2]*r;
00410       if (ddotn>=0) return 0.0;
00411       // we can cross (+) solution of rmin       
00412       TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta);
00413 
00414       if (delta<0) return 0.0;
00415       snxt = -b+delta;
00416       if (snxt<0) return TGeoShape::Big();
00417       if (TMath::Abs(-b-delta)>snxt) return TGeoShape::Big();
00418       zp = point[2]+snxt*dir[2];
00419       if (TMath::Abs(zp)<=dz) return snxt;
00420       return TGeoShape::Big();
00421    }
00422             
00423    // compute distance to inner cone
00424    snxt = TGeoShape::Big();
00425    if (!inrmin) {
00426       // ray can cross inner cone (but not only!)
00427       TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta);
00428       if (delta<0) return TGeoShape::Big();
00429       snxt = -b+delta;
00430       if (snxt>0) {
00431          zp = point[2]+snxt*dir[2];
00432          if (TMath::Abs(zp)<=dz) return snxt;
00433       }   
00434       snxt = -b-delta;
00435       if (snxt>0) {
00436          zp = point[2]+snxt*dir[2];
00437          if (TMath::Abs(zp)<=dz) return snxt;
00438       }   
00439       snxt = TGeoShape::Big();      
00440    } else {
00441       if (hasrmin) {
00442          TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta);
00443          if (delta>0) {
00444             Double_t din = -b+delta;
00445             if (din>0) {
00446                zp = point[2]+din*dir[2];
00447                if (TMath::Abs(zp)<=dz) snxt = din;
00448             }
00449          }
00450       }
00451    }   
00452    
00453    if (inrmax) return snxt;
00454    // We can cross outer cone, both solutions possible
00455    // compute distance to outer cone
00456    TGeoCone::DistToCone(point, dir, dz, rmax1, rmax2, b, delta);
00457    if (delta<0) return snxt;
00458    Double_t dout = -b-delta;
00459    if (dout>0 && dout<snxt) {
00460       zp = point[2]+dout*dir[2];
00461       if (TMath::Abs(zp)<=dz) return dout;
00462    }
00463    dout = -b+delta;  
00464    if (dout<=0 || dout>snxt) return snxt;
00465    zp = point[2]+dout*dir[2];
00466    if (TMath::Abs(zp)<=dz) return dout;
00467    return snxt;
00468 }
00469 
00470 //_____________________________________________________________________________
00471 Double_t TGeoCone::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00472 {
00473 // compute distance from outside point to surface of the tube
00474    // compute safe radius
00475    if (iact<3 && safe) {
00476       *safe = Safety(point, kFALSE);
00477       if (iact==0) return TGeoShape::Big();
00478       if ((iact==1) && (*safe>step)) return TGeoShape::Big();
00479    }
00480 // Check if the bounding box is crossed within the requested distance
00481    Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
00482    if (sdist>=step) return TGeoShape::Big();
00483    // compute distance to Z planes
00484    return TGeoCone::DistFromOutsideS(point, dir, fDz, fRmin1, fRmax1, fRmin2, fRmax2);
00485 }
00486 
00487 //_____________________________________________________________________________
00488 void TGeoCone::DistToCone(Double_t *point, Double_t *dir, Double_t dz, Double_t r1, Double_t r2,
00489                               Double_t &b, Double_t &delta)
00490 {
00491    // Static method to compute distance to a conical surface with :
00492    // - r1, z1 - radius and Z position of lower base
00493    // - r2, z2 - radius and Z position of upper base
00494    delta = -1.;
00495    if (dz<0) return;
00496    Double_t ro0 = 0.5*(r1+r2);
00497    Double_t tz  = 0.5*(r2-r1)/dz;
00498    Double_t rsq = point[0]*point[0] + point[1]*point[1];
00499    Double_t rc = ro0 + point[2]*tz;
00500 
00501    Double_t a = dir[0]*dir[0] + dir[1]*dir[1] - tz*tz*dir[2]*dir[2];
00502    b = point[0]*dir[0] + point[1]*dir[1] - tz*rc*dir[2];
00503    Double_t c = rsq - rc*rc;
00504 
00505    if (TMath::Abs(a)<TGeoShape::Tolerance()) {
00506       if (TMath::Abs(b)<TGeoShape::Tolerance()) return;
00507       b = 0.5*c/b;
00508       delta = 0.;
00509       return;
00510    }   
00511    a = 1./a;
00512    b *= a;
00513    c *= a;
00514    delta = b*b - c;
00515    if (delta>0) {
00516       delta = TMath::Sqrt(delta);
00517    } else {
00518       delta = -1.;
00519    }
00520 }
00521 
00522 //_____________________________________________________________________________
00523 Int_t TGeoCone::DistancetoPrimitive(Int_t px, Int_t py)
00524 {
00525 // compute closest distance from point px,py to each corner
00526    Int_t n = gGeoManager->GetNsegments();
00527    const Int_t numPoints = 4*n;
00528    return ShapeDistancetoPrimitive(numPoints, px, py);
00529 }
00530 
00531 //_____________________________________________________________________________
00532 TGeoVolume *TGeoCone::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv,
00533                              Double_t start, Double_t step)
00534 {
00535 //--- Divide this cone shape belonging to volume "voldiv" into ndiv volumes
00536 // called divname, from start position with the given step. Returns pointer
00537 // to created division cell volume in case of Z divisions. For Z division
00538 // creates all volumes with different shapes and returns pointer to volume that
00539 // was divided. In case a wrong division axis is supplied, returns pointer to
00540 // volume that was divided.
00541    TGeoShape *shape;           //--- shape to be created
00542    TGeoVolume *vol;            //--- division volume to be created
00543    TGeoVolumeMulti *vmulti;    //--- generic divided volume
00544    TGeoPatternFinder *finder;  //--- finder to be attached
00545    TString opt = "";           //--- option to be attached
00546    Int_t id;
00547    Double_t end = start+ndiv*step;
00548    switch (iaxis) {
00549       case 1:  //---              R division
00550          Error("Divide","division of a cone on R not implemented");
00551          return 0;
00552       case 2:  // ---             Phi division
00553          finder = new TGeoPatternCylPhi(voldiv, ndiv, start, end);
00554          voldiv->SetFinder(finder);
00555          finder->SetDivIndex(voldiv->GetNdaughters());
00556          shape = new TGeoConeSeg(fDz, fRmin1, fRmax1, fRmin2, fRmax2, -step/2, step/2);
00557          vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
00558          vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
00559          vmulti->AddVolume(vol);
00560          opt = "Phi";
00561          for (id=0; id<ndiv; id++) {
00562             voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
00563             ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
00564          }
00565          return vmulti;
00566       case 3: //---               Z division
00567          vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
00568          finder = new TGeoPatternZ(voldiv, ndiv, start, end);
00569          voldiv->SetFinder(finder);
00570          finder->SetDivIndex(voldiv->GetNdaughters());
00571          for (id=0; id<ndiv; id++) {
00572             Double_t z1 = start+id*step;
00573             Double_t z2 = start+(id+1)*step;
00574             Double_t rmin1n = 0.5*(fRmin1*(fDz-z1)+fRmin2*(fDz+z1))/fDz;
00575             Double_t rmax1n = 0.5*(fRmax1*(fDz-z1)+fRmax2*(fDz+z1))/fDz;
00576             Double_t rmin2n = 0.5*(fRmin1*(fDz-z2)+fRmin2*(fDz+z2))/fDz;
00577             Double_t rmax2n = 0.5*(fRmax1*(fDz-z2)+fRmax2*(fDz+z2))/fDz;
00578             shape = new TGeoCone(0.5*step,rmin1n, rmax1n, rmin2n, rmax2n);
00579             vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
00580             vmulti->AddVolume(vol);
00581             opt = "Z";
00582             voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
00583             ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
00584          }
00585          return vmulti;
00586       default:
00587          Error("Divide", "Wrong axis type for division");
00588          return 0;
00589    }
00590 }
00591 
00592 //_____________________________________________________________________________
00593 const char *TGeoCone::GetAxisName(Int_t iaxis) const
00594 {
00595 // Returns name of axis IAXIS.
00596    switch (iaxis) {
00597       case 1:
00598          return "R";
00599       case 2:
00600          return "PHI";
00601       case 3:
00602          return "Z";
00603       default:
00604          return "undefined";
00605    }
00606 }
00607 
00608 //_____________________________________________________________________________
00609 Double_t TGeoCone::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
00610 {
00611 // Get range of shape for a given axis.
00612    xlo = 0;
00613    xhi = 0;
00614    Double_t dx = 0;
00615    switch (iaxis) {
00616       case 2:
00617          xlo = 0.;
00618          xhi = 360.;
00619          return 360.;
00620       case 3:
00621          xlo = -fDz;
00622          xhi = fDz;
00623          dx = xhi-xlo;
00624          return dx;
00625    }
00626    return dx;
00627 }
00628 
00629 //_____________________________________________________________________________
00630 void TGeoCone::GetBoundingCylinder(Double_t *param) const
00631 {
00632 //--- Fill vector param[4] with the bounding cylinder parameters. The order
00633 // is the following : Rmin, Rmax, Phi1, Phi2, dZ
00634    param[0] = TMath::Min(fRmin1, fRmin2); // Rmin
00635    param[0] *= param[0];
00636    param[1] = TMath::Max(fRmax1, fRmax2); // Rmax
00637    param[1] *= param[1];
00638    param[2] = 0.;                         // Phi1
00639    param[3] = 360.;                       // Phi1
00640 }
00641 
00642 //_____________________________________________________________________________
00643 TGeoShape *TGeoCone::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * /*mat*/) const
00644 {
00645 // in case shape has some negative parameters, these has to be computed
00646 // in order to fit the mother
00647    if (!TestShapeBit(kGeoRunTimeShape)) return 0;
00648    if (!mother->TestShapeBit(kGeoCone)) {
00649       Error("GetMakeRuntimeShape", "invalid mother");
00650       return 0;
00651    }
00652    Double_t rmin1, rmax1, rmin2, rmax2, dz;
00653    rmin1 = fRmin1;
00654    rmax1 = fRmax1;
00655    rmin2 = fRmin2;
00656    rmax2 = fRmax2;
00657    dz = fDz;
00658    if (fDz<0) dz=((TGeoCone*)mother)->GetDz();
00659    if (fRmin1<0)
00660       rmin1 = ((TGeoCone*)mother)->GetRmin1();
00661    if (fRmax1<0)
00662       rmax1 = ((TGeoCone*)mother)->GetRmax1();
00663    if (fRmin2<0)
00664       rmin2 = ((TGeoCone*)mother)->GetRmin2();
00665    if (fRmax2<0)
00666       rmax2 = ((TGeoCone*)mother)->GetRmax2();
00667 
00668    return (new TGeoCone(GetName(), dz, rmin1, rmax1, rmin2, rmax2));
00669 }
00670 
00671 //_____________________________________________________________________________
00672 Bool_t TGeoCone::GetPointsOnSegments(Int_t npoints, Double_t *array) const
00673 {
00674 // Fills array with n random points located on the line segments of the shape mesh.
00675 // The output array must be provided with a length of minimum 3*npoints. Returns
00676 // true if operation is implemented.
00677    if (npoints > (npoints/2)*2) {
00678       Error("GetPointsOnSegments","Npoints must be even number");
00679       return kFALSE;
00680    }   
00681    Bool_t hasrmin = (fRmin1>0 || fRmin2>0)?kTRUE:kFALSE;
00682    Int_t nc = 0;
00683    if (hasrmin)   nc = (Int_t)TMath::Sqrt(0.5*npoints);
00684    else           nc = (Int_t)TMath::Sqrt(1.*npoints);
00685    Double_t dphi = TMath::TwoPi()/nc;
00686    Double_t phi = 0;
00687    Int_t ntop = 0;
00688    if (hasrmin)   ntop = npoints/2 - nc*(nc-1);
00689    else           ntop = npoints - nc*(nc-1);
00690    Double_t dz = 2*fDz/(nc-1);
00691    Double_t z = 0;
00692    Int_t icrt = 0;
00693    Int_t nphi = nc;
00694    Double_t rmin = 0.;
00695    Double_t rmax = 0.;
00696    // loop z sections
00697    for (Int_t i=0; i<nc; i++) {
00698       if (i == (nc-1)) nphi = ntop;
00699       z = -fDz + i*dz;
00700       if (hasrmin) rmin = 0.5*(fRmin1+fRmin2) + 0.5*(fRmin2-fRmin1)*z/fDz;
00701       rmax = 0.5*(fRmax1+fRmax2) + 0.5*(fRmax2-fRmax1)*z/fDz; 
00702       // loop points on circle sections
00703       for (Int_t j=0; j<nphi; j++) {
00704          phi = j*dphi;
00705          if (hasrmin) {
00706             array[icrt++] = rmin * TMath::Cos(phi);
00707             array[icrt++] = rmin * TMath::Sin(phi);
00708             array[icrt++] = z;
00709          }
00710          array[icrt++] = rmax * TMath::Cos(phi);
00711          array[icrt++] = rmax * TMath::Sin(phi);
00712          array[icrt++] = z;
00713       }
00714    }
00715    return kTRUE;
00716 }                    
00717 
00718 
00719 //_____________________________________________________________________________
00720 void TGeoCone::InspectShape() const
00721 {
00722 // print shape parameters
00723    printf("*** Shape %s TGeoCone ***\n", GetName());
00724    printf("    dz    =: %11.5f\n", fDz);
00725    printf("    Rmin1 = %11.5f\n", fRmin1);
00726    printf("    Rmax1 = %11.5f\n", fRmax1);
00727    printf("    Rmin2 = %11.5f\n", fRmin2);
00728    printf("    Rmax2 = %11.5f\n", fRmax2);
00729    printf(" Bounding box:\n");
00730    TGeoBBox::InspectShape();
00731 }
00732 
00733 //_____________________________________________________________________________
00734 TBuffer3D *TGeoCone::MakeBuffer3D() const
00735 { 
00736    // Creates a TBuffer3D describing *this* shape.
00737    // Coordinates are in local reference frame.
00738 
00739    Int_t n = gGeoManager->GetNsegments();
00740    Int_t nbPnts = 4*n;
00741    Int_t nbSegs = 8*n;
00742    Int_t nbPols = 4*n; 
00743    TBuffer3D* buff = new TBuffer3D(TBuffer3DTypes::kGeneric,
00744                                    nbPnts, 3*nbPnts,
00745                                    nbSegs, 3*nbSegs,
00746                                    nbPols, 6*nbPols);
00747 
00748    if (buff)
00749    {
00750       SetPoints(buff->fPnts);   
00751       SetSegsAndPols(*buff);
00752    }
00753    return buff; 
00754 }
00755 
00756 //_____________________________________________________________________________
00757 void TGeoCone::SetSegsAndPols(TBuffer3D &buffer) const
00758 {
00759 // Fill TBuffer3D structure for segments and polygons.
00760    Int_t i,j;
00761    Int_t n = gGeoManager->GetNsegments();
00762    Int_t c = GetBasicColor();
00763 
00764    for (i = 0; i < 4; i++) {
00765       for (j = 0; j < n; j++) {
00766          buffer.fSegs[(i*n+j)*3  ] = c;
00767          buffer.fSegs[(i*n+j)*3+1] = i*n+j;
00768          buffer.fSegs[(i*n+j)*3+2] = i*n+j+1;
00769       }
00770       buffer.fSegs[(i*n+j-1)*3+2] = i*n;
00771    }
00772    for (i = 4; i < 6; i++) {
00773       for (j = 0; j < n; j++) {
00774          buffer.fSegs[(i*n+j)*3  ] = c+1;
00775          buffer.fSegs[(i*n+j)*3+1] = (i-4)*n+j;
00776          buffer.fSegs[(i*n+j)*3+2] = (i-2)*n+j;
00777       }
00778    }
00779    for (i = 6; i < 8; i++) {
00780       for (j = 0; j < n; j++) {
00781          buffer.fSegs[(i*n+j)*3  ] = c;
00782          buffer.fSegs[(i*n+j)*3+1] = 2*(i-6)*n+j;
00783          buffer.fSegs[(i*n+j)*3+2] = (2*(i-6)+1)*n+j;
00784       }
00785    }
00786 
00787    Int_t indx = 0;
00788    i=0;
00789    for (j = 0; j < n; j++) {
00790       indx = 6*(i*n+j);
00791       buffer.fPols[indx  ] = c;
00792       buffer.fPols[indx+1] = 4;
00793       buffer.fPols[indx+5] = i*n+j;
00794       buffer.fPols[indx+4] = (4+i)*n+j;
00795       buffer.fPols[indx+3] = (2+i)*n+j;
00796       buffer.fPols[indx+2] = (4+i)*n+j+1;
00797    }
00798    buffer.fPols[indx+2] = (4+i)*n;
00799    i=1;
00800    for (j = 0; j < n; j++) {
00801       indx = 6*(i*n+j);
00802       buffer.fPols[indx  ] = c;
00803       buffer.fPols[indx+1] = 4;
00804       buffer.fPols[indx+2] = i*n+j;
00805       buffer.fPols[indx+3] = (4+i)*n+j;
00806       buffer.fPols[indx+4] = (2+i)*n+j;
00807       buffer.fPols[indx+5] = (4+i)*n+j+1;
00808    }
00809    buffer.fPols[indx+5] = (4+i)*n;
00810    i=2;
00811    for (j = 0; j < n; j++) {
00812       indx = 6*(i*n+j);
00813       buffer.fPols[indx  ] = c+i;
00814       buffer.fPols[indx+1] = 4;
00815       buffer.fPols[indx+2] = (i-2)*2*n+j;
00816       buffer.fPols[indx+3] = (4+i)*n+j;
00817       buffer.fPols[indx+4] = ((i-2)*2+1)*n+j;
00818       buffer.fPols[indx+5] = (4+i)*n+j+1;
00819    }
00820    buffer.fPols[indx+5] = (4+i)*n;
00821    i=3;
00822    for (j = 0; j < n; j++) {
00823       indx = 6*(i*n+j);
00824       buffer.fPols[indx  ] = c+i;
00825       buffer.fPols[indx+1] = 4;
00826       buffer.fPols[indx+5] = (i-2)*2*n+j;
00827       buffer.fPols[indx+4] = (4+i)*n+j;
00828       buffer.fPols[indx+3] = ((i-2)*2+1)*n+j;
00829       buffer.fPols[indx+2] = (4+i)*n+j+1;
00830    }
00831    buffer.fPols[indx+2] = (4+i)*n;
00832 }
00833 
00834 //_____________________________________________________________________________
00835 Double_t TGeoCone::Safety(Double_t *point, Bool_t in) const
00836 {
00837 // computes the closest distance from given point to this shape, according
00838 // to option. The matching point on the shape is stored in spoint.
00839    Double_t saf[3];
00840 //   Double_t edges[4];
00841 //   edges[0] = edges[1] = edges[2] = edges[3] = TGeoShape::Big();
00842    Double_t ro1 = 0.5*(fRmin1+fRmin2);
00843    Double_t tg1 = 0.5*(fRmin2-fRmin1)/fDz;
00844    Double_t cr1 = 1./TMath::Sqrt(1.+tg1*tg1);
00845    Double_t ro2 = 0.5*(fRmax1+fRmax2);
00846    Double_t tg2 = 0.5*(fRmax2-fRmax1)/fDz;
00847    Double_t cr2 = 1./TMath::Sqrt(1.+tg2*tg2);
00848 
00849    Double_t r=TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
00850    Double_t rin = tg1*point[2]+ro1;
00851    Double_t rout = tg2*point[2]+ro2;
00852    saf[0] = fDz-TMath::Abs(point[2]);
00853    saf[1] = (ro1>0)?((r-rin)*cr1):TGeoShape::Big();
00854    saf[2] = (rout-r)*cr2;
00855    if (in) return saf[TMath::LocMin(3,saf)];
00856    for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
00857    return saf[TMath::LocMax(3,saf)];
00858    // Compute distance to visible edges
00859 /*
00860    if (r<rin || point[2]<-fDz) edges[0] = (r-fRmin1)*(r-fRmin1) + (point[2]+fDz)*(point[2]+fDz);
00861    if (r<rin || point[2]>fDz) edges[1] = (r-fRmin2)*(r-fRmin2) + (point[2]-fDz)*(point[2]-fDz);
00862    if (r>rout || point[2]<-fDz) edges[2] = (r-fRmax1)*(r-fRmax1) + (point[2]+fDz)*(point[2]+fDz);
00863    if (r>rout || point[2]>fDz) edges[3] = (r-fRmax2)*(r-fRmax2) + (point[2]-fDz)*(point[2]-fDz);
00864    Double_t dist_edge = edges[TMath::LocMin(4,edges)];
00865    if (dist_edge>1.e10) dist_edge = 0;
00866    else dist_edge = TMath::Sqrt(dist_edge);
00867    Double_t dist_side = saf[TMath::LocMax(3,saf)];
00868    return TMath::Max(dist_edge,dist_side);
00869 */
00870 }
00871 
00872 //_____________________________________________________________________________
00873 Double_t TGeoCone::SafetyS(Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1,
00874                            Double_t rmin2, Double_t rmax2, Int_t skipz)
00875 {
00876 // computes the closest distance from given point to this shape, according
00877 // to option. The matching point on the shape is stored in spoint.
00878    Double_t saf[3];
00879    Double_t ro1 = 0.5*(rmin1+rmin2);
00880    Double_t tg1 = 0.5*(rmin2-rmin1)/dz;
00881    Double_t cr1 = 1./TMath::Sqrt(1.+tg1*tg1);
00882    Double_t ro2 = 0.5*(rmax1+rmax2);
00883    Double_t tg2 = 0.5*(rmax2-rmax1)/dz;
00884    Double_t cr2 = 1./TMath::Sqrt(1.+tg2*tg2);
00885 
00886    Double_t r=TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
00887    Double_t rin = tg1*point[2]+ro1;
00888    Double_t rout = tg2*point[2]+ro2;
00889    switch (skipz) {
00890       case 1: // skip lower Z plane
00891          saf[0] = dz - point[2];
00892          break;
00893       case 2: // skip upper Z plane
00894          saf[0] = dz + point[2];
00895          break;
00896       case 3: // skip both
00897          saf[0] = TGeoShape::Big();
00898          break;
00899       default:
00900          saf[0] = dz-TMath::Abs(point[2]);
00901    }
00902    saf[1] = (ro1>0)?((r-rin)*cr1):TGeoShape::Big();
00903    saf[2] = (rout-r)*cr2;
00904    if (in) return saf[TMath::LocMin(3,saf)];
00905    for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
00906    return saf[TMath::LocMax(3,saf)];
00907 }
00908 
00909 //_____________________________________________________________________________
00910 void TGeoCone::SavePrimitive(ostream &out, Option_t * /*option*/ /*= ""*/)
00911 {
00912 // Save a primitive as a C++ statement(s) on output stream "out".
00913    if (TObject::TestBit(kGeoSavePrimitive)) return;
00914    out << "   // Shape: " << GetName() << " type: " << ClassName() << endl;
00915    out << "   dz    = " << fDz << ";" << endl;
00916    out << "   rmin1 = " << fRmin1 << ";" << endl;
00917    out << "   rmax1 = " << fRmax1 << ";" << endl;
00918    out << "   rmin2 = " << fRmin2 << ";" << endl;
00919    out << "   rmax2 = " << fRmax2 << ";" << endl;
00920    out << "   TGeoShape *" << GetPointerName() << " = new TGeoCone(\"" << GetName() << "\", dz,rmin1,rmax1,rmin2,rmax2);" << endl;
00921    TObject::SetBit(TGeoShape::kGeoSavePrimitive);   
00922 }
00923          
00924 //_____________________________________________________________________________
00925 void TGeoCone::SetConeDimensions(Double_t dz, Double_t rmin1, Double_t rmax1,
00926                              Double_t rmin2, Double_t rmax2)
00927 {
00928 // Set cone dimensions.
00929    if (rmin1>=0) {
00930       if (rmax1>0) {
00931          if (rmin1<=rmax1) {
00932          // normal rmin/rmax
00933             fRmin1 = rmin1;
00934             fRmax1 = rmax1;
00935          } else {
00936             fRmin1 = rmax1;
00937             fRmax1 = rmin1;
00938             Warning("SetConeDimensions", "rmin1>rmax1 Switch rmin1<->rmax1");
00939             SetShapeBit(TGeoShape::kGeoBad);
00940          }
00941       } else {
00942          // run-time
00943          fRmin1 = rmin1;
00944          fRmax1 = rmax1;
00945       }
00946    } else {
00947       // run-time
00948       fRmin1 = rmin1;
00949       fRmax1 = rmax1;
00950    }
00951    if (rmin2>=0) {
00952       if (rmax2>0) {
00953          if (rmin2<=rmax2) {
00954          // normal rmin/rmax
00955             fRmin2 = rmin2;
00956             fRmax2 = rmax2;
00957          } else {
00958             fRmin2 = rmax2;
00959             fRmax2 = rmin2;
00960             Warning("SetConeDimensions", "rmin2>rmax2 Switch rmin2<->rmax2");
00961             SetShapeBit(TGeoShape::kGeoBad);
00962          }
00963       } else {
00964          // run-time
00965          fRmin2 = rmin2;
00966          fRmax2 = rmax2;
00967       }
00968    } else {
00969       // run-time
00970       fRmin2 = rmin2;
00971       fRmax2 = rmax2;
00972    }
00973 
00974    fDz   = dz;
00975 }
00976 
00977 //_____________________________________________________________________________
00978 void TGeoCone::SetDimensions(Double_t *param)
00979 {
00980 // Set cone dimensions from an array.
00981    Double_t dz    = param[0];
00982    Double_t rmin1 = param[1];
00983    Double_t rmax1 = param[2];
00984    Double_t rmin2 = param[3];
00985    Double_t rmax2 = param[4];
00986    SetConeDimensions(dz, rmin1, rmax1, rmin2, rmax2);
00987 }
00988 
00989 //_____________________________________________________________________________
00990 void TGeoCone::SetPoints(Double_t *points) const
00991 {
00992 // Create cone mesh points.
00993    Double_t dz, phi, dphi;
00994    Int_t j, n;
00995 
00996    n = gGeoManager->GetNsegments();
00997    dphi = 360./n;
00998    dz    = fDz;
00999    Int_t indx = 0;
01000 
01001    if (points) {
01002       for (j = 0; j < n; j++) {
01003          phi = j*dphi*TMath::DegToRad();
01004          points[indx++] = fRmin1 * TMath::Cos(phi);
01005          points[indx++] = fRmin1 * TMath::Sin(phi);
01006          points[indx++] = -dz;
01007       }
01008       
01009       for (j = 0; j < n; j++) {
01010          phi = j*dphi*TMath::DegToRad();
01011          points[indx++] = fRmax1 * TMath::Cos(phi);
01012          points[indx++] = fRmax1 * TMath::Sin(phi);
01013          points[indx++] = -dz;
01014       }
01015 
01016       for (j = 0; j < n; j++) {
01017          phi = j*dphi*TMath::DegToRad();
01018          points[indx++] = fRmin2 * TMath::Cos(phi);
01019          points[indx++] = fRmin2 * TMath::Sin(phi);
01020          points[indx++] = dz;
01021       }
01022 
01023       for (j = 0; j < n; j++) {
01024          phi = j*dphi*TMath::DegToRad();
01025          points[indx++] = fRmax2 * TMath::Cos(phi);
01026          points[indx++] = fRmax2 * TMath::Sin(phi);
01027          points[indx++] = dz;
01028       }
01029    }
01030 }
01031 
01032 //_____________________________________________________________________________
01033 void TGeoCone::SetPoints(Float_t *points) const
01034 {
01035 // Create cone mesh points.
01036    Double_t dz, phi, dphi;
01037    Int_t j, n;
01038 
01039    n = gGeoManager->GetNsegments();
01040    dphi = 360./n;
01041    dz    = fDz;
01042    Int_t indx = 0;
01043 
01044    if (points) {
01045       for (j = 0; j < n; j++) {
01046          phi = j*dphi*TMath::DegToRad();
01047          points[indx++] = fRmin1 * TMath::Cos(phi);
01048          points[indx++] = fRmin1 * TMath::Sin(phi);
01049          points[indx++] = -dz;
01050       }
01051       
01052       for (j = 0; j < n; j++) {
01053          phi = j*dphi*TMath::DegToRad();
01054          points[indx++] = fRmax1 * TMath::Cos(phi);
01055          points[indx++] = fRmax1 * TMath::Sin(phi);
01056          points[indx++] = -dz;
01057       }
01058 
01059       for (j = 0; j < n; j++) {
01060          phi = j*dphi*TMath::DegToRad();
01061          points[indx++] = fRmin2 * TMath::Cos(phi);
01062          points[indx++] = fRmin2 * TMath::Sin(phi);
01063          points[indx++] = dz;
01064       }
01065 
01066       for (j = 0; j < n; j++) {
01067          phi = j*dphi*TMath::DegToRad();
01068          points[indx++] = fRmax2 * TMath::Cos(phi);
01069          points[indx++] = fRmax2 * TMath::Sin(phi);
01070          points[indx++] = dz;
01071       }
01072    }
01073 }
01074 
01075 //_____________________________________________________________________________
01076 void TGeoCone::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
01077 {
01078 // Returns numbers of vertices, segments and polygons composing the shape mesh.
01079    Int_t n = gGeoManager->GetNsegments();
01080    nvert = n*4;
01081    nsegs = n*8;
01082    npols = n*4;
01083 }
01084 
01085 //_____________________________________________________________________________
01086 Int_t TGeoCone::GetNmeshVertices() const
01087 {
01088 // Return number of vertices of the mesh representation
01089    Int_t n = gGeoManager->GetNsegments();
01090    Int_t numPoints = n*4;
01091    return numPoints;
01092 }
01093 
01094 //_____________________________________________________________________________
01095 void TGeoCone::Sizeof3D() const
01096 {
01097 ///// fill size of this 3-D object
01098 ///    TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
01099 ///    if (!painter) return;
01100 ///    Int_t n = gGeoManager->GetNsegments();
01101 ///    Int_t numPoints = n*4;
01102 ///    Int_t numSegs   = n*8;
01103 ///    Int_t numPolys  = n*4;
01104 ///    painter->AddSize3D(numPoints, numSegs, numPolys);
01105 }
01106 
01107 //_____________________________________________________________________________
01108 const TBuffer3D & TGeoCone::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
01109 {
01110 // Fills a static 3D buffer and returns a reference.
01111    static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
01112 
01113    TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
01114 
01115    if (reqSections & TBuffer3D::kRawSizes) {
01116       Int_t n = gGeoManager->GetNsegments();
01117       Int_t nbPnts = 4*n;
01118       Int_t nbSegs = 8*n;
01119       Int_t nbPols = 4*n;
01120       if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
01121          buffer.SetSectionsValid(TBuffer3D::kRawSizes);
01122       }
01123    }
01124 
01125    // TODO: Can we push this as common down to TGeoShape?
01126    if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
01127       SetPoints(buffer.fPnts);
01128       if (!buffer.fLocalFrame) {
01129          TransformPoints(buffer.fPnts, buffer.NbPnts());
01130       }
01131 
01132       SetSegsAndPols(buffer);
01133       buffer.SetSectionsValid(TBuffer3D::kRaw);
01134    }
01135       
01136    return buffer;
01137 }
01138 
01139 ClassImp(TGeoConeSeg)
01140 
01141 //_____________________________________________________________________________
01142 TGeoConeSeg::TGeoConeSeg()
01143 {
01144 // Default constructor
01145    SetShapeBit(TGeoShape::kGeoConeSeg);
01146    fPhi1 = fPhi2 = 0.0;
01147 }
01148 
01149 //_____________________________________________________________________________
01150 TGeoConeSeg::TGeoConeSeg(Double_t dz, Double_t rmin1, Double_t rmax1,
01151                           Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2)
01152             :TGeoCone(dz, rmin1, rmax1, rmin2, rmax2)
01153 {
01154 // Default constructor specifying minimum and maximum radius
01155    SetShapeBit(TGeoShape::kGeoConeSeg);
01156    SetConsDimensions(dz, rmin1, rmax1, rmin2, rmax2, phi1, phi2);
01157    ComputeBBox();
01158 }
01159 
01160 //_____________________________________________________________________________
01161 TGeoConeSeg::TGeoConeSeg(const char *name, Double_t dz, Double_t rmin1, Double_t rmax1,
01162                           Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2)
01163             :TGeoCone(name, dz, rmin1, rmax1, rmin2, rmax2)
01164 {
01165 // Default constructor specifying minimum and maximum radius
01166    SetShapeBit(TGeoShape::kGeoConeSeg);
01167    SetConsDimensions(dz, rmin1, rmax1, rmin2, rmax2, phi1, phi2);
01168    ComputeBBox();
01169 }
01170 
01171 //_____________________________________________________________________________
01172 TGeoConeSeg::TGeoConeSeg(Double_t *param)
01173             :TGeoCone(0,0,0,0,0)
01174 {
01175 // Default constructor specifying minimum and maximum radius
01176 // param[0] = dz
01177 // param[1] = Rmin1
01178 // param[2] = Rmax1
01179 // param[3] = Rmin2
01180 // param[4] = Rmax2
01181 // param[5] = phi1
01182 // param[6] = phi2
01183    SetShapeBit(TGeoShape::kGeoConeSeg);
01184    SetDimensions(param);
01185    ComputeBBox();
01186 }
01187 
01188 //_____________________________________________________________________________
01189 TGeoConeSeg::~TGeoConeSeg()
01190 {
01191 // destructor
01192 }
01193 
01194 //_____________________________________________________________________________
01195 Double_t TGeoConeSeg::Capacity() const
01196 {
01197 // Computes capacity of the shape in [length^3]
01198    return TGeoConeSeg::Capacity(fDz, fRmin1, fRmax1, fRmin2, fRmax2, fPhi1, fPhi2);
01199 }   
01200 
01201 //_____________________________________________________________________________
01202 Double_t TGeoConeSeg::Capacity(Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2)
01203 {
01204 // Computes capacity of the shape in [length^3]
01205    Double_t capacity = (TMath::Abs(phi2-phi1)*TMath::DegToRad()*dz/3.)*
01206                        (rmax1*rmax1+rmax2*rmax2+rmax1*rmax2-
01207                         rmin1*rmin1-rmin2*rmin2-rmin1*rmin2);
01208    return capacity;                                            
01209 }   
01210 
01211 //_____________________________________________________________________________
01212 void TGeoConeSeg::ComputeBBox()
01213 {
01214 // compute bounding box of the tube segment
01215    Double_t rmin, rmax;
01216    rmin = TMath::Min(fRmin1, fRmin2);
01217    rmax = TMath::Max(fRmax1, fRmax2);
01218 
01219    Double_t xc[4];
01220    Double_t yc[4];
01221    xc[0] = rmax*TMath::Cos(fPhi1*TMath::DegToRad());
01222    yc[0] = rmax*TMath::Sin(fPhi1*TMath::DegToRad());
01223    xc[1] = rmax*TMath::Cos(fPhi2*TMath::DegToRad());
01224    yc[1] = rmax*TMath::Sin(fPhi2*TMath::DegToRad());
01225    xc[2] = rmin*TMath::Cos(fPhi1*TMath::DegToRad());
01226    yc[2] = rmin*TMath::Sin(fPhi1*TMath::DegToRad());
01227    xc[3] = rmin*TMath::Cos(fPhi2*TMath::DegToRad());
01228    yc[3] = rmin*TMath::Sin(fPhi2*TMath::DegToRad());
01229 
01230    Double_t xmin = xc[TMath::LocMin(4, &xc[0])];
01231    Double_t xmax = xc[TMath::LocMax(4, &xc[0])];
01232    Double_t ymin = yc[TMath::LocMin(4, &yc[0])];
01233    Double_t ymax = yc[TMath::LocMax(4, &yc[0])];
01234 
01235    Double_t dp = fPhi2-fPhi1;
01236    Double_t ddp = -fPhi1;
01237    if (ddp<0) ddp+= 360;
01238    if (ddp<=dp) xmax = rmax;
01239    ddp = 90-fPhi1;
01240    if (ddp<0) ddp+= 360;
01241    if (ddp<=dp) ymax = rmax;
01242    ddp = 180-fPhi1;
01243    if (ddp<0) ddp+= 360;
01244    if (ddp<=dp) xmin = -rmax;
01245    ddp = 270-fPhi1;
01246    if (ddp<0) ddp+= 360;
01247    if (ddp<=dp) ymin = -rmax;
01248    fOrigin[0] = (xmax+xmin)/2;
01249    fOrigin[1] = (ymax+ymin)/2;
01250    fOrigin[2] = 0;
01251    fDX = (xmax-xmin)/2;
01252    fDY = (ymax-ymin)/2;
01253    fDZ = fDz;
01254 }
01255 
01256 //_____________________________________________________________________________
01257 void TGeoConeSeg::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
01258 {
01259 // Compute normal to closest surface from POINT.
01260    Double_t saf[3];
01261    Double_t ro1 = 0.5*(fRmin1+fRmin2);
01262    Double_t tg1 = 0.5*(fRmin2-fRmin1)/fDz;
01263    Double_t cr1 = 1./TMath::Sqrt(1.+tg1*tg1);
01264    Double_t ro2 = 0.5*(fRmax1+fRmax2);
01265    Double_t tg2 = 0.5*(fRmax2-fRmax1)/fDz;
01266    Double_t cr2 = 1./TMath::Sqrt(1.+tg2*tg2);
01267 
01268    Double_t c1 = TMath::Cos(fPhi1*TMath::DegToRad());
01269    Double_t s1 = TMath::Sin(fPhi1*TMath::DegToRad());
01270    Double_t c2 = TMath::Cos(fPhi2*TMath::DegToRad());
01271    Double_t s2 = TMath::Sin(fPhi2*TMath::DegToRad());
01272 
01273    Double_t r=TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
01274    Double_t rin = tg1*point[2]+ro1;
01275    Double_t rout = tg2*point[2]+ro2;
01276    saf[0] = TMath::Abs(fDz-TMath::Abs(point[2]));
01277    saf[1] = (ro1>0)?(TMath::Abs((r-rin)*cr1)):TGeoShape::Big();
01278    saf[2] = TMath::Abs((rout-r)*cr2);
01279    Int_t i = TMath::LocMin(3,saf);
01280    if (((fPhi2-fPhi1)<360.) && TGeoShape::IsCloseToPhi(saf[i], point,c1,s1,c2,s2)) {
01281       TGeoShape::NormalPhi(point,dir,norm,c1,s1,c2,s2);
01282       return;
01283    }
01284    if (i==0) {
01285       norm[0] = norm[1] = 0.;
01286       norm[2] = TMath::Sign(1.,dir[2]);
01287       return;
01288    }
01289 
01290    Double_t phi = TMath::ATan2(point[1],point[0]);
01291    Double_t cphi = TMath::Cos(phi);
01292    Double_t sphi = TMath::Sin(phi);
01293 
01294    if (i==1) {
01295       norm[0] = cr1*cphi;
01296       norm[1] = cr1*sphi;
01297       norm[2] = -tg1*cr1;
01298    } else {
01299       norm[0] = cr2*cphi;
01300       norm[1] = cr2*sphi;
01301       norm[2] = -tg2*cr2;
01302    }
01303 
01304    if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
01305       norm[0] = -norm[0];
01306       norm[1] = -norm[1];
01307       norm[2] = -norm[2];
01308    }
01309 }
01310 
01311 //_____________________________________________________________________________
01312 void TGeoConeSeg::ComputeNormalS(Double_t *point, Double_t *dir, Double_t *norm,
01313                                  Double_t dz, Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2,
01314                                  Double_t c1, Double_t s1, Double_t c2, Double_t s2)
01315 {
01316 // Compute normal to closest surface from POINT.
01317    Double_t saf[2];
01318    Double_t ro1 = 0.5*(rmin1+rmin2);
01319    Double_t tg1 = 0.5*(rmin2-rmin1)/dz;
01320    Double_t cr1 = 1./TMath::Sqrt(1.+tg1*tg1);
01321    Double_t ro2 = 0.5*(rmax1+rmax2);
01322    Double_t tg2 = 0.5*(rmax2-rmax1)/dz;
01323    Double_t cr2 = 1./TMath::Sqrt(1.+tg2*tg2);
01324 
01325    Double_t r=TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
01326    Double_t rin = tg1*point[2]+ro1;
01327    Double_t rout = tg2*point[2]+ro2;
01328    saf[0] = (ro1>0)?(TMath::Abs((r-rin)*cr1)):TGeoShape::Big();
01329    saf[1] = TMath::Abs((rout-r)*cr2);
01330    Int_t i = TMath::LocMin(2,saf);
01331    if (TGeoShape::IsCloseToPhi(saf[i], point,c1,s1,c2,s2)) {
01332       TGeoShape::NormalPhi(point,dir,norm,c1,s1,c2,s2);
01333       return;
01334    }
01335 
01336    Double_t phi = TMath::ATan2(point[1],point[0]);
01337    Double_t cphi = TMath::Cos(phi);
01338    Double_t sphi = TMath::Sin(phi);
01339 
01340    if (i==0) {
01341       norm[0] = cr1*cphi;
01342       norm[1] = cr1*sphi;
01343       norm[2] = -tg1*cr1;
01344    } else {
01345       norm[0] = cr2*cphi;
01346       norm[1] = cr2*sphi;
01347       norm[2] = -tg2*cr2;
01348    }
01349 
01350    if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
01351       norm[0] = -norm[0];
01352       norm[1] = -norm[1];
01353       norm[2] = -norm[2];
01354    }
01355 }
01356 
01357 //_____________________________________________________________________________
01358 Bool_t TGeoConeSeg::Contains(Double_t *point) const
01359 {
01360 // test if point is inside this sphere
01361    if (!TGeoCone::Contains(point)) return kFALSE;
01362    Double_t dphi = fPhi2 - fPhi1;
01363    if (dphi >= 360.) return kTRUE;
01364    Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
01365    if (phi < 0 ) phi+=360.;
01366    Double_t ddp = phi-fPhi1;
01367    if (ddp < 0) ddp+=360.;
01368 //   if (ddp > 360) ddp-=360;
01369    if (ddp > dphi) return kFALSE;
01370    return kTRUE;
01371 }
01372 
01373 //_____________________________________________________________________________
01374 Double_t TGeoConeSeg::DistToCons(Double_t *point, Double_t *dir, Double_t r1, Double_t z1, Double_t r2, Double_t z2, Double_t phi1, Double_t phi2)
01375 {
01376    // Static method to compute distance to a conical surface with :
01377    // - r1, z1 - radius and Z position of lower base
01378    // - r2, z2 - radius and Z position of upper base
01379    // - phi1, phi2 - phi limits
01380    Double_t dz = z2-z1;
01381    if (dz<=0) {
01382       return TGeoShape::Big();
01383    }
01384 
01385    Double_t dphi = phi2 - phi1;
01386    Bool_t hasphi = kTRUE;
01387    if (dphi >= 360.) hasphi=kFALSE;
01388    if (dphi < 0) dphi+=360.;
01389 //   printf("phi1=%f phi2=%f dphi=%f\n", phi1, phi2, dphi);
01390 
01391    Double_t ro0 = 0.5*(r1+r2);
01392    Double_t fz  = (r2-r1)/dz;
01393    Double_t r0sq = point[0]*point[0] + point[1]*point[1];
01394    Double_t rc = ro0 + fz*(point[2]-0.5*(z1+z2));
01395 
01396    Double_t a = dir[0]*dir[0] + dir[1]*dir[1] - fz*fz*dir[2]*dir[2];
01397    Double_t b = point[0]*dir[0] + point[1]*dir[1] - fz*rc*dir[2];
01398    Double_t c = r0sq - rc*rc;
01399 
01400    if (a==0) return TGeoShape::Big();
01401    a = 1./a;
01402    b *= a;
01403    c *= a;
01404    Double_t delta = b*b - c;
01405    if (delta<0) return TGeoShape::Big();
01406    delta = TMath::Sqrt(delta);
01407 
01408    Double_t snxt = -b-delta;
01409    Double_t ptnew[3];
01410    Double_t ddp, phi;
01411    if (snxt>0) {
01412       // check Z range
01413       ptnew[2] = point[2] + snxt*dir[2];
01414       if (((ptnew[2]-z1)*(ptnew[2]-z2)) < 0) {
01415       // check phi range
01416          if (!hasphi) return snxt;
01417          ptnew[0] = point[0] + snxt*dir[0];
01418          ptnew[1] = point[1] + snxt*dir[1];
01419          phi = TMath::ATan2(ptnew[1], ptnew[0]) * TMath::RadToDeg();
01420          if (phi < 0 ) phi+=360.;
01421          ddp = phi-phi1;
01422          if (ddp < 0) ddp+=360.;
01423 //       printf("snxt1=%f phi=%f ddp=%f\n", snxt, phi, ddp);
01424          if (ddp<=dphi) return snxt;
01425       }
01426    }
01427    snxt = -b+delta;
01428    if (snxt>0) {
01429       // check Z range
01430       ptnew[2] = point[2] + snxt*dir[2];
01431       if (((ptnew[2]-z1)*(ptnew[2]-z2)) < 0) {
01432       // check phi range
01433          if (!hasphi) return snxt;
01434          ptnew[0] = point[0] + snxt*dir[0];
01435          ptnew[1] = point[1] + snxt*dir[1];
01436          phi = TMath::ATan2(ptnew[1], ptnew[0]) * TMath::RadToDeg();
01437          if (phi < 0 ) phi+=360.;
01438          ddp = phi-phi1;
01439          if (ddp < 0) ddp+=360.;
01440 //       printf("snxt2=%f phi=%f ddp=%f\n", snxt, phi, ddp);
01441          if (ddp<=dphi) return snxt;
01442       }
01443    }
01444    return TGeoShape::Big();
01445 }
01446 
01447 //_____________________________________________________________________________
01448 Double_t TGeoConeSeg::DistFromInsideS(Double_t *point, Double_t *dir, Double_t dz, 
01449                        Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, 
01450                        Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi)
01451 {
01452 // compute distance from inside point to surface of the tube segment
01453    if (dz<=0) return TGeoShape::Big();
01454    // Do Z
01455    Double_t scone = TGeoCone::DistFromInsideS(point,dir,dz,rmin1,rmax1,rmin2,rmax2);
01456    if (scone<=0) return 0.0;
01457    Double_t sfmin = TGeoShape::Big();
01458    Double_t rsq = point[0]*point[0]+point[1]*point[1];
01459    Double_t r = TMath::Sqrt(rsq);
01460    Double_t cpsi=point[0]*cm+point[1]*sm;
01461    if (cpsi>r*cdfi+TGeoShape::Tolerance())  {
01462       sfmin = TGeoShape::DistToPhiMin(point, dir, s1, c1, s2, c2, sm, cm);
01463       return TMath::Min(scone,sfmin);
01464    }
01465    // Point on the phi boundary or outside   
01466    // which one: phi1 or phi2
01467    Double_t ddotn, xi, yi;
01468    if (TMath::Abs(point[1]-s1*r) < TMath::Abs(point[1]-s2*r)) {
01469       ddotn = s1*dir[0]-c1*dir[1];
01470       if (ddotn>=0) return 0.0;
01471       ddotn = -s2*dir[0]+c2*dir[1];
01472       if (ddotn<=0) return scone;
01473       sfmin = s2*point[0]-c2*point[1];
01474       if (sfmin<=0) return scone;
01475       sfmin /= ddotn;
01476       if (sfmin >= scone) return scone;
01477       xi = point[0]+sfmin*dir[0];
01478       yi = point[1]+sfmin*dir[1];
01479       if (yi*cm-xi*sm<0) return scone;
01480       return sfmin;
01481    }
01482    ddotn = -s2*dir[0]+c2*dir[1];
01483    if (ddotn>=0) return 0.0;
01484    ddotn = s1*dir[0]-c1*dir[1];
01485    if (ddotn<=0) return scone;
01486    sfmin = -s1*point[0]+c1*point[1];
01487    if (sfmin<=0) return scone;
01488    sfmin /= ddotn;
01489    if (sfmin >= scone) return scone;
01490    xi = point[0]+sfmin*dir[0];
01491    yi = point[1]+sfmin*dir[1];
01492    if (yi*cm-xi*sm>0) return scone;
01493    return sfmin;
01494 }
01495 
01496 //_____________________________________________________________________________
01497 Double_t TGeoConeSeg::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
01498 {
01499 // compute distance from inside point to surface of the tube segment
01500    if (iact<3 && safe) {
01501       *safe = TGeoConeSeg::SafetyS(point, kTRUE, fDz,fRmin1,fRmax1,fRmin2,fRmax2,fPhi1,fPhi2);
01502       if (iact==0) return TGeoShape::Big();
01503       if ((iact==1) && (*safe>step)) return TGeoShape::Big();
01504    }
01505    if ((fPhi2-fPhi1)>=360.) return TGeoCone::DistFromInsideS(point,dir,fDz,fRmin1,fRmax1,fRmin2,fRmax2);
01506    Double_t phi1 = fPhi1*TMath::DegToRad();
01507    Double_t phi2 = fPhi2*TMath::DegToRad();
01508    Double_t c1 = TMath::Cos(phi1);
01509    Double_t c2 = TMath::Cos(phi2);
01510    Double_t s1 = TMath::Sin(phi1);
01511    Double_t s2 = TMath::Sin(phi2);
01512    Double_t phim = 0.5*(phi1+phi2);
01513    Double_t cm = TMath::Cos(phim);
01514    Double_t sm = TMath::Sin(phim);
01515    Double_t dfi = 0.5*(phi2-phi1);
01516    Double_t cdfi = TMath::Cos(dfi);
01517 
01518    // compute distance to surface
01519    return TGeoConeSeg::DistFromInsideS(point,dir,fDz,fRmin1,fRmax1,fRmin2,fRmax2,c1,s1,c2,s2,cm,sm,cdfi);
01520 }
01521 
01522 //_____________________________________________________________________________
01523 Double_t TGeoConeSeg::DistFromOutsideS(Double_t *point, Double_t *dir, Double_t dz, 
01524                        Double_t rmin1, Double_t rmax1, Double_t rmin2, Double_t rmax2, 
01525                        Double_t c1, Double_t s1, Double_t c2, Double_t s2, Double_t cm, Double_t sm, Double_t cdfi)
01526 {
01527 // compute distance from outside point to surface of arbitrary tube
01528    if (dz<=0) return TGeoShape::Big();
01529    Double_t r2, cpsi;
01530    // check Z planes
01531    Double_t xi, yi, zi;
01532    Double_t b,delta;
01533    zi = dz - TMath::Abs(point[2]);
01534    Double_t rin,rout;
01535    Double_t s = TGeoShape::Big();
01536    Double_t snxt=TGeoShape::Big();
01537    Bool_t in = kFALSE;
01538    Bool_t inz = (zi<0)?kFALSE:kTRUE;
01539    if (!inz) {
01540       if (point[2]*dir[2]>=0) return TGeoShape::Big();
01541       s = -zi/TMath::Abs(dir[2]);
01542       xi = point[0]+s*dir[0];
01543       yi = point[1]+s*dir[1];
01544       r2=xi*xi+yi*yi;
01545       if (dir[2]>0) {
01546          rin = rmin1;
01547          rout = rmax1;
01548       } else {
01549          rin = rmin2;
01550          rout = rmax2;
01551       }      
01552       if ((rin*rin<=r2) && (r2<=rout*rout)) {
01553          cpsi=xi*cm+yi*sm;
01554          if (cpsi>=(cdfi*TMath::Sqrt(r2))) return s;
01555       }
01556    }
01557    Double_t zinv = 1./dz;
01558    Double_t rsq = point[0]*point[0]+point[1]*point[1];   
01559    Double_t r = TMath::Sqrt(rsq);
01560    Double_t ro1=0.5*(rmin1+rmin2);
01561    Bool_t hasrmin = (ro1>0)?kTRUE:kFALSE;
01562    Double_t tg1 = 0.0;
01563    Bool_t inrmin = kFALSE;
01564    rin = 0.0;
01565    if (hasrmin) {
01566       tg1=0.5*(rmin2-rmin1)*zinv;
01567       rin = ro1+tg1*point[2];
01568       if (rsq > rin*(rin-TGeoShape::Tolerance())) inrmin=kTRUE;
01569    } else {
01570       inrmin = kTRUE;
01571    }     
01572    Double_t ro2=0.5*(rmax1+rmax2);
01573    Double_t tg2=0.5*(rmax2-rmax1)*zinv;
01574    rout = ro2+tg2*point[2];
01575    Bool_t inrmax = kFALSE;
01576    if (rsq < rout*(rout+TGeoShape::Tolerance())) inrmax = kTRUE;
01577    Bool_t inphi = kFALSE;
01578    cpsi=point[0]*cm+point[1]*sm;
01579    if (cpsi>r*cdfi-TGeoShape::Tolerance())  inphi = kTRUE;
01580    in = inz & inrmin & inrmax & inphi;
01581    // If inside, we are most likely on a boundary within machine precision.
01582    if (in) { 
01583       Double_t safphi = (cpsi-r*cdfi)*TMath::Sqrt(1.-cdfi*cdfi);
01584       Double_t safrmin = (hasrmin)?TMath::Abs(r-rin):(TGeoShape::Big());
01585       Double_t safrmax = TMath::Abs(r-rout);
01586       // check if on Z boundaries
01587       if (zi<safrmax && zi<safrmin && zi<safphi) {
01588          if (point[2]*dir[2]<0) return 0.0;
01589          return TGeoShape::Big();
01590       }   
01591       // check if on Rmax boundary
01592       if (safrmax<safrmin && safrmax<safphi) {
01593          Double_t ddotn = point[0]*dir[0]+point[1]*dir[1]-tg2*dir[2]*r;      
01594          if (ddotn<=0) return 0.0;
01595          return TGeoShape::Big();
01596       }
01597       // check if on phi boundary
01598       if (safphi<safrmin) {
01599       // We may cross again a phi of rmin boundary
01600       // check first if we are on phi1 or phi2
01601          Double_t un;
01602          if (TMath::Abs(point[1]-s1*r) < TMath::Abs(point[1]-s2*r)) {
01603             un = dir[0]*s1-dir[1]*c1;
01604             if (un < 0) return 0.0;
01605             if (cdfi>=0) return TGeoShape::Big();
01606             un = -dir[0]*s2+dir[1]*c2;
01607             if (un<0) {
01608                s = -point[0]*s2+point[1]*c2;
01609                if (s>0) {
01610                   s /= (-un);
01611                   zi = point[2]+s*dir[2];
01612                   if (TMath::Abs(zi)<=dz) {
01613                      xi = point[0]+s*dir[0];
01614                      yi = point[1]+s*dir[1];
01615                      if ((yi*cm-xi*sm)>0) {
01616                         r2=xi*xi+yi*yi;
01617                         rin = ro1+tg1*zi;
01618                         rout = ro2+tg2*zi;
01619                         if ((rin*rin<=r2) && (rout*rout>=r2)) return s;
01620                      }
01621                   }
01622                }
01623             }   
01624          } else {
01625             un = -dir[0]*s2+dir[1]*c2;
01626             if (un < 0) return 0.0;
01627             if (cdfi>=0) return TGeoShape::Big();
01628             un = dir[0]*s1-dir[1]*c1;
01629             if (un<0) {
01630                s = point[0]*s1-point[1]*c1;
01631                if (s>0) {
01632                   s /= (-un);
01633                   zi = point[2]+s*dir[2];
01634                   if (TMath::Abs(zi)<=dz) {
01635                      xi = point[0]+s*dir[0];
01636                      yi = point[1]+s*dir[1];
01637                      if ((yi*cm-xi*sm)<0) {
01638                         r2=xi*xi+yi*yi;
01639                         rin = ro1+tg1*zi;
01640                         rout = ro2+tg2*zi;
01641                         if ((rin*rin<=r2) && (rout*rout>=r2)) return s;
01642                      }
01643                   }
01644                }
01645             }
01646          }      
01647          // We may also cross rmin, second solution coming from outside
01648          Double_t ddotn = point[0]*dir[0]+point[1]*dir[1]-tg1*dir[2]*r;
01649          if (ddotn>=0) return TGeoShape::Big();
01650          if (cdfi>=0) return TGeoShape::Big();              
01651          TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta); 
01652          if (delta<0) return TGeoShape::Big();
01653          snxt = -b-delta;
01654          if (snxt<0) return TGeoShape::Big();
01655          snxt = -b+delta;
01656          zi = point[2]+snxt*dir[2];           
01657          if (TMath::Abs(zi)>dz) return TGeoShape::Big();
01658          xi = point[0]+snxt*dir[0];
01659          yi = point[1]+snxt*dir[1];
01660          r2=xi*xi+yi*yi;
01661          cpsi=xi*cm+yi*sm;
01662          if (cpsi>=(cdfi*TMath::Sqrt(r2))) return snxt;
01663          return TGeoShape::Big();
01664       }
01665       // We are on rmin boundary: we may cross again rmin or a phi facette   
01666       Double_t ddotn = point[0]*dir[0]+point[1]*dir[1]-tg1*dir[2]*r;
01667       if (ddotn>=0) return 0.0;
01668       TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta);
01669       if (delta<0) return 0.0;
01670       snxt = -b+delta;
01671       if (snxt<0) return TGeoShape::Big();
01672       if (TMath::Abs(-b-delta)>snxt) return TGeoShape::Big();
01673       zi = point[2]+snxt*dir[2];
01674       if (TMath::Abs(zi)>dz) return TGeoShape::Big();
01675       // OK, we cross rmin at snxt - check if within phi range
01676       xi = point[0]+snxt*dir[0];
01677       yi = point[1]+snxt*dir[1];
01678       r2=xi*xi+yi*yi;
01679       cpsi=xi*cm+yi*sm;
01680       if (cpsi>=(cdfi*TMath::Sqrt(r2))) return snxt;
01681       // we cross rmin in the phi gap - we may cross a phi facette
01682       if (cdfi>=0) return TGeoShape::Big();
01683       Double_t un=-dir[0]*s1+dir[1]*c1;
01684       if (un > 0) {
01685          s=point[0]*s1-point[1]*c1;
01686          if (s>=0) {
01687             s /= un;
01688             zi=point[2]+s*dir[2];
01689             if (TMath::Abs(zi)<=dz) {
01690                xi=point[0]+s*dir[0];
01691                yi=point[1]+s*dir[1];
01692                if ((yi*cm-xi*sm)<=0) {
01693                   r2=xi*xi+yi*yi;
01694                   rin = ro1+tg1*zi;
01695                   rout = ro2+tg2*zi;
01696                   if ((rin*rin<=r2) && (rout*rout>=r2)) return s;
01697                }   
01698             }
01699          }
01700       }         
01701       un=dir[0]*s2-dir[1]*c2;
01702       if (un > 0) {
01703          s=(point[1]*c2-point[0]*s2)/un;
01704          if (s>=0) {
01705             zi=point[2]+s*dir[2];
01706             if (TMath::Abs(zi)<=dz) {
01707                xi=point[0]+s*dir[0];
01708                yi=point[1]+s*dir[1];
01709                if ((yi*cm-xi*sm)>=0) {
01710                   r2=xi*xi+yi*yi;
01711                   rin = ro1+tg1*zi;
01712                   rout = ro2+tg2*zi;
01713                   if ((rin*rin<=r2) && (rout*rout>=r2)) return s;
01714                }
01715             }
01716          }
01717       }            
01718       return TGeoShape::Big();
01719    }   
01720 
01721    // The point is really outside
01722    Double_t sr1 = TGeoShape::Big();
01723    if (!inrmax) {
01724       // check crossing with outer cone
01725       TGeoCone::DistToCone(point, dir, dz, rmax1, rmax2, b, delta);
01726       if (delta>=0) {
01727          s = -b-delta;
01728          if (s>0) {
01729             zi=point[2]+s*dir[2];
01730             if (TMath::Abs(zi)<=dz) {
01731                xi=point[0]+s*dir[0];
01732                yi=point[1]+s*dir[1];
01733                r2=xi*xi+yi*yi;
01734                cpsi=xi*cm+yi*sm;
01735                if (cpsi>=(cdfi*TMath::Sqrt(r2))) return s; // rmax crossing
01736             }
01737          }
01738          s = -b+delta;
01739          if (s>0) {
01740             zi=point[2]+s*dir[2];
01741             if (TMath::Abs(zi)<=dz) {
01742                xi=point[0]+s*dir[0];
01743                yi=point[1]+s*dir[1];
01744                r2=xi*xi+yi*yi;
01745                cpsi=xi*cm+yi*sm;
01746                if (cpsi>=(cdfi*TMath::Sqrt(r2))) sr1=s;
01747             }
01748          }
01749       }
01750    }
01751    // check crossing with inner cone
01752    Double_t sr2 = TGeoShape::Big();
01753    TGeoCone::DistToCone(point, dir, dz, rmin1, rmin2, b, delta);      
01754    if (delta>=0) {      
01755       s = -b-delta;
01756       if (s>0) {
01757          zi=point[2]+s*dir[2];
01758          if (TMath::Abs(zi)<=dz) {
01759             xi=point[0]+s*dir[0];
01760             yi=point[1]+s*dir[1];
01761             r2=xi*xi+yi*yi;
01762             cpsi=xi*cm+yi*sm;
01763             if (cpsi>=(cdfi*TMath::Sqrt(r2))) sr2=s;
01764          }
01765       }
01766       if (sr2>1E10) {
01767          s = -b+delta;
01768          if (s>0) {
01769          zi=point[2]+s*dir[2];
01770             if (TMath::Abs(zi)<=dz) {
01771                xi=point[0]+s*dir[0];
01772                yi=point[1]+s*dir[1];
01773                r2=xi*xi+yi*yi;
01774                cpsi=xi*cm+yi*sm;
01775                if (cpsi>=(cdfi*TMath::Sqrt(r2))) sr2=s;
01776             }
01777          }
01778       }
01779    }
01780    snxt = TMath::Min(sr1,sr2);   
01781    // Check phi crossing   
01782    s = TGeoShape::DistToPhiMin(point,dir,s1,c1,s2,c2,sm,cm,kFALSE);      
01783    if (s>snxt) return snxt;
01784    zi=point[2]+s*dir[2];
01785    if (TMath::Abs(zi)>dz) return snxt;
01786    xi=point[0]+s*dir[0];
01787    yi=point[1]+s*dir[1];
01788    r2=xi*xi+yi*yi;
01789    rout = ro2+tg2*zi;
01790    if (r2>rout*rout) return snxt;
01791    rin = ro1+tg1*zi;
01792    if (r2>=rin*rin) return s; // phi crossing
01793    return snxt;
01794 }
01795 
01796 //_____________________________________________________________________________
01797 Double_t TGeoConeSeg::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
01798 {
01799 // compute distance from outside point to surface of the tube
01800    // compute safe radius
01801    if (iact<3 && safe) {
01802       *safe = Safety(point, kFALSE);
01803       if (iact==0) return TGeoShape::Big();
01804       if ((iact==1) && (*safe>step)) return TGeoShape::Big();
01805    }
01806 // Check if the bounding box is crossed within the requested distance
01807    Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
01808    if (sdist>=step) return TGeoShape::Big();
01809    if ((fPhi2-fPhi1)>=360.) return TGeoCone::DistFromOutsideS(point,dir,fDz,fRmin1,fRmax1,fRmin2,fRmax2);
01810    Double_t phi1 = fPhi1*TMath::DegToRad();
01811    Double_t phi2 = fPhi2*TMath::DegToRad();
01812    Double_t c1 = TMath::Cos(phi1);
01813    Double_t c2 = TMath::Cos(phi2);
01814    Double_t s1 = TMath::Sin(phi1);
01815    Double_t s2 = TMath::Sin(phi2);
01816    Double_t phim = 0.5*(phi1+phi2);
01817    Double_t cm = TMath::Cos(phim);
01818    Double_t sm = TMath::Sin(phim);
01819    Double_t dfi = 0.5*(phi2-phi1);
01820    Double_t cdfi = TMath::Cos(dfi);
01821    return TGeoConeSeg::DistFromOutsideS(point,dir,fDz,fRmin1,fRmax1,fRmin2,fRmax2,c1,s1,c2,s2,cm,sm,cdfi);
01822 }
01823 
01824 //_____________________________________________________________________________
01825 Int_t TGeoConeSeg::DistancetoPrimitive(Int_t px, Int_t py)
01826 {
01827 // compute closest distance from point px,py to each corner
01828    Int_t n = gGeoManager->GetNsegments()+1;
01829    const Int_t numPoints = 4*n;
01830    return ShapeDistancetoPrimitive(numPoints, px, py);
01831 }
01832 
01833 //_____________________________________________________________________________
01834 TGeoVolume *TGeoConeSeg::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv,
01835                              Double_t start, Double_t step)
01836 {
01837 //--- Divide this cone segment shape belonging to volume "voldiv" into ndiv volumes
01838 // called divname, from start position with the given step. Returns pointer
01839 // to created division cell volume in case of Z divisions. For Z division
01840 // creates all volumes with different shapes and returns pointer to volume that
01841 // was divided. In case a wrong division axis is supplied, returns pointer to
01842 // volume that was divided.
01843    TGeoShape *shape;           //--- shape to be created
01844    TGeoVolume *vol;            //--- division volume to be created
01845    TGeoVolumeMulti *vmulti;    //--- generic divided volume
01846    TGeoPatternFinder *finder;  //--- finder to be attached
01847    TString opt = "";           //--- option to be attached
01848    Double_t dphi;
01849    Int_t id;
01850    Double_t end = start+ndiv*step;
01851    switch (iaxis) {
01852       case 1:  //---               R division
01853          Error("Divide","division of a cone segment on R not implemented");
01854          return 0;
01855       case 2:  //---               Phi division
01856          dphi = fPhi2-fPhi1;
01857          if (dphi<0) dphi+=360.;
01858          finder = new TGeoPatternCylPhi(voldiv, ndiv, start, end);
01859          voldiv->SetFinder(finder);
01860          finder->SetDivIndex(voldiv->GetNdaughters());
01861          shape = new TGeoConeSeg(fDz, fRmin1, fRmax1, fRmin2, fRmax2, -step/2, step/2);
01862          vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
01863          vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
01864          vmulti->AddVolume(vol);
01865          opt = "Phi";
01866          for (id=0; id<ndiv; id++) {
01867             voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
01868             ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
01869          }
01870          return vmulti;
01871       case 3: //---                 Z division
01872          finder = new TGeoPatternZ(voldiv, ndiv, start, end);
01873          vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
01874          voldiv->SetFinder(finder);
01875          finder->SetDivIndex(voldiv->GetNdaughters());
01876          for (id=0; id<ndiv; id++) {
01877             Double_t z1 = start+id*step;
01878             Double_t z2 = start+(id+1)*step;
01879             Double_t rmin1n = 0.5*(fRmin1*(fDz-z1)+fRmin2*(fDz+z1))/fDz;
01880             Double_t rmax1n = 0.5*(fRmax1*(fDz-z1)+fRmax2*(fDz+z1))/fDz;
01881             Double_t rmin2n = 0.5*(fRmin1*(fDz-z2)+fRmin2*(fDz+z2))/fDz;
01882             Double_t rmax2n = 0.5*(fRmax1*(fDz-z2)+fRmax2*(fDz+z2))/fDz;
01883             shape = new TGeoConeSeg(step/2, rmin1n, rmax1n, rmin2n, rmax2n, fPhi1, fPhi2);
01884             vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
01885             vmulti->AddVolume(vol);
01886             opt = "Z";
01887             voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
01888             ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
01889          }
01890          return vmulti;
01891       default:
01892          Error("Divide", "Wrong axis type for division");
01893          return 0;
01894    }
01895 }
01896 
01897 //_____________________________________________________________________________
01898 Double_t TGeoConeSeg::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
01899 {
01900 // Get range of shape for a given axis.
01901    xlo = 0;
01902    xhi = 0;
01903    Double_t dx = 0;
01904    switch (iaxis) {
01905       case 2:
01906          xlo = fPhi1;
01907          xhi = fPhi2;
01908          dx = xhi-xlo;
01909          return dx;
01910       case 3:
01911          xlo = -fDz;
01912          xhi = fDz;
01913          dx = xhi-xlo;
01914          return dx;
01915    }
01916    return dx;
01917 }
01918 
01919 //_____________________________________________________________________________
01920 void TGeoConeSeg::GetBoundingCylinder(Double_t *param) const
01921 {
01922 //--- Fill vector param[4] with the bounding cylinder parameters. The order
01923 // is the following : Rmin, Rmax, Phi1, Phi2
01924    param[0] = TMath::Min(fRmin1, fRmin2); // Rmin
01925    param[0] *= param[0];
01926    param[1] = TMath::Max(fRmax1, fRmax2); // Rmax
01927    param[1] *= param[1];
01928    param[2] = (fPhi1<0)?(fPhi1+360.):fPhi1; // Phi1
01929    param[3] = fPhi2;                        // Phi2
01930    while (param[3]<param[2]) param[3]+=360.;
01931 }
01932 
01933 //_____________________________________________________________________________
01934 TGeoShape *TGeoConeSeg::GetMakeRuntimeShape(TGeoShape *mother, TGeoMatrix * /*mat*/) const
01935 {
01936 // in case shape has some negative parameters, these has to be computed
01937 // in order to fit the mother
01938    if (!TestShapeBit(kGeoRunTimeShape)) return 0;
01939    if (!mother->TestShapeBit(kGeoConeSeg)) {
01940       Error("GetMakeRuntimeShape", "invalid mother");
01941       return 0;
01942    }
01943    Double_t rmin1, rmax1, rmin2, rmax2, dz;
01944    rmin1 = fRmin1;
01945    rmax1 = fRmax1;
01946    rmin2 = fRmin2;
01947    rmax2 = fRmax2;
01948    dz = fDz;
01949    if (fDz<0) dz=((TGeoCone*)mother)->GetDz();
01950    if (fRmin1<0)
01951       rmin1 = ((TGeoCone*)mother)->GetRmin1();
01952    if ((fRmax1<0) || (fRmax1<fRmin1))
01953       rmax1 = ((TGeoCone*)mother)->GetRmax1();
01954    if (fRmin2<0)
01955       rmin2 = ((TGeoCone*)mother)->GetRmin2();
01956    if ((fRmax2<0) || (fRmax2<fRmin2))
01957       rmax2 = ((TGeoCone*)mother)->GetRmax2();
01958 
01959    return (new TGeoConeSeg(GetName(), dz, rmin1, rmax1, rmin2, rmax2, fPhi1, fPhi2));
01960 }
01961 
01962 //_____________________________________________________________________________
01963 void TGeoConeSeg::InspectShape() const
01964 {
01965 // print shape parameters
01966    printf("*** Shape %s: TGeoConeSeg ***\n", GetName());
01967    printf("    dz    = %11.5f\n", fDz);
01968    printf("    Rmin1 = %11.5f\n", fRmin1);
01969    printf("    Rmax1 = %11.5f\n", fRmax1);
01970    printf("    Rmin2 = %11.5f\n", fRmin2);
01971    printf("    Rmax2 = %11.5f\n", fRmax2);
01972    printf("    phi1  = %11.5f\n", fPhi1);
01973    printf("    phi2  = %11.5f\n", fPhi2);
01974    printf(" Bounding box:\n");
01975    TGeoBBox::InspectShape();
01976 }
01977 
01978  //_____________________________________________________________________________
01979 TBuffer3D *TGeoConeSeg::MakeBuffer3D() const
01980 {  
01981    // Creates a TBuffer3D describing *this* shape.
01982    // Coordinates are in local reference frame.
01983 
01984    Int_t n = gGeoManager->GetNsegments()+1;
01985    Int_t nbPnts = 4*n;
01986    Int_t nbSegs = 2*nbPnts;
01987    Int_t nbPols = nbPnts-2; 
01988    TBuffer3D* buff = new TBuffer3D(TBuffer3DTypes::kGeneric,
01989                                    nbPnts, 3*nbPnts, 
01990                                    nbSegs, 3*nbSegs,
01991                                    nbPols, 6*nbPols);
01992 
01993    if (buff)
01994    {
01995       SetPoints(buff->fPnts);
01996       SetSegsAndPols(*buff);
01997    }
01998 
01999    return buff;
02000 }
02001 
02002 //_____________________________________________________________________________
02003 void TGeoConeSeg::SetSegsAndPols(TBuffer3D &buffer) const
02004 {
02005 // Fill TBuffer3D structure for segments and polygons.
02006    Int_t i, j;
02007    Int_t n = gGeoManager->GetNsegments()+1;
02008    Int_t c = GetBasicColor();
02009 
02010    memset(buffer.fSegs, 0, buffer.NbSegs()*3*sizeof(Int_t));
02011    for (i = 0; i < 4; i++) {
02012       for (j = 1; j < n; j++) {
02013          buffer.fSegs[(i*n+j-1)*3  ] = c;
02014          buffer.fSegs[(i*n+j-1)*3+1] = i*n+j-1;
02015          buffer.fSegs[(i*n+j-1)*3+2] = i*n+j;
02016       }
02017    }
02018    for (i = 4; i < 6; i++) {
02019       for (j = 0; j < n; j++) {
02020          buffer.fSegs[(i*n+j)*3  ] = c+1;
02021          buffer.fSegs[(i*n+j)*3+1] = (i-4)*n+j;
02022          buffer.fSegs[(i*n+j)*3+2] = (i-2)*n+j;
02023       }
02024    }
02025    for (i = 6; i < 8; i++) {
02026       for (j = 0; j < n; j++) {
02027          buffer.fSegs[(i*n+j)*3  ] = c;
02028          buffer.fSegs[(i*n+j)*3+1] = 2*(i-6)*n+j;
02029          buffer.fSegs[(i*n+j)*3+2] = (2*(i-6)+1)*n+j;
02030       }
02031    }
02032 
02033    Int_t indx = 0;
02034    memset(buffer.fPols, 0, buffer.NbPols()*6*sizeof(Int_t));
02035    i = 0;
02036    for (j = 0; j < n-1; j++) {
02037       buffer.fPols[indx++] = c;
02038       buffer.fPols[indx++] = 4;
02039       buffer.fPols[indx++] = (4+i)*n+j+1;
02040       buffer.fPols[indx++] = (2+i)*n+j;
02041       buffer.fPols[indx++] = (4+i)*n+j;
02042       buffer.fPols[indx++] = i*n+j;
02043    }
02044    i = 1;
02045    for (j = 0; j < n-1; j++) {
02046       buffer.fPols[indx++] = c;
02047       buffer.fPols[indx++] = 4;
02048       buffer.fPols[indx++] = i*n+j;
02049       buffer.fPols[indx++] = (4+i)*n+j;
02050       buffer.fPols[indx++] = (2+i)*n+j;
02051       buffer.fPols[indx++] = (4+i)*n+j+1;
02052    }
02053    i = 2;
02054    for (j = 0; j < n-1; j++) {
02055       buffer.fPols[indx++] = c+i;
02056       buffer.fPols[indx++] = 4;
02057       buffer.fPols[indx++] = (i-2)*2*n+j;
02058       buffer.fPols[indx++] = (4+i)*n+j;
02059       buffer.fPols[indx++] = ((i-2)*2+1)*n+j;
02060       buffer.fPols[indx++] = (4+i)*n+j+1;
02061    }
02062    i = 3;
02063    for (j = 0; j < n-1; j++) {
02064       buffer.fPols[indx++] = c+i;
02065       buffer.fPols[indx++] = 4;
02066       buffer.fPols[indx++] = (4+i)*n+j+1;
02067       buffer.fPols[indx++] = ((i-2)*2+1)*n+j;
02068       buffer.fPols[indx++] = (4+i)*n+j;
02069       buffer.fPols[indx++] = (i-2)*2*n+j;
02070    }
02071    buffer.fPols[indx++] = c+2;
02072    buffer.fPols[indx++] = 4;
02073    buffer.fPols[indx++] = 6*n;
02074    buffer.fPols[indx++] = 4*n;
02075    buffer.fPols[indx++] = 7*n;
02076    buffer.fPols[indx++] = 5*n;
02077    buffer.fPols[indx++] = c+2;
02078    buffer.fPols[indx++] = 4;
02079    buffer.fPols[indx++] = 6*n-1;
02080    buffer.fPols[indx++] = 8*n-1;
02081    buffer.fPols[indx++] = 5*n-1;
02082    buffer.fPols[indx++] = 7*n-1;
02083 }
02084 
02085 //_____________________________________________________________________________
02086 Double_t TGeoConeSeg::Safety(Double_t *point, Bool_t in) const
02087 {
02088 // computes the closest distance from given point to this shape, according
02089 // to option. The matching point on the shape is stored in spoint.
02090 
02091    Double_t saf[3];
02092    Double_t ro1 = 0.5*(fRmin1+fRmin2);
02093    Double_t tg1 = 0.5*(fRmin2-fRmin1)/fDz;
02094    Double_t cr1 = 1./TMath::Sqrt(1.+tg1*tg1);
02095    Double_t ro2 = 0.5*(fRmax1+fRmax2);
02096    Double_t tg2 = 0.5*(fRmax2-fRmax1)/fDz;
02097    Double_t cr2 = 1./TMath::Sqrt(1.+tg2*tg2);
02098 
02099    Double_t r=TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
02100    Double_t rin = tg1*point[2]+ro1;
02101    Double_t rout = tg2*point[2]+ro2;
02102    Double_t safe = TGeoShape::Big();
02103    if (in) {
02104       saf[0] = fDz-TMath::Abs(point[2]);
02105       saf[1] = (r-rin)*cr1;
02106       saf[2] = (rout-r)*cr2;
02107       safe = saf[TMath::LocMin(3,saf)];
02108    } else {
02109       saf[0] = TMath::Abs(point[2])-fDz; // positive if inside
02110       saf[1] = (rin-r)*cr1;
02111       saf[2] = (r-rout)*cr2;
02112       safe = saf[TMath::LocMax(3,saf)];
02113    }
02114    if ((fPhi2-fPhi1)>=360.) return safe;
02115    Double_t safphi = TGeoShape::SafetyPhi(point, in, fPhi1, fPhi2);
02116 
02117    if (in) return TMath::Min(safe, safphi);
02118    return TMath::Max(safe, safphi);
02119 }
02120 
02121 //_____________________________________________________________________________
02122 Double_t TGeoConeSeg::SafetyS(Double_t *point, Bool_t in, Double_t dz, Double_t rmin1, Double_t rmax1,
02123                               Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2, Int_t skipz)
02124 {
02125 // Static method to compute the closest distance from given point to this shape.
02126    Double_t saf[3];
02127    Double_t ro1 = 0.5*(rmin1+rmin2);
02128    Double_t tg1 = 0.5*(rmin2-rmin1)/dz;
02129    Double_t cr1 = 1./TMath::Sqrt(1.+tg1*tg1);
02130    Double_t ro2 = 0.5*(rmax1+rmax2);
02131    Double_t tg2 = 0.5*(rmax2-rmax1)/dz;
02132    Double_t cr2 = 1./TMath::Sqrt(1.+tg2*tg2);
02133 
02134    Double_t r=TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
02135    Double_t rin = tg1*point[2]+ro1;
02136    Double_t rout = tg2*point[2]+ro2;
02137 
02138    Double_t safe = TGeoShape::Big();
02139    switch (skipz) {
02140       case 1: // skip lower Z plane
02141          saf[0] = dz - point[2];
02142          break;
02143       case 2: // skip upper Z plane
02144          saf[0] = dz + point[2];
02145          break;
02146       case 3: // skip both
02147          saf[0] = TGeoShape::Big();
02148          break;
02149       default:
02150          saf[0] = dz-TMath::Abs(point[2]);
02151    }
02152    saf[1] = (r-rin)*cr1;
02153    saf[2] = (rout-r)*cr2;
02154    Double_t safphi = TGeoShape::SafetyPhi(point,in,phi1,phi2);
02155    if (in) {
02156       safe = saf[TMath::LocMin(3,saf)];
02157       return TMath::Min(safe,safphi);
02158    }
02159    for (Int_t i=0; i<3; i++) saf[i]=-saf[i];
02160    safe = saf[TMath::LocMax(3,saf)];
02161    return TMath::Max(safe,safphi);
02162 }
02163 
02164 //_____________________________________________________________________________
02165 void TGeoConeSeg::SavePrimitive(ostream &out, Option_t * /*option*/ /*= ""*/)
02166 {
02167 // Save a primitive as a C++ statement(s) on output stream "out".
02168    if (TObject::TestBit(kGeoSavePrimitive)) return;
02169    out << "   // Shape: " << GetName() << " type: " << ClassName() << endl;
02170    out << "   dz    = " << fDz << ";" << endl;
02171    out << "   rmin1 = " << fRmin1 << ";" << endl;
02172    out << "   rmax1 = " << fRmax1 << ";" << endl;
02173    out << "   rmin2 = " << fRmin2 << ";" << endl;
02174    out << "   rmax2 = " << fRmax2 << ";" << endl;
02175    out << "   phi1  = " << fPhi1 << ";" << endl;
02176    out << "   phi2  = " << fPhi2 << ";" << endl;
02177    out << "   TGeoShape *" << GetPointerName() << " = new TGeoConeSeg(\"" << GetName() << "\", dz,rmin1,rmax1,rmin2,rmax2,phi1,phi2);" << endl;
02178    TObject::SetBit(TGeoShape::kGeoSavePrimitive);  
02179 }
02180 
02181 //_____________________________________________________________________________
02182 void TGeoConeSeg::SetConsDimensions(Double_t dz, Double_t rmin1, Double_t rmax1,
02183                    Double_t rmin2, Double_t rmax2, Double_t phi1, Double_t phi2)
02184 {
02185 // Set dimensions of the cone segment.
02186    fDz   = dz;
02187    fRmin1 = rmin1;
02188    fRmax1 = rmax1;
02189    fRmin2 = rmin2;
02190    fRmax2 = rmax2;
02191    fPhi1 = phi1;
02192    if (fPhi1<0) fPhi1+=360.;
02193    fPhi2 = phi2;
02194    while (fPhi2<=fPhi1) fPhi2+=360.;
02195    if (TGeoShape::IsSameWithinTolerance(fPhi1,fPhi2)) Error("SetConsDimensions", "In shape %s invalid phi1=%g, phi2=%g\n", GetName(), fPhi1, fPhi2);
02196 }
02197 
02198 //_____________________________________________________________________________
02199 void TGeoConeSeg::SetDimensions(Double_t *param)
02200 {
02201 // Set dimensions of the cone segment from an array.
02202    Double_t dz    = param[0];
02203    Double_t rmin1 = param[1];
02204    Double_t rmax1 = param[2];
02205    Double_t rmin2 = param[3];
02206    Double_t rmax2 = param[4];
02207    Double_t phi1  = param[5];
02208    Double_t phi2  = param[6];
02209    SetConsDimensions(dz, rmin1, rmax1,rmin2, rmax2, phi1, phi2);
02210 }
02211 
02212 //_____________________________________________________________________________
02213 void TGeoConeSeg::SetPoints(Double_t *points) const
02214 {
02215 // Create cone segment mesh points.
02216    Int_t j, n;
02217    Float_t dphi,phi,phi1, phi2,dz;
02218 
02219    n = gGeoManager->GetNsegments()+1;
02220    dz    = fDz;
02221    phi1 = fPhi1;
02222    phi2 = fPhi2;
02223 
02224    dphi = (phi2-phi1)/(n-1);
02225 
02226    Int_t indx = 0;
02227 
02228    if (points) {
02229       for (j = 0; j < n; j++) {
02230          phi = (fPhi1+j*dphi)*TMath::DegToRad();
02231          points[indx++] = fRmin1 * TMath::Cos(phi);
02232          points[indx++] = fRmin1 * TMath::Sin(phi);
02233          points[indx++] = -dz;
02234       }
02235       for (j = 0; j < n; j++) {
02236          phi = (fPhi1+j*dphi)*TMath::DegToRad();
02237          points[indx++] = fRmax1 * TMath::Cos(phi);
02238          points[indx++] = fRmax1 * TMath::Sin(phi);
02239          points[indx++] = -dz;
02240       }
02241       for (j = 0; j < n; j++) {
02242          phi = (fPhi1+j*dphi)*TMath::DegToRad();
02243          points[indx++] = fRmin2 * TMath::Cos(phi);
02244          points[indx++] = fRmin2 * TMath::Sin(phi);
02245          points[indx++] = dz;
02246       }
02247       for (j = 0; j < n; j++) {
02248          phi = (fPhi1+j*dphi)*TMath::DegToRad();
02249          points[indx++] = fRmax2 * TMath::Cos(phi);
02250          points[indx++] = fRmax2 * TMath::Sin(phi);
02251          points[indx++] = dz;
02252       }
02253    }
02254 }
02255 
02256 //_____________________________________________________________________________
02257 void TGeoConeSeg::SetPoints(Float_t *points) const
02258 {
02259 // Create cone segment mesh points.
02260    Int_t j, n;
02261    Float_t dphi,phi,phi1, phi2,dz;
02262 
02263    n = gGeoManager->GetNsegments()+1;
02264    dz    = fDz;
02265    phi1 = fPhi1;
02266    phi2 = fPhi2;
02267 
02268    dphi = (phi2-phi1)/(n-1);
02269 
02270    Int_t indx = 0;
02271 
02272    if (points) {
02273       for (j = 0; j < n; j++) {
02274          phi = (fPhi1+j*dphi)*TMath::DegToRad();
02275          points[indx++] = fRmin1 * TMath::Cos(phi);
02276          points[indx++] = fRmin1 * TMath::Sin(phi);
02277          points[indx++] = -dz;
02278       }
02279       for (j = 0; j < n; j++) {
02280          phi = (fPhi1+j*dphi)*TMath::DegToRad();
02281          points[indx++] = fRmax1 * TMath::Cos(phi);
02282          points[indx++] = fRmax1 * TMath::Sin(phi);
02283          points[indx++] = -dz;
02284       }
02285       for (j = 0; j < n; j++) {
02286          phi = (fPhi1+j*dphi)*TMath::DegToRad();
02287          points[indx++] = fRmin2 * TMath::Cos(phi);
02288          points[indx++] = fRmin2 * TMath::Sin(phi);
02289          points[indx++] = dz;
02290       }
02291       for (j = 0; j < n; j++) {
02292          phi = (fPhi1+j*dphi)*TMath::DegToRad();
02293          points[indx++] = fRmax2 * TMath::Cos(phi);
02294          points[indx++] = fRmax2 * TMath::Sin(phi);
02295          points[indx++] = dz;
02296       }
02297    }
02298 }
02299 
02300 //_____________________________________________________________________________
02301 void TGeoConeSeg::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
02302 {
02303 // Returns numbers of vertices, segments and polygons composing the shape mesh.
02304    Int_t n = gGeoManager->GetNsegments()+1;
02305    nvert = n*4;
02306    nsegs = n*8;
02307    npols = n*4-2;
02308 }
02309 
02310 //_____________________________________________________________________________
02311 Int_t TGeoConeSeg::GetNmeshVertices() const
02312 {
02313 // Return number of vertices of the mesh representation
02314    Int_t n = gGeoManager->GetNsegments()+1;
02315    Int_t numPoints = n*4;
02316    return numPoints;
02317 }
02318 
02319 //_____________________________________________________________________________
02320 void TGeoConeSeg::Sizeof3D() const
02321 {
02322 ///// fill size of this 3-D object
02323 ///    TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
02324 ///    if (!painter) return;
02325 ///
02326 ///    Int_t n = gGeoManager->GetNsegments()+1;
02327 ///
02328 ///    Int_t numPoints = n*4;
02329 ///    Int_t numSegs   = n*8;
02330 ///    Int_t numPolys  = n*4-2;
02331 ///    painter->AddSize3D(numPoints, numSegs, numPolys);
02332 }
02333 
02334 //_____________________________________________________________________________
02335 const TBuffer3D & TGeoConeSeg::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
02336 {
02337 // Fills a static 3D buffer and returns a reference.
02338    static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
02339 
02340    TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
02341 
02342    if (reqSections & TBuffer3D::kRawSizes) {
02343       Int_t n = gGeoManager->GetNsegments()+1;
02344       Int_t nbPnts = 4*n;
02345       Int_t nbSegs = 2*nbPnts;
02346       Int_t nbPols = nbPnts-2;
02347       if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
02348          buffer.SetSectionsValid(TBuffer3D::kRawSizes);
02349       }
02350    }
02351    if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
02352       SetPoints(buffer.fPnts);
02353       if (!buffer.fLocalFrame) {
02354          TransformPoints(buffer.fPnts, buffer.NbPnts());
02355       }
02356 
02357       SetSegsAndPols(buffer);
02358       buffer.SetSectionsValid(TBuffer3D::kRaw);
02359    }
02360       
02361    return buffer;
02362 }
02363 
02364 //_____________________________________________________________________________
02365 Bool_t TGeoConeSeg::GetPointsOnSegments(Int_t npoints, Double_t *array) const
02366 {
02367 // Fills array with n random points located on the line segments of the shape mesh.
02368 // The output array must be provided with a length of minimum 3*npoints. Returns
02369 // true if operation is implemented.
02370    if (npoints > (npoints/2)*2) {
02371       Error("GetPointsOnSegments","Npoints must be even number");
02372       return kFALSE;
02373    }   
02374    Int_t nc = (Int_t)TMath::Sqrt(0.5*npoints);
02375    Double_t dphi = (fPhi2-fPhi1)*TMath::DegToRad()/(nc-1);
02376    Double_t phi = 0;
02377    Double_t phi1 = fPhi1 * TMath::DegToRad();
02378    Int_t ntop = npoints/2 - nc*(nc-1);
02379    Double_t dz = 2*fDz/(nc-1);
02380    Double_t z = 0;
02381    Double_t rmin = 0.;
02382    Double_t rmax = 0.;
02383    Int_t icrt = 0;
02384    Int_t nphi = nc;
02385    // loop z sections
02386    for (Int_t i=0; i<nc; i++) {
02387       if (i == (nc-1)) {
02388          nphi = ntop;
02389          dphi = (fPhi2-fPhi1)*TMath::DegToRad()/(nphi-1);
02390       }   
02391       z = -fDz + i*dz;
02392       rmin = 0.5*(fRmin1+fRmin2) + 0.5*(fRmin2-fRmin1)*z/fDz;
02393       rmax = 0.5*(fRmax1+fRmax2) + 0.5*(fRmax2-fRmax1)*z/fDz; 
02394       // loop points on circle sections
02395       for (Int_t j=0; j<nphi; j++) {
02396          phi = phi1 + j*dphi;
02397          array[icrt++] = rmin * TMath::Cos(phi);
02398          array[icrt++] = rmin * TMath::Sin(phi);
02399          array[icrt++] = z;
02400          array[icrt++] = rmax * TMath::Cos(phi);
02401          array[icrt++] = rmax * TMath::Sin(phi);
02402          array[icrt++] = z;
02403       }
02404    }
02405    return kTRUE;
02406 }                    

Generated on Tue Jul 5 14:12:55 2011 for ROOT_528-00b_version by  doxygen 1.5.1