Logo ROOT   6.14/05
Reference Guide
TGLHistPainter.cxx
Go to the documentation of this file.
1 // @(#)root/gl:$Id$
2 // Author: Timur Pocheptsov 17/11/2005
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2005, 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 <stdexcept>
13 #include <cstring>
14 
15 #include "TVirtualGL.h"
16 #include "KeySymbols.h"
17 #include "Buttons.h"
18 #include "TH2Poly.h"
19 #include "TClass.h"
20 #include "TROOT.h"
21 #include "TGL5D.h"
22 #include "TMath.h"
23 #include "TPad.h"
24 #include "TH3.h"
25 #include "TF3.h"
26 
27 #include "TGLSurfacePainter.h"
28 #include "TGLTH3Composition.h"
29 #include "TGLH2PolyPainter.h"
30 #include "TGLVoxelPainter.h"
31 #include "TGLHistPainter.h"
32 #include "TGLLegoPainter.h"
33 #include "TGLBoxPainter.h"
34 #include "TGLTF3Painter.h"
35 #include "TGLParametric.h"
36 #include "TGL5DPainter.h"
37 #include "TGLUtil.h"
38 
40 
41 /** \class TGLHistPainter
42 \ingroup opengl
43 The histogram painter class using OpenGL.
44 
45 Histograms are, by default, drawn via the `THistPainter` class.
46 `TGLHistPainter` allows to paint them using the OpenGL 3D graphics
47 library. The plotting options provided by `TGLHistPainter` start with
48 `GL` keyword.
49 
50 ### General information: plot types and supported options
51 
52 The following types of plots are provided:
53 
54 #### Lego - (`TGLLegoPainter`)
55  The supported options are:
56 
57  - `"GLLEGO" :` Draw a lego plot.
58  - `"GLLEGO2" :` Bins with color levels.
59  - `"GLLEGO3" :` Cylindrical bars.
60 
61  Lego painter in cartesian supports logarithmic scales for X, Y, Z.
62  In polar only Z axis can be logarithmic, in cylindrical only Y (if you see
63  what it means).
64 
65 
66 #### Surfaces (`TF2` and `TH2` with `"GLSURF"` options) - (`TGLSurfacePainter`)
67  The supported options are:
68 
69  - `"GLSURF" :` Draw a surface.
70  - `"GLSURF1" :` Surface with color levels
71  - `"GLSURF2" :` The same as `"GLSURF1"` but without polygon outlines.
72  - `"GLSURF3" :` Color level projection on top of plot (works only in cartesian coordinate system).
73  - `"GLSURF4" :` Same as `"GLSURF"` but without polygon outlines.
74 
75 
76  The surface painting in cartesian coordinates supports logarithmic scales along X, Y, Z axis.
77  In polar coordinates only the Z axis can be logarithmic, in cylindrical coordinates only the Y axis.
78 
79 #### Additional options to `SURF` and `LEGO` - Coordinate systems:
80  The supported options are:
81 
82  - `" " :` Default, cartesian coordinates system.
83  - `"POL" :` Polar coordinates system.
84  - `"CYL" :` Cylindrical coordinates system.
85  - `"SPH" :` Spherical coordinates system.
86 
87 
88 #### `TH3` as boxes (spheres) - (`TGLBoxPainter`)
89  The supported options are:
90 
91  - `"GLBOX" :` TH3 as a set of boxes, size of box is proportional to bin content.
92  - `"GLBOX1":` the same as "glbox", but spheres are drawn instead of boxes.
93 
94 
95 #### `TH3` as iso-surface(s) - (`TGLIsoPainter`)
96  The supported option is:
97 
98  - `"GLISO" :` TH3 is drawn using iso-surfaces.
99 
100 
101 #### `TH3` as color boxes - (`TGLVoxelPainter`)
102  The supported option is:
103 
104  - `"GLCOL" :` TH3 is drawn using semi-transparent colored boxes.
105  See `$ROOTSYS/tutorials/gl/glvox1.C`.
106 
107 
108 #### `TF3` (implicit function) - (`TGLTF3Painter`)
109  The supported option is:
110 
111  - `"GLTF3" :` Draw a `TF3`.
112 
113 
114 #### Parametric surfaces - (`TGLParametricPlot`)
115  `$ROOTSYS/tutorials/gl/glparametric.C` shows how to create parametric equations and
116  visualize the surface.
117 
118 
119 ### Interaction with the plots
120 
121 
122 #### General information.
123 
124  All the interactions are implemented via standard methods `DistancetoPrimitive` and
125  `ExecuteEvent`. That's why all the interactions with the OpenGL plots are possible i
126  only when the mouse cursor is in the plot's area (the plot's area is the part of a the pad
127  occupied by gl-produced picture). If the mouse cursor is not above gl-picture,
128  the standard pad interaction is performed.
129 
130 #### Selectable parts.
131 
132  Different parts of the plot can be selected:
133 
134  - *xoz, yoz, xoy back planes*:
135  When such a plane selected, it's highlighted in green if the dynamic slicing
136  by this plane is supported, and it's highlighted in red, if the dynamic slicing
137  is not supported.
138  -*The plot itself*:
139  On surfaces, the selected surface is outlined in red. (TF3 and ISO are not
140  outlined). On lego plots, the selected bin is highlihted. The bin number and content are displayed in pad's status
141  bar. In box plots, the box or sphere is highlighted and the bin info is displayed in pad's status bar.
142 
143 #### Rotation and zooming.
144 
145  - *Rotation*:
146 
147  When the plot is selected, it can be rotated by pressing and holding the left mouse button and move the cursor.
148  - *Zoom/Unzoom*:
149 
150  Mouse wheel or `'j'`, `'J'`, `'k'`, `'K'` keys.
151 
152 
153 #### Panning.
154 
155  The selected plot can be moved in a pad's area by
156  pressing and holding the left mouse button and the shift key.
157 
158 ### Box cut
159  Surface, iso, box, TF3 and parametric painters support box cut by pressing the `'c'` or
160  `'C'` key when the mouse cursor is in a plot's area. That will display a transparent box,
161  cutting away part of the surface (or boxes) in order to show internal part of plot.
162  This box can be moved inside the plot's area (the full size of the box is equal to the plot's
163  surrounding box) by selecting one of the box cut axes and pressing the left mouse button to move it.
164 
165 ### Plot specific interactions (dynamic slicing etc.)
166  Currently, all gl-plots support some form of slicing.
167  When back plane is selected (and if it's highlighted in green)
168  you can press and hold left mouse button and shift key
169  and move this back plane inside plot's area, creating the slice.
170  During this "slicing" plot becomes semi-transparent. To remove all slices (and projected curves for surfaces)
171  - double click with left mouse button in a plot's area.
172 
173  #### Surface with option `"GLSURF"`
174 
175  The surface profile is displayed on the slicing plane.
176  The profile projection is drawn on the back plane
177  by pressing `'p'` or `'P'` key.
178 
179  #### TF3
180 
181  The contour plot is drawn on the slicing plane.
182  For `TF3` the color scheme can be changed by pressing `'s'` or `'S'`.
183 
184  #### Box
185 
186  The contour plot corresponding to slice plane position is drawn in real time.
187 
188  #### Iso
189 
190  Slicing is similar to `"GLBOX"` option.
191 
192  #### Parametric plot
193 
194  No slicing. Additional keys: `'s'` or `'S'` to change color scheme - about 20 color schemes supported
195  (`'s'` for "scheme"); `'l'` or `'L'` to increase number of polygons (`'l'` for "level" of details),
196  `'w'` or `'W'` to show outlines (`'w'` for "wireframe").
197 */
198 
199 ////////////////////////////////////////////////////////////////////////////////
200 /// ROOT does not use exceptions, so, if default painter's creation failed,
201 /// fDefaultPainter is 0. In each function, which use it, I have to check the pointer first.
202 
204  : fDefaultPainter(TVirtualHistPainter::HistPainter(hist)),
205  fEq(0),
206  fHist(hist),
207  fF3(0),
208  fStack(0),
209  fPlotType(kGLDefaultPlot)//THistPainter
210 {
211 }
212 
213 ////////////////////////////////////////////////////////////////////////////////
214 ///This ctor creates gl-parametric plot's painter.
215 
217  : fEq(equation),
218  fHist(0),
219  fF3(0),
220  fStack(0),
221  fPlotType(kGLParametricPlot)//THistPainter
222 {
223  fGLPainter.reset(new TGLParametricPlot(equation, &fCamera));
224 }
225 
226 ////////////////////////////////////////////////////////////////////////////////
227 ///This ctor creates plot painter for TGL5DDataSet.
228 
230  : fEq(0),
231  fHist(0),
232  fF3(0),
233  fStack(0),
234  fPlotType(kGL5D)//THistPainter
235 {
236  fGLPainter.reset(new TGL5DPainter(data, &fCamera, &fCoord));
237 }
238 
239 ////////////////////////////////////////////////////////////////////////////////
240 ///This ctor creates plot painter for TGL5DDataSet.
241 
243  : fEq(0),
244  fHist(data),
245  fF3(0),
246  fStack(0),
248 {
249  fGLPainter.reset(new TGLTH3CompositionPainter(data, &fCamera, &fCoord));
250 }
251 
252 ////////////////////////////////////////////////////////////////////////////////
253 ///Selects plot or axis.
254 ///9999 is the magic number, ROOT's classes use in DistancetoPrimitive.
255 
257 {
258  //[tp: return statement added.
259  //tp]
260 
261  if (fPlotType == kGLDefaultPlot)
262  return fDefaultPainter.get() ? fDefaultPainter->DistancetoPrimitive(px, py) : 9999;
263  else {
264  //Adjust px and py - canvas can have several pads inside, so we need to convert
265  //the from canvas' system into pad's.
266 
267  //Retina-related adjustments must be done inside!!!
268 
269  py = gPad->GetWh() - py;
270 
271  //One hist can be appended to several pads,
272  //the current pad should have valid OpenGL context.
273  const Int_t glContext = gPad->GetGLDevice();
274 
275  if (glContext != -1) {
276  //Add "viewport" extraction here.
278 
279  if (!gGLManager->PlotSelected(fGLPainter.get(), px, py))
280  gPad->SetSelected(gPad);
281  } else {
282  Error("DistancetoPrimitive",
283  "Attempt to use TGLHistPainter, while the current pad (gPad) does not support gl");
284  gPad->SetSelected(gPad);
285  }
286 
287  return 0;
288  }
289 }
290 
291 ////////////////////////////////////////////////////////////////////////////////
292 ///Default implementation is OK
293 ///This function is called from a context menu
294 ///after right click on a plot's area. Opens window
295 ///("panel") with several controls.
296 
298 {
299  if (fDefaultPainter.get())
300  fDefaultPainter->DrawPanel();
301 }
302 
303 ////////////////////////////////////////////////////////////////////////////////
304 ///Execute event.
305 ///Events are: mouse events in a plot's area,
306 ///key presses (while mouse cursor is in plot's area).
307 ///"Event execution" means one of the following actions:
308 /// 1. Rotation.
309 /// 2. Panning.
310 /// 3. Zoom changing.
311 /// 4. Moving dynamic profile.
312 /// 5. Plot specific events - for example, 's' or 'S' key press for TF3.
313 
315 {
316  if (fPlotType == kGLDefaultPlot) {
317  if(fDefaultPainter.get()) {
318  fDefaultPainter->ExecuteEvent(event, px, py);
319  }
320  } else {
321  //One hist can be appended to several pads,
322  //the current pad should have valid OpenGL context.
323  const Int_t glContext = gPad->GetGLDevice();
324 
325  if (glContext == -1) {
326  Error("ExecuteEvent",
327  "Attempt to use TGLHistPainter, while the current pad (gPad) does not support gl");
328  return;
329  } else {
330  //Add viewport extraction here.
331  /*fGLDevice.SetGLDevice(glContext);
332  fGLPainter->SetGLDevice(&fGLDevice);*/
333  PadToViewport();
334  }
335 
336  if (event != kKeyPress) {
337  //Adjust px and py - canvas can have several pads inside, so we need to convert
338  //the from canvas' system into pad's. If it was a key press event,
339  //px and py ARE NOT coordinates.
340  py -= Int_t((1 - gPad->GetHNDC() - gPad->GetYlowNDC()) * gPad->GetWh());
341  px -= Int_t(gPad->GetXlowNDC() * gPad->GetWw());
342 
343  //We also have to take care of retina displays with a different viewports.
346  if (scale > 1) {
347  px *= scale;
348  py *= scale;
349  }
350  }
351 
352  switch (event) {
353  case kButton1Double:
354  //Left double click removes dynamic sections, user created (if plot type supports sections).
355  fGLPainter->ProcessEvent(event, px, py);
356  break;
357  case kButton1Down:
358  //Left mouse down in a plot area starts rotation.
359  if (!fGLPainter->CutAxisSelected())
360  fCamera.StartRotation(px, py);
361  else
362  fGLPainter->StartPan(px, py);
363  //During rotation, usual TCanvas/TPad machinery (CopyPixmap/Flush/UpdateWindow/etc.)
364  //is skipped - I use "bit blasting" functions to copy picture directly onto window.
365  //gGLManager->MarkForDirectCopy(glContext, kTRUE);
366  break;
367  case kButton1Motion:
368  //Rotation invalidates "selection buffer"
369  // - (color-to-object map, previously read from gl-buffer).
370  fGLPainter->InvalidateSelection();
371  if (fGLPainter->CutAxisSelected())
372  gGLManager->PanObject(fGLPainter.get(), px, py);
373  else
374  fCamera.RotateCamera(px, py);
375  //Draw modified scene onto canvas' window.
376  //gGLManager->PaintSingleObject(fGLPainter.get());
377  gPad->Update();
378  break;
379  case kButton1Up:
380  case kButton2Up:
381  gGLManager->MarkForDirectCopy(glContext, kFALSE);
382  break;
383  case kMouseMotion:
384  gPad->SetCursor(kRotate);
385  break;
386  case 7://kButton1Down + shift modifier
387  //The current version of ROOT does not
388  //have enumerators for button events + key modifiers,
389  //so I use hardcoded literals. :(
390  //With left mouse button down and shift pressed
391  //we can move plot as the whole or move
392  //plot's parts - dynamic sections.
393  fGLPainter->StartPan(px, py);
394  gGLManager->MarkForDirectCopy(glContext, kTRUE);
395  break;
396  case 8://kButton1Motion + shift modifier
397  gGLManager->PanObject(fGLPainter.get(), px, py);
398  //gGLManager->PaintSingleObject(fGLPainter.get());
399  gPad->Update();
400  break;
401  case kKeyPress:
402  case 5:
403  case 6:
404  //5, 6 are mouse wheel events (see comment about literals above).
405  //'p'/'P' - specific events processed by TGLSurfacePainter,
406  //'s'/'S' - specific events processed by TGLTF3Painter,
407  //'c'/'C' - turn on/off box cut.
408  gGLManager->MarkForDirectCopy(glContext, kTRUE);
409  if (event == 6 || py == kKey_J || py == kKey_j) {
410  fCamera.ZoomIn();
411  fGLPainter->InvalidateSelection();
412  //gGLManager->PaintSingleObject(fGLPainter.get());
413  gPad->Update();
414  } else if (event == 5 || py == kKey_K || py == kKey_k) {
415  fCamera.ZoomOut();
416  fGLPainter->InvalidateSelection();
417  //gGLManager->PaintSingleObject(fGLPainter.get());
418  gPad->Update();
419  } else if (py == kKey_p || py == kKey_P || py == kKey_S || py == kKey_s
420  || py == kKey_c || py == kKey_C || py == kKey_x || py == kKey_X
421  || py == kKey_y || py == kKey_Y || py == kKey_z || py == kKey_Z
422  || py == kKey_w || py == kKey_W || py == kKey_l || py == kKey_L
423  /*|| py == kKey_r || py == kKey_R*/)
424  {
425  fGLPainter->ProcessEvent(event, px, py);
426  //gGLManager->PaintSingleObject(fGLPainter.get());
427  gPad->Update();
428  }
429  gGLManager->MarkForDirectCopy(glContext, kFALSE);
430  break;
431  }
432  }
433 }
434 
435 ////////////////////////////////////////////////////////////////////////////////
436 ///Get contour list.
437 ///I do not use this function. Contours are implemented in
438 ///a completely different way by gl-painters.
439 
441 {
442  return fDefaultPainter.get() ? fDefaultPainter->GetContourList(contour) : 0;
443 }
444 
445 ////////////////////////////////////////////////////////////////////////////////
446 ///Overrides TObject::GetObjectInfo.
447 ///For lego info is: bin numbers (i, j), bin content.
448 ///For TF2 info is: x,y,z 3d surface-point for 2d screen-point under cursor
449 ///(this can work incorrectly now, because of wrong code in TF2).
450 ///For TF3 no info now.
451 ///For box info is: bin numbers (i, j, k), bin content.
452 
454 {
455  static char errMsg[] = { "TGLHistPainter::GetObjectInfo: Error in a hist painter\n" };
456  if (fPlotType == kGLDefaultPlot)
457  return fDefaultPainter.get() ? fDefaultPainter->GetObjectInfo(px, py)
458  : errMsg;
459  else {
462  if (scale > 1.f) {
463  px *= scale;
464  py *= scale;
465  }
466 
467  return gGLManager->GetPlotInfo(fGLPainter.get(), px, py);
468  }
469 }
470 
471 ////////////////////////////////////////////////////////////////////////////////
472 /// Get stack.
473 
475 {
476  return fStack;
477 }
478 
479 ////////////////////////////////////////////////////////////////////////////////
480 ///Returns kTRUE if the cell ix, iy is inside one of the graphical cuts.
481 ///I do not use this function anywhere, this is a "default implementation".
482 
484 {
485  if (fPlotType == kGLDefaultPlot)
486  return fDefaultPainter.get() ? fDefaultPainter->IsInside(x, y) : kFALSE;
487 
488  return kFALSE;
489 }
490 
491 ////////////////////////////////////////////////////////////////////////////////
492 ///Returns kTRUE if the cell x, y is inside one of the graphical cuts.
493 ///I do not use this function anywhere, this is a "default implementation".
494 
496 {
497  if (fPlotType == kGLDefaultPlot)
498  return fDefaultPainter.get() ? fDefaultPainter->IsInside(x, y) : kFALSE;
499 
500  return kFALSE;
501 }
502 
503 ////////////////////////////////////////////////////////////////////////////////
504 ///Paint statistics.
505 ///This does not work on windows.
506 
508 {
509  if (fDefaultPainter.get())
510  fDefaultPainter->PaintStat(dostat, fit);
511 }
512 
513 ////////////////////////////////////////////////////////////////////////////////
514 /// Process message.
515 
516 void TGLHistPainter::ProcessMessage(const char *m, const TObject *o)
517 {
518  if (!std::strcmp(m, "SetF3"))
519  fF3 = (TF3 *)o;
520 
521  if (fDefaultPainter.get())
522  fDefaultPainter->ProcessMessage(m, o);
523 }
524 
525 ////////////////////////////////////////////////////////////////////////////////
526 /// Set histogram.
527 
529 {
530  fHist = h;
531 
532  if (fDefaultPainter.get())
533  fDefaultPainter->SetHistogram(h);
534 }
535 
536 ////////////////////////////////////////////////////////////////////////////////
537 /// Set stack.
538 
540 {
541  fStack = s;
542 
543  if (fDefaultPainter.get())
544  fDefaultPainter->SetStack(s);
545 }
546 
547 ////////////////////////////////////////////////////////////////////////////////
548 /// Make cuts.
549 
551 {
552  if (fPlotType == kGLDefaultPlot && fDefaultPainter.get())
553  return fDefaultPainter->MakeCuts(o);
554 
555  return 0;
556 }
557 
558 struct TGLHistPainter::PlotOption_t {
560  EGLCoordType fCoordType;
561  Bool_t fBackBox;
562  Bool_t fFrontBox;
563  Bool_t fDrawAxes;
564  Bool_t fLogX;
565  Bool_t fLogY;
566  Bool_t fLogZ;
567 };
568 
569 ////////////////////////////////////////////////////////////////////////////////
570 ///Final-overrider for TObject::Paint.
571 
573 {
574  TString option(o);
575  option.ToLower();
576 
577  const Ssiz_t glPos = option.Index("gl");
578  if (glPos != kNPOS)
579  option.Remove(glPos, 2);
581  gPad->SetCopyGLDevice(kFALSE);
582  if (fDefaultPainter.get())
583  fDefaultPainter->Paint(o);//option.Data());
584  return;
585  }
586 
588  CreatePainter(ParsePaintOption(option), option);
589 
590  if (fPlotType == kGLDefaultPlot) {
591  //In case of default plot pad
592  //should not copy gl-buffer (it will be simply black)
593 
594  //[tp: code was commented.
595  //gPad->SetCopyGLDevice(kFALSE);
596  //tp]
597 
598  if (fDefaultPainter.get())
599  fDefaultPainter->Paint(option.Data());
600  } else {
601  Int_t glContext = gPad->GetGLDevice();
602 
603  if (glContext != -1) {
604  //With gl-plot, pad should copy
605  //gl-buffer into the final pad/canvas pixmap/DIB.
606  //fGLDevice.SetGLDevice(glContext);
607 
608  //[tp: code commented.
609  //gPad->SetCopyGLDevice(kTRUE);
610  //tp]
611  //fGLPainter->SetGLDevice(&fGLDevice);
612  //Add viewport extraction here.
613  PadToViewport();
614  if (gPad->GetFrameFillColor() != kWhite)
615  fGLPainter->SetFrameColor(gROOT->GetColor(gPad->GetFrameFillColor()));
616  fGLPainter->SetPadColor(gROOT->GetColor(gPad->GetFillColor()));
617  if (fGLPainter->InitGeometry())
618  gGLManager->PaintSingleObject(fGLPainter.get());
619  }
620  }
621 }
622 
623 namespace {
624 
625 Bool_t FindAndRemoveOption(TString &options, const char *toFind)
626 {
627  const UInt_t len = std::strlen(toFind);
628  const Ssiz_t index = options.Index(toFind);
629 
630  if (index != kNPOS) {
631  options.Remove(index, len);
632  return kTRUE;
633  }
634 
635  return kFALSE;
636 }
637 
638 }
639 
640 ////////////////////////////////////////////////////////////////////////////////
641 ///In principle, we can have several conflicting options: "lego surf pol sph", surfbb: surf, fb, bb.
642 ///but only one will be selected, which one - depends on parsing order in this function.
643 
644 TGLHistPainter::PlotOption_t
646 {
647  TString options(o);
648 
649  PlotOption_t parsedOption = {kGLDefaultPlot, kGLCartesian,
650  kTRUE, kTRUE, kTRUE, //Show back box, show front box, show axes.
651  Bool_t(gPad->GetLogx()), Bool_t(gPad->GetLogy()),
652  Bool_t(gPad->GetLogz())};
653 
654  //Check coordinate system type.
655  if (FindAndRemoveOption(options, "pol"))
656  parsedOption.fCoordType = kGLPolar;
657  if (FindAndRemoveOption(options, "cyl"))
658  parsedOption.fCoordType = kGLCylindrical;
659  if (FindAndRemoveOption(options, "sph"))
660  parsedOption.fCoordType = kGLSpherical;
661 
662  //Define plot type.
663  if (FindAndRemoveOption(options, "lego"))
664  fStack ? parsedOption.fPlotType = kGLStackPlot : parsedOption.fPlotType = kGLLegoPlot;
665  if (FindAndRemoveOption(options, "surf"))
666  parsedOption.fPlotType = kGLSurfacePlot;
667  if (FindAndRemoveOption(options, "tf3"))
668  parsedOption.fPlotType = kGLTF3Plot;
669  if (FindAndRemoveOption(options, "box"))
670  parsedOption.fPlotType = kGLBoxPlot;
671  if (FindAndRemoveOption(options, "iso"))
672  parsedOption.fPlotType = kGLIsoPlot;
673  if (FindAndRemoveOption(options, "col"))
674  parsedOption.fPlotType = kGLVoxel;
675 
676  //Check BB and FB options.
677  if (FindAndRemoveOption(options, "bb"))
678  parsedOption.fBackBox = kFALSE;
679  if (FindAndRemoveOption(options, "fb"))
680  parsedOption.fFrontBox = kFALSE;
681 
682  //Check A option.
683  if (FindAndRemoveOption(options, "a"))
684  parsedOption.fDrawAxes = kFALSE;
685 
686  return parsedOption;
687 }
688 
689 ////////////////////////////////////////////////////////////////////////////////
690 /// Create painter.
691 
692 void TGLHistPainter::CreatePainter(const PlotOption_t &option, const TString &addOption)
693 {
694  if (option.fPlotType != fPlotType) {
696  fGLPainter.reset(0);
697  }
698 
699  if (option.fPlotType == kGLLegoPlot) {
700  if (!fGLPainter.get()) {
701  if (dynamic_cast<TH2Poly*>(fHist))
703  else
704  fGLPainter.reset(new TGLLegoPainter(fHist, &fCamera, &fCoord));
705  }
706  } else if (option.fPlotType == kGLSurfacePlot) {
707  if (!fGLPainter.get())
709  } else if (option.fPlotType == kGLBoxPlot) {
710  if (!fGLPainter.get())
711  fGLPainter.reset(new TGLBoxPainter(fHist, &fCamera, &fCoord));
712  } else if (option.fPlotType == kGLTF3Plot) {
713  if (!fGLPainter.get())
714  fGLPainter.reset(new TGLTF3Painter(fF3, fHist, &fCamera, &fCoord));
715  } else if (option.fPlotType == kGLIsoPlot) {
716  if (!fGLPainter.get())
717  fGLPainter.reset(new TGLIsoPainter(fHist, &fCamera, &fCoord));
718  } else if (option.fPlotType == kGLVoxel) {
719  if (!fGLPainter.get())
721  }
722 
723  if (fGLPainter.get()) {
724  fPlotType = option.fPlotType;
725  fCoord.SetXLog(gPad->GetLogx());
726  fCoord.SetYLog(gPad->GetLogy());
727  fCoord.SetZLog(gPad->GetLogz());
728  fCoord.SetCoordType(option.fCoordType);
729  fGLPainter->AddOption(addOption);
730 
731  fGLPainter->SetDrawFrontBox(option.fFrontBox);
732  fGLPainter->SetDrawBackBox(option.fBackBox);
733  fGLPainter->SetDrawAxes(option.fDrawAxes);
734  } else
736 }
737 
738 ////////////////////////////////////////////////////////////////////////////////
739 /// Set show projection.
740 
741 void TGLHistPainter::SetShowProjection(const char *option, Int_t nbins)
742 {
743  if (fDefaultPainter.get()) fDefaultPainter->SetShowProjection(option, nbins);
744 }
745 
746 ////////////////////////////////////////////////////////////////////////////////
747 
748 void TGLHistPainter::PadToViewport(Bool_t /*selectionPass*/)
749 {
750  if (!fGLPainter.get())
751  return;
752 
753  TGLRect vp;
754  vp.Width() = Int_t(gPad->GetAbsWNDC() * gPad->GetWw());
755  vp.Height() = Int_t(gPad->GetAbsHNDC() * gPad->GetWh());
756 
757  vp.X() = Int_t(gPad->XtoAbsPixel(gPad->GetX1()));
758  vp.Y() = Int_t((gPad->GetWh() - gPad->YtoAbsPixel(gPad->GetY1())));
759 
762 
763  if (scale > 1.f) {
764  vp.X() = Int_t(vp.X() * scale);
765  vp.Y() = Int_t(vp.Y() * scale);
766 
767  vp.Width() = Int_t(vp.Width() * scale);
768  vp.Height() = Int_t(vp.Height() * scale);
769  }
770 
771  fCamera.SetViewport(vp);
772  if (fCamera.ViewportChanged() && fGLPainter.get())
773  fGLPainter->InvalidateSelection();
774 }
void SetViewport(const TGLRect &vp)
Setup viewport, if it was changed, plus reset arcball.
void SetStack(TList *stack)
Set stack.
Plot-painter implementing LEGO rendering of TH2 histograms in cartesian, polar, cylindrical and spher...
auto * m
Definition: textangle.C:8
void CreatePainter(const PlotOption_t &parsed, const TString &option)
Create painter.
Int_t X() const
Definition: TGLUtil.h:447
PlotOption_t ParsePaintOption(const TString &option) const
In principle, we can have several conflicting options: "lego surf pol sph", surfbb: surf...
float Float_t
Definition: RtypesCore.h:53
Bool_t IsInside(Int_t x, Int_t y)
Returns kTRUE if the cell ix, iy is inside one of the graphical cuts.
const char Option_t
Definition: RtypesCore.h:62
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
void SetHistogram(TH1 *hist)
Set histogram.
void DrawPanel()
Default implementation is OK This function is called from a context menu after right click on a plot&#39;...
static Float_t GetScreenScalingFactor()
Returns scaling factor between screen points and GL viewport pixels.
Definition: TGLUtil.cxx:1813
#define gROOT
Definition: TROOT.h:410
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
Paint TH3 histograms as "voxels" - colored boxes, transparent if transfer function was specified...
Basic string class.
Definition: TString.h:131
#define f(i)
Definition: RSha256.hxx:104
Bool_t ViewportChanged() const
Definition: TGLPlotCamera.h:53
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1100
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Int_t Y() const
Definition: TGLUtil.h:449
char * GetObjectInfo(Int_t px, Int_t py) const
Overrides TObject::GetObjectInfo.
Implements painting of TH2 with "SURF" option.
Paints TH3 histograms by rendering variable-sized boxes matching the bin contents.
Definition: TGLBoxPainter.h:32
Int_t DistancetoPrimitive(Int_t px, Int_t py)
Selects plot or axis.
void Paint(Option_t *option)
Final-overrider for TObject::Paint.
TList * GetContourList(Double_t contour) const
Get contour list.
Double_t x[n]
Definition: legend1.C:17
Plot-painter for TF3 functions.
Definition: TGLTF3Painter.h:29
std::unique_ptr< TGLPlotPainter > fGLPainter
Abstract interface to a histogram painter.
void ZoomOut()
Zoom out.
Viewport (pixel base) 2D rectangle class.
Definition: TGLUtil.h:422
void SetYLog(Bool_t yLog)
If log changed, sections must be reset, set fModified.
TGLPlotCoordinates fCoord
void PadToViewport(Bool_t selectionPass=kFALSE)
Paint TH2Poly.
void StartRotation(Int_t px, Int_t py)
User clicks somewhere (px, py).
A doubly linked list.
Definition: TList.h:44
Definition: Rtypes.h:58
std::unique_ptr< TVirtualHistPainter > fDefaultPainter
Definition: TGLUtil.h:58
TGLParametricEquation * fEq
void RotateCamera(Int_t px, Int_t py)
Mouse movement.
EGLCoordType
Definition: TGLUtil.h:41
static void InitializeIfNeeded()
Initialize globals that require other libraries to be initialized.
Definition: TGLUtil.cxx:1543
void ProcessMessage(const char *message, const TObject *obj)
Process message.
A 3-Dim function with parameters.
Definition: TF3.h:28
TGLHistPainter(TH1 *hist)
ROOT does not use exceptions, so, if default painter&#39;s creation failed, fDefaultPainter is 0...
EGLPlotType fPlotType
void ResetModified()
Reset modified.
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
"gliso" option for TH3.
Definition: TGLTF3Painter.h:85
void SetXLog(Bool_t xLog)
If log changed, sections must be reset, set fModified.
A parametric surface is a surface defined by a parametric equation, involving two parameters (u...
Definition: TGLParametric.h:35
#define h(i)
Definition: RSha256.hxx:106
Int_t Width() const
Definition: TGLUtil.h:451
const Bool_t kFALSE
Definition: RtypesCore.h:88
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
int Ssiz_t
Definition: RtypesCore.h:63
#define ClassImp(name)
Definition: Rtypes.h:359
double Double_t
Definition: RtypesCore.h:55
TGLPlotCamera fCamera
void SetCoordType(EGLCoordType type)
If coord type was changed, plot must reset sections (if any), set fModified.
TGL5DPainter implements "gl5d" option for TTree::Draw.
Definition: TGL5DPainter.h:32
Double_t y[n]
Definition: legend1.C:17
#define gGLManager
Definition: TVirtualGL.h:162
The TH1 histogram class.
Definition: TH1.h:56
static constexpr double s
void SetShowProjection(const char *option, Int_t nbins)
Set show projection.
EGLPlotType
Definition: TGLUtil.h:49
The histogram painter class using OpenGL.
Mother of all ROOT objects.
Definition: TObject.h:37
void SetZLog(Bool_t zLog)
If log changed, sections must be reset, set fModified.
1-Dim function class
Definition: TF1.h:211
Int_t MakeCuts(char *cutsOpt)
Make cuts.
#define gPad
Definition: TVirtualPad.h:285
void ZoomIn()
Zoom in.
Int_t Height() const
Definition: TGLUtil.h:453
void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Execute event.
TList * GetStack() const
Get stack.
const Bool_t kTRUE
Definition: RtypesCore.h:87
void PaintStat(Int_t dostat, TF1 *fit)
Paint statistics.
const char * Data() const
Definition: TString.h:364