00001
00002
00003
00004 #include <stdexcept>
00005
00006 #include "KeySymbols.h"
00007 #include "TVirtualX.h"
00008 #include "Buttons.h"
00009 #include "TString.h"
00010 #include "TError.h"
00011 #include "TColor.h"
00012 #include "TROOT.h"
00013 #include "TMath.h"
00014
00015 #include "TGLTH3Composition.h"
00016 #include "TGLIncludes.h"
00017
00018
00019
00020
00021
00022 ClassImp(TGLTH3Composition)
00023
00024
00025 TGLTH3Composition::TGLTH3Composition()
00026 {
00027
00028 }
00029
00030 namespace {
00031
00032 void CompareAxes(const TAxis *a1, const TAxis *a2, const TString &axisName);
00033
00034 }
00035
00036
00037 void TGLTH3Composition::AddTH3(const TH3 *h, ETH3BinShape shape)
00038 {
00039
00040
00041 const TAxis *xa = h->GetXaxis();
00042 const TAxis *ya = h->GetYaxis();
00043 const TAxis *za = h->GetZaxis();
00044
00045 if (!fHists.size()) {
00046
00047
00048 fXaxis.Set(h->GetNbinsX(), xa->GetBinLowEdge(xa->GetFirst()), xa->GetBinUpEdge(xa->GetLast()));
00049 fYaxis.Set(h->GetNbinsY(), ya->GetBinLowEdge(ya->GetFirst()), ya->GetBinUpEdge(ya->GetLast()));
00050 fZaxis.Set(h->GetNbinsZ(), za->GetBinLowEdge(za->GetFirst()), za->GetBinUpEdge(za->GetLast()));
00051 } else {
00052 CompareAxes(xa, GetXaxis(), "X");
00053 CompareAxes(ya, GetYaxis(), "Y");
00054 CompareAxes(za, GetZaxis(), "Z");
00055 }
00056
00057 fHists.push_back(TH3Pair_t(h, shape));
00058 }
00059
00060
00061 Int_t TGLTH3Composition::DistancetoPrimitive(Int_t px, Int_t py)
00062 {
00063
00064 if (!fPainter.get())
00065 return 9999;
00066
00067 return fPainter->DistancetoPrimitive(px, py);
00068 }
00069
00070
00071 void TGLTH3Composition::ExecuteEvent(Int_t event, Int_t px, Int_t py)
00072 {
00073
00074 fPainter->ExecuteEvent(event, px, py);
00075 }
00076
00077
00078 char *TGLTH3Composition::GetObjectInfo(Int_t , Int_t ) const
00079 {
00080
00081
00082 static char message[] = "TH3 composition";
00083 return message;
00084 }
00085
00086
00087 void TGLTH3Composition::Paint(Option_t * )
00088 {
00089
00090 if (!fHists.size())
00091 return;
00092
00093
00094 if (!fPainter.get())
00095 fPainter.reset(new TGLHistPainter(this));
00096
00097 fPainter->Paint("dummy");
00098 }
00099
00100
00101
00102
00103
00104 ClassImp(TGLTH3CompositionPainter)
00105
00106
00107 TGLTH3CompositionPainter::TGLTH3CompositionPainter(TGLTH3Composition *data, TGLPlotCamera *cam,
00108 TGLPlotCoordinates *coord)
00109 : TGLPlotPainter(data, cam, coord, kFALSE, kFALSE, kFALSE),
00110 fData(data)
00111 {
00112
00113 }
00114
00115
00116 char *TGLTH3CompositionPainter::GetPlotInfo(Int_t , Int_t )
00117 {
00118
00119 static char message[] = "TH3 composition";
00120 return message;
00121 }
00122
00123
00124 Bool_t TGLTH3CompositionPainter::InitGeometry()
00125 {
00126 if (!fData->fHists.size())
00127 return kFALSE;
00128
00129
00130
00131 fCoord->SetZLog(kFALSE);
00132 fCoord->SetYLog(kFALSE);
00133 fCoord->SetXLog(kFALSE);
00134
00135 if (!fCoord->SetRanges(fHist, kFALSE, kTRUE))
00136 return kFALSE;
00137
00138 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
00139 if (fCamera)
00140 fCamera->SetViewVolume(fBackBox.Get3DBox());
00141
00142
00143 const TH3 *h = fData->fHists[0].first;
00144 fMinMaxVal.second = h->GetBinContent(fCoord->GetFirstXBin(),
00145 fCoord->GetFirstYBin(),
00146 fCoord->GetFirstZBin());
00147 fMinMaxVal.first = fMinMaxVal.second;
00148
00149 for (UInt_t hNum = 0, lastH = fData->fHists.size(); hNum < lastH; ++hNum) {
00150 h = fData->fHists[hNum].first;
00151 for (Int_t ir = fCoord->GetFirstXBin(); ir <= fCoord->GetLastXBin(); ++ir) {
00152 for (Int_t jr = fCoord->GetFirstYBin(); jr <= fCoord->GetLastYBin(); ++jr) {
00153 for (Int_t kr = fCoord->GetFirstZBin(); kr <= fCoord->GetLastZBin(); ++kr) {
00154 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, h->GetBinContent(ir, jr, kr));
00155 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, h->GetBinContent(ir, jr, kr));
00156 }
00157 }
00158 }
00159 }
00160
00161 if (fCoord->Modified()) {
00162 fUpdateSelection = kTRUE;
00163 fCoord->ResetModified();
00164 }
00165
00166 return kTRUE;
00167 }
00168
00169
00170 void TGLTH3CompositionPainter::StartPan(Int_t px, Int_t py)
00171 {
00172
00173 fMousePosition.fX = px;
00174 fMousePosition.fY = fCamera->GetHeight() - py;
00175 fCamera->StartPan(px, py);
00176 fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
00177 }
00178
00179
00180 void TGLTH3CompositionPainter::Pan(Int_t px, Int_t py)
00181 {
00182
00183
00184 if (fSelectedPart >= fSelectionBase) {
00185 SaveModelviewMatrix();
00186 SaveProjectionMatrix();
00187
00188 fCamera->SetCamera();
00189 fCamera->Apply(fPadPhi, fPadTheta);
00190 fCamera->Pan(px, py);
00191
00192 RestoreProjectionMatrix();
00193 RestoreModelviewMatrix();
00194 } else if (fSelectedPart > 0) {
00195
00196
00197 py = fCamera->GetHeight() - py;
00198 SaveModelviewMatrix();
00199 SaveProjectionMatrix();
00200
00201 fCamera->SetCamera();
00202 fCamera->Apply(fPadPhi, fPadTheta);
00203
00204 if (!fHighColor) {
00205 if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis))
00206 fBoxCut.MoveBox(px, py, fSelectedPart);
00207 }
00208
00209 RestoreProjectionMatrix();
00210 RestoreModelviewMatrix();
00211 }
00212
00213 fMousePosition.fX = px, fMousePosition.fY = py;
00214 fUpdateSelection = kTRUE;
00215 }
00216
00217
00218 void TGLTH3CompositionPainter::AddOption(const TString &)
00219 {
00220
00221 }
00222
00223
00224 void TGLTH3CompositionPainter::ProcessEvent(Int_t event, Int_t , Int_t py)
00225 {
00226
00227 if (event == kButton1Double && fBoxCut.IsActive()) {
00228 fBoxCut.TurnOnOff();
00229 if (!gVirtualX->IsCmdThread())
00230 gROOT->ProcessLineFast(Form("((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)this));
00231 else
00232 Paint();
00233 } else if (event == kKeyPress && (py == kKey_c || py == kKey_C)) {
00234 if (fHighColor)
00235 Info("ProcessEvent", "Switch to true color mode to use box cut");
00236 else {
00237 fBoxCut.TurnOnOff();
00238 fUpdateSelection = kTRUE;
00239 }
00240 }
00241 }
00242
00243
00244 void TGLTH3CompositionPainter::InitGL()const
00245 {
00246
00247 glEnable(GL_DEPTH_TEST);
00248 glEnable(GL_LIGHTING);
00249 glEnable(GL_LIGHT0);
00250 glEnable(GL_CULL_FACE);
00251 glCullFace(GL_BACK);
00252
00253 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
00254 }
00255
00256
00257 void TGLTH3CompositionPainter::DeInitGL()const
00258 {
00259
00260 glDisable(GL_DEPTH_TEST);
00261 glDisable(GL_LIGHTING);
00262 glDisable(GL_LIGHT0);
00263 glDisable(GL_CULL_FACE);
00264 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
00265 }
00266
00267
00268 void TGLTH3CompositionPainter::DrawPlot()const
00269 {
00270
00271
00272
00273 const Rgl::PlotTranslation trGuard(this);
00274
00275 fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
00276
00277 if (!fSelectionPass) {
00278 glEnable(GL_POLYGON_OFFSET_FILL);
00279 glPolygonOffset(1.f, 1.f);
00280 } else
00281 return;
00282
00283
00284
00285 const Int_t frontPoint = fBackBox.GetFrontPoint();
00286 Int_t irInit = fCoord->GetFirstXBin(), iInit = 0;
00287 const Int_t nX = fCoord->GetNXBins();
00288 Int_t jrInit = fCoord->GetFirstYBin(), jInit = 0;
00289 const Int_t nY = fCoord->GetNYBins();
00290 Int_t krInit = fCoord->GetFirstZBin(), kInit = 0;
00291 const Int_t nZ = fCoord->GetNZBins();
00292
00293 const Int_t addI = frontPoint == 2 || frontPoint == 1 ? 1 : (iInit = nX - 1, irInit = fCoord->GetLastXBin(), -1);
00294 const Int_t addJ = frontPoint == 2 || frontPoint == 3 ? 1 : (jInit = nY - 1, jrInit = fCoord->GetLastYBin(), -1);
00295 const Int_t addK = fBackBox.Get2DBox()[frontPoint + 4].Y() < fBackBox.Get2DBox()[frontPoint].Y() ? 1
00296 : (kInit = nZ - 1, krInit = fCoord->GetLastZBin(),-1);
00297 const Double_t xScale = fCoord->GetXScale();
00298 const Double_t yScale = fCoord->GetYScale();
00299 const Double_t zScale = fCoord->GetZScale();
00300 const TAxis *xA = fXAxis;
00301 const TAxis *yA = fYAxis;
00302 const TAxis *zA = fZAxis;
00303
00304 Double_t maxContent = TMath::Max(TMath::Abs(fMinMaxVal.first), TMath::Abs(fMinMaxVal.second));
00305 if(!maxContent)
00306 maxContent = 1.;
00307
00308 for (UInt_t hNum = 0; hNum < fData->fHists.size(); ++hNum) {
00309 const TH3 *h = fData->fHists[hNum].first;
00310 const TGLTH3Composition::ETH3BinShape shape = fData->fHists[hNum].second;
00311 SetColor(h->GetFillColor());
00312
00313 for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
00314 for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
00315 for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
00316 const Double_t binContent = h->GetBinContent(ir, jr, kr);
00317 const Double_t w = TMath::Abs(binContent) / maxContent;
00318 if (!w)
00319 continue;
00320
00321 const Double_t xMin = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 - w * xA->GetBinWidth(ir) / 2);
00322 const Double_t xMax = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 + w * xA->GetBinWidth(ir) / 2);
00323 const Double_t yMin = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 - w * yA->GetBinWidth(jr) / 2);
00324 const Double_t yMax = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 + w * yA->GetBinWidth(jr) / 2);
00325 const Double_t zMin = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 - w * zA->GetBinWidth(kr) / 2);
00326 const Double_t zMax = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 + w * zA->GetBinWidth(kr) / 2);
00327
00328 if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
00329 continue;
00330
00331 if (shape == TGLTH3Composition::kSphere)
00332 Rgl::DrawSphere(&fQuadric, xMin, xMax, yMin, yMax, zMin, zMax);
00333 else
00334 Rgl::DrawBoxFront(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint);
00335 }
00336 }
00337 }
00338 }
00339
00340 if (fBoxCut.IsActive())
00341 fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
00342
00343 glDisable(GL_POLYGON_OFFSET_FILL);
00344 const TGLDisableGuard lightGuard(GL_LIGHTING);
00345 glColor4d(0., 0., 0., 0.25);
00346 glPolygonMode(GL_FRONT, GL_LINE);
00347
00348 const TGLEnableGuard blendGuard(GL_BLEND);
00349 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00350 const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
00351 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00352
00353 for (UInt_t hNum = 0; hNum < fData->fHists.size(); ++hNum) {
00354 if (fData->fHists[hNum].second == TGLTH3Composition::kSphere)
00355 continue;
00356
00357 const TH3 *h = fData->fHists[hNum].first;
00358
00359 for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
00360 for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
00361 for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
00362 const Double_t w = TMath::Abs(h->GetBinContent(ir, jr, kr)) / maxContent;
00363 if (!w)
00364 continue;
00365
00366 const Double_t xMin = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 - w * xA->GetBinWidth(ir) / 2);
00367 const Double_t xMax = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 + w * xA->GetBinWidth(ir) / 2);
00368 const Double_t yMin = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 - w * yA->GetBinWidth(jr) / 2);
00369 const Double_t yMax = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 + w * yA->GetBinWidth(jr) / 2);
00370 const Double_t zMin = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 - w * zA->GetBinWidth(kr) / 2);
00371 const Double_t zMax = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 + w * zA->GetBinWidth(kr) / 2);
00372
00373 if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
00374 continue;
00375
00376 Rgl::DrawBoxFront(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint);
00377 }
00378 }
00379 }
00380 }
00381
00382 glPolygonMode(GL_FRONT, GL_FILL);
00383 }
00384
00385
00386 void TGLTH3CompositionPainter::SetColor(Int_t color)const
00387 {
00388
00389 Float_t diffColor[] = {0.8f, 0.8f, 0.8f, 0.05f};
00390
00391 if (color != kWhite)
00392 if (const TColor *c = gROOT->GetColor(color))
00393 c->GetRGB(diffColor[0], diffColor[1], diffColor[2]);
00394
00395 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffColor);
00396 const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
00397 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
00398 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
00399 }
00400
00401 namespace {
00402
00403
00404 void AxisError(const TString & errorMsg)
00405 {
00406 Error("TGLTH3Composition::AddTH3", "%s", errorMsg.Data());
00407 throw std::runtime_error(errorMsg.Data());
00408 }
00409
00410
00411 void CompareAxes(const TAxis *a1, const TAxis *a2, const TString &axisName)
00412 {
00413
00414 if (a1->GetNbins() != a2->GetNbins())
00415 AxisError("New hist has different number of bins along " + axisName);
00416
00417
00418 const Int_t firstBin1 = a1->GetFirst(), lastBin1 = a1->GetLast();
00419 const Int_t firstBin2 = a2->GetFirst(), lastBin2 = a2->GetLast();
00420
00421 if (firstBin1 != firstBin2)
00422 AxisError("New hist has different first bin along " + axisName);
00423
00424 if (lastBin1 != lastBin2)
00425 AxisError("New hist has different last bin along " + axisName);
00426
00427 const Double_t eps = 1e-7;
00428
00429 if (TMath::Abs(a1->GetBinLowEdge(firstBin1) - a2->GetBinLowEdge(firstBin2)) > eps)
00430 AxisError("New hist has different low edge along " + axisName);
00431 if (TMath::Abs(a1->GetBinUpEdge(lastBin1) - a2->GetBinUpEdge(lastBin2)) > eps)
00432 AxisError("New hist has different low edge along " + axisName);
00433 }
00434
00435 }