#include "Riostream.h"
#include <assert.h>
#include <stdlib.h>
#include "TCanvas.h"
#include "TPad.h"
#include "TCernLib.h"
#include "TBrowser.h"
#include "TVolumeView.h"
#include "TVolumeViewIter.h"
#include "TVolumePosition.h"
#include "TROOT.h"
#include "TView.h"
#include "TTablePadView3D.h"
#include "TGeometry.h"
#include "TVirtualPad.h"
#include "TObjArray.h"
#include "TVirtualViewer3D.h"
#include "TBuffer3D.h"
ClassImp(TVolumeView)
TVolumeView::TVolumeView(TVolumeView *viewNode,TVolumePosition *nodePosition)
: TObjectSet(viewNode->GetName(),(TObject *)nodePosition),fListOfShapes(0)
{
if (!gGeometry) new TGeometry;
if (viewNode) {
SetTitle(viewNode->GetTitle());
EDataSetPass mode = kContinue;
TVolumeViewIter next(viewNode,0);
TVolumeView *nextView = 0;
while ( (nextView = (TVolumeView *)next(mode)) ){
mode = kContinue;
if (nextView->IsMarked()) {
TVolumePosition *position =next[0];
if (!position->GetNode()) {
Error("TVolumeView ctor","%s %s ",GetName(),nextView->GetName());
}
Add(new TVolumeView(nextView,position));
mode = kPrune;
}
}
}
}
TVolumeView::TVolumeView(TVolumeView *viewNode,TVolumeView *topNode)
: TObjectSet(viewNode->GetName(),(TObject *)0),fListOfShapes(0)
{
if (!gGeometry) new TGeometry;
if (viewNode && topNode) {
SetTitle(viewNode->GetTitle());
EDataSetPass mode = kContinue;
TVolumeViewIter next(viewNode,0);
TVolumeView *nextView = 0;
while ( (nextView = (TVolumeView *)next(mode)) ){
mode = kContinue;
if (topNode != nextView) continue;
TVolumePosition *position = next[0];
if (!position->GetNode()) {
Error("TVolumeView ctor","%s %s ",GetName(),nextView->GetName());
}
Add(new TVolumeView(nextView,position));
break;
}
}
}
TVolumeView::TVolumeView(TVolumeView *viewNode,const Char_t *nodeName1,const Char_t *nodeName2)
: TObjectSet(viewNode->GetName(),(TObject *)0),fListOfShapes(0)
{
const Char_t *foundName[2] = {nodeName1, nodeName2};
Bool_t found = kFALSE;
if (!gGeometry) new TGeometry;
if (viewNode && nodeName1 && nodeName1[0]) {
SetTitle(viewNode->GetTitle());
EDataSetPass mode = kContinue;
TVolumeViewIter next(viewNode,0);
TVolumeView *nextView = 0;
while ( (nextView = (TVolumeView *)next(mode)) ){
mode = kContinue;
Int_t i = 0;
found = kFALSE;
for (i=0;i<2;i++) {
if (foundName[i]) {
if (strcmp(nextView->GetName(),foundName[i])) continue;
foundName[i] = 0;
found = kTRUE;
break;
}
}
if (!found) continue;
TVolumePosition *position = next[0];
if (!position->GetNode()) {
Error("TVolumeView ctor","%s %s ",GetName(),nextView->GetName());
}
Add(new TVolumeView(nextView,position));
mode = kPrune;
}
}
}
TVolumeView::TVolumeView(TVolumeView *viewNode,const TVolumeView *node1,const TVolumeView *node2)
: TObjectSet(viewNode->GetName(),(TObject *)0),fListOfShapes(0)
{
const TVolumeView *foundView[2] = {node1, node2};
const Int_t nViews = sizeof(foundView)/sizeof(const TVolumeView *);
Bool_t found = kFALSE;
if (!gGeometry) new TGeometry;
if (viewNode) {
SetTitle(viewNode->GetTitle());
EDataSetPass mode = kContinue;
TVolumeViewIter next(viewNode,0);
TVolumeView *nextView = 0;
while ( (nextView = (TVolumeView *)next(mode)) ){
mode = kContinue;
Int_t i = 0;
found = kFALSE;
for (i=0;i<nViews;i++) {
if (foundView[i]) {
if (nextView != foundView[i]) continue;
foundView[i] = 0;
found = kTRUE;
break;
}
}
if (!found) continue;
TVolumePosition *position = next[0];
if (!position->GetNode()) {
Error("TVolumeView ctor","%s %s ",GetName(),nextView->GetName());
}
Add(new TVolumeView(nextView,position));
mode = kPrune;
}
}
}
TVolumeView::TVolumeView(TVolume &pattern,Int_t maxDepLevel,
const TVolumePosition *nodePosition,EDataSetPass iopt, TVolumeView *rootVolume)
: TObjectSet(pattern.GetName(),(TObject *)nodePosition),fListOfShapes(0)
{
if (!gGeometry) new TGeometry;
if (!nodePosition) {
nodePosition = new TVolumePosition(&pattern);
SetObject((TObject*)nodePosition);
}
if (!rootVolume) {
rootVolume = this;
nodePosition = 0;
}
SetTitle(pattern.GetTitle());
if ( pattern.IsMarked() ) Mark();
TVolumePosition *position = 0;
const TList *list = pattern.GetListOfPositions();
if (!list || maxDepLevel == 1 || maxDepLevel < 0) return;
TIter nextPosition(list);
Bool_t optSel = (iopt == kStruct);
Bool_t optMarked = (iopt == kMarked);
const TRotMatrix *thisMatrix = 0;
Double_t thisTranslation[3] = {0,0,0};
if (nodePosition ) {
thisMatrix = nodePosition->GetMatrix();
for (int i =0; i< 3; i++) thisTranslation[i]= nodePosition->GetX(i);
}
while ( (position = (TVolumePosition *)nextPosition()) ) {
TVolume *node = position->GetNode();
Double_t *positionMatrix = ((TRotMatrix *)position->GetMatrix())->GetMatrix();
if (node) {
UInt_t positionId = position->GetId();
Double_t newTranslation[3] = {position->GetX(),position->GetY(),position->GetZ()};
Double_t newMatrix[9];
TRotMatrix currentMatrix;
if (nodePosition) {
if (positionMatrix) {
TGeometry::UpdateTempMatrix(thisTranslation,thisMatrix?((TRotMatrix *)thisMatrix)->GetMatrix():0
,position->GetX(),position->GetY(),position->GetZ(),positionMatrix
,newTranslation,newMatrix);
currentMatrix.SetMatrix(newMatrix);
} else {
TCL::vadd(thisTranslation, newTranslation,newTranslation,3);
currentMatrix.SetMatrix(((TRotMatrix *)thisMatrix)->GetMatrix());
}
} else {
if (positionMatrix)
currentMatrix.SetMatrix(positionMatrix);
else {
TCL::ucopy(thisTranslation,newTranslation,3);
currentMatrix.SetMatrix(TVolume::GetIdentity()->GetMatrix());
}
}
TVolumePosition nextPos(node,newTranslation[0],newTranslation[1],
newTranslation[2], ¤tMatrix);
nextPos.SetId(positionId);
if (optMarked && !node->IsMarked()) {
TVolumeView fakeView(*node,maxDepLevel,&nextPos,iopt,rootVolume);
fakeView.DoOwner(kFALSE);
continue;
}
if (optSel) {
TDataSet *parent = node->GetParent();
if ( parent && (parent != (TDataSet *)&pattern) ) continue;
}
TRotMatrix *newRotation = new TRotMatrix();
newRotation->SetMatrix(currentMatrix.GetMatrix());
TVolumePosition *nP = new TVolumePosition(node,newTranslation[0],newTranslation[1],
newTranslation[2], newRotation);
nP->SetId(positionId);
rootVolume->Add(new TVolumeView(*node,maxDepLevel?maxDepLevel-1:0,nP,iopt));
} else
Error("TVolumeView ctor","Position with NO node attached has been supplied");
}
}
TVolumeView::TVolumeView(TVolumeView &viewNode):
TObjectSet(viewNode.GetName(),(TObject *)viewNode.GetPosition())
,TAtt3D()
,fListOfShapes(viewNode.GetListOfShapes())
{
if (viewNode.IsOwner()) {
viewNode.DoOwner(kFALSE); DoOwner();
}
}
TVolumeView::TVolumeView(Double_t *translate, Double_t *rotate, UInt_t positionId, TVolume *topNode,
const Char_t *thisNodePath, const Char_t *matrixName, Int_t matrixType)
{
if (!gGeometry) new TGeometry;
fListOfShapes = 0;
TVolume *thisNode = 0;
Double_t thisX = translate[0];
Double_t thisY = translate[1];
Double_t thisZ = translate[2];
if (topNode) {
thisNode = (TVolume *)topNode->Find(thisNodePath);
if (!thisNode->InheritsFrom("TVolume")) {
thisNode = 0;
Error("TVolumeView","wrong node <%s> on path: \"%s\"",thisNode->GetName(),thisNodePath);
}
}
TRotMatrix *thisRotMatrix = 0;
if (matrixName && strlen(matrixName)) thisRotMatrix = gGeometry->GetRotMatrix(matrixName);
TVolumePosition *thisPosition = 0;
if (thisRotMatrix)
thisPosition = new TVolumePosition(thisNode,thisX, thisY, thisZ, matrixName);
else if (matrixType==2)
thisPosition = new TVolumePosition(thisNode,thisX, thisY, thisZ);
else if (rotate) {
const Char_t *title = "rotation";
thisRotMatrix = new TRotMatrix((char *)matrixName,(char *)title,rotate);
thisPosition = new TVolumePosition(thisNode,thisX, thisY, thisZ, thisRotMatrix);
} else
Error("TVolumeView"," No rotation matrix is defined");
thisPosition->SetId(positionId);
SetObject(thisPosition);
if (thisNode) {
SetName(thisNode->GetName());
SetTitle(thisNode->GetTitle());
}
}
TVolumeView::TVolumeView(TVolume *thisNode,TVolumePosition *nodePosition)
: TObjectSet(thisNode?thisNode->GetName():"",(TObject *)nodePosition),fListOfShapes(0)
{
if (!gGeometry) new TGeometry;
SafeDelete(fListOfShapes);
if (thisNode)
SetTitle(thisNode->GetTitle());
}
TVolumeView::~TVolumeView()
{
}
TVolume *TVolumeView::AddNode(TVolume *node)
{
TVolume *closedNode = 0;
TVolumePosition *pos ;
if ( node && (pos = GetPosition() ) && (closedNode = pos->GetNode()) )
closedNode->Add(node);
return closedNode;
}
void TVolumeView::Add(TShape *shape, Bool_t IsMaster)
{
if (!shape) return;
if (!fListOfShapes) fListOfShapes = new TList;
if (IsMaster)
fListOfShapes->AddFirst(shape);
else
fListOfShapes->Add(shape);
}
void TVolumeView::Browse(TBrowser *b)
{
TObjectSet::Browse(b);
}
Int_t TVolumeView::DistancetoPrimitive(Int_t px, Int_t py)
{
const Int_t big = 9999;
const Int_t inaxis = 7;
const Int_t maxdist = 5;
Int_t dist = big;
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;
TView *view =gPad->GetView();
if (!view) return big;
TVolumePosition *position = GetPosition();
TVolume *thisNode = 0;
TShape *thisShape = 0;
if (position) {
thisNode = position->GetNode();
position->UpdatePosition();
if (thisNode) {
thisShape = thisNode->GetShape();
if (!(thisNode->GetVisibility() & TVolume::kThisUnvisible) &&
thisShape && thisShape->GetVisibility()) {
dist = thisShape->DistancetoPrimitive(px,py);
if (dist < maxdist) {
gPad->SetSelected(this);
return 0;
}
}
}
}
TSeqCollection *fNodes = GetCollection();
Int_t nsons = fNodes?fNodes->GetSize():0;
Int_t dnode = dist;
if (nsons) {
gGeometry->PushLevel();
TVolume *node;
TIter next(fNodes);
while ((node = (TVolume *)next())) {
dnode = node->DistancetoPrimitive(px,py);
if (dnode <= 0) break;
if (dnode < dist) dist = dnode;
if (gGeometry->GeomLevel() > 2) break;
}
gGeometry->PopLevel();
}
if (gGeometry->GeomLevel()==0 && dnode > maxdist) {
gPad->SetSelected(view);
return 0;
} else
return dnode;
}
void TVolumeView::Draw(Option_t *option)
{
TString opt = option;
opt.ToLower();
if (!gPad) {
gROOT->MakeDefCanvas();
}
if (!opt.Contains("same")) gPad->Clear();
gGeometry->SetGeomLevel();
gGeometry->UpdateTempMatrix();
Int_t iopt = atoi(option);
TDataSet *parent = 0;
char buffer[10];
if (iopt < 0) {
sprintf(buffer,"%d",-iopt);
option = buffer;
parent = this;
do parent = parent->GetParent();
while (parent && ++iopt);
}
if (parent) parent->AppendPad(option);
else AppendPad(option);
#if ROOT_VERSION_CODE >= ROOT_VERSION(4,03,05)
TView *view = gPad->GetView();
if (!view) {
view = TView::CreateView(1,0,0);
view->SetAutoRange(kTRUE);
}
gPad->GetViewer3D(option);
#else
Paint(option);
#endif
}
TVolume *TVolumeView::GetNode() const
{
TVolumePosition *pos = GetPosition();
if (pos)
return pos->GetNode();
return 0;
}
Int_t TVolumeView::GetGlobalRange(const TVolumeView *rootNode,Float_t *globalMin,Float_t *globalMax)
{
if (rootNode) {
SetTitle(rootNode->GetTitle());
EDataSetPass mode = kContinue;
TVolumeViewIter next((TVolumeView *)rootNode,0);
TVolumeView *nextView = 0;
while ( (nextView = (TVolumeView *)next(mode)) && nextView != this ){}
if (nextView == this) {
TVolumePosition *position = next[0];
if (!position->GetNode()) {
Error("TVolumeView ctor","%s %s ",GetName(),nextView->GetName());
}
GetLocalRange(globalMin,globalMax);
Float_t offSet[3] = {position->GetX(),position->GetY(),position->GetZ()};
for (Int_t i=0;i<3;i++) {
globalMin[i] += offSet[i];
globalMax[i] += offSet[i];
}
}
return next.GetDepth();
}
else return -1;
}
void TVolumeView::GetLocalRange(Float_t *min, Float_t *max)
{
TVirtualPad *savePad = gPad;
TCanvas dummyPad("--Dumm--","dum",1,1);
TView *view = TView::CreateView(1,0,0);
gGeometry->SetGeomLevel();
gGeometry->UpdateTempMatrix();
view->SetAutoRange(kTRUE);
Paint("range");
view->GetRange(&min[0],&max[0]);
delete view;
if (savePad) savePad->cd();
}
char *TVolumeView::GetObjectInfo(Int_t px, Int_t py) const
{
if (!gPad) return 0;
static char info[512];
Double_t x[3] = {0,0,0.5};
((TPad *)gPad)->AbsPixeltoXY(px,py,x[0],x[1]);
TView *view =gPad->GetView();
if (view) {
Double_t min[3], max[3];
view->GetRange(min,max);
for (int i =0; i<3;i++) min[i] = (max[i]+min[i])/2;
view->WCtoNDC(min,max);
min[0] = x[0]; min[1] = x[1];
min[2] = max[2];
view->NDCtoWC(min, x);
}
TShape *shape = GetShape();
if (shape)
sprintf(info,"%6.2f/%6.2f/%6.2f: %s/%s, shape=%s/%s",x[0],x[1],x[2],GetName(),GetTitle(),shape->GetName(),shape->ClassName());
else
sprintf(info,"%6.2f/%6.2f/%6.2f: %s/%s",x[0],x[1],x[2],GetName(),GetTitle());
return info;
}
TVolumePosition *TVolumeView::Local2Master(const Char_t *localName, const Char_t *masterName)
{
TVolumeView *masterNode = this;
TVolumePosition *position = 0;
if (masterName && masterName[0]) masterNode = (TVolumeView *)Find(masterName);
if (masterNode) {
TVolumeViewIter transform(masterNode,0);
if (transform(localName)) position = transform[0];
}
return position;
}
TVolumePosition *TVolumeView::Local2Master(const TVolumeView *localNode,const TVolumeView *masterNode)
{
TVolumePosition *position = 0;
if (!masterNode) masterNode = this;
if (masterNode && localNode) {
TVolumeViewIter transform((TVolumeView *)masterNode,0);
TVolumeView *nextNode = 0;
while ((nextNode = (TVolumeView *)transform()) && nextNode != localNode) { }
if (nextNode) position = transform[0];
}
return position;
}
Float_t *TVolumeView::Local2Master(const Float_t *local, Float_t *master,
const Char_t *localName, const Char_t *masterName, Int_t nVector)
{
Float_t *trans = 0;
TVolumePosition *position = 0;
TVolumeView *masterNode = this;
if (masterName && masterName[0]) masterNode = (TVolumeView *)Find(masterName);
if (masterNode) {
TVolumeViewIter transform(masterNode,0);
if (transform(localName) && (position = (TVolumePosition *) transform.GetPosition()) )
trans = position->Local2Master(local,master,nVector);
}
return trans;
}
Float_t *TVolumeView::Local2Master(const Float_t *local, Float_t *master,
const TVolumeView *localNode,
const TVolumeView *masterNode, Int_t nVector)
{
Float_t *trans = 0;
TVolumePosition *position = 0;
if (!masterNode) masterNode = this;
if (masterNode && localNode) {
TVolumeViewIter transform((TVolumeView *)masterNode,0);
TVolumeView *nextNode = 0;
while ((nextNode = (TVolumeView *)transform()) && nextNode != localNode) { }
if (nextNode && (position = (TVolumePosition *) transform.GetPosition()) )
trans = position->Local2Master(local,master,nVector);
}
return trans;
}
void TVolumeView::Paint(Option_t *option)
{
Int_t level = gGeometry->GeomLevel();
if (option && option[0]=='r' && level > 3 ) return;
Int_t iFirst = atoi(option);
Int_t iLast = 0;
const char *delim = strpbrk( option,":-,");
if (delim) iLast = atoi(delim+1);
if (iLast < iFirst) {
iLast = iFirst-1;
iFirst = 0;
}
if ( (0 < iLast) && (iLast < level) ) return;
TTablePadView3D *view3D = (TTablePadView3D*)gPad->GetView3D();
TVolume *thisNode = 0;
TVolumePosition *position = GetPosition();
if (position) {
thisNode = position->GetNode();
position->UpdatePosition(option);
}
if (level >= iFirst) {
PaintShape(option);
if (thisNode) thisNode->PaintShape(option);
}
TSeqCollection *nodes = GetCollection();
Int_t nsons = nodes?nodes->GetSize():0;
if(!nsons) return;
gGeometry->PushLevel();
TVolumeView *node;
TIter next(nodes);
while ((node = (TVolumeView *)next())) {
if (view3D) view3D->PushMatrix();
node->Paint(option);
if (view3D) view3D->PopMatrix();
}
gGeometry->PopLevel();
}
void TVolumeView::PaintShape(Option_t *option)
{
Bool_t rangeView = option && option[0]=='r';
TIter nextShape(fListOfShapes);
TShape *shape = 0;
while( (shape = (TShape *)nextShape()) ) {
if (!shape->GetVisibility()) continue;
if (!rangeView) {
TTablePadView3D *view3D = (TTablePadView3D*)gPad->GetView3D();
if (view3D)
view3D->SetLineAttr(shape->GetLineColor(),shape->GetLineWidth(),option);
}
#if ROOT_VERSION_CODE >= ROOT_VERSION(4,03,05)
Bool_t viewerWantsSons = kTRUE;
TVirtualViewer3D * viewer3D = gPad->GetViewer3D();
if (viewer3D) {
const TBuffer3D & buffer =
shape->GetBuffer3D(TBuffer3D::kCore|TBuffer3D::kBoundingBox|TBuffer3D::kShapeSpecific);
const_cast<TBuffer3D &>(buffer).fID = this;
Int_t reqSections = viewer3D->AddObject(buffer, &viewerWantsSons);
if (reqSections != TBuffer3D::kNone) {
shape->GetBuffer3D(reqSections);
viewer3D->AddObject(buffer);
}
}
#else
shape->Paint(option);
#endif
}
}
TString TVolumeView::PathP() const
{
TString str;
TVolumeView *parent = (TVolumeView *)GetParent();
if (parent) {
str = parent->PathP();
str += "/";
}
str += GetName();
UInt_t positionId = 0;
TVolumePosition *p = GetPosition();
if (p) {
char buffer[10];
positionId = p->GetId();
sprintf(buffer,";%d",p->GetId());
str += buffer;
}
return str;
}
void TVolumeView::SavePrimitive(ostream &out, Option_t * )
{
const Char_t *sceleton[] = {
"TVolumeView *CreateNodeView(TVolume *topNode) {"
," TString thisNodePath = "
," UInt_t thisPositionId = "
," Double_t thisTranslate[3] = "
," "
," TString matrixName = "
," Int_t matrixType = "
," Double_t thisMatrix[] = { "
," "
," "
," };"
," return = new TVolumeView(thisTranslate, thisMatrix, thisPositionId, topNode,"
," thisNodePath.Data(),matrixName.Data(), matrixType);"
,"}"
};
Int_t sceletonSize = sizeof(sceleton)/4;
TVolumePosition *thisPosition = GetPosition();
TVolume *thisFullNode = GetNode();
TString thisNodePath = thisFullNode ? thisFullNode->Path() : TString("");
UInt_t thisPositionId = thisPosition ? thisPosition->GetId():0;
Double_t thisX = thisPosition ? thisPosition->GetX():0;
Double_t thisY = thisPosition ? thisPosition->GetY():0;
Double_t thisZ = thisPosition ? thisPosition->GetZ():0;
const TRotMatrix *matrix = thisPosition ? thisPosition->GetMatrix():0;
Int_t matrixType = 2;
TString matrixName = " ";
Double_t thisMatrix[] = { 0,0,0, 0,0,0, 0,0,0 };
if (matrix) {
matrixName = matrix->GetName();
memcpy(thisMatrix,((TRotMatrix *)matrix)->GetMatrix(),9*sizeof(Double_t));
matrixType = matrix->GetType();
}
Int_t im = 0;
for (Int_t lineNumber =0; lineNumber < sceletonSize; lineNumber++) {
out << sceleton[lineNumber];
switch (lineNumber) {
case 1: out << "\"" << thisNodePath.Data() << "\";" ;
break;
case 2: out << thisPositionId << ";" ;
break;
case 3: out << "{" << thisX << ", " << thisY << ", "<< thisZ << "};";
break;
case 5: out << "\"" << matrixName << "\";" ;
break;
case 6: out << matrixType << ";" ;
break;
case 7: out << thisMatrix[im++] << ", "; out << thisMatrix[im++] << ", "; out << thisMatrix[im++] << ", ";
break;
case 8: out << thisMatrix[im++] << ", "; out << thisMatrix[im++] << ", "; out << thisMatrix[im++] << ", ";
break;
case 9: out << thisMatrix[im++] << ", "; out << thisMatrix[im++] << ", "; out << thisMatrix[im++];
break;
default:
break;
};
out << " " << endl;
}
}
void TVolumeView::SetLineAttributes()
{
TVolume *thisNode = GetNode();
if (thisNode) thisNode->SetLineAttributes();
}
void TVolumeView::SetVisibility(Int_t vis)
{
TVolume *node = GetNode();
if (node) node->SetVisibility(TVolume::ENodeSEEN(vis));
}
void TVolumeView::Sizeof3D() const
{
if (GetListOfShapes()) {
TIter nextShape(GetListOfShapes());
TShape *shape = 0;
while( (shape = (TShape *)nextShape()) ) {
if (shape->GetVisibility()) shape->Sizeof3D();
}
}
TVolume *thisNode = GetNode();
if (thisNode && !(thisNode->GetVisibility()&TVolume::kThisUnvisible) ) {
TIter nextShape(thisNode->GetListOfShapes());
TShape *shape = 0;
while( (shape = (TShape *)nextShape()) ) {
if (shape->GetVisibility()) shape->Sizeof3D();
}
}
TVolumeView *node;
TDataSetIter next((TVolumeView *)this);
while ((node = (TVolumeView *)next())) node->Sizeof3D();
}