Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TEveUtil.cxx
Go to the documentation of this file.
1 // @(#)root/eve:$Id$
2 // Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2007, 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 "TEveUtil.h"
13 #include "TEveElement.h"
14 #include "TEveManager.h"
15 
16 #include "TError.h"
17 #include "TGeoManager.h"
18 #include "TGeoMatrix.h"
19 #include "TClass.h"
20 #include "TMath.h"
21 
22 #include "TStyle.h"
23 #include "TColor.h"
24 
25 #include "TROOT.h"
26 #include "TInterpreter.h"
27 #include "TSystem.h"
28 
29 #include "TGClient.h"
30 #include "TGMimeTypes.h"
31 
32 #include "Riostream.h"
33 
34 #include <list>
35 #include <algorithm>
36 #include <string>
37 
38 /** \class TEveUtil
39 \ingroup TEve
40 Standard utility functions for Eve.
41 */
42 
43 ClassImp(TEveUtil);
44 
45 TObjArray* TEveUtil::fgDefaultColors = 0;
46 
47 ////////////////////////////////////////////////////////////////////////////////
48 /// Setup Include and Macro paths.
49 /// Since inclusion into ROOT this does nothing but could
50 /// potentially be reactivated if some common macros are established
51 /// and shipped with binary ROOT (in macros/eve). For example, these
52 /// might be used to spawn specific GUI / GL configurations.
53 
54 void TEveUtil::SetupEnvironment()
55 {
56  static const TEveException eh("TEveUtil::SetupEnvironment");
57  static Bool_t setupDone = kFALSE;
58 
59  if (setupDone) {
60  Info(eh.Data(), "has already been run.");
61  return;
62  }
63 
64  // Old initialization for ALICE.
65  // Left as an example.
66  /*
67  // Check if REVESYS exists, try fallback to $ALICE_ROOT/EVE.
68  if(gSystem->Getenv("REVESYS") == 0) {
69  if(gSystem->Getenv("ALICE_ROOT") != 0) {
70  Info(eh.Data(), "setting REVESYS from ALICE_ROOT.");
71  gSystem->Setenv("REVESYS", Form("%s/EVE", gSystem->Getenv("ALICE_ROOT")));
72  } else {
73  Error(eh.Data(), "REVESYS not defined, neither is ALICE_ROOT.");
74  gSystem->Exit(1);
75  }
76  }
77  if(gSystem->AccessPathName(gSystem->Getenv("REVESYS")) == kTRUE) {
78  Error(eh.Data(), "REVESYS '%s' does not exist.", gSystem->Getenv("REVESYS"));
79  gSystem->Exit(1);
80  }
81 
82  TString macPath(gROOT->GetMacroPath());
83  macPath += Form(":%s/macros", gSystem->Getenv("REVESYS"));
84  gInterpreter->AddIncludePath(gSystem->Getenv("REVESYS"));
85  if(gSystem->Getenv("ALICE_ROOT") != 0) {
86  macPath += Form(":%s/alice-macros", gSystem->Getenv("REVESYS"));
87  gInterpreter->AddIncludePath(Form("%s/include", gSystem->Getenv("ALICE_ROOT")));
88  gInterpreter->AddIncludePath(gSystem->Getenv("ALICE_ROOT"));
89  }
90  gROOT->SetMacroPath(macPath);
91  */
92 }
93 
94 ////////////////////////////////////////////////////////////////////////////////
95 /// Setup icon pictures and mime-types.
96 
97 void TEveUtil::SetupGUI()
98 {
99  TEveElement::fgRnrIcons[0] = gClient->GetPicture("eve_rnr00_t.xpm");
100  TEveElement::fgRnrIcons[1] = gClient->GetPicture("eve_rnr01_t.xpm");
101  TEveElement::fgRnrIcons[2] = gClient->GetPicture("eve_rnr10_t.xpm");
102  TEveElement::fgRnrIcons[3] = gClient->GetPicture("eve_rnr11_t.xpm");
103 
104  TEveElement::fgListTreeIcons[0] = gClient->GetPicture("folder_t.xpm");
105  TEveElement::fgListTreeIcons[1] = gClient->GetPicture("eve_viewer.xpm");
106  TEveElement::fgListTreeIcons[2] = gClient->GetPicture("eve_scene.xpm");
107  TEveElement::fgListTreeIcons[3] = gClient->GetPicture("eve_pointset.xpm");
108  TEveElement::fgListTreeIcons[4] = gClient->GetPicture("eve_track.xpm");
109  TEveElement::fgListTreeIcons[5] = gClient->GetPicture("eve_text.gif");
110  TEveElement::fgListTreeIcons[6] = gClient->GetPicture("eve_axes.xpm");
111  TEveElement::fgListTreeIcons[7] = gClient->GetPicture("ofolder_t.xpm");
112  TEveElement::fgListTreeIcons[8] = gClient->GetPicture("eve_line.xpm");
113 
114  gClient->GetMimeTypeList()->AddType("root/tmacro", "TEveMacro",
115  "tmacro_s.xpm", "tmacro_t.xpm", "");
116 }
117 
118 namespace
119 {
120 ////////////////////////////////////////////////////////////////////////////////
121 /// Remove last part of string 's', starting from the last
122 /// occurrence of character 'c'.
123 /// Remove directory part -- everything until the last '/'.
124 
125 void ChompTailAndDir(TString& s, char c='.')
126 {
127  Ssiz_t p = s.Last(c);
128  if (p != kNPOS)
129  s.Remove(p);
130 
131  Ssiz_t ls = s.Last('/');
132  if (ls != kNPOS)
133  s.Remove(0, ls + 1);
134 }
135 }
136 
137 ////////////////////////////////////////////////////////////////////////////////
138 /// Checks if macro 'mac' is loaded.
139 
140 Bool_t TEveUtil::CheckMacro(const char* mac)
141 {
142  // Axel's advice; now sth seems slow, using old method below for test.
143  // return gROOT->GetInterpreter()->IsLoaded(mac);
144 
145  // Previous version expected function with same name and used ROOT's
146  // list of global functions.
147 
148  TString foo(mac); ChompTailAndDir(foo);
149  if (gROOT->GetGlobalFunction(foo.Data(), 0, kFALSE) != 0)
150  return kTRUE;
151  else
152  return (gROOT->GetGlobalFunction(foo.Data(), 0, kTRUE) != 0);
153 }
154 
155 ////////////////////////////////////////////////////////////////////////////////
156 /// Load and execute macro 'mac' if it has not been loaded yet.
157 
158 void TEveUtil::AssertMacro(const char* mac)
159 {
160  if( CheckMacro(mac) == kFALSE) {
161  gROOT->Macro(mac);
162  }
163 }
164 
165 ////////////////////////////////////////////////////////////////////////////////
166 /// Execute macro 'mac'. Do not reload the macro.
167 
168 void TEveUtil::Macro(const char* mac)
169 {
170  if (CheckMacro(mac) == kFALSE) {
171  gROOT->LoadMacro(mac);
172  }
173  TString foo(mac); ChompTailAndDir(foo); foo += "()";
174  gROOT->ProcessLine(foo.Data());
175 }
176 
177 ////////////////////////////////////////////////////////////////////////////////
178 /// Makes sure that macro 'mac' is loaded, but do not reload it.
179 
180 void TEveUtil::LoadMacro(const char* mac)
181 {
182  if (CheckMacro(mac) == kFALSE) {
183  gROOT->LoadMacro(mac);
184  }
185 }
186 
187 ////////////////////////////////////////////////////////////////////////////////
188 /// Fill col with RGBA values corresponding to index ci. If alpha
189 /// is true, set alpha component of col to 255.
190 /// ROOT's indexed color palette does not support transparency.
191 
192 void TEveUtil::ColorFromIdx(Color_t ci, UChar_t col[4], Bool_t alpha)
193 {
194  TColor* c = gROOT->GetColor(ci);
195  if (c)
196  {
197  col[0] = (UChar_t)(255*c->GetRed());
198  col[1] = (UChar_t)(255*c->GetGreen());
199  col[2] = (UChar_t)(255*c->GetBlue());
200  if (alpha) col[3] = 255;
201  }
202  else
203  {
204  // Set to magenta.
205  col[0] = 255; col[1] = 0; col[2] = 255;
206  if (alpha) col[3] = 255;
207  return;
208  }
209 }
210 
211 ////////////////////////////////////////////////////////////////////////////////
212 /// Fill col with RGBA values corresponding to index ci and transparency.
213 /// ROOT's indexed color palette does not support transparency.
214 
215 void TEveUtil::ColorFromIdx(Color_t ci, UChar_t col[4], Char_t transparency)
216 {
217  UChar_t alpha = (255*(100 - transparency))/100;
218 
219  TColor* c = gROOT->GetColor(ci);
220  if (c)
221  {
222  col[0] = (UChar_t)(255*c->GetRed());
223  col[1] = (UChar_t)(255*c->GetGreen());
224  col[2] = (UChar_t)(255*c->GetBlue());
225  col[3] = alpha;
226  }
227  else
228  {
229  // Set to magenta.
230  col[0] = 255; col[1] = 0; col[2] = 255; col[3] = alpha;
231  return;
232  }
233 }
234 
235 ////////////////////////////////////////////////////////////////////////////////
236 /// Fill col with weighted RGBA values corresponding to
237 /// color-indices c1 and c2. If alpha is true, set alpha component
238 /// of col to 255.
239 
240 void TEveUtil::ColorFromIdx(Float_t f1, Color_t c1, Float_t f2, Color_t c2,
241  UChar_t col[4], Bool_t alpha)
242 {
243  TColor* t1 = gROOT->GetColor(c1);
244  TColor* t2 = gROOT->GetColor(c2);
245  if(t1 && t2) {
246  col[0] = (UChar_t)(255*(f1*t1->GetRed() + f2*t2->GetRed()));
247  col[1] = (UChar_t)(255*(f1*t1->GetGreen() + f2*t2->GetGreen()));
248  col[2] = (UChar_t)(255*(f1*t1->GetBlue() + f2*t2->GetBlue()));
249  if (alpha) col[3] = 255;
250  }
251 }
252 
253 ////////////////////////////////////////////////////////////////////////////////
254 /// Find address of Color_t data-member with name varname in object
255 /// obj.
256 ///
257 /// This is used to access color information for TGListTreeItem
258 /// coloration from visualization macros that wrap TObjects into
259 /// TEveElementObjectPtr instances.
260 
261 Color_t* TEveUtil::FindColorVar(TObject* obj, const char* varname)
262 {
263  static const TEveException eh("TEveUtil::FindColorVar");
264 
265  Int_t off = obj->IsA()->GetDataMemberOffset(varname);
266  if(off == 0)
267  throw(eh + "could not find member '" + varname + "' in class " + obj->IsA()->GetName() + ".");
268  return (Color_t*) (((char*)obj) + off);
269 }
270 
271 ////////////////////////////////////////////////////////////////////////////////
272 /// Tweak all ROOT colors to become brighter (if value > 0) or
273 /// darker (value < 0). Reasonable values for the value argument are
274 /// from -2.5 to 2.5 (error will be printed otherwise).
275 /// If value is zero, the original colors are restored.
276 ///
277 /// You should call TEveManager::FullRedraw3D() afterwards or set
278 /// the argument full_redraw to true (default is false).
279 
280 void TEveUtil::SetColorBrightness(Float_t value, Bool_t full_redraw)
281 {
282  if (value < -2.5 || value > 2.5)
283  {
284  Error("TEveUtil::SetColorBrightness", "value '%f' out of range [-0.5, 0.5].", value);
285  return;
286  }
287 
288  TObjArray *colors = (TObjArray*) gROOT->GetListOfColors();
289 
290  if (fgDefaultColors == 0)
291  {
292  const Int_t n_col = colors->GetEntriesFast();
293  fgDefaultColors = new TObjArray(n_col);
294  for (Int_t i = 0; i < n_col; ++i)
295  {
296  TColor* c = (TColor*) colors->At(i);
297  if (c)
298  fgDefaultColors->AddAt(new TColor(*c), i);
299  }
300  }
301 
302  const Int_t n_col = fgDefaultColors->GetEntriesFast();
303  for (Int_t i = 0; i < n_col; ++i)
304  {
305  TColor* cdef = (TColor*) fgDefaultColors->At(i);
306  if (cdef)
307  {
308  TColor* croot = (TColor*) colors->At(i);
309  if (croot == 0)
310  {
311  croot = new TColor(*cdef);
312  colors->AddAt(croot, i);
313  }
314  else
315  {
316  cdef->Copy(*croot);
317  }
318 
319  Float_t r, g, b;
320  croot->GetRGB(r, g, b);
321  r = TMath::Power( r, (2.5 - value)/2.5);
322  g = TMath::Power(g, (2.5 - value)/2.5);
323  b = TMath::Power(b, (2.5 - value)/2.5);
324 
325  r = TMath::Min(r, 1.0f);
326  g = TMath::Min(g, 1.0f);
327  b = TMath::Min(b, 1.0f);
328 
329  croot->SetRGB(r, g, b);
330  }
331  else
332  {
333  delete colors->RemoveAt(i);
334  }
335  }
336 
337  if (full_redraw && gEve != 0)
338  gEve->FullRedraw3D();
339 }
340 
341 ////////////////////////////////////////////////////////////////////////////////
342 /// Return true if interval Q is contained within interval M for U1 variables.
343 /// It is assumed that all values are within the [-2pi, 2pi] interval and
344 /// minM <= maxM & minQ <= maxQ.
345 
346 Bool_t TEveUtil::IsU1IntervalContainedByMinMax(Float_t minM, Float_t maxM,
347  Float_t minQ, Float_t maxQ)
348 {
349  using namespace TMath;
350 
351  if (maxQ < minM)
352  {
353  minQ += TwoPi(); maxQ += TwoPi();
354  }
355  else if (minQ > maxM)
356  {
357  minQ -= TwoPi(); maxQ -= TwoPi();
358  }
359  return minQ >= minM && maxQ <= maxM;
360 }
361 
362 ////////////////////////////////////////////////////////////////////////////////
363 /// Return true if interval Q is overlapping within interval M for U1 variables.
364 /// It is assumed that all values are within the [-2pi, 2pi] interval and
365 /// minM <= maxM & minQ <= maxQ.
366 
367 Bool_t TEveUtil::IsU1IntervalOverlappingByMinMax(Float_t minM, Float_t maxM,
368  Float_t minQ, Float_t maxQ)
369 {
370  using namespace TMath;
371 
372  if (maxQ < minM)
373  {
374  minQ += TwoPi(); maxQ += TwoPi();
375  }
376  else if (minQ > maxM)
377  {
378  minQ -= TwoPi(); maxQ -= TwoPi();
379  }
380  return maxQ >= minM && minQ <= maxM;
381 }
382 
383 ////////////////////////////////////////////////////////////////////////////////
384 /// Get fraction of interval [minQ, maxQ] in [minM, maxM]
385 
386 Float_t TEveUtil::GetFraction(Float_t minM, Float_t maxM, Float_t minQ, Float_t maxQ)
387 {
388  if (minQ>=minM && maxQ<=maxM)
389  return 1;
390 
391  else if (minQ<minM && maxQ>maxM)
392  return (maxM-minM)/(maxQ-minQ);
393 
394  else if (minQ>=minM && maxQ>maxM)
395  return (maxM-minQ)/(maxQ-minQ);
396 
397  else if (minQ<minM && maxQ<=maxM)
398  return (maxQ-minM)/(maxQ-minQ);
399 
400  return 0;
401 }
402 
403 
404 /** \class TEveException
405 \ingroup TEve
406 Exception class thrown by TEve classes and macros.
407 */
408 
409 ClassImp(TEveException);
410 
411 ////////////////////////////////////////////////////////////////////////////////
412 
413 bool operator==(const TString& t, const std::string& s)
414 { return (s == t.Data()); }
415 
416 bool operator==(const std::string& s, const TString& t)
417 { return (s == t.Data()); }
418 
419 // Exc
420 
421 TEveException::TEveException(const std::string& s) : TString(s.c_str())
422 {
423  // Constructor.
424 }
425 
426 // Exc + ops
427 
428 TEveException operator+(const TEveException &s1, const std::string &s2)
429 { TEveException r(s1); r += s2; return r; }
430 
431 TEveException operator+(const TEveException &s1, const TString &s2)
432 { TEveException r(s1); r += s2; return r; }
433 
434 TEveException operator+(const TEveException &s1, const char *s2)
435 { TEveException r(s1); r += s2; return r; }
436 
437 
438 /** \class TEvePadHolder
439 \ingroup TEve
440 Exception safe wrapper for setting gPad.
441 Optionally calls gPad->Modified()/Update() in destructor.
442 */
443 
444 ClassImp(TEvePadHolder);
445 
446 ////////////////////////////////////////////////////////////////////////////////
447 /// Constructor.
448 
449 TEvePadHolder::TEvePadHolder(Bool_t modify_update_p, TVirtualPad* new_pad, Int_t subpad) :
450  fOldPad (gPad),
451  fModifyUpdateP (modify_update_p)
452 {
453  if (new_pad != 0)
454  new_pad->cd(subpad);
455  else
456  gPad = 0;
457 }
458 
459 ////////////////////////////////////////////////////////////////////////////////
460 /// Destructor.
461 
462 TEvePadHolder::~TEvePadHolder()
463 {
464  if (fModifyUpdateP && gPad != 0) {
465  gPad->Modified();
466  gPad->Update();
467  }
468  gPad = fOldPad;
469 }
470 
471 /** \class TEveGeoManagerHolder
472 \ingroup TEve
473 Exception safe wrapper for setting gGeoManager.
474 Functionality to lock-unlock via setting of a static lock in
475 TGeoManager should be added (new feature of TGeoManager).
476 */
477 
478 ClassImp(TEveGeoManagerHolder);
479 
480 ////////////////////////////////////////////////////////////////////////////////
481 /// Constructor.
482 /// If n_seg is specified and larger than 2, the new geo-manager's
483 /// NSegments is set to this value.
484 
485 TEveGeoManagerHolder::TEveGeoManagerHolder(TGeoManager* new_gmgr, Int_t n_seg) :
486  fManager (gGeoManager),
487  fNSegments (0)
488 {
489  gGeoManager = new_gmgr;
490  if (gGeoManager)
491  {
492  gGeoIdentity = (TGeoIdentity*) gGeoManager->GetListOfMatrices()->At(0);
493  if (n_seg > 2)
494  {
495  fNSegments = gGeoManager->GetNsegments();
496  gGeoManager->SetNsegments(n_seg);
497  }
498  }
499  else
500  {
501  gGeoIdentity = 0;
502  }
503 }
504 
505 ////////////////////////////////////////////////////////////////////////////////
506 /// Destructor.
507 
508 TEveGeoManagerHolder::~TEveGeoManagerHolder()
509 {
510  if (gGeoManager && fNSegments > 2)
511  {
512  gGeoManager->SetNsegments(fNSegments);
513  }
514  gGeoManager = fManager;
515  if (gGeoManager)
516  {
517  gGeoIdentity = (TGeoIdentity*) gGeoManager->GetListOfMatrices()->At(0);
518  }
519  else
520  {
521  gGeoIdentity = 0;
522  }
523 }
524 
525 /** \class TEveRefCnt
526 \ingroup TEve
527 Base-class for reference-counted objects.
528 By default the object is destroyed when zero reference-count is reached.
529 */
530 
531 ClassImp(TEveRefCnt);
532 
533 /** \class TEveRefBackPtr
534 \ingroup TEve
535 Base-class for reference-counted objects with reverse references to
536 TEveElement objects.
537 */
538 
539 ClassImp(TEveRefBackPtr);
540 
541 ////////////////////////////////////////////////////////////////////////////////
542 /// Default constructor.
543 
544 TEveRefBackPtr::TEveRefBackPtr() :
545  TEveRefCnt(),
546  fBackRefs()
547 {
548 }
549 
550 ////////////////////////////////////////////////////////////////////////////////
551 /// Destructor. Noop, should complain if back-ref list is not empty.
552 
553 TEveRefBackPtr::~TEveRefBackPtr()
554 {
555  // !!! Complain if list not empty.
556 }
557 
558 ////////////////////////////////////////////////////////////////////////////////
559 /// Copy constructor. New copy starts with zero reference count and
560 /// empty back-reference list.
561 
562 TEveRefBackPtr::TEveRefBackPtr(const TEveRefBackPtr&) :
563  TEveRefCnt(),
564  fBackRefs()
565 {
566 }
567 
568 ////////////////////////////////////////////////////////////////////////////////
569 /// Assignment operator. Reference count and back-reference
570 /// information is not assigned as these object hold pointers to a
571 /// specific object.
572 
573 TEveRefBackPtr& TEveRefBackPtr::operator=(const TEveRefBackPtr&)
574 {
575  return *this;
576 }
577 
578 ////////////////////////////////////////////////////////////////////////////////
579 /// Increase reference count and add re to the list of back-references.
580 
581 void TEveRefBackPtr::IncRefCount(TEveElement* re)
582 {
583  TEveRefCnt::IncRefCount();
584  ++fBackRefs[re];
585 }
586 
587 ////////////////////////////////////////////////////////////////////////////////
588 /// Decrease reference count and remove re from the list of back-references.
589 
590 void TEveRefBackPtr::DecRefCount(TEveElement* re)
591 {
592  static const TEveException eh("TEveRefBackPtr::DecRefCount ");
593 
594  RefMap_i i = fBackRefs.find(re);
595  if (i != fBackRefs.end()) {
596  if (--(i->second) <= 0)
597  fBackRefs.erase(i);
598  TEveRefCnt::DecRefCount();
599  } else {
600  Warning(eh, "render element '%s' not found in back-refs.",
601  re->GetObject(eh)->GetName());
602  }
603 }
604 
605 ////////////////////////////////////////////////////////////////////////////////
606 /// Add given stamps to elements in the list of reverse references.
607 
608 void TEveRefBackPtr::StampBackPtrElements(UChar_t stamps)
609 {
610  RefMap_i i = fBackRefs.begin();
611  while (i != fBackRefs.end())
612  {
613  i->first->AddStamp(stamps);
614  ++i;
615  }
616 }