#include "TROOT.h"
#include "TClass.h"
#include "TColor.h"
#include "TPoint.h"
#include "TView.h"
#include "TAttLine.h"
#include "TAttFill.h"
#include "TPad.h"
#include "TCanvas.h"
#include "TH2F.h"
#include "TF1.h"
#include "TPluginManager.h"
#include "TVirtualPadEditor.h"
#include "TStopwatch.h"
#include "TPolyMarker3D.h"
#include "TVirtualGL.h"
#include "TGeoAtt.h"
#include "TGeoVolume.h"
#include "TGeoNode.h"
#include "TGeoManager.h"
#include "TGeoTrack.h"
#include "TGeoOverlap.h"
#include "TGeoChecker.h"
#include "TGeoPhysicalNode.h"
#include "TGeoCompositeShape.h"
#include "TGeoShapeAssembly.h"
#include "TGeoPainter.h"
#include "TMath.h"
#include "X3DBuffer.h"
#include "TBuffer3D.h"
#include "TBuffer3DTypes.h"
#include "TVirtualViewer3D.h"
ClassImp(TGeoPainter)
TGeoPainter::TGeoPainter(TGeoManager *manager) : TVirtualGeoPainter(manager)
{
TVirtualGeoPainter::SetPainter(this);
if (manager) fGeoManager = manager;
else {
Error("ctor", "No geometry loaded");
return;
}
fNsegments = fGeoManager->GetNsegments();
fNVisNodes = 0;
fBombX = 1.3;
fBombY = 1.3;
fBombZ = 1.3;
fBombR = 1.3;
fVisLevel = fGeoManager->GetVisLevel();
fVisOption = fGeoManager->GetVisOption();
fExplodedView = fGeoManager->GetBombMode();
fVisBranch = "";
fVolInfo = "";
fVisLock = kFALSE;
fIsRaytracing = kFALSE;
fTopVisible = kFALSE;
fPaintingOverlaps = kFALSE;
fPlugin = 0;
fVisVolumes = new TObjArray();
fOverlap = 0;
fGlobal = new TGeoHMatrix();
fBuffer = new TBuffer3D(TBuffer3DTypes::kGeneric,20,3*20,0,0,0,0);
fClippingShape = 0;
fLastVolume = 0;
fTopVolume = 0;
fIsPaintingShape = kFALSE;
memset(&fCheckedBox[0], 0, 6*sizeof(Double_t));
fCheckedNode = fGeoManager->GetTopNode();
fChecker = new TGeoChecker(fGeoManager);
fIsEditable = kFALSE;
DefineColors();
}
TGeoPainter::~TGeoPainter()
{
if (fChecker) delete fChecker;
delete fVisVolumes;
delete fGlobal;
delete fBuffer;
if (fPlugin) delete fPlugin;
}
void TGeoPainter::AddSize3D(Int_t numpoints, Int_t numsegs, Int_t numpolys)
{
gSize3D.numPoints += numpoints;
gSize3D.numSegs += numsegs;
gSize3D.numPolys += numpolys;
}
TVirtualGeoTrack *TGeoPainter::AddTrack(Int_t id, Int_t pdgcode, TObject *particle)
{
return (TVirtualGeoTrack*)(new TGeoTrack(id,pdgcode,0,particle));
}
void TGeoPainter::AddTrackPoint(Double_t *point, Double_t *box, Bool_t reset)
{
static Int_t npoints = 0;
static Double_t xmin[3] = {0,0,0};
static Double_t xmax[3] = {0,0,0};
Int_t i;
if (reset) {
memset(box, 0, 6*sizeof(Double_t));
memset(xmin, 0, 3*sizeof(Double_t));
memset(xmax, 0, 3*sizeof(Double_t));
npoints = 0;
return;
}
if (npoints==0) {
for (i=0; i<3; i++) xmin[i]=xmax[i]=0;
npoints++;
}
npoints++;
Double_t ninv = 1./Double_t(npoints);
for (i=0; i<3; i++) {
box[i] += ninv*(point[i]-box[i]);
if (point[i]<xmin[i]) xmin[i]=point[i];
if (point[i]>xmax[i]) xmax[i]=point[i];
box[i+3] = 0.5*(xmax[i]-xmin[i]);
}
}
void TGeoPainter::BombTranslation(const Double_t *tr, Double_t *bombtr)
{
memcpy(bombtr, tr, 3*sizeof(Double_t));
switch (fExplodedView) {
case kGeoNoBomb:
return;
case kGeoBombXYZ:
bombtr[0] *= fBombX;
bombtr[1] *= fBombY;
bombtr[2] *= fBombZ;
return;
case kGeoBombCyl:
bombtr[0] *= fBombR;
bombtr[1] *= fBombR;
bombtr[2] *= fBombZ;
return;
case kGeoBombSph:
bombtr[0] *= fBombR;
bombtr[1] *= fBombR;
bombtr[2] *= fBombR;
return;
default:
return;
}
}
void TGeoPainter::CheckBoundaryErrors(Int_t ntracks, Double_t radius)
{
fChecker->CheckBoundaryErrors(ntracks, radius);
}
void TGeoPainter::CheckBoundaryReference(Int_t icheck)
{
fChecker->CheckBoundaryReference(icheck);
}
void TGeoPainter::CheckGeometryFull(Bool_t checkoverlaps, Bool_t checkcrossings, Int_t ntracks, const Double_t *vertex)
{
fChecker->CheckGeometryFull(checkoverlaps,checkcrossings,ntracks,vertex);
}
void TGeoPainter::CheckGeometry(Int_t nrays, Double_t startx, Double_t starty, Double_t startz) const
{
fChecker->CheckGeometry(nrays, startx, starty, startz);
}
void TGeoPainter::CheckOverlaps(const TGeoVolume *vol, Double_t ovlp, Option_t *option) const
{
fChecker->CheckOverlaps(vol, ovlp, option);
}
void TGeoPainter::CheckPoint(Double_t x, Double_t y, Double_t z, Option_t *option)
{
fChecker->CheckPoint(x,y,z,option);
}
void TGeoPainter::ClearVisibleVolumes()
{
if (!fVisVolumes) return;
TIter next(fVisVolumes);
TGeoVolume *vol;
while ((vol = (TGeoVolume*)next())) {
vol->ResetAttBit(TGeoAtt::kVisOnScreen);
}
fVisVolumes->Clear();
}
void TGeoPainter::DefineColors() const
{
TColor::InitializeColors();
TColor *color = gROOT->GetColor(1000);
if (color) return;
Int_t i,j;
Float_t r,g,b,h,l,s;
for (i=1; i<8; i++) {
color = (TColor*)gROOT->GetListOfColors()->At(i);
if (!color) {
Warning("DefineColors", "No colors defined");
return;
}
color->GetHLS(h,l,s);
for (j=0; j<100; j++) {
l = 0.25+0.5*j/99.;
TColor::HLS2RGB(h,l,s,r,g,b);
new TColor(1000+(i-1)*100+j, r,g,b);
}
}
}
Int_t TGeoPainter::GetColor(Int_t base, Float_t light) const
{
const Int_t kBCols[8] = {1,2,3,5,4,6,7,1};
TColor *tcolor = gROOT->GetColor(base);
if (!tcolor) tcolor = new TColor(base, 0.5,0.5,0.5);
Float_t r,g,b;
tcolor->GetRGB(r,g,b);
Int_t code = 0;
if (r>0.5) code += 1;
if (g>0.5) code += 2;
if (b>0.5) code += 4;
Int_t color, j;
if (light<0.25) {
j=0;
} else {
if (light>0.8) j=99;
else j = Int_t(99*(light-0.25)/0.5);
}
color = 1000 + (kBCols[code]-1)*100+j;
return color;
}
TGeoVolume *TGeoPainter::GetDrawnVolume() const
{
if (!gPad) return 0;
return fTopVolume;
}
Int_t TGeoPainter::DistanceToPrimitiveVol(TGeoVolume *volume, Int_t px, Int_t py)
{
const Int_t big = 9999;
const Int_t inaxis = 7;
const Int_t maxdist = 5;
if (fTopVolume != volume) fTopVolume = volume;
TView *view = gPad->GetView();
if (!view) return big;
TGeoBBox *box;
fGlobal->Clear();
TGeoShape::SetTransform(fGlobal);
Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
if (px < puxmin - inaxis) return big;
if (py > puymin + inaxis) return big;
if (px > puxmax + inaxis) return big;
if (py < puymax - inaxis) return big;
fCheckedNode = fGeoManager->GetTopNode();
gPad->SetSelected(view);
Int_t dist = big;
if (fPaintingOverlaps) {
TGeoVolume *crt;
crt = fOverlap->GetFirstVolume();
*fGlobal = fOverlap->GetFirstMatrix();
dist = crt->GetShape()->DistancetoPrimitive(px,py);
if (dist<maxdist) {
gPad->SetSelected(crt);
box = (TGeoBBox*)crt->GetShape();
fGlobal->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
fCheckedBox[3] = box->GetDX();
fCheckedBox[4] = box->GetDY();
fCheckedBox[5] = box->GetDZ();
return 0;
}
crt = fOverlap->GetSecondVolume();
*fGlobal = fOverlap->GetSecondMatrix();
dist = crt->GetShape()->DistancetoPrimitive(px,py);
if (dist<maxdist) {
gPad->SetSelected(crt);
box = (TGeoBBox*)crt->GetShape();
fGlobal->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
fCheckedBox[3] = box->GetDX();
fCheckedBox[4] = box->GetDY();
fCheckedBox[5] = box->GetDZ();
return 0;
}
return big;
}
if ((puxmax+inaxis-px) < 40) {
if ((py-puymax+inaxis) < 40) {
gPad->SetSelected(fGeoManager);
fVolInfo = fGeoManager->GetName();
box = (TGeoBBox*)volume->GetShape();
memcpy(fCheckedBox, box->GetOrigin(), 3*sizeof(Double_t));
fCheckedBox[3] = box->GetDX();
fCheckedBox[4] = box->GetDY();
fCheckedBox[5] = box->GetDZ();
return 0;
}
gPad->SetSelected(volume);
fVolInfo = volume->GetName();
box = (TGeoBBox*)volume->GetShape();
memcpy(fCheckedBox, box->GetOrigin(), 3*sizeof(Double_t));
fCheckedBox[3] = box->GetDX();
fCheckedBox[4] = box->GetDY();
fCheckedBox[5] = box->GetDZ();
return 0;
}
TGeoVolume *vol = volume;
Bool_t vis = vol->IsVisible();
if (volume->IsVisBranch()) {
if (!fGeoManager->IsClosed()) return big;
fGeoManager->PushPath();
fGeoManager->cd(fVisBranch.Data());
while (fGeoManager->GetLevel()) {
vol = fGeoManager->GetCurrentVolume();
*fGlobal = gGeoManager->GetCurrentMatrix();
dist = vol->GetShape()->DistancetoPrimitive(px,py);
if (dist<maxdist) {
fVolInfo = fVisBranch;
box = (TGeoBBox*)vol->GetShape();
fGeoManager->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
fCheckedNode = gGeoManager->GetCurrentNode();
if (fGeoManager->IsNodeSelectable()) gPad->SetSelected(fCheckedNode);
else gPad->SetSelected(vol);
fCheckedBox[3] = box->GetDX();
fCheckedBox[4] = box->GetDY();
fCheckedBox[5] = box->GetDZ();
fGeoManager->PopPath();
return 0;
}
fGeoManager->CdUp();
}
fGeoManager->PopPath();
return dist;
}
if ((fTopVisible && vis) || !vol->GetNdaughters() || !vol->IsVisDaughters() || vol->IsVisOnly()) {
dist = vol->GetShape()->DistancetoPrimitive(px,py);
if (dist<maxdist) {
fVolInfo = vol->GetName();
gPad->SetSelected(vol);
box = (TGeoBBox*)vol->GetShape();
memcpy(fCheckedBox, box->GetOrigin(), 3*sizeof(Double_t));
fCheckedBox[3] = box->GetDX();
fCheckedBox[4] = box->GetDY();
fCheckedBox[5] = box->GetDZ();
return 0;
}
if (vol->IsVisOnly() || !vol->GetNdaughters() || !vol->IsVisDaughters())
return dist;
}
TGeoIterator next(vol);
next.SetTopName(Form("%s_1",vol->GetName()));
TGeoNode *daughter;
Int_t level, nd;
Bool_t last;
while ((daughter=next())) {
vol = daughter->GetVolume();
level = next.GetLevel();
nd = daughter->GetNdaughters();
vis = daughter->IsVisible();
if (volume->IsVisContainers()) {
if (vis && level<=fVisLevel) {
*fGlobal = next.GetCurrentMatrix();
dist = vol->GetShape()->DistancetoPrimitive(px,py);
if (dist<maxdist) {
next.GetPath(fVolInfo);
box = (TGeoBBox*)vol->GetShape();
fGlobal->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
fCheckedNode = daughter;
if (fGeoManager->IsNodeSelectable()) gPad->SetSelected(fCheckedNode);
else gPad->SetSelected(vol);
fCheckedBox[3] = box->GetDX();
fCheckedBox[4] = box->GetDY();
fCheckedBox[5] = box->GetDZ();
fGeoManager->PopPath();
return 0;
}
}
if (level==fVisLevel || !daughter->IsVisDaughters()) {
next.Skip();
continue;
}
} else if (volume->IsVisLeaves()) {
last = ((nd==0) || (level==fVisLevel) || (!daughter->IsVisDaughters()))?kTRUE:kFALSE;
if (vis && last) {
*fGlobal = next.GetCurrentMatrix();
dist = vol->GetShape()->DistancetoPrimitive(px,py);
if (dist<maxdist) {
next.GetPath(fVolInfo);
box = (TGeoBBox*)vol->GetShape();
fGlobal->LocalToMaster(box->GetOrigin(), &fCheckedBox[0]);
fCheckedNode = daughter;
if (fGeoManager->IsNodeSelectable()) gPad->SetSelected(fCheckedNode);
else gPad->SetSelected(vol);
fCheckedBox[3] = box->GetDX();
fCheckedBox[4] = box->GetDY();
fCheckedBox[5] = box->GetDZ();
fGeoManager->PopPath();
return 0;
}
}
if (last || !daughter->IsVisDaughters()) next.Skip();
}
}
return dist;
}
void TGeoPainter::DefaultAngles()
{
if (gPad) {
Int_t irep;
TView *view = gPad->GetView();
if (!view) return;
view->SetView(-206,126,75,irep);
ModifiedPad();
}
}
void TGeoPainter::DefaultColors()
{
TIter next(fGeoManager->GetListOfVolumes());
TGeoVolume *vol;
while ((vol=(TGeoVolume*)next()))
vol->SetLineColor(vol->GetMaterial()->GetDefaultColor());
ModifiedPad();
}
Int_t TGeoPainter::CountNodes(TGeoVolume *volume, Int_t rlevel) const
{
TGeoVolume *vol = volume;
Int_t count = 0;
Bool_t vis = vol->IsVisible();
if ((fTopVisible && vis) || !vol->GetNdaughters() || !vol->IsVisDaughters() || vol->IsVisOnly())
count++;
if (volume->IsVisOnly()) return count;
if (volume->IsVisBranch()) {
fGeoManager->PushPath();
fGeoManager->cd(fVisBranch.Data());
count = fGeoManager->GetLevel() + 1;
fGeoManager->PopPath();
return count;
}
TGeoIterator next(vol);
TGeoNode *daughter;
Int_t level, nd;
Bool_t last;
while ((daughter=next())) {
vol = daughter->GetVolume();
level = next.GetLevel();
nd = daughter->GetNdaughters();
vis = daughter->IsVisible();
if (volume->IsVisContainers()) {
if (vis && level<=rlevel) count++;
if (level==rlevel || !daughter->IsVisDaughters()) {
next.Skip();
continue;
}
} else if (volume->IsVisLeaves()) {
last = ((nd==0) || (level==rlevel) || (!daughter->IsVisDaughters()))?kTRUE:kFALSE;
if (vis && last) count++;
if (last) next.Skip();
}
}
return count;
}
Int_t TGeoPainter::CountVisibleNodes()
{
Int_t maxnodes = fGeoManager->GetMaxVisNodes();
Int_t vislevel = fGeoManager->GetVisLevel();
TGeoVolume *top = fTopVolume;
if (maxnodes <= 0 && top) {
fNVisNodes = CountNodes(top, vislevel);
SetVisLevel(vislevel);
return fNVisNodes;
}
if (!top) {
SetVisLevel(vislevel);
return 0;
}
fNVisNodes = -1;
Bool_t again = kFALSE;
for (Int_t level = 1;level<20;level++) {
vislevel = level;
Int_t nnodes = CountNodes(top, level);
if (top->IsVisOnly() || top->IsVisBranch()) {
vislevel = fVisLevel;
fNVisNodes = nnodes;
break;
}
if (nnodes > maxnodes) {
vislevel--;
break;
}
if (nnodes == fNVisNodes) {
if (again) break;
again = kTRUE;
}
fNVisNodes = nnodes;
}
SetVisLevel(vislevel);
return fNVisNodes;
}
void TGeoPainter::CheckEdit()
{
if (fIsEditable) return;
if (!TClass::GetClass("TGedEditor")) return;
TPluginHandler *h;
if ((h = gROOT->GetPluginManager()->FindHandler("TGeoManagerEditor"))) {
if (h->LoadPlugin() == -1) return;
h->ExecPlugin(0);
}
fIsEditable = kTRUE;
}
void TGeoPainter::EditGeometry(Option_t *option)
{
if (!gPad) return;
if (!fIsEditable) {
if (!strlen(option)) gPad->GetCanvas()->GetCanvasImp()->ShowEditor();
else TVirtualPadEditor::ShowEditor();
CheckEdit();
}
gPad->SetSelected(fGeoManager);
gPad->GetCanvas()->Selected(gPad,fGeoManager,kButton1Down);
}
void TGeoPainter::Draw(Option_t *option)
{
DrawVolume(fGeoManager->GetTopVolume(), option);
}
void TGeoPainter::DrawBatemanSol(TGeoBatemanSol *sol, Option_t *option)
{
Int_t ncoeff = sol->GetNcoeff();
if (!ncoeff) return;
Double_t tlo=0., thi=0.;
Double_t cn=0., lambda=0.;
Int_t i;
sol->GetRange(tlo, thi);
Bool_t autorange = (thi==0.)?kTRUE:kFALSE;
if (autorange) tlo = 0.;
sol->GetCoeff(0, cn, lambda);
Double_t lambdamin = lambda;
TString formula = "";
for (i=0; i<ncoeff; i++) {
sol->GetCoeff(i, cn, lambda);
formula += Form("%g*exp(-%g*x)",cn, lambda);
if (i < ncoeff-1) formula += "+";
if (lambda < lambdamin &&
lambda > 0.) lambdamin = lambda;
}
if (autorange) thi = 10./lambdamin;
formula += ";time[s]";
formula += Form(";Concentration_of_%s",sol->GetElement()->GetName());
TF1 *func = new TF1(Form("conc%s",sol->GetElement()->GetName()), formula.Data(), tlo,thi);
func->SetMinimum(1.e-3);
func->SetMaximum(1.25*TMath::Max(sol->Concentration(tlo), sol->Concentration(thi)));
func->SetLineColor(sol->GetLineColor());
func->SetLineStyle(sol->GetLineStyle());
func->SetLineWidth(sol->GetLineWidth());
func->SetMarkerColor(sol->GetMarkerColor());
func->SetMarkerStyle(sol->GetMarkerStyle());
func->SetMarkerSize(sol->GetMarkerSize());
func->Draw(option);
}
void TGeoPainter::DrawVolume(TGeoVolume *vol, Option_t *option)
{
fTopVolume = vol;
fLastVolume = 0;
fIsPaintingShape = kFALSE;
CountVisibleNodes();
TString opt = option;
opt.ToLower();
fPaintingOverlaps = kFALSE;
fOverlap = 0;
if (fVisLock) {
ClearVisibleVolumes();
fVisLock = kFALSE;
}
Bool_t has_pad = (gPad==0)?kFALSE:kTRUE;
if (!gPad) {
gROOT->MakeDefCanvas();
}
if (!opt.Contains("same")) gPad->Clear();
fTopVolume->AppendPad(option);
TView *view = gPad->GetView();
if (!view) {
view = TView::CreateView(11,0,0);
view->SetAutoRange(kTRUE);
if (has_pad) gPad->Update();
}
Paint("range");
view->SetAutoRange(kFALSE);
fLastVolume = fTopVolume;
gPad->GetViewer3D(option);
}
void TGeoPainter::DrawShape(TGeoShape *shape, Option_t *option)
{
TString opt = option;
opt.ToLower();
fPaintingOverlaps = kFALSE;
fOverlap = 0;
fIsPaintingShape = kTRUE;
Bool_t has_pad = (gPad==0)?kFALSE:kTRUE;
if (!gPad) {
gROOT->MakeDefCanvas();
}
if (!opt.Contains("same")) gPad->Clear();
shape->AppendPad(option);
TView *view = gPad->GetView();
if (!view) {
view = TView::CreateView(11,0,0);
view->SetAutoRange(kTRUE);
if (has_pad) gPad->Update();
}
PaintShape(shape,"range");
view->SetAutoRange(kTRUE);
gPad->GetViewer3D(option);
}
void TGeoPainter::DrawOverlap(void *ovlp, Option_t *option)
{
TString opt = option;
fIsPaintingShape = kFALSE;
TGeoOverlap *overlap = (TGeoOverlap*)ovlp;
if (!overlap) return;
fPaintingOverlaps = kTRUE;
fOverlap = overlap;
opt.ToLower();
if (fVisLock) {
ClearVisibleVolumes();
fVisLock = kFALSE;
}
Bool_t has_pad = (gPad==0)?kFALSE:kTRUE;
if (!gPad) {
gROOT->MakeDefCanvas();
}
if (!opt.Contains("same")) gPad->Clear();
overlap->AppendPad(option);
gPad->GetViewer3D(option);
TView *view = gPad->GetView();
if (!view) {
view = TView::CreateView(11,0,0);
view->SetAutoRange(kTRUE);
PaintOverlap(ovlp, "range");
overlap->GetPolyMarker()->Draw("SAME");
if (has_pad) gPad->Update();
}
fVisLock = kTRUE;
}
void TGeoPainter::DrawOnly(Option_t *option)
{
TString opt = option;
opt.ToLower();
if (fVisLock) {
ClearVisibleVolumes();
fVisLock = kFALSE;
}
fPaintingOverlaps = kFALSE;
fIsPaintingShape = kFALSE;
Bool_t has_pad = (gPad==0)?kFALSE:kTRUE;
if (!gPad) {
gROOT->MakeDefCanvas();
}
if (!opt.Contains("same")) gPad->Clear();
fTopVolume = fGeoManager->GetCurrentVolume();
fTopVolume->AppendPad(option);
TView *view = gPad->GetView();
if (!view) {
view = TView::CreateView(11,0,0);
view->SetAutoRange(kTRUE);
fVisOption = kGeoVisOnly;
if (has_pad) gPad->Update();
}
fVisLock = kTRUE;
}
void TGeoPainter::DrawCurrentPoint(Int_t color)
{
if (!gPad) return;
if (!gPad->GetView()) return;
TPolyMarker3D *pm = new TPolyMarker3D();
pm->SetMarkerColor(color);
const Double_t *point = fGeoManager->GetCurrentPoint();
pm->SetNextPoint(point[0], point[1], point[2]);
pm->SetMarkerStyle(8);
pm->SetMarkerSize(0.5);
pm->Draw("SAME");
}
void TGeoPainter::DrawPanel()
{
}
void TGeoPainter::DrawPath(const char *path)
{
fVisOption=kGeoVisBranch;
fVisBranch=path;
fIsPaintingShape = kFALSE;
fTopVolume = fGeoManager->GetTopVolume();
fTopVolume->SetVisRaytrace(kFALSE);
DrawVolume(fTopVolume,"");
}
void TGeoPainter::EstimateCameraMove(Double_t tmin, Double_t tmax, Double_t *start, Double_t *end)
{
if (!gPad) return;
TIter next(gPad->GetListOfPrimitives());
TVirtualGeoTrack *track;
TObject *obj;
Int_t ntracks = 0;
Double_t *point = 0;
AddTrackPoint(point, start, kTRUE);
while ((obj=next())) {
if (strcmp(obj->ClassName(), "TGeoTrack")) continue;
track = (TVirtualGeoTrack*)obj;
if (!track) continue;
ntracks++;
track->PaintCollect(tmin, start);
}
if (!ntracks) return;
next.Reset();
AddTrackPoint(point, end, kTRUE);
while ((obj=next())) {
if (strcmp(obj->ClassName(), "TGeoTrack")) continue;
track = (TVirtualGeoTrack*)obj;
if (!track) continue;
track->PaintCollect(tmax, end);
}
}
void TGeoPainter::ExecuteManagerEvent(TGeoManager * , Int_t event, Int_t , Int_t )
{
if (!gPad) return;
gPad->SetCursor(kPointer);
switch (event) {
case kButton1Down:
if (!fIsEditable) CheckEdit();
}
}
void TGeoPainter::ExecuteShapeEvent(TGeoShape * , Int_t event, Int_t , Int_t )
{
if (!gPad) return;
gPad->SetCursor(kHand);
switch (event) {
case kButton1Down:
if (!fIsEditable) CheckEdit();
}
}
void TGeoPainter::ExecuteVolumeEvent(TGeoVolume * , Int_t event, Int_t , Int_t )
{
if (!gPad) return;
if (!fIsEditable) CheckEdit();
gPad->SetCursor(kHand);
switch (event) {
case kMouseEnter:
break;
case kMouseLeave:
break;
case kButton1Down:
break;
case kButton1Up:
break;
case kButton1Double:
gPad->SetCursor(kWatch);
GrabFocus();
break;
}
}
char *TGeoPainter::GetVolumeInfo(const TGeoVolume *volume, Int_t , Int_t ) const
{
const char *snull = "";
if (!gPad) return (char*)snull;
static char info[128];
if (fPaintingOverlaps) {
if (!fOverlap) {
sprintf(info, "wrong overlapping flag");
return info;
}
TString ovtype, name;
if (fOverlap->IsExtrusion()) ovtype="EXTRUSION";
else ovtype = "OVERLAP";
if (volume==fOverlap->GetFirstVolume()) name=volume->GetName();
else name=fOverlap->GetSecondVolume()->GetName();
sprintf(info, "%s: %s of %g", name.Data(), ovtype.Data(), fOverlap->GetOverlap());
return info;
}
else sprintf(info,"%s, shape=%s", fVolInfo.Data(), volume->GetShape()->ClassName());
return info;
}
TGeoChecker *TGeoPainter::GetChecker()
{
if (!fChecker) fChecker = new TGeoChecker(fGeoManager);
return fChecker;
}
void TGeoPainter::GetViewAngles(Double_t &longitude, Double_t &latitude, Double_t &psi)
{
if (!gPad) return;
TView *view = gPad->GetView();
if (!view) return;
longitude = view->GetLongitude();
latitude = view->GetLatitude();
psi = view->GetPsi();
}
void TGeoPainter::GrabFocus(Int_t nfr, Double_t dlong, Double_t dlat, Double_t dpsi)
{
if (!gPad) return;
TView *view = gPad->GetView();
if (!view) return;
if (!fCheckedNode && !fPaintingOverlaps) {
printf("Woops!!!\n");
TGeoBBox *box = (TGeoBBox*)fGeoManager->GetTopVolume()->GetShape();
memcpy(&fCheckedBox[0], box->GetOrigin(), 3*sizeof(Double_t));
fCheckedBox[3] = box->GetDX();
fCheckedBox[4] = box->GetDY();
fCheckedBox[5] = box->GetDZ();
}
view->SetPerspective();
Int_t nvols = fVisVolumes->GetEntriesFast();
Int_t nframes = nfr;
if (nfr==0) {
nframes = 1;
if (nvols<1500) nframes=10;
if (nvols<1000) nframes=20;
if (nvols<200) nframes = 50;
if (nvols<100) nframes = 100;
}
view->MoveFocus(&fCheckedBox[0], fCheckedBox[3], fCheckedBox[4], fCheckedBox[5], nframes, dlong, dlat, dpsi);
}
TH2F *TGeoPainter::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)
{
return fChecker->LegoPlot(ntheta, themin, themax, nphi, phimin, phimax, rmin, rmax, option);
}
void TGeoPainter::LocalToMasterVect(const Double_t *local, Double_t *master) const
{
for (Int_t i=0; i<3; i++)
master[i] = -local[0]*fMat[i]-local[1]*fMat[i+3]-local[2]*fMat[i+6];
}
void TGeoPainter::ModifiedPad(Bool_t update) const
{
if (!gPad) return;
if (update) {
gPad->Update();
return;
}
TView *view = gPad->GetView();
if (!view) return;
view->SetViewChanged();
gPad->Modified();
if (gROOT->FromPopUp()) gPad->Update();
}
void TGeoPainter::Paint(Option_t *option)
{
if (!fGeoManager || !fTopVolume) return;
Bool_t is_padviewer = kTRUE;
if (gPad) is_padviewer = (!strcmp(gPad->GetViewer3D()->ClassName(),"TViewer3DPad"))?kTRUE:kFALSE;
fIsRaytracing = fTopVolume->IsRaytracing();
if (fTopVolume->IsVisContainers()) fVisOption = kGeoVisDefault;
else if (fTopVolume->IsVisLeaves()) fVisOption = kGeoVisLeaves;
else if (fTopVolume->IsVisOnly()) fVisOption = kGeoVisOnly;
else if (fTopVolume->IsVisBranch()) fVisOption = kGeoVisBranch;
if (!fIsRaytracing || !is_padviewer) {
if (fGeoManager->IsDrawingExtra()) {
fGeoManager->CdTop();
TObjArray *nodeList = fGeoManager->GetListOfPhysicalNodes();
Int_t nnodes = nodeList->GetEntriesFast();
Int_t inode;
TGeoPhysicalNode *node;
for (inode=0; inode<nnodes; inode++) {
node = (TGeoPhysicalNode*)nodeList->UncheckedAt(inode);
PaintPhysicalNode(node, option);
}
} else {
PaintVolume(fTopVolume,option);
}
fVisLock = kTRUE;
}
if (fIsRaytracing && is_padviewer) Raytrace();
}
void TGeoPainter::PaintOverlap(void *ovlp, Option_t *option)
{
if (!fGeoManager) return;
TGeoOverlap *overlap = (TGeoOverlap *)ovlp;
if (!overlap) return;
Int_t color, transparency;
if (fOverlap != overlap) fOverlap = overlap;
TGeoShape::SetTransform(fGlobal);
TGeoHMatrix *hmat = fGlobal;
TGeoVolume *vol;
TGeoVolume *vol1 = overlap->GetFirstVolume();
TGeoVolume *vol2 = overlap->GetSecondVolume();
TGeoHMatrix *matrix1 = overlap->GetFirstMatrix();
TGeoHMatrix *matrix2 = overlap->GetSecondMatrix();
vol = vol1;
*hmat = matrix1;
fGeoManager->SetMatrixReflection(matrix1->IsReflection());
if (!fVisLock) fVisVolumes->Add(vol);
fGeoManager->SetPaintVolume(vol);
color = vol->GetLineColor();
transparency = vol->GetTransparency();
vol->SetLineColor(kGreen);
vol->SetTransparency(40);
if (!strstr(option,"range")) ((TAttLine*)vol)->Modify();
PaintShape(*(vol->GetShape()),option);
vol->SetLineColor(color);
vol->SetTransparency(transparency);
vol = vol2;
*hmat = matrix2;
fGeoManager->SetMatrixReflection(matrix2->IsReflection());
if (!fVisLock) fVisVolumes->Add(vol);
fGeoManager->SetPaintVolume(vol);
color = vol->GetLineColor();
transparency = vol->GetTransparency();
vol->SetLineColor(kBlue);
vol->SetTransparency(40);
if (!strstr(option,"range")) ((TAttLine*)vol)->Modify();
PaintShape(*(vol->GetShape()),option);
vol->SetLineColor(color);
vol->SetTransparency(transparency);
fGeoManager->SetMatrixReflection(kFALSE);
fVisLock = kTRUE;
}
void TGeoPainter::PaintNode(TGeoNode *node, Option_t *option, TGeoMatrix* global)
{
PaintVolume(node->GetVolume(), option, global);
}
void TGeoPainter::PaintVolume(TGeoVolume *top, Option_t *option, TGeoMatrix* global)
{
if (fTopVolume != top) {
ClearVisibleVolumes();
fVisLock = kFALSE;
}
fTopVolume = top;
if (!fVisLevel) return;
TGeoVolume *vol = top;
if(global)
*fGlobal = *global;
else
fGlobal->Clear();
TGeoShape::SetTransform(fGlobal);
Bool_t drawDaughters = kTRUE;
Bool_t vis = (top->IsVisible() && !top->IsAssembly());
if (!strstr(option,"range")) ((TAttLine*)vol)->Modify();
if (top->IsVisBranch()) {
fGeoManager->PushPath();
fGeoManager->cd(fVisBranch.Data());
Int_t transparency;
while (fGeoManager->GetLevel()) {
vol = fGeoManager->GetCurrentVolume();
if (!fVisLock) {
fVisVolumes->Add(vol);
vol->SetAttBit(TGeoAtt::kVisOnScreen);
}
fGeoManager->SetPaintVolume(vol);
transparency = vol->GetTransparency();
vol->SetTransparency(40);
if (!strstr(option,"range")) ((TAttLine*)vol)->Modify();
if (global) {
*fGlobal = *global;
*fGlobal *= *fGeoManager->GetCurrentMatrix();
} else {
*fGlobal = fGeoManager->GetCurrentMatrix();
}
fGeoManager->SetMatrixReflection(fGlobal->IsReflection());
PaintShape(*(vol->GetShape()),option);
vol->SetTransparency(transparency);
fGeoManager->CdUp();
}
fVisLock = kTRUE;
fGeoManager->PopPath();
fGeoManager->SetMatrixReflection(kFALSE);
return;
}
if ((fTopVisible && vis) || !top->GetNdaughters() || !top->IsVisDaughters() || top->IsVisOnly()) {
fGeoManager->SetPaintVolume(vol);
fGeoManager->SetMatrixReflection(fGlobal->IsReflection());
drawDaughters = PaintShape(*(vol->GetShape()),option);
if (!fVisLock && !vol->TestAttBit(TGeoAtt::kVisOnScreen)) {
fVisVolumes->Add(vol);
vol->SetAttBit(TGeoAtt::kVisOnScreen);
}
if (top->IsVisOnly() || !top->GetNdaughters() || !top->IsVisDaughters()) {
fVisLock = kTRUE;
return;
}
}
TGeoIterator next(vol);
if (fPlugin) next.SetUserPlugin(fPlugin);
TGeoNode *daughter;
Int_t level, nd;
Bool_t last;
Int_t line_color=0, line_width=0, line_style=0;
while ((daughter=next())) {
vol = daughter->GetVolume();
fGeoManager->SetPaintVolume(vol);
level = next.GetLevel();
nd = daughter->GetNdaughters();
vis = daughter->IsVisible();
drawDaughters = kTRUE;
if (top->IsVisContainers()) {
if (vis && level<=fVisLevel) {
if (fPlugin) {
line_color = vol->GetLineColor();
line_width = vol->GetLineWidth();
line_style = vol->GetLineStyle();
fPlugin->ProcessNode();
}
if (!strstr(option,"range")) ((TAttLine*)vol)->Modify();
if (global) {
*fGlobal = *global;
*fGlobal *= *next.GetCurrentMatrix();
} else {
*fGlobal = next.GetCurrentMatrix();
}
fGeoManager->SetMatrixReflection(fGlobal->IsReflection());
drawDaughters = PaintShape(*(vol->GetShape()),option);
if (fPlugin) {
vol->SetLineColor(line_color);
vol->SetLineWidth(line_width);
vol->SetLineStyle(line_style);
}
if (!fVisLock && !daughter->IsOnScreen()) {
fVisVolumes->Add(vol);
vol->SetAttBit(TGeoAtt::kVisOnScreen);
}
}
if (!drawDaughters || level==fVisLevel || !daughter->IsVisDaughters()) {
next.Skip();
continue;
}
} else if (top->IsVisLeaves()) {
last = ((nd==0) || (level==fVisLevel) || (!daughter->IsVisDaughters()))?kTRUE:kFALSE;
if (vis && last) {
if (fPlugin) {
line_color = vol->GetLineColor();
line_width = vol->GetLineWidth();
line_style = vol->GetLineStyle();
fPlugin->ProcessNode();
}
if (!strstr(option,"range")) ((TAttLine*)vol)->Modify();
if (global) {
*fGlobal = *global;
*fGlobal *= *next.GetCurrentMatrix();
} else {
*fGlobal = next.GetCurrentMatrix();
}
fGeoManager->SetMatrixReflection(fGlobal->IsReflection());
drawDaughters = PaintShape(*(vol->GetShape()),option);
if (fPlugin) {
vol->SetLineColor(line_color);
vol->SetLineWidth(line_width);
vol->SetLineStyle(line_style);
}
if (!fVisLock && !daughter->IsOnScreen()) {
fVisVolumes->Add(vol);
vol->SetAttBit(TGeoAtt::kVisOnScreen);
}
}
if (!drawDaughters || last || !daughter->IsVisDaughters()) next.Skip();
}
}
if (fPlugin) fPlugin->SetIterator(0);
fGeoManager->SetMatrixReflection(kFALSE);
fVisLock = kTRUE;
}
Bool_t TGeoPainter::PaintShape(const TGeoShape & shape, Option_t * option ) const
{
Bool_t addDaughters = kTRUE;
TVirtualViewer3D * viewer = gPad->GetViewer3D();
if (!viewer || shape.IsA()==TGeoShapeAssembly::Class()) {
return addDaughters;
}
if (!shape.IsComposite()) {
Bool_t localFrame = viewer->PreferLocalFrame();
const TBuffer3D & buffer =
shape.GetBuffer3D(TBuffer3D::kCore|TBuffer3D::kBoundingBox|TBuffer3D::kShapeSpecific, localFrame);
Int_t reqSections = viewer->AddObject(buffer, &addDaughters);
if (reqSections != TBuffer3D::kNone) {
shape.GetBuffer3D(reqSections, localFrame);
viewer->AddObject(buffer, &addDaughters);
}
}
else {
const TGeoCompositeShape * composite = static_cast<const TGeoCompositeShape *>(&shape);
addDaughters = composite->PaintComposite(option);
}
return addDaughters;
}
void TGeoPainter::PaintShape(TGeoShape *shape, Option_t *option)
{
TGeoShape::SetTransform(fGlobal);
fGlobal->Clear();
fGeoManager->SetPaintVolume(0);
PaintShape(*shape,option);
}
void TGeoPainter::PaintPhysicalNode(TGeoPhysicalNode *node, Option_t *option)
{
if (!node->IsVisible()) return;
Int_t level = node->GetLevel();
Int_t i, col, wid, sty;
TGeoShape *shape;
TGeoShape::SetTransform(fGlobal);
TGeoHMatrix *matrix = fGlobal;
TGeoVolume *vcrt;
if (!node->IsVisibleFull()) {
vcrt = node->GetVolume();
if (!strstr(option,"range")) ((TAttLine*)vcrt)->Modify();
shape = vcrt->GetShape();
*matrix = node->GetMatrix();
fGeoManager->SetMatrixReflection(matrix->IsReflection());
fGeoManager->SetPaintVolume(vcrt);
if (!node->IsVolAttributes() && !strstr(option,"range")) {
col = vcrt->GetLineColor();
wid = vcrt->GetLineWidth();
sty = vcrt->GetLineStyle();
vcrt->SetLineColor(node->GetLineColor());
vcrt->SetLineWidth(node->GetLineWidth());
vcrt->SetLineStyle(node->GetLineStyle());
((TAttLine*)vcrt)->Modify();
PaintShape(*shape,option);
vcrt->SetLineColor(col);
vcrt->SetLineWidth(wid);
vcrt->SetLineStyle(sty);
} else {
PaintShape(*shape,option);
}
} else {
for (i=1;i<=level; i++) {
vcrt = node->GetVolume(i);
if (!strstr(option,"range")) ((TAttLine*)vcrt)->Modify();
shape = vcrt->GetShape();
*matrix = node->GetMatrix(i);
fGeoManager->SetMatrixReflection(matrix->IsReflection());
fGeoManager->SetPaintVolume(vcrt);
if (!node->IsVolAttributes() && !strstr(option,"range")) {
col = vcrt->GetLineColor();
wid = vcrt->GetLineWidth();
sty = vcrt->GetLineStyle();
vcrt->SetLineColor(node->GetLineColor());
vcrt->SetLineWidth(node->GetLineWidth());
vcrt->SetLineStyle(node->GetLineStyle());
((TAttLine*)vcrt)->Modify();
PaintShape(*shape,option);
vcrt->SetLineColor(col);
vcrt->SetLineWidth(wid);
vcrt->SetLineStyle(sty);
} else {
PaintShape(*shape,option);
}
}
}
fGeoManager->SetMatrixReflection(kFALSE);
}
void TGeoPainter::PrintOverlaps() const
{
fChecker->PrintOverlaps();
}
void TGeoPainter::OpProgress(const char *opname, Long64_t current, Long64_t size, TStopwatch *watch, Bool_t last, Bool_t refresh)
{
fChecker->OpProgress(opname,current,size,watch,last,refresh);
}
void TGeoPainter::RandomPoints(const TGeoVolume *vol, Int_t npoints, Option_t *option)
{
fChecker->RandomPoints((TGeoVolume*)vol, npoints, option);
}
void TGeoPainter::RandomRays(Int_t nrays, Double_t startx, Double_t starty, Double_t startz)
{
fChecker->RandomRays(nrays, startx, starty, startz);
}
void TGeoPainter::Raytrace(Option_t * )
{
if (!gPad || gPad->IsBatch()) return;
TView *view = gPad->GetView();
if (!view) return;
TGeoVolume *top = fGeoManager->GetTopVolume();
if (top != fTopVolume) fGeoManager->SetTopVolume(fTopVolume);
if (!view->IsPerspective()) view->SetPerspective();
gVirtualX->SetMarkerSize(1);
gVirtualX->SetMarkerStyle(1);
Int_t i;
Bool_t inclipst=kFALSE, inclip=kFALSE;
Double_t krad = TMath::DegToRad();
Double_t lat = view->GetLatitude();
Double_t longit = view->GetLongitude();
Double_t psi = view->GetPsi();
Double_t c1 = TMath::Cos(psi*krad);
Double_t s1 = TMath::Sin(psi*krad);
Double_t c2 = TMath::Cos(lat*krad);
Double_t s2 = TMath::Sin(lat*krad);
Double_t s3 = TMath::Cos(longit*krad);
Double_t c3 = -TMath::Sin(longit*krad);
fMat[0] = c1*c3 - s1*c2*s3;
fMat[1] = c1*s3 + s1*c2*c3;
fMat[2] = s1*s2;
fMat[3] = -s1*c3 - c1*c2*s3;
fMat[4] = -s1*s3 + c1*c2*c3;
fMat[5] = c1*s2;
fMat[6] = s2*s3;
fMat[7] = -s2*c3;
fMat[8] = c2;
Double_t u0, v0, du, dv;
view->GetWindow(u0,v0,du,dv);
Double_t dview = view->GetDview();
Double_t dproj = view->GetDproj();
Double_t local[3] = {0,0,1};
Double_t dir[3], normal[3];
LocalToMasterVect(local,dir);
Double_t min[3], max[3];
view->GetRange(min, max);
Double_t cov[3];
for (i=0; i<3; i++) cov[i] = 0.5*(min[i]+max[i]);
Double_t cop[3];
for (i=0; i<3; i++) cop[i] = cov[i] - dir[i]*dview;
fGeoManager->InitTrack(cop, dir);
Bool_t outside = fGeoManager->IsOutside();
fGeoManager->DoBackupState();
if (fClippingShape) inclipst = inclip = fClippingShape->Contains(cop);
Int_t px, py;
Double_t xloc, yloc, modloc;
Int_t pxmin,pxmax, pymin,pymax;
pxmin = gPad->UtoAbsPixel(0);
pxmax = gPad->UtoAbsPixel(1);
pymin = gPad->VtoAbsPixel(1);
pymax = gPad->VtoAbsPixel(0);
TGeoNode *next, *nextnode;
Double_t step,steptot;
Double_t *norm;
const Double_t *point = fGeoManager->GetCurrentPoint();
Double_t *ppoint = (Double_t*)point;
Double_t tosource[3];
Double_t calf;
Double_t phi = 0*krad;
tosource[0] = -dir[0]*TMath::Cos(phi)+dir[1]*TMath::Sin(phi);
tosource[1] = -dir[0]*TMath::Sin(phi)-dir[1]*TMath::Cos(phi);
tosource[2] = -dir[2];
Bool_t done;
Int_t base_color, color;
Double_t light;
Double_t stemin=0, stemax=TGeoShape::Big();
TPoint *pxy = new TPoint[1];
TGeoVolume *nextvol;
Int_t up;
Int_t ntotal = pxmax*pymax;
Int_t nrays = 0;
TStopwatch *timer = new TStopwatch();
timer->Start();
for (px=pxmin; px<pxmax; px++) {
for (py=pymin; py<pymax; py++) {
if ((nrays%100)==0) OpProgress("Raytracing",nrays,ntotal,timer,kFALSE);
nrays++;
base_color = 1;
steptot = 0;
inclip = inclipst;
xloc = gPad->AbsPixeltoX(pxmin+pxmax-px);
xloc = xloc*du-u0;
yloc = gPad->AbsPixeltoY(pymin+pymax-py);
yloc = yloc*dv-v0;
modloc = TMath::Sqrt(xloc*xloc+yloc*yloc+dproj*dproj);
local[0] = xloc/modloc;
local[1] = yloc/modloc;
local[2] = dproj/modloc;
LocalToMasterVect(local,dir);
fGeoManager->DoRestoreState();
fGeoManager->SetOutside(outside);
fGeoManager->SetCurrentPoint(cop);
fGeoManager->SetCurrentDirection(dir);
done = kFALSE;
norm = 0;
if (fClippingShape) {
if (inclip) {
stemin = fClippingShape->DistFromInside(cop,dir,3);
stemax = TGeoShape::Big();
} else {
stemax = fClippingShape->DistFromOutside(cop,dir,3);
stemin = 0;
}
}
while (!done) {
if (fClippingShape) {
if (stemin>1E10) break;
if (stemin>0) {
fGeoManager->SetStep(stemin);
next = fGeoManager->Step();
steptot = 0;
stemin = 0;
up = 0;
while (next) {
nextvol = next->GetVolume();
if (nextvol->TestAttBit(TGeoAtt::kVisOnScreen)) {
done = kTRUE;
base_color = nextvol->GetLineColor();
fClippingShape->ComputeNormal(ppoint, dir, normal);
norm = normal;
break;
}
up++;
next = fGeoManager->GetMother(up);
}
if (done) break;
inclip = fClippingShape->Contains(ppoint);
fGeoManager->SetStep(1E-3);
while (inclip) {
fGeoManager->Step();
inclip = fClippingShape->Contains(ppoint);
}
stemax = fClippingShape->DistFromOutside(ppoint,dir,3);
}
}
nextnode = fGeoManager->FindNextBoundaryAndStep();
step = fGeoManager->GetStep();
if (step>1E10) break;
steptot += step;
next = nextnode;
if (fClippingShape) {
if (steptot>stemax) {
steptot = 0;
inclip = fClippingShape->Contains(ppoint);
if (inclip) {
stemin = fClippingShape->DistFromInside(ppoint,dir,3);
stemax = TGeoShape::Big();
continue;
} else {
stemin = 0;
stemax = fClippingShape->DistFromOutside(ppoint,dir,3);
}
}
}
if (!nextnode) continue;
nextvol = nextnode->GetVolume();
if (nextvol->TestAttBit(TGeoAtt::kVisOnScreen)) {
done = kTRUE;
base_color = nextvol->GetLineColor();
next = nextnode;
break;
}
}
if (!done) continue;
if (!norm) norm = fGeoManager->FindNormalFast();
if (!norm) continue;
calf = norm[0]*tosource[0]+norm[1]*tosource[1]+norm[2]*tosource[2];
light = 0.25+0.5*TMath::Abs(calf);
color = GetColor(base_color, light);
gVirtualX->SetMarkerColor(color);
pxy[0].fX = px;
pxy[0].fY = py;
gVirtualX->DrawPolyMarker(1,pxy);
}
}
delete [] pxy;
timer->Stop();
fChecker->OpProgress("Raytracing",nrays,ntotal,timer,kTRUE);
delete timer;
}
TGeoNode *TGeoPainter::SamplePoints(Int_t npoints, Double_t &dist, Double_t epsil,
const char* g3path)
{
return fChecker->SamplePoints(npoints, dist, epsil, g3path);
}
void TGeoPainter::SetBombFactors(Double_t bombx, Double_t bomby, Double_t bombz, Double_t bombr)
{
fBombX = bombx;
fBombY = bomby;
fBombZ = bombz;
fBombR = bombr;
if (IsExplodedView()) ModifiedPad();
}
void TGeoPainter::SetExplodedView(Int_t ibomb)
{
if ((ibomb<0) || (ibomb>3)) {
Warning("SetExplodedView", "exploded view can be 0-3");
return;
}
if ((Int_t)ibomb==fExplodedView) return;
Bool_t change = (gPad==0)?kFALSE:kTRUE;
if (ibomb==kGeoNoBomb) {
change &= ((fExplodedView==kGeoNoBomb)?kFALSE:kTRUE);
}
if (ibomb==kGeoBombXYZ) {
change &= ((fExplodedView==kGeoBombXYZ)?kFALSE:kTRUE);
}
if (ibomb==kGeoBombCyl) {
change &= ((fExplodedView==kGeoBombCyl)?kFALSE:kTRUE);
}
if (ibomb==kGeoBombSph) {
change &= ((fExplodedView==kGeoBombSph)?kFALSE:kTRUE);
}
fExplodedView = ibomb;
if (change) ModifiedPad();
}
void TGeoPainter::SetNsegments(Int_t nseg)
{
if (nseg<3) {
Warning("SetNsegments", "number of segments should be > 2");
return;
}
if (fNsegments==nseg) return;
fNsegments = nseg;
ModifiedPad();
}
void TGeoPainter::SetNmeshPoints(Int_t npoints) {
fChecker->SetNmeshPoints(npoints);
}
void TGeoPainter::SetCheckedNode(TGeoNode *node) {
fChecker->SetSelectedNode(node);
}
void TGeoPainter::SetVisLevel(Int_t level) {
if (level==fVisLevel && fLastVolume==fTopVolume) return;
fVisLevel=level;
if (!fTopVolume) return;
if (fVisLock) {
ClearVisibleVolumes();
fVisLock = kFALSE;
}
if (!fLastVolume) {
return;
}
if (!gPad) return;
if (gPad->GetView()) {
ModifiedPad();
}
}
void TGeoPainter::SetTopVisible(Bool_t vis)
{
if (fTopVisible==vis) return;
fTopVisible = vis;
ModifiedPad();
}
void TGeoPainter::SetVisOption(Int_t option) {
if ((fVisOption<0) || (fVisOption>4)) {
Warning("SetVisOption", "wrong visualization option");
return;
}
if (option == kGeoVisChanged) {
if (fVisLock) {
ClearVisibleVolumes();
fVisLock = kFALSE;
}
ModifiedPad();
return;
}
if (fTopVolume) {
TGeoAtt *att = (TGeoAtt*)fTopVolume;
att->SetAttBit(TGeoAtt::kVisBranch,kFALSE);
att->SetAttBit(TGeoAtt::kVisContainers,kFALSE);
att->SetAttBit(TGeoAtt::kVisOnly,kFALSE);
switch (option) {
case kGeoVisDefault:
att->SetAttBit(TGeoAtt::kVisContainers,kTRUE);
break;
case kGeoVisLeaves:
break;
case kGeoVisOnly:
att->SetAttBit(TGeoAtt::kVisOnly,kTRUE);
break;
}
}
if (fVisOption==option) return;
fVisOption=option;
if (fVisLock) {
ClearVisibleVolumes();
fVisLock = kFALSE;
}
ModifiedPad();
}
Int_t TGeoPainter::ShapeDistancetoPrimitive(const TGeoShape *shape, Int_t numpoints, Int_t px, Int_t py) const
{
const Int_t inaxis = 7;
const Int_t maxdist = 5;
const Int_t big = 9999;
Int_t dist = big;
if (!gPad) return dist;
TView *view = gPad->GetView();
if (!(numpoints && view)) return dist;
if (shape->IsA()==TGeoShapeAssembly::Class()) return dist;
if (fIsPaintingShape) {
Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
if (px < puxmin - inaxis) return big;
if (py > puymin + inaxis) return big;
if (px > puxmax + inaxis) return big;
if (py < puymax - inaxis) return big;
if ((puxmax+inaxis-px) < 40) {
gPad->SetSelected(fGeoManager);
return 0;
}
}
fBuffer->SetRawSizes(numpoints, 3*numpoints, 0, 0, 0, 0);
Double_t *points = fBuffer->fPnts;
shape->SetPoints(points);
Double_t dpoint2, x1, y1, xndc[3];
Double_t dmaster[3];
Int_t j;
for (Int_t i=0; i<numpoints; i++) {
j = 3*i;
TGeoShape::GetTransform()->LocalToMaster(&points[j], dmaster);
points[j]=dmaster[0]; points[j+1]=dmaster[1]; points[j+2]=dmaster[2];
view->WCtoNDC(&points[j], xndc);
x1 = gPad->XtoAbsPixel(xndc[0]);
y1 = gPad->YtoAbsPixel(xndc[1]);
dpoint2 = (px-x1)*(px-x1) + (py-y1)*(py-y1);
if (dpoint2 < dist) dist=(Int_t)dpoint2;
}
if (dist > 100) return dist;
dist = Int_t(TMath::Sqrt(Double_t(dist)));
if (dist<maxdist && fIsPaintingShape) gPad->SetSelected((TObject*)shape);
return dist;
}
void TGeoPainter::Test(Int_t npoints, Option_t *option)
{
fChecker->Test(npoints, option);
}
void TGeoPainter::TestOverlaps(const char* path)
{
fChecker->TestOverlaps(path);
}
Bool_t TGeoPainter::TestVoxels(TGeoVolume *vol)
{
return fChecker->TestVoxels(vol);
}
void TGeoPainter::UnbombTranslation(const Double_t *tr, Double_t *bombtr)
{
memcpy(bombtr, tr, 3*sizeof(Double_t));
switch (fExplodedView) {
case kGeoNoBomb:
return;
case kGeoBombXYZ:
bombtr[0] /= fBombX;
bombtr[1] /= fBombY;
bombtr[2] /= fBombZ;
return;
case kGeoBombCyl:
bombtr[0] /= fBombR;
bombtr[1] /= fBombR;
bombtr[2] /= fBombZ;
return;
case kGeoBombSph:
bombtr[0] /= fBombR;
bombtr[1] /= fBombR;
bombtr[2] /= fBombR;
return;
default:
return;
}
}
Double_t TGeoPainter::Weight(Double_t precision, Option_t *option)
{
return fChecker->Weight(precision, option);
}