TGLPlotPainter.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLPlotPainter.cxx 37060 2010-11-29 10:31:56Z couet $
00002 // Author:  Timur Pocheptsov  14/06/2006
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 #include "Riostream.h"
00012 #include <cstdio>
00013 
00014 #include "TVirtualPad.h"
00015 #include "TVirtualPS.h"
00016 #include "TVirtualX.h"
00017 #include "TGaxis.h"
00018 #include "TGraph.h"
00019 #include "TStyle.h"
00020 #include "TError.h"
00021 #include "TColor.h"
00022 #include "TAxis.h"
00023 #include "TMath.h"
00024 #include "TList.h"
00025 #include "TH2Poly.h"
00026 #include "TH1.h"
00027 #include "TH3.h"
00028 #include "TF3.h"
00029 
00030 #include "TGLPlotPainter.h"
00031 #include "TGLPlotCamera.h"
00032 #include "TGLIncludes.h"
00033 #include "TGLAdapter.h"
00034 #include "TGLOutput.h"
00035 #include "TGL5D.h"
00036 #include "gl2ps.h"
00037 
00038 //______________________________________________________________________________
00039 //
00040 // Base class for plot-painters that provide GL rendering of various
00041 // 2D and 3D histograms, functions and parametric surfaces.
00042 
00043 ClassImp(TGLPlotPainter)
00044 
00045 //______________________________________________________________________________
00046 TGLPlotPainter::TGLPlotPainter(TH1 *hist, TGLPlotCamera *camera, TGLPlotCoordinates *coord,
00047                                Bool_t xoy, Bool_t xoz, Bool_t yoz)
00048                   : fPadColor(0),
00049                     fPadPhi(45.),
00050                     fPadTheta(0.),
00051                     fHist(hist),
00052                     fXAxis(hist->GetXaxis()),
00053                     fYAxis(hist->GetYaxis()),
00054                     fZAxis(hist->GetZaxis()),
00055                     fCoord(coord),
00056                     fCamera(camera),
00057                     fUpdateSelection(kTRUE),
00058                     fSelectionPass(kFALSE),
00059                     fSelectedPart(0),
00060                     fXOZSectionPos(0.),
00061                     fYOZSectionPos(0.),
00062                     fXOYSectionPos(0.),
00063                     fBackBox(xoy, xoz, yoz),
00064                     fBoxCut(&fBackBox),
00065                     fHighColor(kFALSE),
00066                     fSelectionBase(kTrueColorSelectionBase),
00067                     fDrawPalette(kFALSE)
00068 {
00069    //TGLPlotPainter's ctor.
00070    if (gPad) {
00071       fPadPhi   = gPad->GetPhi();
00072       fPadTheta = gPad->GetTheta();
00073    }
00074 }
00075 
00076 //______________________________________________________________________________
00077 TGLPlotPainter::TGLPlotPainter(TGL5DDataSet *data, TGLPlotCamera *camera, TGLPlotCoordinates *coord)
00078                   : fPadColor(0),
00079                     fPadPhi(45.),
00080                     fPadTheta(0.),
00081                     fHist(0),
00082                     fXAxis(data->GetXAxis()),
00083                     fYAxis(data->GetYAxis()),
00084                     fZAxis(data->GetZAxis()),
00085                     fCoord(coord),
00086                     fCamera(camera),
00087                     fUpdateSelection(kTRUE),
00088                     fSelectionPass(kFALSE),
00089                     fSelectedPart(0),
00090                     fXOZSectionPos(0.),
00091                     fYOZSectionPos(0.),
00092                     fXOYSectionPos(0.),
00093                     fBackBox(kFALSE, kFALSE, kFALSE),
00094                     fBoxCut(&fBackBox),
00095                     fHighColor(kFALSE),
00096                     fSelectionBase(kTrueColorSelectionBase),
00097                     fDrawPalette(kFALSE)
00098 {
00099    //TGLPlotPainter's ctor.
00100    if (gPad) {
00101       fPadPhi   = gPad->GetPhi();
00102       fPadTheta = gPad->GetTheta();
00103    }
00104 }
00105 
00106 //______________________________________________________________________________
00107 TGLPlotPainter::TGLPlotPainter(TGLPlotCamera *camera)
00108                   : fPadColor(0),
00109                     fPadPhi(45.),
00110                     fPadTheta(0.),
00111                     fHist(0),
00112                     fXAxis(0),
00113                     fYAxis(0),
00114                     fZAxis(0),
00115                     fCoord(0),
00116                     fCamera(camera),
00117                     fUpdateSelection(kTRUE),
00118                     fSelectionPass(kFALSE),
00119                     fSelectedPart(0),
00120                     fXOZSectionPos(0.),
00121                     fYOZSectionPos(0.),
00122                     fXOYSectionPos(0.),
00123                     fBackBox(kFALSE, kFALSE, kFALSE),
00124                     fBoxCut(&fBackBox),
00125                     fHighColor(kFALSE),
00126                     fSelectionBase(kTrueColorSelectionBase),
00127                     fDrawPalette(kFALSE)
00128 {
00129    //TGLPlotPainter's ctor.
00130    if (gPad) {
00131       fPadPhi   = gPad->GetPhi();
00132       fPadTheta = gPad->GetTheta();
00133    }
00134 }
00135 
00136 //______________________________________________________________________________
00137 void TGLPlotPainter::Paint()
00138 {
00139    //Draw lego/surf/whatever you can.
00140    fHighColor = kFALSE;
00141    fSelectionBase = fHighColor ? kHighColorSelectionBase : kTrueColorSelectionBase;
00142 
00143    int vp[4] = {};
00144    glGetIntegerv(GL_VIEWPORT, vp);
00145 
00146    //GL pad painter does not use depth test,
00147    //so, switch it on now.
00148    glDepthMask(GL_TRUE);//[0
00149    //
00150    InitGL();
00151    //Save material/light properties in a stack.
00152    glPushAttrib(GL_LIGHTING_BIT);
00153 
00154    //Save projection and modelview matrix, used by glpad.
00155    SaveProjectionMatrix();
00156    SaveModelviewMatrix();
00157 
00158    //glOrtho etc.
00159    fCamera->SetCamera();
00160    //
00161    glClear(GL_DEPTH_BUFFER_BIT);
00162    //
00163 /*   if (fCamera->ViewportChanged()) {
00164       std::cout<<"Set need update\n";
00165       fUpdateSelection = kTRUE;
00166    }*/
00167    //Set light.
00168    const Float_t pos[] = {0.f, 0.f, 0.f, 1.f};
00169    glLightfv(GL_LIGHT0, GL_POSITION, pos);
00170    //Set transformation - shift and rotate the scene.
00171    fCamera->Apply(fPadPhi, fPadTheta);
00172    fBackBox.FindFrontPoint();
00173 
00174    if (gVirtualPS)
00175       PrintPlot();
00176 
00177 
00178 
00179    DrawPlot();
00180    //Restore material properties from stack.
00181    glPopAttrib();
00182    //
00183    DeInitGL();//Disable/enable, what concrete plot painter enabled/disabled
00184 
00185    //Restore projection and modelview matrices.
00186    RestoreProjectionMatrix();
00187    RestoreModelviewMatrix();
00188 
00189    glViewport(vp[0], vp[1], vp[2], vp[3]);
00190    //GL pad painter does not use depth test, so,
00191    //switch it off now.
00192    glDepthMask(GL_FALSE);//0]
00193 
00194    if (fCoord && fCoord->GetCoordType() == kGLCartesian) {
00195 
00196       Bool_t old = gPad->TestBit(TGraph::kClipFrame);
00197       if (!old)
00198          gPad->SetBit(TGraph::kClipFrame);
00199       const Int_t viewport[] = {fCamera->GetX(), fCamera->GetY(), fCamera->GetWidth(), fCamera->GetHeight()};
00200       Rgl::DrawAxes(fBackBox.GetFrontPoint(), viewport, fBackBox.Get2DBox(), fCoord, fXAxis, fYAxis, fZAxis);
00201       if (fDrawPalette)
00202          DrawPaletteAxis();
00203 
00204       if (!old)
00205          gPad->ResetBit(TGraph::kClipFrame);
00206    } else if(fDrawPalette)
00207       DrawPaletteAxis();
00208 
00209 }
00210 
00211 //______________________________________________________________________________
00212 void TGLPlotPainter::PrintPlot()const
00213 {
00214    // Generate PS using gl2ps
00215    using namespace std;
00216 
00217    TGLOutput::StartEmbeddedPS();
00218 
00219    FILE *output = fopen(gVirtualPS->GetName(), "a");
00220    if (!output) {
00221       Error("TGLPlotPainter::PrintPlot", "Could not (re)open ps file for GL output");
00222       //As soon as we started embedded ps, we have to close it before exiting.
00223       TGLOutput::CloseEmbeddedPS();
00224       return;
00225    }
00226 
00227    Int_t gl2psFormat = GL2PS_EPS;
00228    Int_t gl2psSort   = GL2PS_BSP_SORT;
00229    Int_t buffsize    = 0;
00230    Int_t state       = GL2PS_OVERFLOW;
00231    GLint gl2psoption = GL2PS_USE_CURRENT_VIEWPORT |
00232                        GL2PS_SILENT               |
00233                        GL2PS_BEST_ROOT            |
00234                        GL2PS_OCCLUSION_CULL       |
00235                        0;
00236 
00237    while (state == GL2PS_OVERFLOW) {
00238       buffsize += 1024*1024;
00239       gl2psBeginPage ("ROOT Scene Graph", "ROOT", NULL,
00240                       gl2psFormat, gl2psSort, gl2psoption,
00241                       GL_RGBA, 0, NULL,0, 0, 0,
00242                       buffsize, output, NULL);
00243       DrawPlot();
00244       state = gl2psEndPage();
00245    }
00246 
00247    fclose(output);
00248    TGLOutput::CloseEmbeddedPS();
00249    glFlush();
00250 }
00251 
00252 //______________________________________________________________________________
00253 Bool_t TGLPlotPainter::PlotSelected(Int_t px, Int_t py)
00254 {
00255    //Read color buffer content to find selected object
00256    if (fUpdateSelection) {
00257       //Save projection and modelview matrix, used by glpad.
00258       glMatrixMode(GL_PROJECTION);//[1
00259       glPushMatrix();
00260       glMatrixMode(GL_MODELVIEW);//[2
00261       glPushMatrix();
00262 
00263       fSelectionPass = kTRUE;
00264       fCamera->SetCamera();
00265 
00266       glDepthMask(GL_TRUE);
00267       glClearColor(0.f, 0.f, 0.f, 0.f);
00268       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00269 
00270       fCamera->Apply(fPadPhi, fPadTheta);
00271       DrawPlot();
00272 
00273       glFinish();
00274       //fSelection.ReadColorBuffer(fCamera->GetWidth(), fCamera->GetHeight());
00275       fSelection.ReadColorBuffer(fCamera->GetX(), fCamera->GetY(), fCamera->GetWidth(), fCamera->GetHeight());
00276       fSelectionPass   = kFALSE;
00277       fUpdateSelection = kFALSE;
00278 
00279       glDepthMask(GL_FALSE);
00280       glDisable(GL_DEPTH_TEST);
00281 
00282       //Restore projection and modelview matrices.
00283       glMatrixMode(GL_PROJECTION);//1]
00284       glPopMatrix();
00285       glMatrixMode(GL_MODELVIEW);//2]
00286       glPopMatrix();
00287    }
00288 
00289    //Convert from window top-bottom into gl bottom-top.
00290    px -= Int_t(gPad->GetXlowNDC() * gPad->GetWw());
00291    py -= Int_t(gPad->GetWh() - gPad->YtoAbsPixel(gPad->GetY1()));
00292    //py = fCamera->GetHeight() - py;
00293    //Y is a number of a row, x - column.
00294    std::swap(px, py);
00295    Int_t newSelected(Rgl::ColorToObjectID(fSelection.GetPixelColor(px, py), fHighColor));
00296 
00297    if (newSelected != fSelectedPart) {
00298       //New object was selected (or surface deselected) - re-paint.
00299       fSelectedPart = newSelected;
00300       gPad->Update();
00301    }
00302 
00303    return fSelectedPart ? kTRUE : kFALSE;
00304 }
00305 
00306 /*
00307 //______________________________________________________________________________
00308 void TGLPlotPainter::SetGLContext(Int_t context)
00309 {
00310    //One plot can be painted in several gl contexts.
00311 //   fGLContext = context;
00312 }
00313  */
00314 //______________________________________________________________________________
00315 void TGLPlotPainter::SetPadColor(const TColor *c)
00316 {
00317    //Used in a pad.
00318    fPadColor = c;
00319 }
00320 
00321 //______________________________________________________________________________
00322 void TGLPlotPainter::SetFrameColor(const TColor *c)
00323 {
00324    //Set plot's back box color.
00325    fBackBox.SetFrameColor(c);
00326 }
00327 
00328 //______________________________________________________________________________
00329 void TGLPlotPainter::InvalidateSelection()
00330 {
00331    //Selection must be updated.
00332    fUpdateSelection = kTRUE;
00333 }
00334 
00335 //______________________________________________________________________________
00336 const TColor *TGLPlotPainter::GetPadColor()const
00337 {
00338    //Get pad color.
00339    return fPadColor;
00340 }
00341 
00342 //______________________________________________________________________________
00343 void TGLPlotPainter::MoveSection(Int_t px, Int_t py)
00344 {
00345    //Create dynamic profile using selected plane
00346    const TGLVertex3 *frame = fBackBox.Get3DBox();
00347    const Int_t frontPoint  = fBackBox.GetFrontPoint();
00348 
00349    if (fSelectedPart == 1) {
00350       fXOYSectionPos = frame[0].Z();
00351       fSelectedPart = 6;
00352    } else if (fSelectedPart == 2) {
00353       if (frontPoint == 2) {
00354          fXOZSectionPos = frame[0].Y();
00355          fSelectedPart = 4;
00356       } else if (!frontPoint) {
00357          fXOZSectionPos = frame[2].Y();
00358          fSelectedPart = 4;
00359       } else if (frontPoint == 1) {
00360          fYOZSectionPos = frame[0].X();
00361          fSelectedPart = 5;
00362       } else if (frontPoint == 3) {
00363          fYOZSectionPos = frame[1].X();
00364          fSelectedPart = 5;
00365       }
00366    } else if (fSelectedPart == 3) {
00367       if (frontPoint == 2) {
00368          fYOZSectionPos = frame[0].X();
00369          fSelectedPart = 5;
00370       } else if (!frontPoint) {
00371          fYOZSectionPos = frame[1].X();
00372          fSelectedPart = 5;
00373       } else if (frontPoint == 1) {
00374          fXOZSectionPos = frame[2].Y();
00375          fSelectedPart = 4;
00376       } else if (frontPoint == 3) {
00377          fXOZSectionPos = frame[0].Y();
00378          fSelectedPart = 4;
00379       }
00380    }
00381 
00382    Double_t mv[16] = {0.};
00383    glGetDoublev(GL_MODELVIEW_MATRIX, mv);
00384    Double_t pr[16] = {0.};
00385    glGetDoublev(GL_PROJECTION_MATRIX, pr);
00386    Int_t vp[4] = {0};
00387    glGetIntegerv(GL_VIEWPORT, vp);
00388    Double_t winVertex[3] = {0.};
00389 
00390    if (fSelectedPart == 6)
00391       gluProject(0., 0., fXOYSectionPos, mv, pr, vp, &winVertex[0], &winVertex[1], &winVertex[2]);
00392    else
00393       gluProject(fSelectedPart == 5 ? fYOZSectionPos : 0.,
00394                  fSelectedPart == 4 ? fXOZSectionPos : 0.,
00395                  0., mv, pr, vp,
00396                  &winVertex[0], &winVertex[1], &winVertex[2]);
00397    winVertex[0] += px - fMousePosition.fX;
00398    winVertex[1] += py - fMousePosition.fY;
00399    Double_t newPoint[3] = {0.};
00400    gluUnProject(winVertex[0], winVertex[1], winVertex[2], mv, pr, vp,
00401                 newPoint, newPoint + 1, newPoint + 2);
00402 
00403    if (fSelectedPart == 4)
00404       fXOZSectionPos = newPoint[1];
00405    else if (fSelectedPart == 5)
00406       fYOZSectionPos = newPoint[0];
00407    else
00408       fXOYSectionPos = newPoint[2];
00409 }
00410 
00411 //______________________________________________________________________________
00412 void TGLPlotPainter::DrawSections()const
00413 {
00414    //Draw sections (if any).
00415    const TGLVertex3 *frame = fBackBox.Get3DBox();
00416 
00417    if (fXOZSectionPos > frame[0].Y()) {
00418       if (fXOZSectionPos > frame[2].Y())
00419          fXOZSectionPos = frame[2].Y();
00420       const TGLVertex3 v1(frame[0].X(), fXOZSectionPos, frame[0].Z());
00421       const TGLVertex3 v2(frame[4].X(), fXOZSectionPos, frame[4].Z());
00422       const TGLVertex3 v3(frame[5].X(), fXOZSectionPos, frame[5].Z());
00423       const TGLVertex3 v4(frame[1].X(), fXOZSectionPos, frame[1].Z());
00424 
00425       if (fSelectionPass)
00426          Rgl::ObjectIDToColor(4, fHighColor);
00427       else if (fSelectedPart == 4)
00428          glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gBlueEmission);
00429 
00430       glEnable(GL_POLYGON_OFFSET_FILL);
00431       glPolygonOffset(1.f, 1.f);
00432       Rgl::DrawQuadFilled(v1, v2, v3, v4, TGLVector3(0., 1., 0.));
00433       glDisable(GL_POLYGON_OFFSET_FILL);
00434       //Zlevels here.
00435       if (!fSelectionPass) {
00436          if (fSelectedPart == 4)
00437             glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gNullEmission);
00438          const TGLDisableGuard lightGuard(GL_LIGHTING);
00439          const TGLEnableGuard  blendGuard(GL_BLEND);
00440          const TGLEnableGuard  lineSmooth(GL_LINE_SMOOTH);
00441          glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00442          glDepthMask(GL_FALSE);
00443          DrawSectionXOZ();
00444          //Draw z-levels
00445          const TGLEnableGuard stippleGuard(GL_LINE_STIPPLE);//[1-1]
00446          const UShort_t stipple = 0x5555;
00447          glLineStipple(1, stipple);
00448 
00449          glColor3d(0., 0., 0.);
00450          glBegin(GL_LINES);
00451          for (UInt_t i = 0; i < fZLevels.size(); ++i) {
00452             glVertex3d(fBackBox.Get3DBox()[1].X(), fXOZSectionPos, fZLevels[i]);
00453             glVertex3d(fBackBox.Get3DBox()[0].X(), fXOZSectionPos, fZLevels[i]);
00454          }
00455          glEnd();
00456          glDepthMask(GL_TRUE);
00457       }
00458    }
00459 
00460    if (fYOZSectionPos > frame[0].X()) {
00461       if (fYOZSectionPos > frame[1].X())
00462          fYOZSectionPos = frame[1].X();
00463       TGLVertex3 v1(fYOZSectionPos, frame[0].Y(), frame[0].Z());
00464       TGLVertex3 v2(fYOZSectionPos, frame[3].Y(), frame[3].Z());
00465       TGLVertex3 v3(fYOZSectionPos, frame[7].Y(), frame[7].Z());
00466       TGLVertex3 v4(fYOZSectionPos, frame[4].Y(), frame[4].Z());
00467 
00468       if (fSelectionPass) {
00469          Rgl::ObjectIDToColor(5, fHighColor);
00470       } else if (fSelectedPart == 5)
00471          glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gBlueEmission);
00472 
00473       glEnable(GL_POLYGON_OFFSET_FILL);
00474       glPolygonOffset(1.f, 1.f);
00475       Rgl::DrawQuadFilled(v1, v2, v3, v4, TGLVector3(1., 0., 0.));
00476       glDisable(GL_POLYGON_OFFSET_FILL);
00477 
00478       if (!fSelectionPass) {
00479          if (fSelectedPart == 5)
00480             glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gNullEmission);
00481          const TGLDisableGuard lightHuard(GL_LIGHTING);
00482          const TGLEnableGuard blendGuard(GL_BLEND);
00483          const TGLEnableGuard lineSmooth(GL_LINE_SMOOTH);
00484          glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00485          glDepthMask(GL_FALSE);
00486          DrawSectionYOZ();
00487          //Draw z-levels
00488          const TGLEnableGuard stippleGuard(GL_LINE_STIPPLE);//[1-1]
00489          glLineStipple(1, 0x5555);
00490 
00491          glColor3d(0., 0., 0.);
00492          glBegin(GL_LINES);
00493          for (UInt_t i = 0; i < fZLevels.size(); ++i) {
00494             glVertex3d(fYOZSectionPos, fBackBox.Get3DBox()[3].Y(), fZLevels[i]);
00495             glVertex3d(fYOZSectionPos, fBackBox.Get3DBox()[0].Y(), fZLevels[i]);
00496          }
00497          glEnd();
00498          glDepthMask(GL_TRUE);
00499       }
00500    }
00501 
00502    if (fXOYSectionPos > frame[0].Z()) {
00503       if (fXOYSectionPos > frame[4].Z())
00504          fXOYSectionPos = frame[4].Z();
00505       TGLVertex3 v1(frame[0].X(), frame[0].Y(), fXOYSectionPos);
00506       TGLVertex3 v2(frame[1].X(), frame[1].Y(), fXOYSectionPos);
00507       TGLVertex3 v3(frame[2].X(), frame[2].Y(), fXOYSectionPos);
00508       TGLVertex3 v4(frame[3].X(), frame[3].Y(), fXOYSectionPos);
00509 
00510       if (fSelectionPass) {
00511          Rgl::ObjectIDToColor(6, fHighColor);
00512       } else if (fSelectedPart == 6)
00513          glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gBlueEmission);
00514 
00515       glEnable(GL_POLYGON_OFFSET_FILL);
00516       glPolygonOffset(1.f, 1.f);
00517       //if (fSelectionPass || fSelectedPart == 6)
00518       Rgl::DrawQuadFilled(v1, v2, v3, v4, TGLVector3(0., 0., 1.));
00519       glDisable(GL_POLYGON_OFFSET_FILL);
00520 
00521       if (!fSelectionPass) {
00522          if (fSelectedPart == 6)
00523             glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gNullEmission);
00524          const TGLDisableGuard lightGuard(GL_LIGHTING);
00525          const TGLEnableGuard blendGuard(GL_BLEND);
00526          const TGLEnableGuard lineSmooth(GL_LINE_SMOOTH);
00527          glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00528          glDepthMask(GL_FALSE);
00529          DrawSectionXOY();
00530          glDepthMask(GL_TRUE);
00531       }
00532    }
00533 }
00534 
00535 //______________________________________________________________________________
00536 void TGLPlotPainter::ClearBuffers()const
00537 {
00538 /*
00539    // Clear buffer.
00540    Float_t rgb[3] = {1.f, 1.f, 1.f};
00541    if (const TColor *color = GetPadColor())
00542       color->GetRGB(rgb[0], rgb[1], rgb[2]);
00543    glClearColor(rgb[0], rgb[1], rgb[2], 1.);
00544    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00545    */
00546 }
00547 
00548 //______________________________________________________________________________
00549 void TGLPlotPainter::DrawPaletteAxis()const
00550 {
00551    //Draw. Palette. Axis.
00552 }
00553 
00554 //______________________________________________________________________________
00555 void TGLPlotPainter::SaveModelviewMatrix()const
00556 {
00557    glMatrixMode(GL_MODELVIEW);
00558    glPushMatrix();
00559 }
00560 
00561 //______________________________________________________________________________
00562 void TGLPlotPainter::SaveProjectionMatrix()const
00563 {
00564    glMatrixMode(GL_PROJECTION);
00565    glPushMatrix();
00566 }
00567 
00568 //______________________________________________________________________________
00569 void TGLPlotPainter::RestoreModelviewMatrix()const
00570 {
00571    glMatrixMode(GL_MODELVIEW);
00572    glPopMatrix();
00573 }
00574 
00575 //______________________________________________________________________________
00576 void TGLPlotPainter::RestoreProjectionMatrix()const
00577 {
00578    glMatrixMode(GL_PROJECTION);
00579    glPopMatrix();
00580 }
00581 
00582 //______________________________________________________________________________
00583 //
00584 // Helper class for plot-painters holding information about axis
00585 // ranges, numbers of bins and flags if certain axis is logartihmic.
00586 
00587 ClassImp(TGLPlotCoordinates)
00588 
00589 //______________________________________________________________________________
00590 TGLPlotCoordinates::TGLPlotCoordinates()
00591                         : fCoordType(kGLCartesian),
00592                           fXScale(1.),
00593                           fYScale(1.),
00594                           fZScale(1.),
00595                           fXLog(kFALSE),
00596                           fYLog(kFALSE),
00597                           fZLog(kFALSE),
00598                           fModified(kFALSE),
00599                           fFactor(1.)
00600 {
00601    //Constructor.
00602 }
00603 
00604 //______________________________________________________________________________
00605 TGLPlotCoordinates::~TGLPlotCoordinates()
00606 {
00607    //Destructor.
00608 }
00609 
00610 //______________________________________________________________________________
00611 void TGLPlotCoordinates::SetCoordType(EGLCoordType type)
00612 {
00613    //If coord type was changed, plot must reset sections (if any),
00614    //set fModified.
00615    if (fCoordType != type) {
00616       fModified = kTRUE;
00617       fCoordType = type;
00618    }
00619 }
00620 
00621 //______________________________________________________________________________
00622 EGLCoordType TGLPlotCoordinates::GetCoordType()const
00623 {
00624    // Get coordinates type.
00625 
00626    return fCoordType;
00627 }
00628 
00629 //______________________________________________________________________________
00630 void TGLPlotCoordinates::SetXLog(Bool_t xLog)
00631 {
00632    //If log changed, sections must be reset,
00633    //set fModified.
00634    if (fXLog != xLog) {
00635       fXLog = xLog;
00636       fModified = kTRUE;
00637    }
00638 }
00639 
00640 //______________________________________________________________________________
00641 Bool_t TGLPlotCoordinates::GetXLog()const
00642 {
00643    // Get X log.
00644 
00645    return fXLog;
00646 }
00647 
00648 //______________________________________________________________________________
00649 void TGLPlotCoordinates::SetYLog(Bool_t yLog)
00650 {
00651    //If log changed, sections must be reset,
00652    //set fModified.
00653    if (fYLog != yLog) {
00654       fYLog = yLog;
00655       fModified = kTRUE;
00656    }
00657 }
00658 
00659 //______________________________________________________________________________
00660 Bool_t TGLPlotCoordinates::GetYLog()const
00661 {
00662    // Get Y log.
00663 
00664    return fYLog;
00665 }
00666 
00667 //______________________________________________________________________________
00668 void TGLPlotCoordinates::SetZLog(Bool_t zLog)
00669 {
00670    //If log changed, sections must be reset,
00671    //set fModified.
00672    if (fZLog != zLog) {
00673       fZLog = zLog;
00674       fModified = kTRUE;
00675    }
00676 }
00677 
00678 //______________________________________________________________________________
00679 Bool_t TGLPlotCoordinates::GetZLog()const
00680 {
00681    // Get Z log.
00682 
00683    return fZLog;
00684 }
00685 
00686 //______________________________________________________________________________
00687 void TGLPlotCoordinates::ResetModified()
00688 {
00689    // Reset modified.
00690 
00691    fModified = !fModified;//kFALSE;
00692 }
00693 
00694 //______________________________________________________________________________
00695 Bool_t TGLPlotCoordinates::Modified()const
00696 {
00697    // Modified.
00698 
00699    return fModified;
00700 }
00701 
00702 //______________________________________________________________________________
00703 Bool_t TGLPlotCoordinates::SetRanges(const TH1 *hist, Bool_t errors, Bool_t zBins)
00704 {
00705    //Set bin ranges, ranges.
00706    switch (fCoordType) {
00707    case kGLPolar:
00708       return SetRangesPolar(hist);
00709    case kGLCylindrical:
00710       return SetRangesCylindrical(hist);
00711    case kGLSpherical:
00712       return SetRangesSpherical(hist);
00713    case kGLCartesian:
00714    default:
00715       return SetRangesCartesian(hist, errors, zBins);
00716    }
00717 }
00718 
00719 //______________________________________________________________________________
00720 Int_t TGLPlotCoordinates::GetNXBins()const
00721 {
00722    //Number of X bins.
00723    return fXBins.second - fXBins.first + 1;
00724 }
00725 
00726 //______________________________________________________________________________
00727 Int_t TGLPlotCoordinates::GetNYBins()const
00728 {
00729    //Number of Y bins.
00730    return fYBins.second - fYBins.first + 1;
00731 }
00732 
00733 //______________________________________________________________________________
00734 Int_t TGLPlotCoordinates::GetNZBins()const
00735 {
00736    //Number of Z bins.
00737    return fZBins.second - fZBins.first + 1;
00738 }
00739 
00740 //______________________________________________________________________________
00741 const Rgl::BinRange_t &TGLPlotCoordinates::GetXBins()const
00742 {
00743    //X bins range.
00744    return fXBins;
00745 }
00746 
00747 //______________________________________________________________________________
00748 const Rgl::BinRange_t &TGLPlotCoordinates::GetYBins()const
00749 {
00750    //Y bins range.
00751    return fYBins;
00752 }
00753 
00754 //______________________________________________________________________________
00755 const Rgl::BinRange_t &TGLPlotCoordinates::GetZBins()const
00756 {
00757    //Z bins range.
00758    return fZBins;
00759 }
00760 
00761 //______________________________________________________________________________
00762 const Rgl::Range_t &TGLPlotCoordinates::GetXRange()const
00763 {
00764    //X range.
00765    return fXRange;
00766 }
00767 
00768 //______________________________________________________________________________
00769 Double_t TGLPlotCoordinates::GetXLength()const
00770 {
00771    //X length.
00772    return fXRange.second - fXRange.first;
00773 }
00774 
00775 //______________________________________________________________________________
00776 const Rgl::Range_t &TGLPlotCoordinates::GetYRange()const
00777 {
00778    //Y range.
00779    return fYRange;
00780 }
00781 
00782 //______________________________________________________________________________
00783 Double_t TGLPlotCoordinates::GetYLength()const
00784 {
00785    //Y length.
00786    return fYRange.second - fYRange.first;
00787 }
00788 
00789 
00790 //______________________________________________________________________________
00791 const Rgl::Range_t &TGLPlotCoordinates::GetZRange()const
00792 {
00793    //Z range.
00794    return fZRange;
00795 }
00796 
00797 //______________________________________________________________________________
00798 Double_t TGLPlotCoordinates::GetZLength()const
00799 {
00800    //Z length.
00801    return fZRange.second - fZRange.first;
00802 }
00803 
00804 
00805 //______________________________________________________________________________
00806 const Rgl::Range_t &TGLPlotCoordinates::GetXRangeScaled()const
00807 {
00808    //Scaled range.
00809    return fXRangeScaled;
00810 }
00811 
00812 //______________________________________________________________________________
00813 const Rgl::Range_t &TGLPlotCoordinates::GetYRangeScaled()const
00814 {
00815    //Scaled range.
00816    return fYRangeScaled;
00817 }
00818 
00819 //______________________________________________________________________________
00820 const Rgl::Range_t &TGLPlotCoordinates::GetZRangeScaled()const
00821 {
00822    //Scaled range.
00823    return fZRangeScaled;
00824 }
00825 
00826 //______________________________________________________________________________
00827 Double_t TGLPlotCoordinates::GetFactor()const
00828 {
00829    // Get factor.
00830 
00831    return fFactor;
00832 }
00833 
00834 namespace {
00835 
00836 Bool_t FindAxisRange(const TAxis *axis, Bool_t log, Rgl::BinRange_t &bins, Rgl::Range_t &range);
00837 Bool_t FindAxisRange(const TH1 *hist, Bool_t logZ, const Rgl::BinRange_t &xBins,
00838                      const Rgl::BinRange_t &yBins, Rgl::Range_t &zRange,
00839                      Double_t &factor, Bool_t errors);
00840 
00841 Bool_t FindAxisRange(TH2Poly *hist, Bool_t zLog, Rgl::Range_t &zRange);
00842 
00843 }
00844 
00845 //______________________________________________________________________________
00846 Bool_t TGLPlotCoordinates::SetRangesCartesian(const TH1 *hist, Bool_t errors, Bool_t zAsBins)
00847 {
00848    //Set bin ranges, ranges, etc.
00849    Rgl::BinRange_t xBins;
00850    Rgl::Range_t    xRange;
00851    if (!FindAxisRange(hist->GetXaxis(), fXLog, xBins, xRange)) {
00852       Error("TGLPlotCoordinates::SetRangesCartesian", "Cannot set X axis to log scale");
00853       return kFALSE;
00854    }
00855 
00856    Rgl::BinRange_t yBins;
00857    Rgl::Range_t    yRange;
00858    if (!FindAxisRange(hist->GetYaxis(), fYLog, yBins, yRange)) {
00859       Error("TGLPlotCoordinates::SetRangesCartesian", "Cannot set Y axis to log scale");
00860       return kFALSE;
00861    }
00862 
00863    Rgl::BinRange_t zBins;
00864    Rgl::Range_t zRange;
00865    Double_t factor = 1.;
00866 
00867    if (zAsBins) {
00868       if (!FindAxisRange(hist->GetZaxis(), fZLog, zBins, zRange)) {
00869          Error("TGLPlotCoordinates::SetRangesCartesian", "Cannot set Z axis to log scale");
00870          return kFALSE;
00871       }
00872    } else if (!FindAxisRange(hist, fZLog, xBins, yBins, zRange, factor, errors)) {
00873       Error("TGLPlotCoordinates::SetRangesCartesian",
00874             "Log scale is requested for Z, but maximum less or equal 0. (%f)", zRange.second);
00875       return kFALSE;
00876    }
00877 
00878    //Finds the maximum dimension and adjust scale coefficients
00879    const Double_t x = xRange.second - xRange.first;
00880    const Double_t y = yRange.second - yRange.first;
00881    const Double_t z = zRange.second - zRange.first;
00882 
00883    if (!x || !y || !z) {
00884       Error("TGLPlotCoordinates::SetRangesCartesian", "Zero axis range.");
00885       return kFALSE;
00886    }
00887 
00888    if (xRange != fXRange || yRange != fYRange || zRange != fZRange ||
00889        xBins != fXBins || yBins != fYBins || zBins != fZBins || fFactor != factor)
00890    {
00891       fModified = kTRUE;
00892    }
00893 
00894    fXRange = xRange, fXBins = xBins, fYRange = yRange, fYBins = yBins, fZRange = zRange, fZBins = zBins;
00895    fFactor = factor;
00896    /*
00897    const Double_t maxDim = TMath::Max(TMath::Max(x, y), z);
00898    fXScale = maxDim / x;
00899    fYScale = maxDim / y;
00900    fZScale = maxDim / z;
00901    */
00902    fXScale = 1. / x;
00903    fYScale = 1. / y;
00904    fZScale = 1. / z;
00905 
00906    fXRangeScaled.first = fXRange.first * fXScale, fXRangeScaled.second = fXRange.second * fXScale;
00907    fYRangeScaled.first = fYRange.first * fYScale, fYRangeScaled.second = fYRange.second * fYScale;
00908    fZRangeScaled.first = fZRange.first * fZScale, fZRangeScaled.second = fZRange.second * fZScale;
00909 
00910    return kTRUE;
00911 }
00912 
00913 //
00914 //______________________________________________________________________________
00915 Bool_t TGLPlotCoordinates::SetRanges(TH2Poly *hist)
00916 {
00917    //Set bin ranges, ranges, etc.
00918    Rgl::BinRange_t xBins;
00919    Rgl::Range_t    xRange;
00920    FindAxisRange(hist->GetXaxis(), kFALSE, xBins, xRange);//kFALSE == never logarithmic.
00921 
00922    Rgl::BinRange_t yBins;
00923    Rgl::Range_t    yRange;
00924    FindAxisRange(hist->GetYaxis(), kFALSE, yBins, yRange);//kFALSE == never logarithmic.
00925 
00926    Rgl::BinRange_t zBins;
00927    Rgl::Range_t zRange;
00928    Double_t factor = 1.;
00929 
00930    if (!FindAxisRange(hist, fZLog, zRange))
00931       return kFALSE;
00932 
00933    //Finds the maximum dimension and adjust scale coefficients
00934    const Double_t x = xRange.second - xRange.first;
00935    const Double_t y = yRange.second - yRange.first;
00936    const Double_t z = zRange.second - zRange.first;
00937 
00938    if (!x || !y || !z) {
00939       Error("TGLPlotCoordinates::SetRanges", "Zero axis range.");
00940       return kFALSE;
00941    }
00942 
00943    if (xRange != fXRange || yRange != fYRange || zRange != fZRange ||
00944        xBins != fXBins || yBins != fYBins || zBins != fZBins || fFactor != factor)
00945    {
00946       fModified = kTRUE;
00947    }
00948 
00949    fXRange = xRange, fXBins = xBins, fYRange = yRange, fYBins = yBins, fZRange = zRange, fZBins = zBins;
00950    fFactor = factor;
00951 
00952    fXScale = Rgl::gH2PolyScaleXY / x;
00953    fYScale = Rgl::gH2PolyScaleXY / y;
00954    fZScale = 1. / z;
00955 
00956    fXRangeScaled.first = fXRange.first * fXScale, fXRangeScaled.second = fXRange.second * fXScale;
00957    fYRangeScaled.first = fYRange.first * fYScale, fYRangeScaled.second = fYRange.second * fYScale;
00958    fZRangeScaled.first = fZRange.first * fZScale, fZRangeScaled.second = fZRange.second * fZScale;
00959 
00960    return kTRUE;
00961 }
00962 //
00963 
00964 //______________________________________________________________________________
00965 Bool_t TGLPlotCoordinates::SetRanges(const TAxis *xAxis, const TAxis *yAxis, const TAxis *zAxis)
00966 {
00967    //Set bin ranges, ranges, etc.
00968    Rgl::BinRange_t xBins;
00969    Rgl::Range_t    xRange;
00970 
00971    FindAxisRange(xAxis, kFALSE, xBins, xRange);
00972 
00973    Rgl::BinRange_t yBins;
00974    Rgl::Range_t    yRange;
00975 
00976    FindAxisRange(yAxis, kFALSE, yBins, yRange);
00977 
00978    Rgl::BinRange_t zBins;
00979    Rgl::Range_t zRange;
00980    Double_t factor = 1.;
00981 
00982    FindAxisRange(zAxis, kFALSE, zBins, zRange);
00983 
00984    //Finds the maximum dimension and adjust scale coefficients
00985    const Double_t x = xRange.second - xRange.first;
00986    const Double_t y = yRange.second - yRange.first;
00987    const Double_t z = zRange.second - zRange.first;
00988 
00989    if (!x || !y || !z) {
00990       Error("TGLPlotCoordinates::SetRangesCartesian", "Zero axis range.");
00991       return kFALSE;
00992    }
00993 
00994    if (xRange != fXRange || yRange != fYRange || zRange != fZRange ||
00995        xBins != fXBins || yBins != fYBins || zBins != fZBins || fFactor != factor)
00996    {
00997       fModified = kTRUE;
00998    }
00999 
01000    fXRange = xRange, fXBins = xBins, fYRange = yRange, fYBins = yBins, fZRange = zRange, fZBins = zBins;
01001    fFactor = factor;
01002 
01003 /*   const Double_t maxDim = TMath::Max(TMath::Max(x, y), z);
01004    fXScale = maxDim / x;
01005    fYScale = maxDim / y;
01006    fZScale = maxDim / z;*/
01007 
01008    fXScale = 1. / x;
01009    fYScale = 1. / y;
01010    fZScale = 1. / z;
01011 
01012    fXRangeScaled.first = fXRange.first * fXScale, fXRangeScaled.second = fXRange.second * fXScale;
01013    fYRangeScaled.first = fYRange.first * fYScale, fYRangeScaled.second = fYRange.second * fYScale;
01014    fZRangeScaled.first = fZRange.first * fZScale, fZRangeScaled.second = fZRange.second * fZScale;
01015 
01016    return kTRUE;
01017 }
01018 
01019 //______________________________________________________________________________
01020 Bool_t TGLPlotCoordinates::SetRangesPolar(const TH1 *hist)
01021 {
01022    //Set bin ranges, ranges, etc.
01023    Rgl::BinRange_t xBins;
01024    Rgl::Range_t phiRange;
01025    const TAxis *xAxis = hist->GetXaxis();
01026    FindAxisRange(xAxis, kFALSE, xBins, phiRange);
01027    if (xBins.second - xBins.first + 1 > 360) {
01028       Error("TGLPlotCoordinates::SetRangesPolar", "To many PHI sectors");
01029       return kFALSE;
01030    }
01031 
01032    Rgl::BinRange_t yBins;
01033    Rgl::Range_t roRange;
01034    const TAxis *yAxis = hist->GetYaxis();
01035    FindAxisRange(yAxis, kFALSE, yBins, roRange);
01036 
01037    Rgl::Range_t zRange;
01038    Double_t factor = 1.;
01039    if (!FindAxisRange(hist, fZLog, xBins, yBins, zRange, factor, kFALSE))
01040    {
01041       Error("TGLPlotCoordinates::SetRangesPolar",
01042             "Log scale is requested for Z, but maximum less or equal 0. (%f)", zRange.second);
01043       return kFALSE;
01044    }
01045 
01046    const Double_t z = zRange.second - zRange.first;
01047    if (!z || !(phiRange.second - phiRange.first) || !(roRange.second - roRange.first)) {
01048       Error("TGLPlotCoordinates::SetRangesPolar", "Zero axis range.");
01049       return kFALSE;
01050    }
01051 
01052    if (phiRange != fXRange || roRange != fYRange || zRange != fZRange ||
01053        xBins != fXBins || yBins != fYBins || fFactor != factor)
01054    {
01055       fModified = kTRUE;
01056       fXRange = phiRange, fXBins = xBins;
01057       fYRange = roRange,  fYBins = yBins;
01058       fZRange = zRange;
01059       fFactor = factor;
01060    }
01061 
01062    //const Double_t maxDim = TMath::Max(2., z);
01063    fXScale = 0.5;//maxDim / 2.;
01064    fYScale = 0.5;//maxDim / 2.;
01065    fZScale = 1. / z;//maxDim / z;
01066    fXRangeScaled.first = -fXScale, fXRangeScaled.second = fXScale;
01067    fYRangeScaled.first = -fYScale, fYRangeScaled.second = fYScale;
01068    fZRangeScaled.first = fZRange.first * fZScale, fZRangeScaled.second = fZRange.second * fZScale;
01069 
01070    return kTRUE;
01071 }
01072 
01073 //______________________________________________________________________________
01074 Bool_t TGLPlotCoordinates::SetRangesCylindrical(const TH1 *hist)
01075 {
01076    // Set ranges cylindrical.
01077 
01078    Rgl::BinRange_t xBins, yBins;
01079    Rgl::Range_t angleRange, heightRange, radiusRange;
01080    const TAxis *xAxis = hist->GetXaxis();
01081    const TAxis *yAxis = hist->GetYaxis();
01082    Double_t factor = 1.;
01083 
01084    FindAxisRange(xAxis, kFALSE, xBins, angleRange);
01085    if (xBins.second - xBins.first + 1 > 360) {
01086       Error("TGLPlotCoordinates::SetRangesCylindrical", "To many PHI sectors");
01087       return kFALSE;
01088    }
01089    if (!FindAxisRange(yAxis, fYLog, yBins, heightRange)) {
01090       Error("TGLPlotCoordinates::SetRangesCylindrical", "Cannot set Y axis to log scale");
01091       return kFALSE;
01092    }
01093    FindAxisRange(hist, kFALSE, xBins, yBins, radiusRange, factor, kFALSE);
01094 
01095    const Double_t x = angleRange.second  - angleRange.first;
01096    const Double_t y = heightRange.second - heightRange.first;
01097    const Double_t z = radiusRange.second - radiusRange.first;
01098 
01099    if (!x || !y || !z) {
01100       Error("TGLPlotCoordinates::SetRangesCylindrical", "Zero axis range.");
01101       return kFALSE;
01102    }
01103 
01104    if (angleRange != fXRange  || heightRange != fYRange ||
01105        radiusRange != fZRange || xBins != fXBins ||
01106        yBins != fYBins || fFactor != factor)
01107    {
01108       fModified = kTRUE;
01109       fXRange = angleRange,  fXBins = xBins;
01110       fYRange = heightRange, fYBins = yBins;
01111       fZRange = radiusRange;
01112       fFactor = factor;
01113    }
01114 
01115    // const Double_t maxDim = TMath::Max(2., y);
01116    fXScale = 0.5;//maxDim / 2.;
01117    fYScale = 1. / y;//maxDim / y;
01118    fZScale = 0.5;//maxDim / 2.;
01119    fXRangeScaled.first = -fXScale, fXRangeScaled.second = fXScale;
01120    fYRangeScaled.first = fYRange.first * fYScale, fYRangeScaled.second = fYRange.second * fYScale;
01121    fZRangeScaled.first = -fZScale, fZRangeScaled.second = fZScale;
01122 
01123    return kTRUE;
01124 }
01125 
01126 //______________________________________________________________________________
01127 Bool_t TGLPlotCoordinates::SetRangesSpherical(const TH1 *hist)
01128 {
01129    // Set ranges spherical.
01130 
01131    Rgl::BinRange_t xBins;
01132    Rgl::Range_t phiRange;
01133    FindAxisRange(hist->GetXaxis(), kFALSE, xBins, phiRange);
01134    if (xBins.second - xBins.first + 1 > 360) {
01135       Error("TGLPlotCoordinates::SetRangesSpherical", "To many PHI sectors");
01136       return kFALSE;
01137    }
01138 
01139    Rgl::BinRange_t yBins;
01140    Rgl::Range_t thetaRange;
01141    FindAxisRange(hist->GetYaxis(), kFALSE, yBins, thetaRange);
01142    if (yBins.second - yBins.first + 1 > 180) {
01143       Error("TGLPlotCoordinates::SetRangesSpherical", "To many THETA sectors");
01144       return kFALSE;
01145    }
01146 
01147    Rgl::Range_t radiusRange;
01148    Double_t factor = 1.;
01149    FindAxisRange(hist, kFALSE, xBins, yBins, radiusRange, factor, kFALSE);
01150 
01151    if (xBins != fXBins || yBins != fYBins ||
01152        phiRange != fXRange || thetaRange != fYRange ||
01153        radiusRange != fZRange || fFactor != factor)
01154    {
01155       fModified = kTRUE;
01156       fXBins    = xBins;
01157       fYBins    = yBins;
01158       fXRange   = phiRange;
01159       fYRange   = thetaRange,
01160       fZRange   = radiusRange;
01161       fFactor   = factor;
01162    }
01163 
01164    fXScale = 0.5;
01165    fYScale = 0.5;
01166    fZScale = 0.5;
01167    fXRangeScaled.first = -fXScale, fXRangeScaled.second = fXScale;
01168    fYRangeScaled.first = -fYScale, fYRangeScaled.second = fYScale;
01169    fZRangeScaled.first = -fZScale, fZRangeScaled.second = fZScale;
01170 
01171    return kTRUE;
01172 }
01173 
01174 namespace {
01175 
01176 //______________________________________________________________________________
01177 Double_t FindMinBinWidth(const TAxis *axis)
01178 {
01179    // Find minimal bin width.
01180 
01181    Int_t currBin = axis->GetFirst();
01182    Double_t width = axis->GetBinWidth(currBin);
01183 
01184    if (!axis->IsVariableBinSize())//equal bins
01185       return width;
01186 
01187    ++currBin;
01188    //variable size bins
01189    for (const Int_t lastBin = axis->GetLast(); currBin <= lastBin; ++currBin)
01190       width = TMath::Min(width, axis->GetBinWidth(currBin));
01191 
01192    return width;
01193 }
01194 
01195 //______________________________________________________________________________
01196 Bool_t FindAxisRange(const TAxis *axis, Bool_t log, Rgl::BinRange_t &bins, Rgl::Range_t &range)
01197 {
01198    //"Generic" function, can be used for X/Y/Z axis.
01199    //[low edge of first ..... up edge of last]
01200    //If log is true, at least up edge of last MUST be positive or function fails (1).
01201    //If log is true and low edge is negative, try to find bin with positive low edge, bin number
01202    //must be less or equal to last (2). If no such bin, function failes.
01203    //When looking for a such bin, I'm trying to find value which is 0.01 of
01204    //MINIMUM bin width (3) (if bins are equidimensional, first's bin width is OK).
01205    //But even such lookup can fail, so, it's a stupid idea to have negative ranges
01206    //and logarithmic scale :)
01207 
01208    bins.first = axis->GetFirst(), bins.second = axis->GetLast();
01209    range.first = axis->GetBinLowEdge(bins.first), range.second = axis->GetBinUpEdge(bins.second);
01210 
01211    if (log) {
01212       if (range.second <= 0.)
01213          return kFALSE;//(1)
01214 
01215       range.second = TMath::Log10(range.second);
01216 
01217       if (range.first <= 0.) {//(2)
01218          Int_t bin = axis->FindFixBin(FindMinBinWidth(axis) * 0.01);//(3)
01219          //Overflow or something stupid.
01220          if (bin > bins.second)
01221             return kFALSE;
01222 
01223          if (axis->GetBinLowEdge(bin) <= 0.) {
01224             ++bin;
01225             if (bin > bins.second)//Again, something stupid.
01226                return kFALSE;
01227          }
01228 
01229          bins.first = bin;
01230          range.first = axis->GetBinLowEdge(bin);
01231       }
01232 
01233       range.first = TMath::Log10(range.first);
01234    }
01235 
01236    return kTRUE;
01237 }
01238 
01239 //______________________________________________________________________________
01240 Bool_t FindAxisRange(const TH1 *hist, Bool_t logZ, const Rgl::BinRange_t &xBins,
01241                      const Rgl::BinRange_t &yBins, Rgl::Range_t &zRange,
01242                      Double_t &factor, Bool_t errors)
01243 {
01244    //First, look through hist to find minimum and maximum values.
01245    const Bool_t minimum = hist->GetMinimumStored() != -1111;
01246    const Bool_t maximum = hist->GetMaximumStored() != -1111;
01247    const Double_t margin = gStyle->GetHistTopMargin();
01248 
01249    zRange.second = hist->GetCellContent(xBins.first, yBins.first), zRange.first = zRange.second;
01250    Double_t summ = 0.;
01251 
01252    for (Int_t i = xBins.first; i <= xBins.second; ++i) {
01253       for (Int_t j = yBins.first; j <= yBins.second; ++j) {
01254          Double_t val = hist->GetCellContent(i, j);
01255          if (val > 0. && errors)
01256             val = TMath::Max(val, val + hist->GetCellError(i, j));
01257          zRange.second = TMath::Max(val, zRange.second);
01258          zRange.first = TMath::Min(val, zRange.first);
01259          summ += val;
01260       }
01261    }
01262 
01263    if (hist->GetMaximumStored() != -1111)
01264       zRange.second = hist->GetMaximumStored();
01265    if (hist->GetMinimumStored() != -1111)
01266       zRange.first = hist->GetMinimumStored();
01267 
01268    if (logZ && zRange.second <= 0.)
01269       return kFALSE;//cannot setup logarithmic scale
01270 
01271    if (zRange.first >= zRange.second)
01272       zRange.first = 0.001 * zRange.second;
01273 
01274    factor = hist->GetNormFactor() > 0. ? hist->GetNormFactor() : summ;
01275    if (summ) factor /= summ;
01276    if (!factor) factor = 1.;
01277    if (factor < 0.)
01278       Warning("TGLPlotPainter::ExtractAxisZInfo",
01279               "Negative factor, negative ranges - possible incorrect behavior");
01280 
01281    zRange.second *= factor;
01282    zRange.first  *= factor;
01283 
01284    if (logZ) {
01285       if (zRange.first <= 0.)
01286          zRange.first = TMath::Min(1., 0.001 * zRange.second);
01287       zRange.first = TMath::Log10(zRange.first);
01288       if (!minimum)
01289          zRange.first += TMath::Log10(0.5);
01290       zRange.second = TMath::Log10(zRange.second);
01291       if (!maximum)
01292          zRange.second += TMath::Log10(2*(0.9/0.95));//This magic numbers are from THistPainter.
01293       return kTRUE;
01294    }
01295 
01296    if (!maximum)
01297       zRange.second += margin * (zRange.second - zRange.first);
01298    if (!minimum) {
01299       if (gStyle->GetHistMinimumZero())
01300          zRange.first >= 0 ? zRange.first = 0. : zRange.first -= margin * (zRange.second - zRange.first);
01301       else
01302          zRange.first >= 0 && zRange.first - margin * (zRange.second - zRange.first) <= 0 ?
01303                zRange.first = 0 : zRange.first -= margin * (zRange.second - zRange.first);
01304    }
01305 
01306    return kTRUE;
01307 }
01308 
01309 //______________________________________________________________________________
01310 Bool_t FindAxisRange(TH2Poly *hist, Bool_t logZ, Rgl::Range_t &zRange)
01311 {
01312    //First, look through hist to find minimum and maximum values.
01313    TList *bins = hist->GetBins();
01314    if (!bins || !bins->GetEntries()) {
01315       Error("FindAxisRange", "TH2Poly returned empty list of bins");
01316       return kFALSE;
01317    }
01318 
01319    zRange.first  = hist->GetMinimum();
01320    zRange.second = hist->GetMaximum();
01321 
01322    if (zRange.first >= zRange.second)
01323       zRange.first = 0.001 * zRange.second;
01324 
01325    if (logZ) {
01326       if (zRange.second < 1e-20) {//OMG! Why is this code sooo bad and ugly? :)
01327          Error("FindAxisRange", "Failed to switch Z axis to logarithmic scale");
01328          return kFALSE;
01329       }
01330 
01331       if (zRange.first <= 0.)
01332          zRange.first = TMath::Min(1., 0.001 * zRange.second);
01333 
01334       zRange.first  = TMath::Log10(zRange.first);
01335       zRange.first += TMath::Log10(0.5);
01336       zRange.second = TMath::Log10(zRange.second);
01337       zRange.second += TMath::Log10(2 * (0.9 / 0.95));//These magic numbers come from THistPainter.
01338 
01339       return kTRUE;
01340    }
01341 
01342    const Double_t margin = gStyle->GetHistTopMargin();
01343    zRange.second += margin * (zRange.second - zRange.first);
01344    if (gStyle->GetHistMinimumZero())
01345       zRange.first >= 0 ? zRange.first = 0. : zRange.first -= margin * (zRange.second - zRange.first);
01346    else
01347       zRange.first >= 0 && zRange.first - margin * (zRange.second - zRange.first) <= 0 ?
01348          zRange.first = 0 : zRange.first -= margin * (zRange.second - zRange.first);
01349 
01350    return kTRUE;
01351 }
01352 
01353 }
01354 
01355 //______________________________________________________________________________
01356 //
01357 // Used by plot-painters to determine the area of the plot that
01358 // is cut away.
01359 
01360 ClassImp(TGLBoxCut)
01361 
01362 //______________________________________________________________________________
01363 TGLBoxCut::TGLBoxCut(const TGLPlotBox *box)
01364                : fXLength(0.),
01365                  fYLength(0.),
01366                  fZLength(0.),
01367                  fPlotBox(box),
01368                  fActive(kFALSE),
01369                  fFactor(1.)
01370 {
01371    //Constructor.
01372 }
01373 
01374 //______________________________________________________________________________
01375 TGLBoxCut::~TGLBoxCut()
01376 {
01377    //Destructor.
01378 }
01379 
01380 //______________________________________________________________________________
01381 void TGLBoxCut::TurnOnOff()
01382 {
01383    //Turn the box cut on/off.
01384    //If it's on, it will be placed in front point of a plot.
01385    fActive = !fActive;
01386 
01387    if (fActive) {
01388       ResetBoxGeometry();
01389    }
01390 }
01391 
01392 //______________________________________________________________________________
01393 void TGLBoxCut::SetActive(Bool_t a)
01394 {
01395    //Turn the box cut on/off.
01396    if (a == fActive)
01397       return;
01398    TurnOnOff();
01399 }
01400 
01401 //______________________________________________________________________________
01402 void TGLBoxCut::ResetBoxGeometry()
01403 {
01404    //Set geometry using plot's back box.
01405 
01406    const Int_t frontPoint = fPlotBox->GetFrontPoint();
01407    const TGLVertex3 *box = fPlotBox->Get3DBox();
01408    const TGLVertex3 center((box[0].X() + box[1].X()) / 2, (box[0].Y() + box[2].Y()) / 2,
01409                            (box[0].Z() + box[4].Z()) / 2);
01410    fXLength = fFactor * (box[1].X() - box[0].X());
01411    fYLength = fFactor * (box[2].Y() - box[0].Y());
01412    fZLength = fFactor * (box[4].Z() - box[0].Z());
01413 
01414    switch(frontPoint){
01415    case 0:
01416       fCenter.X() = box[0].X();
01417       fCenter.Y() = box[0].Y();
01418       break;
01419    case 1:
01420       fCenter.X() = box[1].X();
01421       fCenter.Y() = box[0].Y();
01422       break;
01423    case 2:
01424       fCenter.X() = box[2].X();
01425       fCenter.Y() = box[2].Y();
01426       break;
01427    case 3:
01428       fCenter.X() = box[0].X();
01429       fCenter.Y() = box[2].Y();
01430       break;
01431    }
01432 
01433    fCenter.Z() = box[0].Z() * 0.5 + box[4].Z() * 0.5;
01434    AdjustBox();
01435 }
01436 
01437 //______________________________________________________________________________
01438 void TGLBoxCut::DrawBox(Bool_t selectionPass, Int_t selected)const
01439 {
01440    //Draw cut as a semi-transparent box.
01441    if (!selectionPass) {
01442       glDisable(GL_LIGHTING);
01443       glLineWidth(3.f);
01444 
01445       selected == TGLPlotPainter::kXAxis ? glColor3d(1., 1., 0.) : glColor3d(1., 0., 0.);
01446       glBegin(GL_LINES);
01447       glVertex3d(fXRange.first, (fYRange.first + fYRange.second) / 2, (fZRange.first + fZRange.second) / 2);
01448       glVertex3d(fXRange.second, (fYRange.first + fYRange.second) / 2, (fZRange.first + fZRange.second) / 2);
01449       glEnd();
01450 
01451       selected == TGLPlotPainter::kYAxis ? glColor3d(1., 1., 0.) : glColor3d(0., 1., 0.);
01452       glBegin(GL_LINES);
01453       glVertex3d((fXRange.first + fXRange.second) / 2, fYRange.first, (fZRange.first + fZRange.second) / 2);
01454       glVertex3d((fXRange.first + fXRange.second) / 2, fYRange.second, (fZRange.first + fZRange.second) / 2);
01455       glEnd();
01456 
01457       selected == TGLPlotPainter::kZAxis ? glColor3d(1., 1., 0.) : glColor3d(0., 0., 1.);
01458       glBegin(GL_LINES);
01459       glVertex3d((fXRange.first + fXRange.second) / 2, (fYRange.first + fYRange.second) / 2, fZRange.first);
01460       glVertex3d((fXRange.first + fXRange.second) / 2, (fYRange.first + fYRange.second) / 2, fZRange.second);
01461       glEnd();
01462 
01463       glLineWidth(1.f);
01464       glEnable(GL_LIGHTING);
01465 
01466       GLboolean oldBlendState = kFALSE;
01467       glGetBooleanv(GL_BLEND, &oldBlendState);
01468 
01469       if (!oldBlendState)
01470          glEnable(GL_BLEND);
01471 
01472       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01473 
01474 
01475       const Float_t diffuseColor[] = {0.f, 0.f, 1.f, 0.1f};
01476       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuseColor);
01477 
01478       Rgl::DrawBoxFront(fXRange.first, fXRange.second, fYRange.first, fYRange.second,
01479                         fZRange.first, fZRange.second, fPlotBox->GetFrontPoint());
01480 
01481       if (!oldBlendState)
01482          glDisable(GL_BLEND);
01483    } else {
01484       glLineWidth(5.f);
01485       Rgl::ObjectIDToColor(TGLPlotPainter::kXAxis, kFALSE);
01486       glBegin(GL_LINES);
01487       glVertex3d(fXRange.first, (fYRange.first + fYRange.second) / 2, (fZRange.first + fZRange.second) / 2);
01488       glVertex3d(fXRange.second, (fYRange.first + fYRange.second) / 2, (fZRange.first + fZRange.second) / 2);
01489       glEnd();
01490 
01491       Rgl::ObjectIDToColor(TGLPlotPainter::kYAxis, kFALSE);
01492       glBegin(GL_LINES);
01493       glVertex3d((fXRange.first + fXRange.second) / 2, fYRange.first, (fZRange.first + fZRange.second) / 2);
01494       glVertex3d((fXRange.first + fXRange.second) / 2, fYRange.second, (fZRange.first + fZRange.second) / 2);
01495       glEnd();
01496 
01497       Rgl::ObjectIDToColor(TGLPlotPainter::kZAxis, kFALSE);
01498       glBegin(GL_LINES);
01499       glVertex3d((fXRange.first + fXRange.second) / 2, (fYRange.first + fYRange.second) / 2, fZRange.first);
01500       glVertex3d((fXRange.first + fXRange.second) / 2, (fYRange.first + fYRange.second) / 2, fZRange.second);
01501       glEnd();
01502       glLineWidth(1.f);
01503    }
01504 }
01505 
01506 //______________________________________________________________________________
01507 void TGLBoxCut::StartMovement(Int_t px, Int_t py)
01508 {
01509    //Start cut's movement
01510    fMousePos.fX = px;
01511    fMousePos.fY = py;
01512 }
01513 
01514 //______________________________________________________________________________
01515 void TGLBoxCut::MoveBox(Int_t px, Int_t py, Int_t axisID)
01516 {
01517    //Move box cut along selected direction.
01518    Double_t mv[16] = {0.};
01519    glGetDoublev(GL_MODELVIEW_MATRIX, mv);
01520    Double_t pr[16] = {0.};
01521    glGetDoublev(GL_PROJECTION_MATRIX, pr);
01522    Int_t vp[4] = {0};
01523    glGetIntegerv(GL_VIEWPORT, vp);
01524    Double_t winVertex[3] = {0.};
01525 
01526    switch(axisID){
01527    case TGLPlotPainter::kXAxis :
01528       gluProject(fCenter.X(), 0., 0., mv, pr, vp, &winVertex[0], &winVertex[1], &winVertex[2]);
01529       break;
01530    case TGLPlotPainter::kYAxis :
01531       gluProject(0., fCenter.Y(), 0., mv, pr, vp, &winVertex[0], &winVertex[1], &winVertex[2]);
01532       break;
01533    case TGLPlotPainter::kZAxis :
01534       gluProject(0., 0., fCenter.Z(), mv, pr, vp, &winVertex[0], &winVertex[1], &winVertex[2]);
01535       break;
01536    }
01537 
01538    winVertex[0] += px - fMousePos.fX;
01539    winVertex[1] += py - fMousePos.fY;
01540    Double_t newPoint[3] = {0.};
01541    gluUnProject(winVertex[0], winVertex[1], winVertex[2], mv, pr, vp,
01542                 newPoint, newPoint + 1, newPoint + 2);
01543 
01544    const TGLVertex3 *box = fPlotBox->Get3DBox();
01545 
01546    switch(axisID){
01547    case TGLPlotPainter::kXAxis :
01548       if (newPoint[0] >= box[1].X() + 0.4 * fXLength)
01549          break;
01550       if (newPoint[0] <= box[0].X() - 0.4 * fXLength)
01551          break;
01552       fCenter.X() = newPoint[0];
01553       break;
01554    case TGLPlotPainter::kYAxis :
01555       if (newPoint[1] >= box[2].Y() + 0.4 * fYLength)
01556          break;
01557       if (newPoint[1] <= box[0].Y() - 0.4 * fYLength)
01558          break;
01559       fCenter.Y() = newPoint[1];
01560       break;
01561    case TGLPlotPainter::kZAxis :
01562       if (newPoint[2] >= box[4].Z() + 0.4 * fZLength)
01563          break;
01564       if (newPoint[2] <= box[0].Z() - 0.4 * fZLength)
01565          break;
01566       fCenter.Z() = newPoint[2];
01567       break;
01568    }
01569 
01570    fMousePos.fX = px;
01571    fMousePos.fY = py;
01572 
01573    AdjustBox();
01574 }
01575 
01576 //______________________________________________________________________________
01577 void TGLBoxCut::AdjustBox()
01578 {
01579    //Box cut is limited by plot's sizes.
01580    const TGLVertex3 *box = fPlotBox->Get3DBox();
01581 
01582    fXRange.first  = fCenter.X() - fXLength / 2.;
01583    fXRange.second = fCenter.X() + fXLength / 2.;
01584    fYRange.first  = fCenter.Y() - fYLength / 2.;
01585    fYRange.second = fCenter.Y() + fYLength / 2.;
01586    fZRange.first  = fCenter.Z() - fZLength / 2.;
01587    fZRange.second = fCenter.Z() + fZLength / 2.;
01588 
01589    fXRange.first  = TMath::Max(fXRange.first,  box[0].X());
01590    fXRange.first  = TMath::Min(fXRange.first,  box[1].X());
01591    fXRange.second = TMath::Min(fXRange.second, box[1].X());
01592    fXRange.second = TMath::Max(fXRange.second, box[0].X());
01593 
01594    fYRange.first  = TMath::Max(fYRange.first,  box[0].Y());
01595    fYRange.first  = TMath::Min(fYRange.first,  box[2].Y());
01596    fYRange.second = TMath::Min(fYRange.second, box[2].Y());
01597    fYRange.second = TMath::Max(fYRange.second, box[0].Y());
01598 
01599    fZRange.first  = TMath::Max(fZRange.first,  box[0].Z());
01600    fZRange.first  = TMath::Min(fZRange.first,  box[4].Z());
01601    fZRange.second = TMath::Min(fZRange.second, box[4].Z());
01602    fZRange.second = TMath::Max(fZRange.second, box[0].Z());
01603 }
01604 
01605 //______________________________________________________________________________
01606 Bool_t TGLBoxCut::IsInCut(Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax,
01607                           Double_t zMin, Double_t zMax)const
01608 {
01609    //Check, if box defined by xmin/xmax etc. is in cut.
01610    if (((xMin >= fXRange.first && xMin < fXRange.second) || (xMax > fXRange.first && xMax <= fXRange.second)) &&
01611        ((yMin >= fYRange.first && yMin < fYRange.second) || (yMax > fYRange.first && yMax <= fYRange.second)) &&
01612        ((zMin >= fZRange.first && zMin < fZRange.second) || (zMax > fZRange.first && zMax <= fZRange.second)))
01613       return kTRUE;
01614    return kFALSE;
01615 }
01616 
01617 
01618 //______________________________________________________________________________
01619 //
01620 // A slice of a TH3.
01621 
01622 ClassImp(TGLTH3Slice)
01623 
01624 //______________________________________________________________________________
01625 TGLTH3Slice::TGLTH3Slice(const TString &name, const TH3 *hist, const TGLPlotCoordinates *coord,
01626                          const TGLPlotBox *box, ESliceAxis axis)
01627                : TNamed(name, name),
01628                  fAxisType(axis),
01629                  fAxis(0),
01630                  fCoord(coord),
01631                  fBox(box),
01632                  fSliceWidth(1),
01633                  fHist(hist),
01634                  fF3(0)
01635 {
01636    // Constructor.
01637    fAxis = fAxisType == kXOZ ? fHist->GetYaxis() : fAxisType == kYOZ ? fHist->GetXaxis() : fHist->GetZaxis();
01638 }
01639 
01640 //______________________________________________________________________________
01641 TGLTH3Slice::TGLTH3Slice(const TString &name, const TH3 *hist, const TF3 *fun, const TGLPlotCoordinates *coord,
01642                          const TGLPlotBox *box, ESliceAxis axis)
01643                : TNamed(name, name),
01644                  fAxisType(axis),
01645                  fAxis(0),
01646                  fCoord(coord),
01647                  fBox(box),
01648                  fSliceWidth(1),
01649                  fHist(hist),
01650                  fF3(fun)
01651 {
01652    // Constructor.
01653    fAxis = fAxisType == kXOZ ? fHist->GetYaxis() : fAxisType == kYOZ ? fHist->GetXaxis() : fHist->GetZaxis();
01654 }
01655 
01656 //______________________________________________________________________________
01657 void TGLTH3Slice::SetSliceWidth(Int_t width)
01658 {
01659    // Set Slice width.
01660 
01661    if (width <= 0)
01662       return;
01663 
01664    if (fAxis->GetLast() - fAxis->GetFirst() + 1 <= width)
01665       fSliceWidth = fAxis->GetLast() - fAxis->GetFirst() + 1;
01666    else
01667       fSliceWidth = width;
01668 }
01669 
01670 //______________________________________________________________________________
01671 void TGLTH3Slice::DrawSlice(Double_t pos)const
01672 {
01673    // Draw slice.
01674    Int_t bin = 0;
01675    for (Int_t i = fAxis->GetFirst(), e = fAxis->GetLast(); i <= e; ++i) {
01676       if (pos >= fAxis->GetBinLowEdge(i) && pos <= fAxis->GetBinUpEdge(i)) {
01677          bin = i;
01678          break;
01679       }
01680    }
01681 
01682    if (bin) {
01683       Int_t low = 1, up = 2;
01684       if (bin - fSliceWidth + 1 >= fAxis->GetFirst()) {
01685          low = bin - fSliceWidth + 1;
01686          up  = bin + 1;
01687       } else {
01688          low = fAxis->GetFirst();
01689          up  = bin + (fSliceWidth - (bin - fAxis->GetFirst() + 1)) + 1;
01690       }
01691 
01692       if (!fF3)
01693          FindMinMax(low, up);
01694 
01695       if (!PreparePalette())
01696          return;
01697 
01698       PrepareTexCoords(pos, low, up);
01699 
01700       fPalette.EnableTexture(GL_REPLACE);
01701       const TGLDisableGuard lightGuard(GL_LIGHTING);
01702       DrawSliceTextured(pos);
01703       fPalette.DisableTexture();
01704       //highlight bins in a slice.
01705       //DrawSliceFrame(low, up);
01706    }
01707 }
01708 
01709 //______________________________________________________________________________
01710 void TGLTH3Slice::FindMinMax(Int_t /*low*/, Int_t /*up*/)const
01711 {
01712    // Find minimum and maximum for slice.
01713   /* fMinMax.first = 0.;
01714 
01715    switch (fAxisType) {
01716    case kXOZ:
01717       for (Int_t level = low; level < up; ++ level)
01718          fMinMax.first += fHist->GetBinContent(fCoord->GetFirstXBin(), level, fCoord->GetFirstZBin());
01719       fMinMax.second = fMinMax.first;
01720       for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j <= ej; ++j, ++jt) {
01721          for (Int_t i = fCoord->GetFirstXBin(), it = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++it) {
01722             Double_t val = 0.;
01723             for (Int_t level = low; level < up; ++ level)
01724                val += fHist->GetBinContent(i, level, j);
01725             fMinMax.second = TMath::Max(fMinMax.second, val);
01726             fMinMax.first = TMath::Min(fMinMax.first, val);
01727          }
01728       }
01729       break;
01730    case kYOZ:
01731       for (Int_t level = low; level < up; ++ level)
01732          fMinMax.first += fHist->GetBinContent(level, fCoord->GetFirstYBin(), fCoord->GetFirstZBin());
01733       fMinMax.second = fMinMax.first;
01734       for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j <= ej; ++j, ++jt) {
01735          for (Int_t i = fCoord->GetFirstYBin(), it = 0, ei = fCoord->GetLastYBin(); i <= ei; ++i, ++it) {
01736             Double_t val = 0.;
01737             for (Int_t level = low; level < up; ++ level)
01738                val += fHist->GetBinContent(level, i, j);
01739             fMinMax.second = TMath::Max(fMinMax.second, val);
01740             fMinMax.first = TMath::Min(fMinMax.first, val);
01741          }
01742       }
01743       break;
01744    case kXOY:
01745       for (Int_t level = low; level < up; ++ level)
01746          fMinMax.first += fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin(), level);
01747       fMinMax.second = fMinMax.first;
01748       for (Int_t i = fCoord->GetFirstXBin(), ir = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++ir) {
01749          for (Int_t j = fCoord->GetFirstYBin(), jr = 0, ej = fCoord->GetLastYBin(); j <= ej; ++j, ++jr) {
01750             Double_t val = 0.;
01751             for (Int_t level = low; level < up; ++ level)
01752                val += fHist->GetBinContent(i, j, level);
01753             fMinMax.second = TMath::Max(fMinMax.second, val);
01754             fMinMax.first = TMath::Min(fMinMax.first, val);
01755          }
01756       }
01757       break;
01758    }*/
01759 }
01760 
01761 //______________________________________________________________________________
01762 Bool_t TGLTH3Slice::PreparePalette()const
01763 {
01764    //Initialize color palette.
01765    UInt_t paletteSize = ((TH1 *)fHist)->GetContour();
01766    if (!paletteSize && !(paletteSize = gStyle->GetNumberContours()))
01767       paletteSize = 20;
01768 
01769    return fPalette.GeneratePalette(paletteSize, fMinMax);
01770 }
01771 
01772 //______________________________________________________________________________
01773 void TGLTH3Slice::PrepareTexCoords(Double_t pos, Int_t low, Int_t up)const
01774 {
01775    // Prepare TexCoords.
01776    switch (fAxisType) {
01777    case kXOZ:
01778       fTexCoords.resize(fCoord->GetNXBins() * fCoord->GetNZBins());
01779       fTexCoords.SetRowLen(fCoord->GetNXBins());
01780       if (!fF3) {
01781 
01782          for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j <= ej; ++j, ++jt) {
01783             for (Int_t i = fCoord->GetFirstXBin(), it = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++it) {
01784                Double_t val = 0.;
01785                for (Int_t level = low; level < up; ++ level)
01786                   val += fHist->GetBinContent(i, level, j);
01787                fTexCoords[jt][it] = fPalette.GetTexCoord(val);
01788             }
01789          }
01790       } else {
01791          for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j <= ej; ++j, ++jt) {
01792             for (Int_t i = fCoord->GetFirstXBin(), it = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++it) {
01793                Double_t val = fF3->Eval(fHist->GetXaxis()->GetBinCenter(i), pos, fHist->GetZaxis()->GetBinCenter(j));
01794                if (val > fMinMax.second)
01795                   val = fMinMax.second;
01796                else if (val < fMinMax.first)
01797                   val = fMinMax.first;
01798                fTexCoords[jt][it] = fPalette.GetTexCoord(val);
01799             }
01800          }
01801       }
01802       break;
01803    case kYOZ:
01804       fTexCoords.resize(fCoord->GetNYBins() * fCoord->GetNZBins());
01805       fTexCoords.SetRowLen(fCoord->GetNYBins());
01806       if (!fF3) {
01807          for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j <= ej; ++j, ++jt) {
01808             for (Int_t i = fCoord->GetFirstYBin(), it = 0, ei = fCoord->GetLastYBin(); i <= ei; ++i, ++it) {
01809                Double_t val = 0.;
01810                for (Int_t level = low; level < up; ++ level)
01811                   val += fHist->GetBinContent(level, i, j);
01812                fTexCoords[jt][it] = fPalette.GetTexCoord(val);
01813             }
01814          }
01815       } else {
01816          for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j <= ej; ++j, ++jt) {
01817             for (Int_t i = fCoord->GetFirstXBin(), it = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++it) {
01818                Double_t val = fF3->Eval(pos, fHist->GetYaxis()->GetBinCenter(i), fHist->GetZaxis()->GetBinCenter(j));
01819                if (val > fMinMax.second)
01820                   val = fMinMax.second;
01821                else if (val < fMinMax.first)
01822                   val = fMinMax.first;
01823                fTexCoords[jt][it] = fPalette.GetTexCoord(val);
01824             }
01825          }
01826       }
01827       break;
01828    case kXOY:
01829       fTexCoords.resize(fCoord->GetNXBins() * fCoord->GetNYBins());
01830       fTexCoords.SetRowLen(fCoord->GetNYBins());
01831       if (!fF3) {
01832          for (Int_t i = fCoord->GetFirstXBin(), ir = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++ir) {
01833             for (Int_t j = fCoord->GetFirstYBin(), jr = 0, ej = fCoord->GetLastYBin(); j <= ej; ++j, ++jr) {
01834                Double_t val = 0.;
01835                for (Int_t level = low; level < up; ++ level)
01836                   val += fHist->GetBinContent(i, j, level);
01837                fTexCoords[ir][jr] = fPalette.GetTexCoord(val);
01838             }
01839          }
01840       } else {
01841          for (Int_t i = fCoord->GetFirstXBin(), it = 0, ei = fCoord->GetLastXBin(); i <= ei; ++i, ++it) {
01842             for (Int_t j = fCoord->GetFirstYBin(), jt = 0, ej = fCoord->GetLastYBin(); j <= ej; ++j, ++jt) {
01843                Double_t val = fF3->Eval(fHist->GetXaxis()->GetBinCenter(i), fHist->GetYaxis()->GetBinCenter(j), pos);
01844                if (val > fMinMax.second)
01845                   val = fMinMax.second;
01846                else if (val < fMinMax.first)
01847                   val = fMinMax.first;
01848                fTexCoords[it][jt] = fPalette.GetTexCoord(val);
01849             }
01850          }
01851 
01852       }
01853       break;
01854    }
01855 }
01856 
01857 //______________________________________________________________________________
01858 void TGLTH3Slice::DrawSliceTextured(Double_t pos)const
01859 {
01860    // Draw slice textured.
01861 
01862    const Double_t xScale = fCoord->GetXScale();
01863    const Double_t yScale = fCoord->GetYScale();
01864    const Double_t zScale = fCoord->GetZScale();
01865    const TAxis *xA = fHist->GetXaxis();
01866    const TAxis *yA = fHist->GetYaxis();
01867    const TAxis *zA = fHist->GetZaxis();
01868 
01869    switch (fAxisType) {
01870    case kXOZ:
01871       pos *= yScale;
01872       for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j < ej; ++j, ++jt) {
01873          for (Int_t i = fCoord->GetFirstXBin(), it = 0, ei = fCoord->GetLastXBin(); i < ei; ++i, ++it) {
01874             const Double_t xMin = xA->GetBinCenter(i) * xScale;
01875             const Double_t xMax = xA->GetBinCenter(i + 1) * xScale;
01876             const Double_t zMin = zA->GetBinCenter(j) * zScale;
01877             const Double_t zMax = zA->GetBinCenter(j + 1) * zScale;
01878             glBegin(GL_POLYGON);
01879             glTexCoord1d(fTexCoords[jt][it]);
01880             glVertex3d(xMin, pos, zMin);
01881             glTexCoord1d(fTexCoords[jt + 1][it]);
01882             glVertex3d(xMin, pos, zMax);
01883             glTexCoord1d(fTexCoords[jt + 1][it + 1]);
01884             glVertex3d(xMax, pos, zMax);
01885             glTexCoord1d(fTexCoords[jt][it + 1]);
01886             glVertex3d(xMax, pos, zMin);
01887             glEnd();
01888          }
01889       }
01890       break;
01891    case kYOZ:
01892       pos *= xScale;
01893       for (Int_t j = fCoord->GetFirstZBin(), jt = 0, ej = fCoord->GetLastZBin(); j < ej; ++j, ++jt) {
01894          for (Int_t i = fCoord->GetFirstYBin(), it = 0, ei = fCoord->GetLastYBin(); i < ei; ++i, ++it) {
01895             const Double_t yMin = yA->GetBinCenter(i) * yScale;
01896             const Double_t yMax = yA->GetBinCenter(i + 1) * yScale;
01897             const Double_t zMin = zA->GetBinCenter(j) * zScale;
01898             const Double_t zMax = zA->GetBinCenter(j + 1) * zScale;
01899             glBegin(GL_POLYGON);
01900             glTexCoord1d(fTexCoords[jt][it]);
01901             glVertex3d(pos, yMin, zMin);
01902             glTexCoord1d(fTexCoords[jt][it + 1]);
01903             glVertex3d(pos, yMax, zMin);
01904             glTexCoord1d(fTexCoords[jt + 1][it + 1]);
01905             glVertex3d(pos, yMax, zMax);
01906             glTexCoord1d(fTexCoords[jt + 1][it]);
01907             glVertex3d(pos, yMin, zMax);
01908             glEnd();
01909          }
01910       }
01911       break;
01912    case kXOY:
01913       pos *= zScale;
01914       for (Int_t j = fCoord->GetFirstXBin(), jt = 0, ej = fCoord->GetLastXBin(); j < ej; ++j, ++jt) {
01915          for (Int_t i = fCoord->GetFirstYBin(), it = 0, ei = fCoord->GetLastYBin(); i < ei; ++i, ++it) {
01916             const Double_t xMin = xA->GetBinCenter(j) * xScale;
01917             const Double_t xMax = xA->GetBinCenter(j + 1) * xScale;
01918             const Double_t yMin = yA->GetBinCenter(i) * yScale;
01919             const Double_t yMax = yA->GetBinCenter(i + 1) * yScale;
01920             glBegin(GL_POLYGON);
01921             glTexCoord1d(fTexCoords[jt + 1][it]);
01922             glVertex3d(xMax, yMin, pos);
01923             glTexCoord1d(fTexCoords[jt + 1][it + 1]);
01924             glVertex3d(xMax, yMax, pos);
01925             glTexCoord1d(fTexCoords[jt][it + 1]);
01926             glVertex3d(xMin, yMax, pos);
01927             glTexCoord1d(fTexCoords[jt][it]);
01928             glVertex3d(xMin, yMin, pos);
01929             glEnd();
01930          }
01931       }
01932       break;
01933    }
01934 }
01935 
01936 namespace {
01937 
01938 //______________________________________________________________________________
01939 void DrawBoxOutline(Double_t xMin, Double_t xMax, Double_t yMin,
01940                     Double_t yMax, Double_t zMin, Double_t zMax)
01941 {
01942    glBegin(GL_LINE_LOOP);
01943    glVertex3d(xMin, yMin, zMin);
01944    glVertex3d(xMax, yMin, zMin);
01945    glVertex3d(xMax, yMax, zMin);
01946    glVertex3d(xMin, yMax, zMin);
01947    glEnd();
01948 
01949    glBegin(GL_LINE_LOOP);
01950    glVertex3d(xMin, yMin, zMax);
01951    glVertex3d(xMax, yMin, zMax);
01952    glVertex3d(xMax, yMax, zMax);
01953    glVertex3d(xMin, yMax, zMax);
01954    glEnd();
01955 
01956    glBegin(GL_LINES);
01957    glVertex3d(xMin, yMin, zMin);
01958    glVertex3d(xMin, yMin, zMax);
01959    glVertex3d(xMax, yMin, zMin);
01960    glVertex3d(xMax, yMin, zMax);
01961    glVertex3d(xMax, yMax, zMin);
01962    glVertex3d(xMax, yMax, zMax);
01963    glVertex3d(xMin, yMax, zMin);
01964    glVertex3d(xMin, yMax, zMax);
01965    glEnd();
01966 }
01967 
01968 }
01969 
01970 //______________________________________________________________________________
01971 void TGLTH3Slice::DrawSliceFrame(Int_t low, Int_t up)const
01972 {
01973    // Draw slice frame.
01974 
01975    glColor3d(1., 0., 0.);
01976    const TGLVertex3 *box = fBox->Get3DBox();
01977 
01978    switch (fAxisType) {
01979    case kXOZ:
01980       DrawBoxOutline(box[0].X(), box[1].X(),
01981                      fAxis->GetBinLowEdge(low) * fCoord->GetYScale(),
01982                      fAxis->GetBinUpEdge(up - 1) * fCoord->GetYScale(),
01983                      box[0].Z(), box[4].Z());
01984       break;
01985    case kYOZ:
01986       DrawBoxOutline(fAxis->GetBinLowEdge(low) * fCoord->GetXScale(),
01987                      fAxis->GetBinUpEdge(up - 1) * fCoord->GetXScale(),
01988                      box[0].Y(), box[2].Y(),
01989                      box[0].Z(), box[4].Z());
01990       break;
01991    case kXOY:
01992       DrawBoxOutline(box[0].X(), box[1].X(),
01993                      box[0].Y(), box[2].Y(),
01994                      fAxis->GetBinLowEdge(low) * fCoord->GetZScale(),
01995                      fAxis->GetBinUpEdge(up - 1) * fCoord->GetZScale());
01996       break;
01997    }
01998 }
01999 
02000 namespace Rgl {
02001 
02002 //______________________________________________________________________________
02003 PlotTranslation::PlotTranslation(const TGLPlotPainter *painter)
02004                    : fPainter(painter)
02005 {
02006    const TGLVertex3 *box = fPainter->fBackBox.Get3DBox();
02007    const Double_t center[] = {(box[0].X() + box[1].X()) / 2,
02008                               (box[0].Y() + box[2].Y()) / 2,
02009                               (box[0].Z() + box[4].Z()) / 2};
02010 
02011    fPainter->SaveModelviewMatrix();
02012    glTranslated(-center[0], -center[1], -center[2]);
02013 }
02014 
02015 //______________________________________________________________________________
02016 PlotTranslation::~PlotTranslation()
02017 {
02018    fPainter->RestoreModelviewMatrix();
02019 }
02020 
02021 namespace
02022 {
02023 
02024 const Double_t lr = 0.85;
02025 const Double_t rr = 0.9;
02026 
02027 }
02028 
02029 //______________________________________________________________________________
02030 void DrawPalette(const TGLPlotCamera * camera, const TGLLevelPalette & palette)
02031 {
02032    //Draw. Palette.
02033    const TGLDisableGuard light(GL_LIGHTING);
02034    const TGLDisableGuard depth(GL_DEPTH_TEST);
02035    const TGLEnableGuard blend(GL_BLEND);
02036 
02037    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
02038 
02039    glMatrixMode(GL_PROJECTION);
02040    glLoadIdentity();
02041    glOrtho(0, camera->GetWidth(), 0, camera->GetHeight(), -1., 1.);
02042 
02043    glMatrixMode(GL_MODELVIEW);
02044    glLoadIdentity();
02045 
02046    const Double_t leftX = camera->GetWidth() * lr;
02047    const Double_t rightX = camera->GetWidth() * rr;
02048    const Double_t margin = 0.1 * camera->GetHeight();
02049    const Double_t h = (camera->GetHeight() * 0.8) / palette.GetPaletteSize();
02050 
02051    for (Int_t i = 0, e = palette.GetPaletteSize(); i < e; ++i) {
02052       glBegin(GL_POLYGON);
02053       const UChar_t * color = palette.GetColour(i);
02054       glColor4ub(color[0], color[1], color[2], 150);
02055       glVertex2d(leftX, margin + i * h);
02056       glVertex2d(rightX, margin + i * h);
02057       glVertex2d(rightX, margin + (i + 1) * h);
02058       glVertex2d(leftX, margin + (i + 1) * h);
02059       glEnd();
02060    }
02061 
02062    const TGLEnableGuard  smoothGuard(GL_LINE_SMOOTH);
02063    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
02064    glColor4d(0., 0., 0., 0.5);
02065 
02066    for (Int_t i = 0, e = palette.GetPaletteSize(); i < e; ++i) {
02067       glBegin(GL_LINE_LOOP);
02068       glVertex2d(leftX, margin + i * h);
02069       glVertex2d(rightX, margin + i * h);
02070       glVertex2d(rightX, margin + (i + 1) * h);
02071       glVertex2d(leftX, margin + (i + 1) * h);
02072       glEnd();
02073    }
02074 
02075 }
02076 
02077 //______________________________________________________________________________
02078 void DrawPaletteAxis(const TGLPlotCamera * camera, const Range_t & minMax, Bool_t logZ)
02079 {
02080    const Double_t x = gPad->AbsPixeltoX(Int_t(gPad->GetXlowNDC() * gPad->GetWw() + rr * camera->GetWidth()));
02081    const Double_t yMin = gPad->AbsPixeltoY(Int_t(camera->GetHeight() - camera->GetHeight() * 0.1
02082                                            + (1 - gPad->GetHNDC() - gPad->GetYlowNDC())
02083                                            * gPad->GetWh() + camera->GetY()));
02084    const Double_t yMax = gPad->AbsPixeltoY(Int_t(camera->GetHeight() - camera->GetHeight() * 0.9
02085                                            + (1 - gPad->GetHNDC() - gPad->GetYlowNDC())
02086                                            * gPad->GetWh() + camera->GetY()));
02087    Double_t zMin = minMax.first;
02088    Double_t zMax = minMax.second;
02089 
02090    if (logZ) {
02091       zMin = TMath::Power(10, zMin);
02092       zMax = TMath::Power(10, zMax);
02093    }
02094 
02095    //Now, some stupid magic, to force ROOT's painting machine work as I want, not as it wants.
02096    const Bool_t logX = gPad->GetLogx();
02097    gPad->SetLogx(kFALSE);
02098    const Bool_t logY = gPad->GetLogy();
02099    gPad->SetLogy(kFALSE);
02100 
02101    TGaxis axisPainter(x, yMin, x, yMax, zMin, zMax, 510, logZ ? "G" : "");
02102    axisPainter.Paint();
02103 
02104    gPad->SetLogx(logX);
02105    gPad->SetLogy(logY);
02106 }
02107 
02108 //Constant for TGLH2PolyPainter.
02109 const Double_t gH2PolyScaleXY = 1.2;
02110 
02111 }
02112 

Generated on Tue Jul 5 14:18:08 2011 for ROOT_528-00b_version by  doxygen 1.5.1