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);