From c1d8afc2da90fd3364f4c6f92f59c007cf55e800 Mon Sep 17 00:00:00 2001
From: Rene Brun <Rene.Brun@cern.ch>
Date: Sun, 11 Jun 2006 12:56:48 +0000
Subject: [PATCH] From Andrei: 1. Mixtures components can now also be other
 materials/mixtures:   TGeoMixture::AddElement(TGeoMaterial *mat, Double_t
 weight); 2. When elements are added via TGeoMixture::AddElement(TGeoElement
 *elem,...), the list of elements is kept. 3. Some fixes related to
 visualization within TGeoPainter

git-svn-id: http://root.cern.ch/svn/root/trunk@15395 27541ba8-7e3a-0410-8455-c3a389f83636
---
 geom/inc/TGeoMaterial.h         |  30 +++-
 geom/inc/TVirtualGeoPainter.h   |   5 +-
 geom/src/TGeoManager.cxx        |   3 +-
 geom/src/TGeoMaterial.cxx       | 267 +++++++++++++++++++++++++-------
 geom/src/TGeoVolume.cxx         |   6 +-
 geompainter/inc/TGeoPainter.h   |   1 +
 geompainter/src/TGeoPainter.cxx | 110 ++++++-------
 7 files changed, 292 insertions(+), 130 deletions(-)

diff --git a/geom/inc/TGeoMaterial.h b/geom/inc/TGeoMaterial.h
index b695d98478b..d38e9c59874 100644
--- a/geom/inc/TGeoMaterial.h
+++ b/geom/inc/TGeoMaterial.h
@@ -1,4 +1,4 @@
-// @(#)root/geom:$Name:  $:$Id: TGeoMaterial.h,v 1.19 2005/11/18 16:07:58 brun Exp $
+// @(#)root/geom:$Name:  $:$Id: TGeoMaterial.h,v 1.20 2006/05/23 04:47:37 brun Exp $
 // Author: Andrei Gheata   25/10/01
 
 /*************************************************************************
@@ -58,6 +58,7 @@ protected:
    Double_t                 fIntLen;     // interaction length
    TObject                 *fShader;     // shader with optical properties
    TObject                 *fCerenkov;   // pointer to class with Cerenkov properties
+   TGeoElement             *fElement;    // pointer to element composing the material
 
 // methods
    TGeoMaterial(const TGeoMaterial&);
@@ -82,6 +83,7 @@ public:
    virtual Int_t            GetDefaultColor() const;
    virtual Double_t         GetDensity() const {return fDensity;}
    virtual TGeoElement     *GetElement(Int_t i=0) const;
+   TGeoElement             *GetBaseElement() const {return fElement;}
    char                    *GetPointerName() const;
    virtual Double_t         GetRadLen() const  {return fRadLen;}
    virtual Double_t         GetIntLen() const  {return fIntLen;}
@@ -102,7 +104,7 @@ public:
 
    
 
-   ClassDef(TGeoMaterial, 3)              // base material class
+   ClassDef(TGeoMaterial, 4)              // base material class
 
 //***** Need to add classes and globals to LinkDef.h *****
 };
@@ -120,10 +122,12 @@ protected :
    Double_t                *fZmixture;   // [fNelements] array of Z of the elements
    Double_t                *fAmixture;   // [fNelements] array of A of the elements
    Double_t                *fWeights;    // [fNelements] array of relative proportions by mass
-
+   Int_t                   *fNatoms;     // [fNelements] array of numbers of atoms
+   TObjArray               *fElements;   // array of elements composing the mixture
 // methods
    TGeoMixture(const TGeoMixture&); // Not implemented
    TGeoMixture& operator=(const TGeoMixture&); // Not implemented
+   void                     AverageProperties();
 
 public:
    // constructors
@@ -131,16 +135,24 @@ public:
    TGeoMixture(const char *name, Int_t nel, Double_t rho=-1);
    // destructor
    virtual ~TGeoMixture();
-   // methods
+   // methods for adding elements
+   void                     AddElement(Double_t a, Double_t z, Double_t weight);
+   void                     AddElement(TGeoMaterial *mat, Double_t weight);
+   void                     AddElement(TGeoElement *elem, Double_t weight);
+   void                     AddElement(TGeoElement *elem, Int_t natoms);
+   // backward compatibility for defining elements
    void                     DefineElement(Int_t iel, Double_t a, Double_t z, Double_t weight);
    void                     DefineElement(Int_t iel, TGeoElement *elem, Double_t weight);
    void                     DefineElement(Int_t iel, Int_t z, Int_t natoms);
+   // getters
    virtual Int_t            GetByteCount() const {return 48+12*fNelements;}
    virtual TGeoElement     *GetElement(Int_t i=0) const;
    Int_t                    GetNelements() const {return fNelements;}
    Double_t                *GetZmixt() const     {return fZmixture;}
    Double_t                *GetAmixt() const     {return fAmixture;}
    Double_t                *GetWmixt() const     {return fWeights;}
+   Int_t                   *GetNmixt() const     {return fNatoms;}
+   // utilities
    virtual Bool_t           IsEq(const TGeoMaterial *other) const;
    virtual Bool_t           IsMixture() const {return kTRUE;}
    virtual void             Print(const Option_t *option="") const;
@@ -148,10 +160,14 @@ public:
    void                     SetA(Double_t a) {fA = a;}
    void                     SetZ(Double_t z) {fZ = z;}
 
-   ClassDef(TGeoMixture, 1)              // material mixtures
-
-//***** Need to add classes and globals to LinkDef.h *****
+   ClassDef(TGeoMixture, 2)              // material mixtures
 };
 
+inline void TGeoMixture::DefineElement(Int_t, Double_t a, Double_t z, Double_t weight) 
+   {return AddElement(a,z,weight);}
+inline void TGeoMixture::DefineElement(Int_t, TGeoElement *elem, Double_t weight) 
+   {return AddElement(elem,weight);}
+
+
 #endif
 
diff --git a/geom/inc/TVirtualGeoPainter.h b/geom/inc/TVirtualGeoPainter.h
index 8b62edb5a10..6a7e3c81f2e 100644
--- a/geom/inc/TVirtualGeoPainter.h
+++ b/geom/inc/TVirtualGeoPainter.h
@@ -1,4 +1,4 @@
-// @(#)root/geom:$Name:  $:$Id: TVirtualGeoPainter.h,v 1.33 2006/04/11 11:21:44 brun Exp $
+// @(#)root/geom:$Name:  $:$Id: TVirtualGeoPainter.h,v 1.34 2006/04/25 09:38:27 brun Exp $
 // Author: Andrei Gheata   11/01/02
 
 /*************************************************************************
@@ -49,7 +49,8 @@ enum EGeoVisOption {
    kGeoVisDefault = 0,    // default visualization - everything visible 3 levels down
    kGeoVisLeaves  = 1,    // only last leaves are visible
    kGeoVisOnly    = 2,    // only current volume is drawn
-   kGeoVisBranch  = 3     // only a given branch is drawn
+   kGeoVisBranch  = 3,    // only a given branch is drawn
+   kGeoVisChanged = 4     // visibility changed
 };
 enum EGeoBombOption {   
    kGeoNoBomb     = 0,    // default - no bomb
diff --git a/geom/src/TGeoManager.cxx b/geom/src/TGeoManager.cxx
index ffeff52130f..de4b9a7e382 100644
--- a/geom/src/TGeoManager.cxx
+++ b/geom/src/TGeoManager.cxx
@@ -1,4 +1,4 @@
-// @(#)root/geom:$Name:  $:$Id: TGeoManager.cxx,v 1.156 2006/06/07 12:22:23 brun Exp $
+// @(#)root/geom:$Name:  $:$Id: TGeoManager.cxx,v 1.157 2006/06/08 15:11:47 brun Exp $
 // Author: Andrei Gheata   25/10/01
 
 /*************************************************************************
@@ -2828,6 +2828,7 @@ void TGeoManager::SetVisOption(Int_t option) {
 // option=0 (default) all nodes drawn down to vislevel
 // option=1           leaves and nodes at vislevel drawn
 // option=2           path is drawn
+// option=4           visibility changed
    if ((option>=0) && (option<3)) fVisOption=option;
    if (fPainter) fPainter->SetVisOption(option);
 }
diff --git a/geom/src/TGeoMaterial.cxx b/geom/src/TGeoMaterial.cxx
index 4f1c3eeb8c7..8ebd5e58997 100644
--- a/geom/src/TGeoMaterial.cxx
+++ b/geom/src/TGeoMaterial.cxx
@@ -1,4 +1,4 @@
-// @(#)root/geom:$Name:  $:$Id: TGeoMaterial.cxx,v 1.29 2006/05/24 17:11:54 brun Exp $
+// @(#)root/geom:$Name:  $:$Id: TGeoMaterial.cxx,v 1.30 2006/05/26 09:09:59 brun Exp $
 // Author: Andrei Gheata   25/10/01
 
 /*************************************************************************
@@ -44,6 +44,7 @@ TGeoMaterial::TGeoMaterial()
    fRadLen   = 0;
    fIntLen   = 0;       
    fCerenkov = 0;
+   fElement  = 0;
 }
 //-----------------------------------------------------------------------------
 TGeoMaterial::TGeoMaterial(const char *name)
@@ -60,6 +61,7 @@ TGeoMaterial::TGeoMaterial(const char *name)
    fRadLen   = 0;
    fIntLen   = 0;
    fCerenkov = 0;
+   fElement  = 0;
    
    if (!gGeoManager) {
       gGeoManager = new TGeoManager("Geometry", "default geometry");
@@ -80,6 +82,7 @@ TGeoMaterial::TGeoMaterial(const char *name, Double_t a, Double_t z,
    fZ        = z;
    fDensity  = rho;
    fCerenkov = 0;
+   fElement  = 0;
    SetRadLen(radlen, intlen);
    if (!gGeoManager) {
       gGeoManager = new TGeoManager("Geometry", "default geometry");
@@ -103,6 +106,7 @@ TGeoMaterial::TGeoMaterial(const char *name, TGeoElement *elem,
    fZ        = elem->Z();
    fDensity  = rho;
    fCerenkov = 0;
+   fElement  = elem;
    
    SetRadLen(0,0);
    if (!gGeoManager) {
@@ -124,7 +128,8 @@ TGeoMaterial::TGeoMaterial(const TGeoMaterial& gm) :
   fRadLen(gm.fRadLen),
   fIntLen(gm.fIntLen),
   fShader(gm.fShader),
-  fCerenkov(gm.fCerenkov)
+  fCerenkov(gm.fCerenkov),
+  fElement(gm.fElement)
 { 
    //copy constructor
 }
@@ -143,6 +148,7 @@ TGeoMaterial& TGeoMaterial::operator=(const TGeoMaterial& gm)
       fIntLen=gm.fIntLen;
       fShader=gm.fShader;
       fCerenkov=gm.fCerenkov;
+      fElement=gm.fElement;
    } 
    return *this;
 }
@@ -250,6 +256,7 @@ Int_t TGeoMaterial::GetDefaultColor() const
 TGeoElement *TGeoMaterial::GetElement(Int_t) const
 {
 // Get a pointer to the element this material is made of.
+   if (fElement) return fElement;
    TGeoElementTable *table = gGeoManager->GetElementTable();
    return table->GetElement(Int_t(fZ));
 }
@@ -277,28 +284,21 @@ TGeoMixture::TGeoMixture()
    fZmixture   = 0;
    fAmixture   = 0;
    fWeights    = 0;
+   fNatoms     = 0;
+   fElements   = 0;
 }
 //-----------------------------------------------------------------------------
-TGeoMixture::TGeoMixture(const char *name, Int_t nel, Double_t rho)
+TGeoMixture::TGeoMixture(const char *name, Int_t /*nel*/, Double_t rho)
             :TGeoMaterial(name)
 {
 // constructor
-   if (nel == 0) {
-      fZmixture   = 0;
-      fAmixture   = 0;
-      fWeights    = 0;
-   } else {
-      fZmixture = new Double_t[nel];
-      fAmixture = new Double_t[nel];
-      fWeights  = new Double_t[nel];
-   }
-   fNelements  = nel;
-   for (Int_t j=0;j<fNelements;j++) {
-      fZmixture[j] = 0;
-      fAmixture[j] = 0;
-      fWeights[j]  = 0;
-   }
-   fDensity = rho; //TO BE CORRECTED
+   fZmixture   = 0;
+   fAmixture   = 0;
+   fWeights    = 0;
+   fNelements  = 0;
+   fNatoms     = 0;
+   fDensity = rho;
+   fElements   = 0;
    if (fDensity < 0) fDensity = 0.001;
 }
 //-----------------------------------------------------------------------------
@@ -307,7 +307,9 @@ TGeoMixture::TGeoMixture(const TGeoMixture& gm) :
   fNelements(gm.fNelements),
   fZmixture(gm.fZmixture),
   fAmixture(gm.fAmixture),
-  fWeights(gm.fWeights)
+  fWeights(gm.fWeights),
+  fNatoms(gm.fNatoms),
+  fElements(gm.fElements)
 { 
    //copy constructor
 }
@@ -321,6 +323,8 @@ TGeoMixture& TGeoMixture::operator=(const TGeoMixture& gm)
       fZmixture=gm.fZmixture;
       fAmixture=gm.fAmixture;
       fWeights=gm.fWeights;
+      fNatoms = gm.fNatoms;
+      fElements = gm.fElements;
    } 
    return *this;
 }
@@ -331,23 +335,13 @@ TGeoMixture::~TGeoMixture()
    if (fZmixture) delete[] fZmixture;
    if (fAmixture) delete[] fAmixture;
    if (fWeights)  delete[] fWeights;
+   if (fNatoms)   delete[] fNatoms;
+   if (fElements) delete fElements;
 }
 //-----------------------------------------------------------------------------
-void TGeoMixture:: DefineElement(Int_t i, Double_t a, Double_t z, Double_t weight)
+void TGeoMixture::AverageProperties()
 {
-// add an element to the mixture
-   if ((i<0) || (i>fNelements)) {
-      Error("DefineElement", "wrong index iel=%i in mixture %s, max is %d", i, GetName(), fNelements);
-      return;
-   }
-   fZmixture[i] = z;
-   fAmixture[i] = a;
-   fWeights[i]  = weight;
-   if (z - Int_t(z) > 1E-3)
-      Warning("DefineElement", "Mixture %s has element defined with fractional Z=%f", GetName(), z);
-   GetElement(i)->SetDefined();
-   
-   //compute equivalent radiation length (taken from Geant3/GSMIXT)
+// Compute effective A/Z and radiation length
    const Double_t alr2av = 1.39621E-03 , al183 =5.20948;
    Double_t radinv = 0;
    fA = 0;
@@ -367,38 +361,198 @@ void TGeoMixture:: DefineElement(Int_t i, Double_t a, Double_t z, Double_t weigh
 }
 
 //-----------------------------------------------------------------------------
-void TGeoMixture:: DefineElement(Int_t i, TGeoElement *elem, Double_t weight)
+void TGeoMixture:: AddElement(Double_t a, Double_t z, Double_t weight)
 {
-// Define one component as being a given element with a specified proportion by weight.
-   DefineElement(i, elem->A(), elem->Z(), weight);
-}   
+// add an element to the mixture using fraction by weight
+   // Check if the element is already defined
+   Int_t i;
+   for (i=0; i<fNelements; i++) {
+      if (TMath::Abs(z-fZmixture[i])<1.e-6  && TMath::Abs(a-fAmixture[i])<1.e-6) {
+         fWeights[i] += weight;
+         AverageProperties();
+         return;
+      }
+   }      
+   if (!fNelements) {
+      fZmixture = new Double_t[1];
+      fAmixture = new Double_t[1];
+      fWeights  = new Double_t[1];
+   } else {   
+      Int_t nelements = fNelements+1;
+      Double_t *zmixture = new Double_t[nelements];
+      Double_t *amixture = new Double_t[nelements];
+      Double_t *weights  = new Double_t[nelements];
+      for (Int_t j=0; j<fNelements; j++) {
+         zmixture[j] = fZmixture[j];
+         amixture[j] = fAmixture[j];
+         weights[j]  = fWeights[j];
+      }
+      delete [] fZmixture;
+      delete [] fAmixture;
+      delete [] fWeights;
+      fZmixture = zmixture;
+      fAmixture = amixture;
+      fWeights  = weights;
+   }       
+   
+   fNelements++;
+   i = fNelements - 1;   
+   fZmixture[i] = z;
+   fAmixture[i] = a;
+   fWeights[i]  = weight;
+   if (z - Int_t(z) > 1E-3)
+      Warning("DefineElement", "Mixture %s has element defined with fractional Z=%f", GetName(), z);
+   GetElement(i)->SetDefined();
+   
+   //compute equivalent radiation length (taken from Geant3/GSMIXT)
+   AverageProperties();
+}
 
 //-----------------------------------------------------------------------------
-void TGeoMixture:: DefineElement(Int_t iel, Int_t z, Int_t natoms)
+void TGeoMixture::AddElement(TGeoMaterial *mat, Double_t weight)
 {
-// Define the mixture element at index iel by number of atoms in the chemical formula.
-   Int_t i;
-   if ((iel<0) || (iel>fNelements)) {
-      Error("DefineElement", "wrong index iel=%i in mixture %s, max is %d", iel, GetName(), fNelements);
+// Define one component of the mixture as an existing material/mixture.
+   TGeoElement *elnew, *elem;   
+   Double_t a,z;
+   if (!mat->IsMixture()) {
+      elem = mat->GetBaseElement();
+      if (elem) {
+         AddElement(elem, weight);
+      } else {   
+         a = mat->GetA();
+         z = mat->GetZ();
+         AddElement(a, z, weight);
+      }   
       return;
    }
+   // The material is a mixture.
+   TGeoMixture *mix = (TGeoMixture*)mat;
+   Double_t wnew;
+   Int_t nelem = mix->GetNelements();
+   Bool_t elfound;
+   Int_t i,j;
+   // loop the elements of the daughter mixture
+   for (i=0; i<nelem; i++) {
+      elfound = kFALSE;
+      elnew = mix->GetElement(i);
+      if (!elnew) continue;
+      // check if we have the element already defined in the parent mixture
+      for (j=0; j<fNelements; j++) {
+         if (fWeights[j]<=0) continue;
+         elem = GetElement(j);
+         if (elem == elnew) {
+            // element found, compute new weight
+            fWeights[j] += weight * (mix->GetWmixt())[i];
+            elfound = kTRUE;
+            break;
+         }
+      }
+      if (elfound) continue;
+      // element not found, define it
+      wnew = weight * (mix->GetWmixt())[i];
+      AddElement(elnew, wnew);
+   }   
+}         
+
+//-----------------------------------------------------------------------------
+void TGeoMixture::AddElement(TGeoElement *elem, Double_t weight)
+{
+// add an element to the mixture using fraction by weight
+   TGeoElement *elemold;
    TGeoElementTable *table = gGeoManager->GetElementTable();
-   TGeoElement *elem = table->GetElement(z);
-   if (!elem) Fatal("DefineElement", "In mixture %s, element with Z=%i not found",GetName(),z);
+   if (!fElements) fElements = new TObjArray(10);
+   Bool_t exist = kFALSE;
+   // If previous elements were defined by A/Z, add corresponding TGeoElements
+   for (Int_t i=0; i<fNelements; i++) {
+      elemold = (TGeoElement*)fElements->At(i);
+      if (!elemold) fElements->AddAt(elemold = table->GetElement((Int_t)fZmixture[i]), i);   
+      if (elemold == elem) exist = kTRUE;
+   }
+   if (!exist) fElements->AddAt(elem, fNelements);   
+   AddElement(elem->A(), elem->Z(), weight);
+}   
+
+//-----------------------------------------------------------------------------
+void TGeoMixture::AddElement(TGeoElement *elem, Int_t natoms)
+{
+// Add a mixture element by number of atoms in the chemical formula.
+   Int_t i,j;
+   Double_t amol;
+   TGeoElement *elemold;
+   TGeoElementTable *table = gGeoManager->GetElementTable();
+   if (!fElements) fElements = new TObjArray(10);
+   // Check if the element is already defined
+   for (i=0; i<fNelements; i++) {
+      elemold = (TGeoElement*)fElements->At(i);
+      if (!elemold) fElements->AddAt(table->GetElement((Int_t)fZmixture[i]), i);
+      else if (elemold != elem) continue;
+      if ((elem==elemold) || 
+          (TMath::Abs(elem->Z()-fZmixture[i])<1.e-6 && TMath::Abs(elem->A()-fAmixture[i])<1.e-6)) {
+         fNatoms[i] += natoms;
+         amol = 0.;
+         for (j=0; j<fNelements; j++) amol += fAmixture[j]*fNatoms[j];
+         for (j=0; j<fNelements; j++) fWeights[j] = fNatoms[j]*fAmixture[j]/amol;
+         AverageProperties();
+         return;
+      }
+   }
+   // New element      
+   if (!fNelements) {
+      fZmixture = new Double_t[1];
+      fAmixture = new Double_t[1];
+      fWeights  = new Double_t[1];
+      fNatoms   = new Int_t[1];
+   } else {   
+      if (!fNatoms) {
+         Error("AddElement", "Cannot add element by natoms in mixture %s after defining elements by weight",
+               GetName());
+         return;
+      }         
+      Int_t nelements = fNelements+1;
+      Double_t *zmixture = new Double_t[nelements];
+      Double_t *amixture = new Double_t[nelements];
+      Double_t *weights  = new Double_t[nelements];
+      Int_t *nnatoms  = new Int_t[nelements];
+      for (Int_t j=0; j<fNelements; j++) {
+         zmixture[j] = fZmixture[j];
+         amixture[j] = fAmixture[j];
+         weights[j]  = fWeights[j];
+         nnatoms[j]  = fNatoms[j];
+      }
+      delete [] fZmixture;
+      delete [] fAmixture;
+      delete [] fWeights;
+      delete [] fNatoms;
+      fZmixture = zmixture;
+      fAmixture = amixture;
+      fWeights  = weights;
+      fNatoms   = nnatoms;
+   }
+   fNelements++;       
+   Int_t iel = fNelements-1;
    fZmixture[iel] = elem->Z();
    fAmixture[iel] = elem->A();
-   fWeights[iel]  = natoms;
-   Double_t amol = 0.;
+   fNatoms[iel]  = natoms;
+   fElements->AddAt(elem, iel);
+   amol = 0.;
    for (i=0; i<fNelements; i++) {
-      if (fWeights[i]<=0) return;
-      amol += fAmixture[i]*fWeights[i];
+      if (fNatoms[i]<=0) return;
+      amol += fAmixture[i]*fNatoms[i];
    }   
-   for (i=0; i<fNelements; i++) {
-      fWeights[i] *= fAmixture[i]/amol;
-      DefineElement(i, fAmixture[i], fZmixture[i], fWeights[i]);
-   }
+   for (i=0; i<fNelements; i++) fWeights[i] = fNatoms[i]*fAmixture[i]/amol;
+   AverageProperties();
 }          
 
+//-----------------------------------------------------------------------------
+void TGeoMixture::DefineElement(Int_t /*iel*/, Int_t z, Int_t natoms)
+{
+// Define the mixture element at index iel by number of atoms in the chemical formula.
+   TGeoElementTable *table = gGeoManager->GetElementTable();
+   TGeoElement *elem = table->GetElement(z);
+   if (!elem) Fatal("DefineElement", "In mixture %s, element with Z=%i not found",GetName(),z);
+   AddElement(elem, natoms);
+}
+   
 //-----------------------------------------------------------------------------
 TGeoElement *TGeoMixture::GetElement(Int_t i) const
 {
@@ -407,6 +561,9 @@ TGeoElement *TGeoMixture::GetElement(Int_t i) const
       Error("GetElement", "Mixture %s has only %d elements", GetName(), fNelements);
       return 0;
    }   
+   TGeoElement *elem = 0;
+   if (fElements) elem = (TGeoElement*)fElements->At(i);
+   if (elem) return elem;
    TGeoElementTable *table = gGeoManager->GetElementTable();
    return table->GetElement(Int_t(fZmixture[i]));
 }
@@ -440,7 +597,9 @@ void TGeoMixture::Print(const Option_t * /*option*/) const
    printf("Mixture %s %s   Aeff=%g Zeff=%g rho=%g radlen=%g index=%i\n", GetName(), GetTitle(),
           fA,fZ,fDensity, fRadLen, fIndex);
    for (Int_t i=0; i<fNelements; i++) {
-      printf("   Element #%i : Z=%6.2f A=%6.2f w=%6.2f\n", i, fZmixture[i],
+      if (fNatoms) printf("   Element #%i : Z=%6.2f A=%6.2f w=%6.2f natoms=%i\n", i, fZmixture[i],
+             fAmixture[i], fWeights[i], fNatoms[i]);
+      else printf("   Element #%i : Z=%6.2f A=%6.2f w=%6.2f\n", i, fZmixture[i],
              fAmixture[i], fWeights[i]);
    }
 }
diff --git a/geom/src/TGeoVolume.cxx b/geom/src/TGeoVolume.cxx
index 938a49dcc70..66af45016f4 100644
--- a/geom/src/TGeoVolume.cxx
+++ b/geom/src/TGeoVolume.cxx
@@ -1,4 +1,4 @@
-// @(#)root/geom:$Name:  $:$Id: TGeoVolume.cxx,v 1.83 2006/05/24 17:11:54 brun Exp $
+// @(#)root/geom:$Name:  $:$Id: TGeoVolume.cxx,v 1.84 2006/05/26 16:26:25 brun Exp $
 // Author: Andrei Gheata   30/05/02
 // Divide(), CheckOverlaps() implemented by Mihaela Gheata
 
@@ -1650,7 +1650,7 @@ void TGeoVolume::SetVisibility(Bool_t vis)
    }   
    TGeoAtt::SetVisibility(vis);
    if (fGeoManager->IsClosed()) SetVisTouched(kTRUE);
-   fGeoManager->ModifiedPad();
+   fGeoManager->SetVisOption(4);
    TSeqCollection *brlist = gROOT->GetListOfBrowsers();
    TIter next(brlist);
    TBrowser *browser = 0;
@@ -1737,7 +1737,7 @@ void TGeoVolume::VisibleDaughters(Bool_t vis)
 // set visibility for daughters
    SetVisDaughters(vis);
    if (fGeoManager->IsClosed()) SetVisTouched(kTRUE);
-   fGeoManager->ModifiedPad();
+   fGeoManager->SetVisOption(4);
 }
 
 //_____________________________________________________________________________
diff --git a/geompainter/inc/TGeoPainter.h b/geompainter/inc/TGeoPainter.h
index 62e24cb2962..6f2198b0935 100644
--- a/geompainter/inc/TGeoPainter.h
+++ b/geompainter/inc/TGeoPainter.h
@@ -125,6 +125,7 @@ public:
    TH2F              *LegoPlot(Int_t ntheta=60, Double_t themin=0., Double_t themax=180.,
                             Int_t nphi=90, Double_t phimin=0., Double_t phimax=360.,
                             Double_t rmin=0., Double_t rmax=9999999, Option_t *option="");
+   void               Lock(Bool_t flag = kTRUE) {fVisLock = flag;}
    virtual void       ModifiedPad() const;
    virtual void       Paint(Option_t *option="");
    virtual void       PaintNode(TGeoNode *node, Option_t *option="");
diff --git a/geompainter/src/TGeoPainter.cxx b/geompainter/src/TGeoPainter.cxx
index 33ee73d6961..e2533fb4b92 100644
--- a/geompainter/src/TGeoPainter.cxx
+++ b/geompainter/src/TGeoPainter.cxx
@@ -1,4 +1,4 @@
-// @(#)root/geompainter:$Name:  $:$Id: TGeoPainter.cxx,v 1.87 2006/05/26 16:26:25 brun Exp $
+// @(#)root/geompainter:$Name:  $:$Id: TGeoPainter.cxx,v 1.88 2006/06/04 09:35:24 brun Exp $
 // Author: Andrei Gheata   05/03/02
 /*************************************************************************
  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
@@ -344,38 +344,6 @@ Int_t TGeoPainter::DistanceToPrimitiveVol(TGeoVolume *volume, Int_t px, Int_t py
    TGeoVolume *vol = volume;
    Bool_t vis = vol->IsVisible();
 //   Bool_t drawDaughters = kTRUE;
-   // Do I need to look for the top volume ?
-   if (fTopVisible && vis) {
-      dist = vol->GetShape()->DistancetoPrimitive(px,py);
-      if (dist<maxdist) {
-         fVolInfo = vol->GetName();
-         gPad->SetSelected(vol);
-         box = (TGeoBBox*)vol->GetShape();
-         memcpy(fCheckedBox, box->GetOrigin(), 3*sizeof(Double_t));
-         fCheckedBox[3] = box->GetDX();
-         fCheckedBox[4] = box->GetDY();
-         fCheckedBox[5] = box->GetDZ();
-         return 0;
-      }
-      return dist;
-   }      
-   // Is this the only volume?
-   if (volume->IsVisOnly()) {
-      if (!fTopVisible) {
-         dist = vol->GetShape()->DistancetoPrimitive(px,py);
-         if (dist<maxdist) {
-            fVolInfo = vol->GetName();
-            gPad->SetSelected(vol);
-            box = (TGeoBBox*)vol->GetShape();
-            memcpy(fCheckedBox, box->GetOrigin(), 3*sizeof(Double_t));
-            fCheckedBox[3] = box->GetDX();
-            fCheckedBox[4] = box->GetDY();
-            fCheckedBox[5] = box->GetDZ();
-            return 0;
-         }
-      } 
-      return dist;  
-   }      
    // Do we need to check a branch only?
    if (volume->IsVisBranch()) {
       if (!fGeoManager->IsClosed()) return big;
@@ -404,6 +372,23 @@ Int_t TGeoPainter::DistanceToPrimitiveVol(TGeoVolume *volume, Int_t px, Int_t py
       return dist;
    }      
 
+   // Do I need to look for the top volume ?
+   if ((fTopVisible && vis) || !vol->GetNdaughters() || !vol->IsVisDaughters() || vol->IsVisOnly()) {
+      dist = vol->GetShape()->DistancetoPrimitive(px,py);
+      if (dist<maxdist) {
+         fVolInfo = vol->GetName();
+         gPad->SetSelected(vol);
+         box = (TGeoBBox*)vol->GetShape();
+         memcpy(fCheckedBox, box->GetOrigin(), 3*sizeof(Double_t));
+         fCheckedBox[3] = box->GetDX();
+         fCheckedBox[4] = box->GetDY();
+         fCheckedBox[5] = box->GetDZ();
+         return 0;
+      }
+      if (vol->IsVisOnly() || !vol->GetNdaughters() || !vol->IsVisDaughters())
+         return dist;
+   }      
+
    // Iterate the volume content
    TGeoIterator next(vol);
    next.SetTopName(Form("%s_1",vol->GetName()));
@@ -460,7 +445,7 @@ Int_t TGeoPainter::DistanceToPrimitiveVol(TGeoVolume *volume, Int_t px, Int_t py
             }
          }
          // Check if we have to skip the branch
-         if (last) next.Skip();
+         if (last || !daughter->IsVisDaughters()) next.Skip();
       }
    }
    return dist;
@@ -1102,37 +1087,11 @@ void TGeoPainter::PaintVolume(TGeoVolume *top, Option_t *option)
    fGlobal->Clear();
    TGeoShape::SetTransform(fGlobal);
    Bool_t drawDaughters = kTRUE;
-   Bool_t vis = top->IsVisible();
+   Bool_t vis = (top->IsVisible() && !top->IsAssembly());
 
    // Update pad attributes in case we need to paint VOL
    if (!strstr(option,"range")) ((TAttLine*)vol)->Modify();
 
-   // Do I need to draw the top volume ?
-   if (fTopVisible && vis) {
-      fGeoManager->SetPaintVolume(vol);
-      fGeoManager->SetMatrixReflection(kFALSE);
-      drawDaughters = PaintShape(*(vol->GetShape()),option);
-      if (!fVisLock && !vol->TestAttBit(TGeoAtt::kVisOnScreen)) {
-         fVisVolumes->Add(vol);
-         vol->SetAttBit(TGeoAtt::kVisOnScreen);
-      }   
-   }   
-
-   // Do we need to draw only this volume ?
-   if (top->IsVisOnly()) {
-      if (!fTopVisible) {
-         fGeoManager->SetPaintVolume(vol);
-         fGeoManager->SetMatrixReflection(kFALSE);
-         drawDaughters = PaintShape(*(vol->GetShape()),option);
-      }   
-      if (!fVisLock && !vol->TestAttBit(TGeoAtt::kVisOnScreen)) {
-         fVisVolumes->Add(vol);
-         vol->SetAttBit(TGeoAtt::kVisOnScreen);
-      }         
-      fVisLock = kTRUE;
-      return;
-   }   
-
    // Do we need to draw a branch ?
    if (top->IsVisBranch()) {
       fGeoManager->PushPath();
@@ -1160,6 +1119,21 @@ void TGeoPainter::PaintVolume(TGeoVolume *top, Option_t *option)
       return;
    }   
       
+   // Do I need to draw the top volume ?
+   if ((fTopVisible && vis) || !top->GetNdaughters() || !top->IsVisDaughters() || top->IsVisOnly()) {
+      fGeoManager->SetPaintVolume(vol);
+      fGeoManager->SetMatrixReflection(kFALSE);
+      drawDaughters = PaintShape(*(vol->GetShape()),option);
+      if (!fVisLock && !vol->TestAttBit(TGeoAtt::kVisOnScreen)) {
+         fVisVolumes->Add(vol);
+         vol->SetAttBit(TGeoAtt::kVisOnScreen);
+      } 
+      if (top->IsVisOnly() || !top->GetNdaughters() || !top->IsVisDaughters()) {
+         fVisLock = kTRUE;
+         return;
+      }    
+   }   
+
    // Iterate the volume content
    TGeoIterator next(vol);
    TGeoNode *daughter;
@@ -1203,7 +1177,7 @@ void TGeoPainter::PaintVolume(TGeoVolume *top, Option_t *option)
             }   
          }
          // Check if we have to skip the branch
-         if (!drawDaughters || last) next.Skip();
+         if (!drawDaughters || last || !daughter->IsVisDaughters()) next.Skip();
       }
    }
    fGeoManager->SetMatrixReflection(kFALSE);
@@ -1633,10 +1607,20 @@ void TGeoPainter::SetVisOption(Int_t option) {
 // 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)) {
+   if ((fVisOption<0) || (fVisOption>4)) {
       Warning("SetVisOption", "wrong visualization option");
       return;
    }
+   
+   if (option == kGeoVisChanged) {
+      if (fVisLock) {
+         ClearVisibleVolumes();
+         fVisLock = kFALSE;
+      }   
+      ModifiedPad();
+      return;
+   }
+   
    if (fTopVolume) {
       TGeoAtt *att = (TGeoAtt*)fTopVolume;
       att->SetAttBit(TGeoAtt::kVisBranch,kFALSE);
-- 
GitLab