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 }