00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 
00186 
00187 
00188 
00189 
00190 
00191 
00192 
00193 
00194 
00195 
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235 
00236 
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 
00271 
00272 
00273 
00274 
00275 
00276 
00277 
00278 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 #include "Riostream.h"
00336 #include "TString.h"
00337 #include "TBrowser.h"
00338 #include "TStyle.h"
00339 #include "TH2F.h"
00340 #include "TPad.h"
00341 #include "TROOT.h"
00342 #include "TClass.h"
00343 #include "TEnv.h"
00344 #include "TMap.h"
00345 #include "TFile.h"
00346 #include "TKey.h"
00347 
00348 #include "TGeoManager.h"
00349 #include "TGeoNode.h"
00350 #include "TGeoMatrix.h"
00351 #include "TVirtualGeoPainter.h"
00352 #include "TGeoVolume.h"
00353 #include "TGeoShapeAssembly.h"
00354 #include "TGeoScaledShape.h"
00355 #include "TGeoCompositeShape.h"
00356 #include "TGeoVoxelFinder.h"
00357 
00358 ClassImp(TGeoVolume)
00359 
00360 
00361 TGeoVolume::TGeoVolume()
00362 { 
00363 
00364    fNodes    = 0;
00365    fShape    = 0;
00366    fFinder   = 0;
00367    fVoxels   = 0;
00368    fField    = 0;
00369    fMedium   = 0;
00370    fNumber   = 0;
00371    fNtotal   = 0;
00372    fOption   = "";
00373    fGeoManager = gGeoManager;
00374    TObject::ResetBit(kVolumeImportNodes);
00375 }
00376 
00377 
00378 TGeoVolume::TGeoVolume(const char *name, const TGeoShape *shape, const TGeoMedium *med)
00379            :TNamed(name, "")
00380 {
00381 
00382    fName = fName.Strip();
00383    fNodes    = 0;
00384    fShape    = (TGeoShape*)shape;
00385    if (fShape) {
00386       if (fShape->TestShapeBit(TGeoShape::kGeoBad)) {
00387          Warning("Ctor", "volume %s has invalid shape", name);
00388       }
00389       if (!fShape->IsValid()) {
00390          Fatal("ctor", "Shape of volume %s invalid. Aborting!", fName.Data());
00391       }   
00392    }      
00393    fFinder   = 0;
00394    fVoxels   = 0;
00395    fField    = 0;
00396    fOption   = "";
00397    fMedium   = (TGeoMedium*)med;
00398    if (fMedium) {
00399       if (fMedium->GetMaterial()) fMedium->GetMaterial()->SetUsed();
00400    }   
00401    fNumber   = 0;
00402    fNtotal   = 0;
00403    fGeoManager = gGeoManager;
00404    if (fGeoManager) fNumber = fGeoManager->AddVolume(this);
00405    TObject::ResetBit(kVolumeImportNodes);
00406 }
00407 
00408 
00409 TGeoVolume::TGeoVolume(const TGeoVolume& gv) :
00410   TNamed(gv),
00411   TGeoAtt(gv),
00412   TAttLine(gv),
00413   TAttFill(gv),
00414   TAtt3D(gv),
00415   fNodes(gv.fNodes),
00416   fShape(gv.fShape),
00417   fMedium(gv.fMedium),
00418   fFinder(gv.fFinder),
00419   fVoxels(gv.fVoxels),
00420   fGeoManager(gv.fGeoManager),
00421   fField(gv.fField),
00422   fOption(gv.fOption),
00423   fNumber(gv.fNumber),
00424   fNtotal(gv.fNtotal)
00425 { 
00426    
00427 }
00428 
00429 
00430 TGeoVolume& TGeoVolume::operator=(const TGeoVolume& gv) 
00431 {
00432    
00433    if(this!=&gv) {
00434       TNamed::operator=(gv);
00435       TGeoAtt::operator=(gv);
00436       TAttLine::operator=(gv);
00437       TAttFill::operator=(gv);
00438       TAtt3D::operator=(gv);
00439       fNodes=gv.fNodes;
00440       fShape=gv.fShape;
00441       fMedium=gv.fMedium;
00442       fFinder=gv.fFinder;
00443       fVoxels=gv.fVoxels;
00444       fGeoManager=gv.fGeoManager;
00445       fField=gv.fField;
00446       fOption=gv.fOption;
00447       fNumber=gv.fNumber;
00448       fNtotal=gv.fNtotal;
00449    } 
00450    return *this;
00451 }
00452 
00453 
00454 TGeoVolume::~TGeoVolume()
00455 {
00456 
00457    
00458    if (fNodes) { 
00459       if (!TObject::TestBit(kVolumeImportNodes)) {
00460          fNodes->Delete();
00461       }   
00462       delete fNodes;
00463    }
00464    if (fFinder && !TObject::TestBit(kVolumeImportNodes | kVolumeClone) ) delete fFinder;
00465    if (fVoxels) delete fVoxels;
00466 }
00467 
00468 
00469 void TGeoVolume::Browse(TBrowser *b)
00470 {
00471 
00472    if (!b) return;
00473 
00474 
00475    TGeoVolume *daughter;
00476    TString title;
00477    for (Int_t i=0; i<GetNdaughters(); i++) { 
00478       daughter = GetNode(i)->GetVolume();
00479       if(!strlen(daughter->GetTitle())) {
00480          if (daughter->IsAssembly()) title.TString::Format("Assembly with %d daughter(s)", 
00481                                                 daughter->GetNdaughters());
00482          else if (daughter->GetFinder()) {
00483             TString s1 = daughter->GetFinder()->ClassName();
00484             s1.ReplaceAll("TGeoPattern","");
00485             title.TString::Format("Volume having %s shape divided in %d %s slices",
00486                        daughter->GetShape()->ClassName(),daughter->GetNdaughters(), s1.Data()); 
00487                        
00488          } else title.TString::Format("Volume with %s shape having %d daughter(s)", 
00489                          daughter->GetShape()->ClassName(),daughter->GetNdaughters());
00490          daughter->SetTitle(title.Data());
00491       }   
00492       b->Add(daughter, daughter->GetName(), daughter->IsVisible());
00493 
00494 
00495 
00496 
00497    }
00498 }
00499 
00500 
00501 Double_t TGeoVolume::Capacity() const
00502 {
00503 
00504 
00505    if (!IsAssembly()) return fShape->Capacity();
00506    Double_t capacity = 0.0;
00507    Int_t nd = GetNdaughters();
00508    Int_t i;
00509    for (i=0; i<nd; i++) capacity += GetNode(i)->GetVolume()->Capacity();
00510    return capacity;
00511 }   
00512 
00513 
00514 void TGeoVolume::CheckGeometry(Int_t nrays, Double_t startx, Double_t starty, Double_t startz) const
00515 {
00516 
00517 
00518 
00519    TGeoVolume *old_vol = fGeoManager->GetTopVolume();
00520    if (old_vol!=this) fGeoManager->SetTopVolume((TGeoVolume*)this);
00521    else old_vol=0;
00522    fGeoManager->GetTopVolume()->Draw();
00523    TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
00524    painter->CheckGeometry(nrays, startx, starty, startz);
00525 }         
00526 
00527 
00528 void TGeoVolume::CheckOverlaps(Double_t ovlp, Option_t *option) const
00529 {
00530 
00531 
00532 
00533 
00534 
00535 
00536    if (!GetNdaughters() || fFinder) return;
00537    Bool_t sampling = kFALSE;
00538    TString opt(option);
00539    opt.ToLower();
00540    if (opt.Contains("s")) sampling = kTRUE;
00541    TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
00542    if (!sampling) fGeoManager->SetNsegments(80);
00543    if (!fGeoManager->IsCheckingOverlaps()) {
00544       fGeoManager->ClearOverlaps();
00545 
00546    }   
00547    painter->CheckOverlaps(this, ovlp, option);
00548 
00549    if (!fGeoManager->IsCheckingOverlaps()) {
00550       fGeoManager->SortOverlaps();
00551       TObjArray *overlaps = fGeoManager->GetListOfOverlaps();
00552       Int_t novlps = overlaps->GetEntriesFast();
00553       TNamed *obj;
00554       TString name;
00555       for (Int_t i=0; i<novlps; i++) {
00556          obj = (TNamed*)overlaps->At(i);
00557          if (novlps<1000) name = TString::Format("ov%03d", i);
00558          else             name = TString::Format("ov%06d", i);
00559          obj->SetName(name);
00560       }   
00561       if (novlps) Info("CheckOverlaps", "Number of illegal overlaps/extrusions for volume %s: %d\n", GetName(), novlps);
00562    }   
00563 }
00564 
00565 
00566 void TGeoVolume::CleanAll()
00567 {
00568 
00569    ClearNodes();
00570    ClearShape();
00571 }
00572 
00573 
00574 void TGeoVolume::ClearShape()
00575 {
00576 
00577    fGeoManager->ClearShape(fShape);
00578 }   
00579 
00580 
00581 void TGeoVolume::CheckShapes()
00582 {
00583 
00584 
00585 
00586    if (fShape->IsRunTimeShape()) {
00587       Error("CheckShapes", "volume %s has run-time shape", GetName());
00588       InspectShape();
00589       return;
00590    }   
00591    if (!fNodes) return;
00592    Int_t nd=fNodes->GetEntriesFast();
00593    TGeoNode *node = 0;
00594    TGeoNode *new_node;
00595    const TGeoShape *shape = 0;
00596    TGeoVolume *old_vol;
00597    for (Int_t i=0; i<nd; i++) {
00598       node=(TGeoNode*)fNodes->At(i);
00599       
00600       if (!strlen(node->GetName())) printf("Daughter %i of volume %s - NO NAME!!!\n",
00601                                            i, GetName());
00602       old_vol = node->GetVolume();
00603       shape = old_vol->GetShape();
00604       if (shape->IsRunTimeShape()) {
00605 
00606 
00607 
00608          
00609          new_node = node->MakeCopyNode();
00610          TGeoShape *new_shape = shape->GetMakeRuntimeShape(fShape, node->GetMatrix());
00611          if (!new_shape) {
00612             Error("CheckShapes","cannot resolve runtime shape for volume %s/%s\n",
00613                    GetName(),old_vol->GetName());
00614             continue;
00615          }         
00616          TGeoVolume *new_volume = old_vol->MakeCopyVolume(new_shape);
00617 
00618 
00619          new_node->SetVolume(new_volume);
00620          
00621          fNodes->AddAt(new_node, i);
00622 
00623       }
00624    }
00625 }     
00626 
00627 
00628 Int_t TGeoVolume::CountNodes(Int_t nlevels, Int_t option)
00629 {
00630 
00631 
00632 
00633 
00634 
00635    static Int_t maxlevel = 0;
00636    static Int_t nlev = 0;
00637    
00638    if (option<0 || option>3) option = 0;
00639    Int_t visopt = 0;
00640    Int_t nd = GetNdaughters();
00641    Bool_t last = (!nlevels || !nd)?kTRUE:kFALSE;
00642    switch (option) {
00643       case 0:
00644          if (fNtotal) return fNtotal;
00645       case 1:   
00646          fNtotal = 1;
00647          break;
00648       case 2:
00649          visopt = fGeoManager->GetVisOption();
00650          if (!IsVisDaughters()) last = kTRUE;
00651          switch (visopt) {
00652             case TVirtualGeoPainter::kGeoVisDefault:
00653                fNtotal = (IsVisible())?1:0;
00654                break;   
00655             case TVirtualGeoPainter::kGeoVisLeaves:
00656                fNtotal = (IsVisible() && last)?1:0;
00657          }
00658          if (!IsVisibleDaughters()) return fNtotal;
00659          break;
00660       case 3:
00661          return maxlevel;   
00662    }      
00663    if (last) return fNtotal;
00664    if (gGeoManager->GetTopVolume() == this) {
00665       maxlevel=0;
00666       nlev = 0;
00667    }   
00668    if (nlev>maxlevel) maxlevel = nlev;   
00669    TGeoNode *node;
00670    TGeoVolume *vol;
00671    nlev++;
00672    for (Int_t i=0; i<nd; i++) {
00673       node = GetNode(i);
00674       vol = node->GetVolume();
00675       fNtotal += vol->CountNodes(nlevels-1, option);
00676    }
00677    nlev--;
00678    return fNtotal;
00679 }
00680 
00681 
00682 Bool_t TGeoVolume::IsAllInvisible() const
00683 {
00684 
00685    if (IsVisible()) return kFALSE;
00686    Int_t nd = GetNdaughters();
00687    for (Int_t i=0; i<nd; i++) if (GetNode(i)->GetVolume()->IsVisible()) return kFALSE;
00688    return kTRUE;
00689 }   
00690 
00691 
00692 void TGeoVolume::InvisibleAll(Bool_t flag)
00693 {
00694 
00695    SetAttVisibility(!flag);
00696    Int_t nd = GetNdaughters();
00697    TObjArray *list = new TObjArray(nd+1);
00698    list->Add(this);
00699    TGeoVolume *vol;
00700    for (Int_t i=0; i<nd; i++) {
00701       vol = GetNode(i)->GetVolume();
00702       vol->SetAttVisibility(!flag);
00703       list->Add(vol);
00704    }
00705    TIter next(gROOT->GetListOfBrowsers());
00706    TBrowser *browser = 0;
00707    while ((browser=(TBrowser*)next())) {
00708       for (Int_t i=0; i<nd+1; i++) {
00709          vol = (TGeoVolume*)list->At(i);
00710          browser->CheckObjectItem(vol, !flag);
00711       }   
00712       browser->Refresh();
00713    }
00714    delete list;
00715    fGeoManager->SetVisOption(4);
00716 }   
00717 
00718 
00719 Bool_t TGeoVolume::IsFolder() const
00720 {
00721 
00722 
00723    return kTRUE;
00724 }
00725 
00726 
00727 Bool_t TGeoVolume::IsStyleDefault() const
00728 {
00729 
00730    if (!IsVisible()) return kFALSE;
00731    if (GetLineColor() != gStyle->GetLineColor()) return kFALSE;
00732    if (GetLineStyle() != gStyle->GetLineStyle()) return kFALSE;
00733    if (GetLineWidth() != gStyle->GetLineWidth()) return kFALSE;
00734    return kTRUE;
00735 }
00736 
00737 
00738 Bool_t TGeoVolume::IsTopVolume() const
00739 {
00740 
00741    if (fGeoManager->GetTopVolume() == this) return kTRUE;
00742    return kFALSE;
00743 }
00744 
00745 
00746 Bool_t TGeoVolume::IsRaytracing() const
00747 {
00748 
00749    return TGeoAtt::IsVisRaytrace();
00750 }
00751 
00752 
00753 void TGeoVolume::InspectMaterial() const
00754 {
00755 
00756    fMedium->GetMaterial()->Print();
00757 }
00758 
00759 
00760 TGeoVolume *TGeoVolume::Import(const char *filename, const char *name, Option_t * )
00761 {
00762 
00763    if (!gGeoManager) gGeoManager = new TGeoManager("geometry","");
00764    if (!filename) return 0;
00765    TGeoVolume *volume = 0;
00766    if (strstr(filename,".gdml")) {
00767    
00768    } else {
00769    
00770       TFile *old = gFile;
00771       TFile *f = TFile::Open(filename);
00772       if (!f || f->IsZombie()) {
00773          if (old) old->cd();
00774          printf("Error: TGeoVolume::Import : Cannot open file %s\n", filename);
00775          return 0;
00776       }
00777       if (name && strlen(name) > 0) {
00778          volume = (TGeoVolume*)f->Get(name);
00779       } else {
00780          TIter next(f->GetListOfKeys());
00781          TKey *key;
00782          while ((key = (TKey*)next())) {
00783             if (strcmp(key->GetClassName(),"TGeoVolume") != 0) continue;
00784             volume = (TGeoVolume*)key->ReadObj();
00785             break;
00786          }
00787       }
00788       if (old) old->cd();
00789       delete f;         
00790    }
00791    if (!volume) return NULL;
00792    volume->RegisterYourself();
00793    return volume;
00794 }
00795    
00796 
00797 Int_t TGeoVolume::Export(const char *filename, const char *name, Option_t *option)
00798 {
00799 
00800    
00801    
00802    
00803    
00804    
00805    
00806    
00807    
00808    
00809    
00810    
00811    
00812    
00813    TString sfile(filename);
00814    if (sfile.Contains(".C")) {
00815       
00816       Info("Export","Exporting volume %s as C++ code", GetName());
00817       SaveAs(filename, "");
00818       return 1;
00819    }
00820    if (sfile.Contains(".gdml")) {
00821      
00822       Info("Export","Exporting %s as gdml code - not implemented yet", GetName());
00823       return 0;
00824    }   
00825    if (sfile.Contains(".root") || sfile.Contains(".xml")) {  
00826       
00827       Info("Export","Exporting %s as root file.", GetName());
00828       TString opt(option);
00829       if (!opt.Length()) opt = "recreate";
00830       TFile *f = TFile::Open(filename,opt.Data());
00831       if (!f || f->IsZombie()) {
00832          Error("Export","Cannot open file");
00833          return 0;
00834       } 
00835       TString keyname(name);
00836       if (keyname.IsNull()) keyname = GetName();
00837       Int_t nbytes = Write(keyname);
00838       delete f;
00839       return nbytes;
00840    }
00841    return 0;
00842 }
00843 
00844 
00845 void TGeoVolume::cd(Int_t inode) const
00846 {
00847 
00848    if (fFinder) fFinder->cd(inode-fFinder->GetDivIndex());
00849 }
00850 
00851 
00852 void TGeoVolume::AddNode(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t * )
00853 {
00854 
00855 
00856    TGeoMatrix *matrix = mat;
00857    if (matrix==0) matrix = gGeoIdentity;
00858    else           matrix->RegisterYourself();
00859    if (!vol) {
00860       Error("AddNode", "Volume is NULL");
00861       return;
00862    }
00863    if (!vol->IsValid()) {
00864       Error("AddNode", "Won't add node with invalid shape");
00865       printf("### invalid volume was : %s\n", vol->GetName());
00866       return;
00867    }   
00868    if (!fNodes) fNodes = new TObjArray();   
00869 
00870    if (fFinder) {
00871       
00872       Error("AddNode", "Cannot add node %s_%i into divided volume %s", vol->GetName(), copy_no, GetName());
00873       return;
00874    }
00875 
00876    TGeoNodeMatrix *node = 0;
00877    node = new TGeoNodeMatrix(vol, matrix);
00878    node->SetMotherVolume(this);
00879    fNodes->Add(node);
00880    TString name = TString::Format("%s_%d", vol->GetName(), copy_no);
00881    if (fNodes->FindObject(name))
00882       Warning("AddNode", "Volume %s : added node %s with same name", GetName(), name.Data());
00883    node->SetName(name);
00884    node->SetNumber(copy_no);
00885 }
00886 
00887 
00888 void TGeoVolume::AddNodeOffset(const TGeoVolume *vol, Int_t copy_no, Double_t offset, Option_t * )
00889 {
00890 
00891 
00892    if (!vol) {
00893       Error("AddNodeOffset", "invalid volume");
00894       return;
00895    }
00896    if (!vol->IsValid()) {
00897       Error("AddNode", "Won't add node with invalid shape");
00898       printf("### invalid volume was : %s\n", vol->GetName());
00899       return;
00900    }   
00901    if (!fNodes) fNodes = new TObjArray();
00902    TGeoNode *node = new TGeoNodeOffset(vol, copy_no, offset);
00903    node->SetMotherVolume(this);
00904    fNodes->Add(node);
00905    TString name = TString::Format("%s_%d", vol->GetName(), copy_no+1);
00906    node->SetName(name);
00907    node->SetNumber(copy_no+1);
00908 }
00909 
00910 
00911 void TGeoVolume::AddNodeOverlap(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
00912 {
00913 
00914 
00915    if (!vol) {
00916       Error("AddNodeOverlap", "Volume is NULL");
00917       return;
00918    }
00919    if (!vol->IsValid()) {
00920       Error("AddNodeOverlap", "Won't add node with invalid shape");
00921       printf("### invalid volume was : %s\n", vol->GetName());
00922       return;
00923    }
00924    if (vol->IsAssembly()) {
00925       Warning("AddNodeOverlap", "Declaring assembly %s as possibly overlapping inside %s not allowed. Using AddNode instead !",vol->GetName(),GetName());
00926       AddNode(vol, copy_no, mat, option);
00927       return;
00928    }   
00929    TGeoMatrix *matrix = mat;
00930    if (matrix==0) matrix = gGeoIdentity;
00931    else           matrix->RegisterYourself();
00932    if (!fNodes) fNodes = new TObjArray();   
00933 
00934    if (fFinder) {
00935       
00936       Error("AddNodeOverlap", "Cannot add node %s_%i into divided volume %s", vol->GetName(), copy_no, GetName());
00937       return;
00938    }
00939 
00940    TGeoNodeMatrix *node = new TGeoNodeMatrix(vol, matrix);
00941    node->SetMotherVolume(this);
00942    fNodes->Add(node);
00943    TString name = TString::Format("%s_%d", vol->GetName(), copy_no);
00944    if (fNodes->FindObject(name))
00945       Warning("AddNode", "Volume %s : added node %s with same name", GetName(), name.Data());
00946    node->SetName(name);
00947    node->SetNumber(copy_no);
00948    node->SetOverlapping();
00949    if (vol->GetMedium() == fMedium)
00950    node->SetVirtual();
00951 }
00952 
00953 
00954 TGeoVolume *TGeoVolume::Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed, Option_t *option)
00955 {
00956 
00957 
00958 
00959 
00960 
00961 
00962 
00963 
00964 
00965 
00966 
00967 
00968    if (fFinder) {
00969    
00970       Fatal("Divide","volume %s already divided", GetName());
00971       return 0;
00972    }
00973    TString opt(option);
00974    opt.ToLower();
00975    TString stype = fShape->ClassName();
00976    if (!fNodes) fNodes = new TObjArray();
00977    Double_t xlo, xhi, range;
00978    range = fShape->GetAxisRange(iaxis, xlo, xhi);
00979    
00980    if (!strcmp(fShape->GetAxisName(iaxis), "PHI")) {
00981       if ((start-xlo)<-1E-3) start+=360.;
00982       if (TGeoShape::IsSameWithinTolerance(range,360)) {
00983          xlo = start;
00984          xhi = start+range;
00985       }   
00986    }   
00987    if (range <=0) {
00988       InspectShape();
00989       Fatal("Divide", "cannot divide volume %s (%s) on %s axis", GetName(), stype.Data(), fShape->GetAxisName(iaxis));
00990       return 0;
00991    }
00992    if (ndiv<=0 || opt.Contains("s")) {
00993       if (step<=0) {
00994          Fatal("Divide", "invalid division type for volume %s : ndiv=%i, step=%g", GetName(), ndiv, step);
00995          return 0;
00996       }   
00997       if (opt.Contains("x")) {
00998          if ((xlo-start)>1E-3 || (xhi-start)<-1E-3) {
00999             Fatal("Divide", "invalid START=%g for division on axis %s of volume %s. Range is (%g, %g)",
01000                   start, fShape->GetAxisName(iaxis), GetName(), xlo, xhi);
01001             return 0;
01002          }
01003          xlo = start;
01004          range = xhi-xlo;
01005       }            
01006       ndiv = Int_t((range+0.1*step)/step);
01007       Double_t ddx = range - ndiv*step;
01008       
01009       if (ddx>1E-3) Warning("Divide", "division of volume %s on %s axis (ndiv=%d) will be centered in the full range",
01010                             GetName(), fShape->GetAxisName(iaxis), ndiv);
01011       start = xlo + 0.5*ddx;
01012    }
01013    if (step<=0 || opt.Contains("n")) {
01014       if (opt.Contains("x")) {
01015          if ((xlo-start)>1E-3 || (xhi-start)<-1E-3) {
01016             Fatal("Divide", "invalid START=%g for division on axis %s of volume %s. Range is (%g, %g)",
01017                   start, fShape->GetAxisName(iaxis), GetName(), xlo, xhi);
01018             return 0;
01019          }
01020          xlo = start;
01021          range = xhi-xlo;
01022       }     
01023       step  = range/ndiv;
01024       start = xlo;
01025    }
01026    
01027    Double_t end = start+ndiv*step;
01028    if (((start-xlo)<-1E-3) || ((end-xhi)>1E-3)) {
01029       Fatal("Divide", "division of volume %s on axis %s exceed range (%g, %g)",
01030             GetName(), fShape->GetAxisName(iaxis), xlo, xhi);
01031       return 0;
01032    }         
01033    TGeoVolume *voldiv = fShape->Divide(this, divname, iaxis, ndiv, start, step);
01034    if (numed) {
01035       TGeoMedium *medium = fGeoManager->GetMedium(numed);
01036       if (!medium) {
01037          Fatal("Divide", "invalid medium number %d for division volume %s", numed, divname);
01038          return voldiv;
01039       }   
01040       voldiv->SetMedium(medium);
01041       if (medium->GetMaterial()) medium->GetMaterial()->SetUsed();
01042    }   
01043    return voldiv; 
01044 }
01045 
01046 
01047 Int_t TGeoVolume::DistancetoPrimitive(Int_t px, Int_t py)
01048 {
01049 
01050    if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
01051    TVirtualGeoPainter *painter = fGeoManager->GetPainter();
01052    Int_t dist = 9999;
01053    if (!painter) return dist;
01054    dist = painter->DistanceToPrimitiveVol(this, px, py);
01055    return dist;
01056 }
01057 
01058 
01059 void TGeoVolume::Draw(Option_t *option)
01060 {
01061 
01062    if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
01063    TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
01064    TGeoAtt::SetVisRaytrace(kFALSE);
01065    if (!IsVisContainers()) SetVisLeaves();
01066    if (option && strlen(option) > 0) {
01067       painter->DrawVolume(this, option); 
01068    } else {
01069       painter->DrawVolume(this, gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
01070    }  
01071 }
01072 
01073 
01074 void TGeoVolume::DrawOnly(Option_t *option)
01075 {
01076 
01077    if (IsAssembly()) {
01078       Info("DrawOnly", "Volume assemblies do not support this option.");
01079       return;
01080    }   
01081    if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
01082    SetVisOnly();
01083    TGeoAtt::SetVisRaytrace(kFALSE);
01084    TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
01085    if (option && strlen(option) > 0) {
01086       painter->DrawVolume(this, option); 
01087    } else {
01088       painter->DrawVolume(this, gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
01089    }  
01090 }
01091 
01092 
01093 Bool_t TGeoVolume::OptimizeVoxels()
01094 {
01095 
01096 
01097    printf("Optimizing volume %s ...\n", GetName());
01098    TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
01099    return painter->TestVoxels(this);   
01100 }
01101 
01102 
01103 void TGeoVolume::Paint(Option_t *option)
01104 {
01105 
01106    TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
01107    painter->SetTopVolume(this);
01108 
01109    if (option && strlen(option) > 0) {
01110       painter->Paint(option); 
01111    } else {
01112       painter->Paint(gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
01113    }  
01114 }
01115 
01116 
01117 void TGeoVolume::PrintVoxels() const
01118 {
01119 
01120    if (fVoxels) fVoxels->Print();
01121 }
01122 
01123 
01124 void TGeoVolume::ReplayCreation(const TGeoVolume *other)
01125 {
01126 
01127 
01128    Int_t nd = other->GetNdaughters();
01129    if (!nd) return;
01130    TGeoPatternFinder *finder = other->GetFinder();
01131    if (finder) {
01132       Int_t iaxis = finder->GetDivAxis();
01133       Int_t ndiv = finder->GetNdiv();
01134       Double_t start = finder->GetStart();
01135       Double_t step = finder->GetStep();
01136       Int_t numed = other->GetNode(0)->GetVolume()->GetMedium()->GetId();
01137       TGeoVolume *voldiv = Divide(other->GetNode(0)->GetVolume()->GetName(), iaxis, ndiv, start, step, numed);
01138       voldiv->ReplayCreation(other->GetNode(0)->GetVolume());
01139       return;
01140    }   
01141    for (Int_t i=0; i<nd; i++) {
01142       TGeoNode *node = other->GetNode(i);
01143       if (node->IsOverlapping()) AddNodeOverlap(node->GetVolume(), node->GetNumber(), node->GetMatrix());
01144       else AddNode(node->GetVolume(), node->GetNumber(), node->GetMatrix());
01145    }
01146 }      
01147    
01148 
01149 void TGeoVolume::PrintNodes() const
01150 {
01151 
01152    Int_t nd = GetNdaughters();
01153    for (Int_t i=0; i<nd; i++) {
01154       printf("%s\n", GetNode(i)->GetName());
01155       cd(i);
01156       GetNode(i)->GetMatrix()->Print();
01157    }   
01158 }
01159 
01160 TH2F *TGeoVolume::LegoPlot(Int_t ntheta, Double_t themin, Double_t themax,
01161                             Int_t nphi,   Double_t phimin, Double_t phimax,
01162                             Double_t rmin, Double_t rmax, Option_t *option)
01163 {
01164 
01165    TVirtualGeoPainter *p = fGeoManager->GetGeomPainter();
01166    TGeoVolume *old_vol = fGeoManager->GetTopVolume();
01167    if (old_vol!=this) fGeoManager->SetTopVolume(this);
01168    else old_vol=0;
01169    TH2F *hist = p->LegoPlot(ntheta, themin, themax, nphi, phimin, phimax, rmin, rmax, option);   
01170    hist->Draw("lego1sph");
01171    return hist;
01172 }
01173 
01174 
01175 void TGeoVolume::RegisterYourself(Option_t *option)
01176 {
01177 
01178    if (fGeoManager->GetListOfVolumes()->FindObject(this)) return;
01179    
01180    fGeoManager->AddVolume(this);
01181    
01182    if (!fGeoManager->GetListOfShapes()->FindObject(fShape)) {
01183       if (fShape->IsComposite()) {
01184          TGeoCompositeShape *comp = (TGeoCompositeShape*)fShape;
01185          comp->RegisterYourself();
01186       } else {
01187          fGeoManager->AddShape(fShape);   
01188       }
01189    }   
01190    
01191    if (fMedium && !fGeoManager->GetListOfMedia()->FindObject(fMedium)) {
01192       fGeoManager->GetListOfMedia()->Add(fMedium);
01193       if (!fGeoManager->GetListOfMaterials()->FindObject(fMedium->GetMaterial()))
01194          fGeoManager->AddMaterial(fMedium->GetMaterial());
01195    }
01196    
01197    TGeoMatrix *matrix;
01198    TGeoNode *node;
01199    Int_t nd = GetNdaughters();
01200    Int_t i;
01201    for (i=0; i<nd; i++) {
01202       node = GetNode(i);
01203       matrix = node->GetMatrix();
01204       if (!matrix->IsRegistered()) matrix->RegisterYourself();
01205       else if (!fGeoManager->GetListOfMatrices()->FindObject(matrix)) {
01206          fGeoManager->GetListOfMatrices()->Add(matrix);
01207       }
01208    }
01209    
01210    for (i=0; i<nd; i++) GetNode(i)->GetVolume()->RegisterYourself(option);
01211 }      
01212       
01213 
01214 void TGeoVolume::RandomPoints(Int_t npoints, Option_t *option)
01215 {
01216 
01217    if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
01218    TGeoVolume *old_vol = fGeoManager->GetTopVolume();
01219    if (old_vol!=this) fGeoManager->SetTopVolume(this);
01220    else old_vol=0;
01221    fGeoManager->RandomPoints(this, npoints, option);
01222    if (old_vol) fGeoManager->SetTopVolume(old_vol);
01223 }
01224 
01225 
01226 void TGeoVolume::RandomRays(Int_t nrays, Double_t startx, Double_t starty, Double_t startz)
01227 {
01228 
01229    if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
01230    TGeoVolume *old_vol = fGeoManager->GetTopVolume();
01231    if (old_vol!=this) fGeoManager->SetTopVolume(this);
01232    else old_vol=0;
01233    fGeoManager->RandomRays(nrays, startx, starty, startz);
01234    if (old_vol) fGeoManager->SetTopVolume(old_vol);
01235 }
01236 
01237 
01238 void TGeoVolume::Raytrace(Bool_t flag)
01239 {
01240 
01241    TGeoAtt::SetVisRaytrace(kFALSE);
01242    if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
01243    TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
01244    Bool_t drawn = (painter->GetDrawnVolume()==this)?kTRUE:kFALSE;   
01245    if (!drawn) {
01246       painter->DrawVolume(this, "");
01247       TGeoAtt::SetVisRaytrace(flag);
01248       painter->ModifiedPad();
01249       return;
01250    }   
01251    TGeoAtt::SetVisRaytrace(flag);
01252    painter->ModifiedPad();
01253 }   
01254 
01255 
01256 void TGeoVolume::SaveAs(const char *filename, Option_t *option) const
01257 {
01258 
01259    if (!filename) return;
01260    ofstream out;
01261    out.open(filename, ios::out);
01262    if (out.bad()) {
01263       Error("SavePrimitive", "Bad file name: %s", filename);
01264       return;
01265    }
01266    if (fGeoManager->GetTopVolume() != this) fGeoManager->SetTopVolume((TGeoVolume*)this);
01267    
01268    TString fname(filename);
01269    Int_t ind = fname.Index(".");
01270    if (ind>0) fname.Remove(ind);
01271    out << "void "<<fname<<"() {" << endl;
01272    out << "   gSystem->Load(\"libGeom\");" << endl;
01273    ((TGeoVolume*)this)->SavePrimitive(out,option);
01274    out << "}" << endl;
01275 }   
01276 
01277 
01278 void TGeoVolume::SavePrimitive(ostream &out, Option_t *option )
01279 {
01280    
01281    out.precision(6);
01282    out.setf(ios::fixed);
01283    Int_t i,icopy;
01284    Int_t nd = GetNdaughters();
01285    TGeoVolume *dvol;
01286    TGeoNode *dnode;
01287    TGeoMatrix *matrix;
01288 
01289    
01290    Bool_t mustDraw = kFALSE;
01291    if (fGeoManager->GetGeomPainter()->GetTopVolume()==this) mustDraw = kTRUE;
01292    if (!strlen(option)) {
01293       fGeoManager->SetAllIndex();
01294       out << "   new TGeoManager(\"" << fGeoManager->GetName() << "\", \"" << fGeoManager->GetTitle() << "\");" << endl << endl;
01295 
01296 
01297       out << "   Double_t dx,dy,dz;" << endl;
01298       out << "   Double_t dx1, dx2, dy1, dy2;" << endl;
01299       out << "   Double_t vert[20], par[20];" << endl;
01300       out << "   Double_t theta, phi, h1, bl1, tl1, alpha1, h2, bl2, tl2, alpha2;" << endl;
01301       out << "   Double_t twist;" << endl;
01302       out << "   Double_t origin[3];" << endl;
01303       out << "   Double_t rmin, rmax, rmin1, rmax1, rmin2, rmax2;" << endl;
01304       out << "   Double_t r, rlo, rhi;" << endl;
01305       out << "   Double_t phi1, phi2;" << endl;
01306       out << "   Double_t a,b;" << endl;
01307       out << "   Double_t point[3], norm[3];" << endl;
01308       out << "   Double_t rin, stin, rout, stout;" << endl;
01309       out << "   Double_t thx, phx, thy, phy, thz, phz;" << endl;
01310       out << "   Double_t alpha, theta1, theta2, phi1, phi2, dphi;" << endl;
01311       out << "   Double_t tr[3], rot[9];" << endl;
01312       out << "   Double_t z, density, radl, absl, w;" << endl;
01313       out << "   Double_t lx,ly,lz,tx,ty,tz;" << endl;
01314       out << "   Double_t xvert[50], yvert[50];" << endl;
01315       out << "   Double_t zsect,x0,y0,scale0;" << endl;
01316       out << "   Int_t nel, numed, nz, nedges, nvert;" << endl;
01317       out << "   TGeoBoolNode *pBoolNode = 0;" << endl << endl;
01318       
01319       out << "   // MATERIALS, MIXTURES AND TRACKING MEDIA" << endl;
01320       SavePrimitive(out, "m");
01321       
01322       out << endl << "   // TRANSFORMATION MATRICES" << endl;
01323       SavePrimitive(out, "x");
01324       
01325       SavePrimitive(out, "s");
01326       out << endl << "   // SET TOP VOLUME OF GEOMETRY" << endl;
01327       out << "   gGeoManager->SetTopVolume(" << GetPointerName() << ");" << endl;
01328       
01329       out << endl << "   // SHAPES, VOLUMES AND GEOMETRICAL HIERARCHY" << endl;
01330       SavePrimitive(out, "d");
01331       out << endl << "   // CLOSE GEOMETRY" << endl;
01332       out << "   gGeoManager->CloseGeometry();" << endl;
01333       if (mustDraw) {
01334          if (!IsRaytracing()) out << "   gGeoManager->GetTopVolume()->Draw();" << endl;
01335          else                 out << "   gGeoManager->GetTopVolume()->Raytrace();" << endl;
01336       }
01337       return;
01338    }
01339    
01340    if (!strcmp(option, "s")) {
01341       
01342       if (TestAttBit(TGeoAtt::kSavePrimitiveAtt)) return;
01343       if (!IsAssembly()) {
01344          fShape->SavePrimitive(out,option);      
01345          out << "   // Volume: " << GetName() << endl;
01346          out << "   " << GetPointerName() << " = new TGeoVolume(\"" << GetName() << "\"," << fShape->GetPointerName() << ", "<< fMedium->GetPointerName() << ");" << endl;
01347       } else {
01348          out << "   // Assembly: " << GetName() << endl;
01349          out << "   " << GetPointerName() << " = new TGeoVolumeAssembly(\"" << GetName() << "\"" << ");" << endl;
01350       }           
01351       if (fLineColor != 1) out << "   " << GetPointerName() << "->SetLineColor(" << fLineColor << ");" << endl;
01352       if (fLineWidth != 1) out << "   " << GetPointerName() << "->SetLineWidth(" << fLineWidth << ");" << endl;
01353       if (fLineStyle != 1) out << "   " << GetPointerName() << "->SetLineStyle(" << fLineStyle << ");" << endl;
01354       if (!IsVisible() && !IsAssembly()) out << "   " << GetPointerName() << "->SetVisibility(kFALSE);" << endl;
01355       if (!IsVisibleDaughters()) out << "   " << GetPointerName() << "->VisibleDaughters(kFALSE);" << endl;
01356       if (IsVisContainers()) out << "   " << GetPointerName() << "->SetVisContainers(kTRUE);" << endl;
01357       if (IsVisLeaves()) out << "   " << GetPointerName() << "->SetVisLeaves(kTRUE);" << endl;
01358       SetAttBit(TGeoAtt::kSavePrimitiveAtt);
01359    }   
01360    
01361    if (!strcmp(option, "m")) {
01362       if (fMedium) fMedium->SavePrimitive(out,option);
01363       for (i=0; i<nd; i++) {
01364          dvol = GetNode(i)->GetVolume();
01365          dvol->SavePrimitive(out,option);
01366       }
01367       return;      
01368    }   
01369    
01370    if (!strcmp(option, "x")) {
01371       if (fFinder) {
01372          dvol = GetNode(0)->GetVolume();
01373          dvol->SavePrimitive(out,option);
01374          return;
01375       }
01376       for (i=0; i<nd; i++) {
01377          dnode = GetNode(i);
01378          matrix = dnode->GetMatrix();
01379          if (!matrix->IsIdentity()) matrix->SavePrimitive(out,option);
01380          dnode->GetVolume()->SavePrimitive(out,option);
01381       }
01382       return;      
01383    } 
01384    
01385    if (!strcmp(option, "d")) {
01386       if (!nd) return;
01387       if (TestAttBit(TGeoAtt::kSaveNodesAtt)) return;
01388       SetAttBit(TGeoAtt::kSaveNodesAtt);     
01389       if (fFinder) {
01390          
01391          dnode = GetNode(0);
01392          dvol = dnode->GetVolume();
01393          out << "   TGeoVolume *" << dvol->GetPointerName() << " = ";
01394          out << GetPointerName() << "->Divide(\"" << dvol->GetName() << "\", ";
01395          fFinder->SavePrimitive(out,option);
01396          if (fMedium != dvol->GetMedium()) {
01397             out << ", " << dvol->GetMedium()->GetId();
01398          }
01399          out << ");" << endl;   
01400          dvol->SavePrimitive(out,"d");   
01401          return;
01402       }
01403       for (i=0; i<nd; i++) {
01404          dnode = GetNode(i);
01405          dvol = dnode->GetVolume();
01406          dvol->SavePrimitive(out,"s");
01407          matrix = dnode->GetMatrix();
01408          icopy = dnode->GetNumber();
01409          
01410          out << "   " << GetPointerName() << "->AddNode";
01411          if (dnode->IsOverlapping()) out << "Overlap";
01412          out << "(" << dvol->GetPointerName() << ", " << icopy;
01413          if (!matrix->IsIdentity()) out << ", " << matrix->GetPointerName();
01414          out << ");" << endl;
01415       }
01416       
01417       for (i=0; i<nd; i++) {
01418          dnode = GetNode(i);
01419          dvol = dnode->GetVolume();
01420          dvol->SavePrimitive(out,"d");
01421       } 
01422    }   
01423 }
01424 
01425 
01426 void TGeoVolume::UnmarkSaved()
01427 {
01428 
01429    ResetAttBit(TGeoAtt::kSavePrimitiveAtt);
01430    ResetAttBit(TGeoAtt::kSaveNodesAtt);
01431    if (fShape) fShape->ResetBit(TGeoShape::kGeoSavePrimitive);
01432 }   
01433 
01434 
01435 void TGeoVolume::ExecuteEvent(Int_t event, Int_t px, Int_t py)
01436 {
01437 
01438    TVirtualGeoPainter *painter = fGeoManager->GetPainter();
01439    if (!painter) return;
01440    painter->ExecuteVolumeEvent(this, event, px, py);
01441 }
01442 
01443 
01444 TGeoNode *TGeoVolume::FindNode(const char *name) const
01445 {
01446 
01447    return ((TGeoNode*)fNodes->FindObject(name));
01448 }
01449 
01450 
01451 Int_t TGeoVolume::GetNodeIndex(const TGeoNode *node, Int_t *check_list, Int_t ncheck) const
01452 {
01453 
01454    TGeoNode *current = 0;
01455    for (Int_t i=0; i<ncheck; i++) {
01456       current = (TGeoNode*)fNodes->At(check_list[i]);
01457       if (current==node) return check_list[i];
01458    }
01459    return -1;
01460 }
01461 
01462 
01463 Int_t TGeoVolume::GetIndex(const TGeoNode *node) const
01464 {
01465 
01466    TGeoNode *current = 0;
01467    Int_t nd = GetNdaughters();
01468    if (!nd) return -1;
01469    for (Int_t i=0; i<nd; i++) {
01470       current = (TGeoNode*)fNodes->At(i);
01471       if (current==node) return i;
01472    }
01473    return -1;
01474 }
01475 
01476 
01477 char *TGeoVolume::GetObjectInfo(Int_t px, Int_t py) const
01478 {
01479 
01480    TGeoVolume *vol = (TGeoVolume*)this;
01481    TVirtualGeoPainter *painter = fGeoManager->GetPainter();
01482    if (!painter) return 0;
01483    return (char*)painter->GetVolumeInfo(vol, px, py);
01484 }
01485 
01486 
01487 Bool_t TGeoVolume::GetOptimalVoxels() const
01488 {
01489 
01490    Int_t nd = GetNdaughters();
01491    if (!nd) return kFALSE;
01492    Int_t id;
01493    Int_t ncyl = 0;
01494    TGeoNode *node;
01495    for (id=0; id<nd; id++) {
01496       node = (TGeoNode*)fNodes->At(id);
01497       ncyl += node->GetOptimalVoxels();
01498    }
01499    if (ncyl>(nd/2)) return kTRUE;
01500    return kFALSE;
01501 }      
01502 
01503 
01504 char *TGeoVolume::GetPointerName() const
01505 {
01506 
01507    static TString name;
01508    name = TString::Format("p%s_%lx", GetName(), (ULong_t)this);
01509    return (char*)name.Data();
01510 }
01511 
01512 
01513 TGeoVoxelFinder *TGeoVolume::GetVoxels() const
01514 {
01515 
01516    if (fVoxels && !fVoxels->IsInvalid()) return fVoxels;
01517    return NULL;
01518 }   
01519 
01520 
01521 void TGeoVolume::GrabFocus()
01522 {
01523 
01524    TVirtualGeoPainter *painter = fGeoManager->GetPainter();
01525    if (painter) painter->GrabFocus();
01526 }   
01527 
01528 
01529 TGeoVolume *TGeoVolume::CloneVolume() const
01530 {
01531 
01532    
01533    TGeoVolume *vol = new TGeoVolume(GetName(), fShape, fMedium);
01534    Int_t i;
01535    
01536    vol->SetLineColor(GetLineColor());
01537    vol->SetLineStyle(GetLineStyle());
01538    vol->SetLineWidth(GetLineWidth());
01539    vol->SetFillColor(GetFillColor());
01540    vol->SetFillStyle(GetFillStyle());
01541    
01542    Int_t nbits = 8*sizeof(UInt_t);
01543    for (i=0; i<nbits; i++) 
01544       vol->SetAttBit(1<<i, TGeoAtt::TestAttBit(1<<i));
01545    for (i=14; i<24; i++)
01546       vol->SetBit(1<<i, TestBit(1<<i));   
01547    
01548    
01549    vol->SetField(fField);
01550    
01551    for (i=0; i<nbits; i++) 
01552       vol->SetBit(1<<i, TObject::TestBit(1<<i));
01553    vol->SetBit(kVolumeClone);   
01554    
01555 
01556    vol->MakeCopyNodes(this);   
01557    
01558    vol->SetFinder(fFinder);
01559    
01560    TGeoVoxelFinder *voxels = 0;
01561    if (fVoxels) {
01562       voxels = new TGeoVoxelFinder(vol);
01563       vol->SetVoxelFinder(voxels);
01564    }   
01565    
01566    vol->SetOption(fOption);
01567    vol->SetNumber(fNumber);
01568    vol->SetNtotal(fNtotal);
01569    return vol;
01570 }
01571 
01572 
01573 void TGeoVolume::CloneNodesAndConnect(TGeoVolume *newmother) const
01574 {
01575 
01576    if (!fNodes) return;
01577    TGeoNode *node;
01578    Int_t nd = fNodes->GetEntriesFast();
01579    if (!nd) return;
01580    
01581    TObjArray *list = new TObjArray(nd);
01582    
01583    newmother->SetNodes(list);
01584 
01585    for (Int_t i=0; i<nd; i++) {
01586       
01587       node = GetNode(i)->MakeCopyNode();
01588       node->SetMotherVolume(newmother);
01589       list->Add(node);
01590    }
01591 }
01592 
01593 
01594 void TGeoVolume::MakeCopyNodes(const TGeoVolume *other)
01595 {
01596 
01597    Int_t nd = other->GetNdaughters();
01598    if (!nd) return;
01599    if (fNodes) {
01600       if (!TObject::TestBit(kVolumeImportNodes)) fNodes->Delete();
01601       delete fNodes;   
01602    }   
01603    fNodes = new TObjArray();
01604    for (Int_t i=0; i<nd; i++) fNodes->Add(other->GetNode(i));
01605    TObject::SetBit(kVolumeImportNodes);
01606 }      
01607 
01608 
01609 TGeoVolume *TGeoVolume::MakeCopyVolume(TGeoShape *newshape)
01610 {
01611     
01612    
01613    TGeoVolume *vol = new TGeoVolume(GetName(), newshape, fMedium);
01614    
01615    vol->SetVisibility(IsVisible());
01616    vol->SetLineColor(GetLineColor());
01617    vol->SetLineStyle(GetLineStyle());
01618    vol->SetLineWidth(GetLineWidth());
01619    vol->SetFillColor(GetFillColor());
01620    vol->SetFillStyle(GetFillStyle());
01621    
01622    vol->SetField(fField);
01623    
01624    if (fFinder) {
01625 
01626       vol->SetFinder(fFinder);
01627    }   
01628    CloneNodesAndConnect(vol);
01629 
01630    ((TObject*)vol)->SetBit(kVolumeClone);
01631    return vol;       
01632 }    
01633 
01634 
01635 TGeoVolume *TGeoVolume::MakeReflectedVolume(const char *newname) const
01636 {
01637 
01638    static TMap map(100);
01639    if (!fGeoManager->IsClosed()) {
01640       Error("MakeReflectedVolume", "Geometry must be closed.");
01641       return NULL;
01642    }   
01643    TGeoVolume *vol = (TGeoVolume*)map.GetValue(this);
01644    if (vol) {
01645       if (strlen(newname)) vol->SetName(newname);
01646       return vol;
01647    }
01648 
01649    vol = CloneVolume();
01650    map.Add((TObject*)this, vol);
01651    if (strlen(newname)) vol->SetName(newname);
01652    delete vol->GetNodes();
01653    vol->SetNodes(NULL);
01654    vol->SetBit(kVolumeImportNodes, kFALSE);
01655    CloneNodesAndConnect(vol);
01656    
01657    
01658    if (fShape) {
01659       TGeoShape *reflected_shape = 
01660          TGeoScaledShape::MakeScaledShape("", fShape, new TGeoScale(1.,1.,-1.));
01661       vol->SetShape(reflected_shape);
01662    }   
01663    
01664    Int_t nd = vol->GetNdaughters();
01665    if (!nd) return vol;
01666    TGeoNodeMatrix *node;
01667    TGeoMatrix *local, *local_cloned;
01668    TGeoVolume *new_vol;
01669    if (!vol->GetFinder()) {
01670       for (Int_t i=0; i<nd; i++) {
01671          node = (TGeoNodeMatrix*)vol->GetNode(i);
01672          local = node->GetMatrix();
01673 
01674 
01675          Bool_t reflected = local->IsReflection();
01676          local_cloned = new TGeoCombiTrans(*local);
01677          local_cloned->RegisterYourself();
01678          node->SetMatrix(local_cloned);
01679          if (!reflected) {
01680          
01681             
01682             local_cloned->ReflectZ(kTRUE);
01683             local_cloned->ReflectZ(kFALSE);
01684 
01685 
01686             new_vol = node->GetVolume()->MakeReflectedVolume();
01687             node->SetVolume(new_vol);
01688             continue;
01689          }
01690          
01691          local_cloned->ReflectZ(kTRUE); 
01692 
01693 
01694       }
01695       if (vol->GetVoxels()) vol->GetVoxels()->Voxelize();
01696       return vol;
01697    }
01698    
01699 
01700    TGeoPatternFinder *new_finder = fFinder->MakeCopy(kTRUE);
01701    new_finder->SetVolume(vol);
01702    vol->SetFinder(new_finder);
01703    TGeoNodeOffset *nodeoff;
01704    new_vol = 0;
01705    for (Int_t i=0; i<nd; i++) {
01706       nodeoff = (TGeoNodeOffset*)vol->GetNode(i);
01707       nodeoff->SetFinder(new_finder);
01708       new_vol = nodeoff->GetVolume()->MakeReflectedVolume();
01709       nodeoff->SetVolume(new_vol); 
01710    }   
01711    return vol;
01712 }
01713    
01714 
01715 void TGeoVolume::SetAsTopVolume()
01716 {
01717 
01718    fGeoManager->SetTopVolume(this);
01719 }
01720 
01721 
01722 void TGeoVolume::SetCurrentPoint(Double_t x, Double_t y, Double_t z)
01723 {
01724 
01725    fGeoManager->SetCurrentPoint(x,y,z);
01726 }
01727 
01728 
01729 void TGeoVolume::SetShape(const TGeoShape *shape)
01730 {
01731 
01732    if (!shape) {
01733       Error("SetShape", "No shape");
01734       return;
01735    }
01736    fShape = (TGeoShape*)shape;  
01737 }
01738 
01739 
01740 void TGeoVolume::SortNodes()
01741 {
01742 
01743 
01744    if (!Valid()) {
01745       Error("SortNodes", "Bounding box not valid");
01746       return;
01747    }
01748    Int_t nd = GetNdaughters();
01749 
01750    if (!nd) return;
01751    if (fFinder) return;
01752 
01753    Int_t id = 0;
01754    TGeoNode *node = 0;
01755    TObjArray *nodes = new TObjArray(nd);
01756    Int_t inode = 0;
01757    
01758    for (id=0; id<nd; id++) {
01759       node = GetNode(id);
01760       if (node->InheritsFrom(TGeoNodeOffset::Class()) || node->IsOverlapping()) continue;
01761       nodes->Add(node);
01762 
01763       inode++;
01764    }
01765    
01766    for (id=0; id<nd; id++) {
01767       node = GetNode(id);
01768       if (node->InheritsFrom(TGeoNodeOffset::Class()) || (!node->IsOverlapping())) continue;
01769       nodes->Add(node);
01770 
01771       inode++;
01772    }
01773    
01774    if (fFinder) {
01775       fFinder->SetDivIndex(inode);
01776       for (id=0; id<nd; id++) {
01777          node = GetNode(id);
01778          if (!node->InheritsFrom(TGeoNodeOffset::Class())) continue;
01779          nodes->Add(node);
01780 
01781          inode++;
01782       }
01783    }
01784    if (inode != nd) printf(" volume %s : number of nodes does not match!!!\n", GetName());
01785    delete fNodes;
01786    fNodes = nodes;
01787 }
01788 
01789 
01790 void TGeoVolume::Streamer(TBuffer &R__b)
01791 {
01792    
01793    if (R__b.IsReading()) {
01794       R__b.ReadClassBuffer(TGeoVolume::Class(), this);
01795       if (fVoxels && fVoxels->IsInvalid()) Voxelize("");
01796    } else {
01797       if (!fVoxels) {
01798          R__b.WriteClassBuffer(TGeoVolume::Class(), this);
01799       } else {
01800          if (!fGeoManager->IsStreamingVoxels()) {
01801             TGeoVoxelFinder *voxels = fVoxels;
01802             fVoxels = 0;
01803             R__b.WriteClassBuffer(TGeoVolume::Class(), this);
01804             fVoxels = voxels;
01805          } else {
01806             R__b.WriteClassBuffer(TGeoVolume::Class(), this);
01807          }
01808       }
01809    }
01810 }
01811 
01812 
01813 void TGeoVolume::SetOption(const char * )
01814 {
01815 
01816 }
01817 
01818 
01819 void TGeoVolume::SetLineColor(Color_t lcolor) 
01820 {
01821 
01822    TAttLine::SetLineColor(lcolor);
01823 }   
01824 
01825 
01826 void TGeoVolume::SetLineStyle(Style_t lstyle) 
01827 {
01828 
01829    TAttLine::SetLineStyle(lstyle);
01830 }   
01831 
01832 
01833 void TGeoVolume::SetLineWidth(Style_t lwidth) 
01834 {
01835 
01836    TAttLine::SetLineWidth(lwidth);
01837 }   
01838 
01839 
01840 TGeoNode *TGeoVolume::GetNode(const char *name) const
01841 {
01842 
01843    if (!fNodes) return 0;
01844    TGeoNode *node = (TGeoNode *)fNodes->FindObject(name);
01845    return node;
01846 }
01847 
01848 
01849 Int_t TGeoVolume::GetByteCount() const
01850 {
01851 
01852    Int_t count = 28+2+6+4+0;    
01853    count += strlen(GetName()) + strlen(GetTitle()); 
01854    count += 4+4+4+4+4; 
01855    count += 8 + strlen(fOption.Data()); 
01856    if (fShape)  count += fShape->GetByteCount();
01857    if (fFinder) count += fFinder->GetByteCount();
01858    if (fNodes) {
01859       count += 32 + 4*fNodes->GetEntries(); 
01860       TIter next(fNodes);
01861       TGeoNode *node;
01862       while ((node=(TGeoNode*)next())) count += node->GetByteCount();
01863    }
01864    return count;
01865 }
01866 
01867 
01868 void TGeoVolume::FindOverlaps() const
01869 {
01870 
01871    if (!Valid()) {
01872       Error("FindOverlaps","Bounding box not valid");
01873       return;
01874    }   
01875    if (!fVoxels) return;
01876    Int_t nd = GetNdaughters();
01877    if (!nd) return;
01878    TGeoNode *node=0;
01879    Int_t inode = 0;
01880    for (inode=0; inode<nd; inode++) {
01881       node = GetNode(inode);
01882       if (!node->IsOverlapping()) continue;
01883       fVoxels->FindOverlaps(inode);
01884    }
01885 }
01886 
01887 
01888 void TGeoVolume::RemoveNode(TGeoNode *node) 
01889 {
01890 
01891    if (!fNodes || !fNodes->GetEntriesFast()) return;
01892    if (!fNodes->Remove(node)) return;
01893    fNodes->Compress();
01894    if (fVoxels) fVoxels->SetNeedRebuild();
01895    if (IsAssembly()) fShape->ComputeBBox();
01896 }   
01897 
01898 
01899 TGeoNode *TGeoVolume::ReplaceNode(TGeoNode *nodeorig, TGeoShape *newshape, TGeoMatrix *newpos, TGeoMedium *newmed) 
01900 {
01901 
01902 
01903 
01904    Int_t ind = GetIndex(nodeorig);
01905    if (ind < 0) return NULL;
01906    TGeoVolume *oldvol = nodeorig->GetVolume();
01907    if (oldvol->IsAssembly()) {
01908       Error("ReplaceNode", "Cannot replace node %s since it is an assembly", nodeorig->GetName());
01909       return NULL;
01910    }   
01911    TGeoShape  *shape = oldvol->GetShape();
01912    if (newshape && !nodeorig->IsOffset()) shape = newshape;
01913    TGeoMedium *med = oldvol->GetMedium();
01914    if (newmed) med = newmed;
01915    
01916    TGeoVolume *vol = new TGeoVolume(oldvol->GetName(), shape, med);
01917    
01918    vol->SetVisibility(oldvol->IsVisible());
01919    vol->SetLineColor(oldvol->GetLineColor());
01920    vol->SetLineStyle(oldvol->GetLineStyle());
01921    vol->SetLineWidth(oldvol->GetLineWidth());
01922    vol->SetFillColor(oldvol->GetFillColor());
01923    vol->SetFillStyle(oldvol->GetFillStyle());
01924    
01925    vol->SetField(oldvol->GetField());
01926    
01927    TGeoNode *newnode = nodeorig->MakeCopyNode();
01928    
01929    newnode->SetVolume(vol);
01930    
01931    if (newpos && !nodeorig->IsOffset()) {
01932       TGeoNodeMatrix *nodemat = (TGeoNodeMatrix*)newnode;
01933       nodemat->SetMatrix(newpos);
01934    }   
01935    
01936    fNodes->RemoveAt(ind);
01937    fNodes->AddAt(newnode, ind);   
01938    if (fVoxels) fVoxels->SetNeedRebuild();
01939    if (IsAssembly()) fShape->ComputeBBox();
01940    return newnode;
01941 }      
01942 
01943 
01944 void TGeoVolume::SelectVolume(Bool_t clear)
01945 {
01946 
01947 
01948 
01949 
01950    static TObjArray array(256);
01951    static Int_t len = 0;
01952    Int_t i;
01953    TObject *vol;
01954    if (clear) {
01955       for (i=0; i<len; i++) {
01956          vol = array.At(i);
01957          vol->ResetBit(TGeoVolume::kVolumeSelected);
01958       }
01959       array.Clear();
01960       len = 0;
01961       return;
01962    }
01963    SetBit(TGeoVolume::kVolumeSelected);
01964    array.AddAtAndExpand(this, len++);
01965 }      
01966 
01967 
01968 void TGeoVolume::SetVisibility(Bool_t vis)
01969 {
01970 
01971    if (IsAssembly()) {
01972       Info("SetVisibility", "Volume %s: assemblies do not have visibility", GetName());
01973       return;
01974    }   
01975    TGeoAtt::SetVisibility(vis);
01976    if (fGeoManager->IsClosed()) SetVisTouched(kTRUE);
01977    fGeoManager->SetVisOption(4);
01978    TSeqCollection *brlist = gROOT->GetListOfBrowsers();
01979    TIter next(brlist);
01980    TBrowser *browser = 0;
01981    while ((browser=(TBrowser*)next())) {
01982       browser->CheckObjectItem(this, vis);
01983       browser->Refresh();
01984    }
01985 }   
01986 
01987 
01988 void TGeoVolume::SetVisContainers(Bool_t flag)
01989 {
01990 
01991    TGeoAtt::SetVisContainers(flag);
01992    if (fGeoManager && fGeoManager->IsClosed()) {
01993       if (flag) fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisDefault);
01994       else      fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisLeaves);
01995    }   
01996 }
01997    
01998 
01999 void TGeoVolume::SetVisLeaves(Bool_t flag)
02000 {
02001 
02002    TGeoAtt::SetVisLeaves(flag);
02003    if (fGeoManager && fGeoManager->IsClosed()) {
02004       if (flag) fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisLeaves);
02005       else      fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisDefault);
02006    }   
02007 }
02008 
02009 
02010 void TGeoVolume::SetVisOnly(Bool_t flag)
02011 {
02012 
02013    if (IsAssembly()) return;
02014    TGeoAtt::SetVisOnly(flag);
02015    if (fGeoManager && fGeoManager->IsClosed()) {
02016       if (flag) fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisOnly);
02017       else      fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisLeaves);
02018    }   
02019 }
02020 
02021 
02022 Bool_t TGeoVolume::Valid() const
02023 {
02024 
02025    return fShape->IsValidBox();
02026 }
02027 
02028 
02029 Bool_t TGeoVolume::FindMatrixOfDaughterVolume(TGeoVolume *vol) const
02030 {
02031 
02032 
02033    if (vol == this) return kTRUE;
02034    Int_t nd = GetNdaughters();
02035    if (!nd) return kFALSE;
02036    TGeoHMatrix *global = fGeoManager->GetHMatrix();
02037    TGeoNode *dnode;
02038    TGeoVolume *dvol;
02039    TGeoMatrix *local;
02040    Int_t i;
02041    for (i=0; i<nd; i++) {
02042       dnode = GetNode(i);
02043       dvol = dnode->GetVolume();
02044       if (dvol == vol) {
02045          local = dnode->GetMatrix();
02046          global->MultiplyLeft(local);
02047          return kTRUE;
02048       }
02049    }
02050    for (i=0; i<nd; i++) {
02051       dnode = GetNode(i);
02052       dvol = dnode->GetVolume();
02053       if (dvol->FindMatrixOfDaughterVolume(vol)) return kTRUE;
02054    }
02055    return kFALSE;
02056 }                    
02057 
02058 
02059 void TGeoVolume::VisibleDaughters(Bool_t vis)
02060 {
02061 
02062    SetVisDaughters(vis);
02063    if (fGeoManager->IsClosed()) SetVisTouched(kTRUE);
02064    fGeoManager->SetVisOption(4);
02065 }
02066 
02067 
02068 void TGeoVolume::Voxelize(Option_t *option)
02069 {
02070 
02071    if (!Valid()) {
02072       Error("Voxelize", "Bounding box not valid");
02073       return; 
02074    }   
02075    
02076    if (fFinder) return;
02077    
02078    Int_t nd = GetNdaughters();
02079    if (!nd) return;
02080    
02081    if (IsAssembly()) fShape->ComputeBBox();
02082    
02083    if (fVoxels) {
02084       if (!TObject::TestBit(kVolumeClone)) delete fVoxels;
02085       fVoxels = 0;
02086    }   
02087    
02088    fVoxels = new TGeoVoxelFinder(this);
02089    fVoxels->Voxelize(option);
02090    if (fVoxels) {
02091       if (fVoxels->IsInvalid()) {
02092          delete fVoxels;
02093          fVoxels = 0;
02094       }
02095    }      
02096 }
02097 
02098 
02099 Double_t TGeoVolume::Weight(Double_t precision, Option_t *option)
02100 {
02101 
02102 
02103    TGeoVolume *top = fGeoManager->GetTopVolume();
02104    if (top != this) fGeoManager->SetTopVolume(this);
02105    else top = 0;
02106    Double_t weight =  fGeoManager->Weight(precision, option);
02107    if (top) fGeoManager->SetTopVolume(top);
02108    return weight;
02109 }   
02110 
02111 
02112 Double_t TGeoVolume::WeightA() const
02113 {
02114 
02115    Double_t capacity = Capacity();
02116    Double_t weight = 0.0;
02117    Int_t i;
02118    Int_t nd = GetNdaughters();
02119    TGeoVolume *daughter;
02120    for (i=0; i<nd; i++) {
02121       daughter = GetNode(i)->GetVolume();
02122       weight += daughter->WeightA();
02123       capacity -= daughter->Capacity();
02124    }
02125    Double_t density = 0.0;
02126    if (!IsAssembly()) {
02127       if (fMedium) density = fMedium->GetMaterial()->GetDensity();
02128       if (density<0.01) density = 0.0; 
02129    }   
02130    weight += 0.001*capacity * density; 
02131    return weight;
02132 }
02133 
02134 ClassImp(TGeoVolumeMulti)
02135 
02136 
02137 
02138 TGeoVolumeMulti::TGeoVolumeMulti()
02139 { 
02140 
02141    fVolumes   = 0;
02142    fDivision = 0;
02143    fNumed = 0;
02144    fNdiv = 0;
02145    fAxis = 0;
02146    fStart = 0;
02147    fStep = 0;
02148    fAttSet = kFALSE;
02149    TObject::SetBit(kVolumeMulti);
02150 }
02151 
02152 
02153 TGeoVolumeMulti::TGeoVolumeMulti(const char *name, TGeoMedium *med)
02154 {
02155 
02156    fVolumes = new TObjArray();
02157    fDivision = 0;
02158    fNumed = 0;
02159    fNdiv = 0;
02160    fAxis = 0;
02161    fStart = 0;
02162    fStep = 0;
02163    fAttSet = kFALSE;
02164    TObject::SetBit(kVolumeMulti);
02165    SetName(name);
02166    SetMedium(med);
02167    fGeoManager->AddVolume(this);
02168 
02169 }
02170 
02171 
02172 TGeoVolumeMulti::TGeoVolumeMulti(const TGeoVolumeMulti& vm) :
02173   TGeoVolume(vm),
02174   fVolumes(vm.fVolumes),
02175   fDivision(vm.fDivision),
02176   fNumed(vm.fNumed),
02177   fNdiv(vm.fNdiv),
02178   fAxis(vm.fAxis),
02179   fStart(vm.fStart),
02180   fStep(vm.fStep),
02181   fAttSet(vm.fAttSet)
02182 { 
02183    
02184 }
02185 
02186 
02187 TGeoVolumeMulti& TGeoVolumeMulti::operator=(const TGeoVolumeMulti& vm) 
02188 {
02189    
02190    if(this!=&vm) {
02191       TGeoVolume::operator=(vm);
02192       fVolumes=vm.fVolumes;
02193       fDivision=vm.fDivision;
02194       fNumed=vm.fNumed;
02195       fNdiv=vm.fNdiv;
02196       fAxis=vm.fAxis;
02197       fStart=vm.fStart;
02198       fStep=vm.fStep;
02199       fAttSet=vm.fAttSet;
02200    } 
02201    return *this;
02202 }
02203 
02204 
02205 TGeoVolumeMulti::~TGeoVolumeMulti()
02206 {
02207 
02208    if (fVolumes) delete fVolumes;
02209 }
02210 
02211 
02212 void TGeoVolumeMulti::AddVolume(TGeoVolume *vol) 
02213 {
02214 
02215 
02216    Int_t idx = fVolumes->GetEntriesFast();
02217    fVolumes->AddAtAndExpand(vol,idx);
02218    vol->SetUniqueID(idx+1);
02219    TGeoVolumeMulti *div;
02220    TGeoVolume *cell;
02221    if (fDivision) {
02222       div = (TGeoVolumeMulti*)vol->Divide(fDivision->GetName(), fAxis, fNdiv, fStart, fStep, fNumed, fOption.Data());
02223       for (Int_t i=0; i<div->GetNvolumes(); i++) {
02224          cell = div->GetVolume(i);
02225          fDivision->AddVolume(cell);
02226       }
02227    }      
02228    if (fNodes) {
02229       Int_t nd = fNodes->GetEntriesFast();
02230       for (Int_t id=0; id<nd; id++) {
02231          TGeoNode *node = (TGeoNode*)fNodes->At(id);
02232          Bool_t many = node->IsOverlapping();
02233          if (many) vol->AddNodeOverlap(node->GetVolume(), node->GetNumber(), node->GetMatrix());
02234          else      vol->AddNode(node->GetVolume(), node->GetNumber(), node->GetMatrix());
02235       }
02236    }      
02237 
02238 }
02239    
02240 
02241 
02242 void TGeoVolumeMulti::AddNode(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
02243 {
02244 
02245 
02246    TGeoVolume::AddNode(vol, copy_no, mat, option);
02247    Int_t nvolumes = fVolumes->GetEntriesFast();
02248    TGeoVolume *volume = 0;
02249    for (Int_t ivo=0; ivo<nvolumes; ivo++) {
02250       volume = GetVolume(ivo);
02251       volume->SetLineColor(GetLineColor());
02252       volume->SetLineStyle(GetLineStyle());
02253       volume->SetLineWidth(GetLineWidth());
02254       volume->SetVisibility(IsVisible());
02255       volume->AddNode(vol, copy_no, mat, option); 
02256    }
02257 
02258 }
02259 
02260 
02261 void TGeoVolumeMulti::AddNodeOverlap(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
02262 {
02263 
02264 
02265    TGeoVolume::AddNodeOverlap(vol, copy_no, mat, option);
02266    Int_t nvolumes = fVolumes->GetEntriesFast();
02267    TGeoVolume *volume = 0;
02268    for (Int_t ivo=0; ivo<nvolumes; ivo++) {
02269       volume = GetVolume(ivo);
02270       volume->SetLineColor(GetLineColor());
02271       volume->SetLineStyle(GetLineStyle());
02272       volume->SetLineWidth(GetLineWidth());
02273       volume->SetVisibility(IsVisible());
02274       volume->AddNodeOverlap(vol, copy_no, mat, option); 
02275    }
02276 
02277 }
02278 
02279 
02280 
02281 TGeoVolume *TGeoVolumeMulti::Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed, const char *option)
02282 {
02283 
02284    if (fDivision) {
02285       Error("Divide", "volume %s already divided", GetName());
02286       return 0;
02287    }   
02288    Int_t nvolumes = fVolumes->GetEntriesFast();
02289    TGeoMedium *medium = fMedium;
02290    if (numed) {
02291       medium = fGeoManager->GetMedium(numed);
02292       if (!medium) {
02293          Error("Divide", "Invalid medium number %d for division volume %s", numed, divname);
02294          medium = fMedium;
02295       }
02296    }      
02297    if (!nvolumes) {
02298       
02299       fDivision = new TGeoVolumeMulti(divname, medium);
02300       fNumed = medium->GetId();
02301       fOption = option;
02302       fAxis = iaxis;
02303       fNdiv = ndiv;
02304       fStart = start;
02305       fStep = step;
02306       
02307       return fDivision;
02308    }      
02309    TGeoVolume *vol = 0;
02310    fDivision = new TGeoVolumeMulti(divname, medium);
02311    if (medium) fNumed = medium->GetId();
02312    fOption = option;
02313    fAxis = iaxis;
02314    fNdiv = ndiv;
02315    fStart = start;
02316    fStep = step;
02317    for (Int_t ivo=0; ivo<nvolumes; ivo++) {
02318       vol = GetVolume(ivo);
02319       vol->SetLineColor(GetLineColor());
02320       vol->SetLineStyle(GetLineStyle());
02321       vol->SetLineWidth(GetLineWidth());
02322       vol->SetVisibility(IsVisible());
02323       fDivision->AddVolume(vol->Divide(divname,iaxis,ndiv,start,step, numed, option)); 
02324    }
02325 
02326    if (numed) fDivision->SetMedium(medium);
02327    return fDivision;
02328 }
02329 
02330 
02331 TGeoVolume *TGeoVolumeMulti::MakeCopyVolume(TGeoShape *newshape)
02332 {
02333    
02334    
02335    TGeoVolume *vol = new TGeoVolume(GetName(), newshape, fMedium);
02336    Int_t i=0;
02337    
02338    vol->SetVisibility(IsVisible());
02339    vol->SetLineColor(GetLineColor());
02340    vol->SetLineStyle(GetLineStyle());
02341    vol->SetLineWidth(GetLineWidth());
02342    vol->SetFillColor(GetFillColor());
02343    vol->SetFillStyle(GetFillStyle());
02344    
02345    vol->SetField(fField);
02346    
02347 
02348 
02349 
02350 
02351    if (fDivision) {
02352       TGeoVolume *cell;
02353       TGeoVolumeMulti *div = (TGeoVolumeMulti*)vol->Divide(fDivision->GetName(), fAxis, fNdiv, fStart, fStep, fNumed, fOption.Data());
02354       for (i=0; i<div->GetNvolumes(); i++) {
02355          cell = div->GetVolume(i);
02356          fDivision->AddVolume(cell);
02357       }
02358    }      
02359                  
02360    if (!fNodes) return vol;
02361    TGeoNode *node;
02362    Int_t nd = fNodes->GetEntriesFast();
02363    if (!nd) return vol;
02364    
02365    TObjArray *list = new TObjArray();
02366    
02367    vol->SetNodes(list);
02368    ((TObject*)vol)->SetBit(kVolumeImportNodes);
02369    for (i=0; i<nd; i++) {
02370       
02371       node = GetNode(i)->MakeCopyNode();
02372       node->SetMotherVolume(vol);
02373       list->Add(node);
02374    }
02375    return vol;       
02376 }    
02377 
02378 
02379 void TGeoVolumeMulti::SetLineColor(Color_t lcolor) 
02380 {
02381 
02382    TGeoVolume::SetLineColor(lcolor);
02383    Int_t nvolumes = fVolumes->GetEntriesFast();
02384    TGeoVolume *vol = 0;
02385    for (Int_t ivo=0; ivo<nvolumes; ivo++) {
02386       vol = GetVolume(ivo);
02387       vol->SetLineColor(lcolor); 
02388    }
02389 }
02390 
02391 
02392 void TGeoVolumeMulti::SetLineStyle(Style_t lstyle) 
02393 {
02394 
02395    TGeoVolume::SetLineStyle(lstyle); 
02396    Int_t nvolumes = fVolumes->GetEntriesFast();
02397    TGeoVolume *vol = 0;
02398    for (Int_t ivo=0; ivo<nvolumes; ivo++) {
02399       vol = GetVolume(ivo);
02400       vol->SetLineStyle(lstyle); 
02401    }
02402 }
02403 
02404 
02405 void TGeoVolumeMulti::SetLineWidth(Width_t lwidth) 
02406 {
02407 
02408    TGeoVolume::SetLineWidth(lwidth);
02409    Int_t nvolumes = fVolumes->GetEntriesFast();
02410    TGeoVolume *vol = 0;
02411    for (Int_t ivo=0; ivo<nvolumes; ivo++) {
02412       vol = GetVolume(ivo);
02413       vol->SetLineWidth(lwidth); 
02414    }
02415 }
02416 
02417 
02418 void TGeoVolumeMulti::SetMedium(TGeoMedium *med)
02419 {
02420 
02421    TGeoVolume::SetMedium(med);
02422    Int_t nvolumes = fVolumes->GetEntriesFast();
02423    TGeoVolume *vol = 0;
02424    for (Int_t ivo=0; ivo<nvolumes; ivo++) {
02425       vol = GetVolume(ivo);
02426       vol->SetMedium(med); 
02427    }
02428 }   
02429 
02430 
02431 
02432 void TGeoVolumeMulti::SetVisibility(Bool_t vis) 
02433 {
02434 
02435    TGeoVolume::SetVisibility(vis); 
02436    Int_t nvolumes = fVolumes->GetEntriesFast();
02437    TGeoVolume *vol = 0;
02438    for (Int_t ivo=0; ivo<nvolumes; ivo++) {
02439       vol = GetVolume(ivo);
02440       vol->SetVisibility(vis); 
02441    }
02442 }
02443 
02444 ClassImp(TGeoVolumeAssembly)
02445 
02446 
02447 TGeoVolumeAssembly::TGeoVolumeAssembly()
02448                    :TGeoVolume()
02449 {
02450 
02451    fCurrent = -1;
02452    fNext = -1;
02453 }
02454 
02455 
02456 TGeoVolumeAssembly::TGeoVolumeAssembly(const char *name)
02457                    :TGeoVolume()
02458 {
02459 
02460 
02461    fName = name;
02462    fName = fName.Strip();
02463    fCurrent = -1;
02464    fNext = -1;
02465    fShape = new TGeoShapeAssembly(this);
02466    if (fGeoManager) fNumber = fGeoManager->AddVolume(this);
02467 }
02468 
02469 
02470 TGeoVolumeAssembly::~TGeoVolumeAssembly()
02471 {
02472 
02473    if (fShape) delete fShape;
02474 }   
02475 
02476 
02477 void TGeoVolumeAssembly::AddNode(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
02478 {
02479 
02480    TGeoVolume::AddNode(vol,copy_no,mat,option);
02481    ((TGeoShapeAssembly*)fShape)->RecomputeBoxLast();
02482 }   
02483 
02484 
02485 void TGeoVolumeAssembly::AddNodeOverlap(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
02486 {
02487 
02488    Warning("AddNodeOverlap", "Declaring assembly %s as possibly overlapping inside %s not allowed. Using AddNode instead !",vol->GetName(),GetName());
02489    AddNode(vol, copy_no, mat, option);
02490 }   
02491 
02492 
02493 TGeoVolume *TGeoVolumeAssembly::CloneVolume() const
02494 {
02495 
02496    
02497    TGeoVolume *vol = new TGeoVolumeAssembly(GetName());
02498    Int_t i;
02499    
02500    Int_t nbits = 8*sizeof(UInt_t);
02501    for (i=0; i<nbits; i++) 
02502       vol->SetAttBit(1<<i, TGeoAtt::TestAttBit(1<<i));
02503    for (i=14; i<24; i++)
02504       vol->SetBit(1<<i, TestBit(1<<i));   
02505    
02506    
02507    vol->SetField(fField);
02508    
02509    for (i=0; i<nbits; i++) 
02510       vol->SetBit(1<<i, TObject::TestBit(1<<i));
02511    vol->SetBit(kVolumeClone);   
02512    
02513    vol->MakeCopyNodes(this);
02514 
02515    ((TGeoShapeAssembly*)vol->GetShape())->NeedsBBoxRecompute();
02516    
02517    TGeoVoxelFinder *voxels = 0;
02518    if (fVoxels) {
02519       voxels = new TGeoVoxelFinder(vol);
02520       vol->SetVoxelFinder(voxels);
02521    }   
02522    
02523    vol->SetOption(fOption);
02524    vol->SetNumber(fNumber);
02525    vol->SetNtotal(fNtotal);
02526    return vol;
02527 }
02528 
02529 
02530 TGeoVolume *TGeoVolumeAssembly::Divide(const char *, Int_t, Int_t, Double_t, Double_t, Int_t, Option_t *)
02531 {
02532 
02533    Error("Divide","Assemblies cannot be divided");
02534    return 0;
02535 }
02536 
02537 
02538 TGeoVolumeAssembly *TGeoVolumeAssembly::MakeAssemblyFromVolume(TGeoVolume *volorig)
02539 {
02540 
02541    if (volorig->IsAssembly() || volorig->IsVolumeMulti()) return 0;
02542    Int_t nd = volorig->GetNdaughters();
02543    if (!nd) return 0;
02544    TGeoVolumeAssembly *vol = new TGeoVolumeAssembly(volorig->GetName());
02545    Int_t i;
02546    
02547    Int_t nbits = 8*sizeof(UInt_t);
02548    for (i=0; i<nbits; i++) 
02549       vol->SetAttBit(1<<i, volorig->TestAttBit(1<<i));
02550    for (i=14; i<24; i++)
02551       vol->SetBit(1<<i, volorig->TestBit(1<<i));   
02552    
02553    
02554    vol->SetField(volorig->GetField());
02555    
02556    for (i=0; i<nbits; i++) 
02557       vol->SetBit(1<<i, volorig->TestBit(1<<i));
02558    vol->SetBit(kVolumeClone);   
02559    
02560    vol->MakeCopyNodes(volorig);
02561 
02562    vol->GetShape()->ComputeBBox();
02563    
02564    TGeoVoxelFinder *voxels = 0;
02565    if (volorig->GetVoxels()) {
02566       voxels = new TGeoVoxelFinder(vol);
02567       vol->SetVoxelFinder(voxels);
02568    }   
02569    
02570    vol->SetOption(volorig->GetOption());
02571    vol->SetNumber(volorig->GetNumber());
02572    vol->SetNtotal(volorig->GetNtotal());
02573    return vol;
02574 }