Logo ROOT   6.12/07
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
38 Implements 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);
109  fBoxCut.StartMovement(px, fCamera->GetHeight() - 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 
122  fCamera->SetCamera();
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 
135  fCamera->SetCamera();
137 
138 
139  if (!fHighColor) {
141  fBoxCut.MoveBox(px, py, fSelectedPart);
142  else
143  MoveSection(px, py);
144  }
145  else
146  MoveSection(px, py);
147 
150  }
151 
152  fMousePosition.fX = px, fMousePosition.fY = py;
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()) {
203  DrawSectionXOZ();
204  DrawSectionYOZ();
205  DrawSectionXOY();
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())
219  fBoxCut.TurnOnOff();
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 {
228  fBoxCut.TurnOnOff();
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 
289  fAverageNormals.assign(fAverageNormals.size(), TGLVector3());
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)
339  DrawProjections();
340  }
341 
342  if (!fSelectionPass) {
343  SetSurfaceColor();
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 
372  if (fHighColor && fSelectionPass)
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 
389  if (fSelectionPass && !fHighColor)
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 
404  if (fSelectionPass && !fHighColor)
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) {
512  fCoord->GetXLog() ? fMesh[i][j].X() = TMath::Log10(fXAxis->GetBinCenter(ir)) * fCoord->GetXScale()
513  : fMesh[i][j].X() = fXAxis->GetBinCenter(ir) * fCoord->GetXScale();
514  fCoord->GetYLog() ? fMesh[i][j].Y() = TMath::Log10(fYAxis->GetBinCenter(jr)) * fCoord->GetYScale()
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];
546  fXOZSectionPos = vertex.Y();
547  fYOZSectionPos = vertex.X();
548  fXOYSectionPos = vertex.Z();
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];
573  fXOZSectionPos = vertex.Y();
574  fYOZSectionPos = vertex.X();
575  fXOYSectionPos = vertex.Z();
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);
587  const Double_t rRange = fYAxis->GetBinCenter(fYAxis->GetNbins()) - fYAxis->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];
640  fXOZSectionPos = vertex.Y();
641  fYOZSectionPos = vertex.X();
642  fXOYSectionPos = vertex.Z();
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];
713  fXOZSectionPos = vertex.Y();
714  fYOZSectionPos = vertex.X();
715  fXOYSectionPos = vertex.Z();
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);
1174  if (fCoord->GetCoordType() == kGLCartesian)
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() ||
1223  fXOYSectionPos > fBackBox.Get3DBox()[0].Z();
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 }
void ClampZ(Double_t &zVal) const
Clamp z value.
void DrawBox(Bool_t selectionPass, Int_t selected) const
Draw cut as a semi-transparent box.
void SetZLevels(TAxis *zAxis, Double_t zMin, Double_t zMax, Double_t zScale, std::vector< Double_t > &zLevels)
Definition: TGLUtil.cxx:3787
Int_t GetFrontPoint() const
The nearest point.
Definition: TGLPlotBox.cxx:294
void SetRowLen(Int_t len)
Definition: TGLUtil.h:1164
void RestoreModelviewMatrix() const
Camera for TGLPlotPainter and sub-classes.
Definition: TGLPlotCamera.h:21
Bool_t InitGeometryCylindrical()
Find bin ranges for X and Y axes, axes ranges for X, Y and Z.
Int_t GetFirstXBin() const
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:3803
Int_t GetNYBins() const
Number of Y bins.
void MoveBox(Int_t px, Int_t py, Int_t axisID)
Move box cut along selected direction.
void DrawSectionXOZ() const
Draw section X.
Int_t GetNumberContours() const
Definition: TStyle.h:225
void DrawContoursProjection() const
Draw flat textured surface.
TLine * line
float Float_t
Definition: RtypesCore.h:53
Bool_t GetZLog() const
Get Z log.
TGL2DArray< TGLVector3 > fAverageNormals
void DrawProjections() const
Draw projections.
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition: TAxis.cxx:504
constexpr Double_t TwoPi()
Definition: TMath.h:44
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
R__EXTERN TStyle * gStyle
Definition: TStyle.h:402
Double_t fYOZSectionPos
EGLCoordType GetCoordType() const
Get coordinates type.
void DrawSections() const
Draw sections (if any).
Bool_t HasSections() const
Any section exists.
void StartPan(Int_t px, Int_t py)
User clicks somewhere (px, py).
TGL2DArray< Double_t > fTexMap
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4763
Double_t GetTexCoord(Double_t z) const
Get tex coordinate.
Definition: TGLUtil.cxx:4229
const TGLVertex3 * Get3DBox() const
Get 3D box.
Definition: TGLPlotBox.cxx:303
void ProcessEvent(Int_t event, Int_t px, Int_t py)
Remove all profiles/sections.
SCoord_t fX
Definition: TPoint.h:35
void DrawPalette() const
Draw.
Double_t GetZLength() const
Z length.
void InitGL() const
Initialize some OpenGL state variables.
const Rgl::Range_t & GetZRange() const
Z range.
#define gROOT
Definition: TROOT.h:402
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:585
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
SCoord_t fY
Definition: TPoint.h:36
Basic string class.
Definition: TString.h:125
Int_t GetNXBins() const
Number of X bins.
Rgl::Range_t fMinMaxVal
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:168
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
void TurnOnOff()
Turn the box cut on/off.
Bool_t GetYLog() const
Get Y log.
void DrawPalette(const TGLPlotCamera *camera, const TGLLevelPalette &palette)
Draw. Palette.
void DrawPaletteAxis(const TGLPlotCamera *camera, const Range_t &minMax, Bool_t logZ)
user specified contour levels
Definition: TH1.h:161
void GenTexMap() const
Find texture coordinates.
STL namespace.
TGL2DArray< TGLVertex3 > fMesh
Implements painting of TH2 with "SURF" option.
void StartPan(Int_t px, Int_t py)
User clicks right mouse button (in a pad).
Bool_t InitGeometryPolar()
Find bin ranges for X and Y axes, axes ranges for X, Y and Z.
T * Normal2Plane(const T v1[3], const T v2[3], const T v3[3], T normal[3])
Definition: TMath.h:1180
void DrawQuadOutline(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3, const TGLVertex3 &v4)
Draw quad outline.
Definition: TGLUtil.cxx:2906
void DrawSectionYOZ() const
Draw section Y.
std::vector< TGLVertex3 > fVertices
null_t< F > null()
void DrawPaletteAxis() const
Draw. Palette. Axis.
void Apply(Double_t phi, Double_t theta) const
Applies rotations and translations before drawing.
void SetNormals()
One normal per vertex; this normal is average of neighbouring triangles normals.
void DrawSectionXOY() const
Draw section Z.
Double_t x[n]
Definition: legend1.C:17
Bool_t InitGeometry()
Set mesh, normals.
This is the base class for the ROOT Random number generators.
Definition: TRandom.h:27
3 component (x/y/z) vertex class.
Definition: TGLUtil.h:82
Double_t fXOZSectionPos
Bool_t IsActive() const
void EnableTexture(Int_t mode) const
Enable 1D texture.
Definition: TGLUtil.cxx:4193
Double_t Log10(Double_t x)
Definition: TMath.h:651
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition: TAxis.cxx:464
virtual UInt_t Integer(UInt_t imax)
Returns a random integer on [ 0, imax-1 ].
Definition: TRandom.cxx:341
TGL2DArray< std::pair< TGLVector3, TGLVector3 > > fFaceNormals
void Info(const char *location, const char *msgfmt,...)
void SetCamera() const
Viewport and projection.
Int_t GetFirstYBin() const
TGLPlotBox fBackBox
3 component (x/y/z) vector class.
Definition: TGLUtil.h:246
char * WindowPointTo3DPoint(Int_t px, Int_t py) const
Find 3d coords using mouse cursor coords.
constexpr Double_t Pi()
Definition: TMath.h:40
static constexpr double second
void SetViewVolume(const TGLVertex3 *box)
&#39;box&#39; is the TGLPlotPainter&#39;s back box&#39;s coordinates.
REAL * vertex
Definition: triangle.c:512
Bool_t GetXLog() const
Get X log.
Definition: Rtypes.h:58
Bool_t InitGeometrySpherical()
Find bin ranges for X and Y axes, axes ranges for X, Y and Z.
Double_t fPadTheta
void ObjectIDToColor(Int_t objectID, Bool_t highColor)
Object id encoded as rgb triplet.
Definition: TGLUtil.cxx:2858
const Rgl::Range_t & GetZRangeScaled() const
Scaled range.
TGLPlotCamera * fCamera
Float_t GetLegoInnerR() const
Definition: TStyle.h:224
void RestoreProjectionMatrix() const
Int_t GetLastYBin() const
TGLLevelPalette fPalette
ROOT::R::TRInterface & r
Definition: Object.C:4
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:2950
void Pan(Int_t px, Int_t py)
User&#39;s moving mouse cursor, with middle mouse button pressed (for pad).
Bool_t Textured() const
Checks, if surf requires texture.
Helper class for plot-painters holding information about axis ranges, numbers of bins and flags if ce...
void ResetModified()
Reset modified.
void Pan(Int_t px, Int_t py)
Pan camera.
Bool_t HasProjections() const
Any projection exists.
unsigned int UInt_t
Definition: RtypesCore.h:42
char * Form(const char *fmt,...)
Ssiz_t Length() const
Definition: TString.h:386
3D space, fixed length, line class, with direction / length &#39;vector&#39;, passing through point &#39;vertex&#39;...
Definition: TGLUtil.h:387
Base class for plot-painters that provide GL rendering of various 2D and 3D histograms, functions and parametric surfaces.
std::vector< Double_t > fZLevels
#define gVirtualX
Definition: TVirtualX.h:350
Double_t Cos(Double_t)
Definition: TMath.h:550
const Bool_t kFALSE
Definition: RtypesCore.h:88
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 Ssiz_t
Definition: RtypesCore.h:63
void DrawPlot() const
Draw surf/surf1/surf2/surf4.
Double_t Z() const
Definition: TGLUtil.h:122
Double_t GetYScale() const
void Swap(Projection_t &rhs)
Constructor.
std::list< Projection_t > fXOYProj
#define ClassImp(name)
Definition: Rtypes.h:359
char * GetPlotInfo(Int_t px, Int_t py)
Coords for point on surface under cursor.
double Double_t
Definition: RtypesCore.h:55
void SetCoordType(EGLCoordType type)
If coord type was changed, plot must reset sections (if any), set fModified.
Bool_t Modified() const
Modified.
unsigned long ULong_t
Definition: RtypesCore.h:51
static RooMathCoreReg dummy
void SetSurfaceColor() const
Set color for surface.
Double_t y[n]
Definition: legend1.C:17
virtual Color_t GetFillColor() const
Return the fill area color.
Definition: TAttFill.h:30
void SaveProjectionMatrix() const
static TRandom * fgRandom
The TH1 histogram class.
Definition: TH1.h:56
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
The color creation and management class.
Definition: TColor.h:19
Bool_t SetRanges(const TH1 *hist, Bool_t errors=kFALSE, Bool_t zBins=kFALSE)
Set bin ranges, ranges.
void DisableTexture() const
Disable 1D texture.
Definition: TGLUtil.cxx:4212
const Rgl::Range_t & GetYRangeScaled() const
Scaled range.
void AddOption(const TString &stringOption)
Additional options for surfaces.
Int_t GetLastXBin() const
you should not use this method at all Int_t Int_t z
Definition: TRolke.cxx:630
const Double_t * CArr() const
Definition: TGLUtil.h:125
Bool_t PreparePalette() const
Generate palette.
Double_t fXOYSectionPos
void Normalise()
Definition: TGLUtil.h:305
void StartMovement(Int_t px, Int_t py)
Start cut&#39;s movement.
void MoveSection(Int_t px, Int_t py)
Create dynamic profile using selected plane.
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:200
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
Double_t Sin(Double_t)
Definition: TMath.h:547
TGLSurfacePainter(TH1 *hist, TGLPlotCamera *camera, TGLPlotCoordinates *coord)
Constructor.
const Rgl::Range_t & GetXRangeScaled() const
Scaled range.
std::list< Projection_t > fXOZProj
std::list< Projection_t > fYOZProj
void ResetBit(UInt_t f)
Definition: TObject.h:171
unsigned char UChar_t
Definition: RtypesCore.h:34
Definition: first.py:1
Bool_t InitGeometryCartesian()
Find bin ranges for X and Y axes, axes ranges for X, Y and Z.
Int_t GetNbins() const
Definition: TAxis.h:121
Bool_t fUpdateSelection
Int_t GetHeight() const
viewport[3]
void SaveModelviewMatrix() const
Bool_t GeneratePalette(UInt_t paletteSize, const Rgl::Range_t &zRange, Bool_t checkSize=kTRUE)
Try to find colors for palette.
Definition: TGLUtil.cxx:4128
TGLPlotCoordinates * fCoord
Double_t Y() const
Definition: TGLUtil.h:120
virtual void Paint()
Draw lego/surf/whatever you can.
const Bool_t kTRUE
Definition: RtypesCore.h:87
3D plane class - of format Ax + By + Cz + D = 0
Definition: TGLUtil.h:525
TGLBoxCut fBoxCut
Double_t GetZScale() const
void DeInitGL() const
Initialize some OpenGL state variables.
Double_t GetXScale() const
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.
std::pair< Bool_t, TGLLine3 > Intersection(const TGLPlane &p1, const TGLPlane &p2)
Find 3D line interestion of this plane with &#39;other&#39;.
Definition: TGLUtil.cxx:544
Double_t X() const
Definition: TGLUtil.h:118