StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
TVolume.cxx
1 // @(#)root/table:$Id$
2 // Author: Valery Fine 10/12/98
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "Riostream.h"
13 #include <stdlib.h>
14 
15 #include "TROOT.h"
16 #include "TClass.h"
17 #include "TVirtualPad.h"
18 #include "TView.h"
19 #include "TGeometry.h"
20 #include "TRotMatrix.h"
21 #include "TShape.h"
22 #include "TVolume.h"
23 #include "TBrowser.h"
24 #include "X3DBuffer.h"
25 
26 #include "TTablePadView3D.h"
27 #include "TCanvas.h"
28 
29 #include "TRotMatrix.h"
30 #include "TVolumePosition.h"
31 #include "TVirtualViewer3D.h"
32 #include "TBuffer3D.h"
33 
34 #if 0
35 const Int_t kVectorSize = 3;
36 const Int_t kMatrixSize = kVectorSize*kVectorSize;
37 const Int_t kMAXLEVELS = 20;
38 
39 static Double_t gTranslation[kMAXLEVELS][kVectorSize];
40 static Double_t gRotMatrix[kMAXLEVELS][kMatrixSize];
41 static Int_t gGeomLevel = 0;
42 
43 TVolume *gNode;
44 #endif
45 //R__EXTERN Size3D gSize3D;
46 static TRotMatrix *gIdentity = 0;
47 
48 // Pin vtable
49 void TVolume::Add(TDataSet *dataset)
50 {
51  TDataSet::Add(dataset);
52 }
53 
54 ClassImp(TVolume);
55 
70 
71 
74 
76 {
77  fShape = 0;
78  fListOfShapes = 0;
79  fVisibility = kBothVisible;
80  if (!gGeometry) new TGeometry;
81 }
82 
89 
90 TVolume::TVolume(const char *name, const char *title, const char *shapename, Option_t *option)
91  :TObjectSet(name),TAttLine(), TAttFill(),fShape(0),fListOfShapes(0)
92 {
93 #ifdef WIN32
94  Color_t lcolor = 16;
96  SetLineColor(lcolor);
97 #endif
98  static Int_t counter = 0;
99  counter++;
100  SetTitle(title);
101  if(!(counter%1000))std::cout<<"TVolume count="<<counter<<" name="<<name<<std::endl;
102  if (!gGeometry) new TGeometry;
103  Add(gGeometry->GetShape(shapename),kTRUE);
104 // fParent = gGeometry->GetCurrenTVolume();
105  fOption = option;
106  fVisibility = kBothVisible;
107 
108  if(fShape) ImportShapeAttributes();
109 }
110 
117 
118 TVolume::TVolume(const char *name, const char *title, TShape *shape, Option_t *option)
119  :TObjectSet(name),TAttLine(),TAttFill(),fShape(0),fListOfShapes(0)
120 {
121 #ifdef WIN32
122  Color_t lcolor = 16;
124  SetLineColor(lcolor);
125 #endif
126 
127  if (!gGeometry) new TGeometry;
128  Add(shape,kTRUE);
129  fOption = option;
130  fVisibility = kBothVisible;
131  SetTitle(title);
132  if(shape) ImportShapeAttributes();
133 }
134 
141 
142 Int_t TVolume::MapStNode2GEANTVis(ENodeSEEN vis)
143 {
144  const Int_t mapVis[4] = {1, -2, 0, -1 };
145  return mapVis[vis];
146 }
147 
151 
153 {
154  const Int_t mapVis[4] = {1, -2, 0, -1 };
155  Int_t i;
156 // for (i =0; i<3;i++) if (mapVis[i] == vis) return (ENodeSEEN)i;
157  for (i =0; i<3;i++) if (mapVis[i] == vis) return i;
158  return kBothVisible;
159 }
160 
163 
164 TVolume::TVolume(TNode &rootNode):fShape(0),fListOfShapes(0)
165 {
166  SetName(rootNode.GetName());
167  SetTitle(rootNode.GetTitle());
168  fVisibility = ENodeSEEN(MapGEANT2StNodeVis(rootNode.GetVisibility()));
169  fOption = rootNode.GetOption();
170  Add(rootNode.GetShape(),kTRUE);
171 
172  SetLineColor(rootNode.GetLineColor());
173  SetLineStyle(rootNode.GetLineStyle());
174  SetLineWidth(rootNode.GetLineWidth());
175  SetFillColor(rootNode.GetFillColor());
176  SetFillStyle(rootNode.GetFillStyle());
177 
178  TList *nodes = rootNode.GetListOfNodes();
179  if (nodes) {
180  TIter next(nodes);
181  TNode *node = 0;
182  while ( (node = (TNode *) next()) ){
183  TVolume *nextNode = new TVolume(*node);
184  Add(nextNode,node->GetX(),node->GetY(),node->GetZ(),node->GetMatrix());
185  }
186  }
187 }
188 
191 
192 void TVolume::Add(TShape *shape, Bool_t IsMaster)
193 {
194  if (!shape) return;
195  if (!fListOfShapes) fListOfShapes = new TList;
196  fListOfShapes->Add(shape);
197  if (IsMaster) fShape = shape;
198 }
199 
202 
203 TNode *TVolume::CreateTNode(const TVolumePosition *position)
204 {
205  Double_t x=0;
206  Double_t y=0;
207  Double_t z=0;
208  const TRotMatrix* matrix = 0;
209  if (position) {
210  x=position->GetX();
211  y=position->GetY();
212  z=position->GetZ();
213  matrix = position->GetMatrix();
214  }
215 // const Char_t *path = Path();
216 // printf("%s: %s/%s, shape=%s/%s\n",path,GetName(),GetTitle(),GetShape()->GetName(),GetShape()->ClassName());
217  TNode *newNode = new TNode(GetName(),GetTitle(),GetShape(),x,y,z,(TRotMatrix* )matrix,GetOption());
218  newNode->SetVisibility(MapStNode2GEANTVis(GetVisibility()));
219 
220  newNode->SetLineColor(GetLineColor());
221  newNode->SetLineStyle(GetLineStyle());
222  newNode->SetLineWidth(GetLineWidth());
223  newNode->SetFillColor(GetFillColor());
224  newNode->SetFillStyle(GetFillStyle());
225 
226  TList *positions = GetListOfPositions();
227  if (positions) {
228  TIter next(positions);
229  TVolumePosition *pos = 0;
230  while ( (pos = (TVolumePosition *) next()) ){
231  TVolume *node = pos->GetNode();
232  if (node) {
233  newNode->cd();
234  node->CreateTNode(pos);
235  }
236  }
237  }
238  newNode->ImportShapeAttributes();
239  return newNode;
240 }
241 
244 
245 TVolume::~TVolume()
246 {
247  // Hmm, here we are in the troubles, in theory we have to find all
248  // place where this node is sitting but we don't (yet :-()
249 
250  if (GetListOfPositions()) {
251  GetListOfPositions()->Delete();
252  SetPositionsList();
253  }
254  SafeDelete(fListOfShapes);
255 
256  // Required since we overload TObject::Hash.
257  ROOT::CallRecursiveRemoveIfNeeded(*this);
258 }
259 
262 
263 void TVolume::Add(TVolumePosition *position)
264 {
265  if (!GetListOfPositions()) SetPositionsList(new TList);
266  if ( GetListOfPositions()) GetListOfPositions()->Add(position);
267  else Error("Add","Can not create list of positions for the current node <%s>:<%s>",GetName(),GetTitle());
268 }
269 
272 
273 TVolumePosition *TVolume::Add(TVolume *node, TVolumePosition *nodePosition)
274 {
275  TVolumePosition *position = nodePosition;
276  if (!node) return 0;
277  if (!position) position = new TVolumePosition(node); // Create default position
278  // The object must be placed at once. Check it:
279  if (!(GetCollection() && GetCollection()->FindObject(node)) ) TDataSet::Add(node);
280  Add(position);
281  return position;
282 }
283 
290 
291 TVolumePosition *TVolume::Add(TVolume *volume, Double_t x, Double_t y, Double_t z,
292  TRotMatrix *matrix, UInt_t id, Option_t *)
293 {
294  if (!volume) return 0;
295  TRotMatrix *rotation = matrix;
296  if(!rotation) rotation = GetIdentity();
297  TVolumePosition *position = new TVolumePosition(volume,x,y,z,rotation);
298  position->SetId(id);
299  return Add(volume,position);
300 }
301 
308 
309 TVolumePosition *TVolume::Add(TVolume *volume, Double_t x, Double_t y, Double_t z,
310  const char *matrixname, UInt_t id, Option_t *)
311 {
312  if (!volume) return 0;
313  TRotMatrix *rotation = 0;
314  if (matrixname && strlen(matrixname)) rotation = gGeometry->GetRotMatrix(matrixname);
315  if (!rotation) rotation = GetIdentity();
316  TVolumePosition *position = new TVolumePosition(volume,x,y,z,rotation);
317  position->SetId(id);
318  return Add(volume,position);
319 }
320 
323 
324 void TVolume::Browse(TBrowser *b)
325 {
326  if (GetListOfPositions()){
327  TVolumePosition *nodePosition = 0;
328  TIter next(GetListOfPositions());
329  Int_t posNumber = 0;
330  while ( (nodePosition = (TVolumePosition *)next()) ) {
331  posNumber = nodePosition->GetId();
332  TString posName = "*";
333  posName += nodePosition->GetNode()->GetTitle();
334  char num[10];
335  posName += ";";
336  snprintf(num,10,"%d",posNumber);
337  posName += num;
338  b->Add(nodePosition,posName.Data());
339  }
340  }
341 }
344 
345 Int_t TVolume::DistancetoPrimitive(Int_t px, Int_t py)
346 {
347  return DistancetoNodePrimitive(px,py);
348 }
349 
358 
359 Int_t TVolume::DistancetoNodePrimitive(Int_t px, Int_t py,TVolumePosition *pos)
360 {
361  const Int_t big = 9999;
362  if ( GetVisibility() == kNoneVisible ) return big;
363 
364  const Int_t inaxis = 7;
365  const Int_t maxdist = 5;
366 
367  Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
368  Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
369  Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
370  Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
371 
373  if (px < puxmin - inaxis) return big;
374  if (py > puymin + inaxis) return big;
375  if (px > puxmax + inaxis) return big;
376  if (py < puymax - inaxis) return big;
377 
378  TView *view =gPad->GetView();
379  if (!view) return big;
380 
381  static TVolumePosition nullPosition;
382  TVolumePosition *position = pos;
383  if (!position) position = &nullPosition;
384  if (pos) position->UpdatePosition();
385  Int_t dist = big;
386  if ( !(GetVisibility() & kThisUnvisible ) ) {
387  TShape *shape = 0;
388  TIter nextShape(fListOfShapes);
389  while ((shape = (TShape *)nextShape())) {
391  if (shape->GetVisibility()) {
392  Int_t dshape = shape->DistancetoPrimitive(px,py);
393  if (dshape < maxdist) {
394  gPad->SetSelected(this);
395  return 0;
396  }
397  if (dshape < dist) dist = dshape;
398  }
399  }
400  }
401 
402  if ( (GetVisibility() & kSonUnvisible) ) return dist;
403 
405  TList *posList = GetListOfPositions();
406  Int_t dnode = dist;
407  if (posList && posList->GetSize()) {
408  gGeometry->PushLevel();
409  TVolumePosition *thisPosition;
410  TObject *obj;
411  TIter next(posList);
412  while ((obj = next())) {
413  thisPosition = (TVolumePosition*)obj;
414  TVolume *node = thisPosition->GetNode();
415  dnode = node->DistancetoNodePrimitive(px,py,thisPosition);
416  if (dnode <= 0) break;
417  if (dnode < dist) dist = dnode;
418  if (gGeometry->GeomLevel() > 2) break;
419  }
420  gGeometry->PopLevel();
421  }
422 
423  if (gGeometry->GeomLevel()==0 && dnode > maxdist) {
424  gPad->SetSelected(view);
425  return 0;
426  } else
427  return dnode;
428 }
429 
432 
433 void TVolume::Draw(Option_t *option)
434 {
435  TString opt = option;
436  opt.ToLower();
438  if (!gPad) {
439  gROOT->MakeDefCanvas();
440  }
441  if (!opt.Contains("same")) gPad->Clear();
442 
443  // Check geometry level
444 
445  Int_t iopt = atoi(option);
446  TDataSet *parent = 0;
447  char buffer[12];
448  if (iopt < 0) {
449  // set the "positive option"
450  snprintf(buffer,12,"%d",-iopt);
451  option = buffer;
452  // select parent to draw
453  parent = this;
454  do parent = parent->GetParent();
455  while (parent && ++iopt);
456  }
457  if (parent) parent->AppendPad(option);
458  else AppendPad(option);
459 #if ROOT_VERSION_CODE >= ROOT_VERSION(4,03,05)
460  // the new (4.03/05) way to active 3D viewer
461  // Create a 3-D view
462  TView *view = gPad->GetView();
463  if (!view) {
464  view = TView::CreateView(1,0,0);
465  // Set the view to perform a first autorange (frame) draw.
466  // TViewer3DPad will revert view to normal painting after this
467  view->SetAutoRange(kTRUE);
468  }
469 
470  // Create a 3D viewer to draw us
471 // gPad->GetViewer3D(option);
472  gPad->GetViewer3D();
473 #else
474  Paint(option);
475 #endif
476 }
477 
478 
481 
482 void TVolume::DrawOnly(Option_t *option)
483 {
484  SetVisibility(kThisUnvisible);
485  Draw(option);
486 }
487 
488 
494 
495 void TVolume::ExecuteEvent(Int_t, Int_t, Int_t)
496 {
497 // if (gPad->GetView())
498 // gPad->GetView()->ExecuteRotateView(event, px, py);
499 
500 // if (!gPad->GetListOfPrimitives()->FindObject(this)) gPad->SetCursor(kCross);
501  gPad->SetCursor(kHand);
502 }
503 
506 
507 TRotMatrix *TVolume::GetIdentity()
508 {
509  Double_t *identityMatrix = 0;
510  if (!gIdentity) {
511  gIdentity = gGeometry->GetRotMatrix("Identity");
512  if (!gIdentity) {
513  gIdentity = new TRotMatrix();
514  gIdentity->SetName("Identity");
515  gIdentity->SetTitle("Identity matrix");
516  gIdentity->SetMatrix((Double_t *)0);
517  identityMatrix = gIdentity->GetMatrix();
518  memset(identityMatrix,0,9*sizeof(Double_t));
519  *identityMatrix = 1;
520  identityMatrix += 4; *identityMatrix = 1;
521  identityMatrix += 4; *identityMatrix = 1;
522  gGeometry->GetListOfMatrices()->AddFirst(gIdentity);
523  }
524  }
525  return gIdentity;
526 }
527 
530 
531 char *TVolume::GetObjectInfo(Int_t px, Int_t py) const
532 {
533  if (!gPad) return 0;
534  static char info[512];
535  snprintf(info,512,"%s/%s",GetName(),GetTitle());
536  Double_t x[3];
537  ((TPad *)gPad)->AbsPixeltoXY(px,py,x[0],x[1]);
538  x[2] = 0;
539  TView *view =gPad->GetView();
540  if (view) view->NDCtoWC(x, x);
541 
542  TIter nextShape(fListOfShapes);
543  TShape *shape = 0;
544  while( (shape = (TShape *)nextShape()) ) {
545  Int_t nchi = strlen(info);
546  snprintf(&info[nchi],512-nchi," %6.2f/%6.2f: shape=%s/%s",x[0],x[1],shape->GetName(),shape->ClassName());
547  }
548  return info;
549 }
550 
553 
554 void TVolume::ImportShapeAttributes()
555 {
556  if (fShape) {
557  SetLineColor(fShape->GetLineColor());
558  SetLineStyle(fShape->GetLineStyle());
559  SetLineWidth(fShape->GetLineWidth());
560  SetFillColor(fShape->GetFillColor());
561  SetFillStyle(fShape->GetFillStyle());
562  }
563 
564  if (!GetCollection()) return;
565  TVolume *volume;
566  TIter next(GetCollection());
567  while ( (volume = (TVolume *)next()) )
568  volume->ImportShapeAttributes();
569 }
570 
573 
574 void TVolume::Paint(Option_t *opt)
575 {
576  gGeometry->SetGeomLevel();
577  gGeometry->UpdateTempMatrix();
578  PaintNodePosition(opt);
579  return;
580 }
581 
590 
591 void TVolume::PaintNodePosition(Option_t *option,TVolumePosition *pos)
592 {
593  if ( GetVisibility() == kNoneVisible ) return;
594 
595  static TVolumePosition nullPosition;
596 
597 // restrict the levels for "range" option
598  Int_t level = gGeometry->GeomLevel();
599 // if (option && option[0]=='r' && level > 3 && strcmp(option,"range") == 0) return;
600  if ((!(GetVisibility() & kThisUnvisible)) && option && option[0]=='r' && level > 3 ) return;
601  Int_t iopt = 0;
602  if (option) iopt = atoi(option);
603  if ( (0 < iopt) && (iopt <= level) ) return;
604 
605  TTablePadView3D *view3D = (TTablePadView3D*)gPad->GetView3D();
606  TVirtualViewer3D * viewer3D = gPad->GetViewer3D();
607 
608  TVolumePosition *position = pos;
609  if (!position) position = &nullPosition;
610 
611  // PaintPosition does change the current matrix and it MUST be called FIRST !!!
612 
613  position->UpdatePosition(option);
614 
615  if ( viewer3D && !(GetVisibility() & kThisUnvisible)) PaintShape(option);
616 
617  if (GetVisibility() & kSonUnvisible) return;
618 
620  TList *posList = GetListOfPositions();
621  if (posList && posList->GetSize()) {
622  gGeometry->PushLevel();
623  TVolumePosition *thisPosition;
624  TIter next(posList);
625  while ((thisPosition = (TVolumePosition *)next())) {
626  if (view3D) view3D->PushMatrix();
627 
628  TVolume *volume = thisPosition->GetNode();
629  if (volume) volume->PaintNodePosition(option,thisPosition);
630 
631  if (view3D) view3D->PopMatrix();
632  }
633  gGeometry->PopLevel();
634  }
635 }
636 
640 
641 void TVolume::PaintShape(Option_t *option)
642 {
643  Bool_t rangeView = option && option[0]=='r';
644  if (!rangeView) {
645  TAttLine::Modify();
646  TAttFill::Modify();
647  }
648 
649  if ( (GetVisibility() & kThisUnvisible) ) return;
650 
651  TIter nextShape(fListOfShapes);
652  TShape *shape = 0;
653  while( (shape = (TShape *)nextShape()) ) {
654  if (!rangeView) {
655  shape->SetLineColor(GetLineColor());
656  shape->SetLineStyle(GetLineStyle());
657  shape->SetLineWidth(GetLineWidth());
658  shape->SetFillColor(GetFillColor());
659  shape->SetFillStyle(GetFillStyle());
660  TTablePadView3D *view3D = (TTablePadView3D*)gPad->GetView3D();
661  gPad->GetViewer3D();
662  if (view3D)
663  view3D->SetLineAttr(GetLineColor(),GetLineWidth(),option);
664  }
665 
666 #if ROOT_VERSION_CODE >= ROOT_VERSION(4,03,05)
667  // It MUST be the TShape::Paint method:
668  Bool_t viewerWantsSons = kTRUE;
669  TVirtualViewer3D * viewer3D = gPad->GetViewer3D();
670  if (viewer3D) {
671  // We only provide master frame positions in these shapes
672  // so don't ask viewer preference
673 
674  // Ask all shapes for kCore/kBoundingBox/kShapeSpecific
675  // Not all will support the last two - which is fine
676  const TBuffer3D & buffer =
677  fShape->GetBuffer3D(TBuffer3D::kCore|TBuffer3D::kBoundingBox|TBuffer3D::kShapeSpecific);
678 
679  // TShape sets buffer id based on TNode * gNode
680  // As we not using TNode we need to override this
681  const_cast<TBuffer3D &>(buffer).fID = this;
682 
683  Int_t reqSections = viewer3D->AddObject(buffer, &viewerWantsSons);
684  if (reqSections != TBuffer3D::kNone) {
685  fShape->GetBuffer3D(reqSections);
686  viewer3D->AddObject(buffer);
687  }
688  }
689 #else
690  shape->Paint(option);
691 #endif
692  }
693 }
694 
698 
700 {
701  if (!position) return;
702 
703  if (GetListOfPositions()) {
704  TObjLink *lnk = GetListOfPositions()->FirstLink();
705  while (lnk) {
706  TVolumePosition *nextPosition = (TVolumePosition *)(lnk->GetObject());
707  if (nextPosition && nextPosition == position) {
708  TVolume *node = nextPosition->GetNode();
709  GetListOfPositions()->Remove(lnk);
710  delete nextPosition;
711  Remove(node);
712  break;
713  }
714  lnk = lnk->Next();
715  }
716  }
717 }
718 
726 
727 void TVolume::GetLocalRange(Float_t *min, Float_t *max)
728 {
729  TVirtualPad *savePad = gPad;
730  // Create a dummy TPad;
731  TCanvas dummyPad("--Dumm--","dum",1,1);
732  // Asking 3D TView
733  TView *view = TView::CreateView(1,0,0);
734 
735  gGeometry->SetGeomLevel();
736  gGeometry->UpdateTempMatrix();
737  view->SetAutoRange(kTRUE);
738  Paint("range");
739  view->GetRange(&min[0],&max[0]);
740  delete view;
741  // restore "current pad"
742  if (savePad) savePad->cd();
743 }
744 
752 
753 void TVolume::SetVisibility(ENodeSEEN vis)
754 {
755  fVisibility = vis;
756 }
757 
760 
761 void TVolume::Sizeof3D() const
762 {
763  if (!(GetVisibility() & kThisUnvisible) ) {
764  TIter nextShape(fListOfShapes);
765  TShape *shape = 0;
766  while( (shape = (TShape *)nextShape()) ) {
767  if (shape->GetVisibility()) shape->Sizeof3D();
768  }
769  }
770 
771  if ( GetVisibility() & kSonUnvisible ) return;
772 
773  if (!Nodes()) return;
774  TVolume *node;
775  TObject *obj;
776  TIter next(Nodes());
777  while ((obj = next())) {
778  node = (TVolume*)obj;
779  node->Sizeof3D();
780  }
781 }
virtual void DeletePosition(TVolumePosition *position)
Definition: TVolume.cxx:699
Definition: FJcore.h:367
static Int_t MapGEANT2StNodeVis(Int_t vis)
Definition: TVolume.cxx:152
static Int_t MapStNode2GEANTVis(ENodeSEEN vis)
Definition: TVolume.cxx:142
virtual void Draw(Option_t *depth="3")
Definition: TVolume.cxx:433
virtual void Remove(TDataSet *set)
Remiove the &quot;set&quot; from this TDataSet.
Definition: TDataSet.cxx:641
virtual void PaintShape(Option_t *option="")
Definition: TVolume.cxx:641
virtual void SetVisibility(ENodeSEEN vis=TVolume::kBothVisible)
Definition: TVolume.cxx:753
static TRotMatrix * GetIdentity()
Return a pointer the &quot;identity&quot; matrix.
Definition: TVolume.cxx:507
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
to be documented
Definition: TVolume.cxx:345
virtual void PaintNodePosition(Option_t *option="", TVolumePosition *postion=0)
Definition: TVolume.cxx:591
virtual void Browse(TBrowser *b)
to be documented
Definition: TVolume.cxx:324
virtual void UpdatePosition(Option_t *option="")
to be documented
virtual TNode * CreateTNode(const TVolumePosition *position=0)
Convert a TVolume object into a TNode.
Definition: TVolume.cxx:203
TVolume()
Definition: TVolume.cxx:75
virtual char * GetObjectInfo(Int_t px, Int_t py) const
to be documented
Definition: TVolume.cxx:531
virtual Int_t DistancetoNodePrimitive(Int_t px, Int_t py, TVolumePosition *position=0)
Definition: TVolume.cxx:359
virtual void GetLocalRange(Float_t *min, Float_t *max)
Definition: TVolume.cxx:727