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