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

#include "TROOT.h"
#include "TView.h"
#include "TAttLine.h"
#include "TAttFill.h"
#include "TPad.h"
#include "TH2F.h"

#include "TPolyMarker3D.h"
#include "TVirtualGL.h"

#include "TGeoSphere.h"
#include "TGeoPcon.h"
#include "TGeoVolume.h"
#include "TGeoNode.h"
#include "TGeoManager.h"
#include "TGeoTrack.h"
#include "TGeoOverlap.h"
#include "TGeoChecker.h"
#include "TGeoPainter.h"

ClassImp(TGeoPainter)

//______________________________________________________________________________
 TGeoPainter::TGeoPainter()
{
//*-*-*-*-*-*-*-*-*-*-*Geometry painter default constructor*-*-*-*-*-*-*-*-*
//*-*                  ====================================
   TVirtualGeoPainter::SetPainter(this);
   fNsegments = 20;
   fBombX = 1.3;
   fBombY = 1.3;
   fBombZ = 1.3;
   fBombR = 1.3;
   fVisLevel = 3;
   fVisOption = kGeoVisDefault;
   fExplodedView = 0;
   fVisBranch = "";
   fVisLock = kFALSE;
   fTopVisible = kFALSE;
   fPaintingOverlaps = kFALSE;
   fVisVolumes = new TObjArray();
   fOverlap = 0;
   fMatrix = 0;
   memset(&fCheckedBox[0], 0, 6*sizeof(Double_t));
   
   if (gGeoManager) fGeom = gGeoManager;
   else Error("ctor", "No geometry loaded");
   fCheckedNode = fGeom->GetTopNode();
   fChecker = new TGeoChecker(fGeom);
}
//______________________________________________________________________________
 TGeoPainter::~TGeoPainter()
{
//*-*-*-*-*-*-*-*-*-*-*Geometry painter default destructor*-*-*-*-*-*-*-*-*
//*-*                  ===================================
   if (fChecker) delete fChecker;
   delete fVisVolumes;
}
//______________________________________________________________________________
 void TGeoPainter::AddSize3D(Int_t numpoints, Int_t numsegs, Int_t numpolys)
{
//--- Add numpoints, numsegs, numpolys to the global 3D size.
   gSize3D.numPoints += numpoints;
   gSize3D.numSegs   += numsegs;
   gSize3D.numPolys  += numpolys;
}      
//______________________________________________________________________________
 TVirtualGeoTrack *TGeoPainter::AddTrack(Int_t id, Int_t pdgcode, TObject *particle)
{
// Create a primary TGeoTrack.
   return (TVirtualGeoTrack*)(new TGeoTrack(id,pdgcode,0,particle));
}

//______________________________________________________________________________
 void TGeoPainter::AddTrackPoint(Double_t *point, Double_t *box, Bool_t reset) 
{
// Average center of view of all painted tracklets and compute view box.
   static Int_t npoints = 0;
   static Double_t xmin[3] = {0,0,0};
   static Double_t xmax[3] = {0,0,0};
   Int_t i;
   if (reset) {
      memset(box, 0, 6*sizeof(Double_t));
      memset(xmin, 0, 3*sizeof(Double_t));
      memset(xmax, 0, 3*sizeof(Double_t));
      npoints = 0;
      return;
   }      
   if (npoints==0) {
      for (i=0; i<3; i++) xmin[i]=xmax[i]=0;
      npoints++;
   }
   npoints++;
   Double_t  ninv = 1./Double_t(npoints); 
   for (i=0; i<3; i++) {
      box[i] += ninv*(point[i]-box[i]);
      if (point[i]<xmin[i]) xmin[i]=point[i];
      if (point[i]>xmax[i]) xmax[i]=point[i];
      box[i+3] = 0.5*(xmax[i]-xmin[i]);
   } 
}
   
//______________________________________________________________________________
 void TGeoPainter::BombTranslation(const Double_t *tr, Double_t *bombtr)
{
// get the new 'bombed' translation vector according current exploded view mode
   memcpy(bombtr, tr, 3*sizeof(Double_t));
   switch (fExplodedView) {
      case kGeoNoBomb:
         return;
      case kGeoBombXYZ:
         bombtr[0] *= fBombX;
         bombtr[1] *= fBombY;
         bombtr[2] *= fBombZ;
         return;
      case kGeoBombCyl:
         bombtr[0] *= fBombR;
         bombtr[1] *= fBombR;
         bombtr[2] *= fBombZ;
         return;
      case kGeoBombSph:
         bombtr[0] *= fBombR;
         bombtr[1] *= fBombR;
         bombtr[2] *= fBombR;
         return;
      default:
         return;
   }   
}
//______________________________________________________________________________
 void TGeoPainter::CheckGeometry(Int_t nrays, Double_t startx, Double_t starty, Double_t startz) const
{
   fChecker->CheckGeometry(nrays, startx, starty, startz);
}   

//______________________________________________________________________________
 void TGeoPainter::CheckOverlaps(const TGeoVolume *vol, Double_t ovlp, Option_t *option) const
{
// Check overlaps for the top volume of the geometry, within a limit OVLP. 
   fChecker->CheckOverlaps(vol, ovlp, option);
}

//______________________________________________________________________________
 void TGeoPainter::CheckPoint(Double_t x, Double_t y, Double_t z, Option_t *option)
{
// check current point in the geometry
   fChecker->CheckPoint(x,y,z,option);
}   
//______________________________________________________________________________
 Int_t TGeoPainter::DistanceToPrimitiveVol(TGeoVolume *vol, Int_t px, Int_t py)
{
// compute the closest distance of approach from point px,py to a volume 
   const Int_t big = 9999;
   const Int_t inaxis = 7;
   const Int_t maxdist = 5;
   
   TGeoBBox *box;

   Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
   Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
   Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
   Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
   // return if point not in user area
   if (px < puxmin - inaxis) return big;
   if (py > puymin + inaxis) return big;
   if (px > puxmax + inaxis) return big;
   if (py < puymax - inaxis) return big;
   
   TView *view = gPad->GetView();
   if (!view) return big;
   Int_t dist = big;
   Int_t id;
   
   if (fPaintingOverlaps) {
      TGeoVolume *crt;
      if (fOverlap->IsExtrusion()) {
         crt = fOverlap->GetVolume();
         fMatrix = gGeoIdentity;
         dist = crt->GetShape()->DistancetoPrimitive(px,py);
         if (dist<maxdist) {
            gPad->SetSelected(crt);
            box = (TGeoBBox*)crt->GetShape();
            fMatrix->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
            fCheckedBox[3] = box->GetDX();
            fCheckedBox[4] = box->GetDY();
            fCheckedBox[5] = box->GetDZ();
            return 0;
         }
      }   
      crt = fOverlap->GetNode(0)->GetVolume();
      fMatrix = fOverlap->GetNode(0)->GetMatrix();
      dist = crt->GetShape()->DistancetoPrimitive(px,py);
      if (dist<maxdist) {
         gPad->SetSelected(crt);
         box = (TGeoBBox*)crt->GetShape();
         fMatrix->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
         fCheckedBox[3] = box->GetDX();
         fCheckedBox[4] = box->GetDY();
         fCheckedBox[5] = box->GetDZ();
         return 0;
      }
      if (fOverlap->IsExtrusion()) {
         gPad->SetSelected(view);
         return big;
      }
      crt = fOverlap->GetNode(1)->GetVolume();
      fMatrix = fOverlap->GetNode(1)->GetMatrix();
      dist = crt->GetShape()->DistancetoPrimitive(px,py);
      if (dist<maxdist) {
         gPad->SetSelected(crt);
         box = (TGeoBBox*)crt->GetShape();
         fMatrix->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
         fCheckedBox[3] = box->GetDX();
         fCheckedBox[4] = box->GetDY();
         fCheckedBox[5] = box->GetDZ();
         return 0;
      }      
      gPad->SetSelected(view);
      return dist;
   }
   
   if (fGeom->GetTopVolume() == vol) fGeom->CdTop();
   Int_t level = fGeom->GetLevel();
   TGeoNode *current = fGeom->GetCurrentNode();
   if (vol != current->GetVolume()) return 9999;
   Bool_t vis=(current->IsVisible() && (level || (!level && fTopVisible)) && fGeom->IsInPhiRange())?kTRUE:kFALSE;
   TGeoNode *node = 0;
   Int_t nd = vol->GetNdaughters();
   Bool_t last = kFALSE;
   fCheckedNode = fGeom->GetTopNode();
   switch (fVisOption) {
      case kGeoVisDefault:
         if (vis && (level<=fVisLevel)) { 
            dist = vol->GetShape()->DistancetoPrimitive(px,py);
            if (dist<maxdist) {
               gPad->SetSelected(vol);
	             fCheckedNode = current;
	             box = (TGeoBBox*)vol->GetShape();
	             fGeom->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
	             fCheckedBox[3] = box->GetDX();
	             fCheckedBox[4] = box->GetDY();
	             fCheckedBox[5] = box->GetDZ();
               return 0;
            }
         }
         // check daughters
         if (level<fVisLevel) {
            if ((!nd) || (!current->IsVisDaughters())) return dist;
            for (id=0; id<nd; id++) {
               node = vol->GetNode(id);
               fGeom->CdDown(id);
               dist = DistanceToPrimitiveVol(node->GetVolume(),px, py);
               if (dist==0) return 0;
               fGeom->CdUp();
            }
         }
         break;
      case kGeoVisLeaves:
         last = ((nd==0) || (level==fVisLevel))?kTRUE:kFALSE;
         if (vis && (last || (!current->IsVisDaughters()))) {
            dist = vol->GetShape()->DistancetoPrimitive(px, py);
            if (dist<maxdist) {
               gPad->SetSelected(vol);
	             fCheckedNode = current;
	             box = (TGeoBBox*)vol->GetShape();
	             fGeom->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
	             fCheckedBox[3] = box->GetDX();
	             fCheckedBox[4] = box->GetDY();
	             fCheckedBox[5] = box->GetDZ();
               return 0;
            }
         }
         if (last || (!current->IsVisDaughters())) return dist;
         for (id=0; id<nd; id++) {
            node = vol->GetNode(id);
            fGeom->CdDown(id);
            dist = DistanceToPrimitiveVol(node->GetVolume(),px,py);
            if (dist==0) return 0;
            fGeom->CdUp();
         }
         break;
      case kGeoVisOnly:
         dist = vol->GetShape()->DistancetoPrimitive(px, py);
         if (dist<maxdist) {
            gPad->SetSelected(vol);
            fCheckedNode = current;
	          box = (TGeoBBox*)vol->GetShape();
	          fGeom->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
	          fCheckedBox[3] = box->GetDX();
	          fCheckedBox[4] = box->GetDY();
	          fCheckedBox[5] = box->GetDZ();
            return 0;
         }
         break;
      case kGeoVisBranch:
         fGeom->cd(fVisBranch);
         while (fGeom->GetLevel()) {
            if (fGeom->GetCurrentVolume()->IsVisible()) {
               dist = fGeom->GetCurrentVolume()->GetShape()->DistancetoPrimitive(px, py);
               if (dist<maxdist) {
                  gPad->SetSelected(fGeom->GetCurrentVolume());
  	          fCheckedNode = current;
	          box = (TGeoBBox*)fGeom->GetCurrentVolume()->GetShape();
	          fGeom->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
	          fCheckedBox[3] = box->GetDX();
	          fCheckedBox[4] = box->GetDY();
	          fCheckedBox[5] = box->GetDZ();
                  return 0;
               }
            }   
            fGeom->CdUp();
         }
         gPad->SetSelected(view);
	 fCheckedNode = gGeoManager->GetTopNode();      
         return big;   
      default:
	 fCheckedNode = gGeoManager->GetTopNode();      
         return big;
   }       
   if ((dist>maxdist) && !fGeom->GetLevel()) gPad->SetSelected(view);
   fCheckedNode = gGeoManager->GetTopNode();      
   return dist;
}
//______________________________________________________________________________
 void TGeoPainter::DefaultAngles()
{   
// Set default angles for the current view.
   if (gPad) {
      Int_t irep;
      TView *view = gPad->GetView();
      if (!view) return;
      view->SetView(-206,126,75,irep);
      gPad->Modified();
      gPad->Update();
   }
}   
//______________________________________________________________________________
 void TGeoPainter::DefaultColors()
{   
// Set default volume colors according to tracking media
   TIter next(fGeom->GetListOfVolumes());
   TGeoVolume *vol;
   while ((vol=(TGeoVolume*)next()))
      vol->SetLineColor(vol->GetMaterial()->GetDefaultColor());
   if (gPad) {
      if (gPad->GetView()) {
         gPad->Modified();
         gPad->Update();
      }
   }
}   
//______________________________________________________________________________
 void TGeoPainter::Draw(Option_t *option)
{
   TString opt = option;
   opt.ToLower();
   fPaintingOverlaps = kFALSE;
   fOverlap = 0;
   if (fVisOption==kGeoVisOnly) fGeom->SetVisOption(kGeoVisDefault);
   
   if (fVisLock) {
      fVisVolumes->Clear();
      fVisLock = kFALSE;
   }   
   Bool_t has_pad = (gPad==0)?kFALSE:kTRUE;
   // Clear pad if option "same" not given
   if (!gPad) {
      if (!gROOT->GetMakeDefCanvas()) return;
      (gROOT->GetMakeDefCanvas())();
   }
   if (!opt.Contains("same")) gPad->Clear();
   // append this volume to pad
   fGeom->GetTopVolume()->AppendPad(option);

   // Create a 3-D view
   TView *view = gPad->GetView();
   if (!view) {
      view = new TView(11);
      view->SetAutoRange(kTRUE);
      fGeom->GetTopVolume()->Paint("range");
      view->SetAutoRange(kFALSE);
      if (has_pad) gPad->Update();
   }
   if (!view->IsPerspective()) view->SetPerspective();
   fVisLock = kTRUE;
   printf("--- number of nodes on screen : %in", fVisVolumes->GetEntriesFast());
}
//______________________________________________________________________________
 void TGeoPainter::DrawOverlap(void *ovlp, Option_t *option)
{
   TString opt = option;
   TGeoOverlap *overlap = (TGeoOverlap*)ovlp;
   if (!overlap) return;
   
   fPaintingOverlaps = kTRUE;
   fOverlap = overlap;
   opt.ToLower();
   if (fVisLock) {
      fVisVolumes->Clear();
      fVisLock = kFALSE;
   }   
   Bool_t has_pad = (gPad==0)?kFALSE:kTRUE;
   // Clear pad if option "same" not given
   if (!gPad) {
      if (!gROOT->GetMakeDefCanvas()) return;
      (gROOT->GetMakeDefCanvas())();
   }
   if (!opt.Contains("same")) gPad->Clear();
   // append this volume to pad
   overlap->AppendPad(option);

   // Create a 3-D view
   TView *view = gPad->GetView();
   if (!view) {
      view = new TView(11);
      view->SetAutoRange(kTRUE);
      PaintOverlap(overlap, "range");
      view->SetAutoRange(kFALSE);
      overlap->GetPolyMarker()->Draw("SAME");
      if (has_pad) gPad->Update();
   }
   if (!view->IsPerspective()) view->SetPerspective();
   fVisLock = kTRUE;
   printf("--- number of nodes on screen : %in", fVisVolumes->GetEntriesFast());
}
//______________________________________________________________________________
 void TGeoPainter::DrawOnly(Option_t *option)
{
   TString opt = option;
   opt.ToLower();
   if (fVisLock) {
      fVisVolumes->Clear();
      fVisLock = kFALSE;
   }   
   fPaintingOverlaps = kFALSE;
   Bool_t has_pad = (gPad==0)?kFALSE:kTRUE;
   // Clear pad if option "same" not given
   if (!gPad) {
      if (!gROOT->GetMakeDefCanvas()) return;
      (gROOT->GetMakeDefCanvas())();
   }
   if (!opt.Contains("same")) gPad->Clear();
   // append this volume to pad
   fGeom->GetCurrentVolume()->AppendPad(option);

   // Create a 3-D view
   TView *view = gPad->GetView();
   if (!view) {
      view = new TView(11);
      view->SetAutoRange(kTRUE);
      fVisOption = kGeoVisOnly;
      fGeom->GetCurrentVolume()->Paint("range");
      view->SetAutoRange(kFALSE);
      if (has_pad) gPad->Update();
   }
   if (!view->IsPerspective()) view->SetPerspective();
   fVisLock = kTRUE;
}
//-----------------------------------------------------------------------------
 void TGeoPainter::DrawCurrentPoint(Int_t color)
{
// Draw current point in the same view.
   if (!gPad) return;
   if (!gPad->GetView()) return;
   TPolyMarker3D *pm = new TPolyMarker3D();
   pm->SetMarkerColor(color);
   Double_t *point = fGeom->GetCurrentPoint();
   pm->SetNextPoint(point[0], point[1], point[2]);
   pm->SetMarkerStyle(8);
   pm->SetMarkerSize(0.5);
   pm->Draw("SAME");
}
//______________________________________________________________________________
 void TGeoPainter::DrawPanel()
{
}
//______________________________________________________________________________
 void TGeoPainter::DrawPath(const char *path)
{
// Draw all volumes for a given path.
   fVisOption=kGeoVisBranch;
   fVisBranch=path; 
   fGeom->GetTopVolume()->Draw();   
}
//______________________________________________________________________________
 void TGeoPainter::EstimateCameraMove(Double_t tmin, Double_t tmax, Double_t *start, Double_t *end)
{
// Estimate camera movement between tmin and tmax for best track display
   if (!gPad) return;
   TIter next(gPad->GetListOfPrimitives());
   TVirtualGeoTrack *track;
   TObject *obj;
   Int_t ntracks = 0;
   Double_t *point = 0;
   AddTrackPoint(point, start, kTRUE);
   while ((obj=next())) {
      if (strcmp(obj->ClassName(), "TGeoTrack")) continue;
      track = (TVirtualGeoTrack*)obj;
      if (!track) continue;
      ntracks++;
      track->PaintCollect(tmin, start);
   }
   
   if (!ntracks) return;
   next.Reset();
   AddTrackPoint(point, end, kTRUE);
   while ((obj=next())) {
      if (strcmp(obj->ClassName(), "TGeoTrack")) continue;
      track = (TVirtualGeoTrack*)obj;
      if (!track) continue;
      track->PaintCollect(tmax, end);
   }   
}

//______________________________________________________________________________
 void TGeoPainter::ExecuteVolumeEvent(TGeoVolume *volume, Int_t event, Int_t /*px*/, Int_t /*py*/)
{
// Execute mouse actions on a given volume.
   if (!gPad) return;
   gPad->SetCursor(kHand);
   switch (event) {
   case kMouseEnter:
      volume->SetLineWidth(3);
      gPad->Modified();
      gPad->Update();
      break;
   
   case kMouseLeave:
      volume->SetLineWidth(1);
      gPad->Modified();
      gPad->Update();
      break;
   
   case kButton1Double:
      gPad->SetCursor(kWatch);
      GrabFocus();
//      volume->Draw();
      break;
   }
}
//______________________________________________________________________________
 char *TGeoPainter::GetVolumeInfo(const TGeoVolume *volume, Int_t /*px*/, Int_t /*py*/) const
{
   const char *snull = "";
   if (!gPad) return (char*)snull;
   static char info[128];
   if (fPaintingOverlaps) {
      if (!fOverlap) {
         sprintf(info, "wrong overlapping flag");
         return info;
      }   
      TString ovtype, name;
      if (fOverlap->IsExtrusion()) {
         ovtype="EXTRUSION";
         if (volume==fOverlap->GetVolume()) name=volume->GetName();
         else name=fOverlap->GetNode(0)->GetName();
      } else {
         ovtype = "OVERLAP";
         if (volume==fOverlap->GetNode(0)->GetVolume()) name=fOverlap->GetNode(0)->GetName();
         else name=fOverlap->GetNode(1)->GetName();
      }   
      sprintf(info, "%s: %s of %g", name.Data(), ovtype.Data(), fOverlap->GetOverlap());
      return info;
   }   
   else sprintf(info,"%s, shape=%s", fGeom->GetPath(), volume->GetShape()->ClassName());
   return info;
}
//______________________________________________________________________________
 TGeoChecker *TGeoPainter::GetChecker()
{
// Create/return geometry checker.
   if (!fChecker) fChecker = new TGeoChecker(fGeom);
   return fChecker;
}
 
//______________________________________________________________________________
 void TGeoPainter::GetViewAngles(Double_t &longitude, Double_t &latitude, Double_t &psi) 
{
   if (!gPad) return;
   TView *view = gPad->GetView();
   if (!view) return;
   longitude = view->GetLongitude();
   latitude = view->GetLatitude();
   psi = view->GetPsi();
}   

//______________________________________________________________________________
 void TGeoPainter::GrabFocus(Int_t nfr, Double_t dlong, Double_t dlat, Double_t dpsi)
{
// Move focus to current volume
   if (!gPad) return;
   TView *view = gPad->GetView();
   if (!view) return;
   if (!fCheckedNode && !fPaintingOverlaps) {
      printf("Woops!!!n");
      TGeoBBox *box = (TGeoBBox*)fGeom->GetTopVolume()->GetShape();
      memcpy(&fCheckedBox[0], box->GetOrigin(), 3*sizeof(Double_t));
      fCheckedBox[3] = box->GetDX();
      fCheckedBox[4] = box->GetDY();
      fCheckedBox[5] = box->GetDZ();
   }      
   view->SetPerspective();
   Int_t nvols = fVisVolumes->GetEntriesFast();
   Int_t nframes = nfr;
   if (nfr==0) {
      nframes = 1;
      if (nvols<1500) nframes=10;
      if (nvols<1000) nframes=20;
      if (nvols<200) nframes = 50;
      if (nvols<100) nframes = 100;
   }   
   view->MoveFocus(&fCheckedBox[0], fCheckedBox[3], fCheckedBox[4], fCheckedBox[5], nframes, dlong, dlat, dpsi);
}
//______________________________________________________________________________
 Bool_t TGeoPainter::IsOnScreen(const TGeoNode *node) const
{
// check if this node is drawn. Assumes that this node is current
   TObject *obj = (TObject*)node->GetVolume();
   for (Int_t i=0; i<fVisVolumes->GetEntriesFast(); i++) {
      if (fVisVolumes->At(i)==obj) return kTRUE;
   }
   return kFALSE;      
}   
//______________________________________________________________________________
 TH2F *TGeoPainter::LegoPlot(Int_t ntheta, Double_t themin, Double_t themax,
                            Int_t nphi,   Double_t phimin, Double_t phimax,
                            Double_t rmin, Double_t rmax, Option_t *option)
{
// Generate a lego plot fot the top volume, according to option.
   return fChecker->LegoPlot(ntheta, themin, themax, nphi, phimin, phimax, rmin, rmax, option);   
}
//______________________________________________________________________________
 void TGeoPainter::ModifiedPad() const
{
// Check if a pad and view are present and send signal "Modified" to pad.
   if (!gPad) return;
   if (!gPad->GetView()) return;
   gPad->Modified();
   gPad->Update();
}   
//______________________________________________________________________________
 void TGeoPainter::Paint(Option_t *option)
{
// Paint current geometry according to option.
   if (!fGeom) return;
   if (fVisOption==kGeoVisOnly) {
      fGeom->GetCurrentNode()->Paint(option);
      return;
   }
   fGeom->CdTop();
   TGeoNode *top = fGeom->GetTopNode();
   top->Paint(option);
   fVisLock = kTRUE;
}
//______________________________________________________________________________
 void TGeoPainter::PaintOverlap(void *ovlp, Option_t *option)
{
// Paint an overlap.
   if (!fGeom) return;
   TGeoOverlap *overlap = (TGeoOverlap *)ovlp;
   if (!overlap) return;
   if (fOverlap != overlap) fOverlap = overlap;
   TGeoHMatrix *hmat = new TGeoHMatrix(); // id matrix
   TGeoVolume *vol = overlap->GetVolume();
   TGeoNode *node1, *node2;
   if (fOverlap->IsExtrusion()) {
      if (!fVisLock) fVisVolumes->Add(vol);
      fOverlap->SetLineColor(3);
      fOverlap->SetLineWidth(vol->GetLineWidth());
      vol->GetShape()->PaintNext(hmat, option);
      node1 = overlap->GetNode(0);
      *hmat = node1->GetMatrix();
      vol = node1->GetVolume();
      if (!fVisLock) fVisVolumes->Add(vol);
      fOverlap->SetLineColor(4);
      fOverlap->SetLineWidth(vol->GetLineWidth());
      vol->GetShape()->PaintNext(hmat, option);
   } else {
      node1 = overlap->GetNode(0);
      vol = node1->GetVolume();
      fOverlap->SetLineColor(3);
      fOverlap->SetLineWidth(vol->GetLineWidth());
      *hmat = node1->GetMatrix();
      if (!fVisLock) fVisVolumes->Add(vol);
      vol->GetShape()->PaintNext(hmat, option);
      node2 = overlap->GetNode(1);
      vol = node2->GetVolume();
      fOverlap->SetLineColor(4);
      fOverlap->SetLineWidth(vol->GetLineWidth());
      *hmat = node2->GetMatrix();
      if (!fVisLock) fVisVolumes->Add(vol);
      vol->GetShape()->PaintNext(hmat, option);
   }     
   delete hmat;
   fVisLock = kTRUE;
}
//______________________________________________________________________________
 void TGeoPainter::PaintShape(X3DBuffer *buff, Bool_t rangeView, TGeoHMatrix *glmat)
{
//*-*-*-*-*Paint 3-D shape in current pad with its current attributes*-*-*-*-*
//*-*      ==========================================================
//
// rangeView = kTRUE - means no real painting
//                     just estimate the range
//                     of this shape only

    //*-* Paint in the pad
    //*-* Convert to the master system

    if (!buff) return;
    if (!fGeom) return;
    TGeoVolume *vol = fGeom->GetCurrentVolume();
    Float_t *point = &(buff->points[0]);
    Double_t dlocal[3];
    Double_t dmaster[3];
    if (fGeom) {
       for (Int_t j = 0; j < buff->numPoints; j++) {
           dlocal[0]=point[3*j]; dlocal[1]=point[3*j+1]; dlocal[2]=point[3*j+2];
           if (glmat) {
              glmat->LocalToMaster(&dlocal[0],&dmaster[0]);
           } else {   
              if (IsExplodedView()) 
                 fGeom->LocalToMasterBomb(&dlocal[0],&dmaster[0]);
              else   
                 fGeom->LocalToMaster(&dlocal[0],&dmaster[0]);
           }      
//           printf("point %i : %g %g %gn", j,dmaster[0],dmaster[1],dmaster[2]);
           point[3*j]=dmaster[0]; point[3*j+1]=dmaster[1]; point[3*j+2]=dmaster[2];
       }
    }
    
    Float_t x0, y0, z0, x1, y1, z1;
    const Int_t kExpandView = 2;
    int i0;

    x0 = x1 = buff->points[0];
    y0 = y1 = buff->points[1];
    z0 = z1 = buff->points[2];

    if (!rangeView) {
      if (!fPaintingOverlaps) {
         ((TAttLine*)vol)->Modify();  //Change line attributes only if necessary
         ((TAttFill*)vol)->Modify();  //Change fill area attributes only if necessary
      } else {
         ((TAttLine*)fOverlap)->Modify();
      }   
    }

    for (Int_t i = 0; i < buff->numSegs; i++) {
        i0 = 3*buff->segs[3*i+1];
        Float_t *ptpoints_0 = &(buff->points[i0]);
        i0 = 3*buff->segs[3*i+2];
        Float_t *ptpoints_3 = &(buff->points[i0]);
        if (!rangeView) gPad->PaintLine3D(ptpoints_0, ptpoints_3);
        else {
            x0 = ptpoints_0[0] < x0 ? ptpoints_0[0] : x0;
            y0 = ptpoints_0[1] < y0 ? ptpoints_0[1] : y0;
            z0 = ptpoints_0[2] < z0 ? ptpoints_0[2] : z0;
            x1 = ptpoints_3[0] > x1 ? ptpoints_3[0] : x1;
            y1 = ptpoints_3[1] > y1 ? ptpoints_3[1] : y1;
            z1 = ptpoints_3[2] > z1 ? ptpoints_3[2] : z1;
        }
    }
    if (rangeView)
    {
      TView *view = gPad->GetView();
      if (view->GetAutoRange()) view->SetRange(x0,y0,z0,x1,y1,z1,kExpandView);
    }
}

//______________________________________________________________________________
 void *TGeoPainter::MakeBox3DBuffer(const TGeoVolume *vol)
{
// Create a box 3D buffer for a given shape.
   X3DPoints *buff = new X3DPoints;
   const Int_t numpoints = 8;

   buff->numPoints = 8;

   Double_t *points = new Double_t[3*numpoints];
   TGeoShape *shape = vol->GetShape();

   shape->SetPoints(points);

   buff->points = points;
   return buff;
}   

//______________________________________________________________________________
 void TGeoPainter::PaintBox(TGeoShape *shape, Option_t *option, TGeoHMatrix *glmat)
{
// paint any type of box with 8 vertices
   const Int_t numpoints = 8;

//*-* Allocate memory for points *-*

   Float_t *points = new Float_t[3*numpoints];
   if (!points) return;

   shape->SetPoints(points);

   Bool_t rangeView = option && *option && strcmp(option,"range")==0 ? kTRUE : kFALSE;
   if (!rangeView  && gPad->GetView3D()) gVirtualGL->PaintBrik(points);

 //==  for (Int_t i = 0; i < numpoints; i++)
 //            gNode->Local2Master(&points[3*i],&points[3*i]);


   Int_t c = ((fGeom->GetCurrentVolume()->GetLineColor() % 8) - 1) * 4;     // Basic colors: 0, 1, ... 7
   if (c < 0) c = 0;
   if (fPaintingOverlaps) {
      if (fOverlap->IsExtrusion()) {
         if (fOverlap->GetVolume()->GetShape()==shape) c=8;
         else c=12;
      } else {
         if (fOverlap->GetNode(0)->GetVolume()->GetShape()==shape) c=8;
         else c=12;
      }   
   }   

//*-* Allocate memory for segments *-*

    X3DBuffer *buff = new X3DBuffer;
    if (buff) {
        buff->numPoints = 8;
        buff->numSegs   = 12;
        buff->numPolys  = 6;
    }

//*-* Allocate memory for points *-*

    buff->points = points;
    buff->segs = new Int_t[buff->numSegs*3];
    if (buff->segs) {
        buff->segs[ 0] = c;    buff->segs[ 1] = 0;    buff->segs[ 2] = 1;
        buff->segs[ 3] = c+1;  buff->segs[ 4] = 1;    buff->segs[ 5] = 2;
        buff->segs[ 6] = c+1;  buff->segs[ 7] = 2;    buff->segs[ 8] = 3;
        buff->segs[ 9] = c;    buff->segs[10] = 3;    buff->segs[11] = 0;
        buff->segs[12] = c+2;  buff->segs[13] = 4;    buff->segs[14] = 5;
        buff->segs[15] = c+2;  buff->segs[16] = 5;    buff->segs[17] = 6;
        buff->segs[18] = c+3;  buff->segs[19] = 6;    buff->segs[20] = 7;
        buff->segs[21] = c+3;  buff->segs[22] = 7;    buff->segs[23] = 4;
        buff->segs[24] = c;    buff->segs[25] = 0;    buff->segs[26] = 4;
        buff->segs[27] = c+2;  buff->segs[28] = 1;    buff->segs[29] = 5;
        buff->segs[30] = c+1;  buff->segs[31] = 2;    buff->segs[32] = 6;
        buff->segs[33] = c+3;  buff->segs[34] = 3;    buff->segs[35] = 7;
    }

//*-* Allocate memory for polygons *-*

    buff->polys = new Int_t[buff->numPolys*6];
    if (buff->polys) {
        buff->polys[ 0] = c;   buff->polys[ 1] = 4;  buff->polys[ 2] = 0;
        buff->polys[ 3] = 9;   buff->polys[ 4] = 4;  buff->polys[ 5] = 8;
        buff->polys[ 6] = c+1; buff->polys[ 7] = 4;  buff->polys[ 8] = 1;
        buff->polys[ 9] = 10;  buff->polys[10] = 5;  buff->polys[11] = 9;
        buff->polys[12] = c;   buff->polys[13] = 4;  buff->polys[14] = 2;
        buff->polys[15] = 11;  buff->polys[16] = 6;  buff->polys[17] = 10;
        buff->polys[18] = c+1; buff->polys[19] = 4;  buff->polys[20] = 3;
        buff->polys[21] = 8;   buff->polys[22] = 7;  buff->polys[23] = 11;
        buff->polys[24] = c+2; buff->polys[25] = 4;  buff->polys[26] = 0;
        buff->polys[27] = 3;   buff->polys[28] = 2;  buff->polys[29] = 1;
        buff->polys[30] = c+3; buff->polys[31] = 4;  buff->polys[32] = 4;
        buff->polys[33] = 5;   buff->polys[34] = 6;  buff->polys[35] = 7;
    }

    //*-* Paint in the pad
    PaintShape(buff,rangeView, glmat);

    if (strstr(option, "x3d")) {
        if(buff && buff->points && buff->segs)
            FillX3DBuffer(buff);
        else {
            gSize3D.numPoints -= buff->numPoints;
            gSize3D.numSegs   -= buff->numSegs;
            gSize3D.numPolys  -= buff->numPolys;
        }
    }

    delete [] points;
    if (buff->segs)     delete [] buff->segs;
    if (buff->polys)    delete [] buff->polys;
    if (buff)           delete    buff;
}

//______________________________________________________________________________
 void TGeoPainter::PaintCompositeShape(TGeoVolume *vol, Option_t *option)
{
// paint a composite shape
   PaintBox(vol->GetShape(), option);
}

//______________________________________________________________________________
 void *TGeoPainter::MakeTube3DBuffer(const TGeoVolume *vol)
{
// Create a box 3D buffer for a given shape.
   X3DPoints *buff = new X3DPoints;
   Int_t n = fNsegments;
   const Int_t numpoints = 4*n;

   buff->numPoints = numpoints;

   Double_t *points = new Double_t[3*numpoints];
   TGeoShape *shape = vol->GetShape();

   shape->SetPoints(points);

   buff->points = points;
   return buff;
}   
//______________________________________________________________________________
 void TGeoPainter::PaintTube(TGeoShape *shape, Option_t *option, TGeoHMatrix *glmat)
{
// paint tubes
   Int_t i, j;
   Int_t n = fNsegments;
   const Int_t numpoints = 4*n;

//*-* Allocate memory for points *-*

   Float_t *points = new Float_t[3*numpoints];
   if (!points) return;

   shape->SetPoints(points);

   Bool_t rangeView = option && *option && strcmp(option,"range")==0 ? kTRUE : kFALSE;
   if (!rangeView && gPad->GetView3D()) gVirtualGL->PaintCone(points, n, 2);

//==   for (i = 0; i < numpoints; i++)
//==            gNode->Local2Master(&points[3*i],&points[3*i]);

    X3DBuffer *buff = new X3DBuffer;
    if (buff) {
        buff->numPoints = numpoints;
//        if (strstr(option, "x3d"))  
        buff->numSegs   = n*8;
//        else                        buff->numSegs   = n*6;
        buff->numPolys  = n*4;
    }


//*-* Allocate memory for points *-*

    buff->points = points;

    Int_t c = ((fGeom->GetCurrentVolume()->GetLineColor() % 8) - 1) * 4;     // Basic colors: 0, 1, ... 7
    if (c < 0) c = 0;
   if (fPaintingOverlaps) {
      if (fOverlap->IsExtrusion()) {
         if (fOverlap->GetVolume()->GetShape()==shape) c=8;
         else c=12;
      } else {
         if (fOverlap->GetNode(0)->GetVolume()->GetShape()==shape) c=8;
         else c=12;
      }   
   }   

//*-* Allocate memory for segments *-*

    buff->segs = new Int_t[buff->numSegs*3];
    if (buff->segs) {
        for (i = 0; i < 4; i++) {
            for (j = 0; j < n; j++) {
                buff->segs[(i*n+j)*3  ] = c;
                buff->segs[(i*n+j)*3+1] = i*n+j;
                buff->segs[(i*n+j)*3+2] = i*n+j+1;
            }
            buff->segs[(i*n+j-1)*3+2] = i*n;
        }
        for (i = 4; i < 6; i++) {
            for (j = 0; j < n; j++) {
                buff->segs[(i*n+j)*3  ] = c+1;
                buff->segs[(i*n+j)*3+1] = (i-4)*n+j;
                buff->segs[(i*n+j)*3+2] = (i-2)*n+j;
            }
        }
//        if (strstr(option, "x3d")) {
           for (i = 6; i < 8; i++) {
              for (j = 0; j < n; j++) {
                 buff->segs[(i*n+j)*3  ] = c;
                 buff->segs[(i*n+j)*3+1] = 2*(i-6)*n+j;
                 buff->segs[(i*n+j)*3+2] = (2*(i-6)+1)*n+j;
              }
           }
//        }
    }
//*-* Allocate memory for polygons *-*

    Int_t indx = 0;

    buff->polys = new Int_t[buff->numPolys*6];
    if (buff->polys) {
        for (i = 0; i < 2; i++) {
            for (j = 0; j < n; j++) {
                indx = 6*(i*n+j);
                buff->polys[indx  ] = c;
                buff->polys[indx+1] = 4;
                buff->polys[indx+2] = i*n+j;
                buff->polys[indx+3] = (4+i)*n+j;
                buff->polys[indx+4] = (2+i)*n+j;
                buff->polys[indx+5] = (4+i)*n+j+1;
            }
            buff->polys[indx+5] = (4+i)*n;
        }
        for (i = 2; i < 4; i++) {
            for (j = 0; j < n; j++) {
                indx = 6*(i*n+j);
                buff->polys[indx  ] = c+i;
                buff->polys[indx+1] = 4;
                buff->polys[indx+2] = (i-2)*2*n+j;
                buff->polys[indx+3] = (4+i)*n+j;
                buff->polys[indx+4] = ((i-2)*2+1)*n+j;
                buff->polys[indx+5] = (4+i)*n+j+1;
            }
            buff->polys[indx+5] = (4+i)*n;
        }
    }

    //*-* Paint in the pad
    PaintShape(buff,rangeView, glmat);

    if (strstr(option, "x3d")) {
        if(buff && buff->points && buff->segs)
            FillX3DBuffer(buff);
        else {
            gSize3D.numPoints -= buff->numPoints;
            gSize3D.numSegs   -= buff->numSegs;
            gSize3D.numPolys  -= buff->numPolys;
        }
    }

    if (buff->points)   delete [] buff->points;
    if (buff->segs)     delete [] buff->segs;
    if (buff->polys)    delete [] buff->polys;
    if (buff)           delete    buff;
}

//______________________________________________________________________________
 void *TGeoPainter::MakeTubs3DBuffer(const TGeoVolume *vol)
{
// Create a box 3D buffer for a given shape.
   X3DPoints *buff = new X3DPoints;

   const Int_t n = fNsegments+1;
   const Int_t numpoints = 4*n;

   //*-* Allocate memory for points *-*

   Double_t *points = new Double_t[3*numpoints];

   buff->numPoints =   numpoints;

   TGeoShape *shape = vol->GetShape();
   shape->SetPoints(points);
   buff->points = points;
   return buff;
}   
//______________________________________________________________________________
 void TGeoPainter::PaintTubs(TGeoShape *shape, Option_t *option, TGeoHMatrix *glmat)
{
// paint tubes
   Int_t i, j;
   const Int_t n = fNsegments+1;
   const Int_t numpoints = 4*n;

   //*-* Allocate memory for points *-*

   Float_t *points = new Float_t[3*numpoints];
   if (!points) return;

   shape->SetPoints(points);

   Bool_t rangeView = option && *option && strcmp(option,"range")==0 ? kTRUE : kFALSE;
   if (!rangeView && gPad->GetView3D()) gVirtualGL->PaintCone(points,-n,2);

//==   for (i = 0; i < numpoints; i++)
//==            gNode->Local2Master(&points[3*i],&points[3*i]);


    X3DBuffer *buff = new X3DBuffer;
    if (buff) {
        buff->numPoints =   numpoints;
        buff->numSegs   = 2*numpoints;
        buff->numPolys  =   numpoints-2;
    }

    buff->points = points;

    Int_t c = ((fGeom->GetCurrentVolume()->GetLineColor() % 8) - 1) * 4;     // Basic colors: 0, 1, ... 7
    if (c < 0) c = 0;
   if (fPaintingOverlaps) {
      if (fOverlap->IsExtrusion()) {
         if (fOverlap->GetVolume()->GetShape()==shape) c=8;
         else c=12;
      } else {
         if (fOverlap->GetNode(0)->GetVolume()->GetShape()==shape) c=8;
         else c=12;
      }   
   }
//*-* Allocate memory for segments *-*

    buff->segs = new Int_t[buff->numSegs*3];
    memset(buff->segs, 0, buff->numSegs*3*sizeof(Int_t));
    if (buff->segs) {
        for (i = 0; i < 4; i++) {
            for (j = 1; j < n; j++) {
                buff->segs[(i*n+j-1)*3  ] = c;
                buff->segs[(i*n+j-1)*3+1] = i*n+j-1;
                buff->segs[(i*n+j-1)*3+2] = i*n+j;
            }
        }
        for (i = 4; i < 6; i++) {
            for (j = 0; j < n; j++) {
                buff->segs[(i*n+j)*3  ] = c+1;
                buff->segs[(i*n+j)*3+1] = (i-4)*n+j;
                buff->segs[(i*n+j)*3+2] = (i-2)*n+j;
            }
        }
        for (i = 6; i < 8; i++) {
            for (j = 0; j < n; j++) {
                buff->segs[(i*n+j)*3  ] = c;
                buff->segs[(i*n+j)*3+1] = 2*(i-6)*n+j;
                buff->segs[(i*n+j)*3+2] = (2*(i-6)+1)*n+j;
            }
        }
    }

//*-* Allocate memory for polygons *-*

    Int_t indx = 0;

    buff->polys = new Int_t[buff->numPolys*6];
    memset(buff->polys, 0, buff->numPolys*6*sizeof(Int_t));
    if (buff->polys) {
        for (i = 0; i < 2; i++) {
            for (j = 0; j < n-1; j++) {
                buff->polys[indx++] = c;
                buff->polys[indx++] = 4;
                buff->polys[indx++] = i*n+j;
                buff->polys[indx++] = (4+i)*n+j;
                buff->polys[indx++] = (2+i)*n+j;
                buff->polys[indx++] = (4+i)*n+j+1;
            }
        }
        for (i = 2; i < 4; i++) {
            for (j = 0; j < n-1; j++) {
                buff->polys[indx++] = c+i;
                buff->polys[indx++] = 4;
                buff->polys[indx++] = (i-2)*2*n+j;
                buff->polys[indx++] = (4+i)*n+j;
                buff->polys[indx++] = ((i-2)*2+1)*n+j;
                buff->polys[indx++] = (4+i)*n+j+1;
            }
        }
        buff->polys[indx++] = c+2;
        buff->polys[indx++] = 4;
        buff->polys[indx++] = 6*n;
        buff->polys[indx++] = 4*n;
        buff->polys[indx++] = 7*n;
        buff->polys[indx++] = 5*n;

        buff->polys[indx++] = c+2;
        buff->polys[indx++] = 4;
        buff->polys[indx++] = 7*n-1;
        buff->polys[indx++] = 5*n-1;
        buff->polys[indx++] = 8*n-1;
        buff->polys[indx++] = 6*n-1;
    }

    //*-* Paint in the pad
    PaintShape(buff,rangeView, glmat);

    if (strstr(option, "x3d")) {
        if(buff && buff->points && buff->segs)
            FillX3DBuffer(buff);
        else {
            gSize3D.numPoints -= buff->numPoints;
            gSize3D.numSegs   -= buff->numSegs;
            gSize3D.numPolys  -= buff->numPolys;
        }
    }

    delete [] points;
    if (buff->segs)     delete [] buff->segs;
    if (buff->polys)    delete [] buff->polys;
    if (buff)           delete    buff;
}
//______________________________________________________________________________
 void *TGeoPainter::MakeSphere3DBuffer(const TGeoVolume *vol)
{
// Create a box 3D buffer for a given shape.
   X3DPoints *buff = new X3DPoints;

   TGeoShape *shape = vol->GetShape();
   ((TGeoSphere*)shape)->SetNumberOfDivisions(fNsegments);
   const Int_t n = ((TGeoSphere*)shape)->GetNumberOfDivisions()+1;
   Int_t nz = ((TGeoSphere*)shape)->GetNz()+1;
   if (nz < 2) return 0;
   Int_t numpoints = 2*n*nz;
   if (numpoints <= 0) return 0;

   //*-* Allocate memory for points *-*

   Double_t *points = new Double_t[3*numpoints];

   buff->numPoints = numpoints;

   shape->SetPoints(points);
   buff->points = points;
   return buff;
}

//______________________________________________________________________________
 void TGeoPainter::PaintSphere(TGeoShape *shape, Option_t *option, TGeoHMatrix *glmat)
{
// paint a sphere
   Int_t i, j;
   ((TGeoSphere*)shape)->SetNumberOfDivisions(fNsegments);
   const Int_t n = ((TGeoSphere*)shape)->GetNumberOfDivisions()+1;
   Double_t ph1 = ((TGeoSphere*)shape)->GetPhi1();
   Double_t ph2 = ((TGeoSphere*)shape)->GetPhi2();
   Int_t nz = ((TGeoSphere*)shape)->GetNz()+1;
   if (nz < 2) return;
   Int_t numpoints = 2*n*nz;
   if (numpoints <= 0) return;
   //*-* Allocate memory for points *-*

   Float_t *points = new Float_t[3*numpoints];
   if (!points) return;
   shape->SetPoints(points);

   Bool_t rangeView = option && *option && strcmp(option,"range")==0 ? kTRUE : kFALSE;
   if (!rangeView && gPad->GetView3D()) gVirtualGL->PaintCone(points, -n, nz);

 //==  for (i = 0; i < numpoints; i++)
 //==          gNode->Local2Master(&points[3*i],&points[3*i]);

   Bool_t specialCase = kFALSE;

   if (TMath::Abs(TMath::Sin(2*(ph2 - ph1))) <= 0.01)  //mark this as a very special case, when
         specialCase = kTRUE;                                  //we have to draw this PCON like a TUBE

    X3DBuffer *buff = new X3DBuffer;
    if (buff) {
        buff->numPoints = numpoints;
        buff->numSegs   = 4*(nz*n-1+(specialCase == kTRUE));
        buff->numPolys  = 2*(nz*n-1+(specialCase == kTRUE));
    }

//*-* Allocate memory for points *-*

    buff->points = points;

    Int_t c = ((fGeom->GetCurrentVolume()->GetLineColor() % 8) - 1) * 4;     // Basic colors: 0, 1, ... 7
    if (c < 0) c = 0;
   if (fPaintingOverlaps) {
      if (fOverlap->IsExtrusion()) {
         if (fOverlap->GetVolume()->GetShape()==shape) c=8;
         else c=12;
      } else {
         if (fOverlap->GetNode(0)->GetVolume()->GetShape()==shape) c=8;
         else c=12;
      }   
   }

//*-* Allocate memory for segments *-*

    Int_t indx, indx2, k;
    indx = indx2 = 0;

    buff->segs = new Int_t[buff->numSegs*3];
    if (buff->segs) {

        //inside & outside spheres, number of segments: 2*nz*(n-1)
        //             special case number of segments: 2*nz*n
        for (i = 0; i < nz*2; i++) {
            indx2 = i*n;
            for (j = 1; j < n; j++) {
                buff->segs[indx++] = c;
                buff->segs[indx++] = indx2+j-1;
                buff->segs[indx++] = indx2+j;
            }
            if (specialCase) {
                buff->segs[indx++] = c;
                buff->segs[indx++] = indx2+j-1;
                buff->segs[indx++] = indx2;
            }
        }

        //bottom & top lines, number of segments: 2*n
        for (i = 0; i < 2; i++) {
            indx2 = i*(nz-1)*2*n;
            for (j = 0; j < n; j++) {
                buff->segs[indx++] = c;
                buff->segs[indx++] = indx2+j;
                buff->segs[indx++] = indx2+n+j;
            }
        }

        //inside & outside spheres, number of segments: 2*(nz-1)*n
        for (i = 0; i < (nz-1); i++) {

            //inside sphere
            indx2 = i*n*2;
            for (j = 0; j < n; j++) {
                buff->segs[indx++] = c+2;
                buff->segs[indx++] = indx2+j;
                buff->segs[indx++] = indx2+n*2+j;
            }
            //outside sphere
            indx2 = i*n*2+n;
            for (j = 0; j < n; j++) {
                buff->segs[indx++] = c+3;
                buff->segs[indx++] = indx2+j;
                buff->segs[indx++] = indx2+n*2+j;
            }
        }

        //left & right sections, number of segments: 2*(nz-2)
        //          special case number of segments: 0
        if (!specialCase) {
            for (i = 1; i < (nz-1); i++) {
                for (j = 0; j < 2; j++) {
                    buff->segs[indx++] = c;
                    buff->segs[indx++] =  2*i    * n + j*(n-1);
                    buff->segs[indx++] = (2*i+1) * n + j*(n-1);
                }
            }
        }
    }


    Int_t m = n - 1 + (specialCase == kTRUE);

//*-* Allocate memory for polygons *-*

    indx = 0;

    buff->polys = new Int_t[buff->numPolys*6];

    if (buff->polys) {

        //bottom & top, number of polygons: 2*(n-1)
        // special case number of polygons: 2*n
        for (i = 0; i < 2; i++) {
            for (j = 0; j < n-1; j++) {
                buff->polys[indx++] = c+3;
                buff->polys[indx++] = 4;
                buff->polys[indx++] = 2*nz*m+i*n+j;
                buff->polys[indx++] = i*(nz*2-2)*m+m+j;
                buff->polys[indx++] = 2*nz*m+i*n+j+1;
                buff->polys[indx++] = i*(nz*2-2)*m+j;
            }
            if (specialCase) {
                buff->polys[indx++] = c+3;
                buff->polys[indx++] = 4;
                buff->polys[indx++] = 2*nz*m+i*n+j;
                buff->polys[indx++] = i*(nz*2-2)*m+m+j;
                buff->polys[indx++] = 2*nz*m+i*n;
                buff->polys[indx++] = i*(nz*2-2)*m+j;
            }
        }


        //inside & outside, number of polygons: (nz-1)*2*(n-1)
        for (k = 0; k < (nz-1); k++) {
            for (i = 0; i < 2; i++) {
                for (j = 0; j < n-1; j++) {
                    buff->polys[indx++] = c+i;
                    buff->polys[indx++] = 4;
                    buff->polys[indx++] = (2*k+i*1)*m+j;
                    buff->polys[indx++] = nz*2*m+(2*k+i*1+2)*n+j;
                    buff->polys[indx++] = (2*k+i*1+2)*m+j;
                    buff->polys[indx++] = nz*2*m+(2*k+i*1+2)*n+j+1;
                }
                if (specialCase) {
                    buff->polys[indx++] = c+i;
                    buff->polys[indx++] = 4;
                    buff->polys[indx++] = (2*k+i*1)*m+j;
                    buff->polys[indx++] = nz*2*m+(2*k+i*1+2)*n+j;
                    buff->polys[indx++] = (2*k+i*1+2)*m+j;
                    buff->polys[indx++] = nz*2*m+(2*k+i*1+2)*n;
                }
            }
        }


        //left & right sections, number of polygons: 2*(nz-1)
        //          special case number of polygons: 0
        if (!specialCase) {
            indx2 = nz*2*(n-1);
            for (k = 0; k < (nz-1); k++) {
                for (i = 0; i < 2; i++) {
                    buff->polys[indx++] = c+2;
                    buff->polys[indx++] = 4;
                    buff->polys[indx++] = k==0 ? indx2+i*(n-1) : indx2+2*nz*n+2*(k-1)+i;
                    buff->polys[indx++] = indx2+2*(k+1)*n+i*(n-1);
                    buff->polys[indx++] = indx2+2*nz*n+2*k+i;
                    buff->polys[indx++] = indx2+(2*k+3)*n+i*(n-1);
                }
            }
            buff->polys[indx-8] = indx2+n;
            buff->polys[indx-2] = indx2+2*n-1;
        }
    }

    //*-* Paint in the pad
    PaintShape(buff,rangeView, glmat);

    if (strstr(option, "x3d")) {
        if(buff && buff->points && buff->segs)
            FillX3DBuffer(buff);
        else {
            gSize3D.numPoints -= buff->numPoints;
            gSize3D.numSegs   -= buff->numSegs;
            gSize3D.numPolys  -= buff->numPolys;
        }
    }

    delete [] points;
    if (buff->segs)     delete [] buff->segs;
    if (buff->polys)    delete [] buff->polys;
    if (buff)           delete    buff;
}

//______________________________________________________________________________
 void *TGeoPainter::MakePcon3DBuffer(const TGeoVolume *vol)
{
// Create a box 3D buffer for a given shape.
   X3DPoints *buff = new X3DPoints;

   TGeoShape *shape = vol->GetShape();
   const Int_t n = ((TGeoPcon*)shape)->GetNsegments()+1;
   Int_t nz = ((TGeoPcon*)shape)->GetNz();
   if (nz < 2) return 0;
   Int_t numpoints =  nz*2*n;
   if (numpoints <= 0) return 0;
   Double_t *points = new Double_t[3*numpoints];
   shape->SetPoints(points);
   buff->numPoints = numpoints;
   buff->points = points;
   return buff;
}

//______________________________________________________________________________
 void TGeoPainter::PaintPcon(TGeoShape *shape, Option_t *option, TGeoHMatrix *glmat)
{
// paint a pcon
   Int_t i, j;
   const Int_t n = ((TGeoPcon*)shape)->GetNsegments()+1;
   Int_t nz = ((TGeoPcon*)shape)->GetNz();
   if (nz < 2) return;
   Int_t numpoints =  nz*2*n;
   if (numpoints <= 0) return;
   Double_t dphi = ((TGeoPcon*)shape)->GetDphi();
   //*-* Allocate memory for points *-*

   Float_t *points = new Float_t[3*numpoints];
   if (!points) return;
   shape->SetPoints(points);

   Bool_t rangeView = strcmp(option,"range")==0 ? kTRUE : kFALSE;
   if (!rangeView && gPad->GetView3D()) gVirtualGL->PaintCone(points, -n, nz);

 //==  for (i = 0; i < numpoints; i++)
 //==          gNode->Local2Master(&points[3*i],&points[3*i]);

   Bool_t specialCase = kFALSE;

   if (dphi == 360)           //mark this as a very special case, when
        specialCase = kTRUE;     //we have to draw this PCON like a TUBE

    X3DBuffer *buff = new X3DBuffer;
    if (buff) {
        buff->numPoints = numpoints;
        buff->numSegs   = 4*(nz*n-1+(specialCase == kTRUE));
        buff->numPolys  = 2*(nz*n-1+(specialCase == kTRUE));
    }

//*-* Allocate memory for points *-*

    buff->points = points;

    Int_t c = ((fGeom->GetCurrentVolume()->GetLineColor() % 8) - 1) * 4;     // Basic colors: 0, 1, ... 7
    if (c < 0) c = 0;
   if (fPaintingOverlaps) {
      if (fOverlap->IsExtrusion()) {
         if (fOverlap->GetVolume()->GetShape()==shape) c=8;
         else c=12;
      } else {
         if (fOverlap->GetNode(0)->GetVolume()->GetShape()==shape) c=8;
         else c=12;
      }   
   }

//*-* Allocate memory for segments *-*

    Int_t indx, indx2, k;
    indx = indx2 = 0;

    buff->segs = new Int_t[buff->numSegs*3];
    if (buff->segs) {

        //inside & outside circles, number of segments: 2*nz*(n-1)
        //             special case number of segments: 2*nz*n
        for (i = 0; i < nz*2; i++) {
            indx2 = i*n;
            for (j = 1; j < n; j++) {
                buff->segs[indx++] = c;
                buff->segs[indx++] = indx2+j-1;
                buff->segs[indx++] = indx2+j;
            }
            if (specialCase) {
                buff->segs[indx++] = c;
                buff->segs[indx++] = indx2+j-1;
                buff->segs[indx++] = indx2;
            }
        }

        //bottom & top lines, number of segments: 2*n
        for (i = 0; i < 2; i++) {
            indx2 = i*(nz-1)*2*n;
            for (j = 0; j < n; j++) {
                buff->segs[indx++] = c;
                buff->segs[indx++] = indx2+j;
                buff->segs[indx++] = indx2+n+j;
            }
        }

        //inside & outside cilindres, number of segments: 2*(nz-1)*n
        for (i = 0; i < (nz-1); i++) {

            //inside cilinder
            indx2 = i*n*2;
            for (j = 0; j < n; j++) {
                buff->segs[indx++] = c+2;
                buff->segs[indx++] = indx2+j;
                buff->segs[indx++] = indx2+n*2+j;
            }
            //outside cilinder
            indx2 = i*n*2+n;
            for (j = 0; j < n; j++) {
                buff->segs[indx++] = c+3;
                buff->segs[indx++] = indx2+j;
                buff->segs[indx++] = indx2+n*2+j;
            }
        }

        //left & right sections, number of segments: 2*(nz-2)
        //          special case number of segments: 0
        if (!specialCase) {
            for (i = 1; i < (nz-1); i++) {
                for (j = 0; j < 2; j++) {
                    buff->segs[indx++] = c;
                    buff->segs[indx++] =  2*i    * n + j*(n-1);
                    buff->segs[indx++] = (2*i+1) * n + j*(n-1);
                }
            }
        }
    }


    Int_t m = n - 1 + (specialCase == kTRUE);

//*-* Allocate memory for polygons *-*

    indx = 0;

    buff->polys = new Int_t[buff->numPolys*6];

    if (buff->polys) {

        //bottom & top, number of polygons: 2*(n-1)
        // special case number of polygons: 2*n
        for (i = 0; i < 2; i++) {
            for (j = 0; j < n-1; j++) {
                buff->polys[indx++] = c+3;
                buff->polys[indx++] = 4;
                buff->polys[indx++] = 2*nz*m+i*n+j;
                buff->polys[indx++] = i*(nz*2-2)*m+m+j;
                buff->polys[indx++] = 2*nz*m+i*n+j+1;
                buff->polys[indx++] = i*(nz*2-2)*m+j;
            }
            if (specialCase) {
                buff->polys[indx++] = c+3;
                buff->polys[indx++] = 4;
                buff->polys[indx++] = 2*nz*m+i*n+j;
                buff->polys[indx++] = i*(nz*2-2)*m+m+j;
                buff->polys[indx++] = 2*nz*m+i*n;
                buff->polys[indx++] = i*(nz*2-2)*m+j;
            }
        }


        //inside & outside, number of polygons: (nz-1)*2*(n-1)
        for (k = 0; k < (nz-1); k++) {
            for (i = 0; i < 2; i++) {
                for (j = 0; j < n-1; j++) {
                    buff->polys[indx++] = c+i;
                    buff->polys[indx++] = 4;
                    buff->polys[indx++] = (2*k+i*1)*m+j;
                    buff->polys[indx++] = nz*2*m+(2*k+i*1+2)*n+j;
                    buff->polys[indx++] = (2*k+i*1+2)*m+j;
                    buff->polys[indx++] = nz*2*m+(2*k+i*1+2)*n+j+1;
                }
                if (specialCase) {
                    buff->polys[indx++] = c+i;
                    buff->polys[indx++] = 4;
                    buff->polys[indx++] = (2*k+i*1)*m+j;
                    buff->polys[indx++] = nz*2*m+(2*k+i*1+2)*n+j;
                    buff->polys[indx++] = (2*k+i*1+2)*m+j;
                    buff->polys[indx++] = nz*2*m+(2*k+i*1+2)*n;
                }
            }
        }


        //left & right sections, number of polygons: 2*(nz-1)
        //          special case number of polygons: 0
        if (!specialCase) {
            indx2 = nz*2*(n-1);
            for (k = 0; k < (nz-1); k++) {
                for (i = 0; i < 2; i++) {
                    buff->polys[indx++] = c+2;
                    buff->polys[indx++] = 4;
                    buff->polys[indx++] = k==0 ? indx2+i*(n-1) : indx2+2*nz*n+2*(k-1)+i;
                    buff->polys[indx++] = indx2+2*(k+1)*n+i*(n-1);
                    buff->polys[indx++] = indx2+2*nz*n+2*k+i;
                    buff->polys[indx++] = indx2+(2*k+3)*n+i*(n-1);
                }
            }
            buff->polys[indx-8] = indx2+n;
            buff->polys[indx-2] = indx2+2*n-1;
        }
    }

    //*-* Paint in the pad
    PaintShape(buff,rangeView, glmat);

    if (strstr(option, "x3d")) {
        if(buff && buff->points && buff->segs)
            FillX3DBuffer(buff);
        else {
            gSize3D.numPoints -= buff->numPoints;
            gSize3D.numSegs   -= buff->numSegs;
            gSize3D.numPolys  -= buff->numPolys;
        }
    }

    delete [] points;
    if (buff->segs)     delete [] buff->segs;
    if (buff->polys)    delete [] buff->polys;
    if (buff)           delete    buff;
}
//______________________________________________________________________________
 void TGeoPainter::PaintNode(TGeoNode *node, Option_t *option)
{
// paint recursively a node and its content accordind to visualization options
   TGeoNode *daughter = 0;
   TGeoVolume *vol = node->GetVolume();
   Int_t nd = node->GetNdaughters();
   Bool_t last = kFALSE;
   Int_t level = fGeom->GetLevel();
   Bool_t vis=(node->IsVisible() && (level || (!level && fTopVisible)) && fGeom->IsInPhiRange())?kTRUE:kFALSE;
   Int_t id;
   switch (fVisOption) {
      case kGeoVisDefault:
         if (vis && (level<=fVisLevel)) {
            vol->GetShape()->Paint(option);
            if (!fVisLock) fVisVolumes->Add(vol);
         }   
            // draw daughters
         if (level<fVisLevel) {
            if ((!nd) || (!node->IsVisDaughters())) return;
            for (id=0; id<nd; id++) {
               daughter = node->GetDaughter(id);
               fGeom->CdDown(id);
               PaintNode(daughter, option);
               fGeom->CdUp();
            }
         }
         break;
      case kGeoVisLeaves:
         if (level>fVisLevel) return;
         last = ((nd==0) || (level==fVisLevel))?kTRUE:kFALSE;
         if (vis && (last || (!node->IsVisDaughters()))) {
            vol->GetShape()->Paint(option);
            if (!fVisLock) fVisVolumes->Add(vol);
         }            
         if (last || (!node->IsVisDaughters())) return;
         for (id=0; id<nd; id++) {
            daughter = node->GetDaughter(id);
            fGeom->CdDown(id);
            PaintNode(daughter, option);
            fGeom->CdUp();
         }
         break;
      case kGeoVisOnly:
         vol->GetShape()->Paint(option);
         if (!fVisLock) fVisVolumes->Add(vol);
         break;
      case kGeoVisBranch:
         fGeom->cd(fVisBranch);
         while (fGeom->GetLevel()) {
            if (fGeom->GetCurrentVolume()->IsVisible()) {
               fGeom->GetCurrentVolume()->GetShape()->Paint(option);
               if (!fVisLock) fVisVolumes->Add(fGeom->GetCurrentVolume());
            }   
            fGeom->CdUp();
         }
         break;
      default:
         return;
   }
} 

//______________________________________________________________________________
 void TGeoPainter::PrintOverlaps() const
{
   fChecker->PrintOverlaps();
}
   
//______________________________________________________________________________
 void TGeoPainter::RandomPoints(const TGeoVolume *vol, Int_t npoints, Option_t *option)
{
// Draw random points in the bounding box of a volume.
   fChecker->RandomPoints((TGeoVolume*)vol, npoints, option);
}   
//______________________________________________________________________________
 void TGeoPainter::RandomRays(Int_t nrays, Double_t startx, Double_t starty, Double_t startz)
{
// Raytrace nrays in the current drawn geometry
   fChecker->RandomRays(nrays, startx, starty, startz);
}   
//-----------------------------------------------------------------------------
 TGeoNode *TGeoPainter::SamplePoints(Int_t npoints, Double_t &dist, Double_t epsil,
                                    const char* g3path)
{
// shoot npoints randomly in a box of 1E-5 arround current point.
// return minimum distance to points outside
   return fChecker->SamplePoints(npoints, dist, epsil, g3path);
}
//______________________________________________________________________________
 void TGeoPainter::SetBombFactors(Double_t bombx, Double_t bomby, Double_t bombz, Double_t bombr)
{
//--- Set cartesian and radial bomb factors for translations
   fBombX = bombx;
   fBombY = bomby;
   fBombZ = bombz;
   fBombR = bombr;
   if (IsExplodedView()) {
      if (gPad) {
         gPad->Modified();
         gPad->Update();
      }
   }
}          
//______________________________________________________________________________
 void TGeoPainter::Sizeof3D(const TGeoVolume *vol) const
{
//   Compute size of the 3d object "vol".
   if (fGeom->GetTopVolume() == vol) fGeom->CdTop();
   TGeoNode *node = 0;
   Int_t nd = vol->GetNdaughters();
   TGeoShape *shape = vol->GetShape();
   Bool_t last = kFALSE;
   Int_t level = fGeom->GetLevel();
   TGeoNode *current = fGeom->GetCurrentNode();
   Bool_t vis=(current->IsVisible() && (level || (!level && fTopVisible)) && fGeom->IsInPhiRange())?kTRUE:kFALSE;
   Int_t id;
   switch (fVisOption) {
      case kGeoVisDefault:
         if (vis && (level<=fVisLevel)) 
            shape->Sizeof3D();
            // draw daughters
         if (level<fVisLevel) {
            if ((!nd) || (!current->IsVisDaughters())) return;
            for (id=0; id<nd; id++) {
               node = vol->GetNode(id);
               fGeom->CdDown(id);
               Sizeof3D(node->GetVolume());
               fGeom->CdUp();
            }
         }
         break;
      case kGeoVisLeaves:
         last = ((nd==0) || (level==fVisLevel))?kTRUE:kFALSE;
         if (vis && (last || (!current->IsVisDaughters())))
            shape->Sizeof3D();
         if (last || (!current->IsVisDaughters())) return;
         for (id=0; id<nd; id++) {
            node = vol->GetNode(id);
            fGeom->CdDown(id);
            Sizeof3D(node->GetVolume());
            fGeom->CdUp();
         }
         break;
      case kGeoVisOnly:
         shape->Sizeof3D();
         break;
      case kGeoVisBranch:
         fGeom->cd(fVisBranch);
         while (fGeom->GetLevel()) {
            if (fGeom->GetCurrentVolume()->IsVisible()) 
               fGeom->GetCurrentVolume()->GetShape()->Sizeof3D();
            fGeom->CdUp();   
         }   
         break;
      default:
         return;
   }          
}
//______________________________________________________________________________
 void TGeoPainter::SetExplodedView(Int_t ibomb)    
{
   // set type of exploding view
   if ((ibomb<0) || (ibomb>3)) {
      Warning("SetExplodedView", "exploded view can be 0-3");
      return;
   }
   if ((Int_t)ibomb==fExplodedView) return;   
   Bool_t change = (gPad==0)?kFALSE:kTRUE;

   if (ibomb==kGeoNoBomb) {
      change &= ((fExplodedView==kGeoNoBomb)?kFALSE:kTRUE);
   }
   if (ibomb==kGeoBombXYZ) {
      change &= ((fExplodedView==kGeoBombXYZ)?kFALSE:kTRUE);
   }
   if (ibomb==kGeoBombCyl) {
      change &= ((fExplodedView==kGeoBombCyl)?kFALSE:kTRUE);
   }
   if (ibomb==kGeoBombSph) {
      change &= ((fExplodedView==kGeoBombSph)?kFALSE:kTRUE);
   }
   fExplodedView = ibomb;
   if (change && gPad->GetView()) {
      gPad->Modified();
      gPad->Update();
   }   
}
//______________________________________________________________________________
 void TGeoPainter::SetNsegments(Int_t nseg)    
{
// Set number of segments to approximate circles
   if (nseg<3) {
      Warning("SetNsegments", "number of segments should be > 2");
      return;
   }
   if (fNsegments==nseg) return;
   fNsegments = nseg;
   if (!gPad) return;
   if (gPad->GetView()) {    
      gPad->Modified();
      gPad->Update();
   }
}
//______________________________________________________________________________
 void TGeoPainter::SetVisLevel(Int_t level) {
// set default level down to which visualization is performed
   if (level<=0) {
      Warning("SetVisLevel", "visualization level should be >0");
      return;
   }   
   if (level==fVisLevel) return;
   fVisLevel=level;
   if (fVisLock) {
      fVisVolumes->Clear();
      fVisLock = kFALSE;
   }   
   if (!gPad) return;
   if (gPad->GetView()) {
      gPad->Modified();
      gPad->Update();
   }
}
//-----------------------------------------------------------------------------
 void TGeoPainter::SetTopVisible(Bool_t vis)
{
   if (fTopVisible==vis) return;
   fTopVisible = vis;
   if (!gPad) return;
   if (gPad->GetView()) {
      gPad->Modified();
      gPad->Update();
   }
}
   
//-----------------------------------------------------------------------------
 void TGeoPainter::SetVisOption(Int_t option) {
// set drawing mode :
// option=0 (default) all nodes drawn down to vislevel
// option=1           leaves and nodes at vislevel drawn
// option=2           path is drawn
   if ((fVisOption<0) || (fVisOption>3)) {
      Warning("SetVisOption", "wrong visualization option");
      return;
   }
   if (fVisOption==option) return;   
   fVisOption=option;
   if (fVisLock) {
      fVisVolumes->Clear();
      fVisLock = kFALSE;
   }   
   if (!gPad) return;
   if (gPad->GetView()) {
      gPad->Modified();
      gPad->Update();
   }
}
//-----------------------------------------------------------------------------
 Int_t TGeoPainter::ShapeDistancetoPrimitive(const TGeoShape *shape, Int_t numpoints, Int_t px, Int_t py) const   
{   
//  Returns distance between point px,py on the pad an a shape.
  Int_t dist = 9999;
   TView *view = gPad->GetView();
   if (!(numpoints && view)) return dist;
   Float_t *points = new Float_t[3*numpoints];
   shape->SetPoints(points);
   Float_t dpoint2, x1, y1, xndc[3];
   Double_t dlocal[3], dmaster[3];
   for (Int_t i=0; i<numpoints; i++) {
      dlocal[0]=points[3*i]; dlocal[1]=points[3*i+1]; dlocal[2]=points[3*i+2];
      if (fPaintingOverlaps) {
         fMatrix->LocalToMaster(&dlocal[0], &dmaster[0]);
      } else if (IsExplodedView())
         fGeom->LocalToMasterBomb(&dlocal[0], &dmaster[0]);
      else   
         fGeom->LocalToMaster(&dlocal[0], &dmaster[0]);
      points[3*i]=dmaster[0]; points[3*i+1]=dmaster[1]; points[3*i+2]=dmaster[2];
      view->WCtoNDC(&points[3*i], xndc);
      x1 = gPad->XtoAbsPixel(xndc[0]);
      y1 = gPad->YtoAbsPixel(xndc[1]);
      dpoint2 = (px-x1)*(px-x1) + (py-y1)*(py-y1);
      if (dpoint2 < dist) dist=(Int_t)dpoint2;
   }
   delete [] points;
   return Int_t(TMath::Sqrt(Float_t(dist)));
}
//______________________________________________________________________________
 void TGeoPainter::Test(Int_t npoints, Option_t *option)
{
// Check time of finding "Where am I" for n points.
   fChecker->Test(npoints, option);
}   
//-----------------------------------------------------------------------------
 void TGeoPainter::TestOverlaps(const char* path)
{
//--- Geometry overlap checker based on sampling. 
  fChecker->TestOverlaps(path);
}   
//______________________________________________________________________________
 Bool_t TGeoPainter::TestVoxels(TGeoVolume *vol)
{
// Check voxels efficiency per volume.
   return fChecker->TestVoxels(vol);
}   
//______________________________________________________________________________
 void TGeoPainter::UnbombTranslation(const Double_t *tr, Double_t *bombtr)
{
// get the new 'unbombed' translation vector according current exploded view mode
   memcpy(bombtr, tr, 3*sizeof(Double_t));
   switch (fExplodedView) {
      case kGeoNoBomb:
         return;
      case kGeoBombXYZ:
         bombtr[0] /= fBombX;
         bombtr[1] /= fBombY;
         bombtr[2] /= fBombZ;
         return;
      case kGeoBombCyl:
         bombtr[0] /= fBombR;
         bombtr[1] /= fBombR;
         bombtr[2] /= fBombZ;
         return;
      case kGeoBombSph:
         bombtr[0] /= fBombR;
         bombtr[1] /= fBombR;
         bombtr[2] /= fBombR;
         return;
      default:
         return;
   }   
}
   
//______________________________________________________________________________
 Double_t TGeoPainter::Weight(Double_t precision, Option_t *option)
{
   return fChecker->Weight(precision, option);
}
   
   


ROOT page - Class index - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.