36 ClassImp(TGLLegoPainter);
41 TGLLegoPainter::TGLLegoPainter(TH1 *hist, TGLPlotCamera *cam, TGLPlotCoordinates *coord)
42 : TGLPlotPainter(hist, cam, coord, kFALSE, kTRUE, kTRUE),
43 fLegoType(kColorSimple),
52 char *TGLLegoPainter::GetPlotInfo(Int_t , Int_t )
57 if (fSelectedPart < fSelectionBase) {
59 fBinInfo += fHist->Class()->GetName();
61 fBinInfo += fHist->GetName();
62 }
else if (!fHighColor) {
63 const Int_t binI = (fSelectedPart - fSelectionBase) / fCoord->GetNYBins() + fCoord->GetFirstXBin();
64 const Int_t binJ = (fSelectedPart - fSelectionBase) % fCoord->GetNYBins() + fCoord->GetFirstYBin();
65 fBinInfo.Form(
"(binx = %d; biny = %d; binc = %f)", binI, binJ,
66 fHist->GetBinContent(binI, binJ));
68 fBinInfo =
"Switch to true-color mode to obtain correct info";
71 return (Char_t *)fBinInfo.Data();
77 Bool_t TGLLegoPainter::InitGeometry()
80 switch (fCoord->GetCoordType()) {
82 ret = InitGeometryCartesian();
break;
84 ret = InitGeometryPolar();
break;
86 ret = InitGeometryCylindrical();
break;
88 ret = InitGeometrySpherical();
break;
92 if (ret && fCamera) fCamera->SetViewVolume(fBackBox.Get3DBox());
99 Bool_t TGLLegoPainter::InitGeometryCartesian()
101 if (!fCoord->SetRanges(fHist, fDrawErrors, kFALSE))
104 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
107 const Int_t nX = fCoord->GetNXBins();
108 const Double_t barWidth = fHist->GetBarWidth(), barOffset = fHist->GetBarOffset();
109 const TGLVertex3 *frame = fBackBox.Get3DBox();
112 if (fCoord->GetXLog()) {
113 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
114 const Double_t xWidth = fXAxis->GetBinWidth(ir);
115 Double_t low = fXAxis->GetBinLowEdge(ir) + xWidth * barOffset;
116 fXEdges[i].first = TMath::Log10(low) * fCoord->GetXScale();
117 fXEdges[i].second = TMath::Log10(low + xWidth * barWidth) * fCoord->GetXScale();
118 if (fXEdges[i].second > frame[1].X())
119 fXEdges[i].second = frame[1].X();
120 if (fXEdges[i].first < frame[0].X())
121 fXEdges[i].first = frame[0].X();
122 if (fXEdges[i].second < frame[0].X())
123 fXEdges[i].second = frame[0].X();
126 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
127 const Double_t xWidth = fXAxis->GetBinWidth(ir);
128 fXEdges[i].first = (fXAxis->GetBinLowEdge(ir) + xWidth * barOffset) * fCoord->GetXScale();
129 fXEdges[i].second = fXEdges[i].first + xWidth * barWidth * fCoord->GetXScale();
130 if (fXEdges[i].second > frame[1].X())
131 fXEdges[i].second = frame[1].X();
132 if (fXEdges[i].first < frame[0].X())
133 fXEdges[i].first = frame[0].X();
134 if (fXEdges[i].second < frame[0].X())
135 fXEdges[i].second = frame[0].X();
139 const Int_t nY = fCoord->GetNYBins();
142 if (fCoord->GetYLog()) {
143 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
144 const Double_t yWidth = fYAxis->GetBinWidth(jr);
145 Double_t low = fYAxis->GetBinLowEdge(jr) + yWidth * barOffset;
146 fYEdges[j].first = TMath::Log10(low) * fCoord->GetYScale();
147 fYEdges[j].second = TMath::Log10(low + yWidth * barWidth) * fCoord->GetYScale();
148 if (fYEdges[j].second > frame[2].Y())
149 fYEdges[j].second = frame[2].Y();
150 if (fYEdges[j].first < frame[0].Y())
151 fYEdges[j].first = frame[0].Y();
152 if (fYEdges[j].second < frame[0].Y())
153 fYEdges[j].second = frame[0].Y();
156 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
157 const Double_t yWidth = fYAxis->GetBinWidth(jr);
158 fYEdges[j].first = (fYAxis->GetBinLowEdge(jr) + yWidth * barOffset) * fCoord->GetYScale();
159 fYEdges[j].second = fYEdges[j].first + yWidth * barWidth * fCoord->GetYScale();
160 if (fYEdges[j].second > frame[2].Y())
161 fYEdges[j].second = frame[2].Y();
162 if (fYEdges[j].first < frame[0].Y())
163 fYEdges[j].first = frame[0].Y();
164 if (fYEdges[j].second < frame[0].Y())
165 fYEdges[j].second = frame[0].Y();
169 fMinZ = frame[0].Z();
171 frame[4].Z() > 0. ? fMinZ = 0. : fMinZ = frame[4].Z();
173 if (fCoord->Modified()) {
174 fUpdateSelection = kTRUE;
175 fXOZSectionPos = frame[0].Y();
176 fYOZSectionPos = frame[0].X();
177 fXOYSectionPos = frame[0].Z();
178 fCoord->ResetModified();
179 Rgl::SetZLevels(fZAxis, fCoord->GetZRange().first, fCoord->GetZRange().second, fCoord->GetZScale(), fZLevels);
182 fMinMaxVal.first = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin());
183 fMinMaxVal.second = fMinMaxVal.first;
185 for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
186 for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
187 Double_t val = fHist->GetBinContent(i, j);
188 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, val);
189 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
193 ClampZ(fMinMaxVal.first);
194 ClampZ(fMinMaxVal.second);
202 Bool_t TGLLegoPainter::InitGeometryPolar()
204 if (!fCoord->SetRanges(fHist, kFALSE, kFALSE))
207 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
209 if (fCoord->Modified()) {
210 fUpdateSelection = kTRUE;
211 fCoord->ResetModified();
214 const Int_t nY = fCoord->GetNYBins();
217 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
218 fYEdges[j].first = ((fYAxis->GetBinLowEdge(jr)) - fCoord->GetYRange().first) /
219 fCoord->GetYLength() * fCoord->GetYScale();
220 fYEdges[j].second = ((fYAxis->GetBinUpEdge(jr)) - fCoord->GetYRange().first) /
221 fCoord->GetYLength() * fCoord->GetYScale();
224 const Int_t nX = fCoord->GetNXBins();
225 fCosSinTableX.resize(nX + 1);
226 const Double_t fullAngle = fXAxis->GetXmax() - fXAxis->GetXmin();
227 const Double_t phiLow = fXAxis->GetXmin();
229 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
230 angle = (fXAxis->GetBinLowEdge(ir) - phiLow) / fullAngle * TMath::TwoPi();
231 fCosSinTableX[i].first = TMath::Cos(angle);
232 fCosSinTableX[i].second = TMath::Sin(angle);
234 angle = (fXAxis->GetBinUpEdge(fCoord->GetLastXBin()) - phiLow) / fullAngle * TMath::TwoPi();
235 fCosSinTableX[nX].first = TMath::Cos(angle);
236 fCosSinTableX[nX].second = TMath::Sin(angle);
238 fMinZ = fBackBox.Get3DBox()[0].Z();
240 fBackBox.Get3DBox()[4].Z() > 0. ? fMinZ = 0. : fMinZ = fBackBox.Get3DBox()[4].Z();
242 fMinMaxVal.first = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin());
243 fMinMaxVal.second = fMinMaxVal.first;
245 for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
246 for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
247 Double_t val = fHist->GetBinContent(i, j);
248 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, val);
249 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
253 ClampZ(fMinMaxVal.first);
254 ClampZ(fMinMaxVal.second);
262 Bool_t TGLLegoPainter::InitGeometryCylindrical()
264 if (!fCoord->SetRanges(fHist, kFALSE, kFALSE))
267 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
269 const Int_t nY = fCoord->GetNYBins();
272 if (fCoord->GetYLog()) {
273 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
274 fYEdges[j].first = TMath::Log10(fYAxis->GetBinLowEdge(jr)) * fCoord->GetYScale();
275 fYEdges[j].second = TMath::Log10(fYAxis->GetBinUpEdge(jr)) * fCoord->GetYScale();
278 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
279 fYEdges[j].first = fYAxis->GetBinLowEdge(jr) * fCoord->GetYScale();
280 fYEdges[j].second = fYAxis->GetBinUpEdge(jr) * fCoord->GetYScale();
284 const Int_t nX = fCoord->GetNXBins();
285 fCosSinTableX.resize(nX + 1);
286 const Double_t fullAngle = fXAxis->GetXmax() - fXAxis->GetXmin();
287 const Double_t phiLow = fXAxis->GetXmin();
289 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
290 angle = (fXAxis->GetBinLowEdge(ir) - phiLow) / fullAngle * TMath::TwoPi();
291 fCosSinTableX[i].first = TMath::Cos(angle);
292 fCosSinTableX[i].second = TMath::Sin(angle);
294 angle = (fXAxis->GetBinUpEdge(fCoord->GetLastXBin()) - phiLow) / fullAngle * TMath::TwoPi();
295 fCosSinTableX[nX].first = TMath::Cos(angle);
296 fCosSinTableX[nX].second = TMath::Sin(angle);
298 if (fCoord->Modified()) {
299 fUpdateSelection = kTRUE;
300 fCoord->ResetModified();
303 fMinZ = fCoord->GetZRange().first;
305 fCoord->GetZRange().second > 0. ? fMinZ = 0. : fMinZ = fCoord->GetZRange().second;
308 fMinMaxVal.first = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin());
309 fMinMaxVal.second = fMinMaxVal.first;
311 for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
312 for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
313 Double_t val = fHist->GetBinContent(i, j);
314 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, val);
315 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
325 Bool_t TGLLegoPainter::InitGeometrySpherical()
327 if (!fCoord->SetRanges(fHist, kFALSE, kFALSE))
330 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
332 const Int_t nY = fCoord->GetNYBins();
333 fCosSinTableY.resize(nY + 1);
334 const Double_t fullTheta = fYAxis->GetXmax() - fYAxis->GetXmin();
335 const Double_t thetaLow = fYAxis->GetXmin();
337 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
338 angle = (fYAxis->GetBinLowEdge(jr) - thetaLow) / fullTheta * TMath::Pi();
339 fCosSinTableY[j].first = TMath::Cos(angle);
340 fCosSinTableY[j].second = TMath::Sin(angle);
342 angle = (fYAxis->GetBinUpEdge(fCoord->GetLastYBin()) - thetaLow) / fullTheta * TMath::Pi();
343 fCosSinTableY[nY].first = TMath::Cos(angle);
344 fCosSinTableY[nY].second = TMath::Sin(angle);
346 const Int_t nX = fCoord->GetNXBins();
347 fCosSinTableX.resize(nX + 1);
348 const Double_t fullPhi = fXAxis->GetXmax() - fXAxis->GetXmin();
349 const Double_t phiLow = fXAxis->GetXmin();
351 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
352 angle = (fXAxis->GetBinLowEdge(ir) - phiLow) / fullPhi * TMath::TwoPi();
353 fCosSinTableX[i].first = TMath::Cos(angle);
354 fCosSinTableX[i].second = TMath::Sin(angle);
357 angle = (fXAxis->GetBinUpEdge(fCoord->GetLastXBin()) - phiLow) / fullPhi * TMath::TwoPi();
358 fCosSinTableX[nX].first = TMath::Cos(angle);
359 fCosSinTableX[nX].second = TMath::Sin(angle);
361 fMinZ = fCoord->GetZRange().first;
363 fCoord->GetZRange().second > 0. ? fMinZ = 0. : fMinZ = fCoord->GetZRange().second;
365 fMinMaxVal.first = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin());
366 fMinMaxVal.second = fMinMaxVal.first;
368 for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
369 for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
370 Double_t val = fHist->GetBinContent(i, j);
371 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, val);
372 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
383 void TGLLegoPainter::StartPan(Int_t px, Int_t py)
385 fMousePosition.fX = px;
386 fMousePosition.fY = fCamera->GetHeight() - py;
387 fCamera->StartPan(px, py);
388 fBoxCut.StartMovement(px, py);
394 void TGLLegoPainter::Pan(Int_t px, Int_t py)
396 if (fSelectedPart >= fSelectionBase || fSelectedPart == 1) {
397 SaveModelviewMatrix();
398 SaveProjectionMatrix();
400 fCamera->SetCamera();
401 fCamera->Apply(fPadPhi, fPadTheta);
402 fCamera->Pan(px, py);
404 RestoreProjectionMatrix();
405 RestoreModelviewMatrix();
406 }
else if (fSelectedPart > 0) {
408 py = fCamera->GetHeight() - py;
410 SaveModelviewMatrix();
411 SaveProjectionMatrix();
413 fCamera->SetCamera();
414 fCamera->Apply(fPadPhi, fPadTheta);
417 if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis))
418 fBoxCut.MoveBox(px, py, fSelectedPart);
424 RestoreProjectionMatrix();
425 RestoreModelviewMatrix();
428 fMousePosition.fX = px, fMousePosition.fY = py;
429 fUpdateSelection = kTRUE;
435 void TGLLegoPainter::AddOption(
const TString &option)
438 const Ssiz_t legoPos = option.Index(
"lego");
439 if (legoPos + 4 < option.Length() && isdigit(option[legoPos + 4])) {
440 switch (option[legoPos + 4] -
'0') {
442 fLegoType = kColorSimple;
445 fLegoType = kColorLevel;
448 fLegoType = kCylindricBars;
451 fLegoType = kColorSimple;
455 fLegoType = kColorSimple;
457 Ssiz_t ePos = option.Index(
"e");
458 if (ePos == legoPos + 1)
459 ePos = option.Index(
"e", legoPos + 4);
460 fDrawErrors = ePos != kNPOS ? kTRUE : kFALSE;
462 option.Index(
"z") == kNPOS ? fDrawPalette = kFALSE : fDrawPalette = kTRUE;
468 void TGLLegoPainter::InitGL()
const
470 glEnable(GL_DEPTH_TEST);
471 glEnable(GL_LIGHTING);
474 glEnable(GL_CULL_FACE);
477 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
483 void TGLLegoPainter::DeInitGL()
const
485 glDisable(GL_DEPTH_TEST);
486 glDisable(GL_LIGHTING);
487 glDisable(GL_LIGHT0);
488 glDisable(GL_CULL_FACE);
489 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
495 void TGLLegoPainter::DrawPlot()
const
498 const Rgl::PlotTranslation trGuard(
this);
500 switch (fCoord->GetCoordType()) {
502 return DrawLegoCartesian();
504 return DrawLegoPolar();
506 return DrawLegoCylindrical();
508 return DrawLegoSpherical();
516 void TGLLegoPainter::DrawLegoCartesian()
const
518 if (fCoord->GetCoordType() == kGLCartesian) {
519 fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
520 const TGLDisableGuard cullGuard(GL_CULL_FACE);
526 if (!fSelectionPass) {
527 glEnable(GL_POLYGON_OFFSET_FILL);
528 glPolygonOffset(1.f, 1.f);
530 if (fXOZSectionPos > fBackBox.Get3DBox()[0].Y() || fYOZSectionPos> fBackBox.Get3DBox()[0].X()) {
533 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
540 const Int_t nX = fXEdges.size();
541 const Int_t nY = fYEdges.size();
542 const Int_t frontPoint = fBackBox.GetFrontPoint();
543 Int_t iInit = 0, jInit = 0, irInit = fCoord->GetFirstXBin(), jrInit = fCoord->GetFirstYBin();
544 const Int_t addI = frontPoint == 2 || frontPoint == 1 ? 1 : (iInit = nX - 1, irInit = fCoord->GetLastXBin(), -1);
545 const Int_t addJ = frontPoint == 2 || frontPoint == 3 ? 1 : (jInit = nY - 1, jrInit = fCoord->GetLastYBin(), -1);
547 if (fLegoType == kColorLevel && !fSelectionPass) {
548 if (!PreparePalette()) {
549 fLegoType = kColorSimple;
550 fDrawPalette = kFALSE;
552 fPalette.EnableTexture(GL_MODULATE);
555 if (fSelectionPass && fHighColor)
556 Rgl::ObjectIDToColor(fSelectionBase, kTRUE);
558 for(Int_t i = iInit, ir = irInit; addI > 0 ? i < nX : i >= 0; i += addI, ir += addI) {
559 for(Int_t j = jInit, jr = jrInit; addJ > 0 ? j < nY : j >= 0; j += addJ, jr += addJ) {
560 Double_t zMax = fHist->GetBinContent(ir, jr) * fCoord->GetFactor();
564 const Int_t binID = fSelectionBase + i * fCoord->GetNYBins() + j;
566 if (fSelectionPass && !fHighColor)
567 Rgl::ObjectIDToColor(binID, kFALSE);
568 else if(!fHighColor && fSelectedPart == binID)
569 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gOrangeEmission);
571 if (fLegoType == kCylindricBars) {
572 Rgl::DrawCylinder(&fQuadric, fXEdges[i].first, fXEdges[i].second, fYEdges[j].first,
573 fYEdges[j].second, fMinZ, zMax);
574 }
else if (fLegoType == kColorLevel && !fSelectionPass) {
575 Rgl::DrawBoxFrontTextured(fXEdges[i].first, fXEdges[i].second, fYEdges[j].first,
576 fYEdges[j].second, fMinZ, zMax, fPalette.GetTexCoord(fMinZ),
577 fPalette.GetTexCoord(zMax), frontPoint);
579 Rgl::DrawBoxFront(fXEdges[i].first, fXEdges[i].second, fYEdges[j].first,
580 fYEdges[j].second, fMinZ, zMax, frontPoint);
583 if (!fHighColor && !fSelectionPass && fSelectedPart == binID)
584 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gNullEmission);
588 if (fLegoType == kColorLevel && !fSelectionPass)
589 fPalette.DisableTexture();
592 if (!fSelectionPass) {
593 glDisable(GL_POLYGON_OFFSET_FILL);
594 const TGLDisableGuard lightGuard(GL_LIGHTING);
595 if (fXOZSectionPos <= fBackBox.Get3DBox()[0].Y() && fYOZSectionPos <= fBackBox.Get3DBox()[0].X())
596 glColor3d(0., 0., 0.);
598 glColor4d(0., 0., 0., 0.4);
599 glPolygonMode(GL_FRONT, GL_LINE);
601 const TGLEnableGuard blendGuard(GL_BLEND);
602 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
603 const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
604 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
606 for(Int_t i = iInit, ir = irInit; addI > 0 ? i < nX : i >= 0; i += addI, ir += addI) {
607 for(Int_t j = jInit, jr = jrInit; addJ > 0 ? j < nY : j >= 0; j += addJ, jr += addJ) {
608 Double_t zMax = fHist->GetBinContent(ir, jr) * fCoord->GetFactor();
611 if (fLegoType != kCylindricBars) {
612 Rgl::DrawBoxFront(fXEdges[i].first, fXEdges[i].second, fYEdges[j].first,
613 fYEdges[j].second, fMinZ, zMax, frontPoint);
615 if (fDrawErrors && zMax > 0.) {
616 Double_t errorZMax = (fHist->GetBinContent(ir, jr) + fHist->GetBinError(ir, jr)) * fCoord->GetFactor();
618 Rgl::DrawError(fXEdges[i].first, fXEdges[i].second, fYEdges[j].first,
619 fYEdges[j].second, zMax, errorZMax);
624 glPolygonMode(GL_FRONT, GL_FILL);
627 if(!fSelectionPass && fDrawPalette)
634 void TGLLegoPainter::DrawLegoPolar()
const
636 const Int_t nX = fCosSinTableX.size() - 1;
637 const Int_t nY = fYEdges.size();
639 if (!fSelectionPass) {
641 glEnable(GL_POLYGON_OFFSET_FILL);
642 glPolygonOffset(1.f, 1.f);
645 Double_t points[4][2] = {};
647 if (fLegoType == kColorLevel && !fSelectionPass) {
648 if (!PreparePalette()) {
649 fLegoType = kColorSimple;
650 fDrawPalette = kFALSE;
652 fPalette.EnableTexture(GL_MODULATE);
655 if (fHighColor && fSelectionPass)
656 Rgl::ObjectIDToColor(fSelectionBase, kTRUE);
658 for(Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
659 for(Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
660 Double_t zMax = fHist->GetBinContent(ir, jr);
663 points[0][0] = fYEdges[j].first * fCosSinTableX[i].first;
664 points[0][1] = fYEdges[j].first * fCosSinTableX[i].second;
665 points[1][0] = fYEdges[j].second * fCosSinTableX[i].first;
666 points[1][1] = fYEdges[j].second * fCosSinTableX[i].second;
667 points[2][0] = fYEdges[j].second * fCosSinTableX[i + 1].first;
668 points[2][1] = fYEdges[j].second * fCosSinTableX[i + 1].second;
669 points[3][0] = fYEdges[j].first * fCosSinTableX[i + 1].first;
670 points[3][1] = fYEdges[j].first * fCosSinTableX[i + 1].second;
672 const Int_t binID = fSelectionBase + i * fCoord->GetNYBins() + j;
674 if (!fHighColor && fSelectionPass)
675 Rgl::ObjectIDToColor(binID, kFALSE);
676 else if(!fHighColor && fSelectedPart == binID)
677 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gOrangeEmission);
679 if (fLegoType == kColorLevel && !fSelectionPass)
680 Rgl::DrawTrapezoidTextured(points, fMinZ, zMax, fPalette.GetTexCoord(fMinZ),
681 fPalette.GetTexCoord(zMax));
683 Rgl::DrawTrapezoid(points, fMinZ, zMax);
685 if (!fHighColor && !fSelectionPass && fSelectedPart == binID)
686 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gNullEmission);
690 if (fLegoType == kColorLevel && !fSelectionPass)
691 fPalette.DisableTexture();
694 if (!fSelectionPass) {
695 glDisable(GL_POLYGON_OFFSET_FILL);
696 const TGLDisableGuard lightGuard(GL_LIGHTING);
697 glColor3d(0., 0., 0.);
698 glPolygonMode(GL_FRONT, GL_LINE);
699 const TGLEnableGuard blendGuard(GL_BLEND);
700 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
701 const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
702 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
704 for(Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
705 for(Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
706 Double_t zMax = fHist->GetBinContent(ir, jr);
709 points[0][0] = fYEdges[j].first * fCosSinTableX[i].first;
710 points[0][1] = fYEdges[j].first * fCosSinTableX[i].second;
711 points[1][0] = fYEdges[j].second * fCosSinTableX[i].first;
712 points[1][1] = fYEdges[j].second * fCosSinTableX[i].second;
713 points[2][0] = fYEdges[j].second * fCosSinTableX[i + 1].first;
714 points[2][1] = fYEdges[j].second * fCosSinTableX[i + 1].second;
715 points[3][0] = fYEdges[j].first * fCosSinTableX[i + 1].first;
716 points[3][1] = fYEdges[j].first * fCosSinTableX[i + 1].second;
717 Rgl::DrawTrapezoid(points, fMinZ, zMax, kFALSE);
721 glPolygonMode(GL_FRONT, GL_FILL);
724 if(!fSelectionPass && fDrawPalette)
731 void TGLLegoPainter::DrawLegoCylindrical()
const
733 const Int_t nX = fCosSinTableX.size() - 1;
734 const Int_t nY = fYEdges.size();
735 Double_t legoR = gStyle->GetLegoInnerR();
736 if (legoR > 1. || legoR < 0.)
738 const Double_t rRange = fCoord->GetZLength();
740 if (!fSelectionPass) {
742 glEnable(GL_POLYGON_OFFSET_FILL);
743 glPolygonOffset(1.f, 1.f);
746 Double_t points[4][2] = {};
747 const Double_t sc = (1 - legoR) * fCoord->GetXScale();
748 legoR *= fCoord->GetXScale();
750 if (fLegoType == kColorLevel && !fSelectionPass) {
751 if (!PreparePalette()) {
752 fLegoType = kColorSimple;
753 fDrawPalette = kFALSE;
755 fPalette.EnableTexture(GL_MODULATE);
758 if (fHighColor && fSelectionPass)
759 Rgl::ObjectIDToColor(fSelectionBase, kTRUE);
761 for(Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
762 for(Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
763 Double_t zMin = legoR + (fMinZ - fCoord->GetZRange().first) / rRange * sc;
764 Double_t zMax = legoR + (fHist->GetBinContent(ir, jr) - fCoord->GetZRange().first) / rRange * sc;
766 std::swap(zMin, zMax);
768 points[0][0] = fCosSinTableX[i].first * zMin;
769 points[0][1] = fCosSinTableX[i].second * zMin;
770 points[1][0] = fCosSinTableX[i].first * zMax;
771 points[1][1] = fCosSinTableX[i].second * zMax;
772 points[2][0] = fCosSinTableX[i + 1].first * zMax;
773 points[2][1] = fCosSinTableX[i + 1].second * zMax;
774 points[3][0] = fCosSinTableX[i + 1].first * zMin;
775 points[3][1] = fCosSinTableX[i + 1].second * zMin;
777 const Int_t binID = fSelectionBase + i * fCoord->GetNYBins() + j;
779 if (fSelectionPass && !fHighColor)
780 Rgl::ObjectIDToColor(binID, kFALSE);
781 else if(!fHighColor && fSelectedPart == binID)
782 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gOrangeEmission);
784 if (fLegoType == kColorLevel && !fSelectionPass){
785 Rgl::DrawTrapezoidTextured2(points, fYEdges[j].first, fYEdges[j].second,
786 fPalette.GetTexCoord(fMinZ), fPalette.GetTexCoord(fHist->GetBinContent(ir, jr)));
788 Rgl::DrawTrapezoid(points, fYEdges[j].first, fYEdges[j].second);
790 if(!fSelectionPass && !fHighColor && fSelectedPart == binID)
791 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gNullEmission);
795 if (fLegoType == kColorLevel && !fSelectionPass)
796 fPalette.DisableTexture();
799 if (!fSelectionPass) {
800 glDisable(GL_POLYGON_OFFSET_FILL);
801 const TGLDisableGuard lightGuard(GL_LIGHTING);
802 glColor3d(0., 0., 0.);
803 glPolygonMode(GL_FRONT, GL_LINE);
805 const TGLEnableGuard blendGuard(GL_BLEND);
806 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
807 const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
808 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
810 for(Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
811 for(Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
812 Double_t zMin = legoR + (fMinZ - fCoord->GetZRange().first) / rRange * sc;
813 Double_t zMax = legoR + (fHist->GetBinContent(ir, jr) - fCoord->GetZRange().first) / rRange * sc;
815 std::swap(zMin, zMax);
817 points[0][0] = fCosSinTableX[i].first * zMin;
818 points[0][1] = fCosSinTableX[i].second * zMin;
819 points[1][0] = fCosSinTableX[i].first * zMax;
820 points[1][1] = fCosSinTableX[i].second * zMax;
821 points[2][0] = fCosSinTableX[i + 1].first * zMax;
822 points[2][1] = fCosSinTableX[i + 1].second * zMax;
823 points[3][0] = fCosSinTableX[i + 1].first * zMin;
824 points[3][1] = fCosSinTableX[i + 1].second * zMin;
825 Rgl::DrawTrapezoid(points, fYEdges[j].first, fYEdges[j].second);
829 glPolygonMode(GL_FRONT, GL_FILL);
832 if(!fSelectionPass && fDrawPalette)
839 void TGLLegoPainter::DrawLegoSpherical()
const
841 const Int_t nX = fCosSinTableX.size() - 1;
842 const Int_t nY = fCosSinTableY.size() - 1;
843 const Double_t rRange = fCoord->GetZLength();
844 Double_t legoR = gStyle->GetLegoInnerR();
845 if (legoR > 1. || legoR < 0.)
848 if (!fSelectionPass) {
850 glEnable(GL_POLYGON_OFFSET_FILL);
851 glPolygonOffset(1.f, 1.f);
854 Double_t points[8][3] = {};
855 const Double_t sc = 1 - legoR;
857 if (fLegoType == kColorLevel && !fSelectionPass) {
858 if (!PreparePalette()) {
859 fLegoType = kColorSimple;
860 fDrawPalette = kFALSE;
862 fPalette.EnableTexture(GL_MODULATE);
865 if (fSelectionPass && fHighColor)
866 Rgl::ObjectIDToColor(fSelectionBase, kTRUE);
868 for(Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
869 for(Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
870 Double_t zMin = legoR + (fMinZ - fCoord->GetZRange().first) / rRange * sc;
871 Double_t zMax = legoR + (fHist->GetBinContent(ir, jr) - fCoord->GetZRange().first) / rRange * sc;
873 std::swap(zMin, zMax);
875 points[4][0] = zMin * fCosSinTableY[j].second * fCosSinTableX[i].first;
876 points[4][1] = zMin * fCosSinTableY[j].second * fCosSinTableX[i].second;
877 points[4][2] = zMin * fCosSinTableY[j].first;
878 points[5][0] = zMin * fCosSinTableY[j].second * fCosSinTableX[i + 1].first;
879 points[5][1] = zMin * fCosSinTableY[j].second * fCosSinTableX[i + 1].second;
880 points[5][2] = zMin * fCosSinTableY[j].first;
881 points[6][0] = zMax * fCosSinTableY[j].second * fCosSinTableX[i + 1].first;
882 points[6][1] = zMax * fCosSinTableY[j].second * fCosSinTableX[i + 1].second;
883 points[6][2] = zMax * fCosSinTableY[j].first;
884 points[7][0] = zMax * fCosSinTableY[j].second * fCosSinTableX[i].first;
885 points[7][1] = zMax * fCosSinTableY[j].second * fCosSinTableX[i].second;
886 points[7][2] = zMax * fCosSinTableY[j].first;
887 points[0][0] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i].first;
888 points[0][1] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i].second;
889 points[0][2] = zMin * fCosSinTableY[j + 1].first;
890 points[1][0] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].first;
891 points[1][1] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].second;
892 points[1][2] = zMin * fCosSinTableY[j + 1].first;
893 points[2][0] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].first;
894 points[2][1] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].second;
895 points[2][2] = zMax * fCosSinTableY[j + 1].first;
896 points[3][0] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i].first;
897 points[3][1] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i].second;
898 points[3][2] = zMax * fCosSinTableY[j + 1].first;
900 const Int_t binID = fSelectionBase + i * fCoord->GetNYBins() + j;
902 if (fSelectionPass && !fHighColor)
903 Rgl::ObjectIDToColor(binID, kFALSE);
904 else if(!fHighColor && fSelectedPart == binID)
905 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gOrangeEmission);
906 if (fLegoType == kColorLevel && !fSelectionPass)
907 Rgl::DrawTrapezoidTextured(points, fPalette.GetTexCoord(fMinZ),
908 fPalette.GetTexCoord(fHist->GetBinContent(ir, jr)));
910 Rgl::DrawTrapezoid(points);
912 if(!fHighColor && fSelectedPart == binID)
913 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gNullEmission);
917 if (fLegoType == kColorLevel && !fSelectionPass)
918 fPalette.DisableTexture();
921 if (!fSelectionPass) {
922 glDisable(GL_POLYGON_OFFSET_FILL);
923 const TGLDisableGuard lightGuard(GL_LIGHTING);
924 glColor3d(0., 0., 0.);
925 glPolygonMode(GL_FRONT, GL_LINE);
926 const TGLEnableGuard blendGuard(GL_BLEND);
927 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
928 const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
929 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
931 for(Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
932 for(Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
933 Double_t zMin = legoR + (fMinZ - fCoord->GetZRange().first) / rRange * sc;
934 Double_t zMax = legoR + (fHist->GetBinContent(ir, jr) - fCoord->GetZRange().first) / rRange * sc;
936 std::swap(zMin, zMax);
938 points[4][0] = zMin * fCosSinTableY[j].second * fCosSinTableX[i].first;
939 points[4][1] = zMin * fCosSinTableY[j].second * fCosSinTableX[i].second;
940 points[4][2] = zMin * fCosSinTableY[j].first;
941 points[5][0] = zMin * fCosSinTableY[j].second * fCosSinTableX[i + 1].first;
942 points[5][1] = zMin * fCosSinTableY[j].second * fCosSinTableX[i + 1].second;
943 points[5][2] = zMin * fCosSinTableY[j].first;
944 points[6][0] = zMax * fCosSinTableY[j].second * fCosSinTableX[i + 1].first;
945 points[6][1] = zMax * fCosSinTableY[j].second * fCosSinTableX[i + 1].second;
946 points[6][2] = zMax * fCosSinTableY[j].first;
947 points[7][0] = zMax * fCosSinTableY[j].second * fCosSinTableX[i].first;
948 points[7][1] = zMax * fCosSinTableY[j].second * fCosSinTableX[i].second;
949 points[7][2] = zMax * fCosSinTableY[j].first;
950 points[0][0] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i].first;
951 points[0][1] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i].second;
952 points[0][2] = zMin * fCosSinTableY[j + 1].first;
953 points[1][0] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].first;
954 points[1][1] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].second;
955 points[1][2] = zMin * fCosSinTableY[j + 1].first;
956 points[2][0] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].first;
957 points[2][1] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].second;
958 points[2][2] = zMax * fCosSinTableY[j + 1].first;
959 points[3][0] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i].first;
960 points[3][1] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i].second;
961 points[3][2] = zMax * fCosSinTableY[j + 1].first;
962 Rgl::DrawTrapezoid(points);
966 glPolygonMode(GL_FRONT, GL_FILL);
969 if(!fSelectionPass && fDrawPalette)
976 void TGLLegoPainter::SetLegoColor()
const
978 Float_t diffColor[] = {0.8f, 0.8f, 0.8f, 0.15f};
980 if (fLegoType != kColorLevel && fHist->GetFillColor() != kWhite)
981 if (
const TColor *c = gROOT->GetColor(fHist->GetFillColor()))
982 c->GetRGB(diffColor[0], diffColor[1], diffColor[2]);
984 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffColor);
985 const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
986 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
987 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
993 void TGLLegoPainter::DrawSectionXOZ()
const
997 for (Int_t i = 0, e = fYEdges.size(); i < e; ++i) {
998 if (fYEdges[i].first <= fXOZSectionPos && fXOZSectionPos <= fYEdges[i].second) {
1005 binY += fCoord->GetFirstYBin();
1006 glColor3d(1., 0., 0.);
1009 for (UInt_t i = 0, ir = fCoord->GetFirstXBin(), e = fXEdges.size(); i < e; ++i, ++ir) {
1010 Double_t zMax = fHist->GetBinContent(Int_t(ir), binY);
1014 glBegin(GL_LINE_LOOP);
1015 glVertex3d(fXEdges[i].first, fXOZSectionPos, fMinZ);
1016 glVertex3d(fXEdges[i].first, fXOZSectionPos, zMax);
1017 glVertex3d(fXEdges[i].second, fXOZSectionPos, zMax);
1018 glVertex3d(fXEdges[i].second, fXOZSectionPos, fMinZ);
1029 void TGLLegoPainter::DrawSectionYOZ()
const
1033 for (Int_t i = 0, e = fXEdges.size(); i < e; ++i) {
1034 if (fXEdges[i].first <= fYOZSectionPos && fYOZSectionPos <= fXEdges[i].second) {
1041 binX += fCoord->GetFirstXBin();
1042 glColor3d(1., 0., 0.);
1045 for (UInt_t i = 0, ir = fCoord->GetFirstYBin(), e = fYEdges.size(); i < e; ++i, ++ir) {
1046 Double_t zMax = fHist->GetBinContent(binX, ir);
1050 glBegin(GL_LINE_LOOP);
1051 glVertex3d(fYOZSectionPos, fYEdges[i].first, fMinZ);
1052 glVertex3d(fYOZSectionPos, fYEdges[i].first, zMax);
1053 glVertex3d(fYOZSectionPos, fYEdges[i].second, zMax);
1054 glVertex3d(fYOZSectionPos, fYEdges[i].second, fMinZ);
1065 void TGLLegoPainter::DrawSectionXOY()
const
1072 void TGLLegoPainter::ProcessEvent(Int_t event, Int_t , Int_t py)
1074 const TGLVertex3 *frame = fBackBox.Get3DBox();
1075 if (event == kButton1Double && (fXOZSectionPos > frame[0].Y() || fYOZSectionPos > frame[0].X())) {
1076 fXOZSectionPos = frame[0].Y();
1077 fYOZSectionPos = frame[0].X();
1078 if (fBoxCut.IsActive())
1079 fBoxCut.TurnOnOff();
1081 if (!gVirtualX->IsCmdThread())
1082 gROOT->ProcessLineFast(Form(
"((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)
this));
1085 }
else if (event == kKeyPress && (py == kKey_c || py == kKey_C)) {
1086 Info(
"ProcessEvent",
"Box cut does not exist for lego");
1093 Bool_t TGLLegoPainter::ClampZ(Double_t &zVal)
const
1095 if (fCoord->GetZLog())
1099 zVal = TMath::Log10(zVal) * fCoord->GetZScale();
1101 zVal *= fCoord->GetZScale();
1103 const TGLVertex3 *frame = fBackBox.Get3DBox();
1105 if (zVal > frame[4].Z())
1106 zVal = frame[4].Z();
1107 else if (zVal < frame[0].Z())
1108 zVal = frame[0].Z();
1116 Bool_t TGLLegoPainter::PreparePalette()
const
1118 if(fMinMaxVal.first == fMinMaxVal.second)
1122 if (fHist->TestBit(TH1::kUserContour))
1123 fHist->ResetBit(TH1::kUserContour);
1125 UInt_t paletteSize = gStyle->GetNumberContours();
1129 return fPalette.GeneratePalette(paletteSize, Rgl::Range_t(fMinZ, fMinMaxVal.second));
1137 void TGLLegoPainter::DrawPalette()
const
1144 Rgl::DrawPalette(fCamera, fPalette);
1148 fCamera->SetCamera();
1149 fCamera->Apply(fPadPhi, fPadTheta);
1155 void TGLLegoPainter::DrawPaletteAxis()
const
1157 gVirtualX->SetDrawMode(TVirtualX::kCopy);
1158 Rgl::DrawPaletteAxis(fCamera, fMinMaxVal, fCoord->GetCoordType() == kGLCartesian ? fCoord->GetZLog() : kFALSE);