TGeoPainter.cxx

Go to the documentation of this file.
00001 // @(#)root/geompainter:$Id: TGeoPainter.cxx 36535 2010-11-08 14:41:54Z agheata $
00002 // Author: Andrei Gheata   05/03/02
00003 /*************************************************************************
00004  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00005  * All rights reserved.                                                  *
00006  *                                                                       *
00007  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00008  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00009  *************************************************************************/
00010 
00011 //______________________________________________________________________________
00012 // TGeoPainter - class implementing all draw interfaces for a generic 3D viewer
00013 // using TBuffer3D mechanism.
00014 //______________________________________________________________________________
00015 
00016 #include "TROOT.h"
00017 #include "TClass.h"
00018 #include "TColor.h"
00019 #include "TPoint.h"
00020 #include "TView.h"
00021 #include "TAttLine.h"
00022 #include "TAttFill.h"
00023 #include "TPad.h"
00024 #include "TCanvas.h"
00025 #include "TH2F.h"
00026 #include "TF1.h"
00027 #include "TPluginManager.h"
00028 #include "TVirtualPadEditor.h"
00029 #include "TStopwatch.h"
00030 
00031 #include "TPolyMarker3D.h"
00032 #include "TVirtualGL.h"
00033 
00034 #include "TGeoAtt.h"
00035 #include "TGeoVolume.h"
00036 #include "TGeoNode.h"
00037 #include "TGeoManager.h"
00038 #include "TGeoTrack.h"
00039 #include "TGeoOverlap.h"
00040 #include "TGeoChecker.h"
00041 #include "TGeoPhysicalNode.h"
00042 #include "TGeoCompositeShape.h"
00043 #include "TGeoShapeAssembly.h"
00044 #include "TGeoPainter.h"
00045 #include "TMath.h"
00046 
00047 #include "X3DBuffer.h"
00048 
00049 #include "TBuffer3D.h"
00050 #include "TBuffer3DTypes.h"
00051 #include "TVirtualViewer3D.h"
00052 
00053 ClassImp(TGeoPainter)
00054 
00055 //______________________________________________________________________________
00056 TGeoPainter::TGeoPainter(TGeoManager *manager) : TVirtualGeoPainter(manager)
00057 {
00058 //*-*-*-*-*-*-*-*-*-*-*Geometry painter default constructor*-*-*-*-*-*-*-*-*
00059 //*-*                  ====================================
00060    TVirtualGeoPainter::SetPainter(this);
00061    if (manager) fGeoManager = manager;
00062    else {
00063       Error("ctor", "No geometry loaded");
00064       return;
00065    }   
00066    fNsegments = fGeoManager->GetNsegments();
00067    fNVisNodes = 0;
00068    fBombX = 1.3;
00069    fBombY = 1.3;
00070    fBombZ = 1.3;
00071    fBombR = 1.3;
00072    fVisLevel = fGeoManager->GetVisLevel();
00073    fVisOption = fGeoManager->GetVisOption();
00074    fExplodedView = fGeoManager->GetBombMode();
00075    fVisBranch = "";
00076    fVolInfo = "";
00077    fVisLock = kFALSE;
00078    fIsRaytracing = kFALSE;
00079    fTopVisible = kFALSE;
00080    fPaintingOverlaps = kFALSE;
00081    fPlugin = 0;
00082    fVisVolumes = new TObjArray();
00083    fOverlap = 0;
00084    fGlobal = new TGeoHMatrix();
00085    fBuffer = new TBuffer3D(TBuffer3DTypes::kGeneric,20,3*20,0,0,0,0);
00086    fClippingShape = 0;
00087    fLastVolume = 0;
00088    fTopVolume = 0;
00089    fIsPaintingShape = kFALSE;
00090    memset(&fCheckedBox[0], 0, 6*sizeof(Double_t));
00091    
00092    fCheckedNode = fGeoManager->GetTopNode();
00093    fChecker = new TGeoChecker(fGeoManager);
00094    fIsEditable = kFALSE;
00095    DefineColors();
00096 }
00097 //______________________________________________________________________________
00098 TGeoPainter::~TGeoPainter()
00099 {
00100 //*-*-*-*-*-*-*-*-*-*-*Geometry painter default destructor*-*-*-*-*-*-*-*-*
00101 //*-*                  ===================================
00102    if (fChecker) delete fChecker;
00103    delete fVisVolumes;
00104    delete fGlobal;
00105    delete fBuffer;
00106    if (fPlugin) delete fPlugin;
00107 }
00108 //______________________________________________________________________________
00109 void TGeoPainter::AddSize3D(Int_t numpoints, Int_t numsegs, Int_t numpolys)
00110 {
00111 //--- Add numpoints, numsegs, numpolys to the global 3D size.
00112    gSize3D.numPoints += numpoints;
00113    gSize3D.numSegs   += numsegs;
00114    gSize3D.numPolys  += numpolys;
00115 }      
00116 //______________________________________________________________________________
00117 TVirtualGeoTrack *TGeoPainter::AddTrack(Int_t id, Int_t pdgcode, TObject *particle)
00118 {
00119 // Create a primary TGeoTrack.
00120    return (TVirtualGeoTrack*)(new TGeoTrack(id,pdgcode,0,particle));
00121 }
00122 
00123 //______________________________________________________________________________
00124 void TGeoPainter::AddTrackPoint(Double_t *point, Double_t *box, Bool_t reset) 
00125 {
00126 // Average center of view of all painted tracklets and compute view box.
00127    static Int_t npoints = 0;
00128    static Double_t xmin[3] = {0,0,0};
00129    static Double_t xmax[3] = {0,0,0};
00130    Int_t i;
00131    if (reset) {
00132       memset(box, 0, 6*sizeof(Double_t));
00133       memset(xmin, 0, 3*sizeof(Double_t));
00134       memset(xmax, 0, 3*sizeof(Double_t));
00135       npoints = 0;
00136       return;
00137    }      
00138    if (npoints==0) {
00139       for (i=0; i<3; i++) xmin[i]=xmax[i]=0;
00140       npoints++;
00141    }
00142    npoints++;
00143    Double_t  ninv = 1./Double_t(npoints); 
00144    for (i=0; i<3; i++) {
00145       box[i] += ninv*(point[i]-box[i]);
00146       if (point[i]<xmin[i]) xmin[i]=point[i];
00147       if (point[i]>xmax[i]) xmax[i]=point[i];
00148       box[i+3] = 0.5*(xmax[i]-xmin[i]);
00149    } 
00150 }
00151    
00152 //______________________________________________________________________________
00153 void TGeoPainter::BombTranslation(const Double_t *tr, Double_t *bombtr)
00154 {
00155 // get the new 'bombed' translation vector according current exploded view mode
00156    memcpy(bombtr, tr, 3*sizeof(Double_t));
00157    switch (fExplodedView) {
00158       case kGeoNoBomb:
00159          return;
00160       case kGeoBombXYZ:
00161          bombtr[0] *= fBombX;
00162          bombtr[1] *= fBombY;
00163          bombtr[2] *= fBombZ;
00164          return;
00165       case kGeoBombCyl:
00166          bombtr[0] *= fBombR;
00167          bombtr[1] *= fBombR;
00168          bombtr[2] *= fBombZ;
00169          return;
00170       case kGeoBombSph:
00171          bombtr[0] *= fBombR;
00172          bombtr[1] *= fBombR;
00173          bombtr[2] *= fBombR;
00174          return;
00175       default:
00176          return;
00177    }   
00178 }
00179 
00180 //_____________________________________________________________________________
00181 void TGeoPainter::CheckBoundaryErrors(Int_t ntracks, Double_t radius)
00182 {
00183 // Check pushes and pulls needed to cross the next boundary with respect to the
00184 // position given by FindNextBoundary. If radius is not mentioned the full bounding
00185 // box will be sampled.
00186    fChecker->CheckBoundaryErrors(ntracks, radius);
00187 }   
00188 
00189 //_____________________________________________________________________________
00190 void TGeoPainter::CheckBoundaryReference(Int_t icheck)
00191 {
00192 // Check the boundary errors reference file created by CheckBoundaryErrors method.
00193 // The shape for which the crossing failed is drawn with the starting point in red
00194 // and the extrapolated point to boundary (+/- failing push/pull) in yellow.
00195    fChecker->CheckBoundaryReference(icheck);
00196 }   
00197 
00198 //______________________________________________________________________________
00199 void TGeoPainter::CheckGeometryFull(Bool_t checkoverlaps, Bool_t checkcrossings, Int_t ntracks, const Double_t *vertex)
00200 {
00201 // Geometry checking method (see: TGeoManager::CheckGeometry())
00202    fChecker->CheckGeometryFull(checkoverlaps,checkcrossings,ntracks,vertex);
00203 }   
00204 
00205 //______________________________________________________________________________
00206 void TGeoPainter::CheckGeometry(Int_t nrays, Double_t startx, Double_t starty, Double_t startz) const
00207 {
00208 // Geometry checking method (see TGeoChecker).
00209    fChecker->CheckGeometry(nrays, startx, starty, startz);
00210 }   
00211 
00212 //______________________________________________________________________________
00213 void TGeoPainter::CheckOverlaps(const TGeoVolume *vol, Double_t ovlp, Option_t *option) const
00214 {
00215 // Check overlaps for the top volume of the geometry, within a limit OVLP. 
00216    fChecker->CheckOverlaps(vol, ovlp, option);
00217 }
00218 
00219 //______________________________________________________________________________
00220 void TGeoPainter::CheckPoint(Double_t x, Double_t y, Double_t z, Option_t *option)
00221 {
00222 // check current point in the geometry
00223    fChecker->CheckPoint(x,y,z,option);
00224 }   
00225 
00226 //______________________________________________________________________________
00227 void TGeoPainter::ClearVisibleVolumes()
00228 {
00229    //Clear the list of visible volumes
00230    //reset the kVisOnScreen bit for volumes previously in the list
00231    
00232    if (!fVisVolumes) return;
00233    TIter next(fVisVolumes);
00234    TGeoVolume *vol;
00235    while ((vol = (TGeoVolume*)next())) {
00236       vol->ResetAttBit(TGeoAtt::kVisOnScreen);
00237    }
00238    fVisVolumes->Clear();
00239 }
00240       
00241       
00242 //______________________________________________________________________________
00243 void TGeoPainter::DefineColors() const
00244 {
00245 // Define 100 colors with increasing light intensities for each basic color (1-7)
00246 // Register these colors at indexes starting with 1000.
00247    TColor::InitializeColors();
00248    TColor *color = gROOT->GetColor(1000);
00249    if (color) return;
00250    Int_t i,j;
00251    Float_t r,g,b,h,l,s;
00252    
00253    for (i=1; i<8; i++) {
00254       color = (TColor*)gROOT->GetListOfColors()->At(i);
00255       if (!color) {
00256          Warning("DefineColors", "No colors defined");
00257          return;
00258       }         
00259       color->GetHLS(h,l,s);
00260       for (j=0; j<100; j++) {
00261          l = 0.25+0.5*j/99.;
00262          TColor::HLS2RGB(h,l,s,r,g,b);
00263          new TColor(1000+(i-1)*100+j, r,g,b);
00264       }
00265    }           
00266 }
00267 
00268 //______________________________________________________________________________
00269 Int_t TGeoPainter::GetColor(Int_t base, Float_t light) const
00270 {
00271 // Get index of a base color with given light intensity (0,1)
00272    const Int_t kBCols[8] = {1,2,3,5,4,6,7,1};
00273    TColor *tcolor = gROOT->GetColor(base);
00274    if (!tcolor) tcolor = new TColor(base, 0.5,0.5,0.5);
00275    Float_t r,g,b;
00276    tcolor->GetRGB(r,g,b);
00277    Int_t code = 0;
00278    if (r>0.5) code += 1;
00279    if (g>0.5) code += 2;
00280    if (b>0.5) code += 4;
00281    Int_t color, j;
00282    
00283    if (light<0.25) {
00284       j=0;
00285    } else {
00286       if (light>0.8) j=99;
00287       else j = Int_t(99*(light-0.25)/0.5);
00288    }   
00289    color = 1000 + (kBCols[code]-1)*100+j;
00290    return color;
00291 }
00292 
00293 //______________________________________________________________________________
00294 TGeoVolume *TGeoPainter::GetDrawnVolume() const
00295 {
00296 // Get currently drawn volume.
00297    if (!gPad) return 0;
00298    return fTopVolume;
00299 }         
00300  
00301 //______________________________________________________________________________
00302 Int_t TGeoPainter::DistanceToPrimitiveVol(TGeoVolume *volume, Int_t px, Int_t py)
00303 {
00304 // compute the closest distance of approach from point px,py to a volume 
00305    const Int_t big = 9999;
00306    const Int_t inaxis = 7;
00307    const Int_t maxdist = 5;
00308 
00309    if (fTopVolume != volume) fTopVolume = volume;
00310    TView *view = gPad->GetView();
00311    if (!view) return big;   
00312    TGeoBBox *box;
00313    fGlobal->Clear();
00314    TGeoShape::SetTransform(fGlobal);
00315 
00316    Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
00317    Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
00318    Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
00319    Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
00320    // return if point not in user area
00321    if (px < puxmin - inaxis) return big;
00322    if (py > puymin + inaxis) return big;
00323    if (px > puxmax + inaxis) return big;
00324    if (py < puymax - inaxis) return big;
00325    
00326    fCheckedNode = fGeoManager->GetTopNode();         
00327    gPad->SetSelected(view);
00328    Int_t dist = big;
00329 //   Int_t id;
00330    
00331    if (fPaintingOverlaps) {
00332       TGeoVolume *crt;
00333       crt = fOverlap->GetFirstVolume();
00334       *fGlobal = fOverlap->GetFirstMatrix();
00335       dist = crt->GetShape()->DistancetoPrimitive(px,py);
00336       if (dist<maxdist) {
00337          gPad->SetSelected(crt);
00338          box = (TGeoBBox*)crt->GetShape();
00339          fGlobal->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
00340          fCheckedBox[3] = box->GetDX();
00341          fCheckedBox[4] = box->GetDY();
00342          fCheckedBox[5] = box->GetDZ();
00343          return 0;
00344       }
00345       crt = fOverlap->GetSecondVolume();
00346       *fGlobal = fOverlap->GetSecondMatrix();
00347       dist = crt->GetShape()->DistancetoPrimitive(px,py);
00348       if (dist<maxdist) {
00349          gPad->SetSelected(crt);
00350          box = (TGeoBBox*)crt->GetShape();
00351          fGlobal->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
00352          fCheckedBox[3] = box->GetDX();
00353          fCheckedBox[4] = box->GetDY();
00354          fCheckedBox[5] = box->GetDZ();
00355          return 0;
00356       }      
00357       return big;
00358    }
00359       // Compute distance to the right edge
00360    if ((puxmax+inaxis-px) < 40) {
00361       if ((py-puymax+inaxis) < 40) {
00362          // when the mouse points to the (40x40) right corner of the pad, the manager class is selected
00363          gPad->SetSelected(fGeoManager);
00364          fVolInfo = fGeoManager->GetName();
00365          box = (TGeoBBox*)volume->GetShape();
00366          memcpy(fCheckedBox, box->GetOrigin(), 3*sizeof(Double_t));
00367          fCheckedBox[3] = box->GetDX();
00368          fCheckedBox[4] = box->GetDY();
00369          fCheckedBox[5] = box->GetDZ();
00370          return 0;
00371       }
00372       // when the mouse points to the (40 pix) right edge of the pad, the top volume is selected
00373       gPad->SetSelected(volume);
00374       fVolInfo = volume->GetName();
00375       box = (TGeoBBox*)volume->GetShape();
00376       memcpy(fCheckedBox, box->GetOrigin(), 3*sizeof(Double_t));
00377       fCheckedBox[3] = box->GetDX();
00378       fCheckedBox[4] = box->GetDY();
00379       fCheckedBox[5] = box->GetDZ();
00380       return 0;
00381    }   
00382 
00383    TGeoVolume *vol = volume;
00384    Bool_t vis = vol->IsVisible();
00385 //   Bool_t drawDaughters = kTRUE;
00386    // Do we need to check a branch only?
00387    if (volume->IsVisBranch()) {
00388       if (!fGeoManager->IsClosed()) return big;
00389       fGeoManager->PushPath();
00390       fGeoManager->cd(fVisBranch.Data());
00391       while (fGeoManager->GetLevel()) {
00392          vol = fGeoManager->GetCurrentVolume();
00393          *fGlobal = gGeoManager->GetCurrentMatrix();
00394          dist = vol->GetShape()->DistancetoPrimitive(px,py);
00395          if (dist<maxdist) {
00396             fVolInfo = fVisBranch;
00397             box = (TGeoBBox*)vol->GetShape();
00398             fGeoManager->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
00399             fCheckedNode = gGeoManager->GetCurrentNode();
00400             if (fGeoManager->IsNodeSelectable()) gPad->SetSelected(fCheckedNode);
00401             else gPad->SetSelected(vol);
00402             fCheckedBox[3] = box->GetDX();
00403             fCheckedBox[4] = box->GetDY();
00404             fCheckedBox[5] = box->GetDZ();
00405             fGeoManager->PopPath();
00406             return 0;
00407          }
00408          fGeoManager->CdUp();
00409       }
00410       fGeoManager->PopPath();
00411       return dist;
00412    }      
00413 
00414    // Do I need to look for the top volume ?
00415    if ((fTopVisible && vis) || !vol->GetNdaughters() || !vol->IsVisDaughters() || vol->IsVisOnly()) {
00416       dist = vol->GetShape()->DistancetoPrimitive(px,py);
00417       if (dist<maxdist) {
00418          fVolInfo = vol->GetName();
00419          gPad->SetSelected(vol);
00420          box = (TGeoBBox*)vol->GetShape();
00421          memcpy(fCheckedBox, box->GetOrigin(), 3*sizeof(Double_t));
00422          fCheckedBox[3] = box->GetDX();
00423          fCheckedBox[4] = box->GetDY();
00424          fCheckedBox[5] = box->GetDZ();
00425          return 0;
00426       }
00427       if (vol->IsVisOnly() || !vol->GetNdaughters() || !vol->IsVisDaughters())
00428          return dist;
00429    }      
00430 
00431    // Iterate the volume content
00432    TGeoIterator next(vol);
00433    next.SetTopName(TString::Format("%s_1",vol->GetName()));
00434    TGeoNode *daughter;
00435 
00436    Int_t level, nd;
00437    Bool_t last;
00438 
00439    while ((daughter=next())) {
00440       vol = daughter->GetVolume();
00441       level = next.GetLevel();
00442       nd = daughter->GetNdaughters();
00443       vis = daughter->IsVisible();
00444       if (volume->IsVisContainers()) {
00445          if (vis && level<=fVisLevel) {
00446             *fGlobal = next.GetCurrentMatrix();
00447             dist = vol->GetShape()->DistancetoPrimitive(px,py);
00448             if (dist<maxdist) {
00449                next.GetPath(fVolInfo);
00450                box = (TGeoBBox*)vol->GetShape();
00451                fGlobal->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
00452                fCheckedNode = daughter;
00453                if (fGeoManager->IsNodeSelectable()) gPad->SetSelected(fCheckedNode);
00454                else gPad->SetSelected(vol);
00455                fCheckedBox[3] = box->GetDX();
00456                fCheckedBox[4] = box->GetDY();
00457                fCheckedBox[5] = box->GetDZ();
00458                fGeoManager->PopPath();
00459                return 0;
00460             }
00461          }   
00462          // Check if we have to skip this branch
00463          if (level==fVisLevel || !daughter->IsVisDaughters()) {
00464             next.Skip();
00465             continue;
00466          }   
00467       } else if (volume->IsVisLeaves()) {
00468          last = ((nd==0) || (level==fVisLevel) || (!daughter->IsVisDaughters()))?kTRUE:kFALSE;
00469          if (vis && last) {
00470             *fGlobal = next.GetCurrentMatrix();
00471             dist = vol->GetShape()->DistancetoPrimitive(px,py);
00472             if (dist<maxdist) {
00473                next.GetPath(fVolInfo);
00474                box = (TGeoBBox*)vol->GetShape();
00475                fGlobal->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
00476                fCheckedNode = daughter;
00477                if (fGeoManager->IsNodeSelectable()) gPad->SetSelected(fCheckedNode);
00478                else gPad->SetSelected(vol);
00479                fCheckedBox[3] = box->GetDX();
00480                fCheckedBox[4] = box->GetDY();
00481                fCheckedBox[5] = box->GetDZ();
00482                fGeoManager->PopPath();
00483                return 0;
00484             }
00485          }
00486          // Check if we have to skip the branch
00487          if (last || !daughter->IsVisDaughters()) next.Skip();
00488       }
00489    }
00490    return dist;
00491 }
00492 
00493 //______________________________________________________________________________
00494 void TGeoPainter::DefaultAngles()
00495 {   
00496 // Set default angles for the current view.
00497    if (gPad) {
00498       Int_t irep;
00499       TView *view = gPad->GetView();
00500       if (!view) return;
00501       view->SetView(-206,126,75,irep);
00502       ModifiedPad();
00503    }
00504 }   
00505 
00506 //______________________________________________________________________________
00507 void TGeoPainter::DefaultColors()
00508 {   
00509 // Set default volume colors according to tracking media
00510    TIter next(fGeoManager->GetListOfVolumes());
00511    TGeoVolume *vol;
00512    while ((vol=(TGeoVolume*)next()))
00513       vol->SetLineColor(vol->GetMaterial()->GetDefaultColor());
00514    ModifiedPad();
00515 }   
00516 
00517 //______________________________________________________________________________
00518 Int_t TGeoPainter::CountNodes(TGeoVolume *volume, Int_t rlevel) const
00519 {
00520 // Count number of visible nodes down to a given level.
00521    TGeoVolume *vol = volume;
00522    Int_t count = 0;
00523    Bool_t vis = vol->IsVisible();
00524    // Do I need to look for the top volume ?
00525    if ((fTopVisible && vis) || !vol->GetNdaughters() || !vol->IsVisDaughters() || vol->IsVisOnly()) 
00526       count++;
00527    // Is this the only volume?
00528    if (volume->IsVisOnly()) return count;
00529 
00530    // Do we need to check a branch only?
00531    if (volume->IsVisBranch()) {
00532       fGeoManager->PushPath();
00533       fGeoManager->cd(fVisBranch.Data());
00534       count = fGeoManager->GetLevel() + 1;
00535       fGeoManager->PopPath();
00536       return count;
00537    }
00538    // Iterate the volume content
00539    TGeoIterator next(vol);
00540    TGeoNode *daughter;
00541    Int_t level, nd;
00542    Bool_t last;
00543       
00544    while ((daughter=next())) {
00545 //      vol = daughter->GetVolume();
00546       level = next.GetLevel();
00547       nd = daughter->GetNdaughters();
00548       vis = daughter->IsVisible();
00549       if (volume->IsVisContainers()) {
00550          if (vis && level<=rlevel) count++;
00551          // Check if we have to skip this branch
00552          if (level==rlevel || !daughter->IsVisDaughters()) {
00553             next.Skip();
00554             continue;
00555          }   
00556       } else if (volume->IsVisLeaves()) {
00557          last = ((nd==0) || (level==rlevel) || (!daughter->IsVisDaughters()))?kTRUE:kFALSE;
00558          if (vis && last) count++;
00559          // Check if we have to skip the branch
00560          if (last) next.Skip();
00561       }
00562    }      
00563    return count;    
00564 }   
00565 
00566 //______________________________________________________________________________
00567 Int_t TGeoPainter::CountVisibleNodes()
00568 {
00569 // Count total number of visible nodes.
00570    Int_t maxnodes = fGeoManager->GetMaxVisNodes(); 
00571    Int_t vislevel = fGeoManager->GetVisLevel();
00572 //   TGeoVolume *top = fGeoManager->GetTopVolume();
00573    TGeoVolume *top = fTopVolume;
00574    if (maxnodes <= 0  && top) {
00575       fNVisNodes = CountNodes(top, vislevel);
00576       SetVisLevel(vislevel);
00577       return fNVisNodes;
00578    }   
00579    //if (the total number of nodes of the top volume is less than maxnodes
00580    // we can visualize everything.
00581    //recompute the best visibility level
00582    if (!top) {
00583       SetVisLevel(vislevel);
00584       return 0;
00585    }   
00586    fNVisNodes = -1;
00587    Bool_t again = kFALSE;
00588    for (Int_t level = 1;level<20;level++) {
00589       vislevel = level;
00590       Int_t nnodes = CountNodes(top, level);
00591       if (top->IsVisOnly() || top->IsVisBranch()) {
00592          vislevel = fVisLevel;
00593          fNVisNodes = nnodes;
00594          break;
00595       }   
00596       if (nnodes > maxnodes) {
00597          vislevel--;
00598          break;
00599       }
00600       if (nnodes == fNVisNodes) {
00601          if (again) break;
00602          again = kTRUE;
00603       }   
00604       fNVisNodes = nnodes;
00605    }
00606    SetVisLevel(vislevel);
00607    return fNVisNodes;
00608 }
00609 
00610 //______________________________________________________________________________
00611 void TGeoPainter::CheckEdit()
00612 {
00613 // Check if Ged library is loaded and load geometry editor classe.
00614    if (fIsEditable) return;
00615    if (!TClass::GetClass("TGedEditor")) return;
00616    TPluginHandler *h;
00617    if ((h = gROOT->GetPluginManager()->FindHandler("TGeoManagerEditor"))) {
00618       if (h->LoadPlugin() == -1) return;
00619       h->ExecPlugin(0);
00620    }
00621    fIsEditable = kTRUE;
00622 }      
00623 
00624 //______________________________________________________________________________
00625 void TGeoPainter::EditGeometry(Option_t *option)
00626 {
00627 // Start the geometry editor.
00628    if (!gPad) return;
00629    if (!fIsEditable) {
00630       if (!strlen(option)) gPad->GetCanvas()->GetCanvasImp()->ShowEditor();
00631       else TVirtualPadEditor::ShowEditor();
00632       CheckEdit();
00633    }   
00634    gPad->SetSelected(fGeoManager);
00635    gPad->GetCanvas()->Selected(gPad,fGeoManager,kButton1Down);   
00636 }
00637 
00638 //______________________________________________________________________________
00639 void TGeoPainter::Draw(Option_t *option)
00640 {
00641 // Draw method.
00642    DrawVolume(fGeoManager->GetTopVolume(), option);
00643 }
00644 
00645 //______________________________________________________________________________
00646 void TGeoPainter::DrawBatemanSol(TGeoBatemanSol *sol, Option_t *option)
00647 {
00648 // Draw the time evolution of a radionuclide.
00649    Int_t ncoeff = sol->GetNcoeff();
00650    if (!ncoeff) return;
00651    Double_t tlo=0., thi=0.;
00652    Double_t cn=0., lambda=0.;
00653    Int_t i;
00654    sol->GetRange(tlo, thi);
00655    Bool_t autorange = (thi==0.)?kTRUE:kFALSE;
00656    
00657    // Try to find the optimum range in time.
00658    if (autorange) tlo = 0.;
00659    sol->GetCoeff(0, cn, lambda);
00660    Double_t lambdamin = lambda;
00661    TString formula = "";
00662    for (i=0; i<ncoeff; i++) {
00663       sol->GetCoeff(i, cn, lambda);
00664       formula += TString::Format("%g*exp(-%g*x)",cn, lambda);
00665       if (i < ncoeff-1) formula += "+";
00666       if (lambda < lambdamin &&
00667           lambda > 0.) lambdamin = lambda;
00668    }
00669    if (autorange) thi = 10./lambdamin;
00670    formula += ";time[s]";
00671    formula += TString::Format(";Concentration_of_%s",sol->GetElement()->GetName());
00672    // Create a function
00673    TF1 *func = new TF1(TString::Format("conc%s",sol->GetElement()->GetName()), formula.Data(), tlo,thi);
00674    func->SetMinimum(1.e-3);
00675    func->SetMaximum(1.25*TMath::Max(sol->Concentration(tlo), sol->Concentration(thi)));
00676    func->SetLineColor(sol->GetLineColor());
00677    func->SetLineStyle(sol->GetLineStyle());
00678    func->SetLineWidth(sol->GetLineWidth());
00679    func->SetMarkerColor(sol->GetMarkerColor());
00680    func->SetMarkerStyle(sol->GetMarkerStyle());
00681    func->SetMarkerSize(sol->GetMarkerSize());
00682    func->Draw(option);
00683 }   
00684 
00685 //______________________________________________________________________________
00686 void TGeoPainter::DrawVolume(TGeoVolume *vol, Option_t *option)
00687 {
00688 // Draw method.
00689    fTopVolume = vol;
00690    fLastVolume = 0;
00691    fIsPaintingShape = kFALSE;
00692 //   if (fVisOption==kGeoVisOnly ||
00693 //       fVisOption==kGeoVisBranch) fGeoManager->SetVisOption(kGeoVisLeaves);
00694    CountVisibleNodes();         
00695    TString opt = option;
00696    opt.ToLower();
00697    fPaintingOverlaps = kFALSE;
00698    fOverlap = 0;
00699    
00700    if (fVisLock) {
00701       ClearVisibleVolumes();
00702       fVisLock = kFALSE;
00703    }   
00704    Bool_t has_pad = (gPad==0)?kFALSE:kTRUE;
00705    // Clear pad if option "same" not given
00706    if (!gPad) {
00707       gROOT->MakeDefCanvas();
00708    }
00709    if (!opt.Contains("same")) gPad->Clear();
00710    // append this volume to pad
00711    fTopVolume->AppendPad(option);
00712 
00713    // Create a 3-D view
00714    TView *view = gPad->GetView();
00715    if (!view) {
00716       view = TView::CreateView(11,0,0);
00717       // Set the view to perform a first autorange (frame) draw. 
00718       // TViewer3DPad will revert view to normal painting after this
00719       view->SetAutoRange(kTRUE);
00720       if (has_pad) gPad->Update();
00721    }
00722    Paint("range"); 
00723    view->SetAutoRange(kFALSE);    
00724    // If we are drawing into the pad, then the view needs to be
00725    // set to perspective
00726 //   if (!view->IsPerspective()) view->SetPerspective();
00727    
00728    fLastVolume = fTopVolume;
00729  
00730          // Create a 3D viewer to paint us
00731    gPad->GetViewer3D(option);
00732 }
00733 
00734 //______________________________________________________________________________
00735 void TGeoPainter::DrawShape(TGeoShape *shape, Option_t *option)
00736 {
00737 // Draw a shape.
00738    TString opt = option;
00739    opt.ToLower();
00740    fPaintingOverlaps = kFALSE;
00741    fOverlap = 0;
00742    fIsPaintingShape = kTRUE;
00743    
00744    Bool_t has_pad = (gPad==0)?kFALSE:kTRUE;
00745    // Clear pad if option "same" not given
00746    if (!gPad) {
00747       gROOT->MakeDefCanvas();
00748    }
00749    if (!opt.Contains("same")) gPad->Clear();
00750    // append this shape to pad
00751    shape->AppendPad(option);
00752 
00753    // Create a 3-D view
00754    TView *view = gPad->GetView();
00755    if (!view) {
00756       view = TView::CreateView(11,0,0);
00757       // Set the view to perform a first autorange (frame) draw. 
00758       // TViewer3DPad will revert view to normal painting after this
00759       view->SetAutoRange(kTRUE);
00760       if (has_pad) gPad->Update();
00761    }
00762    PaintShape(shape,"range");   
00763    view->SetAutoRange(kTRUE);   
00764    // Create a 3D viewer to paint us
00765    gPad->GetViewer3D(option);
00766 }
00767 
00768 //______________________________________________________________________________
00769 void TGeoPainter::DrawOverlap(void *ovlp, Option_t *option)
00770 {
00771 // Draw an overlap.
00772    TString opt = option;
00773    fIsPaintingShape = kFALSE;
00774    TGeoOverlap *overlap = (TGeoOverlap*)ovlp;
00775    if (!overlap) return;
00776    
00777    fPaintingOverlaps = kTRUE;
00778    fOverlap = overlap;
00779    opt.ToLower();
00780    if (fVisLock) {
00781       ClearVisibleVolumes();
00782       fVisLock = kFALSE;
00783    }   
00784    Bool_t has_pad = (gPad==0)?kFALSE:kTRUE;
00785    // Clear pad if option "same" not given
00786    if (!gPad) {
00787       gROOT->MakeDefCanvas();
00788    }
00789    if (!opt.Contains("same")) gPad->Clear();
00790    // append this volume to pad
00791    overlap->AppendPad(option);
00792 
00793    // Create a 3-D view
00794          // Create a 3D viewer to paint us
00795    gPad->GetViewer3D(option);
00796    TView *view = gPad->GetView();
00797    if (!view) {
00798       view = TView::CreateView(11,0,0);
00799       // Set the view to perform a first autorange (frame) draw. 
00800       // TViewer3DPad will revert view to normal painting after this
00801       view->SetAutoRange(kTRUE);
00802       PaintOverlap(ovlp, "range");
00803       overlap->GetPolyMarker()->Draw("SAME");
00804       if (has_pad) gPad->Update();
00805    }
00806 
00807    // If we are drawing into the pad, then the view needs to be
00808    // set to perspective
00809 //   if (!view->IsPerspective()) view->SetPerspective();
00810    fVisLock = kTRUE;
00811 }
00812 
00813 
00814 //______________________________________________________________________________
00815 void TGeoPainter::DrawOnly(Option_t *option)
00816 {
00817 // Draw only one volume.
00818    TString opt = option;
00819    opt.ToLower();
00820    if (fVisLock) {
00821       ClearVisibleVolumes();
00822       fVisLock = kFALSE;
00823    }   
00824    fPaintingOverlaps = kFALSE;
00825    fIsPaintingShape = kFALSE;
00826    Bool_t has_pad = (gPad==0)?kFALSE:kTRUE;
00827    // Clear pad if option "same" not given
00828    if (!gPad) {
00829       gROOT->MakeDefCanvas();
00830    }
00831    if (!opt.Contains("same")) gPad->Clear();
00832    // append this volume to pad
00833    fTopVolume = fGeoManager->GetCurrentVolume();
00834    fTopVolume->AppendPad(option);
00835 
00836    // Create a 3-D view
00837    TView *view = gPad->GetView();
00838    if (!view) {
00839       view = TView::CreateView(11,0,0);
00840       // Set the view to perform a first autorange (frame) draw. 
00841       // TViewer3DPad will revert view to normal painting after this
00842       view->SetAutoRange(kTRUE);
00843       fVisOption = kGeoVisOnly;
00844       if (has_pad) gPad->Update();
00845    }
00846 
00847    // If we are drawing into the pad, then the view needs to be
00848    // set to perspective
00849 //   if (!view->IsPerspective()) view->SetPerspective();
00850    fVisLock = kTRUE;
00851 }
00852 
00853 //______________________________________________________________________________
00854 void TGeoPainter::DrawCurrentPoint(Int_t color)
00855 {
00856 // Draw current point in the same view.
00857    if (!gPad) return;
00858    if (!gPad->GetView()) return;
00859    TPolyMarker3D *pm = new TPolyMarker3D();
00860    pm->SetMarkerColor(color);
00861    const Double_t *point = fGeoManager->GetCurrentPoint();
00862    pm->SetNextPoint(point[0], point[1], point[2]);
00863    pm->SetMarkerStyle(8);
00864    pm->SetMarkerSize(0.5);
00865    pm->Draw("SAME");
00866 }
00867 
00868 //______________________________________________________________________________
00869 void TGeoPainter::DrawPanel()
00870 {
00871 }
00872 
00873 //______________________________________________________________________________
00874 void TGeoPainter::DrawPath(const char *path)
00875 {
00876 // Draw all volumes for a given path.
00877    fVisOption=kGeoVisBranch;
00878    fVisBranch=path; 
00879    fIsPaintingShape = kFALSE;
00880    fTopVolume = fGeoManager->GetTopVolume();
00881    fTopVolume->SetVisRaytrace(kFALSE);
00882    DrawVolume(fTopVolume,"");   
00883 }
00884 
00885 //______________________________________________________________________________
00886 void TGeoPainter::EstimateCameraMove(Double_t tmin, Double_t tmax, Double_t *start, Double_t *end)
00887 {
00888 // Estimate camera movement between tmin and tmax for best track display
00889    if (!gPad) return;
00890    TIter next(gPad->GetListOfPrimitives());
00891    TVirtualGeoTrack *track;
00892    TObject *obj;
00893    Int_t ntracks = 0;
00894    Double_t *point = 0;
00895    AddTrackPoint(point, start, kTRUE);
00896    while ((obj=next())) {
00897       if (strcmp(obj->ClassName(), "TGeoTrack")) continue;
00898       track = (TVirtualGeoTrack*)obj;
00899       ntracks++;
00900       track->PaintCollect(tmin, start);
00901    }
00902    
00903    if (!ntracks) return;
00904    next.Reset();
00905    AddTrackPoint(point, end, kTRUE);
00906    while ((obj=next())) {
00907       if (strcmp(obj->ClassName(), "TGeoTrack")) continue;
00908       track = (TVirtualGeoTrack*)obj;
00909       if (!track) continue;
00910       track->PaintCollect(tmax, end);
00911    }   
00912 }
00913 
00914 //______________________________________________________________________________
00915 void TGeoPainter::ExecuteManagerEvent(TGeoManager * /*geom*/, Int_t event, Int_t /*px*/, Int_t /*py*/)
00916 {
00917 // Execute mouse actions on a given volume.
00918    if (!gPad) return;
00919    gPad->SetCursor(kPointer);
00920    switch (event) {
00921       case kButton1Down:
00922          if (!fIsEditable) CheckEdit();
00923    }          
00924 }
00925    
00926 //______________________________________________________________________________
00927 void TGeoPainter::ExecuteShapeEvent(TGeoShape * /*shape*/, Int_t event, Int_t /*px*/, Int_t /*py*/)
00928 {
00929 // Execute mouse actions on a given shape.
00930    if (!gPad) return;
00931    gPad->SetCursor(kHand);
00932    switch (event) {
00933       case kButton1Down:
00934          if (!fIsEditable) CheckEdit();
00935    }      
00936 }
00937 
00938 //______________________________________________________________________________
00939 void TGeoPainter::ExecuteVolumeEvent(TGeoVolume * /*volume*/, Int_t event, Int_t /*px*/, Int_t /*py*/)
00940 {
00941 // Execute mouse actions on a given volume.
00942    if (!gPad) return;
00943    if (!fIsEditable) CheckEdit();
00944 //   if (fIsRaytracing) return;
00945 //   Bool_t istop = (volume==fTopVolume)?kTRUE:kFALSE;
00946 //   if (istop) gPad->SetCursor(kHand);
00947 //   else gPad->SetCursor(kPointer);
00948    gPad->SetCursor(kHand);
00949 //   static Int_t width, color;
00950    switch (event) {
00951    case kMouseEnter:
00952 //      width = volume->GetLineWidth();
00953 //      color = volume->GetLineColor();
00954       break;
00955    
00956    case kMouseLeave:
00957 //      volume->SetLineWidth(width);
00958 //      volume->SetLineColor(color);
00959       break;
00960 
00961    case kButton1Down:
00962 //      volume->SetLineWidth(3);
00963 //      volume->SetLineColor(2);
00964 //      gPad->Modified();
00965 //      gPad->Update();
00966       break;
00967    
00968    case kButton1Up:
00969 //      volume->SetLineWidth(width);
00970 //      volume->SetLineColor(color);
00971 //      gPad->Modified();
00972 //      gPad->Update();
00973       break;
00974       
00975    case kButton1Double:
00976       gPad->SetCursor(kWatch);
00977       GrabFocus();
00978       break;
00979    }
00980 }
00981 
00982 //______________________________________________________________________________
00983 const char *TGeoPainter::GetVolumeInfo(const TGeoVolume *volume, Int_t /*px*/, Int_t /*py*/) const
00984 {
00985 // Get some info about the current selected volume.
00986    static TString info;
00987    info = "";
00988    if (!gPad) return info;
00989    if (fPaintingOverlaps) {
00990       if (!fOverlap) {
00991          info =  "wrong overlapping flag";
00992          return info;
00993       }   
00994       TString ovtype, name;
00995       if (fOverlap->IsExtrusion()) ovtype="EXTRUSION";
00996       else ovtype = "OVERLAP";
00997       if (volume==fOverlap->GetFirstVolume()) name=volume->GetName();
00998       else name=fOverlap->GetSecondVolume()->GetName();
00999       info = TString::Format("%s: %s of %g", name.Data(), ovtype.Data(), fOverlap->GetOverlap());
01000       return info;
01001    }   
01002    else info = TString::Format("%s, shape=%s", fVolInfo.Data(), volume->GetShape()->ClassName());
01003    return info;
01004 }
01005 
01006 //______________________________________________________________________________
01007 TGeoChecker *TGeoPainter::GetChecker()
01008 {
01009 // Create/return geometry checker.
01010    if (!fChecker) fChecker = new TGeoChecker(fGeoManager);
01011    return fChecker;
01012 }
01013  
01014 //______________________________________________________________________________
01015 void TGeoPainter::GetViewAngles(Double_t &longitude, Double_t &latitude, Double_t &psi) 
01016 {
01017 // Get the current view angles.
01018    if (!gPad) return;
01019    TView *view = gPad->GetView();
01020    if (!view) return;
01021    longitude = view->GetLongitude();
01022    latitude = view->GetLatitude();
01023    psi = view->GetPsi();
01024 }   
01025 
01026 //______________________________________________________________________________
01027 void TGeoPainter::GrabFocus(Int_t nfr, Double_t dlong, Double_t dlat, Double_t dpsi)
01028 {
01029 // Move focus to current volume
01030    if (!gPad) return;
01031    TView *view = gPad->GetView();
01032    if (!view) return;
01033    if (!fCheckedNode && !fPaintingOverlaps) {
01034       printf("Woops!!!\n");
01035       TGeoBBox *box = (TGeoBBox*)fGeoManager->GetTopVolume()->GetShape();
01036       memcpy(&fCheckedBox[0], box->GetOrigin(), 3*sizeof(Double_t));
01037       fCheckedBox[3] = box->GetDX();
01038       fCheckedBox[4] = box->GetDY();
01039       fCheckedBox[5] = box->GetDZ();
01040    }      
01041    view->SetPerspective();
01042    Int_t nvols = fVisVolumes->GetEntriesFast();
01043    Int_t nframes = nfr;
01044    if (nfr==0) {
01045       nframes = 1;
01046       if (nvols<1500) nframes=10;
01047       if (nvols<1000) nframes=20;
01048       if (nvols<200) nframes = 50;
01049       if (nvols<100) nframes = 100;
01050    }   
01051    view->MoveFocus(&fCheckedBox[0], fCheckedBox[3], fCheckedBox[4], fCheckedBox[5], nframes, dlong, dlat, dpsi);
01052 }
01053 
01054 //______________________________________________________________________________
01055 TH2F *TGeoPainter::LegoPlot(Int_t ntheta, Double_t themin, Double_t themax,
01056                             Int_t nphi,   Double_t phimin, Double_t phimax,
01057                             Double_t rmin, Double_t rmax, Option_t *option)
01058 {
01059 // Generate a lego plot fot the top volume, according to option.
01060    return fChecker->LegoPlot(ntheta, themin, themax, nphi, phimin, phimax, rmin, rmax, option);   
01061 }
01062 //______________________________________________________________________________
01063 void TGeoPainter::LocalToMasterVect(const Double_t *local, Double_t *master) const
01064 {
01065 // Convert a local vector according view rotation matrix
01066    for (Int_t i=0; i<3; i++)
01067       master[i] = -local[0]*fMat[i]-local[1]*fMat[i+3]-local[2]*fMat[i+6];
01068 }
01069 
01070 //______________________________________________________________________________
01071 void TGeoPainter::ModifiedPad(Bool_t update) const
01072 {
01073 // Check if a pad and view are present and send signal "Modified" to pad.
01074    if (!gPad) return;
01075    if (update) {
01076       gPad->Update();
01077       return;
01078    }   
01079    TView *view = gPad->GetView();
01080    if (!view) return;
01081    view->SetViewChanged();
01082    gPad->Modified();
01083    if (gROOT->FromPopUp()) gPad->Update();
01084 }   
01085 
01086 //______________________________________________________________________________
01087 void TGeoPainter::Paint(Option_t *option)
01088 {
01089 // Paint current geometry according to option.
01090    if (!fGeoManager || !fTopVolume) return;
01091    Bool_t is_padviewer = kTRUE;
01092    if (gPad) is_padviewer = (!strcmp(gPad->GetViewer3D()->ClassName(),"TViewer3DPad"))?kTRUE:kFALSE;
01093    
01094    fIsRaytracing = fTopVolume->IsRaytracing();
01095    if (fTopVolume->IsVisContainers()) fVisOption = kGeoVisDefault;
01096    else if (fTopVolume->IsVisLeaves()) fVisOption = kGeoVisLeaves;
01097    else if (fTopVolume->IsVisOnly()) fVisOption = kGeoVisOnly;
01098    else if (fTopVolume->IsVisBranch()) fVisOption = kGeoVisBranch;
01099    
01100    
01101    if (!fIsRaytracing || !is_padviewer) {
01102       if (fGeoManager->IsDrawingExtra()) {
01103          // loop the list of physical volumes
01104          fGeoManager->CdTop();
01105          TObjArray *nodeList = fGeoManager->GetListOfPhysicalNodes();
01106          Int_t nnodes = nodeList->GetEntriesFast();
01107          Int_t inode;
01108          TGeoPhysicalNode *node;
01109          for (inode=0; inode<nnodes; inode++) {
01110             node = (TGeoPhysicalNode*)nodeList->UncheckedAt(inode);
01111             PaintPhysicalNode(node, option);
01112          }
01113       } else {
01114          PaintVolume(fTopVolume,option);
01115       }                      
01116       fVisLock = kTRUE;
01117    } 
01118    // Check if we have to raytrace (only in pad)  
01119    if (fIsRaytracing && is_padviewer) Raytrace();
01120 }
01121 
01122 //______________________________________________________________________________
01123 void TGeoPainter::PaintOverlap(void *ovlp, Option_t *option)
01124 {
01125 // Paint an overlap.
01126    if (!fGeoManager) return;
01127    TGeoOverlap *overlap = (TGeoOverlap *)ovlp;
01128    if (!overlap) return;
01129    Int_t color, transparency;
01130    if (fOverlap != overlap) fOverlap = overlap;
01131    TGeoShape::SetTransform(fGlobal);
01132    TGeoHMatrix *hmat = fGlobal;
01133    TGeoVolume *vol;
01134    TGeoVolume *vol1 = overlap->GetFirstVolume();
01135    TGeoVolume *vol2 = overlap->GetSecondVolume();
01136    TGeoHMatrix *matrix1 = overlap->GetFirstMatrix();
01137    TGeoHMatrix *matrix2 = overlap->GetSecondMatrix();
01138    //
01139    vol = vol1;
01140    *hmat = matrix1;
01141    fGeoManager->SetMatrixReflection(matrix1->IsReflection());
01142    if (!fVisLock) fVisVolumes->Add(vol);
01143    fGeoManager->SetPaintVolume(vol);
01144    color = vol->GetLineColor();
01145    transparency = vol->GetTransparency();
01146    vol->SetLineColor(kGreen);
01147    vol->SetTransparency(40);
01148    if (!strstr(option,"range")) ((TAttLine*)vol)->Modify();
01149    PaintShape(*(vol->GetShape()),option);
01150    vol->SetLineColor(color);
01151    vol->SetTransparency(transparency);
01152    vol = vol2;
01153    *hmat = matrix2;
01154    fGeoManager->SetMatrixReflection(matrix2->IsReflection());
01155    if (!fVisLock) fVisVolumes->Add(vol);
01156    fGeoManager->SetPaintVolume(vol);
01157    color = vol->GetLineColor();
01158    transparency = vol->GetTransparency();
01159    vol->SetLineColor(kBlue);
01160    vol->SetTransparency(40);
01161    if (!strstr(option,"range")) ((TAttLine*)vol)->Modify();
01162    PaintShape(*(vol->GetShape()),option);
01163    vol->SetLineColor(color);
01164    vol->SetTransparency(transparency);
01165    fGeoManager->SetMatrixReflection(kFALSE);
01166    fVisLock = kTRUE;
01167 }
01168 
01169 //______________________________________________________________________________
01170 void TGeoPainter::PaintNode(TGeoNode *node, Option_t *option, TGeoMatrix* global)
01171 {
01172 // Paint recursively a node and its content accordind to visualization options.
01173    PaintVolume(node->GetVolume(), option, global);
01174 } 
01175 
01176 //______________________________________________________________________________
01177 void TGeoPainter::PaintVolume(TGeoVolume *top, Option_t *option, TGeoMatrix* global)
01178 {
01179 // Paint recursively a node and its content accordind to visualization options.
01180    if (fTopVolume != top) {
01181       ClearVisibleVolumes();
01182       fVisLock = kFALSE;
01183    }   
01184    fTopVolume = top;
01185    if (!fVisLevel) return;
01186    TGeoVolume *vol = top;
01187    if(global)
01188       *fGlobal = *global;
01189    else
01190       fGlobal->Clear();
01191    TGeoShape::SetTransform(fGlobal);
01192    Bool_t drawDaughters = kTRUE;
01193    Bool_t vis = (top->IsVisible() && !top->IsAssembly());
01194 
01195    // Update pad attributes in case we need to paint VOL
01196    if (!strstr(option,"range")) ((TAttLine*)vol)->Modify();
01197 
01198    // Do we need to draw a branch ?
01199    if (top->IsVisBranch()) {
01200       fGeoManager->PushPath();
01201       fGeoManager->cd(fVisBranch.Data());
01202       Int_t transparency;
01203       while (fGeoManager->GetLevel()) {
01204          vol = fGeoManager->GetCurrentVolume();
01205          if (!fVisLock) {
01206             fVisVolumes->Add(vol);
01207             vol->SetAttBit(TGeoAtt::kVisOnScreen);
01208          }   
01209          fGeoManager->SetPaintVolume(vol);
01210          transparency = vol->GetTransparency();
01211          vol->SetTransparency(40);
01212          if (!strstr(option,"range")) ((TAttLine*)vol)->Modify();
01213          if (global) {
01214             *fGlobal  = *global;
01215             *fGlobal *= *fGeoManager->GetCurrentMatrix();
01216          } else {
01217             *fGlobal = fGeoManager->GetCurrentMatrix();
01218          }
01219          fGeoManager->SetMatrixReflection(fGlobal->IsReflection());
01220          PaintShape(*(vol->GetShape()),option);
01221          vol->SetTransparency(transparency);
01222          fGeoManager->CdUp();
01223       }
01224       fVisLock = kTRUE;   
01225       fGeoManager->PopPath();
01226       fGeoManager->SetMatrixReflection(kFALSE);
01227       return;
01228    }   
01229       
01230    // Do I need to draw the top volume ?
01231    if ((fTopVisible && vis) || !top->GetNdaughters() || !top->IsVisDaughters() || top->IsVisOnly()) {
01232       fGeoManager->SetPaintVolume(vol);
01233       fGeoManager->SetMatrixReflection(fGlobal->IsReflection());
01234       drawDaughters = PaintShape(*(vol->GetShape()),option);
01235       if (!fVisLock && !vol->TestAttBit(TGeoAtt::kVisOnScreen)) {
01236          fVisVolumes->Add(vol);
01237          vol->SetAttBit(TGeoAtt::kVisOnScreen);
01238       } 
01239       if (top->IsVisOnly() || !top->GetNdaughters() || !top->IsVisDaughters()) {
01240          fVisLock = kTRUE;
01241          return;
01242       }    
01243    }   
01244 
01245    // Iterate the volume content
01246    TGeoIterator next(vol);
01247    if (fPlugin) next.SetUserPlugin(fPlugin);
01248    TGeoNode *daughter;
01249 //   TGeoMatrix *glmat;
01250    Int_t level, nd;
01251    Bool_t last;
01252    Int_t line_color=0, line_width=0, line_style=0;
01253    while ((daughter=next())) {
01254       vol = daughter->GetVolume();
01255       fGeoManager->SetPaintVolume(vol);
01256       level = next.GetLevel();
01257       nd = daughter->GetNdaughters();
01258       vis = daughter->IsVisible();
01259       drawDaughters = kTRUE;
01260       if (top->IsVisContainers()) {
01261          if (vis && level<=fVisLevel) {
01262             if (fPlugin) {
01263                line_color = vol->GetLineColor();
01264                line_width = vol->GetLineWidth();
01265                line_style = vol->GetLineStyle();
01266                fPlugin->ProcessNode();
01267             }   
01268             if (!strstr(option,"range")) ((TAttLine*)vol)->Modify();
01269             if (global) {
01270                *fGlobal  = *global;
01271                *fGlobal *= *next.GetCurrentMatrix();
01272             } else {
01273                *fGlobal = next.GetCurrentMatrix();
01274             }
01275             fGeoManager->SetMatrixReflection(fGlobal->IsReflection());
01276             drawDaughters = PaintShape(*(vol->GetShape()),option);
01277             if (fPlugin) {
01278                vol->SetLineColor(line_color);
01279                vol->SetLineWidth(line_width);
01280                vol->SetLineStyle(line_style);
01281             }   
01282             if (!fVisLock && !daughter->IsOnScreen()) {
01283                fVisVolumes->Add(vol);
01284                vol->SetAttBit(TGeoAtt::kVisOnScreen);
01285             }   
01286          }   
01287          // Check if we have to skip this branch
01288          if (!drawDaughters || level==fVisLevel || !daughter->IsVisDaughters()) {
01289             next.Skip();
01290             continue;
01291          }   
01292       } else if (top->IsVisLeaves()) {
01293          last = ((nd==0) || (level==fVisLevel) || (!daughter->IsVisDaughters()))?kTRUE:kFALSE;
01294          if (vis && last) {
01295             if (fPlugin) {
01296                line_color = vol->GetLineColor();
01297                line_width = vol->GetLineWidth();
01298                line_style = vol->GetLineStyle();
01299                fPlugin->ProcessNode();
01300             }   
01301             if (!strstr(option,"range")) ((TAttLine*)vol)->Modify();
01302             if (global) {
01303                *fGlobal  = *global;
01304                *fGlobal *= *next.GetCurrentMatrix();
01305             } else {
01306                *fGlobal = next.GetCurrentMatrix();
01307             }
01308             fGeoManager->SetMatrixReflection(fGlobal->IsReflection());
01309             drawDaughters = PaintShape(*(vol->GetShape()),option);
01310             if (fPlugin) {
01311                vol->SetLineColor(line_color);
01312                vol->SetLineWidth(line_width);
01313                vol->SetLineStyle(line_style);
01314             }   
01315             if (!fVisLock && !daughter->IsOnScreen()) {
01316                fVisVolumes->Add(vol);
01317                vol->SetAttBit(TGeoAtt::kVisOnScreen);
01318             }   
01319          }
01320          // Check if we have to skip the branch
01321          if (!drawDaughters || last || !daughter->IsVisDaughters()) next.Skip();
01322       }
01323    }
01324    if (fPlugin) fPlugin->SetIterator(0);
01325    fGeoManager->SetMatrixReflection(kFALSE);
01326    fVisLock = kTRUE;
01327 }
01328 
01329 //______________________________________________________________________________
01330 Bool_t TGeoPainter::PaintShape(const TGeoShape & shape, Option_t *  option ) const
01331 {
01332    // Paint the supplied shape into the current 3D viewer
01333    Bool_t addDaughters = kTRUE;
01334 
01335    TVirtualViewer3D * viewer = gPad->GetViewer3D();
01336 
01337    if (!viewer || shape.IsA()==TGeoShapeAssembly::Class()) {
01338       return addDaughters;
01339    }
01340 
01341    // For non-composite shapes we are the main paint method & perform the negotation 
01342    // with the viewer here
01343    if (!shape.IsComposite()) {
01344       // Does viewer prefer local frame positions?
01345       Bool_t localFrame = viewer->PreferLocalFrame();
01346       // Perform first fetch of buffer from the shape and try adding it
01347       // to the viewer
01348       const TBuffer3D & buffer = 
01349          shape.GetBuffer3D(TBuffer3D::kCore|TBuffer3D::kBoundingBox|TBuffer3D::kShapeSpecific, localFrame);
01350       Int_t reqSections = viewer->AddObject(buffer, &addDaughters);
01351 
01352       // If the viewer requires additional sections fetch from the shape (if possible)
01353       // and add again
01354       if (reqSections != TBuffer3D::kNone) {
01355          shape.GetBuffer3D(reqSections, localFrame);
01356          viewer->AddObject(buffer, &addDaughters);
01357       }
01358    }
01359    // Composite shapes have their own internal hierarchy of shapes, each
01360    // of which generate a filled TBuffer3D. Therefore we can't pass up a 
01361    // single buffer to here. So as a special case the TGeoCompositeShape
01362    // performs it's own painting & negotiation with the viewer.
01363    else {
01364       const TGeoCompositeShape * composite = static_cast<const TGeoCompositeShape *>(&shape);
01365 
01366       // We need the addDaughters flag returned from the viewer from paint
01367       // so can't use the normal TObject::Paint()
01368 //      TGeoHMatrix *matrix = (TGeoHMatrix*)TGeoShape::GetTransform();
01369 //      if (viewer->PreferLocalFrame()) matrix->Clear();
01370       addDaughters = composite->PaintComposite(option);
01371    }
01372 
01373    return addDaughters;
01374 }
01375 
01376 //______________________________________________________________________________
01377 void TGeoPainter::PaintShape(TGeoShape *shape, Option_t *option)
01378 {
01379 // Paint an overlap.
01380    TGeoShape::SetTransform(fGlobal);
01381    fGlobal->Clear();
01382    fGeoManager->SetPaintVolume(0);
01383    PaintShape(*shape,option);
01384 }
01385 
01386 //______________________________________________________________________________
01387 void TGeoPainter::PaintPhysicalNode(TGeoPhysicalNode *node, Option_t *option)
01388 {
01389 // Paints a physical node associated with a path.
01390    if (!node->IsVisible()) return;
01391    Int_t level = node->GetLevel();
01392    Int_t i, col, wid, sty;
01393    TGeoShape *shape;
01394    TGeoShape::SetTransform(fGlobal);
01395    TGeoHMatrix *matrix = fGlobal;
01396    TGeoVolume *vcrt;
01397    if (!node->IsVisibleFull()) {
01398       // Paint only last node in the branch
01399       vcrt  = node->GetVolume();
01400       if (!strstr(option,"range")) ((TAttLine*)vcrt)->Modify(); 
01401       shape = vcrt->GetShape();
01402       *matrix = node->GetMatrix();
01403       fGeoManager->SetMatrixReflection(matrix->IsReflection());
01404       fGeoManager->SetPaintVolume(vcrt);
01405       if (!node->IsVolAttributes() && !strstr(option,"range")) {
01406          col = vcrt->GetLineColor();
01407          wid = vcrt->GetLineWidth();
01408          sty = vcrt->GetLineStyle();
01409          vcrt->SetLineColor(node->GetLineColor());
01410          vcrt->SetLineWidth(node->GetLineWidth());
01411          vcrt->SetLineStyle(node->GetLineStyle());
01412          ((TAttLine*)vcrt)->Modify(); 
01413          PaintShape(*shape,option);
01414          vcrt->SetLineColor(col);
01415          vcrt->SetLineWidth(wid);
01416          vcrt->SetLineStyle(sty);
01417       } else {    
01418          PaintShape(*shape,option);
01419       }
01420    } else {
01421       // Paint full branch, except top node
01422       for (i=1;i<=level; i++) {
01423          vcrt  = node->GetVolume(i);
01424          if (!strstr(option,"range")) ((TAttLine*)vcrt)->Modify(); 
01425          shape = vcrt->GetShape();
01426          *matrix = node->GetMatrix(i);
01427          fGeoManager->SetMatrixReflection(matrix->IsReflection());
01428          fGeoManager->SetPaintVolume(vcrt);
01429          if (!node->IsVolAttributes() && !strstr(option,"range")) {
01430             col = vcrt->GetLineColor();
01431             wid = vcrt->GetLineWidth();
01432             sty = vcrt->GetLineStyle();
01433             vcrt->SetLineColor(node->GetLineColor());
01434             vcrt->SetLineWidth(node->GetLineWidth());
01435             vcrt->SetLineStyle(node->GetLineStyle());
01436             ((TAttLine*)vcrt)->Modify();
01437             PaintShape(*shape,option);
01438             vcrt->SetLineColor(col);
01439             vcrt->SetLineWidth(wid);
01440             vcrt->SetLineStyle(sty);
01441          } else {  
01442             PaintShape(*shape,option);
01443          }   
01444       }
01445    }
01446    fGeoManager->SetMatrixReflection(kFALSE);      
01447 }   
01448 
01449 //______________________________________________________________________________
01450 void TGeoPainter::PrintOverlaps() const
01451 {
01452 // Print overlaps (see TGeoChecker::PrintOverlaps())
01453    fChecker->PrintOverlaps();
01454 }   
01455 
01456 //______________________________________________________________________________
01457 void TGeoPainter::OpProgress(const char *opname, Long64_t current, Long64_t size, TStopwatch *watch, Bool_t last, Bool_t refresh)
01458 {
01459 // Text progress bar.
01460    fChecker->OpProgress(opname,current,size,watch,last,refresh);
01461 }   
01462    
01463 //______________________________________________________________________________
01464 void TGeoPainter::RandomPoints(const TGeoVolume *vol, Int_t npoints, Option_t *option)
01465 {
01466 // Draw random points in the bounding box of a volume.
01467    fChecker->RandomPoints((TGeoVolume*)vol, npoints, option);
01468 }   
01469 
01470 //______________________________________________________________________________
01471 void TGeoPainter::RandomRays(Int_t nrays, Double_t startx, Double_t starty, Double_t startz)
01472 {
01473 // Shoot nrays in the current drawn geometry
01474    fChecker->RandomRays(nrays, startx, starty, startz);
01475 }   
01476 
01477 //______________________________________________________________________________
01478 void TGeoPainter::Raytrace(Option_t * /*option*/)
01479 {
01480 // Raytrace current drawn geometry
01481    if (!gPad || gPad->IsBatch()) return;   
01482    TView *view = gPad->GetView();
01483    if (!view) return;
01484    TGeoVolume *top = fGeoManager->GetTopVolume();
01485    if (top != fTopVolume) fGeoManager->SetTopVolume(fTopVolume);
01486    if (!view->IsPerspective()) view->SetPerspective();
01487    gVirtualX->SetMarkerSize(1);
01488    gVirtualX->SetMarkerStyle(1);
01489    Int_t i;
01490    Bool_t inclipst=kFALSE, inclip=kFALSE;
01491    Double_t krad = TMath::DegToRad();
01492    Double_t lat = view->GetLatitude();
01493    Double_t longit = view->GetLongitude();
01494    Double_t psi = view->GetPsi();
01495    Double_t c1 = TMath::Cos(psi*krad);
01496    Double_t s1 = TMath::Sin(psi*krad);
01497    Double_t c2 = TMath::Cos(lat*krad);
01498    Double_t s2 = TMath::Sin(lat*krad);
01499    Double_t s3 = TMath::Cos(longit*krad);
01500    Double_t c3 = -TMath::Sin(longit*krad);
01501    fMat[0] =  c1*c3 - s1*c2*s3;
01502    fMat[1] =  c1*s3 + s1*c2*c3;
01503    fMat[2] =  s1*s2;
01504       
01505    fMat[3] =  -s1*c3 - c1*c2*s3;
01506    fMat[4] = -s1*s3 + c1*c2*c3;
01507    fMat[5] =  c1*s2;
01508    
01509    fMat[6] =  s2*s3;
01510    fMat[7] =  -s2*c3;
01511    fMat[8] = c2; 
01512    Double_t u0, v0, du, dv;
01513    view->GetWindow(u0,v0,du,dv);
01514    Double_t dview = view->GetDview();
01515    Double_t dproj = view->GetDproj();
01516    Double_t local[3] = {0,0,1};
01517    Double_t dir[3], normal[3];   
01518    LocalToMasterVect(local,dir);
01519    Double_t min[3], max[3];
01520    view->GetRange(min, max);
01521    Double_t cov[3];
01522    for (i=0; i<3; i++) cov[i] = 0.5*(min[i]+max[i]);
01523    Double_t cop[3]; 
01524    for (i=0; i<3; i++) cop[i] = cov[i] - dir[i]*dview;
01525    fGeoManager->InitTrack(cop, dir);
01526    Bool_t outside = fGeoManager->IsOutside();
01527    fGeoManager->DoBackupState();
01528    if (fClippingShape) inclipst = inclip = fClippingShape->Contains(cop);
01529    Int_t px, py;
01530    Double_t xloc, yloc, modloc;
01531    Int_t pxmin,pxmax, pymin,pymax;
01532    pxmin = gPad->UtoAbsPixel(0);
01533    pxmax = gPad->UtoAbsPixel(1);
01534    pymin = gPad->VtoAbsPixel(1);
01535    pymax = gPad->VtoAbsPixel(0);
01536    TGeoNode *next, *nextnode;
01537    Double_t step,steptot;
01538    Double_t *norm;
01539    const Double_t *point = fGeoManager->GetCurrentPoint();
01540    Double_t *ppoint = (Double_t*)point;
01541    Double_t tosource[3];
01542    Double_t calf;
01543    Double_t phi = 0*krad;
01544    tosource[0] = -dir[0]*TMath::Cos(phi)+dir[1]*TMath::Sin(phi);
01545    tosource[1] = -dir[0]*TMath::Sin(phi)-dir[1]*TMath::Cos(phi);
01546    tosource[2] = -dir[2];
01547    
01548    Bool_t done;
01549 //   Int_t istep;
01550    Int_t base_color, color;
01551    Double_t light;
01552    Double_t stemin=0, stemax=TGeoShape::Big();
01553    TPoint *pxy = new TPoint[1];
01554    TGeoVolume *nextvol;
01555    Int_t up;
01556    Int_t ntotal = pxmax*pymax;
01557    Int_t nrays = 0;
01558    TStopwatch *timer = new TStopwatch();
01559    timer->Start();
01560    for (px=pxmin; px<pxmax; px++) {
01561       for (py=pymin; py<pymax; py++) {
01562          if ((nrays%100)==0) OpProgress("Raytracing",nrays,ntotal,timer,kFALSE);
01563          nrays++;
01564          base_color = 1;
01565          steptot = 0;
01566          inclip = inclipst;
01567          xloc = gPad->AbsPixeltoX(pxmin+pxmax-px);
01568          xloc = xloc*du-u0;
01569          yloc = gPad->AbsPixeltoY(pymin+pymax-py);
01570          yloc = yloc*dv-v0;
01571          modloc = TMath::Sqrt(xloc*xloc+yloc*yloc+dproj*dproj);  
01572          local[0] = xloc/modloc;
01573          local[1] = yloc/modloc;
01574          local[2] = dproj/modloc;
01575          LocalToMasterVect(local,dir);
01576          fGeoManager->DoRestoreState();
01577          fGeoManager->SetOutside(outside);
01578          fGeoManager->SetCurrentPoint(cop);
01579          fGeoManager->SetCurrentDirection(dir);
01580 //         fGeoManager->InitTrack(cop,dir);
01581          // current ray pointing to pixel (px,py)
01582          done = kFALSE;
01583          norm = 0;
01584          // propagate to the clipping shape if any
01585          if (fClippingShape) {
01586             if (inclip) {
01587                stemin = fClippingShape->DistFromInside(cop,dir,3);
01588                stemax = TGeoShape::Big();
01589             } else {
01590                stemax = fClippingShape->DistFromOutside(cop,dir,3);
01591                stemin = 0;
01592             }
01593          }         
01594                
01595          while (!done) {
01596             if (fClippingShape) {
01597                if (stemin>1E10) break;
01598                if (stemin>0) {
01599                   // we are inside clipping shape
01600                   fGeoManager->SetStep(stemin);
01601                   next = fGeoManager->Step();
01602                   steptot = 0;
01603                   stemin = 0;
01604                   up = 0;
01605                   while (next) {
01606                      // we found something after clipping region
01607                      nextvol = next->GetVolume();
01608                      if (nextvol->TestAttBit(TGeoAtt::kVisOnScreen)) {
01609                         done = kTRUE;
01610                         base_color = nextvol->GetLineColor();
01611                         fClippingShape->ComputeNormal(ppoint, dir, normal);
01612                         norm = normal;
01613                         break;
01614                      }
01615                      up++;
01616                      next = fGeoManager->GetMother(up);
01617                   }
01618                   if (done) break;
01619                   inclip = fClippingShape->Contains(ppoint);
01620                   fGeoManager->SetStep(1E-3);
01621                   while (inclip) {
01622                      fGeoManager->Step();
01623                      inclip = fClippingShape->Contains(ppoint);
01624                   }   
01625                   stemax = fClippingShape->DistFromOutside(ppoint,dir,3);
01626                }
01627             }              
01628             nextnode = fGeoManager->FindNextBoundaryAndStep();
01629             step = fGeoManager->GetStep();
01630             if (step>1E10) break;
01631             steptot += step;
01632             next = nextnode;
01633             // Check the step
01634             if (fClippingShape) {
01635                if (steptot>stemax) {
01636                   steptot = 0;
01637                   inclip = fClippingShape->Contains(ppoint);
01638                   if (inclip) {
01639                      stemin = fClippingShape->DistFromInside(ppoint,dir,3);
01640                      stemax = TGeoShape::Big();
01641                      continue;
01642                   } else {
01643                      stemin = 0;
01644                      stemax = fClippingShape->DistFromOutside(ppoint,dir,3);  
01645                   }
01646                }
01647             }      
01648             // Check if next node is visible
01649             if (!nextnode) continue;
01650             nextvol = nextnode->GetVolume();
01651             if (nextvol->TestAttBit(TGeoAtt::kVisOnScreen)) {
01652                done = kTRUE;
01653                base_color = nextvol->GetLineColor();
01654                next = nextnode;
01655                break;
01656             }
01657          }
01658          if (!done) continue;
01659          // current ray intersect a visible volume having color=base_color
01660 //         if (!norm) norm = fGeoManager->FindNormal(kFALSE);
01661          if (!norm) norm = fGeoManager->FindNormalFast();
01662          if (!norm) continue;
01663          calf = norm[0]*tosource[0]+norm[1]*tosource[1]+norm[2]*tosource[2];
01664          light = 0.25+0.5*TMath::Abs(calf);
01665          color = GetColor(base_color, light);
01666          // Now we know the color of the pixel, just draw it
01667          gVirtualX->SetMarkerColor(color);         
01668          pxy[0].fX = px;
01669          pxy[0].fY = py;
01670          gVirtualX->DrawPolyMarker(1,pxy);
01671       }
01672    } 
01673    delete [] pxy;      
01674    timer->Stop();
01675    fChecker->OpProgress("Raytracing",nrays,ntotal,timer,kTRUE);
01676    delete timer;
01677 }
01678 
01679 //______________________________________________________________________________
01680 TGeoNode *TGeoPainter::SamplePoints(Int_t npoints, Double_t &dist, Double_t epsil,
01681                                     const char* g3path)
01682 {
01683 // shoot npoints randomly in a box of 1E-5 arround current point.
01684 // return minimum distance to points outside
01685    return fChecker->SamplePoints(npoints, dist, epsil, g3path);
01686 }
01687 
01688 //______________________________________________________________________________
01689 void TGeoPainter::SetBombFactors(Double_t bombx, Double_t bomby, Double_t bombz, Double_t bombr)
01690 {
01691 //--- Set cartesian and radial bomb factors for translations
01692    fBombX = bombx;
01693    fBombY = bomby;
01694    fBombZ = bombz;
01695    fBombR = bombr;
01696    if (IsExplodedView()) ModifiedPad();
01697 }          
01698 
01699 //______________________________________________________________________________
01700 void TGeoPainter::SetExplodedView(Int_t ibomb)    
01701 {
01702    // set type of exploding view
01703    if ((ibomb<0) || (ibomb>3)) {
01704       Warning("SetExplodedView", "exploded view can be 0-3");
01705       return;
01706    }
01707    if ((Int_t)ibomb==fExplodedView) return;   
01708    Bool_t change = (gPad==0)?kFALSE:kTRUE;
01709 
01710    if (ibomb==kGeoNoBomb) {
01711       change &= ((fExplodedView==kGeoNoBomb)?kFALSE:kTRUE);
01712    }
01713    if (ibomb==kGeoBombXYZ) {
01714       change &= ((fExplodedView==kGeoBombXYZ)?kFALSE:kTRUE);
01715    }
01716    if (ibomb==kGeoBombCyl) {
01717       change &= ((fExplodedView==kGeoBombCyl)?kFALSE:kTRUE);
01718    }
01719    if (ibomb==kGeoBombSph) {
01720       change &= ((fExplodedView==kGeoBombSph)?kFALSE:kTRUE);
01721    }
01722    fExplodedView = ibomb;
01723    if (change) ModifiedPad(); 
01724 }
01725 
01726 //______________________________________________________________________________
01727 void TGeoPainter::SetNsegments(Int_t nseg)    
01728 {
01729 // Set number of segments to approximate circles
01730    if (nseg<3) {
01731       Warning("SetNsegments", "number of segments should be > 2");
01732       return;
01733    }
01734    if (fNsegments==nseg) return;
01735    fNsegments = nseg;
01736    ModifiedPad();
01737 }
01738 
01739 //______________________________________________________________________________
01740 void TGeoPainter::SetNmeshPoints(Int_t npoints) {
01741 // Set number of points to be generated on the shape outline when checking for overlaps.
01742    fChecker->SetNmeshPoints(npoints);
01743 }   
01744 
01745 //______________________________________________________________________________
01746 void TGeoPainter::SetCheckedNode(TGeoNode *node) {
01747 // Select a node to be checked for overlaps. All overlaps not involving it will
01748 // be ignored.
01749    fChecker->SetSelectedNode(node);
01750 }   
01751 
01752 //______________________________________________________________________________
01753 void TGeoPainter::SetVisLevel(Int_t level) {
01754 // Set default level down to which visualization is performed
01755    if (level==fVisLevel && fLastVolume==fTopVolume) return;
01756    fVisLevel=level;
01757    if (!fTopVolume) return;
01758    if (fVisLock) {
01759       ClearVisibleVolumes();
01760       fVisLock = kFALSE;
01761    }   
01762    if (!fLastVolume) {
01763 //      printf("--- Drawing   %6d nodes with %d visible levels\n",fNVisNodes,fVisLevel);
01764       return;
01765    }   
01766    if (!gPad) return;
01767    if (gPad->GetView()) {
01768 //      printf("--- Drawing   %6d nodes with %d visible levels\n",fNVisNodes,fVisLevel);
01769       ModifiedPad();
01770    }
01771 }
01772 
01773 //______________________________________________________________________________
01774 void TGeoPainter::SetTopVisible(Bool_t vis)
01775 {
01776 // Set top geometry volume as visible.
01777    if (fTopVisible==vis) return;
01778    fTopVisible = vis;
01779    ModifiedPad();
01780 }
01781    
01782 //-----------------------------------------------------------------------------
01783 void TGeoPainter::SetVisOption(Int_t option) {
01784 // set drawing mode :
01785 // option=0 (default) all nodes drawn down to vislevel
01786 // option=1           leaves and nodes at vislevel drawn
01787 // option=2           path is drawn
01788    if ((fVisOption<0) || (fVisOption>4)) {
01789       Warning("SetVisOption", "wrong visualization option");
01790       return;
01791    }
01792    
01793    if (option == kGeoVisChanged) {
01794       if (fVisLock) {
01795          ClearVisibleVolumes();
01796          fVisLock = kFALSE;
01797       }   
01798       ModifiedPad();
01799       return;
01800    }
01801    
01802    if (fTopVolume) {
01803       TGeoAtt *att = (TGeoAtt*)fTopVolume;
01804       att->SetAttBit(TGeoAtt::kVisBranch,kFALSE);
01805       att->SetAttBit(TGeoAtt::kVisContainers,kFALSE);
01806       att->SetAttBit(TGeoAtt::kVisOnly,kFALSE);
01807       switch (option) {
01808          case kGeoVisDefault:
01809             att->SetAttBit(TGeoAtt::kVisContainers,kTRUE);
01810             break;
01811          case kGeoVisLeaves:
01812             break;
01813          case kGeoVisOnly:   
01814             att->SetAttBit(TGeoAtt::kVisOnly,kTRUE);
01815             break;
01816       } 
01817    }            
01818 
01819    if (fVisOption==option) return;   
01820    fVisOption=option;
01821    if (fVisLock) {
01822       ClearVisibleVolumes();
01823       fVisLock = kFALSE;
01824    }   
01825    ModifiedPad();
01826 }
01827 
01828 //______________________________________________________________________________
01829 Int_t TGeoPainter::ShapeDistancetoPrimitive(const TGeoShape *shape, Int_t numpoints, Int_t px, Int_t py) const   
01830 {   
01831 //  Returns distance between point px,py on the pad an a shape.
01832    const Int_t inaxis = 7;
01833    const Int_t maxdist = 5;
01834    const Int_t big = 9999;
01835    Int_t dist = big;
01836    if (!gPad) return dist;
01837    TView *view = gPad->GetView();
01838    if (!(numpoints && view)) return dist;
01839    if (shape->IsA()==TGeoShapeAssembly::Class()) return dist;
01840 
01841    if (fIsPaintingShape) {
01842       Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
01843       Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
01844       Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
01845       Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
01846       // return if point not in user area
01847       if (px < puxmin - inaxis) return big;
01848       if (py > puymin + inaxis) return big;
01849       if (px > puxmax + inaxis) return big;
01850       if (py < puymax - inaxis) return big;
01851       if ((puxmax+inaxis-px) < 40) {
01852          // when the mouse points to the (40 pix) right edge of the pad, the manager class is selected
01853          gPad->SetSelected(fGeoManager);
01854          return 0;
01855       }
01856    }
01857 
01858    fBuffer->SetRawSizes(numpoints, 3*numpoints, 0, 0, 0, 0);
01859    Double_t *points = fBuffer->fPnts;
01860    shape->SetPoints(points);
01861    Double_t dpoint2, x1, y1, xndc[3];
01862    Double_t dmaster[3];
01863    Int_t j;
01864    for (Int_t i=0; i<numpoints; i++) {
01865       j = 3*i;
01866       TGeoShape::GetTransform()->LocalToMaster(&points[j], dmaster); 
01867       points[j]=dmaster[0]; points[j+1]=dmaster[1]; points[j+2]=dmaster[2];
01868       view->WCtoNDC(&points[j], xndc);
01869       x1 = gPad->XtoAbsPixel(xndc[0]);
01870       y1 = gPad->YtoAbsPixel(xndc[1]);
01871       dpoint2 = (px-x1)*(px-x1) + (py-y1)*(py-y1);
01872       if (dpoint2 < dist) dist=(Int_t)dpoint2;
01873    }
01874    if (dist > 100) return dist;
01875    dist = Int_t(TMath::Sqrt(Double_t(dist)));
01876    if (dist<maxdist && fIsPaintingShape) gPad->SetSelected((TObject*)shape);
01877    return dist;
01878 }
01879 
01880 //______________________________________________________________________________
01881 void TGeoPainter::Test(Int_t npoints, Option_t *option)
01882 {
01883 // Check time of finding "Where am I" for n points.
01884    fChecker->Test(npoints, option);
01885 }   
01886 
01887 //______________________________________________________________________________
01888 void TGeoPainter::TestOverlaps(const char* path)
01889 {
01890 //--- Geometry overlap checker based on sampling. 
01891    fChecker->TestOverlaps(path);
01892 }   
01893 
01894 //______________________________________________________________________________
01895 Bool_t TGeoPainter::TestVoxels(TGeoVolume *vol)
01896 {
01897 // Check voxels efficiency per volume.
01898    return fChecker->TestVoxels(vol);
01899 }   
01900 
01901 //______________________________________________________________________________
01902 void TGeoPainter::UnbombTranslation(const Double_t *tr, Double_t *bombtr)
01903 {
01904 // get the new 'unbombed' translation vector according current exploded view mode
01905    memcpy(bombtr, tr, 3*sizeof(Double_t));
01906    switch (fExplodedView) {
01907       case kGeoNoBomb:
01908          return;
01909       case kGeoBombXYZ:
01910          bombtr[0] /= fBombX;
01911          bombtr[1] /= fBombY;
01912          bombtr[2] /= fBombZ;
01913          return;
01914       case kGeoBombCyl:
01915          bombtr[0] /= fBombR;
01916          bombtr[1] /= fBombR;
01917          bombtr[2] /= fBombZ;
01918          return;
01919       case kGeoBombSph:
01920          bombtr[0] /= fBombR;
01921          bombtr[1] /= fBombR;
01922          bombtr[2] /= fBombR;
01923          return;
01924       default:
01925          return;
01926    }   
01927 }
01928    
01929 //______________________________________________________________________________
01930 Double_t TGeoPainter::Weight(Double_t precision, Option_t *option)
01931 {
01932 // Compute weight [kg] of the current volume.
01933    return fChecker->Weight(precision, option);
01934 }
01935    
01936    

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