Introducing TGeoMatrix where needed
[u/mrichter/AliRoot.git] / EVE / Reve / GeoNode.cxx
1 // $Header$
2
3 #include "GeoNode.h"
4 #include <Reve/ReveManager.h>
5 #include <Reve/NLTPolygonSet.h>
6
7 #include "TGeoShapeExtract.h"
8 #include "TGeoMatrix.h"
9
10 #include <TPad.h>
11 #include <TBuffer3D.h>
12 #include <TVirtualViewer3D.h>
13 #include <TColor.h>
14 #include <TFile.h>
15
16 #include <TGeoShape.h>
17 #include <TGeoVolume.h>
18 #include <TGeoNode.h>
19 #include <TGeoShapeAssembly.h>
20 #include <TGeoManager.h>
21 #include <TVirtualGeoPainter.h>
22
23 using namespace Reve;
24
25
26 //______________________________________________________________________
27 // GeoNodeRnrEl
28 //
29
30 ClassImp(GeoNodeRnrEl)
31
32 GeoNodeRnrEl::GeoNodeRnrEl(TGeoNode* node) :
33   RenderElement(),
34   TObject(),
35   fNode(node)
36 {
37   // Hack!! Should use cint to retrieve TAttLine::fLineColor offset.
38   char* l = (char*) dynamic_cast<TAttLine*>(node->GetVolume());
39   SetMainColorPtr((Color_t*)(l + sizeof(void*)));
40
41   fRnrSelf      = fNode->TGeoAtt::IsVisible();
42 }
43
44 const Text_t* GeoNodeRnrEl::GetName()  const { return fNode->GetName(); }
45 const Text_t* GeoNodeRnrEl::GetTitle() const { return fNode->GetTitle(); }
46
47 /**************************************************************************/
48
49 Int_t GeoNodeRnrEl::ExpandIntoListTree(TGListTree* ltree,
50                                        TGListTreeItem* parent)
51 {
52   // Checks if child-nodes have been imported ... imports them if not.
53   // Then calls RenderElement::ExpandIntoListTree.
54
55   if(fChildren.empty() && fNode->GetVolume()->GetNdaughters() > 0) {
56     TIter next(fNode->GetVolume()->GetNodes());
57     TGeoNode* dnode;
58     while((dnode = (TGeoNode*) next()) != 0) {
59       GeoNodeRnrEl* node_re = new GeoNodeRnrEl(dnode);
60       AddElement(node_re);
61     }
62   }
63   return RenderElement::ExpandIntoListTree(ltree, parent);
64 }
65
66 /**************************************************************************/
67
68 void GeoNodeRnrEl::SetRnrSelf(Bool_t rnr)
69 {
70   RenderElement::SetRnrSelf(rnr);
71   fNode->SetVisibility(rnr);
72 }
73
74 void GeoNodeRnrEl::SetRnrChildren(Bool_t rnr)
75 {
76   RenderElement::SetRnrChildren(rnr);
77   fNode->VisibleDaughters(rnr);
78 }
79
80 void GeoNodeRnrEl::SetRnrState(Bool_t rnr)
81 {
82   RenderElement::SetRnrState(rnr);
83   fNode->SetVisibility(rnr);
84   fNode->VisibleDaughters(rnr);
85 }
86
87 /**************************************************************************/
88
89 void GeoNodeRnrEl::SetMainColor(Color_t color)
90 {
91   fNode->GetVolume()->SetLineColor(color);
92   UpdateItems();
93 }
94
95 void GeoNodeRnrEl::SetMainColor(Pixel_t pixel)
96 {
97   // This one needed for proper calling via CINT (signals).
98
99   SetMainColor(Color_t(TColor::GetColor(pixel)));
100 }
101
102 /**************************************************************************/
103
104 void GeoNodeRnrEl::UpdateNode(TGeoNode* node)
105 {
106   // Updates all reve-browsers having the node in their contents.
107   // All 3D-pads updated if any change found.
108   //
109   // Should (could?) be optimized with some assumptions about
110   // volume/node structure (search for parent, know the same node can not
111   // reoccur on lower level once found).
112
113   static const Exc_t eH("GeoNodeRnrEl::UpdateNode ");
114
115   // printf("%s node %s %p\n", eH.Data(), node->GetName(), node);
116
117   if(fNode == node)
118     UpdateItems();
119
120   for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
121     ((GeoNodeRnrEl*)(*i))->UpdateNode(node);
122   }
123
124 }
125
126 void GeoNodeRnrEl::UpdateVolume(TGeoVolume* volume)
127 {
128   // Updates all reve-browsers having the volume in their contents.
129   // All 3D-pads updated if any change found.
130   //
131   // Should (could?) be optimized with some assumptions about
132   // volume/node structure (search for parent, know the same node can not
133   // reoccur on lower level once found).
134
135   static const Exc_t eH("GeoNodeRnrEl::UpdateVolume ");
136
137   // printf("%s volume %s %p\n", eH.Data(), volume->GetName(), volume);
138
139   if(fNode->GetVolume() == volume)
140     UpdateItems();
141
142   for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
143     ((GeoNodeRnrEl*)(*i))->UpdateVolume(volume);
144   }
145 }
146
147 /**************************************************************************/
148
149 void GeoNodeRnrEl::Draw(Option_t* option)
150 {
151   TString opt("SAME");
152   opt += option;
153   fNode->GetVolume()->Draw(opt);
154 }
155
156 /**************************************************************************/
157
158 void GeoNodeRnrEl::Save(const char* file, const char* name)
159 {
160   TGeoShapeExtract* gse = DumpShapeTree(this, 0, 0);
161   
162   TFile f(file, "RECREATE");
163   gse->Write(name);
164   f.Close();
165 }
166
167 /**************************************************************************/
168
169 TGeoShapeExtract* GeoNodeRnrEl::DumpShapeTree(GeoNodeRnrEl* geon, TGeoShapeExtract* parent, Int_t level)
170 {
171   printf("dump_shape_tree %s \n", geon->GetName());
172   TGeoNode*   tnode   = 0;
173   TGeoVolume* tvolume = 0;
174   TGeoShape*  tshape  = 0;
175
176   tnode = geon->GetNode();
177   if(tnode == 0) {
178     printf("Null node for %s; assuming it's a holder and descending.\n", geon->GetName());
179     goto do_dump;
180   }
181
182   tvolume = tnode->GetVolume();
183   if(tvolume == 0) {
184     printf("Null volume for %s; skipping.\n", geon->GetName());
185     return 0;
186   }
187
188   tshape  = tvolume->GetShape();
189
190 do_dump:
191   // transformation
192   ZTrans trans;
193   if (parent) if (parent) trans.SetFromArray(parent->GetTrans());
194   TGeoMatrix* gm =  tnode->GetMatrix();
195   const Double_t* rm = gm->GetRotationMatrix();
196   const Double_t* tv = gm->GetTranslation();
197   ZTrans t;
198   t(1,1) = rm[0]; t(1,2) = rm[1]; t(1,3) = rm[2];
199   t(2,1) = rm[3]; t(2,2) = rm[4]; t(2,3) = rm[5];
200   t(3,1) = rm[6]; t(3,2) = rm[7]; t(3,3) = rm[8];
201   t(1,4) = tv[0]; t(2,4) = tv[1]; t(3,4) = tv[2];
202   trans *= t;
203
204   TGeoShapeExtract* gse = new TGeoShapeExtract(geon->GetName(), geon->GetTitle());
205   gse->SetTrans(trans.Array());
206   Int_t ci = 0;
207   if(tvolume) ci = tvolume->GetLineColor();
208   TColor* c = gROOT->GetColor(ci);
209   Float_t rgba[4] = {1, 0, 0, 1};
210   if (c) {
211     rgba[0] = c->GetRed();
212     rgba[1] = c->GetGreen();
213     rgba[2] = c->GetBlue();
214   } 
215   gse->SetRGBA(rgba);
216   Bool_t rnr = geon->GetRnrSelf();
217   if(level > gGeoManager->GetVisLevel())
218     rnr = kFALSE;
219   gse->SetRnrSelf(rnr);
220   gse->SetRnrElements(geon->GetRnrChildren());
221
222   if(dynamic_cast<TGeoShapeAssembly*>(tshape)){
223     //    printf("<TGeoShapeAssembly \n");
224     tshape = 0;
225   }
226   gse->SetShape(tshape);
227   level ++;
228   if ( geon->GetNChildren())
229   {
230     TList* ele = new TList();
231     gse->SetElements(ele);
232     gse->GetElements()->SetOwner(true);
233
234     RenderElement::List_i i = geon->BeginChildren();
235     while (i != geon->EndChildren()) {
236       GeoNodeRnrEl* l = dynamic_cast<GeoNodeRnrEl*>(*i);
237       DumpShapeTree(l, gse, level+1);
238       i++;
239     }
240   }
241
242   if(parent)
243     parent->GetElements()->Add(gse);
244    
245   return gse;
246 }
247 /**************************************************************************/
248 //______________________________________________________________________
249 // GeoTopNodeRnrEl
250 //
251 // A wrapper over a TGeoNode, possibly displaced with a global
252 // trasformation fGlobalTrans (the matrix is owned by this class).
253 /**************************************************************************/
254
255 ClassImp(GeoTopNodeRnrEl)
256
257 GeoTopNodeRnrEl::GeoTopNodeRnrEl(TGeoManager* manager, TGeoNode* node,
258                                  Int_t visopt, Int_t vislvl) :
259   GeoNodeRnrEl (node),
260   fManager     (manager),
261   fGlobalTrans (),
262   fVisOption   (visopt),
263   fVisLevel    (vislvl)
264 {
265   fRnrSelf = true;
266 }
267
268 GeoTopNodeRnrEl::~GeoTopNodeRnrEl()
269 {}
270
271 /**************************************************************************/
272
273 void GeoTopNodeRnrEl::SetGlobalTrans(const TGeoHMatrix* m)
274 {
275   fGlobalTrans.SetFrom(*m);
276 }
277
278 void GeoTopNodeRnrEl::UseNodeTrans()
279 {
280   fGlobalTrans.SetFrom(*fNode->GetMatrix());
281 }
282
283 /**************************************************************************/
284
285 void GeoTopNodeRnrEl::SetVisOption(Int_t visopt)
286 {
287   fVisOption = visopt;
288   gReve->Redraw3D();
289 }
290
291 void GeoTopNodeRnrEl::SetVisLevel(Int_t vislvl)
292 {
293   fVisLevel = vislvl;
294   gReve->Redraw3D();
295 }
296
297 /**************************************************************************/
298
299 void GeoTopNodeRnrEl::SetRnrSelf(Bool_t rnr)
300 {
301   // Revert from GeoNode to back to standard behaviour.
302   RenderElement::SetRnrSelf(rnr);
303 }
304
305 /**************************************************************************/
306
307 void GeoTopNodeRnrEl::Draw(Option_t* option)
308 {
309   AppendPad(option);
310 }
311
312 void GeoTopNodeRnrEl::Paint(Option_t* option)
313 {
314   if(fRnrSelf) {
315     gGeoManager = fManager;
316     TVirtualPad* pad = gPad;
317     gPad = 0;
318     TGeoVolume* top_volume = fManager->GetTopVolume();
319     fManager->SetVisOption(fVisOption);
320     fManager->SetVisLevel(fVisLevel);
321     fManager->SetTopVolume(fNode->GetVolume());
322     gPad = pad;
323     TVirtualGeoPainter* vgp = fManager->GetGeomPainter();
324     if(vgp != 0) {
325       TGeoHMatrix geomat;
326       fGlobalTrans.SetGeoHMatrix(geomat);
327       vgp->PaintNode(fNode, option, &geomat);
328     }
329     fManager->SetTopVolume(top_volume);
330   }
331 }
332
333 /**************************************************************************/
334
335 void GeoTopNodeRnrEl::VolumeVisChanged(TGeoVolume* volume)
336 {
337   static const Exc_t eH("GeoTopNodeRnrEl::VolumeVisChanged ");
338   printf("%s volume %s %p\n", eH.Data(), volume->GetName(), (void*)volume);
339   UpdateVolume(volume);
340 }
341
342 void GeoTopNodeRnrEl::VolumeColChanged(TGeoVolume* volume)
343 {
344   static const Exc_t eH("GeoTopNodeRnrEl::VolumeColChanged ");
345   printf("%s volume %s %p\n", eH.Data(), volume->GetName(), (void*)volume);
346   UpdateVolume(volume);
347 }
348
349 void GeoTopNodeRnrEl::NodeVisChanged(TGeoNode* node)
350 {
351   static const Exc_t eH("GeoTopNodeRnrEl::NodeVisChanged ");
352   printf("%s node %s %p\n", eH.Data(), node->GetName(), (void*)node);
353   UpdateNode(node);
354 }
355
356
357 /**************************************************************************/
358 //______________________________________________________________________
359 // GeoShapeRnrEl
360 //
361 // Minimal shape-wrapper allowing import of stuff from gled and retaining
362 // user-set visibility, colors and transparency.
363 /**************************************************************************/
364
365 ClassImp(GeoShapeRnrEl)
366
367 GeoShapeRnrEl::GeoShapeRnrEl(const Text_t* name, const Text_t* title) :
368   RenderElement(),
369   TNamed        (name, title),
370   fHMTrans      (),
371   fColor        (0),
372   fTransparency (0),
373   fShape        (0)
374 {
375   fMainColorPtr = &fColor;
376 }
377
378 GeoShapeRnrEl::~GeoShapeRnrEl()
379 {
380   if (fShape) {
381     fShape->SetUniqueID(fShape->GetUniqueID() - 1);
382     if (fShape->GetUniqueID() == 0)
383       delete fShape;
384   }
385 }
386
387 /**************************************************************************/
388
389 void GeoShapeRnrEl::Paint(Option_t* /*option*/)
390 {
391   if (fShape == 0)
392     return;
393
394   TBuffer3D& buff = (TBuffer3D&) fShape->GetBuffer3D
395     (TBuffer3D::kCore, false);
396
397   buff.fID           = this;
398   buff.fColor        = fColor;
399   buff.fTransparency = fTransparency;
400   fHMTrans.SetBuffer3D(buff);
401   buff.fLocalFrame   = kTRUE; // Always enforce local frame (no geo manager).
402
403   fShape->GetBuffer3D(TBuffer3D::kBoundingBox | TBuffer3D::kShapeSpecific, true);
404
405   Int_t reqSec = gPad->GetViewer3D()->AddObject(buff);
406
407   if (reqSec != TBuffer3D::kNone) {
408     fShape->GetBuffer3D(reqSec, true);
409     reqSec = gPad->GetViewer3D()->AddObject(buff);
410   }
411
412   if (reqSec != TBuffer3D::kNone)
413     printf("spooky reqSec=%d for %s\n", reqSec, GetName());
414 }
415
416 /**************************************************************************/
417
418 void GeoShapeRnrEl::Save(const char* file, const char* name)
419 {
420   TGeoShapeExtract* gse = DumpShapeTree(this, 0);
421   
422   TFile f(file, "RECREATE");
423   gse->Write(name);
424   f.Close();
425 }
426
427 /**************************************************************************/
428
429 TGeoShapeExtract* GeoShapeRnrEl::DumpShapeTree(GeoShapeRnrEl* gsre, TGeoShapeExtract* parent)
430 {
431   //  printf("dump_shape_tree %s \n", gsre->GetName());
432   TGeoShapeExtract* she = new TGeoShapeExtract(gsre->GetName(), gsre->GetTitle());
433   she->SetTrans(gsre->RefHMTrans().Array());
434   Int_t ci = gsre->GetColor();
435   TColor* c = gROOT->GetColor(ci);
436   Float_t rgba[4] = {1, 0, 0, 1 - gsre->GetMainTransparency()/100.};
437   if (c)
438  {
439     rgba[0] = c->GetRed();
440     rgba[1] = c->GetGreen();
441     rgba[2] = c->GetBlue();
442   } 
443   she->SetRGBA(rgba);
444   she->SetRnrSelf(gsre->GetRnrSelf());
445   she->SetRnrElements(gsre->GetRnrChildren());
446   she->SetShape(gsre->GetShape());
447   if ( gsre->GetNChildren())
448   {
449     TList* ele = new TList();
450     she->SetElements(ele);
451     she->GetElements()->SetOwner(true);
452     RenderElement::List_i i = gsre->BeginChildren();
453     while (i != gsre->EndChildren()) {
454       GeoShapeRnrEl* l = dynamic_cast<GeoShapeRnrEl*>(*i);
455       DumpShapeTree(l, she);
456       i++;
457     }
458   }
459   if(parent)
460     parent->GetElements()->Add(she);
461
462   return she; 
463 }
464
465 GeoShapeRnrEl* GeoShapeRnrEl::ImportShapeExtract(TGeoShapeExtract * gse,
466                                         RenderElement    * parent)
467 {
468   gReve->DisableRedraw();
469   GeoShapeRnrEl* gsre = SubImportShapeExtract(gse, parent);
470   gsre->ElementChanged();
471   gReve->EnableRedraw();
472   return gsre;
473 }
474
475
476 GeoShapeRnrEl* GeoShapeRnrEl::SubImportShapeExtract(TGeoShapeExtract * gse,
477                                            RenderElement    * parent)
478 {
479   GeoShapeRnrEl* gsre = new GeoShapeRnrEl(gse->GetName(), gse->GetTitle());
480   gsre->fHMTrans.SetFromArray(gse->GetTrans());
481   const Float_t* rgba = gse->GetRGBA();
482   gsre->fColor        = TColor::GetColor(rgba[0], rgba[1], rgba[2]);
483   gsre->fTransparency = (UChar_t) (100.0f*(1.0f - rgba[3]));
484   gsre->SetRnrSelf(gse->GetRnrSelf());
485   gsre->SetRnrChildren(gse->GetRnrElements());
486   gsre->fShape = gse->GetShape();
487   if (gsre->fShape)
488     gsre->fShape->SetUniqueID(gsre->fShape->GetUniqueID() + 1);
489
490   gReve->AddGlobalRenderElement(gsre, parent);
491
492   if (gse->HasElements())
493   {
494     TIter next(gse->GetElements());
495     TGeoShapeExtract* chld;
496     while ((chld = (TGeoShapeExtract*) next()) != 0)
497      SubImportShapeExtract(chld, gsre);
498   }
499
500   return gsre;
501 }
502
503 /**************************************************************************/
504
505 TClass* GeoShapeRnrEl::ProjectedClass() const
506 {
507    return NLTPolygonSet::Class();
508
509
510 /**************************************************************************/
511
512 TBuffer3D* GeoShapeRnrEl::MakeBuffer3D()
513 {
514   if(fShape == 0) return 0;
515
516   if(dynamic_cast<TGeoShapeAssembly*>(fShape)){
517     // !!!! TGeoShapeAssembly makes a bad TBuffer3D
518     return 0;
519   }
520
521   TBuffer3D* buff  = fShape->MakeBuffer3D();
522   if (fHMTrans.GetUseTrans())
523   {
524     Reve::ZTrans& mx = RefHMTrans();
525     Int_t N = buff->NbPnts();
526     Double_t* pnts = buff->fPnts;
527     for(Int_t k=0; k<N; k++)
528     {
529       mx.MultiplyIP(&pnts[3*k]);
530     }
531   }
532   return buff;
533 }
534
535
536