Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TGLTH3Composition.cxx
Go to the documentation of this file.
1// @(#)root/gl:$Id$
2// Author: Timur Pocheptsov 07/08/2009
3
4#include <memory>
5#include <stdexcept>
6
7#include "KeySymbols.h"
8#include "TVirtualX.h"
9#include "Buttons.h"
10#include "TString.h"
11#include "TError.h"
12#include "TColor.h"
13#include "TROOT.h"
14#include "TMath.h"
15
16#include "TGLTH3Composition.h"
17#include "TGLIncludes.h"
18
19/** \class TGLTH3Composition
20\ingroup opengl
21*/
22
23
24////////////////////////////////////////////////////////////////////////////////
25///I have to define it, since explicit copy ctor was declared.
26
30
31namespace {
32
33void CompareAxes(const TAxis *a1, const TAxis *a2, const TString &axisName);
34
35}
36
37////////////////////////////////////////////////////////////////////////////////
38///Add TH3 into collection. Throw if fHists is not empty
39///but ranges are not equal.
40
42{
43 const TAxis *xa = h->GetXaxis();
44 const TAxis *ya = h->GetYaxis();
45 const TAxis *za = h->GetZaxis();
46
47 if (fHists.empty()) {
48 //This is the first hist in a composition,
49 //take its ranges and reset axes for the composition.
50 fXaxis.Set(h->GetNbinsX(), xa->GetBinLowEdge(xa->GetFirst()), xa->GetBinUpEdge(xa->GetLast()));
51 fYaxis.Set(h->GetNbinsY(), ya->GetBinLowEdge(ya->GetFirst()), ya->GetBinUpEdge(ya->GetLast()));
52 fZaxis.Set(h->GetNbinsZ(), za->GetBinLowEdge(za->GetFirst()), za->GetBinUpEdge(za->GetLast()));
53 } else {
54 CompareAxes(xa, GetXaxis(), "X");
55 CompareAxes(ya, GetYaxis(), "Y");
56 CompareAxes(za, GetZaxis(), "Z");
57 }
58
59 fHists.push_back(TH3Pair_t(h, shape));
60}
61
62////////////////////////////////////////////////////////////////////////////////
63///Check if "this" is under cursor.
64
66{
67 if (!fPainter.get())
68 return 9999;
69
70 return fPainter->DistancetoPrimitive(px, py);
71}
72
73////////////////////////////////////////////////////////////////////////////////
74///Mouse and keyboard events.
75
77{
78 fPainter->ExecuteEvent(event, px, py);
79}
80
81////////////////////////////////////////////////////////////////////////////////
82///I cannot show bin content in a status bar -
83///since there can be several bins in one.
84
85char *TGLTH3Composition::GetObjectInfo(Int_t /*px*/, Int_t /*py*/) const
86{
87 static char message[] = "TH3 composition";
88 return message;
89}
90
91////////////////////////////////////////////////////////////////////////////////
92///Paint a composition of 3d hists.
93
95{
96 if (fHists.empty())
97 return;
98
99 //create a painter.
100 if (!fPainter.get())
101 fPainter = std::make_unique<TGLHistPainter>(this);
102
103 fPainter->Paint("dummy");
104}
105
106/** \class TGLTH3CompositionPainter
107\ingroup opengl
108*/
109
110
111////////////////////////////////////////////////////////////////////////////////
112///Ctor.
113
120
121////////////////////////////////////////////////////////////////////////////////
122///Will be never called from TPad.
123
125{
126 static char message[] = "TH3 composition";
127 return message;
128}
129
130////////////////////////////////////////////////////////////////////////////////
131
133{
134 if (fData->fHists.empty())
135 return kFALSE;
136
137 //Prepare plot painter.
138 //Forget about log scale.
142
143 if (!fCoord->SetRanges(fHist, kFALSE, kTRUE))//kFALSE == drawErrors, kTRUE == zAsBins
144 return kFALSE;
145
147 if (fCamera)
149
150 //Loop on hists.
151 const TH3 *h = fData->fHists[0].first;
152 fMinMaxVal.second = h->GetBinContent(fCoord->GetFirstXBin(),
155 fMinMaxVal.first = fMinMaxVal.second;
156
157 for (UInt_t hNum = 0, lastH = fData->fHists.size(); hNum < lastH; ++hNum) {
158 h = fData->fHists[hNum].first;
159 for (Int_t ir = fCoord->GetFirstXBin(); ir <= fCoord->GetLastXBin(); ++ir) {
160 for (Int_t jr = fCoord->GetFirstYBin(); jr <= fCoord->GetLastYBin(); ++jr) {
161 for (Int_t kr = fCoord->GetFirstZBin(); kr <= fCoord->GetLastZBin(); ++kr) {
162 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, h->GetBinContent(ir, jr, kr));
163 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, h->GetBinContent(ir, jr, kr));
164 }
165 }
166 }
167 }
168
169 if (fCoord->Modified()) {
172 }
173
174 return kTRUE;
175}
176
177////////////////////////////////////////////////////////////////////////////////
178///Move plot or box cut.
179
187
188////////////////////////////////////////////////////////////////////////////////
189/// User's moving mouse cursor, with middle mouse button pressed (for pad).
190/// Calculate 3d shift related to 2d mouse movement.
191
193{
194 if (fSelectedPart >= fSelectionBase) {//Pan camera.
197
200 fCamera->Pan(px, py);
201
204 } else if (fSelectedPart > 0) {
205 //Convert py into bottom-top orientation.
206 //Possibly, move box here
207 py = fCamera->GetHeight() - py;
210
213
214 if (!fHighColor) {
217 }
218
221 }
222
225}
226
227////////////////////////////////////////////////////////////////////////////////
228///No options for composition.
229
231{
232}
233
234////////////////////////////////////////////////////////////////////////////////
235///Switch on/off box cut.
236
238{
239 if (event == kButton1Double && fBoxCut.IsActive()) {
241 if (!gVirtualX->IsCmdThread())
242 gROOT->ProcessLineFast(Form("((TGLPlotPainter *)0x%zx)->Paint()", (size_t)this));
243 else
244 Paint();
245 } else if (event == kKeyPress && (py == kKey_c || py == kKey_C)) {
246 if (fHighColor)
247 Info("ProcessEvent", "Switch to true color mode to use box cut");
248 else {
251 }
252 }
253}
254
255////////////////////////////////////////////////////////////////////////////////
256/// Initialize some gl state variables.
257
268
269////////////////////////////////////////////////////////////////////////////////
270///Return back some gl state variables.
271
280
281////////////////////////////////////////////////////////////////////////////////
282///Draw composition of TH3s.
283
285{
286 //Shift plot to point of origin.
287 const Rgl::PlotTranslation trGuard(this);
288
290
291 if (!fSelectionPass) {
293 glPolygonOffset(1.f, 1.f);
294 } else
295 return;
296
297 //Using front point, find the correct order to draw boxes from
298 //back to front/from bottom to top (it's important only for semi-transparent boxes).
301 const Int_t nX = fCoord->GetNXBins();
303 const Int_t nY = fCoord->GetNYBins();
304 Int_t krInit = fCoord->GetFirstZBin(), kInit = 0;
305 const Int_t nZ = fCoord->GetNZBins();
306
307 const Int_t addI = frontPoint == 2 || frontPoint == 1 ? 1 : (iInit = nX - 1, irInit = fCoord->GetLastXBin(), -1);
308 const Int_t addJ = frontPoint == 2 || frontPoint == 3 ? 1 : (jInit = nY - 1, jrInit = fCoord->GetLastYBin(), -1);
309 const Int_t addK = fBackBox.Get2DBox()[frontPoint + 4].Y() < fBackBox.Get2DBox()[frontPoint].Y() ? 1
310 : (kInit = nZ - 1, krInit = fCoord->GetLastZBin(),-1);
311 const Double_t xScale = fCoord->GetXScale();
312 const Double_t yScale = fCoord->GetYScale();
313 const Double_t zScale = fCoord->GetZScale();
314 const TAxis *xA = fXAxis;
315 const TAxis *yA = fYAxis;
316 const TAxis *zA = fZAxis;
317
319 if(!maxContent)//bad, find better way to check zero.
320 maxContent = 1.;
321
322 for (UInt_t hNum = 0; hNum < fData->fHists.size(); ++hNum) {
323 const TH3 *h = fData->fHists[hNum].first;
324 const TGLTH3Composition::ETH3BinShape shape = fData->fHists[hNum].second;
325 SetColor(h->GetFillColor());
326
327 for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
328 for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
329 for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
330 const Double_t binContent = h->GetBinContent(ir, jr, kr);
332 if (!w)
333 continue;
334
335 const Double_t xMin = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 - w * xA->GetBinWidth(ir) / 2);
336 const Double_t xMax = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 + w * xA->GetBinWidth(ir) / 2);
337 const Double_t yMin = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 - w * yA->GetBinWidth(jr) / 2);
338 const Double_t yMax = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 + w * yA->GetBinWidth(jr) / 2);
339 const Double_t zMin = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 - w * zA->GetBinWidth(kr) / 2);
340 const Double_t zMax = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 + w * zA->GetBinWidth(kr) / 2);
341
343 continue;
344
345 if (shape == TGLTH3Composition::kSphere)
347 else
349 }
350 }
351 }
352 }
353
354 if (fBoxCut.IsActive())
356
358 const TGLDisableGuard lightGuard(GL_LIGHTING);//[2 - 2]
359 glColor4d(0., 0., 0., 0.25);
361
362 const TGLEnableGuard blendGuard(GL_BLEND);//[4-4] + 1]
366
367 for (UInt_t hNum = 0; hNum < fData->fHists.size(); ++hNum) {
369 continue;//No outlines for spherical bins.
370
371 const TH3 *h = fData->fHists[hNum].first;
372
373 for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
374 for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
375 for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
376 const Double_t w = TMath::Abs(h->GetBinContent(ir, jr, kr)) / maxContent;
377 if (!w)
378 continue;
379
380 const Double_t xMin = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 - w * xA->GetBinWidth(ir) / 2);
381 const Double_t xMax = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 + w * xA->GetBinWidth(ir) / 2);
382 const Double_t yMin = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 - w * yA->GetBinWidth(jr) / 2);
383 const Double_t yMax = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 + w * yA->GetBinWidth(jr) / 2);
384 const Double_t zMin = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 - w * zA->GetBinWidth(kr) / 2);
385 const Double_t zMax = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 + w * zA->GetBinWidth(kr) / 2);
386
388 continue;
389
391 }
392 }
393 }
394 }
395
397}
398
399////////////////////////////////////////////////////////////////////////////////
400///Set material.
401
403{
404 Float_t diffColor[] = {0.8f, 0.8f, 0.8f, 0.05f};
405
406 if (color != kWhite)
407 if (const TColor *c = gROOT->GetColor(color))
408 c->GetRGB(diffColor[0], diffColor[1], diffColor[2]);
409
411 const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
414}
415
416namespace {
417
418////////////////////////////////////////////////////////////////////////////////
419
420void AxisError(const TString & errorMsg)
421{
422 Error("TGLTH3Composition::AddTH3", "%s", errorMsg.Data());
423 throw std::runtime_error(errorMsg.Data());
424}
425
426////////////////////////////////////////////////////////////////////////////////
427///Check number of bins.
428
429void CompareAxes(const TAxis *a1, const TAxis *a2, const TString &axisName)
430{
431 if (a1->GetNbins() != a2->GetNbins())
432 AxisError("New hist has different number of bins along " + axisName);
433
434 //Check bin ranges.
435 const Int_t firstBin1 = a1->GetFirst(), lastBin1 = a1->GetLast();
436 const Int_t firstBin2 = a2->GetFirst(), lastBin2 = a2->GetLast();
437
438 if (firstBin1 != firstBin2)
439 AxisError("New hist has different first bin along " + axisName);
440
441 if (lastBin1 != lastBin2)
442 AxisError("New hist has different last bin along " + axisName);
443
444 const Double_t eps = 1e-7;//?????:((((
445 //Check axes ranges.
446 if (TMath::Abs(a1->GetBinLowEdge(firstBin1) - a2->GetBinLowEdge(firstBin2)) > eps)
447 AxisError("New hist has different low edge along " + axisName);
448 if (TMath::Abs(a1->GetBinUpEdge(lastBin1) - a2->GetBinUpEdge(lastBin2)) > eps)
449 AxisError("New hist has different low edge along " + axisName);
450}
451
452}
@ kKeyPress
Definition Buttons.h:20
@ kButton1Double
Definition Buttons.h:24
@ kKey_C
Definition KeySymbols.h:128
@ kKey_c
Definition KeySymbols.h:160
#define c(i)
Definition RSha256.hxx:101
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
@ kWhite
Definition Rtypes.h:66
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
#define gROOT
Definition TROOT.h:411
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2495
#define gVirtualX
Definition TVirtualX.h:337
Class to manage histogram axis.
Definition TAxis.h:32
virtual void Set(Int_t nbins, Double_t xmin, Double_t xmax)
Initialize axis with fix bins.
Definition TAxis.cxx:783
The color creation and management class.
Definition TColor.h:22
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1926
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
void SetPlotBox(const Rgl::Range_t &xRange, const Rgl::Range_t &yRange, const Rgl::Range_t &zRange)
Set up a frame box.
const TGLVertex3 * Get3DBox() const
Get 3D box.
const TGLVertex3 * Get2DBox() const
Get 2D box.
void DrawBox(Int_t selectedPart, Bool_t selectionPass, const std::vector< Double_t > &zLevels, Bool_t highColor) const
Draw back box for a plot.
Int_t GetFrontPoint() const
The nearest point.
Camera for TGLPlotPainter and sub-classes.
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,...
std::vector< Double_t > fZLevels
void RestoreModelviewMatrix() const
TGLPlotCoordinates * fCoord
void Paint() override
Draw lego/surf/whatever you can.
TGLPlotBox fBackBox
void SaveProjectionMatrix() const
void SaveModelviewMatrix() const
TGLPlotCamera * fCamera
void RestoreProjectionMatrix() const
void ProcessEvent(Int_t event, Int_t px, Int_t py) override
Switch on/off box cut.
void StartPan(Int_t px, Int_t py) override
Move plot or box cut.
void DeInitGL() const override
Return back some gl state variables.
char * GetPlotInfo(Int_t px, Int_t py) override
Will be never called from TPad.
void Pan(Int_t px, Int_t py) override
User's moving mouse cursor, with middle mouse button pressed (for pad).
TGLTH3Composition * fData
void AddOption(const TString &option) override
No options for composition.
std::pair< Double_t, Double_t > fMinMaxVal
void InitGL() const override
Initialize some gl state variables.
void SetColor(Int_t color) const
Set material.
void DrawPlot() const override
Draw composition of TH3s.
TGLTH3CompositionPainter(TGLTH3Composition *data, TGLPlotCamera *camera, TGLPlotCoordinates *coord)
Ctor.
void AddTH3(const TH3 *hist, ETH3BinShape shape=kBox)
Add TH3 into collection.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Check if "this" is under cursor.
std::vector< TH3Pair_t > fHists
void Paint(Option_t *option) override
Paint a composition of 3d hists.
TGLTH3Composition()
I have to define it, since explicit copy ctor was declared.
char * GetObjectInfo(Int_t px, Int_t py) const override
I cannot show bin content in a status bar - since there can be several bins in one.
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Mouse and keyboard events.
std::pair< const TH3 *, ETH3BinShape > TH3Pair_t
std::unique_ptr< TGLHistPainter > fPainter
TAxis * GetZaxis()
Definition TH1.h:574
TAxis * GetXaxis()
Definition TH1.h:572
TAxis * GetYaxis()
Definition TH1.h:573
TAxis fZaxis
Z axis descriptor.
Definition TH1.h:153
TAxis fXaxis
X axis descriptor.
Definition TH1.h:151
TAxis fYaxis
Y axis descriptor.
Definition TH1.h:152
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:40
SCoord_t fY
Definition TPoint.h:36
SCoord_t fX
Definition TPoint.h:35
Basic string class.
Definition TString.h:138
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
void DrawSphere(TGLQuadric *quadric, Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax, Double_t zMin, Double_t zMax)
Cylinder for lego3.
Definition TGLUtil.cxx:3274
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:251
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:199
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:124