Logo ROOT  
Reference Guide
TGLVoxelPainter.cxx
Go to the documentation of this file.
1#include <algorithm>
2
3#include "KeySymbols.h"
4#include "TVirtualX.h"
5#include "Buttons.h"
6#include "TString.h"
7#include "TROOT.h"
8#include "TList.h"
9#include "TStyle.h"
10#include "TH3.h"
11#include "TF1.h"
12
13#include "TGLVoxelPainter.h"
14#include "TGLPlotCamera.h"
15#include "TGLIncludes.h"
16
17/** \class TGLVoxelPainter
18\ingroup opengl
19Paint TH3 histograms as "voxels" - colored boxes, transparent if transfer function was specified.
20*/
21
23
24////////////////////////////////////////////////////////////////////////////////
25/// Constructor.
26///This plot always needs a palette.
27
29 : TGLPlotPainter(hist, cam, coord, kFALSE, kFALSE, kFALSE),
30 fTransferFunc(0)
31{
33}
34
35
36////////////////////////////////////////////////////////////////////////////////
37///Show box info (i, j, k, binContent).
38
40{
41 fPlotInfo = "";
42
43 if (fSelectedPart) {
45 if (fHist->Class())
46 fPlotInfo += fHist->Class()->GetName();
47 fPlotInfo += "::";
49 } else if (!fHighColor){
50 const Int_t arr2Dsize = fCoord->GetNYBins() * fCoord->GetNZBins();
51 const Int_t binI = (fSelectedPart - fSelectionBase) / arr2Dsize + fCoord->GetFirstXBin();
52 const Int_t binJ = (fSelectedPart - fSelectionBase) % arr2Dsize / fCoord->GetNZBins() + fCoord->GetFirstYBin();
53 const Int_t binK = (fSelectedPart - fSelectionBase) % arr2Dsize % fCoord->GetNZBins() + fCoord->GetFirstZBin();
54
55 fPlotInfo.Form("(binx = %d; biny = %d; binz = %d; binc = %f)", binI, binJ, binK,
56 fHist->GetBinContent(binI, binJ, binK));
57 } else
58 fPlotInfo = "Switch to true color mode to get correct info";
59 }
60
61 return (Char_t *)fPlotInfo.Data();
62}
63
64
65////////////////////////////////////////////////////////////////////////////////
66///Set ranges, find min and max bin content.
67
69{
73
74 if (!fCoord->SetRanges(fHist, kFALSE, kTRUE))//kFALSE == drawErrors, kTRUE == zAsBins
75 return kFALSE;
76
79
81 fMinMaxVal.first = fMinMaxVal.second;
82 //Bad. You can up-date some bin value and get wrong picture.
83 for (Int_t ir = fCoord->GetFirstXBin(); ir <= fCoord->GetLastXBin(); ++ir) {
84 for (Int_t jr = fCoord->GetFirstYBin(); jr <= fCoord->GetLastYBin(); ++jr) {
85 for (Int_t kr = fCoord->GetFirstZBin(); kr <= fCoord->GetLastZBin(); ++kr) {
86 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, fHist->GetBinContent(ir, jr, kr));
87 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, fHist->GetBinContent(ir, jr, kr));
88 }
89 }
90 }
91
92 if (fCoord->Modified()) {
98 }
99
100 const TList *funcList = fHist->GetListOfFunctions();
101 fTransferFunc = dynamic_cast<TF1*>(funcList->FindObject("TransferFunction"));
102
103 return kTRUE;
104}
105
106
107////////////////////////////////////////////////////////////////////////////////
108/// User clicks right mouse button (in a pad).
109
111{
112 fMousePosition.fX = px;
114 fCamera->StartPan(px, py);
116}
117
118
119////////////////////////////////////////////////////////////////////////////////
120/// User's moving mouse cursor, with middle mouse button pressed (for pad).
121/// Calculate 3d shift related to 2d mouse movement.
122
124{
125 // User's moving mouse cursor, with middle mouse button pressed (for pad).
126 // Calculate 3d shift related to 2d mouse movement.
127 if (fSelectedPart >= fSelectionBase) {//Pan camera.
130
133 fCamera->Pan(px, py);
134
137 } else if (fSelectedPart > 0) {
138 //Convert py into bottom-top orientation.
139 //Possibly, move box here
140 py = fCamera->GetHeight() - py;
143
146
147
148 if (!fHighColor) {
151 else
152 MoveSection(px, py);
153 } else {
154 MoveSection(px, py);
155 }
156
159 }
160
163}
164
165
166////////////////////////////////////////////////////////////////////////////////
167/// "z" draw palette or not.
168
170{
171 option.Index("z") == kNPOS ? fDrawPalette = kFALSE : fDrawPalette = kTRUE;
172
173}
174
175////////////////////////////////////////////////////////////////////////////////
176/// Remove sections, switch on/off box cut.
177
179{
180 if (event == kButton1Double && fBoxCut.IsActive()) {
181 if (fBoxCut.IsActive())
183 if (!gVirtualX->IsCmdThread())
184 gROOT->ProcessLineFast(Form("((TGLPlotPainter *)0x%zx)->Paint()", (size_t)this));
185 else
186 Paint();
187 } else if (event == kKeyPress && (py == kKey_c || py == kKey_C)) {
188 if (fHighColor)
189 Info("ProcessEvent", "Switch to true color mode to use box cut");
190 else {
193 }
194 }
195}
196
197////////////////////////////////////////////////////////////////////////////////
198/// Initialize some gl state variables.
199
201{
202 glEnable(GL_DEPTH_TEST);
203 glEnable(GL_LIGHTING);
204 glEnable(GL_LIGHT0);
205
206 glEnable(GL_CULL_FACE);
207 glCullFace(GL_BACK);
208
209 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
210}
211
212////////////////////////////////////////////////////////////////////////////////
213/// Return back some gl state variables.
214
216{
217 glDisable(GL_DEPTH_TEST);
218 glDisable(GL_LIGHTING);
219 glDisable(GL_LIGHT0);
220 glDisable(GL_CULL_FACE);
221 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
222}
223
224////////////////////////////////////////////////////////////////////////////////
225/// Draw "voxels".
226
228{
229 //Shift plot to point of origin.
230 const Rgl::PlotTranslation trGuard(this);
231
232 if (!fSelectionPass)
234
236
237 TGLDisableGuard depthTest(GL_DEPTH_TEST);
238
239 if (!fSelectionPass) {
240 glEnable(GL_BLEND);//[1
241 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
242 }
243
244 //Using front point, find the correct order to draw boxes from
245 //back to front/from bottom to top (it's important only for semi-transparent boxes).
246 const Int_t frontPoint = fBackBox.GetFrontPoint();
247 Int_t irInit = fCoord->GetFirstXBin(), iInit = 0;
248 const Int_t nX = fCoord->GetNXBins();
249 Int_t jrInit = fCoord->GetFirstYBin(), jInit = 0;
250 const Int_t nY = fCoord->GetNYBins();
251 Int_t krInit = fCoord->GetFirstZBin(), kInit = 0;
252 const Int_t nZ = fCoord->GetNZBins();
253
254 const Int_t addI = frontPoint == 2 || frontPoint == 1 ? 1 : (iInit = nX - 1, irInit = fCoord->GetLastXBin(), -1);
255 const Int_t addJ = frontPoint == 2 || frontPoint == 3 ? 1 : (jInit = nY - 1, jrInit = fCoord->GetLastYBin(), -1);
256 const Int_t addK = fBackBox.Get2DBox()[frontPoint + 4].Y() > fBackBox.Get2DBox()[frontPoint].Y() ? 1
257 : (kInit = nZ - 1, krInit = fCoord->GetLastZBin(),-1);
258 const Double_t xScale = fCoord->GetXScale();
259 const Double_t yScale = fCoord->GetYScale();
260 const Double_t zScale = fCoord->GetZScale();
261 const TAxis *xA = fXAxis;
262 const TAxis *yA = fYAxis;
263 const TAxis *zA = fZAxis;
264
267
268 Double_t maxContent = TMath::Max(TMath::Abs(fMinMaxVal.first), TMath::Abs(fMinMaxVal.second));
269 if(!maxContent)//bad, find better way to check zero.
270 maxContent = 1.;
271
272 Float_t rgba[4] = {};
273
274 Double_t wmin = TMath::Max(fHist->GetMinimum(),0.);
277 Double_t binContent;
278
279 for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
280 for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
281 for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
282 const Double_t xMin = xScale * xA->GetBinLowEdge(ir);
283 const Double_t xMax = xScale * xA->GetBinUpEdge(ir);
284 const Double_t yMin = yScale * yA->GetBinLowEdge(jr);
285 const Double_t yMax = yScale * yA->GetBinUpEdge(jr);
286 const Double_t zMin = zScale * zA->GetBinLowEdge(kr);
287 const Double_t zMax = zScale * zA->GetBinUpEdge(kr);
288
289 if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
290 continue;
291
292 binContent = fHist->GetBinContent(ir, jr, kr);
293 if (binContent < wmin) continue;
294 if (binContent > wmax) binContent = wmax;
295
296 FindVoxelColor(binContent, rgba);
297
298 if (rgba[3] < 0.01f)
299 continue;
300
301 if (!fSelectionPass)
302 SetVoxelColor(rgba);
303
304 const Int_t binID = fSelectionBase + i * fCoord->GetNZBins() * fCoord->GetNYBins() + j * fCoord->GetNZBins() + k;
305
308 else if(!fHighColor && fSelectedPart == binID)
309 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gOrangeEmission);
310
311 Rgl::DrawBoxFront(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint);
312
313 if (!fSelectionPass && !fHighColor && fSelectedPart == binID)
314 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gNullEmission);
315 }
316 }
317 }
318
319 if (fBoxCut.IsActive())
321
322 if (!fSelectionPass) {
323 if (fDrawPalette)
324 DrawPalette();
325 glDisable(GL_BLEND);//1]
326 }
327}
328
329////////////////////////////////////////////////////////////////////////////////
330/// Noop.
331
333{
334}
335
336////////////////////////////////////////////////////////////////////////////////
337/// Noop.
338
340{
341}
342
343
344////////////////////////////////////////////////////////////////////////////////
345/// Noop.
346
348{
349}
350
351////////////////////////////////////////////////////////////////////////////////
352///Draw. Palette.
353
355{
357 return;
358
361 else
363
364 glFinish();
365
368}
369
370////////////////////////////////////////////////////////////////////////////////
371///Draw. Palette. Axis.
372
374{
375 if (fCamera) {
376 gVirtualX->SetDrawMode(TVirtualX::kCopy);//TCanvas by default sets in kInverse
378 }
379}
380
381////////////////////////////////////////////////////////////////////////////////
382///Generate palette.
383
385{
386 if(fMinMaxVal.first == fMinMaxVal.second)
387 return;//must be std::abs(fMinMaxVal.second - fMinMaxVal.first) < ...
388
389 fLevels.clear();
390 UInt_t paletteSize = 0;
391
393 if (const UInt_t trySize = fHist->GetContour()) {
394 fLevels.reserve(trySize);
395
396 for (UInt_t i = 0; i < trySize; ++i) {
397 const Double_t level = fHist->GetContourLevel(Int_t(i));
398 if (level <= fMinMaxVal.first || level >= fMinMaxVal.second)
399 continue;
400 fLevels.push_back(level);
401 }
402 //sort levels
403 if (fLevels.size()) {
404 std::sort(fLevels.begin(), fLevels.end());
405 fLevels.push_back(fMinMaxVal.second);
406 fLevels.insert(fLevels.begin(), fMinMaxVal.first);
408 paletteSize = fLevels.size() - 1;
409 }
410 }
411
412 if (!paletteSize)
414 }
415
416 if (!paletteSize && !(paletteSize = gStyle->GetNumberContours()))
417 paletteSize = 20;
418
419 fPalette.GeneratePalette(paletteSize, fMinMaxVal);
420}
421
422////////////////////////////////////////////////////////////////////////////////
423/// Find box color.
424
426{
427 const UChar_t * tc = fPalette.GetColour(binContent);
428 rgba[3] = 0.06f; //Just a constant transparency.
429
430
431 if (fTransferFunc) {
432 rgba[3] = fTransferFunc->Eval(binContent);
433 }
434
435 rgba[0] = tc[0] / 255.f;
436 rgba[1] = tc[1] / 255.f;
437 rgba[2] = tc[2] / 255.f;
438}
439
440
441////////////////////////////////////////////////////////////////////////////////
442/// Set box color.
443
444void TGLVoxelPainter::SetVoxelColor(const Float_t *diffColor)const
445{
446 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffColor);
447 const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
448 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
449 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
450}
@ kKeyPress
Definition: Buttons.h:20
@ kButton1Double
Definition: Buttons.h:24
#define GL_TRUE
Definition: GL_glu.h:262
#define GL_FALSE
Definition: GL_glu.h:261
@ kKey_C
Definition: KeySymbols.h:128
@ kKey_c
Definition: KeySymbols.h:160
const Ssiz_t kNPOS
Definition: RtypesCore.h:124
int Int_t
Definition: RtypesCore.h:45
unsigned char UChar_t
Definition: RtypesCore.h:38
char Char_t
Definition: RtypesCore.h:33
unsigned int UInt_t
Definition: RtypesCore.h:46
const Bool_t kFALSE
Definition: RtypesCore.h:101
bool Bool_t
Definition: RtypesCore.h:63
double Double_t
Definition: RtypesCore.h:59
float Float_t
Definition: RtypesCore.h:57
const Bool_t kTRUE
Definition: RtypesCore.h:100
#define ClassImp(name)
Definition: Rtypes.h:364
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition: TError.cxx:220
#define gROOT
Definition: TROOT.h:404
char * Form(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition: TStyle.h:413
#define gVirtualX
Definition: TVirtualX.h:338
Class to manage histogram axis.
Definition: TAxis.h:30
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition: TAxis.cxx:518
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition: TAxis.cxx:528
1-Dim function class
Definition: TF1.h:213
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition: TF1.cxx:1440
void MoveBox(Int_t px, Int_t py, Int_t axisID)
Move box cut along selected direction.
Bool_t IsInCut(Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax, Double_t zMin, Double_t zMax) const
Check, if box defined by xmin/xmax etc. is in cut.
void DrawBox(Bool_t selectionPass, Int_t selected) const
Draw cut as a semi-transparent box.
void TurnOnOff()
Turn the box cut on/off.
void StartMovement(Int_t px, Int_t py)
Start cut's movement.
Bool_t IsActive() const
const UChar_t * GetColour(Double_t z) const
Get color.
Definition: TGLUtil.cxx:4291
Int_t GetPaletteSize() const
Get. Palette. Size.
Definition: TGLUtil.cxx:4254
void SetContours(const std::vector< Double_t > *contours)
Clear :)
Definition: TGLUtil.cxx:4218
Bool_t GeneratePalette(UInt_t paletteSize, const Rgl::Range_t &zRange, Bool_t checkSize=kTRUE)
Try to find colors for palette.
Definition: TGLUtil.cxx:4161
void SetPlotBox(const Rgl::Range_t &xRange, const Rgl::Range_t &yRange, const Rgl::Range_t &zRange)
Set up a frame box.
Definition: TGLPlotBox.cxx:198
const TGLVertex3 * Get3DBox() const
Get 3D box.
Definition: TGLPlotBox.cxx:303
const TGLVertex3 * Get2DBox() const
Get 2D box.
Definition: TGLPlotBox.cxx:312
void DrawBox(Int_t selectedPart, Bool_t selectionPass, const std::vector< Double_t > &zLevels, Bool_t highColor) const
Draw back box for a plot.
Definition: TGLPlotBox.cxx:184
Int_t GetFrontPoint() const
The nearest point.
Definition: TGLPlotBox.cxx:294
Camera for TGLPlotPainter and sub-classes.
Definition: TGLPlotCamera.h:22
void StartPan(Int_t px, Int_t py)
User clicks somewhere (px, py).
void Apply(Double_t phi, Double_t theta) const
Applies rotations and translations before drawing.
void SetCamera() const
Viewport and projection.
void Pan(Int_t px, Int_t py)
Pan camera.
Int_t GetHeight() const
viewport[3]
void SetViewVolume(const TGLVertex3 *box)
'box' is the TGLPlotPainter's back box's coordinates.
Helper class for plot-painters holding information about axis ranges, numbers of bins and flags if ce...
void SetXLog(Bool_t xLog)
If log changed, sections must be reset, set fModified.
Bool_t SetRanges(const TH1 *hist, Bool_t errors=kFALSE, Bool_t zBins=kFALSE)
Set bin ranges, ranges.
Double_t GetYScale() const
const Rgl::Range_t & GetXRangeScaled() const
Scaled range.
Int_t GetFirstXBin() const
Int_t GetFirstYBin() const
const Rgl::Range_t & GetYRangeScaled() const
Scaled range.
void ResetModified()
Reset modified.
Bool_t Modified() const
Modified.
Double_t GetXScale() const
Double_t GetZScale() const
Int_t GetLastZBin() const
Int_t GetNXBins() const
Number of X bins.
Int_t GetFirstZBin() const
const Rgl::Range_t & GetZRangeScaled() const
Scaled range.
void SetZLog(Bool_t zLog)
If log changed, sections must be reset, set fModified.
void SetYLog(Bool_t yLog)
If log changed, sections must be reset, set fModified.
Int_t GetLastYBin() const
Int_t GetNYBins() const
Number of Y bins.
Int_t GetLastXBin() const
Int_t GetNZBins() const
Number of Z bins.
Base class for plot-painters that provide GL rendering of various 2D and 3D histograms,...
Double_t fPadTheta
std::vector< Double_t > fZLevels
Double_t fXOYSectionPos
void RestoreModelviewMatrix() const
Double_t fXOZSectionPos
TGLBoxCut fBoxCut
virtual void Paint()
Draw lego/surf/whatever you can.
TGLPlotCoordinates * fCoord
TGLPlotBox fBackBox
void SaveProjectionMatrix() const
void SaveModelviewMatrix() const
void MoveSection(Int_t px, Int_t py)
Create dynamic profile using selected plane.
Bool_t fUpdateSelection
TGLPlotCamera * fCamera
void RestoreProjectionMatrix() const
Double_t fYOZSectionPos
Double_t X() const
Definition: TGLUtil.h:119
Double_t Z() const
Definition: TGLUtil.h:123
Double_t Y() const
Definition: TGLUtil.h:121
Paint TH3 histograms as "voxels" - colored boxes, transparent if transfer function was specified.
void DrawPaletteAxis() const
Draw. Palette. Axis.
void DeInitGL() const
Return back some gl state variables.
void DrawSectionXOY() const
Noop.
void DrawSectionYOZ() const
Noop.
void SetVoxelColor(const Float_t *rgba) const
Set box color.
void InitGL() const
Initialize some gl state variables.
Rgl::Range_t fMinMaxVal
void PreparePalette() const
Generate palette.
void DrawPalette() const
Draw. Palette.
void AddOption(const TString &stringOption)
"z" draw palette or not.
TGLVoxelPainter(const TGLVoxelPainter &)=delete
void DrawSectionXOZ() const
Noop.
void ProcessEvent(Int_t event, Int_t px, Int_t py)
Remove sections, switch on/off box cut.
void Pan(Int_t px, Int_t py)
User's moving mouse cursor, with middle mouse button pressed (for pad).
Bool_t InitGeometry()
Set ranges, find min and max bin content.
TGLLevelPalette fPalette
void DrawPlot() const
Draw "voxels".
void FindVoxelColor(Double_t binContent, Float_t *rgba) const
Find box color.
void StartPan(Int_t px, Int_t py)
User clicks right mouse button (in a pad).
char * GetPlotInfo(Int_t px, Int_t py)
Show box info (i, j, k, binContent).
std::vector< Double_t > fLevels
TH1 is the base class of all histogram classes in ROOT.
Definition: TH1.h:58
@ kUserContour
User specified contour levels.
Definition: TH1.h:165
virtual Double_t GetMaximum(Double_t maxval=FLT_MAX) const
Return maximum value smaller than maxval of bins in the range, unless the value has been overridden b...
Definition: TH1.cxx:8388
TList * GetListOfFunctions() const
Definition: TH1.h:243
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4994
virtual Double_t GetContourLevel(Int_t level) const
Return value of contour number level.
Definition: TH1.cxx:8273
virtual Double_t GetMinimum(Double_t minval=-FLT_MAX) const
Return minimum value larger than minval of bins in the range, unless the value has been overridden by...
Definition: TH1.cxx:8478
virtual Int_t GetContour(Double_t *levels=0)
Return contour values into array levels if pointer levels is non zero.
Definition: TH1.cxx:8254
A doubly linked list.
Definition: TList.h:44
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:578
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:187
void ResetBit(UInt_t f)
Definition: TObject.h:186
SCoord_t fY
Definition: TPoint.h:36
SCoord_t fX
Definition: TPoint.h:35
Basic string class.
Definition: TString.h:136
const char * Data() const
Definition: TString.h:369
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2314
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:639
Int_t GetNumberContours() const
Definition: TStyle.h:232
const Float_t gNullEmission[]
Definition: TGLUtil.cxx:2847
void ObjectIDToColor(Int_t objectID, Bool_t highColor)
Object id encoded as rgb triplet.
Definition: TGLUtil.cxx:2891
void DrawPalette(const TGLPlotCamera *camera, const TGLLevelPalette &palette)
Draw. Palette.
void DrawPaletteAxis(const TGLPlotCamera *camera, const Range_t &minMax, Bool_t logZ)
void DrawBoxFront(Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax, Double_t zMin, Double_t zMax, Int_t fp)
Draws lego's bar as a 3d box.
Definition: TGLUtil.cxx:3007
const Float_t gOrangeEmission[]
Definition: TGLUtil.cxx:2844
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:208
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:176
Short_t Abs(Short_t d)
Definition: TMathBase.h:120