36 ClassImp(TGLBoxPainter);
41 TGLBoxPainter::TGLBoxPainter(TH1 *hist, TGLPlotCamera *cam, TGLPlotCoordinates *coord)
42 : TGLPlotPainter(hist, cam, coord, kTRUE, kTRUE, kTRUE),
43 fXOZSlice(
"XOZ", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kXOZ),
44 fYOZSlice(
"YOZ", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kYOZ),
45 fXOYSlice(
"XOY", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kXOY),
55 TGLBoxPainter::TGLBoxPainter(TH1 *hist, TPolyMarker3D * pm,
56 TGLPlotCamera *cam, TGLPlotCoordinates *coord)
57 : TGLPlotPainter(hist, cam, coord, kFALSE, kFALSE, kFALSE),
58 fXOZSlice(
"XOZ", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kXOZ),
59 fYOZSlice(
"YOZ", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kYOZ),
60 fXOYSlice(
"XOY", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kXOY),
69 char *TGLBoxPainter::GetPlotInfo(Int_t, Int_t)
74 if (fSelectedPart < fSelectionBase) {
76 fPlotInfo += fHist->Class()->GetName();
78 fPlotInfo += fHist->GetName();
79 }
else if (!fHighColor){
80 const Int_t arr2Dsize = fCoord->GetNYBins() * fCoord->GetNZBins();
81 const Int_t binI = (fSelectedPart - fSelectionBase) / arr2Dsize + fCoord->GetFirstXBin();
82 const Int_t binJ = (fSelectedPart - fSelectionBase) % arr2Dsize / fCoord->GetNZBins() + fCoord->GetFirstYBin();
83 const Int_t binK = (fSelectedPart - fSelectionBase) % arr2Dsize % fCoord->GetNZBins() + fCoord->GetFirstZBin();
85 fPlotInfo.Form(
"(binx = %d; biny = %d; binz = %d; binc = %f)", binI, binJ, binK,
86 fHist->GetBinContent(binI, binJ, binK));
88 fPlotInfo =
"Switch to true color mode to get correct info";
91 return (Char_t *)fPlotInfo.Data();
97 Bool_t TGLBoxPainter::InitGeometry()
99 fCoord->SetZLog(kFALSE);
100 fCoord->SetYLog(kFALSE);
101 fCoord->SetXLog(kFALSE);
103 if (!fCoord->SetRanges(fHist, kFALSE, kTRUE))
106 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
107 if(fCamera) fCamera->SetViewVolume(fBackBox.Get3DBox());
109 fMinMaxVal.second = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin(), fCoord->GetFirstZBin());
110 fMinMaxVal.first = fMinMaxVal.second;
112 for (Int_t ir = fCoord->GetFirstXBin(); ir <= fCoord->GetLastXBin(); ++ir) {
113 for (Int_t jr = fCoord->GetFirstYBin(); jr <= fCoord->GetLastYBin(); ++jr) {
114 for (Int_t kr = fCoord->GetFirstZBin(); kr <= fCoord->GetLastZBin(); ++kr) {
115 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, fHist->GetBinContent(ir, jr, kr));
116 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, fHist->GetBinContent(ir, jr, kr));
121 fXOYSlice.SetMinMax(fMinMaxVal);
122 fXOZSlice.SetMinMax(fMinMaxVal);
123 fYOZSlice.SetMinMax(fMinMaxVal);
126 const Double_t xScale = fCoord->GetXScale();
127 const Double_t yScale = fCoord->GetYScale();
128 const Double_t zScale = fCoord->GetZScale();
130 fPMPoints.assign(fPolymarker->GetP(), fPolymarker->GetP() + fPolymarker->GetN() * 3);
131 for (
unsigned i = 0; i < fPMPoints.size(); i += 3) {
132 fPMPoints[i] *= xScale;
133 fPMPoints[i + 1] *= yScale;
134 fPMPoints[i + 2] *= zScale;
138 if (fCoord->Modified()) {
139 fUpdateSelection = kTRUE;
140 fXOZSectionPos = fBackBox.Get3DBox()[0].Y();
141 fYOZSectionPos = fBackBox.Get3DBox()[0].X();
142 fXOYSectionPos = fBackBox.Get3DBox()[0].Z();
143 fCoord->ResetModified();
152 void TGLBoxPainter::StartPan(Int_t px, Int_t py)
154 fMousePosition.fX = px;
155 fMousePosition.fY = fCamera->GetHeight() - py;
156 fCamera->StartPan(px, py);
157 fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
164 void TGLBoxPainter::Pan(Int_t px, Int_t py)
166 if (fSelectedPart >= fSelectionBase) {
167 SaveModelviewMatrix();
168 SaveProjectionMatrix();
170 fCamera->SetCamera();
171 fCamera->Apply(fPadPhi, fPadTheta);
172 fCamera->Pan(px, py);
174 RestoreProjectionMatrix();
175 RestoreModelviewMatrix();
176 }
else if (fSelectedPart > 0) {
179 py = fCamera->GetHeight() - py;
180 SaveModelviewMatrix();
181 SaveProjectionMatrix();
183 fCamera->SetCamera();
184 fCamera->Apply(fPadPhi, fPadTheta);
188 if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis))
189 fBoxCut.MoveBox(px, py, fSelectedPart);
196 RestoreProjectionMatrix();
197 RestoreModelviewMatrix();
200 fMousePosition.fX = px, fMousePosition.fY = py;
201 fUpdateSelection = kTRUE;
207 void TGLBoxPainter::AddOption(
const TString &option)
211 const Ssiz_t boxPos = option.Index(
"box");
212 if (boxPos + 3 < option.Length() && isdigit(option[boxPos + 3]))
213 option[boxPos + 3] -
'0' == 1 ? fType = kBox1 : fType = kBox;
216 option.Index(
"z") == kNPOS ? fDrawPalette = kFALSE : fDrawPalette = kTRUE;
222 void TGLBoxPainter::ProcessEvent(Int_t event, Int_t , Int_t py)
224 if (event == kButton1Double && (HasSections() || fBoxCut.IsActive())) {
225 fXOZSectionPos = fBackBox.Get3DBox()[0].Y();
226 fYOZSectionPos = fBackBox.Get3DBox()[0].X();
227 fXOYSectionPos = fBackBox.Get3DBox()[0].Z();
228 if (fBoxCut.IsActive())
230 if (!gVirtualX->IsCmdThread())
231 gROOT->ProcessLineFast(Form(
"((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)
this));
234 }
else if (event == kKeyPress && (py == kKey_c || py == kKey_C)) {
236 Info(
"ProcessEvent",
"Switch to true color mode to use box cut");
239 fUpdateSelection = kTRUE;
247 void TGLBoxPainter::InitGL()
const
249 glEnable(GL_DEPTH_TEST);
250 glEnable(GL_LIGHTING);
253 glEnable(GL_CULL_FACE);
256 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
262 void TGLBoxPainter::DeInitGL()
const
264 glDisable(GL_DEPTH_TEST);
265 glDisable(GL_LIGHTING);
266 glDisable(GL_LIGHT0);
267 glDisable(GL_CULL_FACE);
268 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
276 void DrawMinusSigns(Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax,
277 Double_t zMin, Double_t zMax, Int_t fp, Bool_t onSphere, Bool_t transp)
279 const TGLDisableGuard depthTest(GL_DEPTH_TEST);
280 const TGLDisableGuard cullFace(GL_CULL_FACE);
282 const Double_t ratio = onSphere ? 0.4 : 0.15;
283 const Double_t leftX = xMin + ratio * (xMax - xMin), rightX = xMax - ratio * (xMax - xMin);
284 const Double_t leftY = yMin + ratio * (yMax - yMin), rightY = yMax - ratio * (yMax - yMin);
285 const Double_t lowZ = zMin / 2. + zMax / 2. - 0.1 * (zMax - zMin);
286 const Double_t upZ = zMin / 2. + zMax / 2. + 0.1 * (zMax - zMin);
289 const Double_t minusVerts[][3] = {{xMin, leftY, lowZ}, {xMin, leftY, upZ}, {xMin, rightY, upZ}, {xMin, rightY, lowZ},
290 {leftX, yMin, lowZ}, {rightX, yMin, lowZ}, {rightX, yMin, upZ}, {leftX, yMin, upZ},
291 {xMax, leftY, lowZ}, {xMax, rightY, lowZ}, {xMax, rightY, upZ}, {xMax, leftY, upZ},
292 {rightX, yMax, lowZ}, {leftX, yMax, lowZ}, {leftX, yMax, upZ}, {rightX, yMax, upZ}};
293 const Int_t minusQuads[][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}, {12, 13, 14, 15}};
296 TGLDisableGuard light(GL_LIGHTING);
297 glColor3d(1., 0., 0.);
299 const Int_t frontPlanes[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0}};
300 const Int_t *verts = minusQuads[frontPlanes[fp][0]];
303 glVertex3dv(minusVerts[verts[0]]);
304 glVertex3dv(minusVerts[verts[1]]);
305 glVertex3dv(minusVerts[verts[2]]);
306 glVertex3dv(minusVerts[verts[3]]);
309 verts = minusQuads[frontPlanes[fp][1]];
312 glVertex3dv(minusVerts[verts[0]]);
313 glVertex3dv(minusVerts[verts[1]]);
314 glVertex3dv(minusVerts[verts[2]]);
315 glVertex3dv(minusVerts[verts[3]]);
318 const Float_t nullEmission[] = {0.f, 0.f, 0.f, 1.f};
319 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, nullEmission);
320 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, nullEmission);
322 glColor4d(0., 0., 0., 0.25);
323 glPolygonMode(GL_FRONT, GL_LINE);
327 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
330 glEnable(GL_LINE_SMOOTH);
331 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
333 verts = minusQuads[frontPlanes[fp][0]];
336 glVertex3dv(minusVerts[verts[0]]);
337 glVertex3dv(minusVerts[verts[1]]);
338 glVertex3dv(minusVerts[verts[2]]);
339 glVertex3dv(minusVerts[verts[3]]);
342 verts = minusQuads[frontPlanes[fp][1]];
345 glVertex3dv(minusVerts[verts[0]]);
346 glVertex3dv(minusVerts[verts[1]]);
347 glVertex3dv(minusVerts[verts[2]]);
348 glVertex3dv(minusVerts[verts[3]]);
351 glPolygonMode(GL_FRONT, GL_FILL);
361 void TGLBoxPainter::DrawPlot()
const
369 const Rgl::PlotTranslation trGuard(
this);
371 fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
372 glDisable(GL_CULL_FACE);
374 glEnable(GL_CULL_FACE);
376 if (!fSelectionPass) {
377 glEnable(GL_POLYGON_OFFSET_FILL);
378 glPolygonOffset(1.f, 1.f);
383 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
389 const Int_t frontPoint = fBackBox.GetFrontPoint();
390 Int_t irInit = fCoord->GetFirstXBin(), iInit = 0;
391 const Int_t nX = fCoord->GetNXBins();
392 Int_t jrInit = fCoord->GetFirstYBin(), jInit = 0;
393 const Int_t nY = fCoord->GetNYBins();
394 Int_t krInit = fCoord->GetFirstZBin(), kInit = 0;
395 const Int_t nZ = fCoord->GetNZBins();
397 const Int_t addI = frontPoint == 2 || frontPoint == 1 ? 1 : (iInit = nX - 1, irInit = fCoord->GetLastXBin(), -1);
398 const Int_t addJ = frontPoint == 2 || frontPoint == 3 ? 1 : (jInit = nY - 1, jrInit = fCoord->GetLastYBin(), -1);
399 const Int_t addK = fBackBox.Get2DBox()[frontPoint + 4].Y() < fBackBox.Get2DBox()[frontPoint].Y() ? 1
400 : (kInit = nZ - 1, krInit = fCoord->GetLastZBin(),-1);
401 const Double_t xScale = fCoord->GetXScale();
402 const Double_t yScale = fCoord->GetYScale();
403 const Double_t zScale = fCoord->GetZScale();
404 const TAxis *xA = fXAxis;
405 const TAxis *yA = fYAxis;
406 const TAxis *zA = fZAxis;
408 if (fSelectionPass && fHighColor)
409 Rgl::ObjectIDToColor(fSelectionBase, fHighColor);
411 Double_t maxContent = TMath::Max(TMath::Abs(fMinMaxVal.first), TMath::Abs(fMinMaxVal.second));
415 for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
416 for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
417 for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
418 const Double_t binContent = fHist->GetBinContent(ir, jr, kr);
419 const Double_t w = TMath::Power(TMath::Abs(binContent) / maxContent,1./3.);
423 const Double_t xMin = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 - w * xA->GetBinWidth(ir) / 2);
424 const Double_t xMax = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 + w * xA->GetBinWidth(ir) / 2);
425 const Double_t yMin = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 - w * yA->GetBinWidth(jr) / 2);
426 const Double_t yMax = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 + w * yA->GetBinWidth(jr) / 2);
427 const Double_t zMin = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 - w * zA->GetBinWidth(kr) / 2);
428 const Double_t zMax = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 + w * zA->GetBinWidth(kr) / 2);
430 if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
433 const Int_t binID = fSelectionBase + i * fCoord->GetNZBins() * fCoord->GetNYBins() + j * fCoord->GetNZBins() + k;
435 if (fSelectionPass && !fHighColor)
436 Rgl::ObjectIDToColor(binID, fHighColor);
437 else if(!fHighColor && fSelectedPart == binID)
438 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gOrangeEmission);
441 Rgl::DrawBoxFront(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint);
443 Rgl::DrawSphere(&fQuadric, xMin, xMax, yMin, yMax, zMin, zMax);
446 if (binContent < 0. && !fSelectionPass)
447 DrawMinusSigns(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint, fType != kBox, HasSections());
449 if (!fSelectionPass && !fHighColor && fSelectedPart == binID)
450 glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gNullEmission);
455 if (fBoxCut.IsActive())
456 fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
458 if (!fSelectionPass && fType != kBox1) {
459 glDisable(GL_POLYGON_OFFSET_FILL);
460 TGLDisableGuard lightGuard(GL_LIGHTING);
461 glColor4d(0., 0., 0., 0.25);
462 glPolygonMode(GL_FRONT, GL_LINE);
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);
469 for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
470 for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
471 for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
472 const Double_t w = TMath::Power(TMath::Abs(fHist->GetBinContent(ir, jr, kr)) / maxContent,1./3.);
477 const Double_t xMin = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 - w * xA->GetBinWidth(ir) / 2);
478 const Double_t xMax = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 + w * xA->GetBinWidth(ir) / 2);
479 const Double_t yMin = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 - w * yA->GetBinWidth(jr) / 2);
480 const Double_t yMax = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 + w * yA->GetBinWidth(jr) / 2);
481 const Double_t zMin = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 - w * zA->GetBinWidth(kr) / 2);
482 const Double_t zMax = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 + w * zA->GetBinWidth(kr) / 2);
484 if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
487 Rgl::DrawBoxFront(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint);
492 glPolygonMode(GL_FRONT, GL_FILL);
495 if (!fSelectionPass && fDrawPalette && HasSections())
502 void TGLBoxPainter::DrawCloud()
const
505 const Rgl::PlotTranslation trGuard(
this);
508 fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
510 if (fPhysicalShapeColor)
511 glColor3fv(fPhysicalShapeColor);
513 glDisable(GL_LIGHTING);
515 const TGLVertex3 *bb = fBackBox.Get3DBox();
516 const Double_t dX = (bb[1].X() - bb[0].X()) / 40.;
517 const Double_t dY = (bb[3].Y() - bb[0].Y()) / 40.;
518 const Double_t dZ = (bb[4].Z() - bb[0].Z()) / 40.;
520 TGLUtil::RenderPolyMarkers(*fPolymarker, fPMPoints, dX, dY, dZ);
522 glEnable(GL_LIGHTING);
528 void TGLBoxPainter::SetPlotColor()
const
530 Float_t diffColor[] = {0.8f, 0.8f, 0.8f, 0.05f};
532 if (fPhysicalShapeColor) {
533 diffColor[0] = fPhysicalShapeColor[0];
534 diffColor[1] = fPhysicalShapeColor[1];
535 diffColor[2] = fPhysicalShapeColor[2];
537 if (fHist->GetFillColor() != kWhite)
538 if (
const TColor *c = gROOT->GetColor(fHist->GetFillColor()))
539 c->GetRGB(diffColor[0], diffColor[1], diffColor[2]);
542 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffColor);
543 const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
544 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
545 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
551 void TGLBoxPainter::DrawSectionXOZ()
const
555 fXOZSlice.DrawSlice(fXOZSectionPos / fCoord->GetYScale());
561 void TGLBoxPainter::DrawSectionYOZ()
const
565 fYOZSlice.DrawSlice(fYOZSectionPos / fCoord->GetXScale());
571 void TGLBoxPainter::DrawSectionXOY()
const
575 fXOYSlice.DrawSlice(fXOYSectionPos / fCoord->GetZScale());
581 Bool_t TGLBoxPainter::HasSections()
const
583 return fXOZSectionPos > fBackBox.Get3DBox()[0].Y() || fYOZSectionPos> fBackBox.Get3DBox()[0].X() ||
584 fXOYSectionPos > fBackBox.Get3DBox()[0].Z();
592 void TGLBoxPainter::DrawPalette()
const
599 const TGLLevelPalette * palette = 0;
600 const TGLVertex3 *frame = fBackBox.Get3DBox();
602 if (fXOZSectionPos > frame[0].Y())
603 palette = &fXOZSlice.GetPalette();
604 else if (fYOZSectionPos > frame[0].X())
605 palette = &fYOZSlice.GetPalette();
606 else if (fXOYSectionPos > frame[0].Z())
607 palette = &fXOYSlice.GetPalette();
609 if (!palette || !palette->GetPaletteSize()) {
613 Rgl::DrawPalette(fCamera, *palette);
617 fCamera->SetCamera();
618 fCamera->Apply(fPadPhi, fPadTheta);
624 void TGLBoxPainter::DrawPaletteAxis()
const
627 gVirtualX->SetDrawMode(TVirtualX::kCopy);
628 Rgl::DrawPaletteAxis(fCamera, fMinMaxVal, fCoord->GetCoordType() == kGLCartesian ? fCoord->GetZLog() : kFALSE);