Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
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
22
23////////////////////////////////////////////////////////////////////////////////
24/// Constructor.
25///This plot always needs a palette.
26
33
34
35////////////////////////////////////////////////////////////////////////////////
36///Show box info (i, j, k, binContent).
37
39{
40 fPlotInfo = "";
41
42 if (fSelectedPart) {
44 if (fHist->Class())
45 fPlotInfo += fHist->Class()->GetName();
46 fPlotInfo += "::";
47 fPlotInfo += fHist->GetName();
48 } else if (!fHighColor){
49 const Int_t arr2Dsize = fCoord->GetNYBins() * fCoord->GetNZBins();
50 const Int_t binI = (fSelectedPart - fSelectionBase) / arr2Dsize + fCoord->GetFirstXBin();
51 const Int_t binJ = (fSelectedPart - fSelectionBase) % arr2Dsize / fCoord->GetNZBins() + fCoord->GetFirstYBin();
52 const Int_t binK = (fSelectedPart - fSelectionBase) % arr2Dsize % fCoord->GetNZBins() + fCoord->GetFirstZBin();
53
54 fPlotInfo.Form("(binx = %d; biny = %d; binz = %d; binc = %f)", binI, binJ, binK,
55 fHist->GetBinContent(binI, binJ, binK));
56 } else
57 fPlotInfo = "Switch to true color mode to get correct info";
58 }
59
60 return (Char_t *)fPlotInfo.Data();
61}
62
63
64////////////////////////////////////////////////////////////////////////////////
65///Set ranges, find min and max bin content.
66
68{
69 fCoord->SetZLog(kFALSE);
70 fCoord->SetYLog(kFALSE);
71 fCoord->SetXLog(kFALSE);
72
73 if (!fCoord->SetRanges(fHist, kFALSE, kTRUE))//kFALSE == drawErrors, kTRUE == zAsBins
74 return kFALSE;
75
76 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
77 if(fCamera) fCamera->SetViewVolume(fBackBox.Get3DBox());
78
79 fMinMaxVal.second = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin(), fCoord->GetFirstZBin());
80 fMinMaxVal.first = fMinMaxVal.second;
81 //Bad. You can up-date some bin value and get wrong picture.
82 for (Int_t ir = fCoord->GetFirstXBin(); ir <= fCoord->GetLastXBin(); ++ir) {
83 for (Int_t jr = fCoord->GetFirstYBin(); jr <= fCoord->GetLastYBin(); ++jr) {
84 for (Int_t kr = fCoord->GetFirstZBin(); kr <= fCoord->GetLastZBin(); ++kr) {
85 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, fHist->GetBinContent(ir, jr, kr));
86 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, fHist->GetBinContent(ir, jr, kr));
87 }
88 }
89 }
90
91 if (fCoord->Modified()) {
93 fXOZSectionPos = fBackBox.Get3DBox()[0].Y();
94 fYOZSectionPos = fBackBox.Get3DBox()[0].X();
95 fXOYSectionPos = fBackBox.Get3DBox()[0].Z();
96 fCoord->ResetModified();
97 }
98
99 const TList *funcList = fHist->GetListOfFunctions();
100 fTransferFunc = dynamic_cast<TF1*>(funcList->FindObject("TransferFunction"));
101
102 return kTRUE;
103}
104
105
106////////////////////////////////////////////////////////////////////////////////
107/// User clicks right mouse button (in a pad).
108
110{
111 fMousePosition.fX = px;
112 fMousePosition.fY = fCamera->GetHeight() - py;
113 fCamera->StartPan(px, py);
114 fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
115}
116
117
118////////////////////////////////////////////////////////////////////////////////
119/// User's moving mouse cursor, with middle mouse button pressed (for pad).
120/// Calculate 3d shift related to 2d mouse movement.
121
123{
124 // User's moving mouse cursor, with middle mouse button pressed (for pad).
125 // Calculate 3d shift related to 2d mouse movement.
126 if (fSelectedPart >= fSelectionBase) {//Pan camera.
129
130 fCamera->SetCamera();
131 fCamera->Apply(fPadPhi, fPadTheta);
132 fCamera->Pan(px, py);
133
136 } else if (fSelectedPart > 0) {
137 //Convert py into bottom-top orientation.
138 //Possibly, move box here
139 py = fCamera->GetHeight() - py;
142
143 fCamera->SetCamera();
144 fCamera->Apply(fPadPhi, fPadTheta);
145
146
147 if (!fHighColor) {
148 if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis))
149 fBoxCut.MoveBox(px, py, fSelectedPart);
150 else
151 MoveSection(px, py);
152 } else {
153 MoveSection(px, py);
154 }
155
158 }
159
160 fMousePosition.fX = px, fMousePosition.fY = py;
162}
163
164
165////////////////////////////////////////////////////////////////////////////////
166/// "z" draw palette or not.
167
169{
170 option.Index("z") == kNPOS ? fDrawPalette = kFALSE : fDrawPalette = kTRUE;
171
172}
173
174////////////////////////////////////////////////////////////////////////////////
175/// Remove sections, switch on/off box cut.
176
178{
179 if (event == kButton1Double && fBoxCut.IsActive()) {
180 if (fBoxCut.IsActive())
181 fBoxCut.TurnOnOff();
182 if (!gVirtualX->IsCmdThread())
183 gROOT->ProcessLineFast(Form("((TGLPlotPainter *)0x%zx)->Paint()", (size_t)this));
184 else
185 Paint();
186 } else if (event == kKeyPress && (py == kKey_c || py == kKey_C)) {
187 if (fHighColor)
188 Info("ProcessEvent", "Switch to true color mode to use box cut");
189 else {
190 fBoxCut.TurnOnOff();
192 }
193 }
194}
195
196////////////////////////////////////////////////////////////////////////////////
197/// Initialize some gl state variables.
198
200{
201 glEnable(GL_DEPTH_TEST);
202 glEnable(GL_LIGHTING);
203 glEnable(GL_LIGHT0);
204
205 glEnable(GL_CULL_FACE);
206 glCullFace(GL_BACK);
207
208 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
209}
210
211////////////////////////////////////////////////////////////////////////////////
212/// Return back some gl state variables.
213
215{
216 glDisable(GL_DEPTH_TEST);
217 glDisable(GL_LIGHTING);
218 glDisable(GL_LIGHT0);
219 glDisable(GL_CULL_FACE);
220 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
221}
222
223////////////////////////////////////////////////////////////////////////////////
224/// Draw "voxels".
225
227{
228 //Shift plot to point of origin.
229 const Rgl::PlotTranslation trGuard(this);
230
231 if (!fSelectionPass)
233
235
236 TGLDisableGuard depthTest(GL_DEPTH_TEST);
237
238 if (!fSelectionPass) {
239 glEnable(GL_BLEND);//[1
240 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
241 }
242
243 //Using front point, find the correct order to draw boxes from
244 //back to front/from bottom to top (it's important only for semi-transparent boxes).
245 const Int_t frontPoint = fBackBox.GetFrontPoint();
246 Int_t irInit = fCoord->GetFirstXBin(), iInit = 0;
247 const Int_t nX = fCoord->GetNXBins();
248 Int_t jrInit = fCoord->GetFirstYBin(), jInit = 0;
249 const Int_t nY = fCoord->GetNYBins();
250 Int_t krInit = fCoord->GetFirstZBin(), kInit = 0;
251 const Int_t nZ = fCoord->GetNZBins();
252
253 const Int_t addI = frontPoint == 2 || frontPoint == 1 ? 1 : (iInit = nX - 1, irInit = fCoord->GetLastXBin(), -1);
254 const Int_t addJ = frontPoint == 2 || frontPoint == 3 ? 1 : (jInit = nY - 1, jrInit = fCoord->GetLastYBin(), -1);
255 const Int_t addK = fBackBox.Get2DBox()[frontPoint + 4].Y() > fBackBox.Get2DBox()[frontPoint].Y() ? 1
256 : (kInit = nZ - 1, krInit = fCoord->GetLastZBin(),-1);
257 const Double_t xScale = fCoord->GetXScale();
258 const Double_t yScale = fCoord->GetYScale();
259 const Double_t zScale = fCoord->GetZScale();
260 const TAxis *xA = fXAxis;
261 const TAxis *yA = fYAxis;
262 const TAxis *zA = fZAxis;
263
266
267 Double_t maxContent = TMath::Max(TMath::Abs(fMinMaxVal.first), TMath::Abs(fMinMaxVal.second));
268 if(!maxContent)//bad, find better way to check zero.
269 maxContent = 1.;
270
271 Float_t rgba[4] = {};
272
273 Double_t wmin = TMath::Max(fHist->GetMinimum(),0.);
274 Double_t wmax = TMath::Max(TMath::Abs(fHist->GetMaximum()),
275 TMath::Abs(fHist->GetMinimum()));
276 Double_t binContent;
277
278 for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
279 for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
280 for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
281 const Double_t xMin = xScale * xA->GetBinLowEdge(ir);
282 const Double_t xMax = xScale * xA->GetBinUpEdge(ir);
283 const Double_t yMin = yScale * yA->GetBinLowEdge(jr);
284 const Double_t yMax = yScale * yA->GetBinUpEdge(jr);
285 const Double_t zMin = zScale * zA->GetBinLowEdge(kr);
286 const Double_t zMax = zScale * zA->GetBinUpEdge(kr);
287
288 if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
289 continue;
290
291 binContent = fHist->GetBinContent(ir, jr, kr);
292 if (binContent < wmin) continue;
293 if (binContent > wmax) binContent = wmax;
294
295 FindVoxelColor(binContent, rgba);
296
297 if (rgba[3] < 0.01f)
298 continue;
299
300 if (!fSelectionPass)
301 SetVoxelColor(rgba);
302
303 const Int_t binID = fSelectionBase + i * fCoord->GetNZBins() * fCoord->GetNYBins() + j * fCoord->GetNZBins() + k;
304
307 else if(!fHighColor && fSelectedPart == binID)
308 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gOrangeEmission);
309
310 Rgl::DrawBoxFront(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint);
311
312 if (!fSelectionPass && !fHighColor && fSelectedPart == binID)
313 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gNullEmission);
314 }
315 }
316 }
317
318 if (fBoxCut.IsActive())
320
321 if (!fSelectionPass) {
322 if (fDrawPalette)
323 DrawPalette();
324 glDisable(GL_BLEND);//1]
325 }
326}
327
328////////////////////////////////////////////////////////////////////////////////
329/// Noop.
330
334
335////////////////////////////////////////////////////////////////////////////////
336/// Noop.
337
341
342
343////////////////////////////////////////////////////////////////////////////////
344/// Noop.
345
349
350////////////////////////////////////////////////////////////////////////////////
351///Draw. Palette.
352
354{
355 if (!fPalette.GetPaletteSize() || !fCamera)
356 return;
357
358 if (!fHist->TestBit(TH1::kUserContour))
360 else
362
363 glFinish();
364
365 fCamera->SetCamera();
366 fCamera->Apply(fPadPhi, fPadTheta);
367}
368
369////////////////////////////////////////////////////////////////////////////////
370///Draw. Palette. Axis.
371
373{
374 if (fCamera) {
375 gVirtualX->SetDrawMode(TVirtualX::kCopy);//TCanvas by default sets in kInverse
377 }
378}
379
380////////////////////////////////////////////////////////////////////////////////
381///Generate palette.
382
384{
385 if(fMinMaxVal.first == fMinMaxVal.second)
386 return;//must be std::abs(fMinMaxVal.second - fMinMaxVal.first) < ...
387
388 fLevels.clear();
389 UInt_t paletteSize = 0;
390
391 if (fHist->TestBit(TH1::kUserContour)) {
392 if (const UInt_t trySize = fHist->GetContour()) {
393 fLevels.reserve(trySize);
394
395 for (UInt_t i = 0; i < trySize; ++i) {
396 const Double_t level = fHist->GetContourLevel(Int_t(i));
397 if (level <= fMinMaxVal.first || level >= fMinMaxVal.second)
398 continue;
399 fLevels.push_back(level);
400 }
401 //sort levels
402 if (!fLevels.empty()) {
403 std::sort(fLevels.begin(), fLevels.end());
404 fLevels.push_back(fMinMaxVal.second);
405 fLevels.insert(fLevels.begin(), fMinMaxVal.first);
406 fPalette.SetContours(&fLevels);
407 paletteSize = fLevels.size() - 1;
408 }
409 }
410
411 if (!paletteSize)
412 fHist->ResetBit(TH1::kUserContour);
413 }
414
415 if (!paletteSize && !(paletteSize = gStyle->GetNumberContours()))
416 paletteSize = 20;
417
418 fPalette.GeneratePalette(paletteSize, fMinMaxVal);
419}
420
421////////////////////////////////////////////////////////////////////////////////
422/// Find box color.
423
425{
426 const UChar_t * tc = fPalette.GetColour(binContent);
427 rgba[3] = 0.06f; //Just a constant transparency.
428
429
430 if (fTransferFunc) {
431 rgba[3] = fTransferFunc->Eval(binContent);
432 }
433
434 rgba[0] = tc[0] / 255.f;
435 rgba[1] = tc[1] / 255.f;
436 rgba[2] = tc[2] / 255.f;
437}
438
439
440////////////////////////////////////////////////////////////////////////////////
441/// Set box color.
442
443void TGLVoxelPainter::SetVoxelColor(const Float_t *diffColor)const
444{
445 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffColor);
446 const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
447 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
448 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
449}
@ kKeyPress
Definition Buttons.h:20
@ kButton1Double
Definition Buttons.h:24
@ kKey_C
Definition KeySymbols.h:128
@ kKey_c
Definition KeySymbols.h:160
int Int_t
Signed integer 4 bytes (int).
Definition RtypesCore.h:59
unsigned char UChar_t
Unsigned Character 1 byte (unsigned char).
Definition RtypesCore.h:52
char Char_t
Character 1 byte (char).
Definition RtypesCore.h:51
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int).
Definition RtypesCore.h:60
bool Bool_t
Boolean (0=false, 1=true) (bool).
Definition RtypesCore.h:77
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:131
float Float_t
Float 4 bytes (float).
Definition RtypesCore.h:71
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
#define gROOT
Definition TROOT.h:417
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2496
externTStyle * gStyle
Definition TStyle.h:442
#define gVirtualX
Definition TVirtualX.h:375
Class to manage histogram axis.
Definition TAxis.h:32
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:522
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
Definition TF1.h:182
Camera for TGLPlotPainter and sub-classes.
Helper class for plot-painters holding information about axis ranges, numbers of bins and flags if ce...
TGLPlotPainter(TH1 *hist, TGLPlotCamera *camera, TGLPlotCoordinates *coord, Bool_t xoySelectable, Bool_t xozSelectable, Bool_t yozSelectable)
TGLPlotPainter's ctor.
std::vector< Double_t > fZLevels
Double_t fXOYSectionPos
void RestoreModelviewMatrix() const
Double_t fXOZSectionPos
TGLPlotCoordinates * fCoord
void Paint() override
Draw lego/surf/whatever you can.
TGLPlotBox fBackBox
void SaveProjectionMatrix() const
void SaveModelviewMatrix() const
void MoveSection(Int_t px, Int_t py)
Create dynamic profile using selected plane.
TGLPlotCamera * fCamera
void RestoreProjectionMatrix() const
Double_t fYOZSectionPos
void DrawPlot() const override
Draw "voxels".
void SetVoxelColor(const Float_t *rgba) const
Set box color.
void DrawSectionXOZ() const override
Noop.
void ProcessEvent(Int_t event, Int_t px, Int_t py) override
Remove sections, switch on/off box cut.
void Pan(Int_t px, Int_t py) override
User's moving mouse cursor, with middle mouse button pressed (for pad).
void AddOption(const TString &stringOption) override
"z" draw palette or not.
Rgl::Range_t fMinMaxVal
void PreparePalette() const
Generate palette.
void DrawPalette() const
Draw. Palette.
TGLVoxelPainter(const TGLVoxelPainter &)=delete
void DeInitGL() const override
Return back some gl state variables.
void InitGL() const override
Initialize some gl state variables.
void DrawSectionYOZ() const override
Noop.
char * GetPlotInfo(Int_t px, Int_t py) override
Show box info (i, j, k, binContent).
Bool_t InitGeometry() override
Set ranges, find min and max bin content.
TGLLevelPalette fPalette
void DrawPaletteAxis() const override
Draw. Palette. Axis.
void FindVoxelColor(Double_t binContent, Float_t *rgba) const
Find box color.
void StartPan(Int_t px, Int_t py) override
User clicks right mouse button (in a pad).
std::vector< Double_t > fLevels
void DrawSectionXOY() const override
Noop.
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
@ kUserContour
User specified contour levels.
Definition TH1.h:404
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
Basic string class.
Definition TString.h:138
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:660
const Float_t gNullEmission[]
Definition TGLUtil.cxx:2846
void ObjectIDToColor(Int_t objectID, Bool_t highColor)
Object id encoded as rgb triplet.
Definition TGLUtil.cxx:2890
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:3006
const Float_t gOrangeEmission[]
Definition TGLUtil.cxx:2843
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122