Logo ROOT  
Reference Guide
TGLSurfacePainter.cxx
Go to the documentation of this file.
1// @(#)root/gl:$Id$
2// Author: Timur Pocheptsov 31/08/2006
3
4/*************************************************************************
5 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <algorithm>
13#include "Riostream.h"
14#include <cstdlib>
15#include <cctype>
16
17#include "TVirtualPad.h"
18#include "KeySymbols.h"
19#include "TVirtualGL.h"
20#include "TVirtualX.h"
21#include "Buttons.h"
22#include "TString.h"
23#include "TStyle.h"
24#include "TGaxis.h"
25#include "TColor.h"
26#include "TROOT.h"
27#include "TMath.h"
28#include "TAxis.h"
29#include "TH1.h"
30#include "TRandom.h"
31
32#include "TGLSurfacePainter.h"
33#include "TGLPlotCamera.h"
34#include "TGLIncludes.h"
35
36/** \class TGLSurfacePainter
37\ingroup opengl
38Implements painting of TH2 with "SURF" option.
39*/
40
42
44
45////////////////////////////////////////////////////////////////////////////////
46/// Constructor.
47
49{
50 fRGBA[0] = rhs.fRGBA[0], fRGBA[1] = rhs.fRGBA[1], fRGBA[2] = rhs.fRGBA[2], fRGBA[3] = rhs.fRGBA[3];
51 fVertices.swap(rhs.fVertices);
52}
53
54////////////////////////////////////////////////////////////////////////////////
55/// Constructor.
56
58 : TGLPlotPainter(hist, camera, coord, kTRUE, kTRUE, kTRUE),
59 fType(kSurf),
62{
63}
64
65////////////////////////////////////////////////////////////////////////////////
66///Coords for point on surface under cursor.
67
69{
70 static char null[] = { "" };
71 if (fSelectedPart) {
72 if (fHighColor)
73 return fSelectedPart < fSelectionBase ? (char *)"TF2" : (char *)"Switch to true-color mode to obtain correct info";
74 return fSelectedPart < fSelectionBase ? (char *)"TF2" : WindowPointTo3DPoint(px, py);
75 }
76 return null;
77}
78
79////////////////////////////////////////////////////////////////////////////////
80///Set mesh, normals.
81
83{
84 Bool_t ret = kFALSE;
85 switch (fCoord->GetCoordType()) {
86 case kGLCartesian:
87 ret = InitGeometryCartesian(); break;
88 case kGLPolar:
89 ret = InitGeometryPolar(); break;
90 case kGLCylindrical:
91 ret = InitGeometryCylindrical(); break;
92 case kGLSpherical:
93 ret = InitGeometrySpherical(); break;
94 default:
95 return kFALSE;
96 }
98 return ret;
99}
100
101////////////////////////////////////////////////////////////////////////////////
102///User clicks right mouse button (in a pad).
103
105{
106 fMousePosition.fX = px;
108 fCamera->StartPan(px, py);
110}
111
112////////////////////////////////////////////////////////////////////////////////
113///User's moving mouse cursor, with middle mouse button pressed (for pad).
114///Calculate 3d shift related to 2d mouse movement.
115
117{
118 if (fSelectedPart >= fSelectionBase) {//Pan camera.
121
124 fCamera->Pan(px, py);
125
128 } else if (fSelectedPart > 0) {
129 //Convert py into bottom-top orientation.
130 py = fCamera->GetHeight() - py;
131
134
137
138
139 if (!fHighColor) {
142 else
143 MoveSection(px, py);
144 }
145 else
146 MoveSection(px, py);
147
150 }
151
154}
155
156////////////////////////////////////////////////////////////////////////////////
157///Additional options for surfaces.
158
160{
161 using namespace std;
162 const Ssiz_t surfPos = option.Index("surf");//"surf" _already_ _exists_ in a string.
163 if (surfPos + 4 < option.Length() && isdigit(option[surfPos + 4])) {
164 switch (option[surfPos + 4] - '0') {
165 case 1:
166 fType = kSurf1;
167 break;
168 case 2:
169 fType = kSurf2;
170 break;
171 case 3:
172 fType = kSurf3;
174 break;
175 case 4:
176 fType = kSurf4;
177 break;
178 case 5:
180 fType = kSurf3;
181 else
182 fType = kSurf5;
183 break;
184 default:
185 fType = kSurf;
186 }
187 } else
188 fType = kSurf;
189
190 option.Index("z") == kNPOS ? fDrawPalette = kFALSE : fDrawPalette = kTRUE;
191}
192
193////////////////////////////////////////////////////////////////////////////////
194///Remove all profiles/sections.
195
197{
198 const TGLVertex3 *frame = fBackBox.Get3DBox();
199 if (py == kKey_P || py == kKey_p) {
200
201 if (HasSections()) {
206 fXOZSectionPos = frame[0].Y();
207 fYOZSectionPos = frame[0].X();
208 fXOYSectionPos = frame[0].Z();
210 }
211 } else if (event == kButton1Double && (HasSections() || HasProjections() || fBoxCut.IsActive())) {
212 fXOZSectionPos = frame[0].Y();
213 fYOZSectionPos = frame[0].X();
214 fXOYSectionPos = frame[0].Z();
215 fXOZProj.clear();
216 fYOZProj.clear();
217 fXOYProj.clear();
218 if (fBoxCut.IsActive())
220 if (!gVirtualX->IsCmdThread())
221 gROOT->ProcessLineFast(Form("((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)this));
222 else
223 Paint();
224 } else if (event == kKeyPress && (py == kKey_c || py == kKey_C)) {
225 if (fHighColor)
226 Info("ProcessEvent", "Switch to true color to use box cut");
227 else {
230 }
231 }
232}
233
234////////////////////////////////////////////////////////////////////////////////
235///Initialize some OpenGL state variables.
236
238{
239 glEnable(GL_LIGHTING);
240 glEnable(GL_LIGHT0);
241 glEnable(GL_DEPTH_TEST);
242 glDisable(GL_CULL_FACE);
243 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
244}
245
246////////////////////////////////////////////////////////////////////////////////
247///Initialize some OpenGL state variables.
248
250{
251 glDisable(GL_LIGHTING);
252 glDisable(GL_LIGHT0);
253 glDisable(GL_DEPTH_TEST);
254 glDisable(GL_CULL_FACE);
255 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
256}
257
258
259////////////////////////////////////////////////////////////////////////////////
260///One normal per vertex;
261///this normal is average of
262///neighbouring triangles normals.
263
265{
266 const Int_t nX = fCoord->GetNXBins();
267 const Int_t nY = fCoord->GetNYBins();
268
269 fFaceNormals.resize((nX + 1) * (nY + 1));
270 fFaceNormals.assign(fFaceNormals.size(), std::pair<TGLVector3, TGLVector3>());
271 fFaceNormals.SetRowLen(nY + 1);
272
273
274 //first, calculate normal for each triangle face
275 for (Int_t i = 0; i < nX - 1; ++i) {
276 for (Int_t j = 0; j < nY - 1; ++j) {
277 //first "bottom-left" triangle
278 TMath::Normal2Plane(fMesh[i][j + 1].CArr(), fMesh[i][j].CArr(), fMesh[i + 1][j].CArr(),
279 fFaceNormals[i + 1][j + 1].first.Arr());
280 //second "top-right" triangle
281 TMath::Normal2Plane(fMesh[i + 1][j].CArr(), fMesh[i + 1][j + 1].CArr(), fMesh[i][j + 1].CArr(),
282 fFaceNormals[i + 1][j + 1].second.Arr());
283 }
284 }
285
286 fAverageNormals.resize(nX * nY);
288
290 //second, calculate average normal for each vertex
291 for (Int_t i = 0; i < nX; ++i) {
292 for (Int_t j = 0; j < nY; ++j) {
293 TGLVector3 &norm = fAverageNormals[i][j];
294
295 norm += fFaceNormals[i][j].second;
296 norm += fFaceNormals[i][j + 1].first;
297 norm += fFaceNormals[i][j + 1].second;
298 norm += fFaceNormals[i + 1][j].first;
299 norm += fFaceNormals[i + 1][j].second;
300 norm += fFaceNormals[i + 1][j + 1].first;
301
302 if (!norm.X() && !norm.Y() && !norm.Z())
303 continue;
304
305 norm.Normalise();
306 }
307 }
308}
309
310////////////////////////////////////////////////////////////////////////////////
311///Set color for surface.
312
314{
315 Float_t diffColor[] = {0.8f, 0.8f, 0.8f, 0.35f};
316
317 if (fHist->GetFillColor() != kWhite && fType != kSurf1 && fType != kSurf2 && fType != kSurf5)
318 if (const TColor *c = gROOT->GetColor(fHist->GetFillColor()))
319 c->GetRGB(diffColor[0], diffColor[1], diffColor[2]);
320
321 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffColor);
322 const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
323 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
324 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
325}
326
327////////////////////////////////////////////////////////////////////////////////
328///Draw surf/surf1/surf2/surf4
329
331{
332 //Shift plot to point of origin.
333 const Rgl::PlotTranslation trGuard(this);
334
335 if (fCoord->GetCoordType() == kGLCartesian) {
337 DrawSections();
338 if (!fSelectionPass)
340 }
341
342 if (!fSelectionPass) {
344 glEnable(GL_POLYGON_OFFSET_FILL);
345 glPolygonOffset(1.f, 1.f);
346
347 if (HasSections() || HasProjections())
348 {
349 //Surface is semi-transparent during dynamic profiling
350 glEnable(GL_BLEND);
351 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
352 }
353
354 }
355
356 if (Textured() && !fSelectionPass) {
357 if (!PreparePalette()) {
358 fType = kSurf;
360 }
361 else if (fType != kSurf3)
362 fPalette.EnableTexture(GL_MODULATE);
363 }
364
365 const Int_t nX = fCoord->GetNXBins();
366 const Int_t nY = fCoord->GetNYBins();
367 const Int_t frontPoint = fBackBox.GetFrontPoint();
368 Int_t i = 0, firstJ = 0;
369 const Int_t addI = frontPoint == 2 || frontPoint == 1 ? i = 0, 1 : (i = nX - 2, -1);
370 const Int_t addJ = frontPoint == 2 || frontPoint == 3 ? firstJ = 0, 1 : (firstJ = nY - 2, -1);
371
374
375 for (; addI > 0 ? i < nX - 1 : i >= 0; i += addI) {
376 for (Int_t j = firstJ; addJ > 0 ? j < nY - 1 : j >= 0; j += addJ) {
377 Int_t triNumber = 2 * i * (nY - 1) + j * 2 + fSelectionBase;
378
379 Double_t xMin = TMath::Min(TMath::Min(fMesh[i][j + 1].X(), fMesh[i][j].X()), fMesh[i + 1][j].X());
380 Double_t xMax = TMath::Max(TMath::Max(fMesh[i][j + 1].X(), fMesh[i][j].X()), fMesh[i + 1][j].X());
381 Double_t yMin = TMath::Min(TMath::Min(fMesh[i][j + 1].Y(), fMesh[i][j].Y()), fMesh[i + 1][j].Y());
382 Double_t yMax = TMath::Max(TMath::Max(fMesh[i][j + 1].Y(), fMesh[i][j].Y()), fMesh[i + 1][j].Y());
383 Double_t zMin = TMath::Min(TMath::Min(fMesh[i][j + 1].Z(), fMesh[i][j].Z()), fMesh[i + 1][j].Z());
384 Double_t zMax = TMath::Max(TMath::Max(fMesh[i][j + 1].Z(), fMesh[i][j].Z()), fMesh[i + 1][j].Z());
385
386 if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
387 continue;
388
390 Rgl::ObjectIDToColor(triNumber, kFALSE);
391
392 if ((fType == kSurf1 || fType == kSurf2 || fType == kSurf5) && !fSelectionPass)
393 Rgl::DrawFaceTextured(fMesh[i][j + 1], fMesh[i][j], fMesh[i + 1][j],
394 fTexMap[i][j + 1], fTexMap[i][j], fTexMap[i + 1][j],
395 fAverageNormals[i][j + 1], fAverageNormals[i][j],
396 fAverageNormals[i + 1][j]);
397 else
398 Rgl::DrawSmoothFace(fMesh[i][j + 1], fMesh[i][j], fMesh[i + 1][j],
399 fAverageNormals[i][j + 1], fAverageNormals[i][j],
400 fAverageNormals[i + 1][j]);
401
402 ++triNumber;
403
405 Rgl::ObjectIDToColor(triNumber, kFALSE);
406
407 if ((fType == kSurf1 || fType == kSurf2 || fType == kSurf5) && !fSelectionPass)
408 Rgl::DrawFaceTextured(fMesh[i + 1][j], fMesh[i + 1][j + 1], fMesh[i][j + 1],
409 fTexMap[i + 1][j], fTexMap[i + 1][j + 1], fTexMap[i][j + 1],
410 fAverageNormals[i + 1][j], fAverageNormals[i + 1][j + 1],
411 fAverageNormals[i][j + 1]);
412 else
413 Rgl::DrawSmoothFace(fMesh[i + 1][j], fMesh[i + 1][j + 1], fMesh[i][j + 1],
414 fAverageNormals[i + 1][j], fAverageNormals[i + 1][j + 1],
415 fAverageNormals[i][j + 1]);
416 }
417 }
418
419 if (!fSelectionPass)
420 glDisable(GL_POLYGON_OFFSET_FILL);
421
422 if (fBoxCut.IsActive())
424
425 if (fType != kSurf3 && Textured() && !fSelectionPass)
427
428 //Draw outlines here
429 if (!fSelectionPass) {
430 const TGLEnableGuard blendGuard(GL_BLEND);
431
432 if (fType == kSurf || fType == kSurf1 || fType == kSurf3) {
433 const TGLDisableGuard lightGuard(GL_LIGHTING);
434 const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
435
436 glDepthMask(GL_FALSE);
437
438 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
439 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
440
441 glColor4d(0., 0., 0., 0.5);
442
443 for (i = 0; i < nX - 1; ++i) {
444 for (Int_t j = 0; j < nY - 1; ++j) {
445 Rgl::DrawQuadOutline(fMesh[i][j + 1], fMesh[i][j], fMesh[i + 1][j], fMesh[i + 1][j + 1]);
446 }
447 }
448
449 glDepthMask(GL_TRUE);
450 }
451 }
452
453 if (fType == kSurf3 && !fSelectionPass) {
454 fPalette.EnableTexture(GL_MODULATE);
455 const TGLEnableGuard blend(GL_BLEND);
456 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
459 }
460
461 if (!fSelectionPass && fSelectedPart > 6) {
462 //Draw red outline for surface.
463 const TGLDisableGuard lightGuard(GL_LIGHTING);
464 const TGLEnableGuard blendGuard(GL_BLEND);
465 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
466 const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
467 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
468 glLineWidth(3.f);
469
470 glColor4d(1.f, 0.f, 0.4f, 0.6f);
471 glBegin(GL_LINE_STRIP);
472 for (i = 0; i < nX; ++i)
473 glVertex3dv(fMesh[i][0].CArr());
474 for (Int_t j = 0; j < nY; ++j)
475 glVertex3dv(fMesh[nX - 1][j].CArr());
476 for (i = nX - 1; i >= 0; --i)
477 glVertex3dv(fMesh[i][nY - 1].CArr());
478 for (Int_t j = nY - 1; j >= 0; --j)
479 glVertex3dv(fMesh[0][j].CArr());
480 glEnd();
481 glLineWidth(1.f);
482 }
483
485 DrawPalette();
486}
487
488////////////////////////////////////////////////////////////////////////////////
489///Find bin ranges for X and Y axes,
490///axes ranges for X, Y and Z.
491///Function returns false, if logarithmic scale for
492///some axis was requested, but we cannot
493///find correct range.
494
496{
497 if (!fCoord->SetRanges(fHist, kFALSE, kFALSE)) //the second arg must be drawErrors, the third is always kFALSE.
498 return kFALSE;
499
501 //Set surface's mesh
502 //Calculates table of X and Y for lego (Z is obtained during drawing) or
503 //calculate mesh of triangles with vertices in the centres of bins
504 const Int_t nX = fCoord->GetNXBins();
505 const Int_t nY = fCoord->GetNYBins();
506
507 fMesh.resize(nX * nY);
508 fMesh.SetRowLen(nY);
509
510 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
511 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
513 : fMesh[i][j].X() = fXAxis->GetBinCenter(ir) * fCoord->GetXScale();
515 : fMesh[i][j].Y() = fYAxis->GetBinCenter(jr) * fCoord->GetYScale();
516
517 Double_t z = fHist->GetBinContent(ir, jr);
518 ClampZ(z);
519 fMesh[i][j].Z() = z;
520 }
521 }
522
523 if (Textured()) {
525 fMinMaxVal.second = fMinMaxVal.first;
526
527 for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
528 for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
529 const Double_t val = fHist->GetBinContent(i, j);
530 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, val);
531 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
532 }
533 }
534
535 ClampZ(fMinMaxVal.first);
536 ClampZ(fMinMaxVal.second);
537
539 }
540
541 SetNormals();
542
543 if (fCoord->Modified()) {
545 const TGLVertex3 &vertex = fBackBox.Get3DBox()[0];
551 }
552
553 return kTRUE;
554}
555
556////////////////////////////////////////////////////////////////////////////////
557///Find bin ranges for X and Y axes,
558///axes ranges for X, Y and Z.
559///Function returns false, if logarithmic scale for
560///some axis was requested, but we cannot
561///find correct range.
562
564{
566 return kFALSE;
567
569
570 if (fCoord->Modified()) {
572 const TGLVertex3 &vertex = fBackBox.Get3DBox()[0];
577 }
578
579 const Int_t nY = fCoord->GetNYBins();
580 const Int_t nX = fCoord->GetNXBins();
581
582 fMesh.resize(nX * nY);
583 fMesh.SetRowLen(nY);
584
585 const Double_t fullAngle = fXAxis->GetBinCenter(fXAxis->GetNbins()) - fXAxis->GetBinCenter(1);
586 const Double_t phiLow = fXAxis->GetBinCenter(1);
588
589 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
590 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
591 const Double_t angle = (fXAxis->GetBinCenter(ir) - phiLow) / fullAngle * TMath::TwoPi();
592 const Double_t radius = ((fYAxis->GetBinCenter(jr)) - fYAxis->GetBinCenter(1)) /
593 rRange * fCoord->GetYScale();
594 fMesh[i][j].X() = radius * TMath::Cos(angle);
595 fMesh[i][j].Y() = radius * TMath::Sin(angle);
596 Double_t z = fHist->GetBinContent(ir, jr);
597 ClampZ(z);
598 fMesh[i][j].Z() = z;
599 }
600 }
601
602 SetNormals();
603
604 if (Textured()) {
606 fMinMaxVal.second = fMinMaxVal.first;
607
608 for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
609 for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
610 const Double_t val = fHist->GetBinContent(i, j);
611 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, val);
612 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
613 }
614 }
615
617 }
618
619
620 return kTRUE;
621}
622
623////////////////////////////////////////////////////////////////////////////////
624///Find bin ranges for X and Y axes,
625///axes ranges for X, Y and Z.
626///Function returns false, if logarithmic scale for
627///some axis was requested, but we cannot
628///find correct range.
629
631{
633 return kFALSE;
634
636
637 if (fCoord->Modified()) {
639 const TGLVertex3 &vertex = fBackBox.Get3DBox()[0];
644 }
645
646 const Int_t nY = fCoord->GetNYBins();
647 const Int_t nX = fCoord->GetNXBins();
648 fMesh.resize(nX * nY);
649 fMesh.SetRowLen(nY);
650
651 Double_t legoR = gStyle->GetLegoInnerR();
652 if (legoR > 1. || legoR < 0.)
653 legoR = 0.5;
654 const Double_t rRange = fCoord->GetZLength();
655 const Double_t sc = (1 - legoR) * fCoord->GetXScale();
656 legoR *= fCoord->GetXScale();
657
658 const Double_t fullAngle = fXAxis->GetBinCenter(fXAxis->GetNbins()) - fXAxis->GetBinCenter(1);
659 const Double_t phiLow = fXAxis->GetBinCenter(1);
660 Double_t angle = 0.;
661
662 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
663 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
664 angle = (fXAxis->GetBinLowEdge(ir) - phiLow) / fullAngle * TMath::TwoPi();
665 Double_t r = fType != kSurf5 ? legoR + (fHist->GetBinContent(ir, jr) - fCoord->GetZRange().first) / rRange * sc : legoR;
666 fMesh[i][j].X() = r * TMath::Cos(angle);
667 fMesh[i][j].Y() = fCoord->GetYLog() ?
669 :
671 fMesh[i][j].Z() = r * TMath::Sin(angle);
672 }
673 }
674
675 if (Textured()) {
677 fMinMaxVal.second = fMinMaxVal.first;
678
679 for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
680 for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
681 const Double_t val = fHist->GetBinContent(i, j);
682 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, val);
683 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
684 }
685 }
686
688 }
689
690
691 SetNormals();
692
693 return kTRUE;
694}
695
696////////////////////////////////////////////////////////////////////////////////
697///Find bin ranges for X and Y axes,
698///axes ranges for X, Y and Z.
699///Function returns false, if logarithmic scale for
700///some axis was requested, but we cannot
701///find correct range.
702
704{
706 return kFALSE;
707
709
710 if (fCoord->Modified()) {
712 const TGLVertex3 &vertex = fBackBox.Get3DBox()[0];
717 }
718
719 const Int_t nY = fCoord->GetNYBins();
720 const Int_t nX = fCoord->GetNXBins();
721 fMesh.resize(nX * nY);
722 fMesh.SetRowLen(nY);
723
724 Double_t legoR = gStyle->GetLegoInnerR();
725 if (legoR > 1. || legoR < 0.)
726 legoR = 0.5;
727 const Double_t rRange = fCoord->GetZLength();
728 const Double_t sc = (1 - legoR) * fCoord->GetXScale();
729 legoR *= fCoord->GetXScale();
730
731 //0 <= theta <= 2 * pi
732 const Double_t fullTheta = fXAxis->GetBinCenter(fXAxis->GetNbins()) - fXAxis->GetBinCenter(1);
733 const Double_t thetaLow = fXAxis->GetBinCenter(1);
734 //0 <= phi <= pi
735 const Double_t fullPhi = fYAxis->GetBinCenter(fYAxis->GetNbins()) - fYAxis->GetBinCenter(1);
736 const Double_t phiLow = fYAxis->GetBinCenter(1);
737
738 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
739
740 const Double_t theta = (fXAxis->GetBinCenter(ir) - thetaLow) / fullTheta * TMath::TwoPi();
741
742 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
743
744 const Double_t phi = (fYAxis->GetBinCenter(jr) - phiLow) / fullPhi * TMath::Pi();
745 const Double_t r = fType != kSurf5 ? legoR + (fHist->GetBinContent(ir, jr) - fCoord->GetZRange().first) / rRange * sc
746 : legoR;
747
748 fMesh[i][j].X() = r * TMath::Sin(phi) * TMath::Cos(theta);
749 fMesh[i][j].Y() = r * TMath::Sin(phi) * TMath::Sin(theta);
750 fMesh[i][j].Z() = r * TMath::Cos(phi);
751 }
752 }
753
754 if (Textured()) {
756 fMinMaxVal.second = fMinMaxVal.first;
757
758 for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
759 for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
760 const Double_t val = fHist->GetBinContent(i, j);
761 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, val);
762 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
763 }
764 }
765
767 }
768
769
770 SetNormals();
771
772 return kTRUE;
773}
774
775////////////////////////////////////////////////////////////////////////////////
776/// Draw projections.
777
779{
780 const TGLDisableGuard lightGuard(GL_LIGHTING);
781 const TGLEnableGuard blendGuard(GL_BLEND);
782 const TGLEnableGuard lineSmooth(GL_LINE_SMOOTH);
783 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
784 glDepthMask(GL_FALSE);
785 glLineWidth(3.f);
786
787 typedef std::list<Projection_t>::const_iterator CLI_t;
788 for (CLI_t begin = fXOZProj.begin(), end = fXOZProj.end(); begin != end; ++begin) {
789 const Projection_t &proj = *begin;
790 glColor4ub(proj.fRGBA[0], proj.fRGBA[1], proj.fRGBA[2], proj.fRGBA[3]);
791
792 for(UInt_t i = 0, e = proj.fVertices.size() / 3; i < e; ++i) {
793 glBegin(GL_LINE_STRIP);
794 glVertex3dv(proj.fVertices[i * 3].CArr());
795 glVertex3dv(proj.fVertices[i * 3 + 1].CArr());
796 glVertex3dv(proj.fVertices[i * 3 + 2].CArr());
797 glEnd();
798 }
799 const Double_t y = fBackBox.GetFrontPoint() == 2 || fBackBox.GetFrontPoint() == 3 ? fBackBox.Get3DBox()[0].Y() : fBackBox.Get3DBox()[2].Y();
800 for(UInt_t i = 0, e = proj.fVertices.size() / 3; i < e; ++i) {
801 glBegin(GL_LINE_STRIP);
802 const TGLVertex3 &v1 = proj.fVertices[i * 3];
803 glVertex3d(v1.X(), y, v1.Z());
804 const TGLVertex3 &v2 = proj.fVertices[i * 3 + 1];
805 glVertex3d(v2.X(), y, v2.Z());
806 const TGLVertex3 &v3 = proj.fVertices[i * 3 + 2];
807 glVertex3d(v3.X(), y, v3.Z());
808 glEnd();
809 }
810 }
811
812 for (CLI_t begin = fYOZProj.begin(), end = fYOZProj.end(); begin != end; ++begin) {
813 const Projection_t &proj = *begin;
814 glColor4ub(proj.fRGBA[0], proj.fRGBA[1], proj.fRGBA[2], proj.fRGBA[3]);
815
816 for(UInt_t i = 0, e = proj.fVertices.size() / 3; i < e; ++i) {
817 glBegin(GL_LINE_STRIP);
818 glVertex3dv(proj.fVertices[i * 3].CArr());
819 glVertex3dv(proj.fVertices[i * 3 + 1].CArr());
820 glVertex3dv(proj.fVertices[i * 3 + 2].CArr());
821 glEnd();
822 }
823
824 const Double_t x = fBackBox.GetFrontPoint() == 2 || fBackBox.GetFrontPoint() == 1 ? fBackBox.Get3DBox()[0].X() : fBackBox.Get3DBox()[2].X();
825 for(UInt_t i = 0, e = proj.fVertices.size() / 3; i < e; ++i) {
826 glBegin(GL_LINE_STRIP);
827 const TGLVertex3 &v1 = proj.fVertices[i * 3];
828 glVertex3d(x, v1.Y(), v1.Z());
829 const TGLVertex3 &v2 = proj.fVertices[i * 3 + 1];
830 glVertex3d(x, v2.Y(), v2.Z());
831 const TGLVertex3 &v3 = proj.fVertices[i * 3 + 2];
832 glVertex3d(x, v3.Y(), v3.Z());
833 glEnd();
834 }
835 }
836
837 for (CLI_t begin = fXOYProj.begin(), end = fXOYProj.end(); begin != end; ++begin) {
838 const Projection_t &proj = *begin;
839 glColor4ub(proj.fRGBA[0], proj.fRGBA[1], proj.fRGBA[2], proj.fRGBA[3]);
840
841 for(UInt_t i = 0, e = proj.fVertices.size() / 2; i < e; ++i) {
842 glBegin(GL_LINES);
843 glVertex3dv(proj.fVertices[i * 2].CArr());
844 glVertex3dv(proj.fVertices[i * 2 + 1].CArr());
845 glEnd();
846 }
847
848
849 for(UInt_t i = 0, e = proj.fVertices.size() / 2; i < e; ++i) {
850 glBegin(GL_LINES);
851 const TGLVertex3 &v1 = proj.fVertices[i * 2];
852 glVertex3d(v1.X(), v1.Y(), fBackBox.Get3DBox()[0].Z());
853 const TGLVertex3 &v2 = proj.fVertices[i * 2 + 1];
854 glVertex3d(v2.X(), v2.Y(), fBackBox.Get3DBox()[0].Z());
855 glEnd();
856 }
857
858 }
859
860 glDepthMask(GL_TRUE);
861 glLineWidth(1.f);
862}
863
864////////////////////////////////////////////////////////////////////////////////
865/// Draw section X.
866
868{
869 using namespace std;
870 //XOZ parallel section.
871 Int_t binY = -1;
872 for (Int_t j = 0, e = fCoord->GetNYBins() - 1; j < e; ++j) {
873 if (fMesh[0][j].Y() <= fXOZSectionPos && fXOZSectionPos <= fMesh[0][j + 1].Y()) {
874 binY = j;
875 break;
876 }
877 }
878
879 if (binY >= 0) {
880 //Draw 2d curve on the profile's plane.
881 const TGLPlane profilePlane(0., 1., 0., -fXOZSectionPos);
882
883 if (!fSectionPass) {
884 glColor3d(1., 0., 0.);
885 glLineWidth(3.f);
886
887 for (Int_t i = 0, e = fCoord->GetNXBins() - 1; i < e; ++i) {
888 glBegin(GL_LINE_STRIP);
889 glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[i + 1][binY], fMesh[i + 1][binY + 1]), kFALSE).second.CArr());
890 glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[i + 1][binY], fMesh[i][binY + 1]), kFALSE).second.CArr());
891 glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[i][binY], fMesh[i][binY + 1]), kFALSE).second.CArr());
892 glEnd();
893 }
894 glLineWidth(1.f);
895 } else {
896 fProj.fVertices.clear();
897 for (Int_t i = 0, e = fCoord->GetNXBins() - 1; i < e; ++i) {
898 fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[i + 1][binY], fMesh[i + 1][binY + 1]), kFALSE).second);
899 fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[i + 1][binY], fMesh[i][binY + 1]), kFALSE).second);
900 fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[i][binY], fMesh[i][binY + 1]), kFALSE).second);
901 }
902 if (fProj.fVertices.size()) {
903 fProj.fRGBA[0] = (UChar_t) (50 + fgRandom->Integer(206));
904 fProj.fRGBA[1] = (UChar_t) fgRandom->Integer(150);
905 fProj.fRGBA[2] = (UChar_t) fgRandom->Integer(150);
906 fProj.fRGBA[3] = 150;
907 static Projection_t dummy;
908 fXOZProj.push_back(dummy);
909 fXOZProj.back().Swap(fProj);
910 }
911 }
912 }
913}
914
915////////////////////////////////////////////////////////////////////////////////
916/// Draw section Y.
917
919{
920 using namespace std;
921 //YOZ parallel section.
922 Int_t binX = -1;
923 for (Int_t i = 0, e = fCoord->GetNXBins() - 1; i < e; ++i) {
924 if (fMesh[i][0].X() <= fYOZSectionPos && fYOZSectionPos <= fMesh[i + 1][0].X()) {
925 binX = i;
926 break;
927 }
928 }
929
930 if (binX >= 0) {
931 //Draw 2d curve on the profile's plane.
932 const TGLPlane profilePlane(1., 0., 0., -fYOZSectionPos);
933
934 if (!fSectionPass) {
935 glColor3d(1., 0., 0.);
936 glLineWidth(3.f);
937 for (Int_t j = 0, e = fCoord->GetNYBins() - 1; j < e; ++j) {
938 glBegin(GL_LINE_STRIP);
939 glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[binX][j + 1], fMesh[binX + 1][j + 1]), kFALSE).second.CArr());
940 glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[binX][j + 1], fMesh[binX + 1][j]), kFALSE).second.CArr());
941 glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[binX][j], fMesh[binX + 1][j]), kFALSE).second.CArr());
942 glEnd();
943 }
944 glLineWidth(1.f);
945 } else {
946 fProj.fVertices.clear();
947 for (Int_t j = 0, e = fCoord->GetNYBins() - 1; j < e; ++j) {
948 fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[binX][j + 1], fMesh[binX + 1][j + 1]), kFALSE).second);
949 fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[binX][j + 1], fMesh[binX + 1][j]), kFALSE).second);
950 fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[binX][j], fMesh[binX + 1][j]), kFALSE).second);
951 }
952 if (fProj.fVertices.size()) {
953 fProj.fRGBA[0] = (UChar_t) (50 + fgRandom->Integer(206));
954 fProj.fRGBA[1] = (UChar_t) fgRandom->Integer(150);
955 fProj.fRGBA[2] = (UChar_t) fgRandom->Integer(150);
956 fProj.fRGBA[3] = 150;
957 static Projection_t dummy;
958 fYOZProj.push_back(dummy);
959 fYOZProj.back().Swap(fProj);
960 }
961 }
962
963 }
964}
965
966////////////////////////////////////////////////////////////////////////////////
967/// Draw section Z.
968
970{
971 using namespace std;
972 //XOY parallel section.
973 const Int_t nX = fCoord->GetNXBins();
974 const Int_t nY = fCoord->GetNYBins();
975 const TGLPlane profilePlane(0., 0., 1., -fXOYSectionPos);
976 TGLVertex3 intersection[2];
977
978
979 if (fSectionPass)
980 fProj.fVertices.clear();
981 else {
982 glColor3d(1., 0., 0.);
983 glLineWidth(3.f);
984 }
985
986 for (Int_t i = 0; i < nX - 1; ++i) {
987 for (Int_t j = 0; j < nY - 1; ++j) {
988 const TGLVertex3 &v1 = fMesh[i + 1][j], &v2 = fMesh[i][j], &v3 = fMesh[i][j + 1], &v4 = fMesh[i + 1][j + 1];
989 Double_t zMin = TMath::Min(TMath::Min(v1.Z(), v2.Z()), v3.Z());
990 Double_t zMax = TMath::Max(TMath::Max(v1.Z(), v2.Z()), v3.Z());
991
992 if (zMin < fXOYSectionPos && zMax > fXOYSectionPos) {
993 Int_t np = 0;
994 if ((v1.Z() > fXOYSectionPos && v2.Z() < fXOYSectionPos) || (v2.Z() > fXOYSectionPos && v1.Z() < fXOYSectionPos)) {
995 TGLLine3 line(v1, v2);
996 intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
997 }
998 if ((v2.Z() > fXOYSectionPos && v3.Z() < fXOYSectionPos) || (v3.Z() > fXOYSectionPos && v2.Z() < fXOYSectionPos)) {
999 TGLLine3 line(v2, v3);
1000 intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
1001 }
1002 if ((np < 2 && v1.Z() > fXOYSectionPos && v3.Z() < fXOYSectionPos) || (v3.Z() > fXOYSectionPos && v1.Z() < fXOYSectionPos)) {
1003 TGLLine3 line(v1, v3);
1004 intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
1005 }
1006 if (np > 1) {
1007 if (!fSectionPass) {
1008 glBegin(GL_LINES);
1009 glVertex3dv(intersection[0].CArr());
1010 glVertex3dv(intersection[1].CArr());
1011 glEnd();
1012 } else {
1013 fProj.fVertices.push_back(intersection[0]);
1014 fProj.fVertices.push_back(intersection[1]);
1015 }
1016 }
1017 }
1018 zMin = TMath::Min(v4.Z(), zMin);
1019 zMax = TMath::Max(v4.Z(), zMax);
1020 if (zMin < fXOYSectionPos && zMax > fXOYSectionPos) {
1021 Int_t np = 0;
1022 if ((v3.Z() > fXOYSectionPos && v4.Z() < fXOYSectionPos) || (v4.Z() > fXOYSectionPos && v3.Z() < fXOYSectionPos)) {
1023 TGLLine3 line(v3, v4);
1024 intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
1025 }
1026 if ((v4.Z() > fXOYSectionPos && v1.Z() < fXOYSectionPos) || (v1.Z() > fXOYSectionPos && v4.Z() < fXOYSectionPos)) {
1027 TGLLine3 line(v4, v1);
1028 intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
1029 }
1030 if ((np < 2 && v3.Z() > fXOYSectionPos && v1.Z() < fXOYSectionPos) || (v1.Z() > fXOYSectionPos && v3.Z() < fXOYSectionPos)) {
1031 TGLLine3 line(v3, v1);
1032 intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
1033 }
1034 if (np > 1) {
1035 if (!fSectionPass) {
1036 glBegin(GL_LINES);
1037 glVertex3dv(intersection[0].CArr());
1038 glVertex3dv(intersection[1].CArr());
1039 glEnd();
1040 } else {
1041 fProj.fVertices.push_back(intersection[0]);
1042 fProj.fVertices.push_back(intersection[1]);
1043 }
1044 }
1045 }
1046 }
1047 }
1048
1049 if (fSectionPass && fProj.fVertices.size()) {
1050 fProj.fRGBA[0] = (UChar_t) fgRandom->Integer(150);
1051 fProj.fRGBA[1] = (UChar_t) fgRandom->Integer(150);
1052 fProj.fRGBA[2] = (UChar_t) (50 + fgRandom->Integer(206));
1053 fProj.fRGBA[3] = 150;
1054 static Projection_t dummy;
1055 fXOYProj.push_back(dummy);
1056 fXOYProj.back().Swap(fProj);
1057 }
1058
1059 if (!fSectionPass)
1060 glLineWidth(1.f);
1061}
1062
1063////////////////////////////////////////////////////////////////////////////////
1064///Clamp z value.
1065
1067{
1068 const TGLVertex3 *frame = fBackBox.Get3DBox();
1069
1070 if (fCoord->GetZLog())
1071 if (zVal <= 0.)
1072 zVal = frame[0].Z();
1073 else
1074 zVal = TMath::Log10(zVal) * fCoord->GetZScale();
1075 else
1076 zVal *= fCoord->GetZScale();
1077
1078 if (zVal > frame[4].Z())
1079 zVal = frame[4].Z();
1080 else if (zVal < frame[0].Z())
1081 zVal = frame[0].Z();
1082}
1083
1084////////////////////////////////////////////////////////////////////////////////
1085///Find 3d coords using mouse cursor coords.
1086
1088{
1089 py = fCamera->GetHeight() - py;
1090
1091 const Int_t nY = fCoord->GetNYBins() - 1;
1092 Int_t selected = fSelectedPart - (fSelectionBase - 1);
1093 Int_t k = selected / 2;
1094 Int_t i = k / nY;
1095 Int_t j = k % nY;
1096
1097 const Bool_t odd = selected & 1;
1098 const TGLVertex3 &v1 = odd ? fMesh[i][j + 1] : fMesh[i + 1][j];
1099 const TGLVertex3 &v2 = odd ? fMesh[i + 1][j + 1] : fMesh[i][j];
1100 const TGLVertex3 &v3 = odd ? fMesh[i + 1][j] : fMesh[i][j + 1];
1101
1102 TGLVertex3 winV1, winV2, winV3;
1103
1104 Double_t mvMatrix[16] = {0.};
1105 glGetDoublev(GL_MODELVIEW_MATRIX, mvMatrix);
1106 Double_t prMatrix[16] = {0.};
1107 glGetDoublev(GL_PROJECTION_MATRIX, prMatrix);
1108 Int_t viewport[4] = {0};
1109 glGetIntegerv(GL_VIEWPORT, viewport);
1110
1111 gluProject(v1.X(), v1.Y(), v1.Z(), mvMatrix, prMatrix, viewport, &winV1.X(), &winV1.Y(), &winV1.Z());
1112 gluProject(v2.X(), v2.Y(), v2.Z(), mvMatrix, prMatrix, viewport, &winV2.X(), &winV2.Y(), &winV2.Z());
1113 gluProject(v3.X(), v3.Y(), v3.Z(), mvMatrix, prMatrix, viewport, &winV3.X(), &winV3.Y(), &winV3.Z());
1114
1115 Double_t planeABCD[4] = {0.};
1116 TMath::Normal2Plane(winV1.CArr(), winV2.CArr(), winV3.CArr(), planeABCD);
1117 planeABCD[3] = - winV1.X() * planeABCD[0] - winV1.Y() * planeABCD[1] - winV1.Z() * planeABCD[2];
1118 Double_t pz = (-planeABCD[3] - planeABCD[0] * px - planeABCD[1] * py) / planeABCD[2];
1119 Double_t rez[3] = {0.};
1120
1121 gluUnProject(px, py, pz, mvMatrix, prMatrix, viewport, rez, rez + 1, rez + 2);
1122
1123 fObjectInfo.Form("(x == %f, y == %f, z == %f)",
1124 rez[0] / fCoord->GetXScale(),
1125 rez[1] / fCoord->GetYScale(),
1126 rez[2] / fCoord->GetZScale());
1127
1128 return (char *)fObjectInfo.Data();
1129}
1130
1131////////////////////////////////////////////////////////////////////////////////
1132///Generate palette.
1133
1135{
1136 if (!fUpdateTexMap)
1137 return kTRUE;
1138
1139 if(fMinMaxVal.first == fMinMaxVal.second)
1140 return kFALSE;//must be std::abs(fMinMaxVal.second - fMinMaxVal.first) < ...
1141
1142 //User-defined contours are disabled. To be fixed.
1145
1146 UInt_t paletteSize = gStyle->GetNumberContours();
1147 if (!paletteSize)
1148 paletteSize = 20;
1149
1150 Bool_t rez = fPalette.GeneratePalette(paletteSize, fMinMaxVal);
1151
1152 if (rez && fUpdateTexMap) {
1153 GenTexMap();
1155 }
1156
1157 return rez;
1158}
1159
1160////////////////////////////////////////////////////////////////////////////////
1161///Find texture coordinates.
1162
1164{
1165 const Int_t nX = fCoord->GetNXBins();
1166 const Int_t nY = fCoord->GetNYBins();
1167
1168 fTexMap.resize(nX * nY);
1169 fTexMap.SetRowLen(nY);
1170
1171 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
1172 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
1173 Double_t z = fHist->GetBinContent(ir, jr);
1175 ClampZ(z);
1176 fTexMap[i][j] = fPalette.GetTexCoord(z);
1177 }
1178 }
1179}
1180
1181////////////////////////////////////////////////////////////////////////////////
1182///Draw flat textured surface.
1183
1185{
1186 static const Float_t whiteDiffuse[] = {0.8f, 0.8f, 0.8f, 0.65f};
1187 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, whiteDiffuse);
1188 for (Int_t i = 0, ei = fCoord->GetNXBins() - 1; i < ei; ++i) {
1189 for (Int_t j = 0, ej = fCoord->GetNYBins() - 1; j < ej; ++j) {
1190 Rgl::DrawFaceTextured(fMesh[i][j + 1], fMesh[i][j], fMesh[i + 1][j],
1191 fTexMap[i][j + 1], fTexMap[i][j], fTexMap[i + 1][j],
1192 fBackBox.Get3DBox()[4].Z(), TGLVector3(0., 0., 1.));
1193 Rgl::DrawFaceTextured(fMesh[i + 1][j], fMesh[i + 1][j + 1], fMesh[i][j + 1],
1194 fTexMap[i + 1][j], fTexMap[i + 1][j + 1], fTexMap[i][j + 1],
1195 fBackBox.Get3DBox()[4].Z(), TGLVector3(0., 0., 1.));
1196 }
1197 }
1198}
1199
1200////////////////////////////////////////////////////////////////////////////////
1201///Checks, if surf requires texture.
1202
1204{
1205 switch (fType) {
1206 case kSurf1:
1207 case kSurf2:
1208 case kSurf3:
1209 case kSurf5:
1210 return kTRUE;
1211 default:;
1212 }
1213
1214 return kFALSE;
1215}
1216
1217////////////////////////////////////////////////////////////////////////////////
1218///Any section exists.
1219
1221{
1222 return fXOZSectionPos > fBackBox.Get3DBox()[0].Y() || fYOZSectionPos > fBackBox.Get3DBox()[0].X() ||
1224}
1225
1226////////////////////////////////////////////////////////////////////////////////
1227///Any projection exists.
1228
1230{
1231 return fXOZProj.size() || fYOZProj.size() || fXOYProj.size();
1232}
1233
1234////////////////////////////////////////////////////////////////////////////////
1235///Draw. Palette.
1236///Originally, fCamera was never null.
1237///It can be a null now because of gl-viewer.
1238
1240{
1241 if (!fCamera) {
1242 //Thank you, gl-viewer!
1243 return;
1244 }
1245
1247
1248 glFinish();
1249
1250 fCamera->SetCamera();
1252}
1253
1254////////////////////////////////////////////////////////////////////////////////
1255///Draw. Palette. Axis.
1256
1258{
1259 gVirtualX->SetDrawMode(TVirtualX::kCopy);//TCanvas by default sets in kInverse
1261}
@ kKeyPress
Definition: Buttons.h:20
@ kButton1Double
Definition: Buttons.h:24
#define GL_TRUE
Definition: GL_glu.h:262
#define GL_LINE_STRIP
Definition: GL_glu.h:286
#define GL_LINES
Definition: GL_glu.h:284
#define GL_FALSE
Definition: GL_glu.h:261
@ kKey_P
Definition: KeySymbols.h:141
@ kKey_C
Definition: KeySymbols.h:128
@ kKey_p
Definition: KeySymbols.h:173
@ kKey_c
Definition: KeySymbols.h:160
ROOT::R::TRInterface & r
Definition: Object.C:4
#define c(i)
Definition: RSha256.hxx:101
#define e(i)
Definition: RSha256.hxx:103
static RooMathCoreReg dummy
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
int Int_t
Definition: RtypesCore.h:41
unsigned char UChar_t
Definition: RtypesCore.h:34
int Ssiz_t
Definition: RtypesCore.h:63
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
unsigned long ULong_t
Definition: RtypesCore.h:51
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:365
@ kWhite
Definition: Rtypes.h:63
void Info(const char *location, const char *msgfmt,...)
std::pair< Bool_t, TGLLine3 > Intersection(const TGLPlane &p1, const TGLPlane &p2)
Find 3D line interestion of this plane with 'other'.
Definition: TGLUtil.cxx:517
@ kGLSpherical
Definition: TGLUtil.h:46
@ kGLCylindrical
Definition: TGLUtil.h:45
@ kGLPolar
Definition: TGLUtil.h:44
@ kGLCartesian
Definition: TGLUtil.h:43
#define gROOT
Definition: TROOT.h:415
char * Form(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition: TStyle.h:407
#define gVirtualX
Definition: TVirtualX.h:345
virtual Color_t GetFillColor() const
Return the fill area color.
Definition: TAttFill.h:30
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition: TAxis.cxx:464
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition: TAxis.cxx:504
Int_t GetNbins() const
Definition: TAxis.h:121
The color creation and management class.
Definition: TColor.h:19
void SetRowLen(Int_t len)
Definition: TGLUtil.h:1165
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 DisableTexture() const
Disable 1D texture.
Definition: TGLUtil.cxx:4246
Double_t GetTexCoord(Double_t z) const
Get tex coordinate.
Definition: TGLUtil.cxx:4263
Bool_t GeneratePalette(UInt_t paletteSize, const Rgl::Range_t &zRange, Bool_t checkSize=kTRUE)
Try to find colors for palette.
Definition: TGLUtil.cxx:4162
void EnableTexture(Int_t mode) const
Enable 1D texture.
Definition: TGLUtil.cxx:4227
3D space, fixed length, line class, with direction / length 'vector', passing through point 'vertex'.
Definition: TGLUtil.h:386
3D plane class - of format Ax + By + Cz + D = 0
Definition: TGLUtil.h:524
void SetPlotBox(const Rgl::Range_t &xRange, const Rgl::Range_t &yRange, const Rgl::Range_t &zRange)
Set up a frame box.
Definition: TGLPlotBox.cxx:198
const TGLVertex3 * Get3DBox() const
Get 3D box.
Definition: TGLPlotBox.cxx:303
void DrawBox(Int_t selectedPart, Bool_t selectionPass, const std::vector< Double_t > &zLevels, Bool_t highColor) const
Draw back box for a plot.
Definition: TGLPlotBox.cxx:184
Int_t GetFrontPoint() const
The nearest point.
Definition: TGLPlotBox.cxx:294
Camera for TGLPlotPainter and sub-classes.
Definition: TGLPlotCamera.h:22
void StartPan(Int_t px, Int_t py)
User clicks somewhere (px, py).
void Apply(Double_t phi, Double_t theta) const
Applies rotations and translations before drawing.
void SetCamera() const
Viewport and projection.
void Pan(Int_t px, Int_t py)
Pan camera.
Int_t GetHeight() const
viewport[3]
void SetViewVolume(const TGLVertex3 *box)
'box' is the TGLPlotPainter's back box's coordinates.
Helper class for plot-painters holding information about axis ranges, numbers of bins and flags if ce...
Double_t GetZLength() const
Z length.
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.
Bool_t GetXLog() const
Get X log.
Int_t GetFirstXBin() const
Int_t GetFirstYBin() const
const Rgl::Range_t & GetZRange() const
Z range.
const Rgl::Range_t & GetYRangeScaled() const
Scaled range.
void SetCoordType(EGLCoordType type)
If coord type was changed, plot must reset sections (if any), set fModified.
void ResetModified()
Reset modified.
Bool_t GetYLog() const
Get Y log.
Bool_t GetZLog() const
Get Z log.
Bool_t Modified() const
Modified.
Double_t GetXScale() const
Double_t GetZScale() const
Int_t GetNXBins() const
Number of X bins.
const Rgl::Range_t & GetZRangeScaled() const
Scaled range.
Int_t GetLastYBin() const
Int_t GetNYBins() const
Number of Y bins.
Int_t GetLastXBin() const
EGLCoordType GetCoordType() const
Get coordinates type.
Base class for plot-painters that provide GL rendering of various 2D and 3D histograms,...
void DrawSections() const
Draw sections (if any).
Double_t fPadTheta
std::vector< Double_t > fZLevels
Double_t fXOYSectionPos
void RestoreModelviewMatrix() const
Double_t fXOZSectionPos
TGLBoxCut fBoxCut
virtual void Paint()
Draw lego/surf/whatever you can.
TGLPlotCoordinates * fCoord
TGLPlotBox fBackBox
void SaveProjectionMatrix() const
void SaveModelviewMatrix() const
void MoveSection(Int_t px, Int_t py)
Create dynamic profile using selected plane.
Bool_t fUpdateSelection
TGLPlotCamera * fCamera
void RestoreProjectionMatrix() const
Double_t fYOZSectionPos
Implements painting of TH2 with "SURF" option.
char * WindowPointTo3DPoint(Int_t px, Int_t py) const
Find 3d coords using mouse cursor coords.
void DrawPlot() const
Draw surf/surf1/surf2/surf4.
TGLLevelPalette fPalette
TGL2DArray< Double_t > fTexMap
Bool_t InitGeometryPolar()
Find bin ranges for X and Y axes, axes ranges for X, Y and Z.
void DrawSectionXOY() const
Draw section Z.
void DeInitGL() const
Initialize some OpenGL state variables.
void DrawProjections() const
Draw projections.
Bool_t HasProjections() const
Any projection exists.
Bool_t Textured() const
Checks, if surf requires texture.
std::list< Projection_t > fXOYProj
Bool_t InitGeometry()
Set mesh, normals.
void DrawPalette() const
Draw.
TGL2DArray< TGLVector3 > fAverageNormals
void StartPan(Int_t px, Int_t py)
User clicks right mouse button (in a pad).
void SetSurfaceColor() const
Set color for surface.
char * GetPlotInfo(Int_t px, Int_t py)
Coords for point on surface under cursor.
TGL2DArray< std::pair< TGLVector3, TGLVector3 > > fFaceNormals
void DrawContoursProjection() const
Draw flat textured surface.
void InitGL() const
Initialize some OpenGL state variables.
std::list< Projection_t > fXOZProj
void ProcessEvent(Int_t event, Int_t px, Int_t py)
Remove all profiles/sections.
void DrawSectionYOZ() const
Draw section Y.
Bool_t InitGeometrySpherical()
Find bin ranges for X and Y axes, axes ranges for X, Y and Z.
void AddOption(const TString &stringOption)
Additional options for surfaces.
TGLSurfacePainter(TH1 *hist, TGLPlotCamera *camera, TGLPlotCoordinates *coord)
Constructor.
void ClampZ(Double_t &zVal) const
Clamp z value.
TGL2DArray< TGLVertex3 > fMesh
Bool_t InitGeometryCartesian()
Find bin ranges for X and Y axes, axes ranges for X, Y and Z.
Bool_t PreparePalette() const
Generate palette.
void Pan(Int_t px, Int_t py)
User's moving mouse cursor, with middle mouse button pressed (for pad).
static TRandom * fgRandom
void GenTexMap() const
Find texture coordinates.
void DrawSectionXOZ() const
Draw section X.
void SetNormals()
One normal per vertex; this normal is average of neighbouring triangles normals.
Bool_t InitGeometryCylindrical()
Find bin ranges for X and Y axes, axes ranges for X, Y and Z.
std::list< Projection_t > fYOZProj
void DrawPaletteAxis() const
Draw. Palette. Axis.
Bool_t HasSections() const
Any section exists.
Rgl::Range_t fMinMaxVal
3 component (x/y/z) vector class.
Definition: TGLUtil.h:247
void Normalise()
Definition: TGLUtil.h:303
3 component (x/y/z) vertex class.
Definition: TGLUtil.h:83
Double_t X() const
Definition: TGLUtil.h:118
Double_t Z() const
Definition: TGLUtil.h:122
Double_t Y() const
Definition: TGLUtil.h:120
const Double_t * CArr() const
Definition: TGLUtil.h:125
The TH1 histogram class.
Definition: TH1.h:56
@ kUserContour
user specified contour levels
Definition: TH1.h:161
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4899
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
void ResetBit(UInt_t f)
Definition: TObject.h:171
SCoord_t fY
Definition: TPoint.h:36
SCoord_t fX
Definition: TPoint.h:35
This is the base class for the ROOT Random number generators.
Definition: TRandom.h:27
virtual UInt_t Integer(UInt_t imax)
Returns a random integer uniformly distributed on the interval [ 0, imax-1 ].
Definition: TRandom.cxx:349
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
const char * Data() const
Definition: TString.h:364
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2289
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
Float_t GetLegoInnerR() const
Definition: TStyle.h:228
Int_t GetNumberContours() const
Definition: TStyle.h:229
TLine * line
Double_t y[n]
Definition: legend1.C:17
Double_t x[n]
Definition: legend1.C:17
void DrawFaceTextured(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3, Double_t t1, Double_t t2, Double_t t3, const TGLVector3 &norm1, const TGLVector3 &norm2, const TGLVector3 &norm3)
Draw textured triangle.
Definition: TGLUtil.cxx:3837
void ObjectIDToColor(Int_t objectID, Bool_t highColor)
Object id encoded as rgb triplet.
Definition: TGLUtil.cxx:2892
void SetZLevels(TAxis *zAxis, Double_t zMin, Double_t zMax, Double_t zScale, std::vector< Double_t > &zLevels)
Definition: TGLUtil.cxx:3821
void DrawPalette(const TGLPlotCamera *camera, const TGLLevelPalette &palette)
Draw. Palette.
void DrawPaletteAxis(const TGLPlotCamera *camera, const Range_t &minMax, Bool_t logZ)
void DrawQuadOutline(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3, const TGLVertex3 &v4)
Draw quad outline.
Definition: TGLUtil.cxx:2940
void DrawSmoothFace(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3, const TGLVector3 &norm1, const TGLVector3 &norm2, const TGLVector3 &norm3)
Draws triangle face, each vertex has its own averaged normal.
Definition: TGLUtil.cxx:2984
static constexpr double second
null_t< F > null()
T * Normal2Plane(const T v1[3], const T v2[3], const T v3[3], T normal[3])
Calculate a normal vector of a plane.
Definition: TMath.h:1179
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:180
Double_t Cos(Double_t)
Definition: TMath.h:631
constexpr Double_t Pi()
Definition: TMath.h:38
Double_t Sin(Double_t)
Definition: TMath.h:627
Double_t Log10(Double_t x)
Definition: TMath.h:754
constexpr Double_t TwoPi()
Definition: TMath.h:45
Definition: first.py:1
void Swap(Projection_t &rhs)
Constructor.
std::vector< TGLVertex3 > fVertices
REAL * vertex
Definition: triangle.c:512