Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
TGLPlotPainter.cxx
Go to the documentation of this file.
1// @(#)root/gl:$Id$
2// Author: Timur Pocheptsov 14/06/2006
3
4/*************************************************************************
5 * Copyright (C) 1995-2004, 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#include <cstdio>
12
13#include "TVirtualPad.h"
14#include "TVirtualPS.h"
15#include "TGaxis.h"
16#include "TGraph.h"
17#include "TStyle.h"
18#include "TError.h"
19#include "TColor.h"
20#include "TAxis.h"
21#include "TMath.h"
22#include "TList.h"
23#include "TH2Poly.h"
24#include "TH1.h"
25#include "TH3.h"
26#include "TF3.h"
27#include "TROOT.h"
28#include "TVirtualMutex.h"
29
30#include "TGLPlotPainter.h"
31#include "TGLPlotCamera.h"
32#include "TGLIncludes.h"
33#include "TGLAdapter.h"
34#include "TGLOutput.h"
35#include "TGLUtil.h"
36#include "TGL5D.h"
37#include "gl2ps.h"
38
39/** \class TGLPlotPainter
40\ingroup opengl
41Base class for plot-painters that provide GL rendering of various
422D and 3D histograms, functions and parametric surfaces.
43*/
44
45
46////////////////////////////////////////////////////////////////////////////////
47///TGLPlotPainter's ctor.
48
50 Bool_t xoy, Bool_t xoz, Bool_t yoz)
51 : fPadColor(nullptr),
52 fPhysicalShapeColor(nullptr),
53 fPadPhi(45.),
54 fPadTheta(0.),
55 fHist(hist),
56 fXAxis(hist->GetXaxis()),
57 fYAxis(hist->GetYaxis()),
58 fZAxis(hist->GetZaxis()),
59 fCoord(coord),
60 fCamera(camera),
67 fBackBox(xoy, xoz, yoz),
73{
74 if (gPad) {
75 fPadPhi = gPad->GetPhi();
76 fPadTheta = gPad->GetTheta();
77 }
78}
79
80////////////////////////////////////////////////////////////////////////////////
81///TGLPlotPainter's ctor.
82
84 : fPadColor(nullptr),
85 fPhysicalShapeColor(nullptr),
86 fPadPhi(45.),
87 fPadTheta(0.),
88 fHist(nullptr),
89 fXAxis(data->GetXAxis()),
90 fYAxis(data->GetYAxis()),
91 fZAxis(data->GetZAxis()),
92 fCoord(coord),
93 fCamera(camera),
106{
107 if (gPad) {
108 fPadPhi = gPad->GetPhi();
109 fPadTheta = gPad->GetTheta();
110 }
111}
112
113////////////////////////////////////////////////////////////////////////////////
114///TGLPlotPainter's ctor.
115
117 : fPadColor(nullptr),
118 fPhysicalShapeColor(nullptr),
119 fPadPhi(45.),
120 fPadTheta(0.),
121 fHist(nullptr),
122 fXAxis(nullptr),
123 fYAxis(nullptr),
124 fZAxis(nullptr),
125 fCoord(nullptr),
126 fCamera(camera),
129 fSelectedPart(0),
130 fXOZSectionPos(0.),
131 fYOZSectionPos(0.),
132 fXOYSectionPos(0.),
139{
140 if (gPad) {
141 fPadPhi = gPad->GetPhi();
142 fPadTheta = gPad->GetTheta();
143 }
144}
145
146////////////////////////////////////////////////////////////////////////////////
147///Draw lego/surf/whatever you can.
148
150{
152
155
156 int vp[4] = {};
157 glGetIntegerv(GL_VIEWPORT, vp);
158
159 //GL pad painter does not use depth test,
160 //so, switch it on now.
161 glDepthMask(GL_TRUE);//[0
162 //
163 InitGL();
164 //Save material/light properties in a stack.
165 glPushAttrib(GL_LIGHTING_BIT);
166
167 //Save projection and modelview matrix, used by glpad.
170
171 //glOrtho etc.
172 fCamera->SetCamera();
173 //
174 glClear(GL_DEPTH_BUFFER_BIT);
175 //Set light.
176 const Float_t pos[] = {0.f, 0.f, 0.f, 1.f};
177 glLightfv(GL_LIGHT0, GL_POSITION, pos);
178 //Set transformation - shift and rotate the scene.
179 fCamera->Apply(fPadPhi, fPadTheta);
180 fBackBox.FindFrontPoint();
181
182 if (gVirtualPS)
183 PrintPlot();
184
185 DrawPlot();
186 //Restore material properties from stack.
187 glPopAttrib();
188 //
189 DeInitGL();//Disable/enable, what concrete plot painter enabled/disabled
190
191 //Restore projection and modelview matrices.
194
195 glViewport(vp[0], vp[1], vp[2], vp[3]);
196 //GL pad painter does not use depth test, so,
197 //switch it off now.
198 glDepthMask(GL_FALSE);//0]
199
200 if (fCoord && fCoord->GetCoordType() == kGLCartesian && fDrawAxes) {
201
202 Bool_t old = gPad->TestBit(TGraph::kClipFrame);
203 if (!old)
204 gPad->SetBit(TGraph::kClipFrame);
205
206 //Viewport on retina is bigger than real pixel coordinates in
207 //a pad, scale it back.
210 if (scale < 1.f)//Just ignore this.
211 scale = 1.f;
212
213 const Int_t viewport[] = {Int_t(fCamera->GetX() / scale),
214 Int_t(fCamera->GetY() / scale),
215 Int_t(fCamera->GetWidth() / scale),
216 Int_t(fCamera->GetHeight() / scale)};
217 Rgl::DrawAxes(fBackBox.GetFrontPoint(), viewport, fBackBox.Get2DBox(), fCoord, fXAxis, fYAxis, fZAxis);
218 if (fDrawPalette)
220
221 if (!old)
222 gPad->ResetBit(TGraph::kClipFrame);
223 } else if(fDrawPalette)
225
226}
227
228////////////////////////////////////////////////////////////////////////////////
229/// Generate PS using gl2ps
230
232{
234
235 FILE *output = fopen(gVirtualPS->GetName(), "a");
236 if (!output) {
237 Error("TGLPlotPainter::PrintPlot", "Could not (re)open ps file for GL output");
238 //As soon as we started embedded ps, we have to close it before exiting.
240 return;
241 }
242
243 Int_t gl2psFormat = GL2PS_EPS;
244 Int_t gl2psSort = GL2PS_BSP_SORT;
245 Int_t bufsize = 0;
246 Int_t state = GL2PS_OVERFLOW;
247 GLint gl2psoption = GL2PS_USE_CURRENT_VIEWPORT |
248 GL2PS_SILENT |
249 GL2PS_BEST_ROOT |
250 GL2PS_OCCLUSION_CULL |
251 0;
252
253 while (state == GL2PS_OVERFLOW) {
254 bufsize += 1024*1024;
255 gl2psBeginPage ("ROOT Scene Graph", "ROOT", nullptr,
256 gl2psFormat, gl2psSort, gl2psoption,
257 GL_RGBA, 0, nullptr,0, 0, 0,
258 bufsize, output, nullptr);
259 DrawPlot();
260 state = gl2psEndPage();
261 }
262
263 fclose(output);
265 glFlush();
266}
267
268////////////////////////////////////////////////////////////////////////////////
269///Read color buffer content to find selected object
270
272{
273 if (fUpdateSelection) {
274 //Save projection and modelview matrix, used by glpad.
275 glMatrixMode(GL_PROJECTION);//[1
276 glPushMatrix();
277 glMatrixMode(GL_MODELVIEW);//[2
278 glPushMatrix();
279
281 fCamera->SetCamera();
282
283 glDepthMask(GL_TRUE);
284 glClearColor(0.f, 0.f, 0.f, 0.f);
285 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
286
287 fCamera->Apply(fPadPhi, fPadTheta);
288 DrawPlot();
289
290 glFinish();
291 //fSelection.ReadColorBuffer(fCamera->GetWidth(), fCamera->GetHeight());
292
293 fSelection.ReadColorBuffer(fCamera->GetX(), fCamera->GetY(), fCamera->GetWidth(), fCamera->GetHeight());
296
297 glDepthMask(GL_FALSE);
298 glDisable(GL_DEPTH_TEST);
299
300 //Restore projection and modelview matrices.
301 glMatrixMode(GL_PROJECTION);//1]
302 glPopMatrix();
303 glMatrixMode(GL_MODELVIEW);//2]
304 glPopMatrix();
305 }
306
307 px -= Int_t(gPad->GetXlowNDC() * gPad->GetWw());
308 py -= Int_t(gPad->GetWh() - gPad->YtoAbsPixel(gPad->GetY1()));
309
310 //Pixel coords can be affected by scaling factor on retina displays.
313
314 if (scale > 1.f) {
315 px *= scale;
316 py *= scale;
317 }
318
319 //py = fCamera->GetHeight() - py;
320 //Y is a number of a row, x - column.
321 std::swap(px, py);
322 Int_t newSelected(Rgl::ColorToObjectID(fSelection.GetPixelColor(px, py), fHighColor));
323
324 if (newSelected != fSelectedPart) {
325 //New object was selected (or surface deselected) - re-paint.
326 fSelectedPart = newSelected;
327 gPad->Update();
328 }
329
330 return fSelectedPart ? kTRUE : kFALSE;
331}
332
333////////////////////////////////////////////////////////////////////////////////
334///Used in a pad.
335
337{
338 fPadColor = c;
339}
340
341////////////////////////////////////////////////////////////////////////////////
342///Set plot's back box color.
343
345{
346 fBackBox.SetFrameColor(c);
347}
348
349////////////////////////////////////////////////////////////////////////////////
350///Selection must be updated.
351
356
357////////////////////////////////////////////////////////////////////////////////
358///Get pad color.
359
361{
362 return fPadColor;
363}
364
365////////////////////////////////////////////////////////////////////////////////
366///Create dynamic profile using selected plane
367
369{
370 //Coordinates are expected to be fixed for retina!
371
372 const TGLVertex3 *frame = fBackBox.Get3DBox();
373 const Int_t frontPoint = fBackBox.GetFrontPoint();
374
375 if (fSelectedPart == 1) {
376 fXOYSectionPos = frame[0].Z();
377 fSelectedPart = 6;
378 } else if (fSelectedPart == 2) {
379 if (frontPoint == 2) {
380 fXOZSectionPos = frame[0].Y();
381 fSelectedPart = 4;
382 } else if (!frontPoint) {
383 fXOZSectionPos = frame[2].Y();
384 fSelectedPart = 4;
385 } else if (frontPoint == 1) {
386 fYOZSectionPos = frame[0].X();
387 fSelectedPart = 5;
388 } else if (frontPoint == 3) {
389 fYOZSectionPos = frame[1].X();
390 fSelectedPart = 5;
391 }
392 } else if (fSelectedPart == 3) {
393 if (frontPoint == 2) {
394 fYOZSectionPos = frame[0].X();
395 fSelectedPart = 5;
396 } else if (!frontPoint) {
397 fYOZSectionPos = frame[1].X();
398 fSelectedPart = 5;
399 } else if (frontPoint == 1) {
400 fXOZSectionPos = frame[2].Y();
401 fSelectedPart = 4;
402 } else if (frontPoint == 3) {
403 fXOZSectionPos = frame[0].Y();
404 fSelectedPart = 4;
405 }
406 }
407
408 Double_t mv[16] = {0.};
409 glGetDoublev(GL_MODELVIEW_MATRIX, mv);
410 Double_t pr[16] = {0.};
411 glGetDoublev(GL_PROJECTION_MATRIX, pr);
412 Int_t vp[4] = {0};
413 glGetIntegerv(GL_VIEWPORT, vp);
414 Double_t winVertex[3] = {0.};
415
416 if (fSelectedPart == 6)
417 gluProject(0., 0., fXOYSectionPos, mv, pr, vp, &winVertex[0], &winVertex[1], &winVertex[2]);
418 else
419 gluProject(fSelectedPart == 5 ? fYOZSectionPos : 0.,
420 fSelectedPart == 4 ? fXOZSectionPos : 0.,
421 0., mv, pr, vp,
422 &winVertex[0], &winVertex[1], &winVertex[2]);
423 winVertex[0] += px - fMousePosition.fX;
424 winVertex[1] += py - fMousePosition.fY;
425 Double_t newPoint[3] = {0.};
426 gluUnProject(winVertex[0], winVertex[1], winVertex[2], mv, pr, vp,
427 newPoint, newPoint + 1, newPoint + 2);
428
429 if (fSelectedPart == 4)
430 fXOZSectionPos = newPoint[1];
431 else if (fSelectedPart == 5)
432 fYOZSectionPos = newPoint[0];
433 else
434 fXOYSectionPos = newPoint[2];
435}
436
437////////////////////////////////////////////////////////////////////////////////
438///Draw sections (if any).
439
441{
442 const TGLVertex3 *frame = fBackBox.Get3DBox();
443
444 if (fXOZSectionPos > frame[0].Y()) {
445 if (fXOZSectionPos > frame[2].Y())
446 fXOZSectionPos = frame[2].Y();
447 const TGLVertex3 v1(frame[0].X(), fXOZSectionPos, frame[0].Z());
448 const TGLVertex3 v2(frame[4].X(), fXOZSectionPos, frame[4].Z());
449 const TGLVertex3 v3(frame[5].X(), fXOZSectionPos, frame[5].Z());
450 const TGLVertex3 v4(frame[1].X(), fXOZSectionPos, frame[1].Z());
451
452 if (fSelectionPass)
454 else if (fSelectedPart == 4)
455 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gBlueEmission);
456
457 glEnable(GL_POLYGON_OFFSET_FILL);
458 glPolygonOffset(1.f, 1.f);
459 Rgl::DrawQuadFilled(v1, v2, v3, v4, TGLVector3(0., 1., 0.));
460 glDisable(GL_POLYGON_OFFSET_FILL);
461 //Zlevels here.
462 if (!fSelectionPass) {
463 if (fSelectedPart == 4)
464 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gNullEmission);
465 const TGLDisableGuard lightGuard(GL_LIGHTING);
466 const TGLEnableGuard blendGuard(GL_BLEND);
467 const TGLEnableGuard lineSmooth(GL_LINE_SMOOTH);
468 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
469 glDepthMask(GL_FALSE);
471 //Draw z-levels
472 const TGLEnableGuard stippleGuard(GL_LINE_STIPPLE);//[1-1]
473 const UShort_t stipple = 0x5555;
474 glLineStipple(1, stipple);
475
476 glColor3d(0., 0., 0.);
477 glBegin(GL_LINES);
478 for (UInt_t i = 0; i < fZLevels.size(); ++i) {
479 glVertex3d(fBackBox.Get3DBox()[1].X(), fXOZSectionPos, fZLevels[i]);
480 glVertex3d(fBackBox.Get3DBox()[0].X(), fXOZSectionPos, fZLevels[i]);
481 }
482 glEnd();
483 glDepthMask(GL_TRUE);
484 }
485 }
486
487 if (fYOZSectionPos > frame[0].X()) {
488 if (fYOZSectionPos > frame[1].X())
489 fYOZSectionPos = frame[1].X();
490 TGLVertex3 v1(fYOZSectionPos, frame[0].Y(), frame[0].Z());
491 TGLVertex3 v2(fYOZSectionPos, frame[3].Y(), frame[3].Z());
492 TGLVertex3 v3(fYOZSectionPos, frame[7].Y(), frame[7].Z());
493 TGLVertex3 v4(fYOZSectionPos, frame[4].Y(), frame[4].Z());
494
495 if (fSelectionPass) {
497 } else if (fSelectedPart == 5)
498 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gBlueEmission);
499
500 glEnable(GL_POLYGON_OFFSET_FILL);
501 glPolygonOffset(1.f, 1.f);
502 Rgl::DrawQuadFilled(v1, v2, v3, v4, TGLVector3(1., 0., 0.));
503 glDisable(GL_POLYGON_OFFSET_FILL);
504
505 if (!fSelectionPass) {
506 if (fSelectedPart == 5)
507 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gNullEmission);
508 const TGLDisableGuard lightHuard(GL_LIGHTING);
509 const TGLEnableGuard blendGuard(GL_BLEND);
510 const TGLEnableGuard lineSmooth(GL_LINE_SMOOTH);
511 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
512 glDepthMask(GL_FALSE);
514 //Draw z-levels
515 const TGLEnableGuard stippleGuard(GL_LINE_STIPPLE);//[1-1]
516 glLineStipple(1, 0x5555);
517
518 glColor3d(0., 0., 0.);
519 glBegin(GL_LINES);
520 for (UInt_t i = 0; i < fZLevels.size(); ++i) {
521 glVertex3d(fYOZSectionPos, fBackBox.Get3DBox()[3].Y(), fZLevels[i]);
522 glVertex3d(fYOZSectionPos, fBackBox.Get3DBox()[0].Y(), fZLevels[i]);
523 }
524 glEnd();
525 glDepthMask(GL_TRUE);
526 }
527 }
528
529 if (fXOYSectionPos > frame[0].Z()) {
530 if (fXOYSectionPos > frame[4].Z())
531 fXOYSectionPos = frame[4].Z();
532 TGLVertex3 v1(frame[0].X(), frame[0].Y(), fXOYSectionPos);
533 TGLVertex3 v2(frame[1].X(), frame[1].Y(), fXOYSectionPos);
534 TGLVertex3 v3(frame[2].X(), frame[2].Y(), fXOYSectionPos);
535 TGLVertex3 v4(frame[3].X(), frame[3].Y(), fXOYSectionPos);
536
537 if (fSelectionPass) {
539 } else if (fSelectedPart == 6)
540 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gBlueEmission);
541
542 glEnable(GL_POLYGON_OFFSET_FILL);
543 glPolygonOffset(1.f, 1.f);
544 //if (fSelectionPass || fSelectedPart == 6)
545 Rgl::DrawQuadFilled(v1, v2, v3, v4, TGLVector3(0., 0., 1.));
546 glDisable(GL_POLYGON_OFFSET_FILL);
547
548 if (!fSelectionPass) {
549 if (fSelectedPart == 6)
550 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gNullEmission);
551 const TGLDisableGuard lightGuard(GL_LIGHTING);
552 const TGLEnableGuard blendGuard(GL_BLEND);
553 const TGLEnableGuard lineSmooth(GL_LINE_SMOOTH);
554 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
555 glDepthMask(GL_FALSE);
557 glDepthMask(GL_TRUE);
558 }
559 }
560}
561
562////////////////////////////////////////////////////////////////////////////////
563
565{
566/*
567 // Clear buffer.
568 Float_t rgb[3] = {1.f, 1.f, 1.f};
569 if (const TColor *color = GetPadColor())
570 color->GetRGB(rgb[0], rgb[1], rgb[2]);
571 glClearColor(rgb[0], rgb[1], rgb[2], 1.);
572 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
573 */
574}
575
576////////////////////////////////////////////////////////////////////////////////
577///Draw. Palette. Axis.
578
582
583////////////////////////////////////////////////////////////////////////////////
584
586{
587 glMatrixMode(GL_MODELVIEW);
588 glPushMatrix();
589}
590
591////////////////////////////////////////////////////////////////////////////////
592
594{
595 glMatrixMode(GL_PROJECTION);
596 glPushMatrix();
597}
598
599////////////////////////////////////////////////////////////////////////////////
600
602{
603 glMatrixMode(GL_MODELVIEW);
604 glPopMatrix();
605}
606
607////////////////////////////////////////////////////////////////////////////////
608
610{
611 glMatrixMode(GL_PROJECTION);
612 glPopMatrix();
613}
614
615/** \class TGLPlotCoordinates
616\ingroup opengl
617Helper class for plot-painters holding information about axis
618ranges, numbers of bins and flags if certain axis is logarithmic.
619*/
620
621
622////////////////////////////////////////////////////////////////////////////////
623///Constructor.
624
627 fXScale(1.),
628 fYScale(1.),
629 fZScale(1.),
630 fXLog(kFALSE),
631 fYLog(kFALSE),
632 fZLog(kFALSE),
634 fFactor(1.)
635{
636}
637
638////////////////////////////////////////////////////////////////////////////////
639///Destructor.
640
644
645////////////////////////////////////////////////////////////////////////////////
646///If coord type was changed, plot must reset sections (if any),
647///set fModified.
648
650{
651 if (fCoordType != type) {
653 fCoordType = type;
654 }
655}
656
657////////////////////////////////////////////////////////////////////////////////
658/// Get coordinates type.
659
664
665////////////////////////////////////////////////////////////////////////////////
666///If log changed, sections must be reset,
667///set fModified.
668
670{
671 if (fXLog != xLog) {
672 fXLog = xLog;
674 }
675}
676
677////////////////////////////////////////////////////////////////////////////////
678/// Get X log.
679
681{
682 return fXLog;
683}
684
685////////////////////////////////////////////////////////////////////////////////
686///If log changed, sections must be reset,
687///set fModified.
688
690{
691 if (fYLog != yLog) {
692 fYLog = yLog;
694 }
695}
696
697////////////////////////////////////////////////////////////////////////////////
698/// Get Y log.
699
701{
702 return fYLog;
703}
704
705////////////////////////////////////////////////////////////////////////////////
706///If log changed, sections must be reset,
707///set fModified.
708
710{
711 if (fZLog != zLog) {
712 fZLog = zLog;
714 }
715}
716
717////////////////////////////////////////////////////////////////////////////////
718/// Get Z log.
719
721{
722 return fZLog;
723}
724
725////////////////////////////////////////////////////////////////////////////////
726/// Reset modified.
727
729{
730 fModified = !fModified;//kFALSE;
731}
732
733////////////////////////////////////////////////////////////////////////////////
734/// Modified.
735
737{
738 return fModified;
739}
740
741////////////////////////////////////////////////////////////////////////////////
742///Set bin ranges, ranges.
743
745{
746 switch (fCoordType) {
747 case kGLPolar:
748 return SetRangesPolar(hist);
749 case kGLCylindrical:
750 return SetRangesCylindrical(hist);
751 case kGLSpherical:
752 return SetRangesSpherical(hist);
753 case kGLCartesian:
754 default:
755 return SetRangesCartesian(hist, errors, zBins);
756 }
757}
758
759////////////////////////////////////////////////////////////////////////////////
760///Number of X bins.
761
763{
764 return fXBins.second - fXBins.first + 1;
765}
766
767////////////////////////////////////////////////////////////////////////////////
768///Number of Y bins.
769
771{
772 return fYBins.second - fYBins.first + 1;
773}
774
775////////////////////////////////////////////////////////////////////////////////
776///Number of Z bins.
777
779{
780 return fZBins.second - fZBins.first + 1;
781}
782
783////////////////////////////////////////////////////////////////////////////////
784///X bins range.
785
787{
788 return fXBins;
789}
790
791////////////////////////////////////////////////////////////////////////////////
792///Y bins range.
793
795{
796 return fYBins;
797}
798
799////////////////////////////////////////////////////////////////////////////////
800///Z bins range.
801
803{
804 return fZBins;
805}
806
807////////////////////////////////////////////////////////////////////////////////
808///X range.
809
811{
812 return fXRange;
813}
814
815////////////////////////////////////////////////////////////////////////////////
816///X length.
817
819{
820 return fXRange.second - fXRange.first;
821}
822
823////////////////////////////////////////////////////////////////////////////////
824///Y range.
825
827{
828 return fYRange;
829}
830
831////////////////////////////////////////////////////////////////////////////////
832///Y length.
833
835{
836 return fYRange.second - fYRange.first;
837}
838
839
840////////////////////////////////////////////////////////////////////////////////
841///Z range.
842
844{
845 return fZRange;
846}
847
848////////////////////////////////////////////////////////////////////////////////
849///Z length.
850
852{
853 return fZRange.second - fZRange.first;
854}
855
856
857////////////////////////////////////////////////////////////////////////////////
858///Scaled range.
859
864
865////////////////////////////////////////////////////////////////////////////////
866///Scaled range.
867
872
873////////////////////////////////////////////////////////////////////////////////
874///Scaled range.
875
880
881////////////////////////////////////////////////////////////////////////////////
882/// Get factor.
883
885{
886 return fFactor;
887}
888
889namespace {
890
891Bool_t FindAxisRange(const TAxis *axis, Bool_t log, Rgl::BinRange_t &bins, Rgl::Range_t &range);
892Bool_t FindAxisRange(const TH1 *hist, Bool_t logZ, const Rgl::BinRange_t &xBins,
893 const Rgl::BinRange_t &yBins, Rgl::Range_t &zRange,
894 Double_t &factor, Bool_t errors);
895
896Bool_t FindAxisRange(TH2Poly *hist, Bool_t zLog, Rgl::Range_t &zRange);
897
898}
899
900////////////////////////////////////////////////////////////////////////////////
901///Set bin ranges, ranges, etc.
902
904{
905 Rgl::BinRange_t xBins;
906 Rgl::Range_t xRange;
907 if (!FindAxisRange(hist->GetXaxis(), fXLog, xBins, xRange)) {
908 Error("TGLPlotCoordinates::SetRangesCartesian", "Cannot set X axis to log scale");
909 return kFALSE;
910 }
911
912 Rgl::BinRange_t yBins;
913 Rgl::Range_t yRange;
914 if (!FindAxisRange(hist->GetYaxis(), fYLog, yBins, yRange)) {
915 Error("TGLPlotCoordinates::SetRangesCartesian", "Cannot set Y axis to log scale");
916 return kFALSE;
917 }
918
919 Rgl::BinRange_t zBins;
920 Rgl::Range_t zRange;
921 Double_t factor = 1.;
922
923 if (zAsBins) {
924 if (!FindAxisRange(hist->GetZaxis(), fZLog, zBins, zRange)) {
925 Error("TGLPlotCoordinates::SetRangesCartesian", "Cannot set Z axis to log scale");
926 return kFALSE;
927 }
928 } else if (!FindAxisRange(hist, fZLog, xBins, yBins, zRange, factor, errors)) {
929 Error("TGLPlotCoordinates::SetRangesCartesian",
930 "Log scale is requested for Z, but maximum less or equal 0. (%f)", zRange.second);
931 return kFALSE;
932 }
933
934 //Finds the maximum dimension and adjust scale coefficients
935 const Double_t x = xRange.second - xRange.first;
936 const Double_t y = yRange.second - yRange.first;
937 const Double_t z = zRange.second - zRange.first;
938
939 if (!x || !y || !z) {
940 Error("TGLPlotCoordinates::SetRangesCartesian", "Zero axis range.");
941 return kFALSE;
942 }
943
944 if (xRange != fXRange || yRange != fYRange || zRange != fZRange ||
945 xBins != fXBins || yBins != fYBins || zBins != fZBins || fFactor != factor)
946 {
948 }
949
950 fXRange = xRange, fXBins = xBins, fYRange = yRange, fYBins = yBins, fZRange = zRange, fZBins = zBins;
951 fFactor = factor;
952 /*
953 const Double_t maxDim = TMath::Max(TMath::Max(x, y), z);
954 fXScale = maxDim / x;
955 fYScale = maxDim / y;
956 fZScale = maxDim / z;
957 */
958 fXScale = 1. / x;
959 fYScale = 1. / y;
960 fZScale = 1. / z;
961
962 fXRangeScaled.first = fXRange.first * fXScale, fXRangeScaled.second = fXRange.second * fXScale;
963 fYRangeScaled.first = fYRange.first * fYScale, fYRangeScaled.second = fYRange.second * fYScale;
964 fZRangeScaled.first = fZRange.first * fZScale, fZRangeScaled.second = fZRange.second * fZScale;
965
966 return kTRUE;
967}
968
969//
970////////////////////////////////////////////////////////////////////////////////
971///Set bin ranges, ranges, etc.
972
974{
975 Rgl::BinRange_t xBins;
976 Rgl::Range_t xRange;
977 FindAxisRange(hist->GetXaxis(), kFALSE, xBins, xRange);//kFALSE == never logarithmic.
978
979 Rgl::BinRange_t yBins;
980 Rgl::Range_t yRange;
981 FindAxisRange(hist->GetYaxis(), kFALSE, yBins, yRange);//kFALSE == never logarithmic.
982
983 Rgl::BinRange_t zBins;
984 Rgl::Range_t zRange;
985 Double_t factor = 1.;
986
987 if (!FindAxisRange(hist, fZLog, zRange))
988 return kFALSE;
989
990 //Finds the maximum dimension and adjust scale coefficients
991 const Double_t x = xRange.second - xRange.first;
992 const Double_t y = yRange.second - yRange.first;
993 const Double_t z = zRange.second - zRange.first;
994
995 if (!x || !y || !z) {
996 Error("TGLPlotCoordinates::SetRanges", "Zero axis range.");
997 return kFALSE;
998 }
999
1000 if (xRange != fXRange || yRange != fYRange || zRange != fZRange ||
1001 xBins != fXBins || yBins != fYBins || zBins != fZBins || fFactor != factor)
1002 {
1003 fModified = kTRUE;
1004 }
1005
1006 fXRange = xRange, fXBins = xBins, fYRange = yRange, fYBins = yBins, fZRange = zRange, fZBins = zBins;
1007 fFactor = factor;
1008
1011 fZScale = 1. / z;
1012
1013 fXRangeScaled.first = fXRange.first * fXScale, fXRangeScaled.second = fXRange.second * fXScale;
1014 fYRangeScaled.first = fYRange.first * fYScale, fYRangeScaled.second = fYRange.second * fYScale;
1015 fZRangeScaled.first = fZRange.first * fZScale, fZRangeScaled.second = fZRange.second * fZScale;
1016
1017 return kTRUE;
1018}
1019//
1020
1021////////////////////////////////////////////////////////////////////////////////
1022///Set bin ranges, ranges, etc.
1023
1024Bool_t TGLPlotCoordinates::SetRanges(const TAxis *xAxis, const TAxis *yAxis, const TAxis *zAxis)
1025{
1026 Rgl::BinRange_t xBins;
1027 Rgl::Range_t xRange;
1028
1029 FindAxisRange(xAxis, kFALSE, xBins, xRange);
1030
1031 Rgl::BinRange_t yBins;
1032 Rgl::Range_t yRange;
1033
1034 FindAxisRange(yAxis, kFALSE, yBins, yRange);
1035
1036 Rgl::BinRange_t zBins;
1037 Rgl::Range_t zRange;
1038 Double_t factor = 1.;
1039
1040 FindAxisRange(zAxis, kFALSE, zBins, zRange);
1041
1042 //Finds the maximum dimension and adjust scale coefficients
1043 const Double_t x = xRange.second - xRange.first;
1044 const Double_t y = yRange.second - yRange.first;
1045 const Double_t z = zRange.second - zRange.first;
1046
1047 if (!x || !y || !z) {
1048 Error("TGLPlotCoordinates::SetRangesCartesian", "Zero axis range.");
1049 return kFALSE;
1050 }
1051
1052 if (xRange != fXRange || yRange != fYRange || zRange != fZRange ||
1053 xBins != fXBins || yBins != fYBins || zBins != fZBins || fFactor != factor)
1054 {
1055 fModified = kTRUE;
1056 }
1057
1058 fXRange = xRange, fXBins = xBins, fYRange = yRange, fYBins = yBins, fZRange = zRange, fZBins = zBins;
1059 fFactor = factor;
1060
1061/* const Double_t maxDim = TMath::Max(TMath::Max(x, y), z);
1062 fXScale = maxDim / x;
1063 fYScale = maxDim / y;
1064 fZScale = maxDim / z;*/
1065
1066 fXScale = 1. / x;
1067 fYScale = 1. / y;
1068 fZScale = 1. / z;
1069
1070 fXRangeScaled.first = fXRange.first * fXScale, fXRangeScaled.second = fXRange.second * fXScale;
1071 fYRangeScaled.first = fYRange.first * fYScale, fYRangeScaled.second = fYRange.second * fYScale;
1072 fZRangeScaled.first = fZRange.first * fZScale, fZRangeScaled.second = fZRange.second * fZScale;
1073
1074 return kTRUE;
1075}
1076
1077////////////////////////////////////////////////////////////////////////////////
1078///Set bin ranges, ranges, etc.
1079
1081{
1082 Rgl::BinRange_t xBins;
1083 Rgl::Range_t phiRange;
1084 const TAxis *xAxis = hist->GetXaxis();
1085 FindAxisRange(xAxis, kFALSE, xBins, phiRange);
1086 if (xBins.second - xBins.first + 1 > 360) {
1087 Error("TGLPlotCoordinates::SetRangesPolar", "To many PHI sectors");
1088 return kFALSE;
1089 }
1090
1091 Rgl::BinRange_t yBins;
1092 Rgl::Range_t roRange;
1093 const TAxis *yAxis = hist->GetYaxis();
1094 FindAxisRange(yAxis, kFALSE, yBins, roRange);
1095
1096 Rgl::Range_t zRange;
1097 Double_t factor = 1.;
1098 if (!FindAxisRange(hist, fZLog, xBins, yBins, zRange, factor, kFALSE))
1099 {
1100 Error("TGLPlotCoordinates::SetRangesPolar",
1101 "Log scale is requested for Z, but maximum less or equal 0. (%f)", zRange.second);
1102 return kFALSE;
1103 }
1104
1105 const Double_t z = zRange.second - zRange.first;
1106 if (!z || !(phiRange.second - phiRange.first) || !(roRange.second - roRange.first)) {
1107 Error("TGLPlotCoordinates::SetRangesPolar", "Zero axis range.");
1108 return kFALSE;
1109 }
1110
1111 if (phiRange != fXRange || roRange != fYRange || zRange != fZRange ||
1112 xBins != fXBins || yBins != fYBins || fFactor != factor)
1113 {
1114 fModified = kTRUE;
1115 fXRange = phiRange, fXBins = xBins;
1116 fYRange = roRange, fYBins = yBins;
1117 fZRange = zRange;
1118 fFactor = factor;
1119 }
1120
1121 //const Double_t maxDim = TMath::Max(2., z);
1122 fXScale = 0.5;//maxDim / 2.;
1123 fYScale = 0.5;//maxDim / 2.;
1124 fZScale = 1. / z;//maxDim / z;
1125 fXRangeScaled.first = -fXScale, fXRangeScaled.second = fXScale;
1126 fYRangeScaled.first = -fYScale, fYRangeScaled.second = fYScale;
1127 fZRangeScaled.first = fZRange.first * fZScale, fZRangeScaled.second = fZRange.second * fZScale;
1128
1129 return kTRUE;
1130}
1131
1132////////////////////////////////////////////////////////////////////////////////
1133/// Set ranges cylindrical.
1134
1136{
1137 Rgl::BinRange_t xBins, yBins;
1138 Rgl::Range_t angleRange, heightRange, radiusRange;
1139 const TAxis *xAxis = hist->GetXaxis();
1140 const TAxis *yAxis = hist->GetYaxis();
1141 Double_t factor = 1.;
1142
1143 FindAxisRange(xAxis, kFALSE, xBins, angleRange);
1144 if (xBins.second - xBins.first + 1 > 360) {
1145 Error("TGLPlotCoordinates::SetRangesCylindrical", "To many PHI sectors");
1146 return kFALSE;
1147 }
1148 if (!FindAxisRange(yAxis, fYLog, yBins, heightRange)) {
1149 Error("TGLPlotCoordinates::SetRangesCylindrical", "Cannot set Y axis to log scale");
1150 return kFALSE;
1151 }
1152 FindAxisRange(hist, kFALSE, xBins, yBins, radiusRange, factor, kFALSE);
1153
1154 const Double_t x = angleRange.second - angleRange.first;
1155 const Double_t y = heightRange.second - heightRange.first;
1156 const Double_t z = radiusRange.second - radiusRange.first;
1157
1158 if (!x || !y || !z) {
1159 Error("TGLPlotCoordinates::SetRangesCylindrical", "Zero axis range.");
1160 return kFALSE;
1161 }
1162
1163 if (angleRange != fXRange || heightRange != fYRange ||
1164 radiusRange != fZRange || xBins != fXBins ||
1165 yBins != fYBins || fFactor != factor)
1166 {
1167 fModified = kTRUE;
1168 fXRange = angleRange, fXBins = xBins;
1169 fYRange = heightRange, fYBins = yBins;
1170 fZRange = radiusRange;
1171 fFactor = factor;
1172 }
1173
1174 // const Double_t maxDim = TMath::Max(2., y);
1175 fXScale = 0.5;//maxDim / 2.;
1176 fYScale = 1. / y;//maxDim / y;
1177 fZScale = 0.5;//maxDim / 2.;
1178 fXRangeScaled.first = -fXScale, fXRangeScaled.second = fXScale;
1179 fYRangeScaled.first = fYRange.first * fYScale, fYRangeScaled.second = fYRange.second * fYScale;
1180 fZRangeScaled.first = -fZScale, fZRangeScaled.second = fZScale;
1181
1182 return kTRUE;
1183}
1184
1185////////////////////////////////////////////////////////////////////////////////
1186/// Set ranges spherical.
1187
1189{
1190 Rgl::BinRange_t xBins;
1191 Rgl::Range_t phiRange;
1192 FindAxisRange(hist->GetXaxis(), kFALSE, xBins, phiRange);
1193 if (xBins.second - xBins.first + 1 > 360) {
1194 Error("TGLPlotCoordinates::SetRangesSpherical", "To many PHI sectors");
1195 return kFALSE;
1196 }
1197
1198 Rgl::BinRange_t yBins;
1199 Rgl::Range_t thetaRange;
1200 FindAxisRange(hist->GetYaxis(), kFALSE, yBins, thetaRange);
1201 if (yBins.second - yBins.first + 1 > 180) {
1202 Error("TGLPlotCoordinates::SetRangesSpherical", "To many THETA sectors");
1203 return kFALSE;
1204 }
1205
1206 Rgl::Range_t radiusRange;
1207 Double_t factor = 1.;
1208 FindAxisRange(hist, kFALSE, xBins, yBins, radiusRange, factor, kFALSE);
1209
1210 if (xBins != fXBins || yBins != fYBins ||
1211 phiRange != fXRange || thetaRange != fYRange ||
1212 radiusRange != fZRange || fFactor != factor)
1213 {
1214 fModified = kTRUE;
1215 fXBins = xBins;
1216 fYBins = yBins;
1217 fXRange = phiRange;
1218 fYRange = thetaRange,
1219 fZRange = radiusRange;
1220 fFactor = factor;
1221 }
1222
1223 fXScale = 0.5;
1224 fYScale = 0.5;
1225 fZScale = 0.5;
1226 fXRangeScaled.first = -fXScale, fXRangeScaled.second = fXScale;
1227 fYRangeScaled.first = -fYScale, fYRangeScaled.second = fYScale;
1228 fZRangeScaled.first = -fZScale, fZRangeScaled.second = fZScale;
1229
1230 return kTRUE;
1231}
1232
1233namespace {
1234
1235////////////////////////////////////////////////////////////////////////////////
1236/// Find minimal bin width.
1237
1238Double_t FindMinBinWidth(const TAxis *axis)
1239{
1240 Int_t currBin = axis->GetFirst();
1241 Double_t width = axis->GetBinWidth(currBin);
1242
1243 if (!axis->IsVariableBinSize())//equal bins
1244 return width;
1245
1246 ++currBin;
1247 //variable size bins
1248 for (const Int_t lastBin = axis->GetLast(); currBin <= lastBin; ++currBin)
1249 width = TMath::Min(width, axis->GetBinWidth(currBin));
1250
1251 return width;
1252}
1253
1254////////////////////////////////////////////////////////////////////////////////
1255///"Generic" function, can be used for X/Y/Z axis.
1256///[low edge of first ..... up edge of last]
1257///If log is true, at least up edge of last MUST be positive or function fails (1).
1258///If log is true and low edge is negative, try to find bin with positive low edge, bin number
1259///must be less or equal to last (2). If no such bin, function fails.
1260///When looking for a such bin, I'm trying to find value which is 0.01 of
1261///MINIMUM bin width (3) (if bins are equidimensional, first's bin width is OK).
1262///But even such lookup can fail, so, it's a stupid idea to have negative ranges
1263///and logarithmic scale :)
1264
1265Bool_t FindAxisRange(const TAxis *axis, Bool_t log, Rgl::BinRange_t &bins, Rgl::Range_t &range)
1266{
1267 bins.first = axis->GetFirst(), bins.second = axis->GetLast();
1268 range.first = axis->GetBinLowEdge(bins.first), range.second = axis->GetBinUpEdge(bins.second);
1269
1270 if (log) {
1271 if (range.second <= 0.)
1272 return kFALSE;//(1)
1273
1274 range.second = TMath::Log10(range.second);
1275
1276 if (range.first <= 0.) {//(2)
1277 Int_t bin = axis->FindFixBin(FindMinBinWidth(axis) * 0.01);//(3)
1278 //Overflow or something stupid.
1279 if (bin > bins.second)
1280 return kFALSE;
1281
1282 if (axis->GetBinLowEdge(bin) <= 0.) {
1283 ++bin;
1284 if (bin > bins.second)//Again, something stupid.
1285 return kFALSE;
1286 }
1287
1288 bins.first = bin;
1289 range.first = axis->GetBinLowEdge(bin);
1290 }
1291
1292 range.first = TMath::Log10(range.first);
1293 }
1294
1295 return kTRUE;
1296}
1297
1298////////////////////////////////////////////////////////////////////////////////
1299///First, look through hist to find minimum and maximum values.
1300
1301Bool_t FindAxisRange(const TH1 *hist, Bool_t logZ, const Rgl::BinRange_t &xBins,
1302 const Rgl::BinRange_t &yBins, Rgl::Range_t &zRange,
1303 Double_t &factor, Bool_t errors)
1304{
1305 const Bool_t minimum = hist->GetMinimumStored() != -1111;
1306 const Bool_t maximum = hist->GetMaximumStored() != -1111;
1307 const Double_t margin = gStyle->GetHistTopMargin();
1308
1309 zRange.second = hist->GetBinContent(hist->GetBin(xBins.first, yBins.first)), zRange.first = zRange.second;
1310 Double_t summ = 0.;
1311
1312 for (Int_t i = xBins.first; i <= xBins.second; ++i) {
1313 for (Int_t j = yBins.first; j <= yBins.second; ++j) {
1314 Double_t val = hist->GetBinContent(hist->GetBin(i, j));
1315 if (val > 0. && errors)
1316 val = TMath::Max(val, val + hist->GetCellError(i, j));
1317 zRange.second = TMath::Max(val, zRange.second);
1318 zRange.first = TMath::Min(val, zRange.first);
1319 summ += val;
1320 }
1321 }
1322
1323 if (hist->GetMaximumStored() != -1111)
1324 zRange.second = hist->GetMaximumStored();
1325 if (hist->GetMinimumStored() != -1111)
1326 zRange.first = hist->GetMinimumStored();
1327
1328 if (logZ && zRange.second <= 0.)
1329 return kFALSE;//cannot setup logarithmic scale
1330
1331 if (zRange.first >= zRange.second)
1332 zRange.first = 0.001 * zRange.second;
1333
1334 factor = hist->GetNormFactor() > 0. ? hist->GetNormFactor() : summ;
1335 if (summ) factor /= summ;
1336 if (!factor) factor = 1.;
1337 if (factor < 0.)
1338 Warning("TGLPlotPainter::ExtractAxisZInfo",
1339 "Negative factor, negative ranges - possible incorrect behavior");
1340
1341 zRange.second *= factor;
1342 zRange.first *= factor;
1343
1344 if (logZ) {
1345 if (zRange.first <= 0.)
1346 zRange.first = TMath::Min(1., 0.001 * zRange.second);
1347 zRange.first = TMath::Log10(zRange.first);
1348 if (!minimum)
1349 zRange.first += TMath::Log10(0.5);
1350 zRange.second = TMath::Log10(zRange.second);
1351 if (!maximum)
1352 zRange.second += TMath::Log10(2*(0.9/0.95));//This magic numbers are from THistPainter.
1353 return kTRUE;
1354 }
1355
1356 if (!maximum)
1357 zRange.second += margin * (zRange.second - zRange.first);
1358 if (!minimum) {
1359 if (gStyle->GetHistMinimumZero())
1360 zRange.first >= 0 ? zRange.first = 0. : zRange.first -= margin * (zRange.second - zRange.first);
1361 else
1362 zRange.first >= 0 && zRange.first - margin * (zRange.second - zRange.first) <= 0 ?
1363 zRange.first = 0 : zRange.first -= margin * (zRange.second - zRange.first);
1364 }
1365
1366 return kTRUE;
1367}
1368
1369////////////////////////////////////////////////////////////////////////////////
1370///First, look through hist to find minimum and maximum values.
1371
1372Bool_t FindAxisRange(TH2Poly *hist, Bool_t logZ, Rgl::Range_t &zRange)
1373{
1374 TList *bins = hist->GetBins();
1375 if (!bins || !bins->GetEntries()) {
1376 Error("FindAxisRange", "TH2Poly returned empty list of bins");
1377 return kFALSE;
1378 }
1379
1380 zRange.first = hist->GetMinimum();
1381 zRange.second = hist->GetMaximum();
1382
1383 if (zRange.first >= zRange.second)
1384 zRange.first = 0.001 * zRange.second;
1385
1386 if (logZ) {
1387 if (zRange.second < 1e-20) {
1388 Error("FindAxisRange", "Failed to switch Z axis to logarithmic scale");
1389 return kFALSE;
1390 }
1391
1392 if (zRange.first <= 0.)
1393 zRange.first = TMath::Min(1., 0.001 * zRange.second);
1394
1395 zRange.first = TMath::Log10(zRange.first);
1396 zRange.first += TMath::Log10(0.5);
1397 zRange.second = TMath::Log10(zRange.second);
1398 zRange.second += TMath::Log10(2 * (0.9 / 0.95));//These magic numbers come from THistPainter.
1399
1400 return kTRUE;
1401 }
1402
1403 const Double_t margin = gStyle->GetHistTopMargin();
1404 zRange.second += margin * (zRange.second - zRange.first);
1405 if (gStyle->GetHistMinimumZero())
1406 zRange.first >= 0 ? zRange.first = 0. : zRange.first -= margin * (zRange.second - zRange.first);
1407 else
1408 zRange.first >= 0 && zRange.first - margin * (zRange.second - zRange.first) <= 0 ?
1409 zRange.first = 0 : zRange.first -= margin * (zRange.second - zRange.first);
1410
1411 return kTRUE;
1412}
1413
1414}
1415
1416/** \class TGLBoxCut
1417\ingroup opengl
1418Used by plot-painters to determine the area of the plot that is cut away.
1419*/
1420
1421
1422////////////////////////////////////////////////////////////////////////////////
1423///Constructor.
1424
1426 : fXLength(0.),
1427 fYLength(0.),
1428 fZLength(0.),
1429 fPlotBox(box),
1430 fActive(kFALSE),
1431 fFactor(1.)
1432{
1433}
1434
1435////////////////////////////////////////////////////////////////////////////////
1436///Destructor.
1437
1441
1442////////////////////////////////////////////////////////////////////////////////
1443///Turn the box cut on/off.
1444///If it's on, it will be placed in front point of a plot.
1445
1447{
1448 fActive = !fActive;
1449
1450 if (fActive) {
1452 }
1453}
1454
1455////////////////////////////////////////////////////////////////////////////////
1456///Turn the box cut on/off.
1457
1459{
1460 if (a == fActive)
1461 return;
1462 TurnOnOff();
1463}
1464
1465////////////////////////////////////////////////////////////////////////////////
1466///Set geometry using plot's back box.
1467
1469{
1470 const Int_t frontPoint = fPlotBox->GetFrontPoint();
1471 const TGLVertex3 *box = fPlotBox->Get3DBox();
1472 const TGLVertex3 center((box[0].X() + box[1].X()) / 2, (box[0].Y() + box[2].Y()) / 2,
1473 (box[0].Z() + box[4].Z()) / 2);
1474 fXLength = fFactor * (box[1].X() - box[0].X());
1475 fYLength = fFactor * (box[2].Y() - box[0].Y());
1476 fZLength = fFactor * (box[4].Z() - box[0].Z());
1477
1478 switch(frontPoint){
1479 case 0:
1480 fCenter.X() = box[0].X();
1481 fCenter.Y() = box[0].Y();
1482 break;
1483 case 1:
1484 fCenter.X() = box[1].X();
1485 fCenter.Y() = box[0].Y();
1486 break;
1487 case 2:
1488 fCenter.X() = box[2].X();
1489 fCenter.Y() = box[2].Y();
1490 break;
1491 case 3:
1492 fCenter.X() = box[0].X();
1493 fCenter.Y() = box[2].Y();
1494 break;
1495 }
1496
1497 fCenter.Z() = box[0].Z() * 0.5 + box[4].Z() * 0.5;
1498 AdjustBox();
1499}
1500
1501////////////////////////////////////////////////////////////////////////////////
1502///Draw cut as a semi-transparent box.
1503
1504void TGLBoxCut::DrawBox(Bool_t selectionPass, Int_t selected)const
1505{
1506 if (!selectionPass) {
1507 glDisable(GL_LIGHTING);
1508 glLineWidth(3.f);
1509
1510 selected == TGLPlotPainter::kXAxis ? glColor3d(1., 1., 0.) : glColor3d(1., 0., 0.);
1511 glBegin(GL_LINES);
1512 glVertex3d(fXRange.first, (fYRange.first + fYRange.second) / 2, (fZRange.first + fZRange.second) / 2);
1513 glVertex3d(fXRange.second, (fYRange.first + fYRange.second) / 2, (fZRange.first + fZRange.second) / 2);
1514 glEnd();
1515
1516 selected == TGLPlotPainter::kYAxis ? glColor3d(1., 1., 0.) : glColor3d(0., 1., 0.);
1517 glBegin(GL_LINES);
1518 glVertex3d((fXRange.first + fXRange.second) / 2, fYRange.first, (fZRange.first + fZRange.second) / 2);
1519 glVertex3d((fXRange.first + fXRange.second) / 2, fYRange.second, (fZRange.first + fZRange.second) / 2);
1520 glEnd();
1521
1522 selected == TGLPlotPainter::kZAxis ? glColor3d(1., 1., 0.) : glColor3d(0., 0., 1.);
1523 glBegin(GL_LINES);
1524 glVertex3d((fXRange.first + fXRange.second) / 2, (fYRange.first + fYRange.second) / 2, fZRange.first);
1525 glVertex3d((fXRange.first + fXRange.second) / 2, (fYRange.first + fYRange.second) / 2, fZRange.second);
1526 glEnd();
1527
1528 glLineWidth(1.f);
1529 glEnable(GL_LIGHTING);
1530
1531 GLboolean oldBlendState = kFALSE;
1532 glGetBooleanv(GL_BLEND, &oldBlendState);
1533
1534 if (!oldBlendState)
1535 glEnable(GL_BLEND);
1536
1537 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1538
1539
1540 const Float_t diffuseColor[] = {0.f, 0.f, 1.f, 0.1f};
1541 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuseColor);
1542
1543 Rgl::DrawBoxFront(fXRange.first, fXRange.second, fYRange.first, fYRange.second,
1544 fZRange.first, fZRange.second, fPlotBox->GetFrontPoint());
1545
1546 if (!oldBlendState)
1547 glDisable(GL_BLEND);
1548 } else {
1549 glLineWidth(5.f);
1551 glBegin(GL_LINES);
1552 glVertex3d(fXRange.first, (fYRange.first + fYRange.second) / 2, (fZRange.first + fZRange.second) / 2);
1553 glVertex3d(fXRange.second, (fYRange.first + fYRange.second) / 2, (fZRange.first + fZRange.second) / 2);
1554 glEnd();
1555
1557 glBegin(GL_LINES);
1558 glVertex3d((fXRange.first + fXRange.second) / 2, fYRange.first, (fZRange.first + fZRange.second) / 2);
1559 glVertex3d((fXRange.first + fXRange.second) / 2, fYRange.second, (fZRange.first + fZRange.second) / 2);
1560 glEnd();
1561
1563 glBegin(GL_LINES);
1564 glVertex3d((fXRange.first + fXRange.second) / 2, (fYRange.first + fYRange.second) / 2, fZRange.first);
1565 glVertex3d((fXRange.first + fXRange.second) / 2, (fYRange.first + fYRange.second) / 2, fZRange.second);
1566 glEnd();
1567 glLineWidth(1.f);
1568 }
1569}
1570
1571////////////////////////////////////////////////////////////////////////////////
1572///Start cut's movement
1573
1575{
1576 fMousePos.fX = px;
1577 fMousePos.fY = py;
1578}
1579
1580////////////////////////////////////////////////////////////////////////////////
1581///Move box cut along selected direction.
1582
1584{
1585 Double_t mv[16] = {0.};
1586 glGetDoublev(GL_MODELVIEW_MATRIX, mv);
1587 Double_t pr[16] = {0.};
1588 glGetDoublev(GL_PROJECTION_MATRIX, pr);
1589 Int_t vp[4] = {0};
1590 glGetIntegerv(GL_VIEWPORT, vp);
1591 Double_t winVertex[3] = {0.};
1592
1593 switch(axisID){
1595 gluProject(fCenter.X(), 0., 0., mv, pr, vp, &winVertex[0], &winVertex[1], &winVertex[2]);
1596 break;
1598 gluProject(0., fCenter.Y(), 0., mv, pr, vp, &winVertex[0], &winVertex[1], &winVertex[2]);
1599 break;
1601 gluProject(0., 0., fCenter.Z(), mv, pr, vp, &winVertex[0], &winVertex[1], &winVertex[2]);
1602 break;
1603 }
1604
1605 winVertex[0] += px - fMousePos.fX;
1606 winVertex[1] += py - fMousePos.fY;
1607 Double_t newPoint[3] = {0.};
1608 gluUnProject(winVertex[0], winVertex[1], winVertex[2], mv, pr, vp,
1609 newPoint, newPoint + 1, newPoint + 2);
1610
1611 const TGLVertex3 *box = fPlotBox->Get3DBox();
1612
1613 switch(axisID){
1615 if (newPoint[0] >= box[1].X() + 0.4 * fXLength)
1616 break;
1617 if (newPoint[0] <= box[0].X() - 0.4 * fXLength)
1618 break;
1619 fCenter.X() = newPoint[0];
1620 break;
1622 if (newPoint[1] >= box[2].Y() + 0.4 * fYLength)
1623 break;
1624 if (newPoint[1] <= box[0].Y() - 0.4 * fYLength)
1625 break;
1626 fCenter.Y() = newPoint[1];
1627 break;
1629 if (newPoint[2] >= box[4].Z() + 0.4 * fZLength)
1630 break;
1631 if (newPoint[2] <= box[0].Z() - 0.4 * fZLength)
1632 break;
1633 fCenter.Z() = newPoint[2];
1634 break;
1635 }
1636
1637 fMousePos.fX = px;
1638 fMousePos.fY = py;
1639
1640 AdjustBox();
1641}
1642
1643////////////////////////////////////////////////////////////////////////////////
1644///Box cut is limited by plot's sizes.
1645
1647{
1648 const TGLVertex3 *box = fPlotBox->Get3DBox();
1649
1650 fXRange.first = fCenter.X() - fXLength / 2.;
1651 fXRange.second = fCenter.X() + fXLength / 2.;
1652 fYRange.first = fCenter.Y() - fYLength / 2.;
1653 fYRange.second = fCenter.Y() + fYLength / 2.;
1654 fZRange.first = fCenter.Z() - fZLength / 2.;
1655 fZRange.second = fCenter.Z() + fZLength / 2.;
1656
1657 fXRange.first = TMath::Max(fXRange.first, box[0].X());
1658 fXRange.first = TMath::Min(fXRange.first, box[1].X());
1659 fXRange.second = TMath::Min(fXRange.second, box[1].X());
1660 fXRange.second = TMath::Max(fXRange.second, box[0].X());
1661
1662 fYRange.first = TMath::Max(fYRange.first, box[0].Y());
1663 fYRange.first = TMath::Min(fYRange.first, box[2].Y());
1664 fYRange.second = TMath::Min(fYRange.second, box[2].Y());
1665 fYRange.second = TMath::Max(fYRange.second, box[0].Y());
1666
1667 fZRange.first = TMath::Max(fZRange.first, box[0].Z());
1668 fZRange.first = TMath::Min(fZRange.first, box[4].Z());
1669 fZRange.second = TMath::Min(fZRange.second, box[4].Z());
1670 fZRange.second = TMath::Max(fZRange.second, box[0].Z());
1671}
1672
1673////////////////////////////////////////////////////////////////////////////////
1674///Check, if box defined by xmin/xmax etc. is in cut.
1675
1677 Double_t zMin, Double_t zMax)const
1678{
1679 if (((xMin >= fXRange.first && xMin < fXRange.second) || (xMax > fXRange.first && xMax <= fXRange.second)) &&
1680 ((yMin >= fYRange.first && yMin < fYRange.second) || (yMax > fYRange.first && yMax <= fYRange.second)) &&
1681 ((zMin >= fZRange.first && zMin < fZRange.second) || (zMax > fZRange.first && zMax <= fZRange.second)))
1682 return kTRUE;
1683 return kFALSE;
1684}
1685
1686
1687/** \class TGLTH3Slice
1688\ingroup opengl
1689A slice of a TH3.
1690*/
1691
1692
1693////////////////////////////////////////////////////////////////////////////////
1694/// Constructor.
1695
1697 const TGLPlotBox *box, ESliceAxis axis)
1698 : TNamed(name, name),
1699 fAxisType(axis),
1700 fAxis(nullptr),
1701 fCoord(coord),
1702 fBox(box),
1703 fSliceWidth(1),
1704 fHist(hist),
1705 fF3(nullptr)
1706{
1707 fAxis = fAxisType == kXOZ ? fHist->GetYaxis() : fAxisType == kYOZ ? fHist->GetXaxis() : fHist->GetZaxis();
1708}
1709
1710////////////////////////////////////////////////////////////////////////////////
1711/// Constructor.
1712
1713TGLTH3Slice::TGLTH3Slice(const TString &name, const TH3 *hist, const TF3 *fun, const TGLPlotCoordinates *coord,
1714 const TGLPlotBox *box, ESliceAxis axis)
1715 : TNamed(name, name),
1716 fAxisType(axis),
1717 fAxis(nullptr),
1718 fCoord(coord),
1719 fBox(box),
1720 fSliceWidth(1),
1721 fHist(hist),
1722 fF3(fun)
1723{
1724 fAxis = fAxisType == kXOZ ? fHist->GetYaxis() : fAxisType == kYOZ ? fHist->GetXaxis() : fHist->GetZaxis();
1725}
1726
1727////////////////////////////////////////////////////////////////////////////////
1728/// Set Slice width.
1729
1731{
1732 if (width <= 0)
1733 return;
1734
1735 if (fAxis->GetLast() - fAxis->GetFirst() + 1 <= width)
1736 fSliceWidth = fAxis->GetLast() - fAxis->GetFirst() + 1;
1737 else
1738 fSliceWidth = width;
1739}
1740
1741////////////////////////////////////////////////////////////////////////////////
1742/// Draw slice.
1743
1745{
1746 Int_t bin = 0;
1747 for (Int_t i = fAxis->GetFirst(), e = fAxis->GetLast(); i <= e; ++i) {
1748 if (pos >= fAxis->GetBinLowEdge(i) && pos <= fAxis->GetBinUpEdge(i)) {
1749 bin = i;
1750 break;
1751 }
1752 }
1753
1754 if (bin) {
1755 Int_t low = 1, up = 2;
1756 if (bin - fSliceWidth + 1 >= fAxis->GetFirst()) {
1757 low = bin - fSliceWidth + 1;
1758 up = bin + 1;
1759 } else {
1760 low = fAxis->GetFirst();
1761 up = bin + (fSliceWidth - (bin - fAxis->GetFirst() + 1)) + 1;
1762 }
1763
1764 if (!fF3)
1765 FindMinMax(low, up);
1766
1767 if (!PreparePalette())
1768 return;
1769
1770 PrepareTexCoords(pos, low, up);
1771
1772 fPalette.EnableTexture(GL_REPLACE);
1773 const TGLDisableGuard lightGuard(GL_LIGHTING);
1774 DrawSliceTextured(pos);
1775 fPalette.DisableTexture();
1776 //highlight bins in a slice.
1777 //DrawSliceFrame(low, up);
1778 }
1779}
1780
1781////////////////////////////////////////////////////////////////////////////////
1782/// Find minimum and maximum for slice.
1783
1784void TGLTH3Slice::FindMinMax(Int_t /*low*/, Int_t /*up*/)const
1785{
1786 /* fMinMax.first = 0.;
1787
1788 switch (fAxisType) {
1789 case kXOZ:
1790 for (Int_t level = low; level < up; ++ level)
1791 fMinMax.first += fHist->GetBinContent(fCoord->GetFirstXBin(), level, fCoord->GetFirstZBin());
1792 fMinMax.second = fMinMax.first;
1793 for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j <= ej; ++j, ++jt) {
1794 for (Int_t i = fCoord->GetFirstXBin(), it = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++it) {
1795 Double_t val = 0.;
1796 for (Int_t level = low; level < up; ++ level)
1797 val += fHist->GetBinContent(i, level, j);
1798 fMinMax.second = TMath::Max(fMinMax.second, val);
1799 fMinMax.first = TMath::Min(fMinMax.first, val);
1800 }
1801 }
1802 break;
1803 case kYOZ:
1804 for (Int_t level = low; level < up; ++ level)
1805 fMinMax.first += fHist->GetBinContent(level, fCoord->GetFirstYBin(), fCoord->GetFirstZBin());
1806 fMinMax.second = fMinMax.first;
1807 for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j <= ej; ++j, ++jt) {
1808 for (Int_t i = fCoord->GetFirstYBin(), it = 0, ei = fCoord->GetLastYBin(); i <= ei; ++i, ++it) {
1809 Double_t val = 0.;
1810 for (Int_t level = low; level < up; ++ level)
1811 val += fHist->GetBinContent(level, i, j);
1812 fMinMax.second = TMath::Max(fMinMax.second, val);
1813 fMinMax.first = TMath::Min(fMinMax.first, val);
1814 }
1815 }
1816 break;
1817 case kXOY:
1818 for (Int_t level = low; level < up; ++ level)
1819 fMinMax.first += fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin(), level);
1820 fMinMax.second = fMinMax.first;
1821 for (Int_t i = fCoord->GetFirstXBin(), ir = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++ir) {
1822 for (Int_t j = fCoord->GetFirstYBin(), jr = 0, ej = fCoord->GetLastYBin(); j <= ej; ++j, ++jr) {
1823 Double_t val = 0.;
1824 for (Int_t level = low; level < up; ++ level)
1825 val += fHist->GetBinContent(i, j, level);
1826 fMinMax.second = TMath::Max(fMinMax.second, val);
1827 fMinMax.first = TMath::Min(fMinMax.first, val);
1828 }
1829 }
1830 break;
1831 }*/
1832}
1833
1834////////////////////////////////////////////////////////////////////////////////
1835///Initialize color palette.
1836
1838{
1839 UInt_t paletteSize = ((TH1 *)fHist)->GetContour();
1840 if (!paletteSize && !(paletteSize = gStyle->GetNumberContours()))
1841 paletteSize = 20;
1842
1843 return fPalette.GeneratePalette(paletteSize, fMinMax);
1844}
1845
1846////////////////////////////////////////////////////////////////////////////////
1847/// Prepare TexCoords.
1848
1850{
1851 switch (fAxisType) {
1852 case kXOZ:
1853 fTexCoords.resize(fCoord->GetNXBins() * fCoord->GetNZBins());
1854 fTexCoords.SetRowLen(fCoord->GetNXBins());
1855 if (!fF3) {
1856
1857 for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j <= ej; ++j, ++jt) {
1858 for (Int_t i = fCoord->GetFirstXBin(), it = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++it) {
1859 Double_t val = 0.;
1860 for (Int_t level = low; level < up; ++ level)
1861 val += fHist->GetBinContent(i, level, j);
1862 fTexCoords[jt][it] = fPalette.GetTexCoord(val);
1863 }
1864 }
1865 } else {
1866 for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j <= ej; ++j, ++jt) {
1867 for (Int_t i = fCoord->GetFirstXBin(), it = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++it) {
1868 Double_t val = fF3->Eval(fHist->GetXaxis()->GetBinCenter(i), pos, fHist->GetZaxis()->GetBinCenter(j));
1869 if (val > fMinMax.second)
1870 val = fMinMax.second;
1871 else if (val < fMinMax.first)
1872 val = fMinMax.first;
1873 fTexCoords[jt][it] = fPalette.GetTexCoord(val);
1874 }
1875 }
1876 }
1877 break;
1878 case kYOZ:
1879 fTexCoords.resize(fCoord->GetNYBins() * fCoord->GetNZBins());
1880 fTexCoords.SetRowLen(fCoord->GetNYBins());
1881 if (!fF3) {
1882 for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j <= ej; ++j, ++jt) {
1883 for (Int_t i = fCoord->GetFirstYBin(), it = 0, ei = fCoord->GetLastYBin(); i <= ei; ++i, ++it) {
1884 Double_t val = 0.;
1885 for (Int_t level = low; level < up; ++ level)
1886 val += fHist->GetBinContent(level, i, j);
1887 fTexCoords[jt][it] = fPalette.GetTexCoord(val);
1888 }
1889 }
1890 } else {
1891 for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j <= ej; ++j, ++jt) {
1892 for (Int_t i = fCoord->GetFirstXBin(), it = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++it) {
1893 Double_t val = fF3->Eval(pos, fHist->GetYaxis()->GetBinCenter(i), fHist->GetZaxis()->GetBinCenter(j));
1894 if (val > fMinMax.second)
1895 val = fMinMax.second;
1896 else if (val < fMinMax.first)
1897 val = fMinMax.first;
1898 fTexCoords[jt][it] = fPalette.GetTexCoord(val);
1899 }
1900 }
1901 }
1902 break;
1903 case kXOY:
1904 fTexCoords.resize(fCoord->GetNXBins() * fCoord->GetNYBins());
1905 fTexCoords.SetRowLen(fCoord->GetNYBins());
1906 if (!fF3) {
1907 for (Int_t i = fCoord->GetFirstXBin(), ir = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++ir) {
1908 for (Int_t j = fCoord->GetFirstYBin(), jr = 0, ej = fCoord->GetLastYBin(); j <= ej; ++j, ++jr) {
1909 Double_t val = 0.;
1910 for (Int_t level = low; level < up; ++ level)
1911 val += fHist->GetBinContent(i, j, level);
1912 fTexCoords[ir][jr] = fPalette.GetTexCoord(val);
1913 }
1914 }
1915 } else {
1916 for (Int_t i = fCoord->GetFirstXBin(), it = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++it) {
1917 for (Int_t j = fCoord->GetFirstYBin(), jt = 0, ej = fCoord->GetLastYBin(); j <= ej; ++j, ++jt) {
1918 Double_t val = fF3->Eval(fHist->GetXaxis()->GetBinCenter(i), fHist->GetYaxis()->GetBinCenter(j), pos);
1919 if (val > fMinMax.second)
1920 val = fMinMax.second;
1921 else if (val < fMinMax.first)
1922 val = fMinMax.first;
1923 fTexCoords[it][jt] = fPalette.GetTexCoord(val);
1924 }
1925 }
1926
1927 }
1928 break;
1929 }
1930}
1931
1932////////////////////////////////////////////////////////////////////////////////
1933/// Draw slice textured.
1934
1936{
1937 const Double_t xScale = fCoord->GetXScale();
1938 const Double_t yScale = fCoord->GetYScale();
1939 const Double_t zScale = fCoord->GetZScale();
1940 const TAxis *xA = fHist->GetXaxis();
1941 const TAxis *yA = fHist->GetYaxis();
1942 const TAxis *zA = fHist->GetZaxis();
1943
1944 switch (fAxisType) {
1945 case kXOZ:
1946 pos *= yScale;
1947 for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j < ej; ++j, ++jt) {
1948 for (Int_t i = fCoord->GetFirstXBin(), it = 0, ei = fCoord->GetLastXBin(); i < ei; ++i, ++it) {
1949 const Double_t xMin = xA->GetBinCenter(i) * xScale;
1950 const Double_t xMax = xA->GetBinCenter(i + 1) * xScale;
1951 const Double_t zMin = zA->GetBinCenter(j) * zScale;
1952 const Double_t zMax = zA->GetBinCenter(j + 1) * zScale;
1953 glBegin(GL_POLYGON);
1954 glTexCoord1d(fTexCoords[jt][it]);
1955 glVertex3d(xMin, pos, zMin);
1956 glTexCoord1d(fTexCoords[jt + 1][it]);
1957 glVertex3d(xMin, pos, zMax);
1958 glTexCoord1d(fTexCoords[jt + 1][it + 1]);
1959 glVertex3d(xMax, pos, zMax);
1960 glTexCoord1d(fTexCoords[jt][it + 1]);
1961 glVertex3d(xMax, pos, zMin);
1962 glEnd();
1963 }
1964 }
1965 break;
1966 case kYOZ:
1967 pos *= xScale;
1968 for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j < ej; ++j, ++jt) {
1969 for (Int_t i = fCoord->GetFirstYBin(), it = 0, ei = fCoord->GetLastYBin(); i < ei; ++i, ++it) {
1970 const Double_t yMin = yA->GetBinCenter(i) * yScale;
1971 const Double_t yMax = yA->GetBinCenter(i + 1) * yScale;
1972 const Double_t zMin = zA->GetBinCenter(j) * zScale;
1973 const Double_t zMax = zA->GetBinCenter(j + 1) * zScale;
1974 glBegin(GL_POLYGON);
1975 glTexCoord1d(fTexCoords[jt][it]);
1976 glVertex3d(pos, yMin, zMin);
1977 glTexCoord1d(fTexCoords[jt][it + 1]);
1978 glVertex3d(pos, yMax, zMin);
1979 glTexCoord1d(fTexCoords[jt + 1][it + 1]);
1980 glVertex3d(pos, yMax, zMax);
1981 glTexCoord1d(fTexCoords[jt + 1][it]);
1982 glVertex3d(pos, yMin, zMax);
1983 glEnd();
1984 }
1985 }
1986 break;
1987 case kXOY:
1988 pos *= zScale;
1989 for (Int_t j = fCoord->GetFirstXBin(), jt = 0, ej = fCoord->GetLastXBin(); j < ej; ++j, ++jt) {
1990 for (Int_t i = fCoord->GetFirstYBin(), it = 0, ei = fCoord->GetLastYBin(); i < ei; ++i, ++it) {
1991 const Double_t xMin = xA->GetBinCenter(j) * xScale;
1992 const Double_t xMax = xA->GetBinCenter(j + 1) * xScale;
1993 const Double_t yMin = yA->GetBinCenter(i) * yScale;
1994 const Double_t yMax = yA->GetBinCenter(i + 1) * yScale;
1995 glBegin(GL_POLYGON);
1996 glTexCoord1d(fTexCoords[jt + 1][it]);
1997 glVertex3d(xMax, yMin, pos);
1998 glTexCoord1d(fTexCoords[jt + 1][it + 1]);
1999 glVertex3d(xMax, yMax, pos);
2000 glTexCoord1d(fTexCoords[jt][it + 1]);
2001 glVertex3d(xMin, yMax, pos);
2002 glTexCoord1d(fTexCoords[jt][it]);
2003 glVertex3d(xMin, yMin, pos);
2004 glEnd();
2005 }
2006 }
2007 break;
2008 }
2009}
2010
2011namespace {
2012
2013////////////////////////////////////////////////////////////////////////////////
2014
2015void DrawBoxOutline(Double_t xMin, Double_t xMax, Double_t yMin,
2016 Double_t yMax, Double_t zMin, Double_t zMax)
2017{
2018 glBegin(GL_LINE_LOOP);
2019 glVertex3d(xMin, yMin, zMin);
2020 glVertex3d(xMax, yMin, zMin);
2021 glVertex3d(xMax, yMax, zMin);
2022 glVertex3d(xMin, yMax, zMin);
2023 glEnd();
2024
2025 glBegin(GL_LINE_LOOP);
2026 glVertex3d(xMin, yMin, zMax);
2027 glVertex3d(xMax, yMin, zMax);
2028 glVertex3d(xMax, yMax, zMax);
2029 glVertex3d(xMin, yMax, zMax);
2030 glEnd();
2031
2032 glBegin(GL_LINES);
2033 glVertex3d(xMin, yMin, zMin);
2034 glVertex3d(xMin, yMin, zMax);
2035 glVertex3d(xMax, yMin, zMin);
2036 glVertex3d(xMax, yMin, zMax);
2037 glVertex3d(xMax, yMax, zMin);
2038 glVertex3d(xMax, yMax, zMax);
2039 glVertex3d(xMin, yMax, zMin);
2040 glVertex3d(xMin, yMax, zMax);
2041 glEnd();
2042}
2043
2044}
2045
2046////////////////////////////////////////////////////////////////////////////////
2047/// Draw slice frame.
2048
2050{
2051 glColor3d(1., 0., 0.);
2052 const TGLVertex3 *box = fBox->Get3DBox();
2053
2054 switch (fAxisType) {
2055 case kXOZ:
2056 DrawBoxOutline(box[0].X(), box[1].X(),
2057 fAxis->GetBinLowEdge(low) * fCoord->GetYScale(),
2058 fAxis->GetBinUpEdge(up - 1) * fCoord->GetYScale(),
2059 box[0].Z(), box[4].Z());
2060 break;
2061 case kYOZ:
2062 DrawBoxOutline(fAxis->GetBinLowEdge(low) * fCoord->GetXScale(),
2063 fAxis->GetBinUpEdge(up - 1) * fCoord->GetXScale(),
2064 box[0].Y(), box[2].Y(),
2065 box[0].Z(), box[4].Z());
2066 break;
2067 case kXOY:
2068 DrawBoxOutline(box[0].X(), box[1].X(),
2069 box[0].Y(), box[2].Y(),
2070 fAxis->GetBinLowEdge(low) * fCoord->GetZScale(),
2071 fAxis->GetBinUpEdge(up - 1) * fCoord->GetZScale());
2072 break;
2073 }
2074}
2075
2076namespace Rgl {
2077
2078////////////////////////////////////////////////////////////////////////////////
2079
2081 : fPainter(painter)
2082{
2083 const TGLVertex3 *box = fPainter->fBackBox.Get3DBox();
2084 const Double_t center[] = {(box[0].X() + box[1].X()) / 2,
2085 (box[0].Y() + box[2].Y()) / 2,
2086 (box[0].Z() + box[4].Z()) / 2};
2087
2088 fPainter->SaveModelviewMatrix();
2089 glTranslated(-center[0], -center[1], -center[2]);
2090}
2091
2092////////////////////////////////////////////////////////////////////////////////
2093
2095{
2096 fPainter->RestoreModelviewMatrix();
2097}
2098
2099namespace
2100{
2101
2102const Double_t lr = 0.85;
2103const Double_t rr = 0.9;
2104
2105}
2106
2107////////////////////////////////////////////////////////////////////////////////
2108///Draw. Palette.
2109
2110void DrawPalette(const TGLPlotCamera * camera, const TGLLevelPalette & palette)
2111{
2112 const TGLDisableGuard light(GL_LIGHTING);
2113 const TGLDisableGuard depth(GL_DEPTH_TEST);
2114 const TGLEnableGuard blend(GL_BLEND);
2115
2116 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2117
2118 glMatrixMode(GL_PROJECTION);
2119 glLoadIdentity();
2120 glOrtho(0, camera->GetWidth(), 0, camera->GetHeight(), -1., 1.);
2121
2122 glMatrixMode(GL_MODELVIEW);
2123 glLoadIdentity();
2124
2125 const Double_t leftX = camera->GetWidth() * lr;
2126 const Double_t rightX = camera->GetWidth() * rr;
2127 const Double_t margin = 0.1 * camera->GetHeight();
2128 const Double_t h = (camera->GetHeight() * 0.8) / palette.GetPaletteSize();
2129
2130 for (Int_t i = 0, e = palette.GetPaletteSize(); i < e; ++i) {
2131 glBegin(GL_POLYGON);
2132 const UChar_t * color = palette.GetColour(i);
2133 glColor4ub(color[0], color[1], color[2], 150);
2134 glVertex2d(leftX, margin + i * h);
2135 glVertex2d(rightX, margin + i * h);
2136 glVertex2d(rightX, margin + (i + 1) * h);
2137 glVertex2d(leftX, margin + (i + 1) * h);
2138 glEnd();
2139 }
2140
2141 const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
2142 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
2143 glColor4d(0., 0., 0., 0.5);
2144
2145 for (Int_t i = 0, e = palette.GetPaletteSize(); i < e; ++i) {
2146 glBegin(GL_LINE_LOOP);
2147 glVertex2d(leftX, margin + i * h);
2148 glVertex2d(rightX, margin + i * h);
2149 glVertex2d(rightX, margin + (i + 1) * h);
2150 glVertex2d(leftX, margin + (i + 1) * h);
2151 glEnd();
2152 }
2153
2154}
2155
2156////////////////////////////////////////////////////////////////////////////////
2157///Draw. Palette.
2158
2159void DrawPalette(const TGLPlotCamera * camera, const TGLLevelPalette & palette,
2160 const std::vector<Double_t> & levels)
2161{
2162 const TGLDisableGuard light(GL_LIGHTING);
2163 const TGLDisableGuard depth(GL_DEPTH_TEST);
2164 const TGLEnableGuard blend(GL_BLEND);
2165
2166 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2167
2168 glMatrixMode(GL_PROJECTION);
2169 glLoadIdentity();
2170 glOrtho(0, camera->GetWidth(), 0, camera->GetHeight(), -1., 1.);
2171
2172 glMatrixMode(GL_MODELVIEW);
2173 glLoadIdentity();
2174
2175 const Double_t leftX = camera->GetWidth() * lr;
2176 const Double_t rightX = camera->GetWidth() * rr;
2177 const Double_t margin = 0.1 * camera->GetHeight();
2178 const Double_t h = (camera->GetHeight() * 0.8);
2179 const Double_t range = levels.back() - levels.front();
2180
2181 const UChar_t opacity = 200;
2182
2183 for (Int_t i = 0, e = palette.GetPaletteSize(); i < e; ++i) {
2184 const Double_t yMin = margin + (levels[i] - levels.front()) / range * h;
2185 const Double_t yMax = margin + (levels[i + 1] - levels.front()) / range * h;
2186 glBegin(GL_POLYGON);
2187 const UChar_t * color = palette.GetColour(i);
2188 glColor4ub(color[0], color[1], color[2], opacity);
2189 glVertex2d(leftX, yMin);
2190 glVertex2d(rightX, yMin);
2191 glVertex2d(rightX, yMax);
2192 glVertex2d(leftX, yMax);
2193 glEnd();
2194 }
2195
2196 const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
2197 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
2198 glColor4d(0., 0., 0., 0.5);
2199
2200 for (Int_t i = 0, e = palette.GetPaletteSize(); i < e; ++i) {
2201 const Double_t yMin = (levels[i] - levels.front()) / range * h;
2202 const Double_t yMax = (levels[i + 1] - levels.front()) / range * h;
2203
2204 glBegin(GL_LINE_LOOP);
2205 glVertex2d(leftX, margin + yMin);
2206 glVertex2d(rightX, margin + yMin);
2207 glVertex2d(rightX, margin + yMax);
2208 glVertex2d(leftX, margin + yMax);
2209 glEnd();
2210 }
2211
2212}
2213
2214////////////////////////////////////////////////////////////////////////////////
2215
2216void DrawPaletteAxis(const TGLPlotCamera * camera, const Range_t & minMax, Bool_t logZ)
2217{
2218 UInt_t pixelW = camera->GetWidth();
2219 UInt_t pixelH = camera->GetHeight();
2220
2223 if (scale > 1.) {
2224 pixelW = UInt_t(pixelW / scale);
2225 pixelH = UInt_t(pixelH / scale);
2226 }
2227
2228 const Double_t x = gPad->AbsPixeltoX(Int_t(gPad->GetXlowNDC() * gPad->GetWw() + rr * pixelW));
2229 const Double_t yMin = gPad->AbsPixeltoY(Int_t(gPad->GetWh() - (pixelH * 0.1
2230 + gPad->GetYlowNDC() * gPad->GetWh())));
2231 const Double_t yMax = gPad->AbsPixeltoY(Int_t(gPad->GetWh() - (pixelH * 0.9
2232 + gPad->GetYlowNDC() * gPad->GetWh())));
2233
2234 Double_t zMin = minMax.first;
2235 Double_t zMax = minMax.second;
2236
2237 if (logZ) {
2238 zMin = TMath::Power(10, zMin);
2239 zMax = TMath::Power(10, zMax);
2240 }
2241
2242 //Now, some stupid magic, to force ROOT's painting machine work as I want, not as it wants.
2243 const Bool_t logX = gPad->GetLogx();
2244 gPad->SetLogx(kFALSE);
2245 const Bool_t logY = gPad->GetLogy();
2246 gPad->SetLogy(kFALSE);
2247
2248 TGaxis axisPainter(x, yMin, x, yMax, zMin, zMax, 510, logZ ? "G" : "");
2249 axisPainter.Paint();
2250
2251 gPad->SetLogx(logX);
2252 gPad->SetLogy(logY);
2253}
2254
2255//Constant for TGLH2PolyPainter.
2257
2258}
2259
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
unsigned short UShort_t
Unsigned Short integer 2 bytes (unsigned short).
Definition RtypesCore.h:54
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
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
float Float_t
Float 4 bytes (float).
Definition RtypesCore.h:71
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
#define X(type, name)
Error("WriteTObject","The current directory (%s) is not associated with a file. The object (%s) has not been written.", GetName(), objname)
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
EGLCoordType
Definition TGLUtil.h:43
@ kGLSpherical
Definition TGLUtil.h:47
@ kGLCylindrical
Definition TGLUtil.h:46
@ kGLPolar
Definition TGLUtil.h:45
@ kGLCartesian
Definition TGLUtil.h:44
char name[80]
Definition TGX11.cxx:148
externTVirtualMutex * gROOTMutex
Definition TROOT.h:63
externTStyle * gStyle
Definition TStyle.h:442
#define R__LOCKGUARD(mutex)
externTVirtualPS * gVirtualPS
Definition TVirtualPS.h:88
#define gPad
const TGLPlotPainter * fPainter
PlotTranslation(const TGLPlotPainter *painter)
Class to manage histogram axis.
Definition TAxis.h:32
Bool_t IsVariableBinSize() const
Definition TAxis.h:144
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:482
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:522
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:422
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:473
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:546
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:462
virtual Int_t GetEntries() const
Definition TF3.h:28
void MoveBox(Int_t px, Int_t py, Int_t axisID)
Move box cut along selected direction.
void AdjustBox()
Box cut is limited by plot's sizes.
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.
Double_t fYLength
Rgl::Range_t fYRange
void DrawBox(Bool_t selectionPass, Int_t selected) const
Draw cut as a semi-transparent box.
void TurnOnOff()
Turn the box cut on/off.
Double_t fXLength
TPoint fMousePos
Bool_t fActive
const TGLPlotBox *const fPlotBox
void StartMovement(Int_t px, Int_t py)
Start cut's movement.
TGLVertex3 fCenter
Double_t fFactor
Double_t fZLength
Rgl::Range_t fZRange
virtual ~TGLBoxCut()
Destructor.
void SetActive(Bool_t a)
Turn the box cut on/off.
void ResetBoxGeometry()
Set geometry using plot's back box.
TGLBoxCut(const TGLPlotBox *plotBox)
Constructor.
Rgl::Range_t fXRange
const UChar_t * GetColour(Double_t z) const
Get color.
Definition TGLUtil.cxx:4290
Int_t GetPaletteSize() const
Get. Palette. Size.
Definition TGLUtil.cxx:4253
static void CloseEmbeddedPS()
this function used by gl-in-pad Restore the gVirtualPS output stream
static void StartEmbeddedPS()
this function used by gl-in-pad
Implementation of a box around a histogram/function for plot-painters.
Definition TGLPlotBox.h:26
Camera for TGLPlotPainter and sub-classes.
Int_t GetWidth() const
viewport[2]
Int_t GetHeight() const
viewport[3]
Helper class for plot-painters holding information about axis ranges, numbers of bins and flags if ce...
Double_t GetZLength() const
Z length.
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.
const Rgl::Range_t & GetXRangeScaled() const
Scaled range.
Rgl::BinRange_t fZBins
const Rgl::BinRange_t & GetZBins() const
Z bins range.
Rgl::Range_t fZRangeScaled
Bool_t GetXLog() const
Get X log.
const Rgl::BinRange_t & GetXBins() const
X bins range.
const Rgl::Range_t & GetZRange() const
Z range.
virtual ~TGLPlotCoordinates()
Destructor.
EGLCoordType fCoordType
Bool_t SetRangesPolar(const TH1 *hist)
Set bin ranges, ranges, etc.
const Rgl::Range_t & GetYRangeScaled() const
Scaled range.
Bool_t SetRangesCartesian(const TH1 *hist, Bool_t errors=kFALSE, Bool_t zBins=kFALSE)
Set bin ranges, ranges, etc.
void SetCoordType(EGLCoordType type)
If coord type was changed, plot must reset sections (if any), set fModified.
void ResetModified()
Reset modified.
TGLPlotCoordinates()
Constructor.
Bool_t SetRangesCylindrical(const TH1 *hist)
Set ranges cylindrical.
Bool_t GetYLog() const
Get Y log.
Bool_t GetZLog() const
Get Z log.
Bool_t Modified() const
Modified.
Int_t GetNXBins() const
Number of X bins.
const Rgl::Range_t & GetZRangeScaled() const
Scaled range.
const Rgl::Range_t & GetYRange() const
Y range.
Rgl::BinRange_t fXBins
Double_t GetXLength() const
X length.
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.
Bool_t SetRangesSpherical(const TH1 *hist)
Set ranges spherical.
Rgl::BinRange_t fYBins
const Rgl::Range_t & GetXRange() const
X range.
Int_t GetNYBins() const
Number of Y bins.
Rgl::Range_t fYRangeScaled
EGLCoordType GetCoordType() const
Get coordinates type.
Rgl::Range_t fXRangeScaled
const Rgl::BinRange_t & GetYBins() const
Y bins range.
Int_t GetNZBins() const
Number of Z bins.
Double_t GetYLength() const
Y length.
Double_t GetFactor() const
Get factor.
Base class for plot-painters that provide GL rendering of various 2D and 3D histograms,...
void InvalidateSelection()
Selection must be updated.
void DrawSections() const
Draw sections (if any).
const Float_t * fPhysicalShapeColor
TGLPlotPainter(TH1 *hist, TGLPlotCamera *camera, TGLPlotCoordinates *coord, Bool_t xoySelectable, Bool_t xozSelectable, Bool_t yozSelectable)
TGLPlotPainter's ctor.
std::vector< Double_t > fZLevels
virtual void SetFrameColor(const TColor *frameColor)
Set plot's back box color.
TGLSelectionBuffer fSelection
Double_t fXOYSectionPos
void RestoreModelviewMatrix() const
virtual void DrawPaletteAxis() const
Draw. Palette. Axis.
const TColor * fPadColor
void SetPadColor(const TColor *color)
Used in a pad.
const TColor * GetPadColor() const
Get pad color.
Double_t fXOZSectionPos
virtual void DrawPlot() const =0
void PrintPlot() const
Generate PS using gl2ps.
virtual void InitGL() const =0
TGLPlotCoordinates * fCoord
void Paint() override
Draw lego/surf/whatever you can.
virtual void DrawSectionXOY() const =0
TGLPlotBox fBackBox
Bool_t PlotSelected(Int_t px, Int_t py) override
Read color buffer content to find selected object.
void SaveProjectionMatrix() const
virtual void DrawSectionYOZ() const =0
void SaveModelviewMatrix() const
void MoveSection(Int_t px, Int_t py)
Create dynamic profile using selected plane.
TGLPlotCamera * fCamera
virtual void DeInitGL() const =0
void RestoreProjectionMatrix() const
virtual void ClearBuffers() const
Double_t fYOZSectionPos
virtual void DrawSectionXOZ() const =0
void FindMinMax(Int_t sliceBegin, Int_t sliceEnd) const
Find minimum and maximum for slice.
Rgl::Range_t fMinMax
void DrawSliceFrame(Int_t low, Int_t up) const
Draw slice frame.
const TH3 * fHist
Bool_t PreparePalette() const
Initialize color palette.
const TAxis * fAxis
ESliceAxis fAxisType
const TGLPlotCoordinates * fCoord
void PrepareTexCoords(Double_t pos, Int_t sliceBegin, Int_t sliceEnd) const
Prepare TexCoords.
void DrawSlice(Double_t pos) const
Draw slice.
TGLLevelPalette fPalette
TGLTH3Slice(const TString &sliceName, const TH3 *hist, const TGLPlotCoordinates *coord, const TGLPlotBox *box, ESliceAxis axis)
Constructor.
void SetSliceWidth(Int_t width=1)
Set Slice width.
const TGLPlotBox * fBox
void DrawSliceTextured(Double_t pos) const
Draw slice textured.
const TF3 * fF3
TGL2DArray< Double_t > fTexCoords
static void InitializeIfNeeded()
Initialize globals that require other libraries to be initialized.
Definition TGLUtil.cxx:1573
static Float_t GetScreenScalingFactor()
Returns scaling factor between screen points and GL viewport pixels.
Definition TGLUtil.cxx:1843
3 component (x/y/z) vector class.
Definition TGLUtil.h:248
3 component (x/y/z) vertex class.
Definition TGLUtil.h:84
Double_t X() const
Definition TGLUtil.h:119
Double_t Z() const
Definition TGLUtil.h:123
Double_t Y() const
Definition TGLUtil.h:121
void Paint(Option_t *chopt="") override
This method must be overridden if a class wants to paint itself.
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:75
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
TAxis * GetZaxis()
Definition TH1.h:573
virtual Double_t GetMinimumStored() const
Definition TH1.h:537
virtual Double_t GetNormFactor() const
Definition TH1.h:545
TAxis * GetXaxis()
Definition TH1.h:571
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:5041
TAxis * GetYaxis()
Definition TH1.h:572
virtual Double_t GetCellError(Int_t binx, Int_t biny) const
Definition TH1.h:684
virtual Double_t GetMaximumStored() const
Definition TH1.h:533
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5143
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
TList * GetBins()
Returns the TList of all bins in the histogram.
Definition TH2Poly.h:100
Double_t GetMinimum() const
Returns the minimum value of the histogram.
Definition TH2Poly.cxx:962
Double_t GetMaximum() const
Returns the maximum value of the histogram.
Definition TH2Poly.cxx:914
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:45
A doubly linked list.
Definition TList.h:38
TNamed()
Definition TNamed.h:38
Basic string class.
Definition TString.h:138
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
void DrawQuadFilled(const TGLVertex3 &v0, const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3, const TGLVector3 &normal)
Draw quad face.
Definition TGLUtil.cxx:2952
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
const Float_t gBlueEmission[]
Definition TGLUtil.cxx:2842
void DrawPalette(const TGLPlotCamera *camera, const TGLLevelPalette &palette)
Draw. Palette.
void DrawPaletteAxis(const TGLPlotCamera *camera, const Range_t &minMax, Bool_t logZ)
std::pair< Int_t, Int_t > BinRange_t
Definition TGLUtil.h:1201
std::pair< Double_t, Double_t > Range_t
Definition TGLUtil.h:1202
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 Double_t gH2PolyScaleXY
Int_t ColorToObjectID(const UChar_t *color, Bool_t highColor)
Definition TGLUtil.cxx:2916
void DrawAxes(Int_t frontPoint, const Int_t *viewport, const TGLVertex3 *box2D, const TGLPlotCoordinates *plotCoord, TAxis *xAxis, TAxis *yAxis, TAxis *zAxis)
Using front point, find, where to draw axes and which labels to use for them gVirtualX->SelectWindow(...
Definition TGLUtil.cxx:3758
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:732
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:773