#include "TEveGeoNode.h"
#include "TEveTrans.h"
#include "TEveManager.h"
#include "TEvePolygonSetProjected.h"
#include "TEveGeoShapeExtract.h"
#include "TEvePad.h"
#include "TEveGeoPolyShape.h"
#include "TGLScenePad.h"
#include "TGLFaceSet.h"
#include "TROOT.h"
#include "TBuffer3D.h"
#include "TVirtualViewer3D.h"
#include "TColor.h"
#include "TFile.h"
#include "TGeoShape.h"
#include "TGeoVolume.h"
#include "TGeoNode.h"
#include "TGeoShapeAssembly.h"
#include "TGeoCompositeShape.h"
#include "TGeoManager.h"
#include "TGeoMatrix.h"
#include "TVirtualGeoPainter.h"
ClassImp(TEveGeoNode);
Int_t TEveGeoNode::fgCSGExportNSeg = 64;
std::list<TGeoShape*> TEveGeoNode::fgTemporaryStore;
Int_t TEveGeoNode::GetCSGExportNSeg()
{
return fgCSGExportNSeg;
}
void TEveGeoNode::SetCSGExportNSeg(Int_t nseg)
{
fgCSGExportNSeg = nseg;
}
TEveGeoNode::TEveGeoNode(TGeoNode* node) :
TEveElement(),
TObject(),
fNode(node)
{
char* l = (char*) dynamic_cast<TAttLine*>(node->GetVolume());
SetMainColorPtr((Color_t*)(l + sizeof(void*)));
SetMainTransparency((UChar_t) fNode->GetVolume()->GetTransparency());
fRnrSelf = fNode->TGeoAtt::IsVisible();
}
const char* TEveGeoNode::GetName() const
{
return fNode->GetName();
}
const char* TEveGeoNode::GetTitle() const
{
return fNode->GetTitle();
}
const char* TEveGeoNode::GetElementName() const
{
return fNode->GetName();
}
const char* TEveGeoNode::GetElementTitle() const
{
return fNode->GetTitle();
}
void TEveGeoNode::ExpandIntoListTree(TGListTree* ltree,
TGListTreeItem* parent)
{
if (fChildren.empty() && fNode->GetVolume()->GetNdaughters() > 0) {
TIter next(fNode->GetVolume()->GetNodes());
TGeoNode* dnode;
while ((dnode = (TGeoNode*) next()) != 0) {
TEveGeoNode* node_re = new TEveGeoNode(dnode);
AddElement(node_re);
}
}
TEveElement::ExpandIntoListTree(ltree, parent);
}
void TEveGeoNode::ExpandIntoListTrees()
{
for (sLTI_i i = fItems.begin(); i != fItems.end(); ++i)
{
ExpandIntoListTree(i->fTree, i->fItem);
}
}
void TEveGeoNode::ExpandIntoListTreesRecursively()
{
ExpandIntoListTrees();
for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
{
TEveGeoNode *egn = dynamic_cast<TEveGeoNode*>(*i);
if (egn)
egn->ExpandIntoListTreesRecursively();
}
}
void TEveGeoNode::AddStamp(UChar_t bits)
{
TEveElement::AddStamp(bits);
if (bits & kCBVisibility)
{
fNode->SetVisibility(fRnrSelf);
fNode->VisibleDaughters(fRnrChildren);
}
}
Bool_t TEveGeoNode::CanEditMainColor() const
{
return ! fNode->GetVolume()->IsAssembly();
}
void TEveGeoNode::SetMainColor(Color_t color)
{
TEveElement::SetMainColor(color);
fNode->GetVolume()->SetLineColor(color);
}
Bool_t TEveGeoNode::CanEditMainTransparency() const
{
return ! fNode->GetVolume()->IsAssembly();
}
UChar_t TEveGeoNode::GetMainTransparency() const
{
UChar_t t = (UChar_t) fNode->GetVolume()->GetTransparency();
if (fMainTransparency != t)
{
TEveGeoNode* ncthis = const_cast<TEveGeoNode*>(this);
ncthis->SetMainTransparency(t);
}
return t;
}
void TEveGeoNode::SetMainTransparency(UChar_t t)
{
TEveElement::SetMainTransparency(t);
fNode->GetVolume()->SetTransparency((Char_t) t);
}
void TEveGeoNode::UpdateNode(TGeoNode* node)
{
static const TEveException eH("TEveGeoNode::UpdateNode ");
if (fNode == node)
StampColorSelection();
for (List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
((TEveGeoNode*)(*i))->UpdateNode(node);
}
}
void TEveGeoNode::UpdateVolume(TGeoVolume* volume)
{
static const TEveException eH("TEveGeoNode::UpdateVolume ");
if(fNode->GetVolume() == volume)
StampColorSelection();
for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
((TEveGeoNode*)(*i))->UpdateVolume(volume);
}
}
void TEveGeoNode::Draw(Option_t* option)
{
TString opt("SAME");
opt += option;
fNode->GetVolume()->Draw(opt);
}
void TEveGeoNode::Save(const char* file, const char* name, Bool_t leafs_only)
{
Warning("Save()", "This function is deprecated, use SaveExtract() instead.");
SaveExtract(file, name, leafs_only);
}
void TEveGeoNode::SaveExtract(const char* file, const char* name, Bool_t leafs_only)
{
TEveGeoShapeExtract* gse = DumpShapeTree(this, 0, leafs_only);
TFile f(file, "RECREATE");
gse->Write(name);
f.Close();
for (std::list<TGeoShape*>::iterator i = fgTemporaryStore.begin(); i != fgTemporaryStore.end(); ++i)
delete *i;
fgTemporaryStore.clear();
}
void TEveGeoNode::WriteExtract(const char* name, Bool_t leafs_only)
{
TEveGeoShapeExtract* gse = DumpShapeTree(this, 0, leafs_only);
gse->Write(name);
}
TEveGeoShapeExtract* TEveGeoNode::DumpShapeTree(TEveGeoNode* geon,
TEveGeoShapeExtract* parent,
Bool_t leafs_only)
{
static const TEveException eh("TEveGeoNode::DumpShapeTree ");
TGeoNode* tnode = 0;
TGeoVolume* tvolume = 0;
TGeoShape* tshape = 0;
tnode = geon->GetNode();
if (tnode == 0)
{
Info(eh, "Null TGeoNode for TEveGeoNode '%s': assuming it's a holder and descending.", geon->GetName());
}
else
{
tvolume = tnode->GetVolume();
if (tvolume == 0) {
Warning(eh, "Null TGeoVolume for TEveGeoNode '%s'; skipping its sub-tree.\n", geon->GetName());
return 0;
}
tshape = tvolume->GetShape();
if (tshape->IsComposite())
{
TEvePad pad;
TEvePadHolder gpad(kFALSE, &pad);
pad.GetListOfPrimitives()->Add(tshape);
TGLScenePad scene_pad(&pad);
pad.SetViewer3D(&scene_pad);
TEveGeoManagerHolder gmgr(tvolume->GetGeoManager());
gGeoManager->SetPaintVolume(tvolume);
Int_t nseg = gGeoManager->GetNsegments();
gGeoManager->SetNsegments(fgCSGExportNSeg);
Bool_t had_null_transform = kFALSE;
if (tshape->GetTransform() == 0) {
had_null_transform = kTRUE;
tshape->SetTransform(gGeoIdentity);
}
scene_pad.BeginScene();
dynamic_cast<TGeoCompositeShape*>(tshape)->PaintComposite();
scene_pad.EndScene();
if (had_null_transform) {
tshape->SetTransform(0);
}
gGeoManager->SetNsegments(nseg);
pad.SetViewer3D(0);
TGLFaceSet* fs = dynamic_cast<TGLFaceSet*>(scene_pad.FindLogical(tvolume));
if (!fs) {
Warning(eh, "Failed extracting CSG tesselation TEveGeoNode '%s'; skipping its sub-tree.\n", geon->GetName());
return 0;
}
TEveGeoPolyShape* egps = new TEveGeoPolyShape();
egps->SetFromFaceSet(fs);
tshape = egps;
fgTemporaryStore.push_back(egps);
}
}
TEveTrans trans;
if (parent)
trans.SetFromArray(parent->GetTrans());
if (tnode)
{
TGeoMatrix *gm = tnode->GetMatrix();
const Double_t *rm = gm->GetRotationMatrix();
const Double_t *tv = gm->GetTranslation();
TEveTrans t;
t(1,1) = rm[0]; t(1,2) = rm[1]; t(1,3) = rm[2];
t(2,1) = rm[3]; t(2,2) = rm[4]; t(2,3) = rm[5];
t(3,1) = rm[6]; t(3,2) = rm[7]; t(3,3) = rm[8];
t(1,4) = tv[0]; t(2,4) = tv[1]; t(3,4) = tv[2];
trans *= t;
}
TEveGeoShapeExtract* gse = new TEveGeoShapeExtract(geon->GetName(), geon->GetTitle());
gse->SetTrans(trans.Array());
Int_t ci = 0;
if (tvolume) ci = tvolume->GetLineColor();
TColor* c = gROOT->GetColor(ci);
Float_t rgba[4] = {1, 0, 0, 1};
if (c) {
rgba[0] = c->GetRed();
rgba[1] = c->GetGreen();
rgba[2] = c->GetBlue();
}
gse->SetRGBA(rgba);
Bool_t rnr = tnode ? tnode->IsVisible() : geon->GetRnrSelf();
Bool_t rnr_els = tnode ? tnode->IsVisDaughters() : geon->GetRnrChildren();
if (tvolume) {
rnr = rnr && tvolume->IsVisible();
rnr_els = rnr_els && tvolume->IsVisDaughters();
}
gse->SetRnrSelf (rnr);
gse->SetRnrElements(rnr_els);
gse->SetShape((leafs_only && geon->HasChildren()) ? 0 : tshape);
if (geon->HasChildren())
{
TList* ele = new TList();
gse->SetElements(ele);
gse->GetElements()->SetOwner(true);
TEveElement::List_i i = geon->BeginChildren();
while (i != geon->EndChildren())
{
TEveGeoNode* l = dynamic_cast<TEveGeoNode*>(*i);
DumpShapeTree(l, gse, leafs_only);
++i;
}
}
if (parent)
parent->GetElements()->Add(gse);
return gse;
}
ClassImp(TEveGeoTopNode);
TEveGeoTopNode::TEveGeoTopNode(TGeoManager* manager, TGeoNode* node,
Int_t visopt, Int_t vislvl, Int_t maxvisnds) :
TEveGeoNode (node),
fManager (manager),
fVisOption (visopt),
fVisLevel (vislvl),
fMaxVisNodes (maxvisnds)
{
InitMainTrans();
fRnrSelf = kTRUE;
}
void TEveGeoTopNode::UseNodeTrans()
{
RefMainTrans().SetFrom(*fNode->GetMatrix());
}
void TEveGeoTopNode::AddStamp(UChar_t bits)
{
TEveElement::AddStamp(bits);
}
void TEveGeoTopNode::Draw(Option_t* option)
{
AppendPad(option);
}
void TEveGeoTopNode::Paint(Option_t* option)
{
if (fRnrSelf) {
gGeoManager = fManager;
TVirtualPad* pad = gPad;
gPad = 0;
TGeoVolume* top_volume = fManager->GetTopVolume();
fManager->SetVisOption(fVisOption);
if (fVisLevel > 0)
fManager->SetVisLevel(fVisLevel);
else
fManager->SetMaxVisNodes(fMaxVisNodes);
fManager->SetTopVolume(fNode->GetVolume());
gPad = pad;
TVirtualGeoPainter* vgp = fManager->GetGeomPainter();
if(vgp != 0) {
TGeoHMatrix geomat;
if (HasMainTrans()) RefMainTrans().SetGeoHMatrix(geomat);
vgp->PaintNode(fNode, option, &geomat);
}
fManager->SetTopVolume(top_volume);
}
}
void TEveGeoTopNode::VolumeVisChanged(TGeoVolume* volume)
{
static const TEveException eh("TEveGeoTopNode::VolumeVisChanged ");
printf("%s volume %s %p\n", eh.Data(), volume->GetName(), (void*)volume);
UpdateVolume(volume);
}
void TEveGeoTopNode::VolumeColChanged(TGeoVolume* volume)
{
static const TEveException eh("TEveGeoTopNode::VolumeColChanged ");
printf("%s volume %s %p\n", eh.Data(), volume->GetName(), (void*)volume);
UpdateVolume(volume);
}
void TEveGeoTopNode::NodeVisChanged(TGeoNode* node)
{
static const TEveException eh("TEveGeoTopNode::NodeVisChanged ");
printf("%s node %s %p\n", eh.Data(), node->GetName(), (void*)node);
UpdateNode(node);
}