#include "TVirtualPad.h"
#include "TCanvas.h"
#include "TStyle.h"
#include "TFile.h"
#include "TNtuple.h"
#include "TH2.h"
#include "TRandom3.h"
#include "TPolyMarker3D.h"
#include "TPolyLine3D.h"
#include "TStopwatch.h"
#include "TGeoVoxelFinder.h"
#include "TGeoBBox.h"
#include "TGeoPcon.h"
#include "TGeoManager.h"
#include "TGeoOverlap.h"
#include "TGeoPainter.h"
#include "TGeoChecker.h"
#include "TBuffer3D.h"
#include "TBuffer3DTypes.h"
#include "TMath.h"
#include <stdlib.h>
ClassImp(TGeoChecker)
TGeoChecker::TGeoChecker()
:TObject(),
fGeoManager(NULL),
fVsafe(NULL),
fBuff1(NULL),
fBuff2(NULL),
fFullCheck(kFALSE),
fVal1(NULL),
fVal2(NULL),
fFlags(NULL),
fTimer(NULL),
fSelectedNode(NULL),
fNchecks(0),
fNmeshPoints(1000)
{
}
TGeoChecker::TGeoChecker(TGeoManager *geom)
:TObject(),
fGeoManager(geom),
fVsafe(NULL),
fBuff1(NULL),
fBuff2(NULL),
fFullCheck(kFALSE),
fVal1(NULL),
fVal2(NULL),
fFlags(NULL),
fTimer(NULL),
fSelectedNode(NULL),
fNchecks(0),
fNmeshPoints(1000)
{
fBuff1 = new TBuffer3D(TBuffer3DTypes::kGeneric,500,3*500,0,0,0,0);
fBuff2 = new TBuffer3D(TBuffer3DTypes::kGeneric,500,3*500,0,0,0,0);
}
TGeoChecker::~TGeoChecker()
{
if (fBuff1) delete fBuff1;
if (fBuff2) delete fBuff2;
if (fTimer) delete fTimer;
}
void TGeoChecker::OpProgress(const char *opname, Long64_t current, Long64_t size, TStopwatch *watch, Bool_t last, Bool_t refresh)
{
static Long64_t icount = 0;
static TString oname;
static TString nname;
static Long64_t ocurrent = 0;
static Long64_t osize = 0;
static Int_t oseconds = 0;
static TStopwatch *owatch = 0;
static Bool_t oneoftwo = kFALSE;
static Int_t nrefresh = 0;
const char symbol[4] = {'=','\\','|','/'};
char progress[11] = " ";
Int_t ichar = icount%4;
if (!refresh) {
nrefresh = 0;
if (!size) return;
owatch = watch;
oname = opname;
ocurrent = TMath::Abs(current);
osize = TMath::Abs(size);
if (ocurrent > osize) ocurrent=osize;
} else {
nrefresh++;
if (!osize) return;
}
icount++;
Double_t time = 0.;
Int_t hours = 0;
Int_t minutes = 0;
Int_t seconds = 0;
if (owatch && !last) {
owatch->Stop();
time = owatch->RealTime();
hours = (Int_t)(time/3600.);
time -= 3600*hours;
minutes = (Int_t)(time/60.);
time -= 60*minutes;
seconds = (Int_t)time;
if (refresh) {
if (oseconds==seconds) {
owatch->Continue();
return;
}
oneoftwo = !oneoftwo;
}
oseconds = seconds;
}
if (refresh && oneoftwo) {
nname = oname;
if (fNchecks <= 0) fNchecks = nrefresh+1;
Int_t pctdone = (Int_t)(100.*nrefresh/fNchecks);
oname = Form(" == %d%% ==", pctdone);
}
Double_t percent = 100.0*ocurrent/osize;
Int_t nchar = Int_t(percent/10);
if (nchar>10) nchar=10;
Int_t i;
for (i=0; i<nchar; i++) progress[i] = '=';
progress[nchar] = symbol[ichar];
for (i=nchar+1; i<10; i++) progress[i] = ' ';
progress[10] = '\0';
oname += " ";
oname.Remove(20);
if(size<10000) fprintf(stderr, "%s [%10s] %4lld ", oname.Data(), progress, ocurrent);
else if(size<100000) fprintf(stderr, "%s [%10s] %5lld ",oname.Data(), progress, ocurrent);
else fprintf(stderr, "%s [%10s] %7lld ",oname.Data(), progress, ocurrent);
if (time>0.) fprintf(stderr, "[%6.2f %%] TIME %.2d:%.2d:%.2d \r", percent, hours, minutes, seconds);
else fprintf(stderr, "[%6.2f %%]\r", percent);
if (refresh && oneoftwo) oname = nname;
if (owatch) owatch->Continue();
if (last) {
icount = 0;
owatch = 0;
ocurrent = 0;
osize = 0;
oseconds = 0;
oneoftwo = kFALSE;
nrefresh = 0;
fprintf(stderr, "\n");
}
}
void TGeoChecker::CheckBoundaryErrors(Int_t ntracks, Double_t radius)
{
gRandom = new TRandom3();
TGeoVolume *tvol = fGeoManager->GetTopVolume();
Info("CheckBoundaryErrors", "Top volume is %s",tvol->GetName());
const TGeoShape *shape = tvol->GetShape();
TGeoBBox *box = (TGeoBBox *)shape;
Double_t dl[3];
Double_t ori[3];
Double_t xyz[3];
Double_t nxyz[3];
Double_t dir[3];
Double_t relp;
Char_t path[1024];
Char_t cdir[10];
TFile *f=new TFile("geobugs.root","recreate");
TTree *bug=new TTree("bug","Geometrical problems");
bug->Branch("pos",xyz,"xyz[3]/D");
bug->Branch("dir",dir,"dir[3]/D");
bug->Branch("push",&relp,"push/D");
bug->Branch("path",&path,"path/C");
bug->Branch("cdir",&cdir,"cdir/C");
dl[0] = box->GetDX();
dl[1] = box->GetDY();
dl[2] = box->GetDZ();
ori[0] = (box->GetOrigin())[0];
ori[1] = (box->GetOrigin())[1];
ori[2] = (box->GetOrigin())[2];
if (radius>0)
dl[0] = dl[1] = dl[2] = radius;
TH1::AddDirectory(kFALSE);
TH1F *hnew = new TH1F("hnew","Precision pushing",30,-20.,10.);
TH1F *hold = new TH1F("hold","Precision pulling", 30,-20.,10.);
TH2F *hplotS = new TH2F("hplotS","Problematic points",100,-dl[0],dl[0],100,-dl[1],dl[1]);
gStyle->SetOptStat(111111);
TGeoNode *node = 0;
Long_t igen=0;
Long_t itry=0;
Long_t n100 = ntracks/100;
Double_t rad = TMath::Sqrt(dl[0]*dl[0]+dl[1]*dl[1]);
printf("Random box : %f, %f, %f, %f, %f, %f\n", ori[0], ori[1], ori[2], dl[0], dl[1], dl[2]);
printf("Start... %i points\n", ntracks);
if (!fTimer) fTimer = new TStopwatch();
fTimer->Reset();
fTimer->Start();
while (igen<ntracks) {
Double_t phi1 = TMath::TwoPi()*gRandom->Rndm();
Double_t r = rad*gRandom->Rndm();
xyz[0] = ori[0] + r*TMath::Cos(phi1);
xyz[1] = ori[1] + r*TMath::Sin(phi1);
Double_t z = (1.-2.*gRandom->Rndm());
xyz[2] = ori[2]+dl[2]*z*TMath::Abs(z);
++itry;
fGeoManager->SetCurrentPoint(xyz);
node = fGeoManager->FindNode();
if (!node || node==fGeoManager->GetTopNode()) continue;
++igen;
if (n100 && !(igen%n100))
OpProgress("Sampling progress:",igen, ntracks, fTimer);
Double_t cost = 1.-2.*gRandom->Rndm();
Double_t sint = TMath::Sqrt((1.+cost)*(1.-cost));
Double_t phi = TMath::TwoPi()*gRandom->Rndm();
dir[0] = sint * TMath::Cos(phi);
dir[1] = sint * TMath::Sin(phi);
dir[2] = cost;
fGeoManager->SetCurrentDirection(dir);
fGeoManager->FindNextBoundary();
Double_t step = fGeoManager->GetStep();
relp = 1.e-21;
for(Int_t i=0; i<30; ++i) {
relp *=10.;
for(Int_t j=0; j<3; ++j) nxyz[j]=xyz[j]+step*(1.+relp)*dir[j];
if(!fGeoManager->IsSameLocation(nxyz[0],nxyz[1],nxyz[2])) {
hnew->Fill(i-20.);
if(i>15) {
const Double_t* norm = fGeoManager->FindNormal();
strcpy(path,fGeoManager->GetPath());
Double_t dotp = norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2];
printf("Forward error i=%d p=%5.4f %5.4f %5.4f s=%5.4f dot=%5.4f path=%s\n",
i,xyz[0],xyz[1],xyz[2],step,dotp,path);
hplotS->Fill(xyz[0],xyz[1],(Double_t)i);
strcpy(cdir,"Forward");
bug->Fill();
}
break;
}
}
relp = -1.e-21;
for(Int_t i=0; i<30; ++i) {
relp *=10.;
for(Int_t j=0; j<3; ++j) nxyz[j]=xyz[j]+step*(1.+relp)*dir[j];
if(fGeoManager->IsSameLocation(nxyz[0],nxyz[1],nxyz[2])) {
hold->Fill(i-20.);
if(i>15) {
const Double_t* norm = fGeoManager->FindNormal();
strcpy(path,fGeoManager->GetPath());
Double_t dotp = norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2];
printf("Backward error i=%d p=%5.4f %5.4f %5.4f s=%5.4f dot=%5.4f path=%s\n",
i,xyz[0],xyz[1],xyz[2],step,dotp,path);
strcpy(cdir,"Backward");
bug->Fill();
}
break;
}
}
}
fTimer->Stop();
printf("CPU time/point = %5.2emus: Real time/point = %5.2emus\n",
1000000.*fTimer->CpuTime()/itry,1000000.*fTimer->RealTime()/itry);
bug->Write();
delete bug;
bug=0;
delete f;
CheckBoundaryReference();
printf("Effic = %3.1f%%\n",(100.*igen)/itry);
TCanvas *c1 = new TCanvas("c1","Results",600,800);
c1->Divide(1,2);
c1->cd(1);
gPad->SetLogy();
hold->Draw();
c1->cd(2);
gPad->SetLogy();
hnew->Draw();
new TCanvas("c3","Plot",600,600);
hplotS->Draw("cont0");
}
void TGeoChecker::CheckBoundaryReference(Int_t icheck)
{
Double_t xyz[3];
Double_t nxyz[3];
Double_t dir[3];
Double_t lnext[3];
Double_t push;
Char_t path[1024];
Char_t cdir[10];
TFile *f=new TFile("geobugs.root","read");
TTree *bug=(TTree*)f->Get("bug");
bug->SetBranchAddress("pos",xyz);
bug->SetBranchAddress("dir",dir);
bug->SetBranchAddress("push",&push);
bug->SetBranchAddress("path",&path);
bug->SetBranchAddress("cdir",&cdir);
Int_t nentries = (Int_t)bug->GetEntries();
printf("nentries %d\n",nentries);
if (icheck<0) {
for (Int_t i=0;i<nentries;i++) {
bug->GetEntry(i);
printf("%-9s error push=%g p=%5.4f %5.4f %5.4f s=%5.4f dot=%5.4f path=%s\n",
cdir,push,xyz[0],xyz[1],xyz[2],1.,1.,path);
}
} else {
if (icheck>=nentries) return;
Int_t idebug = TGeoManager::GetVerboseLevel();
TGeoManager::SetVerboseLevel(5);
bug->GetEntry(icheck);
printf("%-9s error push=%g p=%5.4f %5.4f %5.4f s=%5.4f dot=%5.4f path=%s\n",
cdir,push,xyz[0],xyz[1],xyz[2],1.,1.,path);
fGeoManager->SetCurrentPoint(xyz);
fGeoManager->SetCurrentDirection(dir);
fGeoManager->FindNode();
TGeoNode *next = fGeoManager->FindNextBoundary();
Double_t step = fGeoManager->GetStep();
for (Int_t j=0; j<3; j++) nxyz[j]=xyz[j]+step*(1.+0.1*push)*dir[j];
Bool_t change = !fGeoManager->IsSameLocation(nxyz[0],nxyz[1],nxyz[2]);
printf("step=%g in: %s\n", step, fGeoManager->GetPath());
printf(" -> next = %s push=%g change=%d\n", next->GetName(),push, (UInt_t)change);
next->GetVolume()->InspectShape();
next->GetVolume()->DrawOnly();
if (next != fGeoManager->GetCurrentNode()) {
Int_t index1 = fGeoManager->GetCurrentVolume()->GetIndex(next);
if (index1>=0) fGeoManager->CdDown(index1);
}
TPolyMarker3D *pm = new TPolyMarker3D();
fGeoManager->MasterToLocal(xyz, lnext);
pm->SetNextPoint(lnext[0], lnext[1], lnext[2]);
pm->SetMarkerStyle(2);
pm->SetMarkerSize(0.2);
pm->SetMarkerColor(kRed);
pm->Draw("SAME");
TPolyMarker3D *pm1 = new TPolyMarker3D();
for (Int_t j=0; j<3; j++) nxyz[j]=xyz[j]+step*dir[j];
fGeoManager->MasterToLocal(nxyz, lnext);
pm1->SetNextPoint(lnext[0], lnext[1], lnext[2]);
pm1->SetMarkerStyle(2);
pm1->SetMarkerSize(0.2);
pm1->SetMarkerColor(kYellow);
pm1->Draw("SAME");
TGeoManager::SetVerboseLevel(idebug);
}
delete bug;
delete f;
}
void TGeoChecker::CheckGeometryFull(Bool_t checkoverlaps, Bool_t checkcrossings, Int_t ntracks, const Double_t *vertex)
{
Int_t nuid = fGeoManager->GetListOfUVolumes()->GetEntries();
if (!fTimer) fTimer = new TStopwatch();
Int_t i;
Double_t value;
fFlags = new Bool_t[nuid];
memset(fFlags, 0, nuid*sizeof(Bool_t));
TGeoVolume *vol;
TCanvas *c = new TCanvas("overlaps", "Overlaps by sampling", 800,800);
new TRandom3();
if (checkoverlaps) {
printf("====================================================================\n");
printf("STAGE 1: Overlap checking by sampling within 10 microns\n");
printf("====================================================================\n");
fGeoManager->CheckOverlaps(0.001, "s");
printf("====================================================================\n");
printf("STAGE 2: Global overlap/extrusion checking within 10 microns\n");
printf("====================================================================\n");
fGeoManager->CheckOverlaps(0.001);
}
if (!checkcrossings) {
delete [] fFlags;
fFlags = 0;
delete c;
return;
}
fVal1 = new Double_t[nuid];
fVal2 = new Double_t[nuid];
memset(fVal1, 0, nuid*sizeof(Double_t));
memset(fVal2, 0, nuid*sizeof(Double_t));
printf("====================================================================\n");
printf("STAGE 3: Propagating %i tracks starting from vertex\n and conting number of boundary crossings...\n", ntracks);
printf("====================================================================\n");
Int_t nbound = 0;
Double_t theta, phi;
Double_t point[3], dir[3];
memset(point, 0, 3*sizeof(Double_t));
if (vertex) memcpy(point, vertex, 3*sizeof(Double_t));
fTimer->Reset();
fTimer->Start();
for (i=0; i<ntracks; i++) {
phi = 2.*TMath::Pi()*gRandom->Rndm();
theta= TMath::ACos(1.-2.*gRandom->Rndm());
dir[0]=TMath::Sin(theta)*TMath::Cos(phi);
dir[1]=TMath::Sin(theta)*TMath::Sin(phi);
dir[2]=TMath::Cos(theta);
if ((i%100)==0) OpProgress("Transporting tracks",i, ntracks, fTimer);
nbound += PropagateInGeom(point,dir);
}
fTimer->Stop();
Double_t time1 = fTimer->CpuTime() *1.E6;
Double_t time2 = time1/ntracks;
Double_t time3 = time1/nbound;
OpProgress("Transporting tracks",ntracks, ntracks, fTimer, kTRUE);
printf("Time for crossing %i boundaries: %g [ms]\n", nbound, time1);
printf("Time per track for full geometry traversal: %g [ms], per crossing: %g [ms]\n", time2, time3);
printf("====================================================================\n");
printf("STAGE 4: How much navigation time per volume per next+safety call\n");
printf("====================================================================\n");
TGeoIterator next(fGeoManager->GetTopVolume());
TGeoNode*current;
TString path;
vol = fGeoManager->GetTopVolume();
memset(fFlags, 0, nuid*sizeof(Bool_t));
TStopwatch timer;
timer.Start();
i = 0;
char volname[30];
sprintf(volname, "Tracking %s", vol->GetName());
volname[15] = '\0';
OpProgress(volname,i++, nuid, &timer);
Score(vol, 1, TimingPerVolume(vol));
while ((current=next())) {
vol = current->GetVolume();
Int_t uid = vol->GetNumber();
if (fFlags[uid]) continue;
fFlags[uid] = kTRUE;
next.GetPath(path);
fGeoManager->cd(path.Data());
sprintf(volname, "Tracking %s", vol->GetName());
volname[15] = '\0';
OpProgress(volname,i++, nuid, &timer);
Score(vol,1,TimingPerVolume(vol));
}
OpProgress("STAGE 4 completed",i, nuid, &timer, kTRUE);
Double_t time_tot_pertrack = 0.;
TCanvas *c1 = new TCanvas("c2","ncrossings",10,10,900,500);
c1->SetGrid();
c1->SetTopMargin(0.15);
TFile *f = new TFile("statistics.root", "RECREATE");
TH1F *h = new TH1F("h","number of boundary crossings per volume",3,0,3);
h->SetStats(0);
h->SetFillColor(38);
h->SetBit(TH1::kCanRebin);
memset(fFlags, 0, nuid*sizeof(Bool_t));
for (i=0; i<nuid; i++) {
vol = fGeoManager->GetVolume(i);
if (!vol->GetNdaughters()) continue;
time_tot_pertrack += fVal1[i]*fVal2[i];
h->Fill(vol->GetName(), (Int_t)fVal1[i]);
}
time_tot_pertrack /= ntracks;
h->LabelsDeflate();
h->LabelsOption(">","X");
h->Draw();
TCanvas *c2 = new TCanvas("c3","time spent per volume in navigation",10,10,900,500);
c2->SetGrid();
c2->SetTopMargin(0.15);
TH2F *h2 = new TH2F("h2", "time per FNB call vs. ndaughters", 100, 0,100,100,0,15);
h2->SetStats(0);
h2->SetMarkerStyle(2);
TH1F *h1 = new TH1F("h1","percent of time spent per volume",3,0,3);
h1->SetStats(0);
h1->SetFillColor(38);
h1->SetBit(TH1::kCanRebin);
for (i=0; i<nuid; i++) {
vol = fGeoManager->GetVolume(i);
if (!vol->GetNdaughters()) continue;
value = fVal1[i]*fVal2[i]/ntracks/time_tot_pertrack;
h1->Fill(vol->GetName(), value);
h2->Fill(vol->GetNdaughters(), fVal2[i]);
}
h1->LabelsDeflate();
h1->LabelsOption(">","X");
h1->Draw();
TCanvas *c3 = new TCanvas("c4","timing vs. ndaughters",10,10,900,500);
c3->SetGrid();
c3->SetTopMargin(0.15);
h2->Draw();
f->Write();
delete [] fFlags;
fFlags = 0;
delete [] fVal1;
fVal1 = 0;
delete [] fVal2;
fVal2 = 0;
delete fTimer;
fTimer = 0;
delete c;
}
Int_t TGeoChecker::PropagateInGeom(Double_t *start, Double_t *dir)
{
fGeoManager->InitTrack(start, dir);
TGeoNode *current = 0;
Int_t nzero = 0;
Int_t nhits = 0;
while (!fGeoManager->IsOutside()) {
current = fGeoManager->FindNextBoundaryAndStep(TGeoShape::Big(), kFALSE);
if (!current || fGeoManager->IsOutside()) return nhits;
Double_t step = fGeoManager->GetStep();
if (step<2.*TGeoShape::Tolerance()) {
nzero++;
continue;
}
else nzero = 0;
if (nzero>3) {
printf("Error in trying to cross boundary of %s\n", current->GetName());
return nhits;
}
nhits++;
TGeoVolume *vol = current->GetVolume();
Score(vol,0,1.);
Int_t iup = 1;
TGeoNode *mother = fGeoManager->GetMother(iup++);
while (mother && mother->GetVolume()->IsAssembly()) {
Score(mother->GetVolume(), 0, 1.);
mother = fGeoManager->GetMother(iup++);
}
}
return nhits;
}
void TGeoChecker::Score(TGeoVolume *vol, Int_t ifield, Double_t value)
{
Int_t uid = vol->GetNumber();
switch (ifield) {
case 0:
fVal1[uid] += value;
break;
case 1:
fVal2[uid] += value;
}
}
void TGeoChecker::SetNmeshPoints(Int_t npoints) {
fNmeshPoints = npoints;
if (npoints<1000) {
Error("SetNmeshPoints", "Cannot allow less than 1000 points for checking - set to 1000");
fNmeshPoints = 1000;
}
}
Double_t TGeoChecker::TimingPerVolume(TGeoVolume *vol)
{
fTimer->Reset();
const TGeoShape *shape = vol->GetShape();
TGeoBBox *box = (TGeoBBox *)shape;
Double_t dx = box->GetDX();
Double_t dy = box->GetDY();
Double_t dz = box->GetDZ();
Double_t ox = (box->GetOrigin())[0];
Double_t oy = (box->GetOrigin())[1];
Double_t oz = (box->GetOrigin())[2];
Double_t point[3], dir[3], lpt[3], ldir[3];
Double_t pstep = 0.;
pstep = TMath::Max(pstep,dz);
Double_t theta, phi;
Int_t idaughter;
fTimer->Start();
Double_t dist;
Bool_t inside;
for (Int_t i=0; i<1000000; i++) {
lpt[0] = ox-dx+2*dx*gRandom->Rndm();
lpt[1] = oy-dy+2*dy*gRandom->Rndm();
lpt[2] = oz-dz+2*dz*gRandom->Rndm();
fGeoManager->GetCurrentMatrix()->LocalToMaster(lpt,point);
fGeoManager->SetCurrentPoint(point[0],point[1],point[2]);
phi = 2*TMath::Pi()*gRandom->Rndm();
theta= TMath::ACos(1.-2.*gRandom->Rndm());
ldir[0]=TMath::Sin(theta)*TMath::Cos(phi);
ldir[1]=TMath::Sin(theta)*TMath::Sin(phi);
ldir[2]=TMath::Cos(theta);
fGeoManager->GetCurrentMatrix()->LocalToMasterVect(ldir,dir);
fGeoManager->SetCurrentDirection(dir);
fGeoManager->SetStep(pstep);
fGeoManager->ResetState();
inside = kTRUE;
dist = TGeoShape::Big();
if (!vol->IsAssembly()) {
inside = vol->Contains(lpt);
if (!inside) {
dist = vol->GetShape()->DistFromOutside(lpt,ldir,3,pstep);
} else {
vol->GetShape()->DistFromInside(lpt,ldir,3,pstep);
}
if (!vol->GetNdaughters()) vol->GetShape()->Safety(lpt, inside);
}
if (vol->GetNdaughters()) {
fGeoManager->Safety();
fGeoManager->FindNextDaughterBoundary(point,dir,idaughter,kFALSE);
}
}
fTimer->Stop();
Double_t time_per_track = fTimer->CpuTime();
Int_t uid = vol->GetNumber();
Int_t ncrossings = (Int_t)fVal1[uid];
if (!vol->GetNdaughters())
printf("Time for volume %s (shape=%s): %g [ms] ndaughters=%d ncross=%d\n", vol->GetName(), vol->GetShape()->GetName(), time_per_track, vol->GetNdaughters(), ncrossings);
else
printf("Time for volume %s (assemb=%d): %g [ms] ndaughters=%d ncross=%d\n", vol->GetName(), vol->IsAssembly(), time_per_track, vol->GetNdaughters(), ncrossings);
return time_per_track;
}
void TGeoChecker::CheckGeometry(Int_t nrays, Double_t startx, Double_t starty, Double_t startz) const
{
Int_t i, j;
Double_t start[3], end[3];
Double_t dir[3];
Double_t dummy[3];
Double_t eps = 0.;
Double_t *array1 = new Double_t[3*1000];
Double_t *array2 = new Double_t[3*1000];
TObjArray *pma = new TObjArray();
TPolyMarker3D *pm;
pm = new TPolyMarker3D();
pm->SetMarkerColor(2);
pm->SetMarkerStyle(8);
pm->SetMarkerSize(0.4);
pma->AddAt(pm, 0);
pm = new TPolyMarker3D();
pm->SetMarkerColor(4);
pm->SetMarkerStyle(8);
pm->SetMarkerSize(0.4);
pma->AddAt(pm, 1);
pm = new TPolyMarker3D();
pm->SetMarkerColor(6);
pm->SetMarkerStyle(8);
pm->SetMarkerSize(0.4);
pma->AddAt(pm, 2);
Int_t nelem1, nelem2;
Int_t dim1=1000, dim2=1000;
if ((startx==0) && (starty==0) && (startz==0)) eps=1E-3;
start[0] = startx+eps;
start[1] = starty+eps;
start[2] = startz+eps;
Int_t n10=nrays/10;
Double_t theta,phi;
Double_t dw, dwmin, dx, dy, dz;
Int_t ist1, ist2, ifound;
for (i=0; i<nrays; i++) {
if (n10) {
if ((i%n10) == 0) printf("%i percent\n", Int_t(100*i/nrays));
}
phi = 2*TMath::Pi()*gRandom->Rndm();
theta= TMath::ACos(1.-2.*gRandom->Rndm());
dir[0]=TMath::Sin(theta)*TMath::Cos(phi);
dir[1]=TMath::Sin(theta)*TMath::Sin(phi);
dir[2]=TMath::Cos(theta);
nelem1=nelem2=0;
ShootRay(&start[0], dir[0], dir[1], dir[2], array1, nelem1, dim1);
if (!nelem1) continue;
memcpy(&end[0], &array1[3*(nelem1-1)], 3*sizeof(Double_t));
ShootRay(&end[0], -dir[0], -dir[1], -dir[2], array2, nelem2, dim2, &start[0]);
if (!nelem2) {
printf("#### NOTHING BACK ###########################\n");
for (j=0; j<nelem1; j++) {
pm = (TPolyMarker3D*)pma->At(0);
pm->SetNextPoint(array1[3*j], array1[3*j+1], array1[3*j+2]);
}
continue;
}
Int_t k=nelem2>>1;
for (j=0; j<k; j++) {
memcpy(&dummy[0], &array2[3*j], 3*sizeof(Double_t));
memcpy(&array2[3*j], &array2[3*(nelem2-1-j)], 3*sizeof(Double_t));
memcpy(&array2[3*(nelem2-1-j)], &dummy[0], 3*sizeof(Double_t));
}
if (nelem1!=nelem2) printf("### DIFFERENT SIZES : nelem1=%i nelem2=%i ##########\n", nelem1, nelem2);
ist1 = ist2 = 0;
dx = array1[3*ist1]-array2[3*ist2];
dy = array1[3*ist1+1]-array2[3*ist2+1];
dz = array1[3*ist1+2]-array2[3*ist2+2];
dw = dx*dir[0]+dy*dir[1]+dz*dir[2];
fGeoManager->SetCurrentPoint(&array1[3*ist1]);
fGeoManager->FindNode();
if (TMath::Abs(dw)<1E-4) {
ist2++;
} else {
printf("### NOT MATCHING %i f:(%f, %f, %f) b:(%f %f %f) DCLOSE=%f\n", ist2, array1[3*ist1], array1[3*ist1+1], array1[3*ist1+2], array2[3*ist2], array2[3*ist2+1], array2[3*ist2+2],dw);
pm = (TPolyMarker3D*)pma->At(0);
pm->SetNextPoint(array2[3*ist2], array2[3*ist2+1], array2[3*ist2+2]);
if (dw<0) {
} else {
ist2++;
}
}
while ((ist1<nelem1-1) && (ist2<nelem2)) {
fGeoManager->SetCurrentPoint(&array1[3*ist1+3]);
fGeoManager->FindNode();
dx = array1[3*ist1+3]-array1[3*ist1];
dy = array1[3*ist1+4]-array1[3*ist1+1];
dz = array1[3*ist1+5]-array1[3*ist1+2];
dwmin = dx+dir[0]+dy*dir[1]+dz*dir[2];
while (ist2<nelem2) {
ifound = 0;
dx = array2[3*ist2]-array1[3*ist1];
dy = array2[3*ist2+1]-array1[3*ist1+1];
dz = array2[3*ist2+2]-array1[3*ist1+2];
dw = dx+dir[0]+dy*dir[1]+dz*dir[2];
if (TMath::Abs(dw-dwmin)<1E-4) {
ist1++;
ist2++;
break;
}
if (dw<dwmin) {
ifound++;
dw = dwmin-dw;
if (dw<1E-4) {
ist2++;
ist1++;
break;
} else {
fGeoManager->SetCurrentPoint(&array2[3*ist2]);
fGeoManager->FindNode();
pm = (TPolyMarker3D*)pma->At(2);
pm->SetNextPoint(array2[3*ist2], array2[3*ist2+1], array2[3*ist2+2]);
printf("### EXTRA BOUNDARY %i : %s found at DCLOSE=%f\n", ist2, fGeoManager->GetPath(), dw);
ist2++;
continue;
}
} else {
if (!ifound) {
fGeoManager->SetCurrentPoint(&array1[3*ist1+3]);
fGeoManager->FindNode();
pm = (TPolyMarker3D*)pma->At(1);
pm->SetNextPoint(array2[3*ist1+3], array2[3*ist1+4], array2[3*ist1+5]);
printf("### BOUNDARY MISSED BACK #########################\n");
ist1++;
break;
} else {
ist1++;
break;
}
}
}
}
}
pm = (TPolyMarker3D*)pma->At(0);
pm->Draw("SAME");
pm = (TPolyMarker3D*)pma->At(1);
pm->Draw("SAME");
pm = (TPolyMarker3D*)pma->At(2);
pm->Draw("SAME");
if (gPad) {
gPad->Modified();
gPad->Update();
}
delete [] array1;
delete [] array2;
}
void TGeoChecker::CleanPoints(Double_t *points, Int_t &numPoints) const
{
Int_t ipoint = 0;
Int_t j, k=0;
Double_t rsq;
for (Int_t i=0; i<numPoints; i++) {
j = 3*i;
rsq = points[j]*points[j]+points[j+1]*points[j+1];
if (rsq < 1.e-10) continue;
points[k] = points[j];
points[k+1] = points[j+1];
points[k+2] = points[j+2];
ipoint++;
k = 3*ipoint;
}
numPoints = ipoint;
}
TGeoOverlap *TGeoChecker::MakeCheckOverlap(const char *name, TGeoVolume *vol1, TGeoVolume *vol2, TGeoMatrix *mat1, TGeoMatrix *mat2, Bool_t isovlp, Double_t ovlp)
{
TGeoOverlap *nodeovlp = 0;
Int_t numPoints1 = fBuff1->NbPnts();
Int_t numSegs1 = fBuff1->NbSegs();
Int_t numPols1 = fBuff1->NbPols();
Int_t numPoints2 = fBuff2->NbPnts();
Int_t numSegs2 = fBuff2->NbSegs();
Int_t numPols2 = fBuff2->NbPols();
Int_t ip;
Bool_t extrude, isextrusion, isoverlapping;
Double_t *points1 = fBuff1->fPnts;
Double_t *points2 = fBuff2->fPnts;
Double_t local[3], local1[3];
Double_t point[3];
Double_t safety = TGeoShape::Big();
if (vol1->IsAssembly() || vol2->IsAssembly()) return nodeovlp;
TGeoShape *shape1 = vol1->GetShape();
TGeoShape *shape2 = vol2->GetShape();
OpProgress("refresh", 0,0,NULL,kFALSE,kTRUE);
shape1->GetMeshNumbers(numPoints1, numSegs1, numPols1);
if (!shape1->IsComposite() &&
fBuff1->fID != (TObject*)shape1) {
fBuff1->SetRawSizes(TMath::Max(numPoints1,fNmeshPoints), 3*TMath::Max(numPoints1,fNmeshPoints), 0, 0, 0, 0);
points1 = fBuff1->fPnts;
if (shape1->GetPointsOnSegments(fNmeshPoints, points1)) {
numPoints1 = fNmeshPoints;
} else {
shape1->SetPoints(points1);
}
fBuff1->fID = shape1;
}
shape2->GetMeshNumbers(numPoints2, numSegs2, numPols2);
if (!shape2->IsComposite() &&
fBuff2->fID != (TObject*)shape2) {
fBuff2->SetRawSizes(TMath::Max(numPoints2,fNmeshPoints), 3*TMath::Max(numPoints2,fNmeshPoints), 0, 0, 0,0);
points2 = fBuff2->fPnts;
if (shape2->GetPointsOnSegments(fNmeshPoints, points2)) {
numPoints2 = fNmeshPoints;
} else {
shape2->SetPoints(points2);
}
fBuff2->fID = shape2;
}
if (!isovlp) {
isextrusion=kFALSE;
if (!shape2->IsComposite()) {
for (ip=0; ip<numPoints2; ip++) {
memcpy(local, &points2[3*ip], 3*sizeof(Double_t));
if (local[0]<1e-10 && local[1]<1e-10) continue;
mat2->LocalToMaster(local, point);
mat1->MasterToLocal(point, local);
extrude = !shape1->Contains(local);
if (extrude) {
safety = shape1->Safety(local, kFALSE);
if (safety<ovlp) extrude=kFALSE;
}
if (extrude) {
if (!isextrusion) {
isextrusion = kTRUE;
nodeovlp = new TGeoOverlap(name, vol1, vol2, mat1,mat2,kFALSE,safety);
nodeovlp->SetNextPoint(point[0],point[1],point[2]);
fGeoManager->AddOverlap(nodeovlp);
} else {
if (safety>nodeovlp->GetOverlap()) nodeovlp->SetOverlap(safety);
nodeovlp->SetNextPoint(point[0],point[1],point[2]);
}
}
}
}
if (!shape1->IsComposite()) {
for (ip=0; ip<numPoints1; ip++) {
memcpy(local, &points1[3*ip], 3*sizeof(Double_t));
if (local[0]<1e-10 && local[1]<1e-10) continue;
mat1->LocalToMaster(local, point);
mat2->MasterToLocal(point, local1);
extrude = shape2->Contains(local1);
if (extrude) {
safety = shape1->Safety(local,kTRUE);
if (safety>1E-6) {
extrude = kFALSE;
} else {
safety = shape2->Safety(local1,kTRUE);
if (safety<ovlp) extrude=kFALSE;
}
}
if (extrude) {
if (!isextrusion) {
isextrusion = kTRUE;
nodeovlp = new TGeoOverlap(name, vol1,vol2,mat1,mat2,kFALSE,safety);
nodeovlp->SetNextPoint(point[0],point[1],point[2]);
fGeoManager->AddOverlap(nodeovlp);
} else {
if (safety>nodeovlp->GetOverlap()) nodeovlp->SetOverlap(safety);
nodeovlp->SetNextPoint(point[0],point[1],point[2]);
}
}
}
}
return nodeovlp;
}
Bool_t overlap;
overlap = kFALSE;
isoverlapping = kFALSE;
if (!shape1->IsComposite()) {
for (ip=0; ip<numPoints1; ip++) {
memcpy(local, &points1[3*ip], 3*sizeof(Double_t));
if (local[0]<1e-10 && local[1]<1e-10) continue;
mat1->LocalToMaster(local, point);
mat2->MasterToLocal(point, local);
overlap = shape2->Contains(local);
if (overlap) {
safety = shape2->Safety(local, kTRUE);
if (safety<ovlp) overlap=kFALSE;
}
if (overlap) {
if (!isoverlapping) {
isoverlapping = kTRUE;
nodeovlp = new TGeoOverlap(name,vol1,vol2,mat1,mat2,kTRUE,safety);
nodeovlp->SetNextPoint(point[0],point[1],point[2]);
fGeoManager->AddOverlap(nodeovlp);
} else {
if (safety>nodeovlp->GetOverlap()) nodeovlp->SetOverlap(safety);
nodeovlp->SetNextPoint(point[0],point[1],point[2]);
}
}
}
}
if (!shape2->IsComposite()) {
for (ip=0; ip<numPoints2; ip++) {
memcpy(local, &points2[3*ip], 3*sizeof(Double_t));
if (local[0]<1e-10 && local[1]<1e-10) continue;
mat2->LocalToMaster(local, point);
mat1->MasterToLocal(point, local);
overlap = shape1->Contains(local);
if (overlap) {
safety = shape1->Safety(local, kTRUE);
if (safety<ovlp) overlap=kFALSE;
}
if (overlap) {
if (!isoverlapping) {
isoverlapping = kTRUE;
nodeovlp = new TGeoOverlap(name,vol1,vol2,mat1,mat2,kTRUE,safety);
nodeovlp->SetNextPoint(point[0],point[1],point[2]);
fGeoManager->AddOverlap(nodeovlp);
} else {
if (safety>nodeovlp->GetOverlap()) nodeovlp->SetOverlap(safety);
nodeovlp->SetNextPoint(point[0],point[1],point[2]);
}
}
}
}
return nodeovlp;
}
void TGeoChecker::CheckOverlapsBySampling(TGeoVolume *vol, Double_t , Int_t npoints) const
{
Int_t nd = vol->GetNdaughters();
if (nd<2) return;
TGeoVoxelFinder *voxels = vol->GetVoxels();
if (!voxels) return;
if (voxels->NeedRebuild()) {
voxels->Voxelize();
vol->FindOverlaps();
}
TGeoBBox *box = (TGeoBBox*)vol->GetShape();
TGeoShape *shape;
TGeoNode *node;
Double_t dx = box->GetDX();
Double_t dy = box->GetDY();
Double_t dz = box->GetDZ();
Double_t pt[3];
Double_t local[3];
Int_t *check_list = 0;
Int_t ncheck = 0;
const Double_t *orig = box->GetOrigin();
Int_t ipoint = 0;
Int_t itry = 0;
Int_t iovlp = 0;
Int_t id=0, id0=0, id1=0;
Bool_t in, incrt;
Double_t safe;
TString name1 = "";
TString name2 = "";
TGeoOverlap **flags = 0;
TGeoNode *node1, *node2;
Int_t novlps = 0;
TGeoHMatrix mat1, mat2;
if (!gRandom) new TRandom3();
while (ipoint < npoints) {
pt[0] = orig[0] - dx + 2.*dx*gRandom->Rndm();
pt[1] = orig[1] - dy + 2.*dy*gRandom->Rndm();
pt[2] = orig[2] - dz + 2.*dz*gRandom->Rndm();
if (!vol->Contains(pt)) {
itry++;
if (itry>10000 && !ipoint) {
Error("CheckOverlapsBySampling", "No point inside volume!!! - aborting");
break;
}
continue;
}
in = kFALSE;
ipoint++;
check_list = voxels->GetCheckList(pt, ncheck);
if (!check_list || ncheck<2) continue;
for (id=0; id<ncheck; id++) {
id0 = check_list[id];
node = vol->GetNode(id0);
if (node->IsOverlapping()) continue;
node->GetMatrix()->MasterToLocal(pt,local);
shape = node->GetVolume()->GetShape();
incrt = shape->Contains(local);
if (!incrt) continue;
if (!in) {
in = kTRUE;
id1 = id0;
continue;
}
safe = shape->Safety(local, kTRUE);
iovlp++;
if (!novlps) {
flags = new TGeoOverlap*[nd*nd];
memset(flags, 0, nd*nd*sizeof(TGeoOverlap*));
}
TGeoOverlap *nodeovlp = flags[nd*id1+id0];
if (!nodeovlp) {
novlps++;
node1 = vol->GetNode(id1);
name1 = node1->GetName();
mat1 = node1->GetMatrix();
Int_t cindex = node1->GetVolume()->GetCurrentNodeIndex();
while (cindex >= 0) {
node1 = node1->GetVolume()->GetNode(cindex);
name1 += Form("/%s", node1->GetName());
mat1.Multiply(node1->GetMatrix());
cindex = node1->GetVolume()->GetCurrentNodeIndex();
}
node2 = vol->GetNode(id0);
name2 = node2->GetName();
mat2 = node2->GetMatrix();
cindex = node2->GetVolume()->GetCurrentNodeIndex();
while (cindex >= 0) {
node2 = node2->GetVolume()->GetNode(cindex);
name2 += Form("/%s", node2->GetName());
mat2.Multiply(node2->GetMatrix());
cindex = node2->GetVolume()->GetCurrentNodeIndex();
}
nodeovlp = new TGeoOverlap(Form("Volume %s: node %s overlapping %s",
vol->GetName(), name1.Data(), name2.Data()), node1->GetVolume(),node2->GetVolume(),
&mat1,&mat2, kTRUE, safe);
flags[nd*id1+id0] = nodeovlp;
fGeoManager->AddOverlap(nodeovlp);
}
if (nodeovlp->GetPolyMarker()->GetN()<100) nodeovlp->SetNextPoint(pt[0],pt[1],pt[2]);
if (nodeovlp->GetOverlap()<safe) nodeovlp->SetOverlap(safe);
}
}
if (flags) delete [] flags;
if (!novlps) return;
Double_t capacity = vol->GetShape()->Capacity();
capacity *= Double_t(iovlp)/Double_t(npoints);
Double_t err = 1./TMath::Sqrt(Double_t(iovlp));
Info("CheckOverlapsBySampling", "#Found %d overlaps adding-up to %g +/- %g [cm3] for daughters of %s",
novlps, capacity, err*capacity, vol->GetName());
}
Int_t TGeoChecker::NChecksPerVolume(TGeoVolume *vol)
{
if (vol->GetFinder()) return 0;
UInt_t nd = vol->GetNdaughters();
if (!nd) return 0;
Bool_t is_assembly = vol->IsAssembly();
TGeoIterator next1(vol);
TGeoIterator next2(vol);
Int_t nchecks = 0;
TGeoNode *node;
UInt_t id;
if (!is_assembly) {
while ((node=next1())) {
if (node->IsOverlapping()) {
next1.Skip();
continue;
}
if (!node->GetVolume()->IsAssembly()) {
nchecks++;
next1.Skip();
}
}
}
if (nd<2) return nchecks;
TGeoVoxelFinder *vox = vol->GetVoxels();
if (!vox) return nchecks;
TGeoNode *node1, *node01, *node02;
Int_t novlp;
Int_t *ovlps;
Int_t ko;
UInt_t io;
for (id=0; id<nd; id++) {
node01 = vol->GetNode(id);
if (node01->IsOverlapping()) continue;
vox->FindOverlaps(id);
ovlps = node01->GetOverlaps(novlp);
if (!ovlps) continue;
for (ko=0; ko<novlp; ko++) {
io = ovlps[ko];
if (io<=id) continue;
node02 = vol->GetNode(io);
if (node02->IsOverlapping()) continue;
if (node01->GetVolume()->IsAssembly()) {
next1.Reset(node01->GetVolume());
while ((node=next1())) {
if (!node->GetVolume()->IsAssembly()) {
if (node02->GetVolume()->IsAssembly()) {
next2.Reset(node02->GetVolume());
while ((node1=next2())) {
if (!node1->GetVolume()->IsAssembly()) {
nchecks++;
next2.Skip();
}
}
} else {
nchecks++;
}
next1.Skip();
}
}
} else {
if (node02->GetVolume()->IsAssembly()) {
next2.Reset(node02->GetVolume());
while ((node1=next2())) {
if (!node1->GetVolume()->IsAssembly()) {
nchecks++;
next2.Skip();
}
}
} else {
nchecks++;
}
}
}
node01->SetOverlaps(0,0);
}
return nchecks;
}
void TGeoChecker::CheckOverlaps(const TGeoVolume *vol, Double_t ovlp, Option_t *option)
{
if (vol->GetFinder()) return;
UInt_t nd = vol->GetNdaughters();
if (!nd) return;
TGeoShape::SetTransform(gGeoIdentity);
fNchecks = NChecksPerVolume((TGeoVolume*)vol);
Bool_t sampling = kFALSE;
TString opt(option);
opt.ToLower();
if (opt.Contains("s")) sampling = kTRUE;
if (opt.Contains("f")) fFullCheck = kTRUE;
else fFullCheck = kFALSE;
if (sampling) {
opt = opt.Strip(TString::kLeading, 's');
Int_t npoints = atoi(opt.Data());
if (!npoints) npoints = 1000000;
CheckOverlapsBySampling((TGeoVolume*)vol, ovlp, npoints);
return;
}
Bool_t is_assembly = vol->IsAssembly();
TGeoIterator next1((TGeoVolume*)vol);
TGeoIterator next2((TGeoVolume*)vol);
TString path;
TGeoNode * node, *nodecheck;
TGeoChecker *checker = (TGeoChecker*)this;
TGeoOverlap *nodeovlp = 0;
UInt_t id;
Int_t level;
if (!is_assembly) {
while ((node=next1())) {
if (node->IsOverlapping()) {
next1.Skip();
continue;
}
if (!node->GetVolume()->IsAssembly()) {
if (fSelectedNode) {
if ((fSelectedNode != node) && (!fSelectedNode->GetVolume()->IsAssembly())) {
next1.Skip();
continue;
}
if (node != fSelectedNode) {
level = next1.GetLevel();
while ((nodecheck=next1.GetNode(level--))) {
if (nodecheck == fSelectedNode) break;
}
if (!nodecheck) {
next1.Skip();
continue;
}
}
}
next1.GetPath(path);
nodeovlp = checker->MakeCheckOverlap(Form("%s extruded by: %s", vol->GetName(),path.Data()),
(TGeoVolume*)vol,node->GetVolume(),gGeoIdentity,(TGeoMatrix*)next1.GetCurrentMatrix(),kFALSE,ovlp);
next1.Skip();
}
}
}
if (nd<2) return;
TGeoVoxelFinder *vox = vol->GetVoxels();
if (!vox) {
Warning("CheckOverlaps", "Volume %s with %i daughters but not voxelized", vol->GetName(),nd);
return;
}
if (vox->NeedRebuild()) {
vox->Voxelize();
vol->FindOverlaps();
}
TGeoNode *node1, *node01, *node02;
TGeoHMatrix hmat1, hmat2;
TString path1;
Int_t novlp;
Int_t *ovlps;
Int_t ko;
UInt_t io;
for (id=0; id<nd; id++) {
node01 = vol->GetNode(id);
if (node01->IsOverlapping()) continue;
vox->FindOverlaps(id);
ovlps = node01->GetOverlaps(novlp);
if (!ovlps) continue;
next1.SetTopName(node01->GetName());
path = node01->GetName();
for (ko=0; ko<novlp; ko++) {
io = ovlps[ko];
if (io<=id) continue;
node02 = vol->GetNode(io);
if (node02->IsOverlapping()) continue;
next2.SetTopName(node02->GetName());
path1 = node02->GetName();
if (node01->GetVolume()->IsAssembly()) {
next1.Reset(node01->GetVolume());
while ((node=next1())) {
if (!node->GetVolume()->IsAssembly()) {
next1.GetPath(path);
hmat1 = node01->GetMatrix();
hmat1 *= *next1.GetCurrentMatrix();
if (node02->GetVolume()->IsAssembly()) {
next2.Reset(node02->GetVolume());
while ((node1=next2())) {
if (!node1->GetVolume()->IsAssembly()) {
if (fSelectedNode) {
if ((fSelectedNode != node) && (fSelectedNode != node1) && (!fSelectedNode->GetVolume()->IsAssembly())) {
next2.Skip();
continue;
}
if ((fSelectedNode != node1) && (fSelectedNode != node)) {
level = next2.GetLevel();
while ((nodecheck=next2.GetNode(level--))) {
if (nodecheck == fSelectedNode) break;
}
if (node02 == fSelectedNode) nodecheck = node02;
if (!nodecheck) {
level = next1.GetLevel();
while ((nodecheck=next1.GetNode(level--))) {
if (nodecheck == fSelectedNode) break;
}
}
if (node01 == fSelectedNode) nodecheck = node01;
if (!nodecheck) {
next2.Skip();
continue;
}
}
}
next2.GetPath(path1);
hmat2 = node02->GetMatrix();
hmat2 *= *next2.GetCurrentMatrix();
nodeovlp = checker->MakeCheckOverlap(Form("%s/%s overlapping %s/%s", vol->GetName(),path.Data(),vol->GetName(),path1.Data()),
node->GetVolume(),node1->GetVolume(),&hmat1,&hmat2,kTRUE,ovlp);
next2.Skip();
}
}
} else {
if (fSelectedNode) {
if ((fSelectedNode != node) && (fSelectedNode != node02) && (!fSelectedNode->GetVolume()->IsAssembly())) {
next1.Skip();
continue;
}
if ((fSelectedNode != node) && (fSelectedNode != node02)) {
level = next1.GetLevel();
while ((nodecheck=next1.GetNode(level--))) {
if (nodecheck == fSelectedNode) break;
}
if (node01 == fSelectedNode) nodecheck = node01;
if (!nodecheck) {
next1.Skip();
continue;
}
}
}
nodeovlp = checker->MakeCheckOverlap(Form("%s/%s overlapping %s/%s", vol->GetName(),path.Data(),vol->GetName(),path1.Data()),
node->GetVolume(),node02->GetVolume(),&hmat1,node02->GetMatrix(),kTRUE,ovlp);
}
next1.Skip();
}
}
} else {
if (node02->GetVolume()->IsAssembly()) {
next2.Reset(node02->GetVolume());
while ((node1=next2())) {
if (!node1->GetVolume()->IsAssembly()) {
if (fSelectedNode) {
if ((fSelectedNode != node1) && (fSelectedNode != node01) && (!fSelectedNode->GetVolume()->IsAssembly())) {
next2.Skip();
continue;
}
if ((fSelectedNode != node1) && (fSelectedNode != node01)) {
level = next2.GetLevel();
while ((nodecheck=next2.GetNode(level--))) {
if (nodecheck == fSelectedNode) break;
}
if (node02 == fSelectedNode) nodecheck = node02;
if (!nodecheck) {
next2.Skip();
continue;
}
}
}
next2.GetPath(path1);
hmat2 = node02->GetMatrix();
hmat2 *= *next2.GetCurrentMatrix();
nodeovlp = checker->MakeCheckOverlap(Form("%s/%s overlapping %s/%s", vol->GetName(),path.Data(),vol->GetName(),path1.Data()),
node01->GetVolume(),node1->GetVolume(),node01->GetMatrix(),&hmat2,kTRUE,ovlp);
next2.Skip();
}
}
} else {
if (fSelectedNode && (fSelectedNode != node01) && (fSelectedNode != node02)) continue;
nodeovlp = checker->MakeCheckOverlap(Form("%s/%s overlapping %s/%s", vol->GetName(),path.Data(),vol->GetName(),path1.Data()),
node01->GetVolume(),node02->GetVolume(),node01->GetMatrix(),node02->GetMatrix(),kTRUE,ovlp);
}
}
}
node01->SetOverlaps(0,0);
}
}
void TGeoChecker::PrintOverlaps() const
{
TIter next(fGeoManager->GetListOfOverlaps());
TGeoOverlap *ov;
printf("=== Overlaps for %s ===\n", fGeoManager->GetName());
while ((ov=(TGeoOverlap*)next())) ov->PrintInfo();
}
void TGeoChecker::CheckPoint(Double_t x, Double_t y, Double_t z, Option_t *)
{
Double_t point[3];
Double_t local[3];
point[0] = x;
point[1] = y;
point[2] = z;
TGeoVolume *vol = fGeoManager->GetTopVolume();
if (fVsafe) {
TGeoNode *old = fVsafe->GetNode("SAFETY_1");
if (old) fVsafe->GetNodes()->RemoveAt(vol->GetNdaughters()-1);
}
TGeoNode *node = fGeoManager->FindNode(point[0], point[1], point[2]);
fGeoManager->MasterToLocal(point, local);
printf("=== Check current point : (%g, %g, %g) ===\n", point[0], point[1], point[2]);
printf(" - path : %s\n", fGeoManager->GetPath());
if (node) vol = node->GetVolume();
Double_t close = fGeoManager->Safety();
printf("Safety radius : %f\n", close);
if (close>1E-4) {
TGeoVolume *sph = fGeoManager->MakeSphere("SAFETY", vol->GetMedium(), 0, close, 0,180,0,360);
sph->SetLineColor(2);
sph->SetLineStyle(3);
vol->AddNode(sph,1,new TGeoTranslation(local[0], local[1], local[2]));
fVsafe = vol;
}
TPolyMarker3D *pm = new TPolyMarker3D();
pm->SetMarkerColor(2);
pm->SetMarkerStyle(8);
pm->SetMarkerSize(0.5);
pm->SetNextPoint(local[0], local[1], local[2]);
if (vol->GetNdaughters()<2) fGeoManager->SetTopVisible();
else fGeoManager->SetTopVisible(kFALSE);
fGeoManager->SetVisLevel(1);
if (!vol->IsVisible()) vol->SetVisibility(kTRUE);
vol->Draw();
pm->Draw("SAME");
gPad->Modified();
gPad->Update();
}
TH2F *TGeoChecker::LegoPlot(Int_t ntheta, Double_t themin, Double_t themax,
Int_t nphi, Double_t phimin, Double_t phimax,
Double_t , Double_t , Option_t *option)
{
TH2F *hist = new TH2F("lego", option, nphi, phimin, phimax, ntheta, themin, themax);
Double_t degrad = TMath::Pi()/180.;
Double_t theta, phi, step, matprop, x;
Double_t start[3];
Double_t dir[3];
TGeoNode *startnode, *endnode;
Int_t i;
Int_t j;
Int_t ntot = ntheta * nphi;
Int_t n10 = ntot/10;
Int_t igen = 0, iloop=0;
printf("=== Lego plot sph. => nrays=%i\n", ntot);
for (i=1; i<=nphi; i++) {
for (j=1; j<=ntheta; j++) {
igen++;
if (n10) {
if ((igen%n10) == 0) printf("%i percent\n", Int_t(100*igen/ntot));
}
x = 0;
theta = hist->GetYaxis()->GetBinCenter(j);
phi = hist->GetXaxis()->GetBinCenter(i)+1E-3;
start[0] = start[1] = start[2] = 1E-3;
dir[0]=TMath::Sin(theta*degrad)*TMath::Cos(phi*degrad);
dir[1]=TMath::Sin(theta*degrad)*TMath::Sin(phi*degrad);
dir[2]=TMath::Cos(theta*degrad);
fGeoManager->InitTrack(&start[0], &dir[0]);
startnode = fGeoManager->GetCurrentNode();
if (fGeoManager->IsOutside()) startnode=0;
if (startnode) {
matprop = startnode->GetVolume()->GetMaterial()->GetRadLen();
} else {
matprop = 0.;
}
fGeoManager->FindNextBoundary();
endnode = fGeoManager->Step();
step = fGeoManager->GetStep();
while (step<1E10) {
iloop=0;
while (!fGeoManager->IsEntering()) {
iloop++;
fGeoManager->SetStep(1E-3);
step += 1E-3;
endnode = fGeoManager->Step();
}
if (iloop>1000) printf("%i steps\n", iloop);
if (matprop>0) {
x += step/matprop;
}
if (endnode==0 && step>1E10) break;
startnode = endnode;
if (startnode) {
matprop = startnode->GetVolume()->GetMaterial()->GetRadLen();
} else {
matprop = 0.;
}
fGeoManager->FindNextBoundary();
endnode = fGeoManager->Step();
step = fGeoManager->GetStep();
}
hist->Fill(phi, theta, x);
}
}
return hist;
}
void TGeoChecker::RandomPoints(TGeoVolume *vol, Int_t npoints, Option_t *option)
{
if (!vol) return;
gRandom = new TRandom3();
vol->VisibleDaughters(kTRUE);
vol->Draw();
TString opt = option;
opt.ToLower();
TObjArray *pm = new TObjArray(128);
TPolyMarker3D *marker = 0;
const TGeoShape *shape = vol->GetShape();
TGeoBBox *box = (TGeoBBox *)shape;
Double_t dx = box->GetDX();
Double_t dy = box->GetDY();
Double_t dz = box->GetDZ();
Double_t ox = (box->GetOrigin())[0];
Double_t oy = (box->GetOrigin())[1];
Double_t oz = (box->GetOrigin())[2];
Double_t *xyz = new Double_t[3];
printf("Random box : %f, %f, %f\n", dx, dy, dz);
TGeoNode *node = 0;
printf("Start... %i points\n", npoints);
Int_t i=0;
Int_t igen=0;
Int_t ic = 0;
Int_t n10 = npoints/10;
Double_t ratio=0;
while (igen<npoints) {
xyz[0] = ox-dx+2*dx*gRandom->Rndm();
xyz[1] = oy-dy+2*dy*gRandom->Rndm();
xyz[2] = oz-dz+2*dz*gRandom->Rndm();
fGeoManager->SetCurrentPoint(xyz);
igen++;
if (n10) {
if ((igen%n10) == 0) printf("%i percent\n", Int_t(100*igen/npoints));
}
node = fGeoManager->FindNode();
if (!node) continue;
if (!node->IsOnScreen()) continue;
if (opt.Contains("many") && !node->IsOverlapping()) continue;
if (opt.Contains("only") && node->IsOverlapping()) continue;
ic = node->GetColour();
if ((ic<0) || (ic>=128)) ic = 1;
marker = (TPolyMarker3D*)pm->At(ic);
if (!marker) {
marker = new TPolyMarker3D();
marker->SetMarkerColor(ic);
pm->AddAt(marker, ic);
}
marker->SetNextPoint(xyz[0], xyz[1], xyz[2]);
i++;
}
printf("Number of visible points : %i\n", i);
ratio = (Double_t)i/(Double_t)igen;
printf("efficiency : %g\n", ratio);
for (Int_t m=0; m<128; m++) {
marker = (TPolyMarker3D*)pm->At(m);
if (marker) marker->Draw("SAME");
}
fGeoManager->GetTopVolume()->VisibleDaughters(kFALSE);
printf("---Daughters of %s made invisible.\n", fGeoManager->GetTopVolume()->GetName());
printf("---Make them visible with : gGeoManager->GetTopVolume()->VisibleDaughters();\n");
delete pm;
delete [] xyz;
}
void TGeoChecker::RandomRays(Int_t nrays, Double_t startx, Double_t starty, Double_t startz)
{
TObjArray *pm = new TObjArray(128);
TPolyLine3D *line = 0;
gRandom = new TRandom3();
TGeoVolume *vol=fGeoManager->GetTopVolume();
vol->VisibleDaughters(kTRUE);
Double_t start[3];
Double_t dir[3];
Int_t istep= 0;
const Double_t *point = fGeoManager->GetCurrentPoint();
vol->Draw();
printf("Start... %i rays\n", nrays);
TGeoNode *startnode, *endnode;
Bool_t vis1,vis2;
Int_t i=0;
Int_t ipoint;
Int_t itot=0;
Int_t n10=nrays/10;
Double_t theta,phi, step;
while (itot<nrays) {
itot++;
ipoint = 0;
if (n10) {
if ((itot%n10) == 0) printf("%i percent\n", Int_t(100*itot/nrays));
}
start[0] = startx;
start[1] = starty;
start[2] = startz;
phi = 2*TMath::Pi()*gRandom->Rndm();
theta= TMath::ACos(1.-2.*gRandom->Rndm());
dir[0]=TMath::Sin(theta)*TMath::Cos(phi);
dir[1]=TMath::Sin(theta)*TMath::Sin(phi);
dir[2]=TMath::Cos(theta);
startnode = fGeoManager->InitTrack(start[0],start[1],start[2], dir[0],dir[1],dir[2]);
line = 0;
if (fGeoManager->IsOutside()) startnode=0;
vis1 = (startnode)?(startnode->IsOnScreen()):kFALSE;
if (vis1) {
line = new TPolyLine3D(2);
line->SetLineColor(startnode->GetVolume()->GetLineColor());
line->SetPoint(ipoint++, startx, starty, startz);
i++;
pm->Add(line);
}
fGeoManager->FindNextBoundary();
step = fGeoManager->GetStep();
endnode = fGeoManager->Step();
vis2 = (endnode)?(endnode->IsOnScreen()):kFALSE;
while (step<1E10) {
istep = 0;
while (!fGeoManager->IsEntering()) {
istep++;
if (istep>1E4) break;
fGeoManager->SetStep(1E-3);
endnode = fGeoManager->Step();
step += 1E-3;
}
if (istep>1E4) break;
vis2 = (endnode)?(endnode->IsOnScreen()):kFALSE;
if (ipoint>0) {
line->SetPoint(ipoint, point[0], point[1], point[2]);
ipoint = 0;
line = 0;
}
if (vis2) {
line = new TPolyLine3D(2);
line->SetLineColor(endnode->GetVolume()->GetLineColor());
line->SetPoint(ipoint++, point[0], point[1], point[2]);
i++;
pm->Add(line);
}
if (endnode==0 && step>1E10) break;
startnode = endnode;
fGeoManager->FindNextBoundary();
step = fGeoManager->GetStep();
endnode = fGeoManager->Step();
}
}
for (Int_t m=0; m<pm->GetEntriesFast(); m++) {
line = (TPolyLine3D*)pm->At(m);
if (line) line->Draw("SAME");
}
printf("number of segments : %i\n", i);
fGeoManager->GetTopVolume()->VisibleDaughters(kFALSE);
printf("---Daughters of %s made invisible.\n", fGeoManager->GetTopVolume()->GetName());
printf("---Make them visible with : gGeoManager->GetTopVolume()->VisibleDaughters();\n");
delete pm;
}
TGeoNode *TGeoChecker::SamplePoints(Int_t npoints, Double_t &dist, Double_t epsil,
const char* g3path)
{
TGeoNode *node = fGeoManager->FindNode();
TGeoNode *nodegeo = 0;
TGeoNode *nodeg3 = 0;
TGeoNode *solg3 = 0;
if (!node) {dist=-1; return 0;}
gRandom = new TRandom3();
Bool_t hasg3 = kFALSE;
if (strlen(g3path)) hasg3 = kTRUE;
char geopath[200];
sprintf(geopath, "%s\n", fGeoManager->GetPath());
dist = 1E10;
TString common = "";
Double_t point[3];
Double_t closest[3];
TGeoNode *node1 = 0;
TGeoNode *node_close = 0;
dist = 1E10;
Double_t dist1 = 0;
Double_t eps[3];
eps[0] = epsil; eps[1]=epsil; eps[2]=epsil;
const Double_t *pointg = fGeoManager->GetCurrentPoint();
if (hasg3) {
TString spath = geopath;
TString name = "";
Int_t index=0;
while (index>=0) {
index = spath.Index("/", index+1);
if (index>0) {
name = spath(0, index);
if (strstr(g3path, name.Data())) {
common = name;
continue;
} else break;
}
}
if (strlen(common.Data())) {
while (strcmp(fGeoManager->GetPath(), common.Data()) && fGeoManager->GetLevel()) {
nodegeo = fGeoManager->GetCurrentNode();
fGeoManager->CdUp();
}
fGeoManager->cd(g3path);
solg3 = fGeoManager->GetCurrentNode();
while (strcmp(fGeoManager->GetPath(), common.Data()) && fGeoManager->GetLevel()) {
nodeg3 = fGeoManager->GetCurrentNode();
fGeoManager->CdUp();
}
if (!nodegeo) return 0;
if (!nodeg3) return 0;
fGeoManager->cd(common.Data());
fGeoManager->MasterToLocal(fGeoManager->GetCurrentPoint(), &point[0]);
Double_t xyz[3], local[3];
for (Int_t i=0; i<npoints; i++) {
xyz[0] = point[0] - eps[0] + 2*eps[0]*gRandom->Rndm();
xyz[1] = point[1] - eps[1] + 2*eps[1]*gRandom->Rndm();
xyz[2] = point[2] - eps[2] + 2*eps[2]*gRandom->Rndm();
nodeg3->MasterToLocal(&xyz[0], &local[0]);
if (!nodeg3->GetVolume()->Contains(&local[0])) continue;
dist1 = TMath::Sqrt((xyz[0]-point[0])*(xyz[0]-point[0])+
(xyz[1]-point[1])*(xyz[1]-point[1])+(xyz[2]-point[2])*(xyz[2]-point[2]));
if (dist1<dist) {
dist = dist1;
node_close = solg3;
eps[0] = TMath::Abs(point[0]-pointg[0]);
eps[1] = TMath::Abs(point[1]-pointg[1]);
eps[2] = TMath::Abs(point[2]-pointg[2]);
}
}
}
if (!node_close) dist = -1;
return node_close;
}
memcpy(&point[0], pointg, 3*sizeof(Double_t));
for (Int_t i=0; i<npoints; i++) {
fGeoManager->SetCurrentPoint(point[0] - eps[0] + 2*eps[0]*gRandom->Rndm(),
point[1] - eps[1] + 2*eps[1]*gRandom->Rndm(),
point[2] - eps[2] + 2*eps[2]*gRandom->Rndm());
if (node1!=node) {
dist1 = TMath::Sqrt((point[0]-pointg[0])*(point[0]-pointg[0])+
(point[1]-pointg[1])*(point[1]-pointg[1])+(point[2]-pointg[2])*(point[2]-pointg[2]));
if (dist1<dist) {
dist = dist1;
node_close = node1;
memcpy(&closest[0], pointg, 3*sizeof(Double_t));
eps[0] = TMath::Abs(point[0]-pointg[0]);
eps[1] = TMath::Abs(point[1]-pointg[1]);
eps[2] = TMath::Abs(point[2]-pointg[2]);
}
}
}
fGeoManager->FindNode(point[0], point[1], point[2]);
if (!node_close) dist=-1;
return node_close;
}
void TGeoChecker::ShootRay(Double_t *start, Double_t dirx, Double_t diry, Double_t dirz, Double_t *array, Int_t &nelem, Int_t &dim, Double_t *endpoint) const
{
nelem = 0;
Int_t istep = 0;
if (!dim) {
printf("empty input array\n");
return;
}
const Double_t *point = fGeoManager->GetCurrentPoint();
TGeoNode *endnode;
Bool_t is_entering;
Double_t step, forward;
Double_t dir[3];
dir[0] = dirx;
dir[1] = diry;
dir[2] = dirz;
fGeoManager->InitTrack(start, &dir[0]);
fGeoManager->GetCurrentNode();
fGeoManager->FindNextBoundary();
step = fGeoManager->GetStep();
if (step>1E10) return;
endnode = fGeoManager->Step();
is_entering = fGeoManager->IsEntering();
while (step<1E10) {
if (endpoint) {
forward = dirx*(endpoint[0]-point[0])+diry*(endpoint[1]-point[1])+dirz*(endpoint[2]-point[2]);
if (forward<1E-3) {
return;
}
}
if (is_entering) {
if (nelem>=dim) {
Double_t *temparray = new Double_t[3*(dim+20)];
memcpy(temparray, array, 3*dim*sizeof(Double_t));
delete [] array;
array = temparray;
dim += 20;
}
memcpy(&array[3*nelem], point, 3*sizeof(Double_t));
nelem++;
} else {
if (endnode==0 && step>1E10) {
return;
}
if (!fGeoManager->IsEntering()) {
istep = 0;
}
while (!fGeoManager->IsEntering()) {
istep++;
if (istep>1E3) {
nelem = 0;
return;
}
fGeoManager->SetStep(1E-5);
endnode = fGeoManager->Step();
}
if (istep>0) printf("%i steps\n", istep);
if (nelem>=dim) {
Double_t *temparray = new Double_t[3*(dim+20)];
memcpy(temparray, array, 3*dim*sizeof(Double_t));
delete [] array;
array = temparray;
dim += 20;
}
memcpy(&array[3*nelem], point, 3*sizeof(Double_t));
nelem++;
is_entering = kTRUE;
}
fGeoManager->FindNextBoundary();
step = fGeoManager->GetStep();
endnode = fGeoManager->Step();
is_entering = fGeoManager->IsEntering();
}
}
void TGeoChecker::Test(Int_t npoints, Option_t *option)
{
gRandom= new TRandom3();
Bool_t recheck = !strcmp(option, "RECHECK");
if (recheck) printf("RECHECK\n");
const TGeoShape *shape = fGeoManager->GetTopVolume()->GetShape();
Double_t dx = ((TGeoBBox*)shape)->GetDX();
Double_t dy = ((TGeoBBox*)shape)->GetDY();
Double_t dz = ((TGeoBBox*)shape)->GetDZ();
Double_t ox = (((TGeoBBox*)shape)->GetOrigin())[0];
Double_t oy = (((TGeoBBox*)shape)->GetOrigin())[1];
Double_t oz = (((TGeoBBox*)shape)->GetOrigin())[2];
Double_t *xyz = new Double_t[3*npoints];
TStopwatch *timer = new TStopwatch();
printf("Random box : %f, %f, %f\n", dx, dy, dz);
timer->Start(kFALSE);
Int_t i;
for (i=0; i<npoints; i++) {
xyz[3*i] = ox-dx+2*dx*gRandom->Rndm();
xyz[3*i+1] = oy-dy+2*dy*gRandom->Rndm();
xyz[3*i+2] = oz-dz+2*dz*gRandom->Rndm();
}
timer->Stop();
printf("Generation time :\n");
timer->Print();
timer->Reset();
TGeoNode *node, *node1;
printf("Start... %i points\n", npoints);
timer->Start(kFALSE);
for (i=0; i<npoints; i++) {
fGeoManager->SetCurrentPoint(xyz+3*i);
if (recheck) fGeoManager->CdTop();
node = fGeoManager->FindNode();
if (recheck) {
node1 = fGeoManager->FindNode();
if (node1 != node) {
printf("Difference for x=%g y=%g z=%g\n", xyz[3*i], xyz[3*i+1], xyz[3*i+2]);
printf(" from top : %s\n", node->GetName());
printf(" redo : %s\n", fGeoManager->GetPath());
}
}
}
timer->Stop();
timer->Print();
delete [] xyz;
delete timer;
}
void TGeoChecker::TestOverlaps(const char* path)
{
if (fGeoManager->GetTopVolume()!=fGeoManager->GetMasterVolume()) fGeoManager->RestoreMasterVolume();
printf("Checking overlaps for path :\n");
if (!fGeoManager->cd(path)) return;
TGeoNode *checked = fGeoManager->GetCurrentNode();
checked->InspectNode();
gRandom= new TRandom3();
Int_t npoints = 1000000;
Double_t big = 1E6;
Double_t xmin = big;
Double_t xmax = -big;
Double_t ymin = big;
Double_t ymax = -big;
Double_t zmin = big;
Double_t zmax = -big;
TObjArray *pm = new TObjArray(128);
TPolyMarker3D *marker = 0;
TPolyMarker3D *markthis = new TPolyMarker3D();
markthis->SetMarkerColor(5);
TNtuple *ntpl = new TNtuple("ntpl","random points","x:y:z");
TGeoShape *shape = fGeoManager->GetCurrentNode()->GetVolume()->GetShape();
Double_t *point = new Double_t[3];
Double_t dx = ((TGeoBBox*)shape)->GetDX();
Double_t dy = ((TGeoBBox*)shape)->GetDY();
Double_t dz = ((TGeoBBox*)shape)->GetDZ();
Double_t ox = (((TGeoBBox*)shape)->GetOrigin())[0];
Double_t oy = (((TGeoBBox*)shape)->GetOrigin())[1];
Double_t oz = (((TGeoBBox*)shape)->GetOrigin())[2];
Double_t *xyz = new Double_t[3*npoints];
Int_t i=0;
printf("Generating %i points inside %s\n", npoints, fGeoManager->GetPath());
while (i<npoints) {
point[0] = ox-dx+2*dx*gRandom->Rndm();
point[1] = oy-dy+2*dy*gRandom->Rndm();
point[2] = oz-dz+2*dz*gRandom->Rndm();
if (!shape->Contains(point)) continue;
fGeoManager->LocalToMaster(point, &xyz[3*i]);
xmin = TMath::Min(xmin, xyz[3*i]);
xmax = TMath::Max(xmax, xyz[3*i]);
ymin = TMath::Min(ymin, xyz[3*i+1]);
ymax = TMath::Max(ymax, xyz[3*i+1]);
zmin = TMath::Min(zmin, xyz[3*i+2]);
zmax = TMath::Max(zmax, xyz[3*i+2]);
i++;
}
delete [] point;
ntpl->Fill(xmin,ymin,zmin);
ntpl->Fill(xmax,ymin,zmin);
ntpl->Fill(xmin,ymax,zmin);
ntpl->Fill(xmax,ymax,zmin);
ntpl->Fill(xmin,ymin,zmax);
ntpl->Fill(xmax,ymin,zmax);
ntpl->Fill(xmin,ymax,zmax);
ntpl->Fill(xmax,ymax,zmax);
ntpl->Draw("z:y:x");
TGeoNode *node;
TString cpath;
Int_t ic=0;
TObjArray *overlaps = new TObjArray();
printf("using FindNode...\n");
for (Int_t j=0; j<npoints; j++) {
fGeoManager->CdTop();
fGeoManager->SetCurrentPoint(&xyz[3*j]);
node = fGeoManager->FindNode();
cpath = fGeoManager->GetPath();
if (cpath.Contains(path)) {
markthis->SetNextPoint(xyz[3*j], xyz[3*j+1], xyz[3*j+2]);
continue;
}
if (!node) ic=128;
else ic = node->GetVolume()->GetLineColor();
if (ic >= 128) ic = 0;
marker = (TPolyMarker3D*)pm->At(ic);
if (!marker) {
marker = new TPolyMarker3D();
marker->SetMarkerColor(ic);
pm->AddAt(marker, ic);
}
marker->SetNextPoint(xyz[3*j], xyz[3*j+1], xyz[3*j+2]);
if (node) {
if (overlaps->IndexOf(node) < 0) overlaps->Add(node);
}
}
for (Int_t m=0; m<128; m++) {
marker = (TPolyMarker3D*)pm->At(m);
}
markthis->Draw("SAME");
if (gPad) gPad->Update();
if (overlaps->GetEntriesFast()) {
printf("list of overlapping nodes :\n");
for (i=0; i<overlaps->GetEntriesFast(); i++) {
node = (TGeoNode*)overlaps->At(i);
if (node->IsOverlapping()) printf("%s MANY\n", node->GetName());
else printf("%s ONLY\n", node->GetName());
}
} else printf("No overlaps\n");
delete ntpl;
delete pm;
delete [] xyz;
delete overlaps;
}
Double_t TGeoChecker::Weight(Double_t precision, Option_t *option)
{
TList *matlist = fGeoManager->GetListOfMaterials();
Int_t nmat = matlist->GetSize();
if (!nmat) return 0;
Int_t *nin = new Int_t[nmat];
memset(nin, 0, nmat*sizeof(Int_t));
gRandom = new TRandom3();
TString opt = option;
opt.ToLower();
Bool_t isverbose = opt.Contains("v");
TGeoBBox *box = (TGeoBBox *)fGeoManager->GetTopVolume()->GetShape();
Double_t dx = box->GetDX();
Double_t dy = box->GetDY();
Double_t dz = box->GetDZ();
Double_t ox = (box->GetOrigin())[0];
Double_t oy = (box->GetOrigin())[1];
Double_t oz = (box->GetOrigin())[2];
Double_t x,y,z;
TGeoNode *node;
TGeoMaterial *mat;
Double_t vbox = 0.000008*dx*dy*dz;
Bool_t end = kFALSE;
Double_t weight=0, sigma, eps, dens;
Double_t eps0=1.;
Int_t indmat;
Int_t igen=0;
Int_t iin = 0;
while (!end) {
x = ox-dx+2*dx*gRandom->Rndm();
y = oy-dy+2*dy*gRandom->Rndm();
z = oz-dz+2*dz*gRandom->Rndm();
node = fGeoManager->FindNode(x,y,z);
igen++;
if (!node) continue;
mat = node->GetVolume()->GetMedium()->GetMaterial();
indmat = mat->GetIndex();
if (indmat<0) continue;
nin[indmat]++;
iin++;
if ((iin%100000)==0 || igen>1E8) {
weight = 0;
sigma = 0;
for (indmat=0; indmat<nmat; indmat++) {
mat = (TGeoMaterial*)matlist->At(indmat);
dens = mat->GetDensity();
if (dens<1E-2) dens=0;
dens *= 1000.;
weight += dens*Double_t(nin[indmat]);
sigma += dens*dens*nin[indmat];
}
sigma = TMath::Sqrt(sigma);
eps = sigma/weight;
weight *= vbox/Double_t(igen);
sigma *= vbox/Double_t(igen);
if (eps<precision || igen>1E8) {
if (isverbose) {
printf("=== Weight of %s : %g +/- %g [kg]\n",
fGeoManager->GetTopVolume()->GetName(), weight, sigma);
}
end = kTRUE;
} else {
if (isverbose && eps<0.5*eps0) {
printf("%8dK: %14.7g kg %g %%\n",
igen/1000, weight, eps*100);
eps0 = eps;
}
}
}
}
delete [] nin;
return weight;
}
Double_t TGeoChecker::CheckVoxels(TGeoVolume *vol, TGeoVoxelFinder *voxels, Double_t *xyz, Int_t npoints)
{
TStopwatch timer;
Double_t time;
TGeoShape *shape = vol->GetShape();
TGeoNode *node;
TGeoMatrix *matrix;
Double_t *point;
Double_t local[3];
Int_t *checklist;
Int_t ncheck;
timer.Start();
for (Int_t i=0; i<npoints; i++) {
point = xyz + 3*i;
if (!shape->Contains(point)) continue;
checklist = voxels->GetCheckList(point, ncheck);
if (!checklist) continue;
if (!ncheck) continue;
for (Int_t id=0; id<ncheck; id++) {
node = vol->GetNode(checklist[id]);
matrix = node->GetMatrix();
matrix->MasterToLocal(point, &local[0]);
if (node->GetVolume()->GetShape()->Contains(&local[0])) break;
}
}
time = timer.CpuTime();
return time;
}
Bool_t TGeoChecker::TestVoxels(TGeoVolume * , Int_t )
{
return kFALSE;
}