/*
<img src="gif/t_volume.jpg">
*/
//End_Html
/*
<img src="gif/t_example.jpg">
*/
//End_Html
#include "Riostream.h"
#include "TString.h"
#include "TBrowser.h"
#include "TStyle.h"
#include "TH2F.h"
#include "TPad.h"
#include "TROOT.h"
#include "TClass.h"
#include "TEnv.h"
#include "TMap.h"
#include "TFile.h"
#include "TKey.h"
#include "TGeoManager.h"
#include "TGeoNode.h"
#include "TGeoMatrix.h"
#include "TVirtualGeoPainter.h"
#include "TGeoVolume.h"
#include "TGeoShapeAssembly.h"
#include "TGeoScaledShape.h"
#include "TGeoCompositeShape.h"
#include "TGeoVoxelFinder.h"
ClassImp(TGeoVolume)
TGeoVolume::TGeoVolume()
{
fNodes = 0;
fShape = 0;
fFinder = 0;
fVoxels = 0;
fField = 0;
fMedium = 0;
fNumber = 0;
fNtotal = 0;
fOption = "";
fGeoManager = gGeoManager;
TObject::ResetBit(kVolumeImportNodes);
}
TGeoVolume::TGeoVolume(const char *name, const TGeoShape *shape, const TGeoMedium *med)
:TNamed(name, "")
{
fName = fName.Strip();
fNodes = 0;
fShape = (TGeoShape*)shape;
if (fShape) {
if (fShape->TestShapeBit(TGeoShape::kGeoBad)) {
Warning("Ctor", "volume %s has invalid shape", name);
}
if (!fShape->IsValid()) {
Fatal("ctor", "Shape of volume %s invalid. Aborting!", fName.Data());
}
}
fFinder = 0;
fVoxels = 0;
fField = 0;
fOption = "";
fMedium = (TGeoMedium*)med;
if (fMedium) {
if (fMedium->GetMaterial()) fMedium->GetMaterial()->SetUsed();
}
fNumber = 0;
fNtotal = 0;
fGeoManager = gGeoManager;
if (fGeoManager) fNumber = fGeoManager->AddVolume(this);
TObject::ResetBit(kVolumeImportNodes);
}
TGeoVolume::TGeoVolume(const TGeoVolume& gv) :
TNamed(gv),
TGeoAtt(gv),
TAttLine(gv),
TAttFill(gv),
TAtt3D(gv),
fNodes(gv.fNodes),
fShape(gv.fShape),
fMedium(gv.fMedium),
fFinder(gv.fFinder),
fVoxels(gv.fVoxels),
fGeoManager(gv.fGeoManager),
fField(gv.fField),
fOption(gv.fOption),
fNumber(gv.fNumber),
fNtotal(gv.fNtotal)
{
}
TGeoVolume& TGeoVolume::operator=(const TGeoVolume& gv)
{
if(this!=&gv) {
TNamed::operator=(gv);
TGeoAtt::operator=(gv);
TAttLine::operator=(gv);
TAttFill::operator=(gv);
TAtt3D::operator=(gv);
fNodes=gv.fNodes;
fShape=gv.fShape;
fMedium=gv.fMedium;
fFinder=gv.fFinder;
fVoxels=gv.fVoxels;
fGeoManager=gv.fGeoManager;
fField=gv.fField;
fOption=gv.fOption;
fNumber=gv.fNumber;
fNtotal=gv.fNtotal;
}
return *this;
}
TGeoVolume::~TGeoVolume()
{
if (fNodes) {
if (!TObject::TestBit(kVolumeImportNodes)) {
fNodes->Delete();
}
delete fNodes;
}
if (fFinder && !TObject::TestBit(kVolumeImportNodes | kVolumeClone) ) delete fFinder;
if (fVoxels) delete fVoxels;
}
void TGeoVolume::Browse(TBrowser *b)
{
if (!b) return;
TGeoVolume *daughter;
TString title;
for (Int_t i=0; i<GetNdaughters(); i++) {
daughter = GetNode(i)->GetVolume();
if(!strlen(daughter->GetTitle())) {
if (daughter->IsAssembly()) title.Form("Assembly with %d daughter(s)",
daughter->GetNdaughters());
else if (daughter->GetFinder()) {
TString s1 = daughter->GetFinder()->ClassName();
s1.ReplaceAll("TGeoPattern","");
title.Form("Volume having %s shape divided in %d %s slices",
daughter->GetShape()->ClassName(),daughter->GetNdaughters(), s1.Data());
} else title.Form("Volume with %s shape having %d daughter(s)",
daughter->GetShape()->ClassName(),daughter->GetNdaughters());
daughter->SetTitle(title.Data());
}
b->Add(daughter, daughter->GetName(), daughter->IsVisible());
}
}
Double_t TGeoVolume::Capacity() const
{
if (!IsAssembly()) return fShape->Capacity();
Double_t capacity = 0.0;
Int_t nd = GetNdaughters();
Int_t i;
for (i=0; i<nd; i++) capacity += GetNode(i)->GetVolume()->Capacity();
return capacity;
}
void TGeoVolume::CheckGeometry(Int_t nrays, Double_t startx, Double_t starty, Double_t startz) const
{
TGeoVolume *old_vol = fGeoManager->GetTopVolume();
if (old_vol!=this) fGeoManager->SetTopVolume((TGeoVolume*)this);
else old_vol=0;
fGeoManager->GetTopVolume()->Draw();
TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
painter->CheckGeometry(nrays, startx, starty, startz);
}
void TGeoVolume::CheckOverlaps(Double_t ovlp, Option_t *option) const
{
if (!GetNdaughters() || fFinder) return;
Bool_t sampling = kFALSE;
TString opt(option);
opt.ToLower();
if (opt.Contains("s")) sampling = kTRUE;
TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
if (!sampling) fGeoManager->SetNsegments(80);
if (!fGeoManager->IsCheckingOverlaps()) {
fGeoManager->ClearOverlaps();
}
painter->CheckOverlaps(this, ovlp, option);
if (!fGeoManager->IsCheckingOverlaps()) {
fGeoManager->SortOverlaps();
TObjArray *overlaps = fGeoManager->GetListOfOverlaps();
Int_t novlps = overlaps->GetEntriesFast();
TNamed *obj;
char name[15];
char num[15];
Int_t ndigits=1;
Int_t i,j, result=novlps;
while ((result /= 10)) ndigits++;
for (i=0; i<novlps; i++) {
obj = (TNamed*)overlaps->At(i);
result = i;
name[0] = 'o';
name[1] = 'v';
for (j=0; j<ndigits; j++) name[j+2]='0';
name[ndigits+2] = 0;
sprintf(num,"%i", i);
memcpy(name+2+ndigits-strlen(num), num, strlen(num));
obj->SetName(name);
}
if (novlps) Info("CheckOverlaps", "Number of illegal overlaps/extrusions for volume %s: %d\n", GetName(), novlps);
}
}
void TGeoVolume::CleanAll()
{
ClearNodes();
ClearShape();
}
void TGeoVolume::ClearShape()
{
fGeoManager->ClearShape(fShape);
}
void TGeoVolume::CheckShapes()
{
if (fShape->IsRunTimeShape()) {
Error("CheckShapes", "volume %s has run-time shape", GetName());
InspectShape();
return;
}
if (!fNodes) return;
Int_t nd=fNodes->GetEntriesFast();
TGeoNode *node = 0;
TGeoNode *new_node;
const TGeoShape *shape = 0;
TGeoVolume *old_vol;
for (Int_t i=0; i<nd; i++) {
node=(TGeoNode*)fNodes->At(i);
if (!strlen(node->GetName())) printf("Daughter %i of volume %s - NO NAME!!!\n",
i, GetName());
old_vol = node->GetVolume();
shape = old_vol->GetShape();
if (shape->IsRunTimeShape()) {
new_node = node->MakeCopyNode();
TGeoShape *new_shape = shape->GetMakeRuntimeShape(fShape, node->GetMatrix());
if (!new_shape) {
Error("CheckShapes","cannot resolve runtime shape for volume %s/%s\n",
GetName(),old_vol->GetName());
continue;
}
TGeoVolume *new_volume = old_vol->MakeCopyVolume(new_shape);
new_node->SetVolume(new_volume);
fNodes->AddAt(new_node, i);
}
}
}
Int_t TGeoVolume::CountNodes(Int_t nlevels, Int_t option)
{
static Int_t maxlevel = 0;
static Int_t nlev = 0;
if (option<0 || option>3) option = 0;
Int_t visopt = 0;
Int_t nd = GetNdaughters();
Bool_t last = (!nlevels || !nd)?kTRUE:kFALSE;
switch (option) {
case 0:
if (fNtotal) return fNtotal;
case 1:
fNtotal = 1;
break;
case 2:
visopt = fGeoManager->GetVisOption();
if (!IsVisDaughters()) last = kTRUE;
switch (visopt) {
case TVirtualGeoPainter::kGeoVisDefault:
fNtotal = (IsVisible())?1:0;
break;
case TVirtualGeoPainter::kGeoVisLeaves:
fNtotal = (IsVisible() && last)?1:0;
}
if (!IsVisibleDaughters()) return fNtotal;
break;
case 3:
return maxlevel;
}
if (last) return fNtotal;
if (gGeoManager->GetTopVolume() == this) {
maxlevel=0;
nlev = 0;
}
if (nlev>maxlevel) maxlevel = nlev;
TGeoNode *node;
TGeoVolume *vol;
nlev++;
for (Int_t i=0; i<nd; i++) {
node = GetNode(i);
vol = node->GetVolume();
fNtotal += vol->CountNodes(nlevels-1, option);
}
nlev--;
return fNtotal;
}
Bool_t TGeoVolume::IsAllInvisible() const
{
if (IsVisible()) return kFALSE;
Int_t nd = GetNdaughters();
for (Int_t i=0; i<nd; i++) if (GetNode(i)->GetVolume()->IsVisible()) return kFALSE;
return kTRUE;
}
void TGeoVolume::InvisibleAll(Bool_t flag)
{
SetAttVisibility(!flag);
Int_t nd = GetNdaughters();
TObjArray *list = new TObjArray(nd+1);
list->Add(this);
TGeoVolume *vol;
for (Int_t i=0; i<nd; i++) {
vol = GetNode(i)->GetVolume();
vol->SetAttVisibility(!flag);
list->Add(vol);
}
TIter next(gROOT->GetListOfBrowsers());
TBrowser *browser = 0;
while ((browser=(TBrowser*)next())) {
for (Int_t i=0; i<nd+1; i++) {
vol = (TGeoVolume*)list->At(i);
browser->CheckObjectItem(vol, !flag);
}
browser->Refresh();
}
delete list;
fGeoManager->SetVisOption(4);
}
Bool_t TGeoVolume::IsFolder() const
{
return kTRUE;
}
Bool_t TGeoVolume::IsStyleDefault() const
{
if (!IsVisible()) return kFALSE;
if (GetLineColor() != gStyle->GetLineColor()) return kFALSE;
if (GetLineStyle() != gStyle->GetLineStyle()) return kFALSE;
if (GetLineWidth() != gStyle->GetLineWidth()) return kFALSE;
return kTRUE;
}
Bool_t TGeoVolume::IsTopVolume() const
{
if (fGeoManager->GetTopVolume() == this) return kTRUE;
return kFALSE;
}
Bool_t TGeoVolume::IsRaytracing() const
{
return TGeoAtt::IsVisRaytrace();
}
void TGeoVolume::InspectMaterial() const
{
fMedium->GetMaterial()->Print();
}
TGeoVolume *TGeoVolume::Import(const char *filename, const char *name, Option_t * )
{
if (!gGeoManager) gGeoManager = new TGeoManager("geometry","");
if (!filename) return 0;
TGeoVolume *volume = 0;
if (strstr(filename,".gdml")) {
} else {
TFile *old = gFile;
TFile *f = TFile::Open(filename);
if (!f || f->IsZombie()) {
if (old) old->cd();
printf("Error: TGeoVolume::Import : Cannot open file %s\n", filename);
return 0;
}
if (name && strlen(name) > 0) {
volume = (TGeoVolume*)f->Get(name);
} else {
TIter next(f->GetListOfKeys());
TKey *key;
while ((key = (TKey*)next())) {
if (strcmp(key->GetClassName(),"TGeoVolume") != 0) continue;
volume = (TGeoVolume*)key->ReadObj();
break;
}
}
if (old) old->cd();
delete f;
}
if (!volume) return NULL;
volume->RegisterYourself();
return volume;
}
Int_t TGeoVolume::Export(const char *filename, const char *name, Option_t *option)
{
TString sfile(filename);
if (sfile.Contains(".C")) {
Info("Export","Exporting volume %s as C++ code", GetName());
SaveAs(filename, "");
return 1;
}
if (sfile.Contains(".gdml")) {
Info("Export","Exporting %s as gdml code - not implemented yet", GetName());
return 0;
}
if (sfile.Contains(".root") || sfile.Contains(".xml")) {
Info("Export","Exporting %s as root file.", GetName());
TString opt(option);
if (!opt.Length()) opt = "recreate";
TFile *f = TFile::Open(filename,opt.Data());
if (!f || f->IsZombie()) {
Error("Export","Cannot open file");
return 0;
}
char keyname[256];
if (name) strcpy(keyname,name);
if (strlen(keyname) == 0) strcpy(keyname,GetName());
Int_t nbytes = Write(keyname);
delete f;
return nbytes;
}
return 0;
}
void TGeoVolume::cd(Int_t inode) const
{
if (fFinder) fFinder->cd(inode-fFinder->GetDivIndex());
}
void TGeoVolume::AddNode(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t * )
{
TGeoMatrix *matrix = mat;
if (matrix==0) matrix = gGeoIdentity;
else matrix->RegisterYourself();
if (!vol) {
Error("AddNode", "Volume is NULL");
return;
}
if (!vol->IsValid()) {
Error("AddNode", "Won't add node with invalid shape");
printf("### invalid volume was : %s\n", vol->GetName());
return;
}
if (!fNodes) fNodes = new TObjArray();
if (fFinder) {
Error("AddNode", "Cannot add node %s_%i into divided volume %s", vol->GetName(), copy_no, GetName());
return;
}
TGeoNodeMatrix *node = 0;
char *name = 0;
node = new TGeoNodeMatrix(vol, matrix);
node->SetMotherVolume(this);
fNodes->Add(node);
name = new char[strlen(vol->GetName())+15];
sprintf(name, "%s_%i", vol->GetName(), copy_no);
if (fNodes->FindObject(name))
Warning("AddNode", "Volume %s : added node %s with same name", GetName(), name);
node->SetName(name);
delete [] name;
node->SetNumber(copy_no);
}
void TGeoVolume::AddNodeOffset(const TGeoVolume *vol, Int_t copy_no, Double_t offset, Option_t * )
{
if (!vol) {
Error("AddNodeOffset", "invalid volume");
return;
}
if (!vol->IsValid()) {
Error("AddNode", "Won't add node with invalid shape");
printf("### invalid volume was : %s\n", vol->GetName());
return;
}
if (!fNodes) fNodes = new TObjArray();
TGeoNode *node = new TGeoNodeOffset(vol, copy_no, offset);
node->SetMotherVolume(this);
fNodes->Add(node);
char *name = new char[strlen(vol->GetName())+15];
sprintf(name, "%s_%i", vol->GetName(), copy_no+1);
node->SetName(name);
delete [] name;
node->SetNumber(copy_no+1);
}
void TGeoVolume::AddNodeOverlap(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
{
if (vol->IsAssembly()) {
Warning("AddNodeOverlap", "Declaring assembly %s as possibly overlapping inside %s not allowed. Using AddNode instead !",vol->GetName(),GetName());
AddNode(vol, copy_no, mat, option);
return;
}
TGeoMatrix *matrix = mat;
if (matrix==0) matrix = gGeoIdentity;
else matrix->RegisterYourself();
if (!vol) {
Error("AddNodeOverlap", "Volume is NULL");
return;
}
if (!vol->IsValid()) {
Error("AddNodeOverlap", "Won't add node with invalid shape");
printf("### invalid volume was : %s\n", vol->GetName());
return;
}
if (!fNodes) fNodes = new TObjArray();
if (fFinder) {
Error("AddNodeOverlap", "Cannot add node %s_%i into divided volume %s", vol->GetName(), copy_no, GetName());
return;
}
TGeoNodeMatrix *node = 0;
char *name = 0;
node = new TGeoNodeMatrix(vol, matrix);
node->SetMotherVolume(this);
fNodes->Add(node);
name = new char[strlen(vol->GetName())+15];
sprintf(name, "%s_%i", vol->GetName(), copy_no);
if (fNodes->FindObject(name))
Warning("AddNode", "Volume %s : added node %s with same name", GetName(), name);
node->SetName(name);
delete [] name;
node->SetNumber(copy_no);
node->SetOverlapping();
if (vol->GetMedium() == fMedium)
node->SetVirtual();
}
TGeoVolume *TGeoVolume::Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed, Option_t *option)
{
if (fFinder) {
Fatal("Divide","volume %s already divided", GetName());
return 0;
}
TString opt(option);
opt.ToLower();
TString stype = fShape->ClassName();
if (!fNodes) fNodes = new TObjArray();
Double_t xlo, xhi, range;
range = fShape->GetAxisRange(iaxis, xlo, xhi);
if (!strcmp(fShape->GetAxisName(iaxis), "PHI")) {
if ((start-xlo)<-1E-3) start+=360.;
if (range==360) {
xlo = start;
xhi = start+range;
}
}
if (range <=0) {
InspectShape();
Fatal("Divide", "cannot divide volume %s (%s) on %s axis", GetName(), stype.Data(), fShape->GetAxisName(iaxis));
return 0;
}
if (ndiv<=0 || opt.Contains("s")) {
if (step<=0) {
Fatal("Divide", "invalid division type for volume %s : ndiv=%i, step=%g", GetName(), ndiv, step);
return 0;
}
if (opt.Contains("x")) {
if ((xlo-start)>1E-3 || (xhi-start)<-1E-3) {
Fatal("Divide", "invalid START=%g for division on axis %s of volume %s. Range is (%g, %g)",
start, fShape->GetAxisName(iaxis), GetName(), xlo, xhi);
return 0;
}
xlo = start;
range = xhi-xlo;
}
ndiv = Int_t((range+0.1*step)/step);
Double_t ddx = range - ndiv*step;
if (ddx>1E-3) Warning("Divide", "division of volume %s on %s axis (ndiv=%d) will be centered in the full range",
GetName(), fShape->GetAxisName(iaxis), ndiv);
start = xlo + 0.5*ddx;
}
if (step<=0 || opt.Contains("n")) {
if (opt.Contains("x")) {
if ((xlo-start)>1E-3 || (xhi-start)<-1E-3) {
Fatal("Divide", "invalid START=%g for division on axis %s of volume %s. Range is (%g, %g)",
start, fShape->GetAxisName(iaxis), GetName(), xlo, xhi);
return 0;
}
xlo = start;
range = xhi-xlo;
}
step = range/ndiv;
start = xlo;
}
Double_t end = start+ndiv*step;
if (((start-xlo)<-1E-3) || ((end-xhi)>1E-3)) {
Fatal("Divide", "division of volume %s on axis %s exceed range (%g, %g)",
GetName(), fShape->GetAxisName(iaxis), xlo, xhi);
return 0;
}
TGeoVolume *voldiv = fShape->Divide(this, divname, iaxis, ndiv, start, step);
if (numed) {
TGeoMedium *medium = fGeoManager->GetMedium(numed);
if (!medium) {
Fatal("Divide", "invalid medium number %d for division volume %s", numed, divname);
return voldiv;
}
voldiv->SetMedium(medium);
if (medium->GetMaterial()) medium->GetMaterial()->SetUsed();
}
return voldiv;
}
Int_t TGeoVolume::DistancetoPrimitive(Int_t px, Int_t py)
{
if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
TVirtualGeoPainter *painter = fGeoManager->GetPainter();
Int_t dist = 9999;
if (!painter) return dist;
dist = painter->DistanceToPrimitiveVol(this, px, py);
return dist;
}
void TGeoVolume::Draw(Option_t *option)
{
if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
TGeoAtt::SetVisRaytrace(kFALSE);
if (!IsVisContainers()) SetVisLeaves();
if (option && strlen(option) > 0) {
painter->DrawVolume(this, option);
} else {
painter->DrawVolume(this, gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
}
}
void TGeoVolume::DrawOnly(Option_t *option)
{
if (IsAssembly()) {
Info("DrawOnly", "Volume assemblies do not support this option.");
return;
}
if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
SetVisOnly();
TGeoAtt::SetVisRaytrace(kFALSE);
TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
if (option && strlen(option) > 0) {
painter->DrawVolume(this, option);
} else {
painter->DrawVolume(this, gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
}
}
Bool_t TGeoVolume::OptimizeVoxels()
{
printf("Optimizing volume %s ...\n", GetName());
TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
return painter->TestVoxels(this);
}
void TGeoVolume::Paint(Option_t *option)
{
TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
painter->SetTopVolume(this);
if (option && strlen(option) > 0) {
painter->Paint(option);
} else {
painter->Paint(gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
}
}
void TGeoVolume::PrintVoxels() const
{
if (fVoxels) fVoxels->Print();
}
void TGeoVolume::PrintNodes() const
{
Int_t nd = GetNdaughters();
for (Int_t i=0; i<nd; i++) {
printf("%s\n", GetNode(i)->GetName());
cd(i);
GetNode(i)->GetMatrix()->Print();
}
}
TH2F *TGeoVolume::LegoPlot(Int_t ntheta, Double_t themin, Double_t themax,
Int_t nphi, Double_t phimin, Double_t phimax,
Double_t rmin, Double_t rmax, Option_t *option)
{
TVirtualGeoPainter *p = fGeoManager->GetGeomPainter();
TGeoVolume *old_vol = fGeoManager->GetTopVolume();
if (old_vol!=this) fGeoManager->SetTopVolume(this);
else old_vol=0;
TH2F *hist = p->LegoPlot(ntheta, themin, themax, nphi, phimin, phimax, rmin, rmax, option);
hist->Draw("lego1sph");
return hist;
}
void TGeoVolume::RegisterYourself(Option_t *option)
{
if (fGeoManager->GetListOfVolumes()->FindObject(this)) return;
fGeoManager->AddVolume(this);
if (!fGeoManager->GetListOfShapes()->FindObject(fShape)) {
if (fShape->IsComposite()) {
TGeoCompositeShape *comp = (TGeoCompositeShape*)fShape;
comp->RegisterYourself();
} else {
fGeoManager->AddShape(fShape);
}
}
if (fMedium && !fGeoManager->GetListOfMedia()->FindObject(fMedium)) {
fGeoManager->GetListOfMedia()->Add(fMedium);
if (!fGeoManager->GetListOfMaterials()->FindObject(fMedium->GetMaterial()))
fGeoManager->AddMaterial(fMedium->GetMaterial());
}
TGeoMatrix *matrix;
TGeoNode *node;
Int_t nd = GetNdaughters();
Int_t i;
for (i=0; i<nd; i++) {
node = GetNode(i);
matrix = node->GetMatrix();
if (!matrix->IsRegistered()) matrix->RegisterYourself();
else if (!fGeoManager->GetListOfMatrices()->FindObject(matrix)) {
fGeoManager->GetListOfMatrices()->Add(matrix);
}
}
for (i=0; i<nd; i++) GetNode(i)->GetVolume()->RegisterYourself(option);
}
void TGeoVolume::RandomPoints(Int_t npoints, Option_t *option)
{
if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
TGeoVolume *old_vol = fGeoManager->GetTopVolume();
if (old_vol!=this) fGeoManager->SetTopVolume(this);
else old_vol=0;
fGeoManager->RandomPoints(this, npoints, option);
if (old_vol) fGeoManager->SetTopVolume(old_vol);
}
void TGeoVolume::RandomRays(Int_t nrays, Double_t startx, Double_t starty, Double_t startz)
{
if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
TGeoVolume *old_vol = fGeoManager->GetTopVolume();
if (old_vol!=this) fGeoManager->SetTopVolume(this);
else old_vol=0;
fGeoManager->RandomRays(nrays, startx, starty, startz);
if (old_vol) fGeoManager->SetTopVolume(old_vol);
}
void TGeoVolume::Raytrace(Bool_t flag)
{
TGeoAtt::SetVisRaytrace(kFALSE);
if (gGeoManager != fGeoManager) gGeoManager = fGeoManager;
TVirtualGeoPainter *painter = fGeoManager->GetGeomPainter();
Bool_t drawn = (painter->GetDrawnVolume()==this)?kTRUE:kFALSE;
if (!drawn) {
painter->DrawVolume(this, "");
TGeoAtt::SetVisRaytrace(flag);
painter->ModifiedPad();
return;
}
TGeoAtt::SetVisRaytrace(flag);
painter->ModifiedPad();
}
void TGeoVolume::SaveAs(const char *filename, Option_t *option) const
{
if (!filename) return;
ofstream out;
out.open(filename, ios::out);
if (out.bad()) {
Error("SavePrimitive", "Bad file name: %s", filename);
return;
}
if (fGeoManager->GetTopVolume() != this) fGeoManager->SetTopVolume((TGeoVolume*)this);
char fname[1000];
strcpy(fname,filename);
char *dot = strstr(fname,".");
if (dot) *dot = 0;
out << "void "<<fname<<"() {" << endl;
out << " gSystem->Load(\"libGeom\");" << endl;
((TGeoVolume*)this)->SavePrimitive(out,option);
out << "}" << endl;
}
void TGeoVolume::SavePrimitive(ostream &out, Option_t *option )
{
out.precision(6);
out.setf(ios::fixed);
Int_t i,icopy;
Int_t nd = GetNdaughters();
TGeoVolume *dvol;
TGeoNode *dnode;
TGeoMatrix *matrix;
Bool_t mustDraw = kFALSE;
if (fGeoManager->GetGeomPainter()->GetTopVolume()==this) mustDraw = kTRUE;
if (!strlen(option)) {
fGeoManager->SetAllIndex();
out << " new TGeoManager(\"" << fGeoManager->GetName() << "\", \"" << fGeoManager->GetTitle() << "\");" << endl << endl;
out << " Double_t dx,dy,dz;" << endl;
out << " Double_t dx1, dx2, dy1, dy2;" << endl;
out << " Double_t vert[20], par[20];" << endl;
out << " Double_t theta, phi, h1, bl1, tl1, alpha1, h2, bl2, tl2, alpha2;" << endl;
out << " Double_t twist;" << endl;
out << " Double_t origin[3];" << endl;
out << " Double_t rmin, rmax, rmin1, rmax1, rmin2, rmax2;" << endl;
out << " Double_t r, rlo, rhi;" << endl;
out << " Double_t phi1, phi2;" << endl;
out << " Double_t a,b;" << endl;
out << " Double_t point[3], norm[3];" << endl;
out << " Double_t rin, stin, rout, stout;" << endl;
out << " Double_t thx, phx, thy, phy, thz, phz;" << endl;
out << " Double_t alpha, theta1, theta2, phi1, phi2, dphi;" << endl;
out << " Double_t tr[3], rot[9];" << endl;
out << " Double_t z, density, radl, absl, w;" << endl;
out << " Double_t lx,ly,lz,tx,ty,tz;" << endl;
out << " Double_t xvert[50], yvert[50];" << endl;
out << " Double_t zsect,x0,y0,scale0;" << endl;
out << " Int_t nel, numed, nz, nedges, nvert;" << endl;
out << " TGeoBoolNode *pBoolNode = 0;" << endl << endl;
out << " // MATERIALS, MIXTURES AND TRACKING MEDIA" << endl;
SavePrimitive(out, "m");
out << endl << " // TRANSFORMATION MATRICES" << endl;
SavePrimitive(out, "x");
SavePrimitive(out, "s");
out << endl << " // SET TOP VOLUME OF GEOMETRY" << endl;
out << " gGeoManager->SetTopVolume(" << GetPointerName() << ");" << endl;
out << endl << " // SHAPES, VOLUMES AND GEOMETRICAL HIERARCHY" << endl;
SavePrimitive(out, "d");
out << endl << " // CLOSE GEOMETRY" << endl;
out << " gGeoManager->CloseGeometry();" << endl;
if (mustDraw) {
if (!IsRaytracing()) out << " gGeoManager->GetTopVolume()->Draw();" << endl;
else out << " gGeoManager->GetTopVolume()->Raytrace();" << endl;
}
return;
}
if (!strcmp(option, "s")) {
if (TestAttBit(TGeoAtt::kSavePrimitiveAtt)) return;
if (!IsAssembly()) {
fShape->SavePrimitive(out,option);
out << " // Volume: " << GetName() << endl;
out << " " << GetPointerName() << " = new TGeoVolume(\"" << GetName() << "\"," << fShape->GetPointerName() << ", "<< fMedium->GetPointerName() << ");" << endl;
} else {
out << " // Assembly: " << GetName() << endl;
out << " " << GetPointerName() << " = new TGeoVolumeAssembly(\"" << GetName() << "\"" << ");" << endl;
}
if (fLineColor != 1) out << " " << GetPointerName() << "->SetLineColor(" << fLineColor << ");" << endl;
if (fLineWidth != 1) out << " " << GetPointerName() << "->SetLineWidth(" << fLineWidth << ");" << endl;
if (fLineStyle != 1) out << " " << GetPointerName() << "->SetLineStyle(" << fLineStyle << ");" << endl;
if (!IsVisible() && !IsAssembly()) out << " " << GetPointerName() << "->SetVisibility(kFALSE);" << endl;
if (!IsVisibleDaughters()) out << " " << GetPointerName() << "->VisibleDaughters(kFALSE);" << endl;
if (IsVisContainers()) out << " " << GetPointerName() << "->SetVisContainers(kTRUE);" << endl;
if (IsVisLeaves()) out << " " << GetPointerName() << "->SetVisLeaves(kTRUE);" << endl;
SetAttBit(TGeoAtt::kSavePrimitiveAtt);
}
if (!strcmp(option, "m")) {
if (fMedium) fMedium->SavePrimitive(out,option);
for (i=0; i<nd; i++) {
dvol = GetNode(i)->GetVolume();
dvol->SavePrimitive(out,option);
}
return;
}
if (!strcmp(option, "x")) {
if (fFinder) {
dvol = GetNode(0)->GetVolume();
dvol->SavePrimitive(out,option);
return;
}
for (i=0; i<nd; i++) {
dnode = GetNode(i);
matrix = dnode->GetMatrix();
if (!matrix->IsIdentity()) matrix->SavePrimitive(out,option);
dnode->GetVolume()->SavePrimitive(out,option);
}
return;
}
if (!strcmp(option, "d")) {
if (!nd) return;
if (TestAttBit(TGeoAtt::kSaveNodesAtt)) return;
SetAttBit(TGeoAtt::kSaveNodesAtt);
if (fFinder) {
dnode = GetNode(0);
dvol = dnode->GetVolume();
out << " TGeoVolume *" << dvol->GetPointerName() << " = ";
out << GetPointerName() << "->Divide(\"" << dvol->GetName() << "\", ";
fFinder->SavePrimitive(out,option);
if (fMedium != dvol->GetMedium()) {
out << ", " << dvol->GetMedium()->GetId();
}
out << ");" << endl;
dvol->SavePrimitive(out,"d");
return;
}
for (i=0; i<nd; i++) {
dnode = GetNode(i);
dvol = dnode->GetVolume();
dvol->SavePrimitive(out,"s");
matrix = dnode->GetMatrix();
icopy = dnode->GetNumber();
out << " " << GetPointerName() << "->AddNode";
if (dnode->IsOverlapping()) out << "Overlap";
out << "(" << dvol->GetPointerName() << ", " << icopy;
if (!matrix->IsIdentity()) out << ", " << matrix->GetPointerName();
out << ");" << endl;
}
for (i=0; i<nd; i++) {
dnode = GetNode(i);
dvol = dnode->GetVolume();
dvol->SavePrimitive(out,"d");
}
}
}
void TGeoVolume::UnmarkSaved()
{
ResetAttBit(TGeoAtt::kSavePrimitiveAtt);
ResetAttBit(TGeoAtt::kSaveNodesAtt);
if (fShape) fShape->ResetBit(TGeoShape::kGeoSavePrimitive);
}
void TGeoVolume::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
TVirtualGeoPainter *painter = fGeoManager->GetPainter();
if (!painter) return;
painter->ExecuteVolumeEvent(this, event, px, py);
}
TGeoNode *TGeoVolume::FindNode(const char *name) const
{
return ((TGeoNode*)fNodes->FindObject(name));
}
Int_t TGeoVolume::GetNodeIndex(const TGeoNode *node, Int_t *check_list, Int_t ncheck) const
{
TGeoNode *current = 0;
for (Int_t i=0; i<ncheck; i++) {
current = (TGeoNode*)fNodes->At(check_list[i]);
if (current==node) return check_list[i];
}
return -1;
}
Int_t TGeoVolume::GetIndex(const TGeoNode *node) const
{
TGeoNode *current = 0;
Int_t nd = GetNdaughters();
if (!nd) return -1;
for (Int_t i=0; i<nd; i++) {
current = (TGeoNode*)fNodes->At(i);
if (current==node) return i;
}
return -1;
}
char *TGeoVolume::GetObjectInfo(Int_t px, Int_t py) const
{
TGeoVolume *vol = (TGeoVolume*)this;
TVirtualGeoPainter *painter = fGeoManager->GetPainter();
if (!painter) return 0;
return painter->GetVolumeInfo(vol, px, py);
}
Bool_t TGeoVolume::GetOptimalVoxels() const
{
Int_t nd = GetNdaughters();
if (!nd) return kFALSE;
Int_t id;
Int_t ncyl = 0;
TGeoNode *node;
for (id=0; id<nd; id++) {
node = (TGeoNode*)fNodes->At(id);
ncyl += node->GetOptimalVoxels();
}
if (ncyl>(nd/2)) return kTRUE;
return kFALSE;
}
char *TGeoVolume::GetPointerName() const
{
static char name[40];
sprintf(name, "p%s_%lx", GetName(), (ULong_t)this);
return name;
}
TGeoVoxelFinder *TGeoVolume::GetVoxels() const
{
if (fVoxels && !fVoxels->IsInvalid()) return fVoxels;
return NULL;
}
void TGeoVolume::GrabFocus()
{
TVirtualGeoPainter *painter = fGeoManager->GetPainter();
if (painter) painter->GrabFocus();
}
TGeoVolume *TGeoVolume::CloneVolume() const
{
TGeoVolume *vol = new TGeoVolume(GetName(), fShape, fMedium);
Int_t i;
vol->SetLineColor(GetLineColor());
vol->SetLineStyle(GetLineStyle());
vol->SetLineWidth(GetLineWidth());
vol->SetFillColor(GetFillColor());
vol->SetFillStyle(GetFillStyle());
Int_t nbits = 8*sizeof(UInt_t);
for (i=0; i<nbits; i++)
vol->SetAttBit(1<<i, TGeoAtt::TestAttBit(1<<i));
for (i=14; i<24; i++)
vol->SetBit(1<<i, TestBit(1<<i));
vol->SetField(fField);
for (i=0; i<nbits; i++)
vol->SetBit(1<<i, TObject::TestBit(1<<i));
vol->SetBit(kVolumeClone);
vol->MakeCopyNodes(this);
vol->SetFinder(fFinder);
TGeoVoxelFinder *voxels = 0;
if (fVoxels) {
voxels = new TGeoVoxelFinder(vol);
vol->SetVoxelFinder(voxels);
}
vol->SetOption(fOption);
vol->SetNumber(fNumber);
vol->SetNtotal(fNtotal);
return vol;
}
void TGeoVolume::CloneNodesAndConnect(TGeoVolume *newmother) const
{
if (!fNodes) return;
TGeoNode *node;
Int_t nd = fNodes->GetEntriesFast();
if (!nd) return;
TObjArray *list = new TObjArray(nd);
newmother->SetNodes(list);
for (Int_t i=0; i<nd; i++) {
node = GetNode(i)->MakeCopyNode();
node->SetMotherVolume(newmother);
list->Add(node);
}
}
void TGeoVolume::MakeCopyNodes(const TGeoVolume *other)
{
Int_t nd = other->GetNdaughters();
if (!nd) return;
if (fNodes) delete fNodes;
fNodes = new TObjArray();
for (Int_t i=0; i<nd; i++) fNodes->Add(other->GetNode(i));
TObject::SetBit(kVolumeImportNodes);
}
TGeoVolume *TGeoVolume::MakeCopyVolume(TGeoShape *newshape)
{
TGeoVolume *vol = new TGeoVolume(GetName(), newshape, fMedium);
vol->SetVisibility(IsVisible());
vol->SetLineColor(GetLineColor());
vol->SetLineStyle(GetLineStyle());
vol->SetLineWidth(GetLineWidth());
vol->SetFillColor(GetFillColor());
vol->SetFillStyle(GetFillStyle());
vol->SetField(fField);
if (fFinder) {
vol->SetFinder(fFinder);
}
CloneNodesAndConnect(vol);
((TObject*)vol)->SetBit(kVolumeClone);
return vol;
}
TGeoVolume *TGeoVolume::MakeReflectedVolume(const char *newname) const
{
static TMap map(100);
if (!fGeoManager->IsClosed()) {
Error("MakeReflectedVolume", "Geometry must be closed.");
return NULL;
}
TGeoVolume *vol = (TGeoVolume*)map.GetValue(this);
if (vol) {
if (strlen(newname)) vol->SetName(newname);
return vol;
}
vol = CloneVolume();
map.Add((TObject*)this, vol);
if (strlen(newname)) vol->SetName(newname);
delete vol->GetNodes();
vol->SetNodes(NULL);
vol->SetBit(kVolumeImportNodes, kFALSE);
CloneNodesAndConnect(vol);
if (fShape) {
TGeoShape *reflected_shape =
TGeoScaledShape::MakeScaledShape("", fShape, new TGeoScale(1.,1.,-1.));
vol->SetShape(reflected_shape);
}
Int_t nd = vol->GetNdaughters();
if (!nd) return vol;
TGeoNodeMatrix *node;
TGeoMatrix *local, *local_cloned;
TGeoVolume *new_vol;
if (!vol->GetFinder()) {
for (Int_t i=0; i<nd; i++) {
node = (TGeoNodeMatrix*)vol->GetNode(i);
local = node->GetMatrix();
Bool_t reflected = local->IsReflection();
local_cloned = new TGeoCombiTrans(*local);
local_cloned->RegisterYourself();
node->SetMatrix(local_cloned);
if (!reflected) {
local_cloned->ReflectZ(kTRUE);
local_cloned->ReflectZ(kFALSE);
new_vol = node->GetVolume()->MakeReflectedVolume();
node->SetVolume(new_vol);
continue;
}
local_cloned->ReflectZ(kTRUE);
}
if (vol->GetVoxels()) vol->GetVoxels()->Voxelize();
return vol;
}
TGeoPatternFinder *new_finder = fFinder->MakeCopy(kTRUE);
new_finder->SetVolume(vol);
vol->SetFinder(new_finder);
TGeoNodeOffset *nodeoff;
new_vol = 0;
for (Int_t i=0; i<nd; i++) {
nodeoff = (TGeoNodeOffset*)vol->GetNode(i);
nodeoff->SetFinder(new_finder);
new_vol = nodeoff->GetVolume()->MakeReflectedVolume();
nodeoff->SetVolume(new_vol);
}
return vol;
}
void TGeoVolume::SetAsTopVolume()
{
fGeoManager->SetTopVolume(this);
}
void TGeoVolume::SetCurrentPoint(Double_t x, Double_t y, Double_t z)
{
fGeoManager->SetCurrentPoint(x,y,z);
}
void TGeoVolume::SetShape(const TGeoShape *shape)
{
if (!shape) {
Error("SetShape", "No shape");
return;
}
fShape = (TGeoShape*)shape;
}
void TGeoVolume::SortNodes()
{
if (!Valid()) {
Error("SortNodes", "Bounding box not valid");
return;
}
Int_t nd = GetNdaughters();
if (!nd) return;
if (fFinder) return;
Int_t id = 0;
TGeoNode *node = 0;
TObjArray *nodes = new TObjArray(nd);
Int_t inode = 0;
for (id=0; id<nd; id++) {
node = GetNode(id);
if (node->InheritsFrom("TGeoNodeOffset") || node->IsOverlapping()) continue;
nodes->Add(node);
inode++;
}
for (id=0; id<nd; id++) {
node = GetNode(id);
if (node->InheritsFrom("TGeoNodeOffset") || (!node->IsOverlapping())) continue;
nodes->Add(node);
inode++;
}
if (fFinder) {
fFinder->SetDivIndex(inode);
for (id=0; id<nd; id++) {
node = GetNode(id);
if (!node->InheritsFrom("TGeoNodeOffset")) continue;
nodes->Add(node);
inode++;
}
}
if (inode != nd) printf(" volume %s : number of nodes does not match!!!\n", GetName());
delete fNodes;
fNodes = nodes;
}
void TGeoVolume::Streamer(TBuffer &R__b)
{
if (R__b.IsReading()) {
R__b.ReadClassBuffer(TGeoVolume::Class(), this);
if (fVoxels && fVoxels->IsInvalid()) Voxelize("");
} else {
if (!fVoxels) {
R__b.WriteClassBuffer(TGeoVolume::Class(), this);
} else {
if (!fGeoManager->IsStreamingVoxels()) {
TGeoVoxelFinder *voxels = fVoxels;
fVoxels = 0;
R__b.WriteClassBuffer(TGeoVolume::Class(), this);
fVoxels = voxels;
} else {
R__b.WriteClassBuffer(TGeoVolume::Class(), this);
}
}
}
}
void TGeoVolume::SetOption(const char * )
{
}
void TGeoVolume::SetLineColor(Color_t lcolor)
{
TAttLine::SetLineColor(lcolor);
}
void TGeoVolume::SetLineStyle(Style_t lstyle)
{
TAttLine::SetLineStyle(lstyle);
}
void TGeoVolume::SetLineWidth(Style_t lwidth)
{
TAttLine::SetLineWidth(lwidth);
}
TGeoNode *TGeoVolume::GetNode(const char *name) const
{
if (!fNodes) return 0;
TGeoNode *node = (TGeoNode *)fNodes->FindObject(name);
return node;
}
Int_t TGeoVolume::GetByteCount() const
{
Int_t count = 28+2+6+4+0;
count += strlen(GetName()) + strlen(GetTitle());
count += 4+4+4+4+4;
count += 8 + strlen(fOption.Data());
if (fShape) count += fShape->GetByteCount();
if (fFinder) count += fFinder->GetByteCount();
if (fNodes) {
count += 32 + 4*fNodes->GetEntries();
TIter next(fNodes);
TGeoNode *node;
while ((node=(TGeoNode*)next())) count += node->GetByteCount();
}
return count;
}
void TGeoVolume::FindOverlaps() const
{
if (!Valid()) {
Error("FindOverlaps","Bounding box not valid");
return;
}
if (!fVoxels) return;
Int_t nd = GetNdaughters();
if (!nd) return;
TGeoNode *node=0;
Int_t inode = 0;
for (inode=0; inode<nd; inode++) {
node = GetNode(inode);
if (!node->IsOverlapping()) continue;
fVoxels->FindOverlaps(inode);
}
}
void TGeoVolume::RemoveNode(TGeoNode *node)
{
if (!fNodes || !fNodes->GetEntriesFast()) return;
if (!fNodes->Remove(node)) return;
fNodes->Compress();
if (fVoxels) fVoxels->SetNeedRebuild();
if (IsAssembly()) fShape->ComputeBBox();
}
TGeoNode *TGeoVolume::ReplaceNode(TGeoNode *nodeorig, TGeoShape *newshape, TGeoMatrix *newpos, TGeoMedium *newmed)
{
Int_t ind = GetIndex(nodeorig);
if (ind < 0) return NULL;
TGeoVolume *oldvol = nodeorig->GetVolume();
if (oldvol->IsAssembly()) {
Error("ReplaceNode", "Cannot replace node %s since it is an assembly", nodeorig->GetName());
return NULL;
}
TGeoShape *shape = oldvol->GetShape();
if (newshape && !nodeorig->IsOffset()) shape = newshape;
TGeoMatrix *pos = nodeorig->GetMatrix();
if (newpos && !nodeorig->IsOffset()) pos = newpos;
TGeoMedium *med = oldvol->GetMedium();
if (newmed) med = newmed;
TGeoVolume *vol = new TGeoVolume(oldvol->GetName(), shape, med);
vol->SetVisibility(oldvol->IsVisible());
vol->SetLineColor(oldvol->GetLineColor());
vol->SetLineStyle(oldvol->GetLineStyle());
vol->SetLineWidth(oldvol->GetLineWidth());
vol->SetFillColor(oldvol->GetFillColor());
vol->SetFillStyle(oldvol->GetFillStyle());
vol->SetField(oldvol->GetField());
TGeoNode *newnode = nodeorig->MakeCopyNode();
newnode->SetVolume(vol);
fNodes->RemoveAt(ind);
fNodes->AddAt(newnode, ind);
if (fVoxels) fVoxels->SetNeedRebuild();
if (IsAssembly()) fShape->ComputeBBox();
return newnode;
}
void TGeoVolume::SelectVolume(Bool_t clear)
{
static TObjArray array(256);
static Int_t len = 0;
Int_t i;
TObject *vol;
if (clear) {
for (i=0; i<len; i++) {
vol = array.At(i);
vol->ResetBit(TGeoVolume::kVolumeSelected);
}
array.Clear();
len = 0;
return;
}
SetBit(TGeoVolume::kVolumeSelected);
array.AddAtAndExpand(this, len++);
}
void TGeoVolume::SetVisibility(Bool_t vis)
{
if (IsAssembly()) {
Info("SetVisibility", "Volume assemblies do not have visibility");
return;
}
TGeoAtt::SetVisibility(vis);
if (fGeoManager->IsClosed()) SetVisTouched(kTRUE);
fGeoManager->SetVisOption(4);
TSeqCollection *brlist = gROOT->GetListOfBrowsers();
TIter next(brlist);
TBrowser *browser = 0;
while ((browser=(TBrowser*)next())) {
browser->CheckObjectItem(this, vis);
browser->Refresh();
}
}
void TGeoVolume::SetVisContainers(Bool_t flag)
{
TGeoAtt::SetVisContainers(flag);
if (fGeoManager && fGeoManager->IsClosed()) {
if (flag) fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisDefault);
else fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisLeaves);
}
}
void TGeoVolume::SetVisLeaves(Bool_t flag)
{
TGeoAtt::SetVisLeaves(flag);
if (fGeoManager && fGeoManager->IsClosed()) {
if (flag) fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisLeaves);
else fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisDefault);
}
}
void TGeoVolume::SetVisOnly(Bool_t flag)
{
if (IsAssembly()) return;
TGeoAtt::SetVisOnly(flag);
if (fGeoManager && fGeoManager->IsClosed()) {
if (flag) fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisOnly);
else fGeoManager->SetVisOption(TVirtualGeoPainter::kGeoVisLeaves);
}
}
Bool_t TGeoVolume::Valid() const
{
return fShape->IsValidBox();
}
Bool_t TGeoVolume::FindMatrixOfDaughterVolume(TGeoVolume *vol) const
{
if (vol == this) return kTRUE;
Int_t nd = GetNdaughters();
if (!nd) return kFALSE;
TGeoHMatrix *global = fGeoManager->GetHMatrix();
TGeoNode *dnode;
TGeoVolume *dvol;
TGeoMatrix *local;
Int_t i;
for (i=0; i<nd; i++) {
dnode = GetNode(i);
dvol = dnode->GetVolume();
if (dvol == vol) {
local = dnode->GetMatrix();
global->MultiplyLeft(local);
return kTRUE;
}
}
for (i=0; i<nd; i++) {
dnode = GetNode(i);
dvol = dnode->GetVolume();
if (dvol->FindMatrixOfDaughterVolume(vol)) return kTRUE;
}
return kFALSE;
}
void TGeoVolume::VisibleDaughters(Bool_t vis)
{
SetVisDaughters(vis);
if (fGeoManager->IsClosed()) SetVisTouched(kTRUE);
fGeoManager->SetVisOption(4);
}
void TGeoVolume::Voxelize(Option_t *option)
{
if (!Valid()) {
Error("Voxelize", "Bounding box not valid");
return;
}
if (fFinder) return;
Int_t nd = GetNdaughters();
if (!nd) return;
if (IsAssembly()) fShape->ComputeBBox();
if (fVoxels) {
if (!TObject::TestBit(kVolumeClone)) delete fVoxels;
fVoxels = 0;
}
fVoxels = new TGeoVoxelFinder(this);
fVoxels->Voxelize(option);
if (fVoxels) {
if (fVoxels->IsInvalid()) {
delete fVoxels;
fVoxels = 0;
}
}
}
Double_t TGeoVolume::Weight(Double_t precision, Option_t *option)
{
TGeoVolume *top = fGeoManager->GetTopVolume();
if (top != this) fGeoManager->SetTopVolume(this);
else top = 0;
Double_t weight = fGeoManager->Weight(precision, option);
if (top) fGeoManager->SetTopVolume(top);
return weight;
}
Double_t TGeoVolume::WeightA() const
{
Double_t capacity = Capacity();
Double_t weight = 0.0;
Int_t i;
Int_t nd = GetNdaughters();
TGeoVolume *daughter;
for (i=0; i<nd; i++) {
daughter = GetNode(i)->GetVolume();
weight += daughter->WeightA();
capacity -= daughter->Capacity();
}
Double_t density = 0.0;
if (!IsAssembly()) {
if (fMedium) density = fMedium->GetMaterial()->GetDensity();
if (density<0.01) density = 0.0;
}
weight += 0.001*capacity * density;
return weight;
}
ClassImp(TGeoVolumeMulti)
TGeoVolumeMulti::TGeoVolumeMulti()
{
fVolumes = 0;
fDivision = 0;
fNumed = 0;
fNdiv = 0;
fAxis = 0;
fStart = 0;
fStep = 0;
fAttSet = kFALSE;
TObject::SetBit(kVolumeMulti);
}
TGeoVolumeMulti::TGeoVolumeMulti(const char *name, const TGeoMedium *med)
{
fVolumes = new TObjArray();
fDivision = 0;
fNumed = 0;
fNdiv = 0;
fAxis = 0;
fStart = 0;
fStep = 0;
fAttSet = kFALSE;
TObject::SetBit(kVolumeMulti);
SetName(name);
SetMedium(med);
fGeoManager->AddVolume(this);
}
TGeoVolumeMulti::TGeoVolumeMulti(const TGeoVolumeMulti& vm) :
TGeoVolume(vm),
fVolumes(vm.fVolumes),
fDivision(vm.fDivision),
fNumed(vm.fNumed),
fNdiv(vm.fNdiv),
fAxis(vm.fAxis),
fStart(vm.fStart),
fStep(vm.fStep),
fAttSet(vm.fAttSet)
{
}
TGeoVolumeMulti& TGeoVolumeMulti::operator=(const TGeoVolumeMulti& vm)
{
if(this!=&vm) {
TGeoVolume::operator=(vm);
fVolumes=vm.fVolumes;
fDivision=vm.fDivision;
fNumed=vm.fNumed;
fNdiv=vm.fNdiv;
fAxis=vm.fAxis;
fStart=vm.fStart;
fStep=vm.fStep;
fAttSet=vm.fAttSet;
}
return *this;
}
TGeoVolumeMulti::~TGeoVolumeMulti()
{
if (fVolumes) delete fVolumes;
}
void TGeoVolumeMulti::AddVolume(TGeoVolume *vol)
{
Int_t idx = fVolumes->GetEntriesFast();
fVolumes->AddAtAndExpand(vol,idx);
vol->SetUniqueID(idx+1);
TGeoVolumeMulti *div;
TGeoVolume *cell;
if (fDivision) {
div = (TGeoVolumeMulti*)vol->Divide(fDivision->GetName(), fAxis, fNdiv, fStart, fStep, fNumed, fOption.Data());
for (Int_t i=0; i<div->GetNvolumes(); i++) {
cell = div->GetVolume(i);
fDivision->AddVolume(cell);
}
}
if (fNodes) {
Int_t nd = fNodes->GetEntriesFast();
for (Int_t id=0; id<nd; id++) {
TGeoNode *node = (TGeoNode*)fNodes->At(id);
Bool_t many = node->IsOverlapping();
if (many) vol->AddNodeOverlap(node->GetVolume(), node->GetNumber(), node->GetMatrix());
else vol->AddNode(node->GetVolume(), node->GetNumber(), node->GetMatrix());
}
}
}
void TGeoVolumeMulti::AddNode(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
{
TGeoVolume::AddNode(vol, copy_no, mat, option);
Int_t nvolumes = fVolumes->GetEntriesFast();
TGeoVolume *volume = 0;
for (Int_t ivo=0; ivo<nvolumes; ivo++) {
volume = GetVolume(ivo);
volume->SetLineColor(GetLineColor());
volume->SetLineStyle(GetLineStyle());
volume->SetLineWidth(GetLineWidth());
volume->SetVisibility(IsVisible());
volume->AddNode(vol, copy_no, mat, option);
}
}
void TGeoVolumeMulti::AddNodeOverlap(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
{
TGeoVolume::AddNodeOverlap(vol, copy_no, mat, option);
Int_t nvolumes = fVolumes->GetEntriesFast();
TGeoVolume *volume = 0;
for (Int_t ivo=0; ivo<nvolumes; ivo++) {
volume = GetVolume(ivo);
volume->SetLineColor(GetLineColor());
volume->SetLineStyle(GetLineStyle());
volume->SetLineWidth(GetLineWidth());
volume->SetVisibility(IsVisible());
volume->AddNodeOverlap(vol, copy_no, mat, option);
}
}
TGeoVolume *TGeoVolumeMulti::Divide(const char *divname, Int_t iaxis, Int_t ndiv, Double_t start, Double_t step, Int_t numed, const char *option)
{
if (fDivision) {
Error("Divide", "volume %s already divided", GetName());
return 0;
}
Int_t nvolumes = fVolumes->GetEntriesFast();
TGeoMedium *medium = fMedium;
if (numed) {
medium = fGeoManager->GetMedium(numed);
if (!medium) {
Error("Divide", "Invalid medium number %d for division volume %s", numed, divname);
medium = fMedium;
}
}
if (!nvolumes) {
fDivision = new TGeoVolumeMulti(divname, medium);
fNumed = medium->GetId();
fOption = option;
fAxis = iaxis;
fNdiv = ndiv;
fStart = start;
fStep = step;
return fDivision;
}
TGeoVolume *vol = 0;
fDivision = new TGeoVolumeMulti(divname, medium);
if (medium) fNumed = medium->GetId();
fOption = option;
fAxis = iaxis;
fNdiv = ndiv;
fStart = start;
fStep = step;
for (Int_t ivo=0; ivo<nvolumes; ivo++) {
vol = GetVolume(ivo);
vol->SetLineColor(GetLineColor());
vol->SetLineStyle(GetLineStyle());
vol->SetLineWidth(GetLineWidth());
vol->SetVisibility(IsVisible());
fDivision->AddVolume(vol->Divide(divname,iaxis,ndiv,start,step, numed, option));
}
if (numed) fDivision->SetMedium(medium);
return fDivision;
}
TGeoVolume *TGeoVolumeMulti::MakeCopyVolume(TGeoShape *newshape)
{
char *name = new char[strlen(GetName())+1];
sprintf(name, "%s", GetName());
TGeoVolume *vol = new TGeoVolume(name, newshape, fMedium);
delete [] name;
Int_t i=0;
vol->SetVisibility(IsVisible());
vol->SetLineColor(GetLineColor());
vol->SetLineStyle(GetLineStyle());
vol->SetLineWidth(GetLineWidth());
vol->SetFillColor(GetFillColor());
vol->SetFillStyle(GetFillStyle());
vol->SetField(fField);
if (fDivision) {
TGeoVolume *cell;
TGeoVolumeMulti *div = (TGeoVolumeMulti*)vol->Divide(fDivision->GetName(), fAxis, fNdiv, fStart, fStep, fNumed, fOption.Data());
for (i=0; i<div->GetNvolumes(); i++) {
cell = div->GetVolume(i);
fDivision->AddVolume(cell);
}
}
if (!fNodes) return vol;
TGeoNode *node;
Int_t nd = fNodes->GetEntriesFast();
if (!nd) return vol;
TObjArray *list = new TObjArray();
vol->SetNodes(list);
((TObject*)vol)->SetBit(kVolumeImportNodes);
for (i=0; i<nd; i++) {
node = GetNode(i)->MakeCopyNode();
node->SetMotherVolume(vol);
list->Add(node);
}
return vol;
}
void TGeoVolumeMulti::SetLineColor(Color_t lcolor)
{
TGeoVolume::SetLineColor(lcolor);
Int_t nvolumes = fVolumes->GetEntriesFast();
TGeoVolume *vol = 0;
for (Int_t ivo=0; ivo<nvolumes; ivo++) {
vol = GetVolume(ivo);
vol->SetLineColor(lcolor);
}
}
void TGeoVolumeMulti::SetLineStyle(Style_t lstyle)
{
TGeoVolume::SetLineStyle(lstyle);
Int_t nvolumes = fVolumes->GetEntriesFast();
TGeoVolume *vol = 0;
for (Int_t ivo=0; ivo<nvolumes; ivo++) {
vol = GetVolume(ivo);
vol->SetLineStyle(lstyle);
}
}
void TGeoVolumeMulti::SetLineWidth(Width_t lwidth)
{
TGeoVolume::SetLineWidth(lwidth);
Int_t nvolumes = fVolumes->GetEntriesFast();
TGeoVolume *vol = 0;
for (Int_t ivo=0; ivo<nvolumes; ivo++) {
vol = GetVolume(ivo);
vol->SetLineWidth(lwidth);
}
}
void TGeoVolumeMulti::SetMedium(const TGeoMedium *med)
{
TGeoVolume::SetMedium(med);
Int_t nvolumes = fVolumes->GetEntriesFast();
TGeoVolume *vol = 0;
for (Int_t ivo=0; ivo<nvolumes; ivo++) {
vol = GetVolume(ivo);
vol->SetMedium(med);
}
}
void TGeoVolumeMulti::SetVisibility(Bool_t vis)
{
TGeoVolume::SetVisibility(vis);
Int_t nvolumes = fVolumes->GetEntriesFast();
TGeoVolume *vol = 0;
for (Int_t ivo=0; ivo<nvolumes; ivo++) {
vol = GetVolume(ivo);
vol->SetVisibility(vis);
}
}
ClassImp(TGeoVolumeAssembly)
TGeoVolumeAssembly::TGeoVolumeAssembly()
:TGeoVolume()
{
fCurrent = -1;
fNext = -1;
}
TGeoVolumeAssembly::TGeoVolumeAssembly(const char *name)
:TGeoVolume()
{
fName = name;
fName = fName.Strip();
fCurrent = -1;
fNext = -1;
fShape = new TGeoShapeAssembly(this);
if (fGeoManager) fNumber = fGeoManager->AddVolume(this);
}
TGeoVolumeAssembly::~TGeoVolumeAssembly()
{
if (fShape) delete fShape;
}
void TGeoVolumeAssembly::AddNode(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
{
TGeoVolume::AddNode(vol,copy_no,mat,option);
fShape->ComputeBBox();
}
void TGeoVolumeAssembly::AddNodeOverlap(const TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat, Option_t *option)
{
Warning("AddNodeOverlap", "Declaring assembly %s as possibly overlapping inside %s not allowed. Using AddNode instead !",vol->GetName(),GetName());
AddNode(vol, copy_no, mat, option);
}
TGeoVolume *TGeoVolumeAssembly::CloneVolume() const
{
TGeoVolume *vol = new TGeoVolumeAssembly(GetName());
Int_t i;
Int_t nbits = 8*sizeof(UInt_t);
for (i=0; i<nbits; i++)
vol->SetAttBit(1<<i, TGeoAtt::TestAttBit(1<<i));
for (i=14; i<24; i++)
vol->SetBit(1<<i, TestBit(1<<i));
vol->SetField(fField);
for (i=0; i<nbits; i++)
vol->SetBit(1<<i, TObject::TestBit(1<<i));
vol->SetBit(kVolumeClone);
vol->MakeCopyNodes(this);
vol->GetShape()->ComputeBBox();
TGeoVoxelFinder *voxels = 0;
if (fVoxels) {
voxels = new TGeoVoxelFinder(vol);
vol->SetVoxelFinder(voxels);
}
vol->SetOption(fOption);
vol->SetNumber(fNumber);
vol->SetNtotal(fNtotal);
return vol;
}
TGeoVolume *TGeoVolumeAssembly::Divide(const char *, Int_t, Int_t, Double_t, Double_t, Int_t, Option_t *)
{
Error("Divide","Assemblies cannot be divided");
return 0;
}
TGeoVolumeAssembly *TGeoVolumeAssembly::MakeAssemblyFromVolume(TGeoVolume *volorig)
{
if (volorig->IsAssembly() || volorig->IsVolumeMulti()) return 0;
Int_t nd = volorig->GetNdaughters();
if (!nd) return 0;
TGeoVolumeAssembly *vol = new TGeoVolumeAssembly(volorig->GetName());
Int_t i;
Int_t nbits = 8*sizeof(UInt_t);
for (i=0; i<nbits; i++)
vol->SetAttBit(1<<i, volorig->TestAttBit(1<<i));
for (i=14; i<24; i++)
vol->SetBit(1<<i, volorig->TestBit(1<<i));
vol->SetField(volorig->GetField());
for (i=0; i<nbits; i++)
vol->SetBit(1<<i, volorig->TestBit(1<<i));
vol->SetBit(kVolumeClone);
vol->MakeCopyNodes(volorig);
vol->GetShape()->ComputeBBox();
TGeoVoxelFinder *voxels = 0;
if (volorig->GetVoxels()) {
voxels = new TGeoVoxelFinder(vol);
vol->SetVoxelFinder(voxels);
}
vol->SetOption(volorig->GetOption());
vol->SetNumber(volorig->GetNumber());
vol->SetNtotal(volorig->GetNtotal());
return vol;
}
Last change: Fri Oct 10 12:55:23 2008
Last generated: 2008-10-10 12:55
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.