404 ClassImp(TGeoVolume);
406 TGeoMedium *TGeoVolume::fgDummyMedium = 0;
411 void TGeoVolume::CreateDummyMedium()
413 if (fgDummyMedium)
return;
414 fgDummyMedium =
new TGeoMedium();
415 fgDummyMedium->SetName(
"dummy");
416 TGeoMaterial *dummyMaterial =
new TGeoMaterial();
417 dummyMaterial->SetName(
"dummy");
418 fgDummyMedium->SetMaterial(dummyMaterial);
423 void TGeoVolume::ClearThreadData()
const
425 if (fFinder) fFinder->ClearThreadData();
426 if (fShape) fShape->ClearThreadData();
431 void TGeoVolume::CreateThreadData(Int_t nthreads)
433 if (fFinder) fFinder->CreateThreadData(nthreads);
434 if (fShape) fShape->CreateThreadData(nthreads);
439 TGeoMedium *TGeoVolume::DummyMedium()
441 return fgDummyMedium;
447 TGeoVolume::TGeoVolume()
454 fGeoManager = gGeoManager;
462 TObject::ResetBit(kVolumeImportNodes);
468 TGeoVolume::TGeoVolume(
const char *name,
const TGeoShape *shape,
const TGeoMedium *med)
471 fName = fName.Strip();
473 fShape = (TGeoShape*)shape;
475 if (fShape->TestShapeBit(TGeoShape::kGeoBad)) {
476 Warning(
"Ctor",
"volume %s has invalid shape", name);
478 if (!fShape->IsValid()) {
479 Fatal(
"ctor",
"Shape of volume %s invalid. Aborting!", fName.Data());
482 fMedium = (TGeoMedium*)med;
483 if (fMedium && fMedium->GetMaterial()) fMedium->GetMaterial()->SetUsed();
486 fGeoManager = gGeoManager;
494 if (fGeoManager) fNumber = fGeoManager->AddVolume(
this);
495 TObject::ResetBit(kVolumeImportNodes);
501 TGeoVolume::~TGeoVolume()
504 if (!TObject::TestBit(kVolumeImportNodes)) {
509 if (fFinder && !TObject::TestBit(kVolumeImportNodes | kVolumeClone) )
delete fFinder;
510 if (fVoxels)
delete fVoxels;
511 if (fUserExtension) {fUserExtension->Release(); fUserExtension=0;}
512 if (fFWExtension) {fFWExtension->Release(); fFWExtension=0;}
518 void TGeoVolume::Browse(TBrowser *b)
523 TGeoVolume *daughter;
525 for (Int_t i=0; i<GetNdaughters(); i++) {
526 daughter = GetNode(i)->GetVolume();
527 if(daughter->GetTitle()[0]) {
528 if (daughter->IsAssembly()) title.TString::Format(
"Assembly with %d daughter(s)",
529 daughter->GetNdaughters());
530 else if (daughter->GetFinder()) {
531 TString s1 = daughter->GetFinder()->ClassName();
532 s1.ReplaceAll(
"TGeoPattern",
"");
533 title.TString::Format(
"Volume having %s shape divided in %d %s slices",
534 daughter->GetShape()->ClassName(),daughter->GetNdaughters(), s1.Data());
536 }
else title.TString::Format(
"Volume with %s shape having %d daughter(s)",
537 daughter->GetShape()->ClassName(),daughter->GetNdaughters());
538 daughter->SetTitle(title.Data());
540 b->Add(daughter, daughter->GetName(), daughter->IsVisible());
552 Double_t TGeoVolume::Capacity()
const
554 if (!IsAssembly())
return fShape->Capacity();
555 Double_t capacity = 0.0;
556 Int_t nd = GetNdaughters();
558 for (i=0; i<nd; i++) capacity += GetNode(i)->GetVolume()->Capacity();
567 void TGeoVolume::CheckGeometry(Int_t nrays, Double_t startx, Double_t starty, Double_t startz)
const
569 TGeoVolume *old_vol = fGeoManager->GetTopVolume();
570 if (old_vol!=
this) fGeoManager->SetTopVolume((TGeoVolume*)
this);
572 fGeoManager->GetTopVolume()->Draw();
573 TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
574 painter->CheckGeometry(nrays, startx, starty, startz);
588 void TGeoVolume::CheckOverlaps(Double_t ovlp, Option_t *option)
const
590 if (!GetNdaughters() || fFinder)
return;
591 Bool_t sampling = kFALSE;
594 if (opt.Contains(
"s")) sampling = kTRUE;
595 TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
596 if (!sampling) fGeoManager->SetNsegments(80);
597 if (!fGeoManager->IsCheckingOverlaps()) {
598 fGeoManager->ClearOverlaps();
601 painter->CheckOverlaps(
this, ovlp, option);
603 if (!fGeoManager->IsCheckingOverlaps()) {
604 fGeoManager->SortOverlaps();
605 TObjArray *overlaps = fGeoManager->GetListOfOverlaps();
606 Int_t novlps = overlaps->GetEntriesFast();
609 for (Int_t i=0; i<novlps; i++) {
610 obj = (TNamed*)overlaps->At(i);
611 if (novlps<1000) name = TString::Format(
"ov%03d", i);
612 else name = TString::Format(
"ov%06d", i);
615 if (novlps) Info(
"CheckOverlaps",
"Number of illegal overlaps/extrusions for volume %s: %d\n", GetName(), novlps);
622 void TGeoVolume::CheckShape(Int_t testNo, Int_t nsamples, Option_t *option)
624 fShape->CheckShape(testNo,nsamples,option);
630 void TGeoVolume::CleanAll()
639 void TGeoVolume::ClearShape()
641 fGeoManager->ClearShape(fShape);
647 void TGeoVolume::CheckShapes()
649 if (fShape->IsRunTimeShape()) {
650 Error(
"CheckShapes",
"volume %s has run-time shape", GetName());
655 Int_t nd=fNodes->GetEntriesFast();
658 const TGeoShape *shape = 0;
660 for (Int_t i=0; i<nd; i++) {
661 node=(TGeoNode*)fNodes->At(i);
663 if (!node->GetName()[0]) printf(
"Daughter %i of volume %s - NO NAME!!!\n",
665 old_vol = node->GetVolume();
666 shape = old_vol->GetShape();
667 if (shape->IsRunTimeShape()) {
672 new_node = node->MakeCopyNode();
674 Fatal(
"CheckShapes",
"Cannot make copy node for %s", node->GetName());
677 TGeoShape *new_shape = shape->GetMakeRuntimeShape(fShape, node->GetMatrix());
679 Error(
"CheckShapes",
"cannot resolve runtime shape for volume %s/%s\n",
680 GetName(),old_vol->GetName());
683 TGeoVolume *new_volume = old_vol->MakeCopyVolume(new_shape);
686 new_node->SetVolume(new_volume);
688 fNodes->AddAt(new_node, i);
701 Int_t TGeoVolume::CountNodes(Int_t nlevels, Int_t option)
703 static Int_t maxlevel = 0;
704 static Int_t nlev = 0;
706 if (option<0 || option>3) option = 0;
708 Int_t nd = GetNdaughters();
709 Bool_t last = (!nlevels || !nd)?kTRUE:kFALSE;
712 if (fNtotal)
return fNtotal;
717 visopt = fGeoManager->GetVisOption();
718 if (!IsVisDaughters()) last = kTRUE;
720 case TVirtualGeoPainter::kGeoVisDefault:
721 fNtotal = (IsVisible())?1:0;
723 case TVirtualGeoPainter::kGeoVisLeaves:
724 fNtotal = (IsVisible() && last)?1:0;
726 if (!IsVisibleDaughters())
return fNtotal;
731 if (last)
return fNtotal;
732 if (gGeoManager->GetTopVolume() ==
this) {
736 if (nlev>maxlevel) maxlevel = nlev;
740 for (Int_t i=0; i<nd; i++) {
742 vol = node->GetVolume();
743 fNtotal += vol->CountNodes(nlevels-1, option);
752 Bool_t TGeoVolume::IsAllInvisible()
const
754 if (IsVisible())
return kFALSE;
755 Int_t nd = GetNdaughters();
756 for (Int_t i=0; i<nd; i++)
if (GetNode(i)->GetVolume()->IsVisible())
return kFALSE;
763 void TGeoVolume::InvisibleAll(Bool_t flag)
765 SetAttVisibility(!flag);
766 Int_t nd = GetNdaughters();
767 TObjArray *list =
new TObjArray(nd+1);
770 for (Int_t i=0; i<nd; i++) {
771 vol = GetNode(i)->GetVolume();
772 vol->SetAttVisibility(!flag);
775 TIter next(gROOT->GetListOfBrowsers());
776 TBrowser *browser = 0;
777 while ((browser=(TBrowser*)next())) {
778 for (Int_t i=0; i<nd+1; i++) {
779 vol = (TGeoVolume*)list->At(i);
780 browser->CheckObjectItem(vol, !flag);
785 fGeoManager->SetVisOption(4);
791 Bool_t TGeoVolume::IsFolder()
const
799 Bool_t TGeoVolume::IsStyleDefault()
const
801 if (!IsVisible())
return kFALSE;
802 if (GetLineColor() != gStyle->GetLineColor())
return kFALSE;
803 if (GetLineStyle() != gStyle->GetLineStyle())
return kFALSE;
804 if (GetLineWidth() != gStyle->GetLineWidth())
return kFALSE;
811 Bool_t TGeoVolume::IsTopVolume()
const
813 if (fGeoManager->GetTopVolume() ==
this)
return kTRUE;
820 Bool_t TGeoVolume::IsRaytracing()
const
822 return TGeoAtt::IsVisRaytrace();
828 void TGeoVolume::InspectMaterial()
const
830 GetMaterial()->Print();
836 TGeoVolume *TGeoVolume::Import(
const char *filename,
const char *name, Option_t * )
838 if (!gGeoManager) gGeoManager =
new TGeoManager(
"geometry",
"");
839 if (!filename)
return 0;
840 TGeoVolume *volume = 0;
841 if (strstr(filename,
".gdml")) {
845 TDirectory::TContext ctxt;
846 TFile *f = TFile::Open(filename);
847 if (!f || f->IsZombie()) {
848 printf(
"Error: TGeoVolume::Import : Cannot open file %s\n", filename);
851 if (name && name[0]) {
852 volume = (TGeoVolume*)f->Get(name);
854 TIter next(f->GetListOfKeys());
856 while ((key = (TKey*)next())) {
857 if (strcmp(key->GetClassName(),
"TGeoVolume") != 0)
continue;
858 volume = (TGeoVolume*)key->ReadObj();
864 if (!volume)
return NULL;
865 volume->RegisterYourself();
886 Int_t TGeoVolume::Export(
const char *filename,
const char *name, Option_t *option)
888 TString sfile(filename);
889 if (sfile.Contains(
".C")) {
891 Info(
"Export",
"Exporting volume %s as C++ code", GetName());
892 SaveAs(filename,
"");
895 if (sfile.Contains(
".gdml")) {
897 Info(
"Export",
"Exporting %s as gdml code - not implemented yet", GetName());
900 if (sfile.Contains(
".root") || sfile.Contains(
".xml")) {
902 Info(
"Export",
"Exporting %s as root file.", GetName());
904 if (!opt.Length()) opt =
"recreate";
905 TFile *f = TFile::Open(filename,opt.Data());
906 if (!f || f->IsZombie()) {
907 Error(
"Export",
"Cannot open file");
910 TString keyname(name);
911 if (keyname.IsNull()) keyname = GetName();
912 Int_t nbytes = Write(keyname);
922 void TGeoVolume::cd(Int_t inode)
const
924 if (fFinder) fFinder->cd(inode-fFinder->GetDivIndex());
931 void TGeoVolume::AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t * )
933 TGeoMatrix *matrix = mat;
934 if (matrix==0) matrix = gGeoIdentity;
935 else matrix->RegisterYourself();
937 Error(
"AddNode",
"Volume is NULL");
940 if (!vol->IsValid()) {
941 Error(
"AddNode",
"Won't add node with invalid shape");
942 printf(
"### invalid volume was : %s\n", vol->GetName());
945 if (!fNodes) fNodes =
new TObjArray();
949 Error(
"AddNode",
"Cannot add node %s_%i into divided volume %s", vol->GetName(), copy_no, GetName());
953 TGeoNodeMatrix *node = 0;
954 node =
new TGeoNodeMatrix(vol, matrix);
955 node->SetMotherVolume(
this);
957 TString name = TString::Format(
"%s_%d", vol->GetName(), copy_no);
961 node->SetNumber(copy_no);
970 void TGeoVolume::AddNodeOffset(TGeoVolume *vol, Int_t copy_no, Double_t offset, Option_t * )
973 Error(
"AddNodeOffset",
"invalid volume");
976 if (!vol->IsValid()) {
977 Error(
"AddNode",
"Won't add node with invalid shape");
978 printf(
"### invalid volume was : %s\n", vol->GetName());
981 if (!fNodes) fNodes =
new TObjArray();
982 TGeoNode *node =
new TGeoNodeOffset(vol, copy_no, offset);
983 node->SetMotherVolume(
this);
985 TString name = TString::Format(
"%s_%d", vol->GetName(), copy_no+1);
987 node->SetNumber(copy_no+1);
995 void TGeoVolume::AddNodeOverlap(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
998 Error(
"AddNodeOverlap",
"Volume is NULL");
1001 if (!vol->IsValid()) {
1002 Error(
"AddNodeOverlap",
"Won't add node with invalid shape");
1003 printf(
"### invalid volume was : %s\n", vol->GetName());
1006 if (vol->IsAssembly()) {
1007 Warning(
"AddNodeOverlap",
"Declaring assembly %s as possibly overlapping inside %s not allowed. Using AddNode instead !",vol->GetName(),GetName());
1008 AddNode(vol, copy_no, mat, option);
1011 TGeoMatrix *matrix = mat;
1012 if (matrix==0) matrix = gGeoIdentity;
1013 else matrix->RegisterYourself();
1014 if (!fNodes) fNodes =
new TObjArray();
1018 Error(
"AddNodeOverlap",
"Cannot add node %s_%i into divided volume %s", vol->GetName(), copy_no, GetName());
1022 TGeoNodeMatrix *node =
new TGeoNodeMatrix(vol, matrix);
1023 node->SetMotherVolume(
this);
1025 TString name = TString::Format(
"%s_%d", vol->GetName(), copy_no);
1026 if (fNodes->FindObject(name))
1027 Warning(
"AddNode",
"Volume %s : added node %s with same name", GetName(), name.Data());
1028 node->SetName(name);
1029 node->SetNumber(copy_no);
1030 node->SetOverlapping();
1031 if (vol->GetMedium() == fMedium)
1049 TGeoVolume *TGeoVolume::Divide(
const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed, Option_t *option)
1053 Fatal(
"Divide",
"volume %s already divided", GetName());
1056 TString opt(option);
1058 TString stype = fShape->ClassName();
1059 if (!fNodes) fNodes =
new TObjArray();
1060 Double_t xlo, xhi, range;
1061 range = fShape->GetAxisRange(iaxis, xlo, xhi);
1063 if (!strcmp(fShape->GetAxisName(iaxis),
"PHI")) {
1064 if ((start-xlo)<-1E-3) start+=360.;
1065 if (TGeoShape::IsSameWithinTolerance(range,360)) {
1072 Fatal(
"Divide",
"cannot divide volume %s (%s) on %s axis", GetName(), stype.Data(), fShape->GetAxisName(iaxis));
1075 if (ndiv<=0 || opt.Contains(
"s")) {
1077 Fatal(
"Divide",
"invalid division type for volume %s : ndiv=%i, step=%g", GetName(), ndiv, step);
1080 if (opt.Contains(
"x")) {
1081 if ((xlo-start)>1E-3 || (xhi-start)<-1E-3) {
1082 Fatal(
"Divide",
"invalid START=%g for division on axis %s of volume %s. Range is (%g, %g)",
1083 start, fShape->GetAxisName(iaxis), GetName(), xlo, xhi);
1089 ndiv = Int_t((range+0.1*step)/step);
1090 Double_t ddx = range - ndiv*step;
1092 if (ddx>1E-3) Warning(
"Divide",
"division of volume %s on %s axis (ndiv=%d) will be centered in the full range",
1093 GetName(), fShape->GetAxisName(iaxis), ndiv);
1094 start = xlo + 0.5*ddx;
1096 if (step<=0 || opt.Contains(
"n")) {
1097 if (opt.Contains(
"x")) {
1098 if ((xlo-start)>1E-3 || (xhi-start)<-1E-3) {
1099 Fatal(
"Divide",
"invalid START=%g for division on axis %s of volume %s. Range is (%g, %g)",
1100 start, fShape->GetAxisName(iaxis), GetName(), xlo, xhi);
1110 Double_t end = start+ndiv*step;
1111 if (((start-xlo)<-1E-3) || ((end-xhi)>1E-3)) {
1112 Fatal(
"Divide",
"division of volume %s on axis %s exceed range (%g, %g)",
1113 GetName(), fShape->GetAxisName(iaxis), xlo, xhi);
1116 TGeoVolume *voldiv = fShape->Divide(
this, divname, iaxis, ndiv, start, step);
1118 TGeoMedium *medium = fGeoManager->GetMedium(numed);
1120 Fatal(
"Divide",
"invalid medium number %d for division volume %s", numed, divname);
1123 voldiv->SetMedium(medium);
1124 if (medium->GetMaterial()) medium->GetMaterial()->SetUsed();
1132 Int_t TGeoVolume::DistancetoPrimitive(Int_t px, Int_t py)
1134 if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
1135 TVirtualGeoPainter *painter = fGeoManager->GetPainter();
1137 if (!painter)
return dist;
1138 dist = painter->DistanceToPrimitiveVol(
this, px, py);
1145 void TGeoVolume::Draw(Option_t *option)
1147 if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
1148 fGeoManager->SetUserPaintVolume(
this);
1149 TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
1150 TGeoAtt::SetVisRaytrace(kFALSE);
1151 if (!IsVisContainers()) SetVisLeaves();
1152 if (option && option[0] > 0) {
1153 painter->DrawVolume(
this, option);
1155 painter->DrawVolume(
this, gEnv->GetValue(
"Viewer3D.DefaultDrawOption",
""));
1162 void TGeoVolume::DrawOnly(Option_t *option)
1165 Info(
"DrawOnly",
"Volume assemblies do not support this option.");
1168 if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
1170 TGeoAtt::SetVisRaytrace(kFALSE);
1171 TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
1172 if (option && option[0] > 0) {
1173 painter->DrawVolume(
this, option);
1175 painter->DrawVolume(
this, gEnv->GetValue(
"Viewer3D.DefaultDrawOption",
""));
1183 Bool_t TGeoVolume::OptimizeVoxels()
1185 printf(
"Optimizing volume %s ...\n", GetName());
1186 TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
1187 return painter->TestVoxels(
this);
1193 void TGeoVolume::Print(Option_t *)
const
1195 printf(
"== Volume: %s type %s positioned %d times\n", GetName(), ClassName(), fRefCount);
1203 void TGeoVolume::Paint(Option_t *option)
1205 TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
1206 painter->SetTopVolume(
this);
1208 if (option && option[0] > 0) {
1209 painter->Paint(option);
1211 painter->Paint(gEnv->GetValue(
"Viewer3D.DefaultDrawOption",
""));
1218 void TGeoVolume::PrintVoxels()
const
1220 if (fVoxels) fVoxels->Print();
1227 void TGeoVolume::ReplayCreation(
const TGeoVolume *other)
1229 Int_t nd = other->GetNdaughters();
1231 TGeoPatternFinder *finder = other->GetFinder();
1233 Int_t iaxis = finder->GetDivAxis();
1234 Int_t ndiv = finder->GetNdiv();
1235 Double_t start = finder->GetStart();
1236 Double_t step = finder->GetStep();
1237 Int_t numed = other->GetNode(0)->GetVolume()->GetMedium()->GetId();
1238 TGeoVolume *voldiv = Divide(other->GetNode(0)->GetVolume()->GetName(), iaxis, ndiv, start, step, numed);
1239 voldiv->ReplayCreation(other->GetNode(0)->GetVolume());
1242 for (Int_t i=0; i<nd; i++) {
1243 TGeoNode *node = other->GetNode(i);
1244 if (node->IsOverlapping()) AddNodeOverlap(node->GetVolume(), node->GetNumber(), node->GetMatrix());
1245 else AddNode(node->GetVolume(), node->GetNumber(), node->GetMatrix());
1252 void TGeoVolume::PrintNodes()
const
1254 Int_t nd = GetNdaughters();
1255 for (Int_t i=0; i<nd; i++) {
1256 printf(
"%s\n", GetNode(i)->GetName());
1258 GetNode(i)->GetMatrix()->Print();
1264 TH2F *TGeoVolume::LegoPlot(Int_t ntheta, Double_t themin, Double_t themax,
1265 Int_t nphi, Double_t phimin, Double_t phimax,
1266 Double_t rmin, Double_t rmax, Option_t *option)
1268 TVirtualGeoPainter *p = fGeoManager->GetGeomPainter();
1269 TGeoVolume *old_vol = fGeoManager->GetTopVolume();
1270 if (old_vol!=
this) fGeoManager->SetTopVolume(
this);
1272 TH2F *hist = p->LegoPlot(ntheta, themin, themax, nphi, phimin, phimax, rmin, rmax, option);
1273 hist->Draw(
"lego1sph");
1280 void TGeoVolume::RegisterYourself(Option_t *option)
1282 if (fGeoManager->GetListOfVolumes()->FindObject(
this))
return;
1284 fGeoManager->AddVolume(
this);
1286 if (!fGeoManager->GetListOfShapes()->FindObject(fShape)) {
1287 if (fShape->IsComposite()) {
1288 TGeoCompositeShape *comp = (TGeoCompositeShape*)fShape;
1289 comp->RegisterYourself();
1291 fGeoManager->AddShape(fShape);
1295 if (fMedium && !fGeoManager->GetListOfMedia()->FindObject(fMedium)) {
1296 fGeoManager->GetListOfMedia()->Add(fMedium);
1297 if (!fGeoManager->GetListOfMaterials()->FindObject(fMedium->GetMaterial()))
1298 fGeoManager->AddMaterial(fMedium->GetMaterial());
1303 Int_t nd = GetNdaughters();
1305 for (i=0; i<nd; i++) {
1307 matrix = node->GetMatrix();
1308 if (!matrix->IsRegistered()) matrix->RegisterYourself();
1309 else if (!fGeoManager->GetListOfMatrices()->FindObject(matrix)) {
1310 fGeoManager->GetListOfMatrices()->Add(matrix);
1314 for (i=0; i<nd; i++) GetNode(i)->GetVolume()->RegisterYourself(option);
1320 void TGeoVolume::RandomPoints(Int_t npoints, Option_t *option)
1322 if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
1323 TGeoVolume *old_vol = fGeoManager->GetTopVolume();
1324 if (old_vol!=
this) fGeoManager->SetTopVolume(
this);
1326 fGeoManager->RandomPoints(
this, npoints, option);
1327 if (old_vol) fGeoManager->SetTopVolume(old_vol);
1333 void TGeoVolume::RandomRays(Int_t nrays, Double_t startx, Double_t starty, Double_t startz,
const char *target_vol, Bool_t check_norm)
1335 if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
1336 TGeoVolume *old_vol = fGeoManager->GetTopVolume();
1337 if (old_vol!=
this) fGeoManager->SetTopVolume(
this);
1339 fGeoManager->RandomRays(nrays, startx, starty, startz, target_vol, check_norm);
1340 if (old_vol) fGeoManager->SetTopVolume(old_vol);
1346 void TGeoVolume::Raytrace(Bool_t flag)
1348 TGeoAtt::SetVisRaytrace(kFALSE);
1349 if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
1350 TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
1351 Bool_t drawn = (painter->GetDrawnVolume()==
this)?kTRUE:kFALSE;
1353 painter->DrawVolume(
this,
"");
1354 TGeoAtt::SetVisRaytrace(flag);
1355 painter->ModifiedPad();
1358 TGeoAtt::SetVisRaytrace(flag);
1359 painter->ModifiedPad();
1365 void TGeoVolume::SaveAs(
const char *filename, Option_t *option)
const
1367 if (!filename)
return;
1369 out.open(filename, std::ios::out);
1371 Error(
"SavePrimitive",
"Bad file name: %s", filename);
1374 if (fGeoManager->GetTopVolume() !=
this) fGeoManager->SetTopVolume((TGeoVolume*)
this);
1376 TString fname(filename);
1377 Int_t ind = fname.Index(
".");
1378 if (ind>0) fname.Remove(ind);
1379 out <<
"void "<<fname<<
"() {" << std::endl;
1380 out <<
" gSystem->Load(\"libGeom\");" << std::endl;
1381 const UInt_t prec = TGeoManager::GetExportPrecision();
1382 out << std::setprecision(prec);
1383 ((TGeoVolume*)
this)->SavePrimitive(out,option);
1384 out <<
"}" << std::endl;
1395 void TGeoVolume::SetUserExtension(TGeoExtension *ext)
1397 if (fUserExtension) fUserExtension->Release();
1399 if (ext) fUserExtension = ext->Grab();
1410 void TGeoVolume::SetFWExtension(TGeoExtension *ext)
1412 if (fFWExtension) fFWExtension->Release();
1414 if (ext) fFWExtension = ext->Grab();
1422 TGeoExtension *TGeoVolume::GrabUserExtension()
const
1424 if (fUserExtension)
return fUserExtension->Grab();
1433 TGeoExtension *TGeoVolume::GrabFWExtension()
const
1435 if (fFWExtension)
return fFWExtension->Grab();
1442 void TGeoVolume::SavePrimitive(std::ostream &out, Option_t *option )
1445 Int_t nd = GetNdaughters();
1451 Bool_t mustDraw = kFALSE;
1452 if (fGeoManager->GetGeomPainter()->GetTopVolume()==
this) mustDraw = kTRUE;
1454 fGeoManager->SetAllIndex();
1455 out <<
" new TGeoManager(\"" << fGeoManager->GetName() <<
"\", \"" << fGeoManager->GetTitle() <<
"\");" << std::endl << std::endl;
1458 out <<
" Double_t dx,dy,dz;" << std::endl;
1459 out <<
" Double_t dx1, dx2, dy1, dy2;" << std::endl;
1460 out <<
" Double_t vert[20], par[20];" << std::endl;
1461 out <<
" Double_t theta, phi, h1, bl1, tl1, alpha1, h2, bl2, tl2, alpha2;" << std::endl;
1462 out <<
" Double_t twist;" << std::endl;
1463 out <<
" Double_t origin[3];" << std::endl;
1464 out <<
" Double_t rmin, rmax, rmin1, rmax1, rmin2, rmax2;" << std::endl;
1465 out <<
" Double_t r, rlo, rhi;" << std::endl;
1466 out <<
" Double_t phi1, phi2;" << std::endl;
1467 out <<
" Double_t a,b;" << std::endl;
1468 out <<
" Double_t point[3], norm[3];" << std::endl;
1469 out <<
" Double_t rin, stin, rout, stout;" << std::endl;
1470 out <<
" Double_t thx, phx, thy, phy, thz, phz;" << std::endl;
1471 out <<
" Double_t alpha, theta1, theta2, phi1, phi2, dphi;" << std::endl;
1472 out <<
" Double_t tr[3], rot[9];" << std::endl;
1473 out <<
" Double_t z, density, radl, absl, w;" << std::endl;
1474 out <<
" Double_t lx,ly,lz,tx,ty,tz;" << std::endl;
1475 out <<
" Double_t xvert[50], yvert[50];" << std::endl;
1476 out <<
" Double_t zsect,x0,y0,scale0;" << std::endl;
1477 out <<
" Int_t nel, numed, nz, nedges, nvert;" << std::endl;
1478 out <<
" TGeoBoolNode *pBoolNode = 0;" << std::endl << std::endl;
1480 out <<
" // MATERIALS, MIXTURES AND TRACKING MEDIA" << std::endl;
1481 SavePrimitive(out,
"m");
1483 out << std::endl <<
" // TRANSFORMATION MATRICES" << std::endl;
1484 SavePrimitive(out,
"x");
1486 SavePrimitive(out,
"s");
1487 out << std::endl <<
" // SET TOP VOLUME OF GEOMETRY" << std::endl;
1488 out <<
" gGeoManager->SetTopVolume(" << GetPointerName() <<
");" << std::endl;
1490 out << std::endl <<
" // SHAPES, VOLUMES AND GEOMETRICAL HIERARCHY" << std::endl;
1491 SavePrimitive(out,
"d");
1492 out << std::endl <<
" // CLOSE GEOMETRY" << std::endl;
1493 out <<
" gGeoManager->CloseGeometry();" << std::endl;
1495 if (!IsRaytracing()) out <<
" gGeoManager->GetTopVolume()->Draw();" << std::endl;
1496 else out <<
" gGeoManager->GetTopVolume()->Raytrace();" << std::endl;
1501 if (!strcmp(option,
"s")) {
1503 if (TestAttBit(TGeoAtt::kSavePrimitiveAtt))
return;
1504 if (!IsAssembly()) {
1505 fShape->SavePrimitive(out,option);
1506 out <<
" // Volume: " << GetName() << std::endl;
1507 if (fMedium) out <<
" " << GetPointerName() <<
" = new TGeoVolume(\"" << GetName() <<
"\"," << fShape->GetPointerName() <<
", "<< fMedium->GetPointerName() <<
");" << std::endl;
1508 else out <<
" " << GetPointerName() <<
" = new TGeoVolume(\"" << GetName() <<
"\"," << fShape->GetPointerName() <<
");" << std::endl;
1511 out <<
" // Assembly: " << GetName() << std::endl;
1512 out <<
" " << GetPointerName() <<
" = new TGeoVolumeAssembly(\"" << GetName() <<
"\"" <<
");" << std::endl;
1514 if (fLineColor != 1) out <<
" " << GetPointerName() <<
"->SetLineColor(" << fLineColor <<
");" << std::endl;
1515 if (fLineWidth != 1) out <<
" " << GetPointerName() <<
"->SetLineWidth(" << fLineWidth <<
");" << std::endl;
1516 if (fLineStyle != 1) out <<
" " << GetPointerName() <<
"->SetLineStyle(" << fLineStyle <<
");" << std::endl;
1517 if (!IsVisible() && !IsAssembly()) out <<
" " << GetPointerName() <<
"->SetVisibility(kFALSE);" << std::endl;
1518 if (!IsVisibleDaughters()) out <<
" " << GetPointerName() <<
"->VisibleDaughters(kFALSE);" << std::endl;
1519 if (IsVisContainers()) out <<
" " << GetPointerName() <<
"->SetVisContainers(kTRUE);" << std::endl;
1520 if (IsVisLeaves()) out <<
" " << GetPointerName() <<
"->SetVisLeaves(kTRUE);" << std::endl;
1521 SetAttBit(TGeoAtt::kSavePrimitiveAtt);
1524 if (!strcmp(option,
"m")) {
1525 if (fMedium) fMedium->SavePrimitive(out,option);
1526 for (i=0; i<nd; i++) {
1527 dvol = GetNode(i)->GetVolume();
1528 dvol->SavePrimitive(out,option);
1533 if (!strcmp(option,
"x")) {
1535 dvol = GetNode(0)->GetVolume();
1536 dvol->SavePrimitive(out,option);
1539 for (i=0; i<nd; i++) {
1541 matrix = dnode->GetMatrix();
1542 if (!matrix->IsIdentity()) matrix->SavePrimitive(out,option);
1543 dnode->GetVolume()->SavePrimitive(out,option);
1548 if (!strcmp(option,
"d")) {
1550 if (TestAttBit(TGeoAtt::kSaveNodesAtt))
return;
1551 SetAttBit(TGeoAtt::kSaveNodesAtt);
1555 dvol = dnode->GetVolume();
1556 out <<
" TGeoVolume *" << dvol->GetPointerName() <<
" = ";
1557 out << GetPointerName() <<
"->Divide(\"" << dvol->GetName() <<
"\", ";
1558 fFinder->SavePrimitive(out,option);
1559 if (fMedium != dvol->GetMedium()) {
1560 out <<
", " << dvol->GetMedium()->GetId();
1562 out <<
");" << std::endl;
1563 dvol->SavePrimitive(out,
"d");
1566 for (i=0; i<nd; i++) {
1568 dvol = dnode->GetVolume();
1569 dvol->SavePrimitive(out,
"s");
1570 matrix = dnode->GetMatrix();
1571 icopy = dnode->GetNumber();
1573 out <<
" " << GetPointerName() <<
"->AddNode";
1574 if (dnode->IsOverlapping()) out <<
"Overlap";
1575 out <<
"(" << dvol->GetPointerName() <<
", " << icopy;
1576 if (!matrix->IsIdentity()) out <<
", " << matrix->GetPointerName();
1577 out <<
");" << std::endl;
1580 for (i=0; i<nd; i++) {
1582 dvol = dnode->GetVolume();
1583 dvol->SavePrimitive(out,
"d");
1591 void TGeoVolume::UnmarkSaved()
1593 ResetAttBit(TGeoAtt::kSavePrimitiveAtt);
1594 ResetAttBit(TGeoAtt::kSaveNodesAtt);
1595 if (fShape) fShape->ResetBit(TGeoShape::kGeoSavePrimitive);
1601 void TGeoVolume::ExecuteEvent(Int_t event, Int_t px, Int_t py)
1603 TVirtualGeoPainter *painter = fGeoManager->GetPainter();
1604 if (!painter)
return;
1605 painter->ExecuteVolumeEvent(
this, event, px, py);
1611 TGeoNode *TGeoVolume::FindNode(
const char *name)
const
1613 return ((TGeoNode*)fNodes->FindObject(name));
1619 Int_t TGeoVolume::GetNodeIndex(
const TGeoNode *node, Int_t *check_list, Int_t ncheck)
const
1621 TGeoNode *current = 0;
1622 for (Int_t i=0; i<ncheck; i++) {
1623 current = (TGeoNode*)fNodes->At(check_list[i]);
1624 if (current==node)
return check_list[i];
1632 Int_t TGeoVolume::GetIndex(
const TGeoNode *node)
const
1634 TGeoNode *current = 0;
1635 Int_t nd = GetNdaughters();
1637 for (Int_t i=0; i<nd; i++) {
1638 current = (TGeoNode*)fNodes->At(i);
1639 if (current==node)
return i;
1647 char *TGeoVolume::GetObjectInfo(Int_t px, Int_t py)
const
1649 TGeoVolume *vol = (TGeoVolume*)
this;
1650 TVirtualGeoPainter *painter = fGeoManager->GetPainter();
1651 if (!painter)
return 0;
1652 return (
char*)painter->GetVolumeInfo(vol, px, py);
1658 Bool_t TGeoVolume::GetOptimalVoxels()
const
1660 Int_t nd = GetNdaughters();
1661 if (!nd)
return kFALSE;
1665 for (
id=0;
id<nd;
id++) {
1666 node = (TGeoNode*)fNodes->At(
id);
1667 ncyl += node->GetOptimalVoxels();
1669 if (ncyl>(nd/2))
return kTRUE;
1676 char *TGeoVolume::GetPointerName()
const
1678 static TString name;
1679 name = TString::Format(
"p%s_%lx", GetName(), (ULong_t)
this);
1680 return (
char*)name.Data();
1686 TGeoVoxelFinder *TGeoVolume::GetVoxels()
const
1688 if (fVoxels && !fVoxels->IsInvalid())
return fVoxels;
1695 void TGeoVolume::GrabFocus()
1697 TVirtualGeoPainter *painter = fGeoManager->GetPainter();
1698 if (painter) painter->GrabFocus();
1704 Bool_t TGeoVolume::IsAssembly()
const
1706 return fShape->IsAssembly();
1713 TGeoVolume *TGeoVolume::CloneVolume()
const
1715 TGeoVolume *vol =
new TGeoVolume(GetName(), fShape, fMedium);
1718 vol->SetLineColor(GetLineColor());
1719 vol->SetLineStyle(GetLineStyle());
1720 vol->SetLineWidth(GetLineWidth());
1721 vol->SetFillColor(GetFillColor());
1722 vol->SetFillStyle(GetFillStyle());
1724 Int_t nbits = 8*
sizeof(UInt_t);
1725 for (i=0; i<nbits; i++)
1726 vol->SetAttBit(1<<i, TGeoAtt::TestAttBit(1<<i));
1727 for (i=14; i<24; i++)
1728 vol->SetBit(1<<i, TestBit(1<<i));
1731 vol->SetField(fField);
1733 for (i=0; i<nbits; i++)
1734 vol->SetBit(1<<i, TObject::TestBit(1<<i));
1735 vol->SetBit(kVolumeClone);
1738 vol->MakeCopyNodes(
this);
1740 vol->SetFinder(fFinder);
1742 TGeoVoxelFinder *voxels = 0;
1744 voxels =
new TGeoVoxelFinder(vol);
1745 vol->SetVoxelFinder(voxels);
1748 vol->SetOption(fOption);
1749 vol->SetNumber(fNumber);
1750 vol->SetNtotal(fNtotal);
1752 vol->SetUserExtension(fUserExtension);
1753 vol->SetFWExtension(fFWExtension);
1754 vol->SetOverlappingCandidate(IsOverlappingCandidate());
1761 void TGeoVolume::CloneNodesAndConnect(TGeoVolume *newmother)
const
1763 if (!fNodes)
return;
1765 Int_t nd = fNodes->GetEntriesFast();
1768 TObjArray *list =
new TObjArray(nd);
1770 newmother->SetNodes(list);
1772 for (Int_t i=0; i<nd; i++) {
1774 node = GetNode(i)->MakeCopyNode();
1776 Fatal(
"CloneNodesAndConnect",
"cannot make copy node");
1779 node->SetMotherVolume(newmother);
1787 void TGeoVolume::MakeCopyNodes(
const TGeoVolume *other)
1789 Int_t nd = other->GetNdaughters();
1792 if (!TObject::TestBit(kVolumeImportNodes)) fNodes->Delete();
1795 fNodes =
new TObjArray();
1796 for (Int_t i=0; i<nd; i++) fNodes->Add(other->GetNode(i));
1797 TObject::SetBit(kVolumeImportNodes);
1804 TGeoVolume *TGeoVolume::MakeCopyVolume(TGeoShape *newshape)
1806 TGeoVolume *vol =
new TGeoVolume(GetName(), newshape, fMedium);
1808 vol->SetVisibility(IsVisible());
1809 vol->SetLineColor(GetLineColor());
1810 vol->SetLineStyle(GetLineStyle());
1811 vol->SetLineWidth(GetLineWidth());
1812 vol->SetFillColor(GetFillColor());
1813 vol->SetFillStyle(GetFillStyle());
1815 vol->SetField(fField);
1819 vol->SetFinder(fFinder);
1822 vol->SetUserExtension(fUserExtension);
1823 vol->SetFWExtension(fFWExtension);
1824 CloneNodesAndConnect(vol);
1826 ((TObject*)vol)->SetBit(kVolumeClone);
1827 vol->SetOverlappingCandidate(IsOverlappingCandidate());
1834 TGeoVolume *TGeoVolume::MakeReflectedVolume(
const char *newname)
const
1836 static TMap map(100);
1837 if (!fGeoManager->IsClosed()) {
1838 Error(
"MakeReflectedVolume",
"Geometry must be closed.");
1841 TGeoVolume *vol = (TGeoVolume*)map.GetValue(
this);
1843 if (newname && newname[0]) vol->SetName(newname);
1847 vol = CloneVolume();
1849 Fatal(
"MakeReflectedVolume",
"Cannot clone volume %s\n", GetName());
1852 map.Add((TObject*)
this, vol);
1853 if (newname && newname[0]) vol->SetName(newname);
1854 delete vol->GetNodes();
1855 vol->SetNodes(NULL);
1856 vol->SetBit(kVolumeImportNodes, kFALSE);
1857 CloneNodesAndConnect(vol);
1861 TGeoShape *reflected_shape =
1862 TGeoScaledShape::MakeScaledShape(
"", fShape,
new TGeoScale(1.,1.,-1.));
1863 vol->SetShape(reflected_shape);
1866 Int_t nd = vol->GetNdaughters();
1867 if (!nd)
return vol;
1868 TGeoNodeMatrix *node;
1869 TGeoMatrix *local, *local_cloned;
1870 TGeoVolume *new_vol;
1871 if (!vol->GetFinder()) {
1872 for (Int_t i=0; i<nd; i++) {
1873 node = (TGeoNodeMatrix*)vol->GetNode(i);
1874 local = node->GetMatrix();
1877 Bool_t reflected = local->IsReflection();
1878 local_cloned =
new TGeoCombiTrans(*local);
1879 local_cloned->RegisterYourself();
1880 node->SetMatrix(local_cloned);
1884 local_cloned->ReflectZ(kTRUE);
1885 local_cloned->ReflectZ(kFALSE);
1888 new_vol = node->GetVolume()->MakeReflectedVolume();
1889 node->SetVolume(new_vol);
1893 local_cloned->ReflectZ(kTRUE);
1897 if (vol->GetVoxels()) vol->GetVoxels()->Voxelize();
1902 TGeoPatternFinder *new_finder = fFinder->MakeCopy(kTRUE);
1904 Fatal(
"MakeReflectedVolume",
"Could not copy finder for volume %s", GetName());
1907 new_finder->SetVolume(vol);
1908 vol->SetFinder(new_finder);
1909 TGeoNodeOffset *nodeoff;
1911 for (Int_t i=0; i<nd; i++) {
1912 nodeoff = (TGeoNodeOffset*)vol->GetNode(i);
1913 nodeoff->SetFinder(new_finder);
1914 new_vol = nodeoff->GetVolume()->MakeReflectedVolume();
1915 nodeoff->SetVolume(new_vol);
1923 void TGeoVolume::SetAsTopVolume()
1925 fGeoManager->SetTopVolume(
this);
1931 void TGeoVolume::SetCurrentPoint(Double_t x, Double_t y, Double_t z)
1933 fGeoManager->SetCurrentPoint(x,y,z);
1939 void TGeoVolume::SetShape(
const TGeoShape *shape)
1942 Error(
"SetShape",
"No shape");
1945 fShape = (TGeoShape*)shape;
1952 void TGeoVolume::SortNodes()
1955 Error(
"SortNodes",
"Bounding box not valid");
1958 Int_t nd = GetNdaughters();
1961 if (fFinder)
return;
1965 TObjArray *nodes =
new TObjArray(nd);
1968 for (
id=0;
id<nd;
id++) {
1970 if (node->InheritsFrom(TGeoNodeOffset::Class()) || node->IsOverlapping())
continue;
1976 for (
id=0;
id<nd;
id++) {
1978 if (node->InheritsFrom(TGeoNodeOffset::Class()) || (!node->IsOverlapping()))
continue;
1985 fFinder->SetDivIndex(inode);
1986 for (
id=0;
id<nd;
id++) {
1988 if (!node->InheritsFrom(TGeoNodeOffset::Class()))
continue;
1994 if (inode != nd) printf(
" volume %s : number of nodes does not match!!!\n", GetName());
2002 void TGeoVolume::Streamer(TBuffer &R__b)
2004 if (R__b.IsReading()) {
2005 R__b.ReadClassBuffer(TGeoVolume::Class(),
this);
2006 if (fVoxels && fVoxels->IsInvalid()) Voxelize(
"");
2009 R__b.WriteClassBuffer(TGeoVolume::Class(),
this);
2011 if (!fGeoManager->IsStreamingVoxels()) {
2012 TGeoVoxelFinder *voxels = fVoxels;
2014 R__b.WriteClassBuffer(TGeoVolume::Class(),
this);
2017 R__b.WriteClassBuffer(TGeoVolume::Class(),
this);
2026 void TGeoVolume::SetOption(
const char *option)
2034 void TGeoVolume::SetLineColor(Color_t lcolor)
2036 TAttLine::SetLineColor(lcolor);
2042 void TGeoVolume::SetLineStyle(Style_t lstyle)
2044 TAttLine::SetLineStyle(lstyle);
2050 void TGeoVolume::SetLineWidth(Style_t lwidth)
2052 TAttLine::SetLineWidth(lwidth);
2058 TGeoNode *TGeoVolume::GetNode(
const char *name)
const
2060 if (!fNodes)
return 0;
2061 TGeoNode *node = (TGeoNode *)fNodes->FindObject(name);
2068 Int_t TGeoVolume::GetByteCount()
const
2070 Int_t count = 28+2+6+4+0;
2071 count += fName.Capacity() + fTitle.Capacity();
2072 count += 7*
sizeof(
char*);
2073 count += fOption.Capacity();
2074 if (fShape) count += fShape->GetByteCount();
2075 if (fFinder) count += fFinder->GetByteCount();
2077 count += 32 + 4*fNodes->GetEntries();
2080 while ((node=(TGeoNode*)next())) count += node->GetByteCount();
2088 void TGeoVolume::FindOverlaps()
const
2091 Error(
"FindOverlaps",
"Bounding box not valid");
2094 if (!fVoxels)
return;
2095 Int_t nd = GetNdaughters();
2099 for (inode=0; inode<nd; inode++) {
2100 node = GetNode(inode);
2101 if (!node->IsOverlapping())
continue;
2102 fVoxels->FindOverlaps(inode);
2109 void TGeoVolume::RemoveNode(TGeoNode *node)
2111 if (!fNodes || !fNodes->GetEntriesFast())
return;
2112 if (!fNodes->Remove(node))
return;
2114 if (fVoxels) fVoxels->SetNeedRebuild();
2115 if (IsAssembly()) fShape->ComputeBBox();
2123 TGeoNode *TGeoVolume::ReplaceNode(TGeoNode *nodeorig, TGeoShape *newshape, TGeoMatrix *newpos, TGeoMedium *newmed)
2125 Int_t ind = GetIndex(nodeorig);
2126 if (ind < 0)
return NULL;
2127 TGeoVolume *oldvol = nodeorig->GetVolume();
2128 if (oldvol->IsAssembly()) {
2129 Error(
"ReplaceNode",
"Cannot replace node %s since it is an assembly", nodeorig->GetName());
2132 TGeoShape *shape = oldvol->GetShape();
2133 if (newshape && !nodeorig->IsOffset()) shape = newshape;
2134 TGeoMedium *med = oldvol->GetMedium();
2135 if (newmed) med = newmed;
2137 TGeoVolume *vol =
new TGeoVolume(oldvol->GetName(), shape, med);
2139 vol->SetVisibility(oldvol->IsVisible());
2140 vol->SetLineColor(oldvol->GetLineColor());
2141 vol->SetLineStyle(oldvol->GetLineStyle());
2142 vol->SetLineWidth(oldvol->GetLineWidth());
2143 vol->SetFillColor(oldvol->GetFillColor());
2144 vol->SetFillStyle(oldvol->GetFillStyle());
2146 vol->SetField(oldvol->GetField());
2148 TGeoNode *newnode = nodeorig->MakeCopyNode();
2150 Fatal(
"ReplaceNode",
"Cannot make copy node for %s", nodeorig->GetName());
2154 newnode->SetVolume(vol);
2156 if (newpos && !nodeorig->IsOffset()) {
2157 TGeoNodeMatrix *nodemat = (TGeoNodeMatrix*)newnode;
2158 nodemat->SetMatrix(newpos);
2161 fNodes->RemoveAt(ind);
2162 fNodes->AddAt(newnode, ind);
2163 if (fVoxels) fVoxels->SetNeedRebuild();
2164 if (IsAssembly()) fShape->ComputeBBox();
2174 void TGeoVolume::SelectVolume(Bool_t clear)
2176 static TObjArray array(256);
2177 static Int_t len = 0;
2181 for (i=0; i<len; i++) {
2183 vol->ResetBit(TGeoVolume::kVolumeSelected);
2189 SetBit(TGeoVolume::kVolumeSelected);
2190 array.AddAtAndExpand(
this, len++);
2196 void TGeoVolume::SetVisibility(Bool_t vis)
2198 TGeoAtt::SetVisibility(vis);
2199 if (fGeoManager->IsClosed()) SetVisTouched(kTRUE);
2200 fGeoManager->SetVisOption(4);
2201 TSeqCollection *brlist = gROOT->GetListOfBrowsers();
2203 TBrowser *browser = 0;
2204 while ((browser=(TBrowser*)next())) {
2205 browser->CheckObjectItem(
this, vis);
2213 void TGeoVolume::SetVisContainers(Bool_t flag)
2215 TGeoAtt::SetVisContainers(flag);
2216 if (fGeoManager && fGeoManager->IsClosed()) {
2217 if (flag) fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisDefault);
2218 else fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisLeaves);
2225 void TGeoVolume::SetVisLeaves(Bool_t flag)
2227 TGeoAtt::SetVisLeaves(flag);
2228 if (fGeoManager && fGeoManager->IsClosed()) {
2229 if (flag) fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisLeaves);
2230 else fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisDefault);
2237 void TGeoVolume::SetVisOnly(Bool_t flag)
2239 if (IsAssembly())
return;
2240 TGeoAtt::SetVisOnly(flag);
2241 if (fGeoManager && fGeoManager->IsClosed()) {
2242 if (flag) fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisOnly);
2243 else fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisLeaves);
2250 Bool_t TGeoVolume::Valid()
const
2252 return fShape->IsValidBox();
2259 Bool_t TGeoVolume::FindMatrixOfDaughterVolume(TGeoVolume *vol)
const
2261 if (vol ==
this)
return kTRUE;
2262 Int_t nd = GetNdaughters();
2263 if (!nd)
return kFALSE;
2264 TGeoHMatrix *global = fGeoManager->GetHMatrix();
2265 if (!global)
return kFALSE;
2270 for (i=0; i<nd; i++) {
2272 dvol = dnode->GetVolume();
2274 local = dnode->GetMatrix();
2275 global->MultiplyLeft(local);
2279 for (i=0; i<nd; i++) {
2281 dvol = dnode->GetVolume();
2282 if (dvol->FindMatrixOfDaughterVolume(vol))
return kTRUE;
2290 void TGeoVolume::VisibleDaughters(Bool_t vis)
2292 SetVisDaughters(vis);
2293 if (fGeoManager->IsClosed()) SetVisTouched(kTRUE);
2294 fGeoManager->SetVisOption(4);
2300 void TGeoVolume::Voxelize(Option_t *option)
2303 Error(
"Voxelize",
"Bounding box not valid");
2307 if (fFinder)
return;
2309 Int_t nd = GetNdaughters();
2312 if (IsAssembly()) fShape->ComputeBBox();
2315 if (!TObject::TestBit(kVolumeClone))
delete fVoxels;
2319 fVoxels =
new TGeoVoxelFinder(
this);
2320 fVoxels->Voxelize(option);
2322 if (fVoxels->IsInvalid()) {
2333 Double_t TGeoVolume::Weight(Double_t precision, Option_t *option)
2335 TGeoVolume *top = fGeoManager->GetTopVolume();
2336 if (top !=
this) fGeoManager->SetTopVolume(
this);
2338 Double_t weight = fGeoManager->Weight(precision, option);
2339 if (top) fGeoManager->SetTopVolume(top);
2346 Double_t TGeoVolume::WeightA()
const
2348 Double_t capacity = Capacity();
2349 Double_t weight = 0.0;
2351 Int_t nd = GetNdaughters();
2352 TGeoVolume *daughter;
2353 for (i=0; i<nd; i++) {
2354 daughter = GetNode(i)->GetVolume();
2355 weight += daughter->WeightA();
2356 capacity -= daughter->Capacity();
2358 Double_t density = 0.0;
2359 if (!IsAssembly()) {
2360 if (fMedium) density = fMedium->GetMaterial()->GetDensity();
2361 if (density<0.01) density = 0.0;
2363 weight += 0.001*capacity * density;
2367 ClassImp(TGeoVolumeMulti);
2373 TGeoVolumeMulti::TGeoVolumeMulti()
2383 TObject::SetBit(kVolumeMulti);
2389 TGeoVolumeMulti::TGeoVolumeMulti(
const char *name, TGeoMedium *med)
2391 fVolumes =
new TObjArray();
2399 TObject::SetBit(kVolumeMulti);
2402 fGeoManager->AddVolume(
this);
2409 TGeoVolumeMulti::~TGeoVolumeMulti()
2411 if (fVolumes)
delete fVolumes;
2418 void TGeoVolumeMulti::AddVolume(TGeoVolume *vol)
2420 Int_t idx = fVolumes->GetEntriesFast();
2421 fVolumes->AddAtAndExpand(vol,idx);
2422 vol->SetUniqueID(idx+1);
2423 TGeoVolumeMulti *div;
2426 div = (TGeoVolumeMulti*)vol->Divide(fDivision->GetName(), fAxis, fNdiv, fStart, fStep, fNumed, fOption.Data());
2428 Fatal(
"AddVolume",
"Cannot divide volume %s", vol->GetName());
2431 for (Int_t i=0; i<div->GetNvolumes(); i++) {
2432 cell = div->GetVolume(i);
2433 fDivision->AddVolume(cell);
2437 Int_t nd = fNodes->GetEntriesFast();
2438 for (Int_t
id=0;
id<nd;
id++) {
2439 TGeoNode *node = (TGeoNode*)fNodes->At(
id);
2440 Bool_t many = node->IsOverlapping();
2441 if (many) vol->AddNodeOverlap(node->GetVolume(), node->GetNumber(), node->GetMatrix());
2442 else vol->AddNode(node->GetVolume(), node->GetNumber(), node->GetMatrix());
2453 void TGeoVolumeMulti::AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
2455 TGeoVolume::AddNode(vol, copy_no, mat, option);
2456 Int_t nvolumes = fVolumes->GetEntriesFast();
2457 TGeoVolume *volume = 0;
2458 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2459 volume = GetVolume(ivo);
2460 volume->SetLineColor(GetLineColor());
2461 volume->SetLineStyle(GetLineStyle());
2462 volume->SetLineWidth(GetLineWidth());
2463 volume->SetVisibility(IsVisible());
2464 volume->AddNode(vol, copy_no, mat, option);
2473 void TGeoVolumeMulti::AddNodeOverlap(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
2475 TGeoVolume::AddNodeOverlap(vol, copy_no, mat, option);
2476 Int_t nvolumes = fVolumes->GetEntriesFast();
2477 TGeoVolume *volume = 0;
2478 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2479 volume = GetVolume(ivo);
2480 volume->SetLineColor(GetLineColor());
2481 volume->SetLineStyle(GetLineStyle());
2482 volume->SetLineWidth(GetLineWidth());
2483 volume->SetVisibility(IsVisible());
2484 volume->AddNodeOverlap(vol, copy_no, mat, option);
2492 TGeoShape *TGeoVolumeMulti::GetLastShape()
const
2494 TGeoVolume *vol = GetVolume(fVolumes->GetEntriesFast()-1);
2496 return vol->GetShape();
2502 TGeoVolume *TGeoVolumeMulti::Divide(
const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed,
const char *option)
2505 Error(
"Divide",
"volume %s already divided", GetName());
2508 Int_t nvolumes = fVolumes->GetEntriesFast();
2509 TGeoMedium *medium = fMedium;
2511 medium = fGeoManager->GetMedium(numed);
2513 Error(
"Divide",
"Invalid medium number %d for division volume %s", numed, divname);
2519 fDivision =
new TGeoVolumeMulti(divname, medium);
2520 fNumed = medium->GetId();
2529 TGeoVolume *vol = 0;
2530 fDivision =
new TGeoVolumeMulti(divname, medium);
2531 if (medium) fNumed = medium->GetId();
2537 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2538 vol = GetVolume(ivo);
2539 vol->SetLineColor(GetLineColor());
2540 vol->SetLineStyle(GetLineStyle());
2541 vol->SetLineWidth(GetLineWidth());
2542 vol->SetVisibility(IsVisible());
2543 fDivision->AddVolume(vol->Divide(divname,iaxis,ndiv,start,step, numed, option));
2546 if (numed) fDivision->SetMedium(medium);
2554 TGeoVolume *TGeoVolumeMulti::MakeCopyVolume(TGeoShape *newshape)
2556 TGeoVolume *vol =
new TGeoVolume(GetName(), newshape, fMedium);
2559 vol->SetVisibility(IsVisible());
2560 vol->SetLineColor(GetLineColor());
2561 vol->SetLineStyle(GetLineStyle());
2562 vol->SetLineWidth(GetLineWidth());
2563 vol->SetFillColor(GetFillColor());
2564 vol->SetFillStyle(GetFillStyle());
2566 vol->SetField(fField);
2568 vol->SetUserExtension(fUserExtension);
2569 vol->SetFWExtension(fFWExtension);
2577 TGeoVolumeMulti *div = (TGeoVolumeMulti*)vol->Divide(fDivision->GetName(), fAxis, fNdiv, fStart, fStep, fNumed, fOption.Data());
2579 Fatal(
"MakeCopyVolume",
"Cannot divide volume %s", vol->GetName());
2582 for (i=0; i<div->GetNvolumes(); i++) {
2583 cell = div->GetVolume(i);
2584 fDivision->AddVolume(cell);
2588 if (!fNodes)
return vol;
2590 Int_t nd = fNodes->GetEntriesFast();
2591 if (!nd)
return vol;
2593 TObjArray *list =
new TObjArray();
2595 vol->SetNodes(list);
2596 ((TObject*)vol)->SetBit(kVolumeImportNodes);
2597 for (i=0; i<nd; i++) {
2599 node = GetNode(i)->MakeCopyNode();
2601 Fatal(
"MakeCopyNode",
"cannot make copy node for daughter %d of %s", i, GetName());
2604 node->SetMotherVolume(vol);
2613 void TGeoVolumeMulti::SetLineColor(Color_t lcolor)
2615 TGeoVolume::SetLineColor(lcolor);
2616 Int_t nvolumes = fVolumes->GetEntriesFast();
2617 TGeoVolume *vol = 0;
2618 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2619 vol = GetVolume(ivo);
2620 vol->SetLineColor(lcolor);
2627 void TGeoVolumeMulti::SetLineStyle(Style_t lstyle)
2629 TGeoVolume::SetLineStyle(lstyle);
2630 Int_t nvolumes = fVolumes->GetEntriesFast();
2631 TGeoVolume *vol = 0;
2632 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2633 vol = GetVolume(ivo);
2634 vol->SetLineStyle(lstyle);
2641 void TGeoVolumeMulti::SetLineWidth(Width_t lwidth)
2643 TGeoVolume::SetLineWidth(lwidth);
2644 Int_t nvolumes = fVolumes->GetEntriesFast();
2645 TGeoVolume *vol = 0;
2646 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2647 vol = GetVolume(ivo);
2648 vol->SetLineWidth(lwidth);
2655 void TGeoVolumeMulti::SetMedium(TGeoMedium *med)
2657 TGeoVolume::SetMedium(med);
2658 Int_t nvolumes = fVolumes->GetEntriesFast();
2659 TGeoVolume *vol = 0;
2660 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2661 vol = GetVolume(ivo);
2662 vol->SetMedium(med);
2670 void TGeoVolumeMulti::SetVisibility(Bool_t vis)
2672 TGeoVolume::SetVisibility(vis);
2673 Int_t nvolumes = fVolumes->GetEntriesFast();
2674 TGeoVolume *vol = 0;
2675 for (Int_t ivo=0; ivo<nvolumes; ivo++) {
2676 vol = GetVolume(ivo);
2677 vol->SetVisibility(vis);
2681 ClassImp(TGeoVolumeAssembly);
2686 TGeoVolumeAssembly::ThreadData_t::ThreadData_t() :
2687 fCurrent(-1), fNext(-1)
2694 TGeoVolumeAssembly::ThreadData_t::~ThreadData_t()
2700 TGeoVolumeAssembly::ThreadData_t& TGeoVolumeAssembly::GetThreadData()
const
2702 Int_t tid = TGeoManager::ThreadId();
2703 return *fThreadData[tid];
2708 void TGeoVolumeAssembly::ClearThreadData()
const
2710 std::lock_guard<std::mutex> guard(fMutex);
2711 TGeoVolume::ClearThreadData();
2712 std::vector<ThreadData_t*>::iterator i = fThreadData.begin();
2713 while (i != fThreadData.end())
2718 fThreadData.clear();
2724 void TGeoVolumeAssembly::CreateThreadData(Int_t nthreads)
2726 std::lock_guard<std::mutex> guard(fMutex);
2728 fThreadData.resize(nthreads);
2729 fThreadSize = nthreads;
2730 for (Int_t tid=0; tid<nthreads; tid++) {
2731 if (fThreadData[tid] == 0) {
2732 fThreadData[tid] =
new ThreadData_t;
2735 TGeoVolume::CreateThreadData(nthreads);
2740 Int_t TGeoVolumeAssembly::GetCurrentNodeIndex()
const
2742 return fThreadData[TGeoManager::ThreadId()]->fCurrent;
2747 Int_t TGeoVolumeAssembly::GetNextNodeIndex()
const
2749 return fThreadData[TGeoManager::ThreadId()]->fNext;
2754 void TGeoVolumeAssembly::SetCurrentNodeIndex(Int_t index)
2756 fThreadData[TGeoManager::ThreadId()]->fCurrent = index;
2761 void TGeoVolumeAssembly::SetNextNodeIndex(Int_t index)
2763 fThreadData[TGeoManager::ThreadId()]->fNext = index;
2769 TGeoVolumeAssembly::TGeoVolumeAssembly()
2773 CreateThreadData(1);
2780 TGeoVolumeAssembly::TGeoVolumeAssembly(
const char *name)
2784 fName = fName.Strip();
2785 fShape =
new TGeoShapeAssembly(
this);
2786 if (fGeoManager) fNumber = fGeoManager->AddVolume(
this);
2788 CreateThreadData(1);
2794 TGeoVolumeAssembly::~TGeoVolumeAssembly()
2797 if (fShape)
delete fShape;
2803 void TGeoVolumeAssembly::AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
2805 TGeoVolume::AddNode(vol,copy_no,mat,option);
2807 ((TGeoShapeAssembly*)fShape)->NeedsBBoxRecompute();
2813 void TGeoVolumeAssembly::AddNodeOverlap(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
2815 Warning(
"AddNodeOverlap",
"Declaring assembly %s as possibly overlapping inside %s not allowed. Using AddNode instead !",vol->GetName(),GetName());
2816 AddNode(vol, copy_no, mat, option);
2823 TGeoVolume *TGeoVolumeAssembly::CloneVolume()
const
2825 TGeoVolume *vol =
new TGeoVolumeAssembly(GetName());
2828 Int_t nbits = 8*
sizeof(UInt_t);
2829 for (i=0; i<nbits; i++)
2830 vol->SetAttBit(1<<i, TGeoAtt::TestAttBit(1<<i));
2831 for (i=14; i<24; i++)
2832 vol->SetBit(1<<i, TestBit(1<<i));
2835 vol->SetField(fField);
2837 for (i=0; i<nbits; i++)
2838 vol->SetBit(1<<i, TObject::TestBit(1<<i));
2839 vol->SetBit(kVolumeClone);
2841 vol->MakeCopyNodes(
this);
2843 ((TGeoShapeAssembly*)vol->GetShape())->NeedsBBoxRecompute();
2845 TGeoVoxelFinder *voxels = 0;
2847 voxels =
new TGeoVoxelFinder(vol);
2848 vol->SetVoxelFinder(voxels);
2851 vol->SetOption(fOption);
2852 vol->SetNumber(fNumber);
2853 vol->SetNtotal(fNtotal);
2860 TGeoVolume *TGeoVolumeAssembly::Divide(
const char *, Int_t, Int_t, Double_t, Double_t, Int_t, Option_t *)
2862 Error(
"Divide",
"Assemblies cannot be divided");
2871 TGeoVolume *TGeoVolumeAssembly::Divide(TGeoVolume *cell, TGeoPatternFinder *pattern, Option_t *option)
2874 Error(
"Divide",
"Cannot divide assembly %s since it has nodes", GetName());
2878 Error(
"Divide",
"Assembly %s already divided", GetName());
2881 Int_t ncells = pattern->GetNdiv();
2882 if (!ncells || pattern->GetStep()<=0) {
2883 Error(
"Divide",
"Pattern finder for dividing assembly %s not initialized. Use SetRange() method.", GetName());
2887 TString opt(option);
2889 if (opt.Contains(
"spacedout")) fFinder->SetSpacedOut(kTRUE);
2890 else fFinder->SetSpacedOut(kFALSE);
2892 for (Int_t i=0; i<ncells; i++) {
2894 TGeoNodeOffset *node =
new TGeoNodeOffset(cell, i, 0.);
2895 node->SetFinder(fFinder);
2904 TGeoVolumeAssembly *TGeoVolumeAssembly::MakeAssemblyFromVolume(TGeoVolume *volorig)
2906 if (volorig->IsAssembly() || volorig->IsVolumeMulti())
return 0;
2907 Int_t nd = volorig->GetNdaughters();
2909 TGeoVolumeAssembly *vol =
new TGeoVolumeAssembly(volorig->GetName());
2912 Int_t nbits = 8*
sizeof(UInt_t);
2913 for (i=0; i<nbits; i++)
2914 vol->SetAttBit(1<<i, volorig->TestAttBit(1<<i));
2915 for (i=14; i<24; i++)
2916 vol->SetBit(1<<i, volorig->TestBit(1<<i));
2919 vol->SetField(volorig->GetField());
2921 for (i=0; i<nbits; i++)
2922 vol->SetBit(1<<i, volorig->TestBit(1<<i));
2923 vol->SetBit(kVolumeClone);
2925 vol->MakeCopyNodes(volorig);
2927 vol->GetShape()->ComputeBBox();
2929 TGeoVoxelFinder *voxels = 0;
2930 if (volorig->GetVoxels()) {
2931 voxels =
new TGeoVoxelFinder(vol);
2932 vol->SetVoxelFinder(voxels);
2935 vol->SetOption(volorig->GetOption());
2936 vol->SetNumber(volorig->GetNumber());
2937 vol->SetNtotal(volorig->GetNtotal());