22 ClassImp(TGLTH3Composition);
27 TGLTH3Composition::TGLTH3Composition()
33 void CompareAxes(
const TAxis *a1,
const TAxis *a2,
const TString &axisName);
41 void TGLTH3Composition::AddTH3(
const TH3 *h, ETH3BinShape shape)
43 const TAxis *xa = h->GetXaxis();
44 const TAxis *ya = h->GetYaxis();
45 const TAxis *za = h->GetZaxis();
50 fXaxis.Set(h->GetNbinsX(), xa->GetBinLowEdge(xa->GetFirst()), xa->GetBinUpEdge(xa->GetLast()));
51 fYaxis.Set(h->GetNbinsY(), ya->GetBinLowEdge(ya->GetFirst()), ya->GetBinUpEdge(ya->GetLast()));
52 fZaxis.Set(h->GetNbinsZ(), za->GetBinLowEdge(za->GetFirst()), za->GetBinUpEdge(za->GetLast()));
54 CompareAxes(xa, GetXaxis(),
"X");
55 CompareAxes(ya, GetYaxis(),
"Y");
56 CompareAxes(za, GetZaxis(),
"Z");
59 fHists.push_back(TH3Pair_t(h, shape));
65 Int_t TGLTH3Composition::DistancetoPrimitive(Int_t px, Int_t py)
70 return fPainter->DistancetoPrimitive(px, py);
76 void TGLTH3Composition::ExecuteEvent(Int_t event, Int_t px, Int_t py)
78 fPainter->ExecuteEvent(event, px, py);
85 char *TGLTH3Composition::GetObjectInfo(Int_t , Int_t )
const
87 static char message[] =
"TH3 composition";
94 void TGLTH3Composition::Paint(Option_t * )
101 fPainter.reset(
new TGLHistPainter(
this));
103 fPainter->Paint(
"dummy");
110 ClassImp(TGLTH3CompositionPainter);
115 TGLTH3CompositionPainter::TGLTH3CompositionPainter(TGLTH3Composition *data, TGLPlotCamera *cam,
116 TGLPlotCoordinates *coord)
117 : TGLPlotPainter(data, cam, coord, kFALSE, kFALSE, kFALSE),
125 char *TGLTH3CompositionPainter::GetPlotInfo(Int_t , Int_t )
127 static char message[] =
"TH3 composition";
133 Bool_t TGLTH3CompositionPainter::InitGeometry()
135 if (!fData->fHists.size())
140 fCoord->SetZLog(kFALSE);
141 fCoord->SetYLog(kFALSE);
142 fCoord->SetXLog(kFALSE);
144 if (!fCoord->SetRanges(fHist, kFALSE, kTRUE))
147 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
149 fCamera->SetViewVolume(fBackBox.Get3DBox());
152 const TH3 *h = fData->fHists[0].first;
153 fMinMaxVal.second = h->GetBinContent(fCoord->GetFirstXBin(),
154 fCoord->GetFirstYBin(),
155 fCoord->GetFirstZBin());
156 fMinMaxVal.first = fMinMaxVal.second;
158 for (UInt_t hNum = 0, lastH = fData->fHists.size(); hNum < lastH; ++hNum) {
159 h = fData->fHists[hNum].first;
160 for (Int_t ir = fCoord->GetFirstXBin(); ir <= fCoord->GetLastXBin(); ++ir) {
161 for (Int_t jr = fCoord->GetFirstYBin(); jr <= fCoord->GetLastYBin(); ++jr) {
162 for (Int_t kr = fCoord->GetFirstZBin(); kr <= fCoord->GetLastZBin(); ++kr) {
163 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, h->GetBinContent(ir, jr, kr));
164 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, h->GetBinContent(ir, jr, kr));
170 if (fCoord->Modified()) {
171 fUpdateSelection = kTRUE;
172 fCoord->ResetModified();
181 void TGLTH3CompositionPainter::StartPan(Int_t px, Int_t py)
183 fMousePosition.fX = px;
184 fMousePosition.fY = fCamera->GetHeight() - py;
185 fCamera->StartPan(px, py);
186 fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
193 void TGLTH3CompositionPainter::Pan(Int_t px, Int_t py)
195 if (fSelectedPart >= fSelectionBase) {
196 SaveModelviewMatrix();
197 SaveProjectionMatrix();
199 fCamera->SetCamera();
200 fCamera->Apply(fPadPhi, fPadTheta);
201 fCamera->Pan(px, py);
203 RestoreProjectionMatrix();
204 RestoreModelviewMatrix();
205 }
else if (fSelectedPart > 0) {
208 py = fCamera->GetHeight() - py;
209 SaveModelviewMatrix();
210 SaveProjectionMatrix();
212 fCamera->SetCamera();
213 fCamera->Apply(fPadPhi, fPadTheta);
216 if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis))
217 fBoxCut.MoveBox(px, py, fSelectedPart);
220 RestoreProjectionMatrix();
221 RestoreModelviewMatrix();
224 fMousePosition.fX = px, fMousePosition.fY = py;
225 fUpdateSelection = kTRUE;
231 void TGLTH3CompositionPainter::AddOption(
const TString &)
238 void TGLTH3CompositionPainter::ProcessEvent(Int_t event, Int_t , Int_t py)
240 if (event == kButton1Double && fBoxCut.IsActive()) {
242 if (!gVirtualX->IsCmdThread())
243 gROOT->ProcessLineFast(Form(
"((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)
this));
246 }
else if (event == kKeyPress && (py == kKey_c || py == kKey_C)) {
248 Info(
"ProcessEvent",
"Switch to true color mode to use box cut");
251 fUpdateSelection = kTRUE;
259 void TGLTH3CompositionPainter::InitGL()
const
261 glEnable(GL_DEPTH_TEST);
262 glEnable(GL_LIGHTING);
264 glEnable(GL_CULL_FACE);
267 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
273 void TGLTH3CompositionPainter::DeInitGL()
const
275 glDisable(GL_DEPTH_TEST);
276 glDisable(GL_LIGHTING);
277 glDisable(GL_LIGHT0);
278 glDisable(GL_CULL_FACE);
279 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
285 void TGLTH3CompositionPainter::DrawPlot()
const
288 const Rgl::PlotTranslation trGuard(
this);
290 fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
292 if (!fSelectionPass) {
293 glEnable(GL_POLYGON_OFFSET_FILL);
294 glPolygonOffset(1.f, 1.f);
300 const Int_t frontPoint = fBackBox.GetFrontPoint();
301 Int_t irInit = fCoord->GetFirstXBin(), iInit = 0;
302 const Int_t nX = fCoord->GetNXBins();
303 Int_t jrInit = fCoord->GetFirstYBin(), jInit = 0;
304 const Int_t nY = fCoord->GetNYBins();
305 Int_t krInit = fCoord->GetFirstZBin(), kInit = 0;
306 const Int_t nZ = fCoord->GetNZBins();
308 const Int_t addI = frontPoint == 2 || frontPoint == 1 ? 1 : (iInit = nX - 1, irInit = fCoord->GetLastXBin(), -1);
309 const Int_t addJ = frontPoint == 2 || frontPoint == 3 ? 1 : (jInit = nY - 1, jrInit = fCoord->GetLastYBin(), -1);
310 const Int_t addK = fBackBox.Get2DBox()[frontPoint + 4].Y() < fBackBox.Get2DBox()[frontPoint].Y() ? 1
311 : (kInit = nZ - 1, krInit = fCoord->GetLastZBin(),-1);
312 const Double_t xScale = fCoord->GetXScale();
313 const Double_t yScale = fCoord->GetYScale();
314 const Double_t zScale = fCoord->GetZScale();
315 const TAxis *xA = fXAxis;
316 const TAxis *yA = fYAxis;
317 const TAxis *zA = fZAxis;
319 Double_t maxContent = TMath::Max(TMath::Abs(fMinMaxVal.first), TMath::Abs(fMinMaxVal.second));
323 for (UInt_t hNum = 0; hNum < fData->fHists.size(); ++hNum) {
324 const TH3 *h = fData->fHists[hNum].first;
325 const TGLTH3Composition::ETH3BinShape shape = fData->fHists[hNum].second;
326 SetColor(h->GetFillColor());
328 for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
329 for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
330 for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
331 const Double_t binContent = h->GetBinContent(ir, jr, kr);
332 const Double_t w = TMath::Abs(binContent) / maxContent;
336 const Double_t xMin = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 - w * xA->GetBinWidth(ir) / 2);
337 const Double_t xMax = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 + w * xA->GetBinWidth(ir) / 2);
338 const Double_t yMin = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 - w * yA->GetBinWidth(jr) / 2);
339 const Double_t yMax = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 + w * yA->GetBinWidth(jr) / 2);
340 const Double_t zMin = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 - w * zA->GetBinWidth(kr) / 2);
341 const Double_t zMax = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 + w * zA->GetBinWidth(kr) / 2);
343 if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
346 if (shape == TGLTH3Composition::kSphere)
347 Rgl::DrawSphere(&fQuadric, xMin, xMax, yMin, yMax, zMin, zMax);
349 Rgl::DrawBoxFront(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint);
355 if (fBoxCut.IsActive())
356 fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
358 glDisable(GL_POLYGON_OFFSET_FILL);
359 const TGLDisableGuard lightGuard(GL_LIGHTING);
360 glColor4d(0., 0., 0., 0.25);
361 glPolygonMode(GL_FRONT, GL_LINE);
363 const TGLEnableGuard blendGuard(GL_BLEND);
364 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
365 const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
366 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
368 for (UInt_t hNum = 0; hNum < fData->fHists.size(); ++hNum) {
369 if (fData->fHists[hNum].second == TGLTH3Composition::kSphere)
372 const TH3 *h = fData->fHists[hNum].first;
374 for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
375 for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
376 for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
377 const Double_t w = TMath::Abs(h->GetBinContent(ir, jr, kr)) / maxContent;
381 const Double_t xMin = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 - w * xA->GetBinWidth(ir) / 2);
382 const Double_t xMax = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 + w * xA->GetBinWidth(ir) / 2);
383 const Double_t yMin = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 - w * yA->GetBinWidth(jr) / 2);
384 const Double_t yMax = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 + w * yA->GetBinWidth(jr) / 2);
385 const Double_t zMin = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 - w * zA->GetBinWidth(kr) / 2);
386 const Double_t zMax = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 + w * zA->GetBinWidth(kr) / 2);
388 if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
391 Rgl::DrawBoxFront(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint);
397 glPolygonMode(GL_FRONT, GL_FILL);
403 void TGLTH3CompositionPainter::SetColor(Int_t color)
const
405 Float_t diffColor[] = {0.8f, 0.8f, 0.8f, 0.05f};
408 if (
const TColor *c = gROOT->GetColor(color))
409 c->GetRGB(diffColor[0], diffColor[1], diffColor[2]);
411 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffColor);
412 const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
413 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
414 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
421 void AxisError(
const TString & errorMsg)
423 Error(
"TGLTH3Composition::AddTH3",
"%s", errorMsg.Data());
424 throw std::runtime_error(errorMsg.Data());
430 void CompareAxes(
const TAxis *a1,
const TAxis *a2,
const TString &axisName)
432 if (a1->GetNbins() != a2->GetNbins())
433 AxisError(
"New hist has different number of bins along " + axisName);
436 const Int_t firstBin1 = a1->GetFirst(), lastBin1 = a1->GetLast();
437 const Int_t firstBin2 = a2->GetFirst(), lastBin2 = a2->GetLast();
439 if (firstBin1 != firstBin2)
440 AxisError(
"New hist has different first bin along " + axisName);
442 if (lastBin1 != lastBin2)
443 AxisError(
"New hist has different last bin along " + axisName);
445 const Double_t eps = 1e-7;
447 if (TMath::Abs(a1->GetBinLowEdge(firstBin1) - a2->GetBinLowEdge(firstBin2)) > eps)
448 AxisError(
"New hist has different low edge along " + axisName);
449 if (TMath::Abs(a1->GetBinUpEdge(lastBin1) - a2->GetBinUpEdge(lastBin2)) > eps)
450 AxisError(
"New hist has different low edge along " + axisName);