TGLHistPainter.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id$
00002 // Author:  Timur Pocheptsov  17/11/2005
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2005, 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 
00012 #include <stdexcept>
00013 #include <cstring>
00014 
00015 #include "TVirtualGL.h"
00016 #include "KeySymbols.h"
00017 #include "Buttons.h"
00018 #include "TH2Poly.h"
00019 #include "TClass.h"
00020 #include "TROOT.h"
00021 #include "TGL5D.h"
00022 #include "TMath.h"
00023 #include "TPad.h"
00024 #include "TH3.h"
00025 #include "TF3.h"
00026 
00027 #include "TGLSurfacePainter.h"
00028 #include "TGLTH3Composition.h"
00029 #include "TGLH2PolyPainter.h"
00030 #include "TGLHistPainter.h"
00031 #include "TGLLegoPainter.h"
00032 #include "TGLBoxPainter.h"
00033 #include "TGLTF3Painter.h"
00034 #include "TGLParametric.h"
00035 #include "TGL5DPainter.h"
00036 
00037 ClassImp(TGLHistPainter)
00038 
00039 //______________________________________________________________________________
00040 /* Begin_Html
00041 <center><h2>The histogram painter class using OpenGL</h2></center>
00042 
00043 Histograms are, by default, drawn via the <tt>THistPainter</tt> class.
00044 <tt>TGLHistPainter</tt> allows to paint them using the OpenGL 3D graphics
00045 library. The plotting options provided by <tt>TGLHistPainter</tt> start with
00046 <tt>GL</tt> keyword.
00047 
00048 <h3>General information: plot types and supported options</h3>
00049 
00050 The following types of plots are provided:
00051 <ul>
00052 <p><li><b>Lego - (<tt>TGLLegoPainter</tt>)</b>
00053   <br> The supported options are:
00054   <ul>
00055   <li> <tt>"GLLEGO"  :</tt> Draw a lego plot.
00056   <li> <tt>"GLLEGO2" :</tt> Bins with color levels.
00057   <li> <tt>"GLLEGO3" :</tt> Cylindrical bars.
00058   </ul>
00059   Lego painter in cartesian supports logarithmic scales for X, Y, Z.
00060   In polar only Z axis can be logarithmic, in cylindrical only Y (if you see
00061   what it means).
00062 
00063 
00064 <p><li><b>Surfaces (<tt>TF2</tt> and <tt>TH2</tt> with <tt>"GLSURF"</tt> options) - (<tt>TGLSurfacePainter</tt>)</b>
00065   <br> The supported options are:
00066   <ul>
00067   <li> <tt>"GLSURF"  :</tt> Draw a surface.
00068   <li> <tt>"GLSURF1" :</tt> Surface with color levels
00069   <li> <tt>"GLSURF2" :</tt> The same as <tt>"GLSURF1"</tt> but without polygon outlines.
00070   <li> <tt>"GLSURF3" :</tt> Color level projection on top of plot (works only in cartesian coordinate system).
00071   <li> <tt>"GLSURF4" :</tt> Same as <tt>"GLSURF"</tt> but without polygon outlines.
00072   </ul>
00073 
00074   The surface painting in cartesian coordinates supports logarithmic scales along X, Y, Z axis.
00075   In polar coordinates only the Z axis can be logarithmic, in cylindrical coordinates only the Y axis.
00076 
00077 <p><li><b>Additional options to <tt>SURF</tt> and <tt>LEGO</tt> - Coordinate systems:</b>
00078   <br> The supported options are:
00079   <ul>
00080   <li> <tt>" "   :</tt> Default, cartesian coordinates system.
00081   <li> <tt>"POL" :</tt> Polar coordinates system.
00082   <li> <tt>"CYL" :</tt> Cylindrical coordinates system.
00083   <li> <tt>"SPH" :</tt> Spherical coordinates system.
00084   </ul>
00085 
00086 <p><li><b><tt>TH3</tt> as boxes (spheres) - (<tt>TGLBoxPainter</tt>)</b>
00087   <br> The supported options are:
00088   <ul>
00089   <li> <tt>"GLBOX" :</tt> TH3 as a set of boxes, size of box is proportional to bin content.
00090   <li> <tt>"GLBOX1":</tt> the same as "glbox", but spheres are drawn instead of boxes.
00091   </ul>
00092 
00093 <p><li><b><tt>TH3</tt> as iso-surface(s) - (<tt>TGLIsoPainter</tt>)</b>
00094   <br> The supported option is:
00095   <ul>
00096   <li> <tt>"GLISO" :</tt> TH3 is drawn using iso-surfaces.
00097   </ul>
00098 
00099 
00100 <p><li><b><tt>TF3</tt> (implicit function) - (<tt>TGLTF3Painter</tt>)</b>
00101   <br> The supported option is:
00102   <ul>
00103   <li> <tt>"GLTF3" :</tt> Draw a <tt>TF3</tt>.
00104   </ul>
00105 
00106 <p><li><b>Parametric surfaces - (<tt>TGLParametricPlot</tt>)</b>
00107   <br><tt>$ROOTSYS/tutorials/gl/glparametric.C</tt> shows how to create parametric equations and
00108   visualize the surface.
00109 </ul>
00110 
00111 <h3>Interaction with the plots</h3>
00112 
00113 <ul>
00114 <p><li><b>General information.</b>
00115   <br>
00116   All the interactions are implemented via standard methods <tt>DistancetoPrimitive</tt> and
00117   <tt>ExecuteEvent</tt>. That's why all the interactions with the OpenGL plots are possible i
00118   only when the mouse cursor is in the plot's area (the plot's area is the part of a the pad
00119   occupied by gl-produced picture). If the mouse cursor is not above gl-picture,
00120   the standard pad interaction is performed.
00121 
00122 <p><li><b>Selectable parts.</b>
00123   <br>
00124   Different parts of the plot can be selected:
00125   <ul>
00126   <li> <em>xoz, yoz, xoy back planes</em>:
00127      <br>When such a plane selected, it's highlighted in green if the dynamic slicing
00128      by this plane is supported, and it's highlighted in red, if the dynamic slicing
00129      is not supported.
00130   <li><em>The plot itself</em>:
00131      <br>On surfaces, the selected surface is outlined in red. (TF3 and ISO are not
00132      outlined). On lego plots, the selected bin is highlihted. The bin number and content are displayed in pad's status
00133      bar. In box plots, the box or sphere is highlighted and the bin info is displayed in pad's status bar.
00134   </ul>
00135 
00136 <p><li><b>Rotation and zooming.</b>
00137   <br>
00138   <ul>
00139   <li> <em>Rotation</em>:
00140   <br>
00141   When the plot is selected, it can be rotated by pressing and holding the left mouse button and move the cursor.
00142   <li> <em>Zoom/Unzoom</em>:
00143   <br>
00144   Mouse wheel or <tt>'j'</tt>, <tt>'J'</tt>, <tt>'k'</tt>, <tt>'K'</tt> keys.
00145   </ul>
00146 
00147 <p><li><b>Panning.</b>
00148  <br>
00149   The selected plot can be moved in a pad's area by
00150   pressing and holding the left mouse button and the shift key.
00151 </ul>
00152 
00153 <h3>Box cut</h3>
00154   Surface, iso, box, TF3 and parametric painters support box cut by pressing the <tt>'c'</tt> or
00155   <tt>'C'</tt> key when the mouse cursor is in a plot's area. That will display a transparent box,
00156   cutting away part of the surface (or boxes) in order to show internal part of plot.
00157   This box can be moved inside the plot's area (the full size of the box is equal to the plot's
00158   surrounding box) by selecting one of the box cut axes and pressing the left mouse button to move it.
00159 
00160 <h3>Plot specific interactions (dynamic slicing etc.)</h3>
00161   Currently, all gl-plots support some form of slicing.
00162   When back plane is selected (and if it's highlighted in green)
00163   you can press and hold left mouse button and shift key
00164   and move this back plane inside plot's area, creating the slice.
00165   During this "slicing" plot becomes semi-transparent. To remove all slices (and projected curves for surfaces)
00166   - double click with left mouse button in a plot's area.
00167   <ul>
00168   <p><li><b>Surface with option <tt>"GLSURF"</tt></b>
00169   <br>
00170   The surface profile is displayed on the slicing plane.
00171   The profile projection is drawn on the back plane
00172   by pressing <tt>'p'</tt> or <tt>'P'</tt> key.
00173 
00174   <p><li><b>TF3</b>
00175   <br>
00176   The contour plot is drawn on the slicing plane.
00177   For <tt>TF3</tt> the color scheme can be changed by pressing <tt>'s'</tt> or <tt>'S'</tt>.
00178 
00179   <p><li><b>Box</b>
00180   <br>
00181   The contour plot corresponding to slice plane position is drawn in real time.
00182 
00183   <p><li><b>Iso</b>
00184   <br>
00185   Slicing is similar to <tt>"GLBOX"</tt> option.
00186 
00187   <p><li><b>Parametric plot</b>
00188   <br>
00189   No slicing. Additional keys: <tt>'s'</tt> or <tt>'S'</tt> to change color scheme - about 20 color schemes supported
00190   (<tt>'s'</tt> for "scheme"); <tt>'l'</tt> or <tt>'L'</tt> to increase number of polygons (<tt>'l'</tt> for "level" of details),
00191   <tt>'w'</tt> or <tt>'W'</tt> to show outlines (<tt>'w'</tt> for "wireframe").
00192   </ul>
00193 End_Html */
00194 
00195 //______________________________________________________________________________
00196 TGLHistPainter::TGLHistPainter(TH1 *hist)
00197                    : fDefaultPainter(TVirtualHistPainter::HistPainter(hist)),
00198                      fEq(0),
00199                      fHist(hist),
00200                      fF3(0),
00201                      fStack(0),
00202                      fPlotType(kGLDefaultPlot)//THistPainter
00203 {
00204    //ROOT does not use exceptions, so, if default painter's creation failed,
00205    //fDefaultPainter is 0. In each function, which use it, I have to check the pointer first.
00206 }
00207 
00208 //______________________________________________________________________________
00209 TGLHistPainter::TGLHistPainter(TGLParametricEquation *equation)
00210                    : fEq(equation),
00211                      fHist(0),
00212                      fF3(0),
00213                      fStack(0),
00214                      fPlotType(kGLParametricPlot)//THistPainter
00215 {
00216    //This ctor creates gl-parametric plot's painter.
00217    fGLPainter.reset(new TGLParametricPlot(equation, &fCamera));
00218 }
00219 
00220 //______________________________________________________________________________
00221 TGLHistPainter::TGLHistPainter(TGL5DDataSet *data)
00222                    : fEq(0),
00223                      fHist(0),
00224                      fF3(0),
00225                      fStack(0),
00226                      fPlotType(kGL5D)//THistPainter
00227 {
00228    //This ctor creates plot painter for TGL5DDataSet.
00229    fGLPainter.reset(new TGL5DPainter(data, &fCamera, &fCoord));
00230 }
00231 
00232 //______________________________________________________________________________
00233 TGLHistPainter::TGLHistPainter(TGLTH3Composition *data)
00234                    : fEq(0),
00235                      fHist(data),
00236                      fF3(0),
00237                      fStack(0),
00238                      fPlotType(kGLTH3Composition)
00239 {
00240    //This ctor creates plot painter for TGL5DDataSet.
00241    fGLPainter.reset(new TGLTH3CompositionPainter(data, &fCamera, &fCoord));
00242 }
00243 
00244 //______________________________________________________________________________
00245 Int_t TGLHistPainter::DistancetoPrimitive(Int_t px, Int_t py)
00246 {
00247    //Selects plot or axis.
00248    //9999 is the magic number, ROOT's classes use in DistancetoPrimitive.
00249    
00250    //[tp: return statement added.
00251    //tp]
00252    
00253    if (fPlotType == kGLDefaultPlot)
00254       return fDefaultPainter.get() ? fDefaultPainter->DistancetoPrimitive(px, py) : 9999;
00255    else {
00256       //Adjust px and py - canvas can have several pads inside, so we need to convert
00257       //the from canvas' system into pad's.
00258       
00259       /*py -= Int_t((1 - gPad->GetHNDC() - gPad->GetYlowNDC()) * gPad->GetWh());
00260       px -= Int_t(gPad->GetXlowNDC() * gPad->GetWw());*/
00261       
00262       py = gPad->GetWh() - py;//-= Int_t((1 - gPad->GetHNDC() - gPad->GetYlowNDC()) * gPad->GetWh());
00263 
00264       //One hist can be appended to several pads,
00265       //the current pad should have valid OpenGL context.
00266       const Int_t glContext = gPad->GetGLDevice();
00267 
00268       if (glContext != -1) {
00269          //Add "viewport" extraction here.
00270          PadToViewport(kTRUE);
00271 
00272          if (!gGLManager->PlotSelected(fGLPainter.get(), px, py))
00273             gPad->SetSelected(gPad);
00274       } else {
00275          Error("DistancetoPrimitive",
00276                "Attempt to use TGLHistPainter, while the current pad (gPad) does not support gl");
00277          gPad->SetSelected(gPad);
00278       }
00279 
00280       return 0;
00281    }
00282 }
00283 
00284 //______________________________________________________________________________
00285 void TGLHistPainter::DrawPanel()
00286 {
00287    //Default implementation is OK
00288    //This function is called from a context menu
00289    //after right click on a plot's area. Opens window
00290    //("panel") with several controls.
00291    if (fDefaultPainter.get())
00292       fDefaultPainter->DrawPanel();
00293 }
00294 
00295 //______________________________________________________________________________
00296 void TGLHistPainter::ExecuteEvent(Int_t event, Int_t px, Int_t py)
00297 {
00298    //Execute event.
00299    //Events are: mouse events in a plot's area,
00300    //key presses (while mouse cursor is in plot's area).
00301    //"Event execution" means one of the following actions:
00302    //1. Rotation.
00303    //2. Panning.
00304    //3. Zoom changing.
00305    //4. Moving dynamic profile.
00306    //5. Plot specific events - for example, 's' or 'S' key press for TF3.
00307    if (fPlotType == kGLDefaultPlot) {
00308       if(fDefaultPainter.get()) {
00309          fDefaultPainter->ExecuteEvent(event, px, py);
00310       }
00311    } else {
00312       //One hist can be appended to several pads,
00313       //the current pad should have valid OpenGL context.
00314       const Int_t glContext = gPad->GetGLDevice();
00315 
00316       if (glContext == -1) {
00317          Error("ExecuteEvent",
00318                "Attempt to use TGLHistPainter, while the current pad (gPad) does not support gl");
00319          return;
00320       } else {
00321          //Add viewport extraction here.
00322          /*fGLDevice.SetGLDevice(glContext);
00323          fGLPainter->SetGLDevice(&fGLDevice);*/
00324          PadToViewport();
00325       }
00326 
00327       if (event != kKeyPress) {
00328          //Adjust px and py - canvas can have several pads inside, so we need to convert
00329          //the from canvas' system into pad's. If it was a key press event,
00330          //px and py ARE NOT coordinates.
00331          py -= Int_t((1 - gPad->GetHNDC() - gPad->GetYlowNDC()) * gPad->GetWh());
00332          px -= Int_t(gPad->GetXlowNDC() * gPad->GetWw());
00333       }
00334 
00335       switch (event) {
00336       case kButton1Double:
00337          //Left double click removes dynamic sections, user created (if plot type supports sections).
00338          fGLPainter->ProcessEvent(event, px, py);
00339          break;
00340       case kButton1Down:
00341          //Left mouse down in a plot area starts rotation.
00342          if (!fGLPainter->CutAxisSelected())
00343             fCamera.StartRotation(px, py);
00344          else
00345             fGLPainter->StartPan(px, py);
00346          //During rotation, usual TCanvas/TPad machinery (CopyPixmap/Flush/UpdateWindow/etc.)
00347          //is skipped - I use "bit blasting" functions to copy picture directly onto window.
00348          //gGLManager->MarkForDirectCopy(glContext, kTRUE);
00349          break;
00350       case kButton1Motion:
00351          //Rotation invalidates "selection buffer"
00352          // - (color-to-object map, previously read from gl-buffer).
00353          fGLPainter->InvalidateSelection();
00354          if (fGLPainter->CutAxisSelected())
00355             gGLManager->PanObject(fGLPainter.get(), px, py);
00356          else
00357             fCamera.RotateCamera(px, py);
00358          //Draw modified scene onto canvas' window.
00359          //gGLManager->PaintSingleObject(fGLPainter.get());
00360          gPad->Update();
00361          break;
00362       case kButton1Up:
00363       case kButton2Up:
00364          gGLManager->MarkForDirectCopy(glContext, kFALSE);
00365          break;
00366       case kMouseMotion:
00367          gPad->SetCursor(kRotate);
00368          break;
00369       case 7://kButton1Down + shift modifier
00370          //The current version of ROOT does not
00371          //have enumerators for button events + key modifiers,
00372          //so I use hardcoded literals. :(
00373          //With left mouse button down and shift pressed
00374          //we can move plot as the whole or move
00375          //plot's parts - dynamic sections.
00376          fGLPainter->StartPan(px, py);
00377          gGLManager->MarkForDirectCopy(glContext, kTRUE);
00378          break;
00379       case 8://kButton1Motion + shift modifier
00380          gGLManager->PanObject(fGLPainter.get(), px, py);
00381          //gGLManager->PaintSingleObject(fGLPainter.get());
00382          gPad->Update();
00383          break;
00384       case kKeyPress:
00385       case 5:
00386       case 6:
00387          //5, 6 are mouse wheel events (see comment about literals above).
00388          //'p'/'P' - specific events processed by TGLSurfacePainter,
00389          //'s'/'S' - specific events processed by TGLTF3Painter,
00390          //'c'/'C' - turn on/off box cut.
00391          gGLManager->MarkForDirectCopy(glContext, kTRUE);
00392          if (event == 6 || py == kKey_J || py == kKey_j) {
00393             fCamera.ZoomIn();
00394             fGLPainter->InvalidateSelection();
00395             //gGLManager->PaintSingleObject(fGLPainter.get());
00396             gPad->Update();
00397          } else if (event == 5 || py == kKey_K || py == kKey_k) {
00398             fCamera.ZoomOut();
00399             fGLPainter->InvalidateSelection();
00400             //gGLManager->PaintSingleObject(fGLPainter.get());
00401             gPad->Update();
00402          } else if (py == kKey_p || py == kKey_P || py == kKey_S || py == kKey_s
00403                     || py == kKey_c || py == kKey_C || py == kKey_x || py == kKey_X
00404                     || py == kKey_y || py == kKey_Y || py == kKey_z || py == kKey_Z
00405                     || py == kKey_w || py == kKey_W || py == kKey_l || py == kKey_L
00406                     /*|| py == kKey_r || py == kKey_R*/)
00407          {
00408             fGLPainter->ProcessEvent(event, px, py);
00409             //gGLManager->PaintSingleObject(fGLPainter.get());
00410             gPad->Update();
00411          }
00412          gGLManager->MarkForDirectCopy(glContext, kFALSE);
00413          break;
00414       }
00415    }
00416 }
00417 
00418 //______________________________________________________________________________
00419 TList *TGLHistPainter::GetContourList(Double_t contour)const
00420 {
00421    //Get contour list.
00422    //I do not use this function. Contours are implemented in
00423    //a completely different way by gl-painters.
00424    return fDefaultPainter.get() ? fDefaultPainter->GetContourList(contour) : 0;
00425 }
00426 
00427 //______________________________________________________________________________
00428 char *TGLHistPainter::GetObjectInfo(Int_t px, Int_t py)const
00429 {
00430    //Overrides TObject::GetObjectInfo.
00431    //For lego info is: bin numbers (i, j), bin content.
00432    //For TF2 info is: x,y,z 3d surface-point for 2d screen-point under cursor
00433    //(this can work incorrectly now, because of wrong code in TF2).
00434    //For TF3 no info now.
00435    //For box info is: bin numbers (i, j, k), bin content.
00436    static char errMsg[] = { "TGLHistPainter::GetObjectInfo: Error in a hist painter\n" };
00437    if (fPlotType == kGLDefaultPlot)
00438       return fDefaultPainter.get() ? fDefaultPainter->GetObjectInfo(px, py)
00439                                    : errMsg;
00440    else
00441       return gGLManager->GetPlotInfo(fGLPainter.get(), px, py);
00442 }
00443 
00444 //______________________________________________________________________________
00445 TList *TGLHistPainter::GetStack()const
00446 {
00447    // Get stack.
00448    return fStack;
00449 }
00450 
00451 //______________________________________________________________________________
00452 Bool_t TGLHistPainter::IsInside(Int_t x, Int_t y)
00453 {
00454    //Returns kTRUE if the cell ix, iy is inside one of the graphical cuts.
00455    //I do not use this function anywhere, this is a "default implementation".
00456    if (fPlotType == kGLDefaultPlot)
00457       return fDefaultPainter.get() ? fDefaultPainter->IsInside(x, y) : kFALSE;
00458 
00459    return kFALSE;
00460 }
00461 
00462 //______________________________________________________________________________
00463 Bool_t TGLHistPainter::IsInside(Double_t x, Double_t y)
00464 {
00465    //Returns kTRUE if the cell x, y is inside one of the graphical cuts.
00466    //I do not use this function anywhere, this is a "default implementation".
00467    if (fPlotType == kGLDefaultPlot)
00468       return fDefaultPainter.get() ? fDefaultPainter->IsInside(x, y) : kFALSE;
00469 
00470    return kFALSE;
00471 }
00472 
00473 //______________________________________________________________________________
00474 void TGLHistPainter::PaintStat(Int_t dostat, TF1 *fit)
00475 {
00476    //Paint statistics.
00477    //This does not work on windows.
00478    if (fDefaultPainter.get())
00479       fDefaultPainter->PaintStat(dostat, fit);
00480 }
00481 
00482 //______________________________________________________________________________
00483 void TGLHistPainter::ProcessMessage(const char *m, const TObject *o)
00484 {
00485    // Process message.
00486    if (!std::strcmp(m, "SetF3"))
00487       fF3 = (TF3 *)o;
00488 
00489    if (fDefaultPainter.get())
00490       fDefaultPainter->ProcessMessage(m, o);
00491 }
00492 
00493 //______________________________________________________________________________
00494 void TGLHistPainter::SetHistogram(TH1 *h)
00495 {
00496    // Set histogram.
00497    fHist = h;
00498 
00499    if (fDefaultPainter.get())
00500       fDefaultPainter->SetHistogram(h);
00501 }
00502 
00503 //______________________________________________________________________________
00504 void TGLHistPainter::SetStack(TList *s)
00505 {
00506    // Set stack.
00507    fStack = s;
00508 
00509    if (fDefaultPainter.get())
00510       fDefaultPainter->SetStack(s);
00511 }
00512 
00513 //______________________________________________________________________________
00514 Int_t TGLHistPainter::MakeCuts(char *o)
00515 {
00516    // Make cuts.
00517    if (fPlotType == kGLDefaultPlot && fDefaultPainter.get())
00518       return fDefaultPainter->MakeCuts(o);
00519 
00520    return 0;
00521 }
00522 
00523 struct TGLHistPainter::PlotOption_t {
00524    EGLPlotType  fPlotType;
00525    EGLCoordType fCoordType;
00526    Bool_t       fBackBox;
00527    Bool_t       fFrontBox;
00528    Bool_t       fLogX;
00529    Bool_t       fLogY;
00530    Bool_t       fLogZ;
00531 };
00532 
00533 //______________________________________________________________________________
00534 void TGLHistPainter::Paint(Option_t *o)
00535 {
00536    //Final-overrider for TObject::Paint.
00537    TString option(o);
00538    option.ToLower();
00539 
00540    const Ssiz_t glPos = option.Index("gl");
00541    if (glPos != kNPOS)
00542       option.Remove(glPos, 2);
00543    else if (fPlotType != kGLParametricPlot && fPlotType != kGL5D && fPlotType != kGLTH3Composition) {
00544       gPad->SetCopyGLDevice(kFALSE);
00545       if (fDefaultPainter.get())
00546          fDefaultPainter->Paint(o);//option.Data());
00547       return;
00548    }
00549 
00550    if (fPlotType != kGLParametricPlot && fPlotType != kGL5D && fPlotType != kGLTH3Composition)
00551       CreatePainter(ParsePaintOption(option), option);
00552 
00553    if (fPlotType == kGLDefaultPlot) {
00554       //In case of default plot pad
00555       //should not copy gl-buffer (it will be simply black)
00556       
00557       //[tp: code was commented.
00558       //gPad->SetCopyGLDevice(kFALSE);
00559       //tp]
00560 
00561       if (fDefaultPainter.get())
00562          fDefaultPainter->Paint(option.Data());
00563    } else {
00564       Int_t glContext = gPad->GetGLDevice();
00565 
00566       if (glContext != -1) {
00567          //With gl-plot, pad should copy
00568          //gl-buffer into the final pad/canvas pixmap/DIB.
00569          //fGLDevice.SetGLDevice(glContext);
00570          
00571          //[tp: code commented.
00572          //gPad->SetCopyGLDevice(kTRUE);
00573          //tp]
00574          //fGLPainter->SetGLDevice(&fGLDevice);
00575          //Add viewport extraction here.
00576          PadToViewport();
00577          if (gPad->GetFrameFillColor() != kWhite)
00578             fGLPainter->SetFrameColor(gROOT->GetColor(gPad->GetFrameFillColor()));
00579          fGLPainter->SetPadColor(gROOT->GetColor(gPad->GetFillColor()));
00580          if (fGLPainter->InitGeometry())
00581             gGLManager->PaintSingleObject(fGLPainter.get());
00582       }
00583    }
00584 }
00585 
00586 //______________________________________________________________________________
00587 TGLHistPainter::PlotOption_t
00588 TGLHistPainter::ParsePaintOption(const TString &option)const
00589 {
00590    //In principle, we can have several conflicting options: "lego surf pol sph",
00591    //but only one will be selected, which one - depends on parsing order in this function.
00592    PlotOption_t parsedOption = {kGLDefaultPlot, kGLCartesian, kFALSE, kFALSE, gPad->GetLogx(),
00593                                 gPad->GetLogy(), gPad->GetLogz()};
00594    //Check coordinate system type.
00595    if (option.Index("pol") != kNPOS)
00596       parsedOption.fCoordType = kGLPolar;
00597    if (option.Index("cyl") != kNPOS)
00598       parsedOption.fCoordType = kGLCylindrical;
00599    if (option.Index("sph") != kNPOS)
00600       parsedOption.fCoordType = kGLSpherical;
00601    //Define plot type
00602    if (option.Index("lego") != kNPOS)
00603       fStack ? parsedOption.fPlotType = kGLStackPlot : parsedOption.fPlotType = kGLLegoPlot;
00604    if (option.Index("surf") != kNPOS)
00605       parsedOption.fPlotType = kGLSurfacePlot;
00606    if (option.Index("tf3") != kNPOS)
00607       parsedOption.fPlotType = kGLTF3Plot;
00608    if (option.Index("box") != kNPOS)
00609       parsedOption.fPlotType = kGLBoxPlot;
00610    if (option.Index("iso") != kNPOS)
00611       parsedOption.fPlotType = kGLIsoPlot;
00612 
00613    return parsedOption;
00614 }
00615 
00616 //______________________________________________________________________________
00617 void TGLHistPainter::CreatePainter(const PlotOption_t &option, const TString &addOption)
00618 {
00619    // Create painter.
00620    if (option.fPlotType != fPlotType) {
00621       fCoord.ResetModified();
00622       fGLPainter.reset(0);
00623    }
00624 
00625    if (option.fPlotType == kGLLegoPlot) {
00626       if (!fGLPainter.get()) {
00627          if (dynamic_cast<TH2Poly*>(fHist))
00628             fGLPainter.reset(new TGLH2PolyPainter(fHist, &fCamera, &fCoord));
00629          else
00630             fGLPainter.reset(new TGLLegoPainter(fHist, &fCamera, &fCoord));
00631       }
00632    } else if (option.fPlotType == kGLSurfacePlot) {
00633       if (!fGLPainter.get())
00634          fGLPainter.reset(new TGLSurfacePainter(fHist, &fCamera, &fCoord));
00635    } else if (option.fPlotType == kGLBoxPlot) {
00636       if (!fGLPainter.get())
00637          fGLPainter.reset(new TGLBoxPainter(fHist, &fCamera, &fCoord));
00638    } else if (option.fPlotType == kGLTF3Plot) {
00639       if (!fGLPainter.get())
00640          fGLPainter.reset(new TGLTF3Painter(fF3, fHist, &fCamera, &fCoord));
00641    } else if (option.fPlotType == kGLIsoPlot) {
00642       if (!fGLPainter.get())
00643          fGLPainter.reset(new TGLIsoPainter(fHist, &fCamera, &fCoord));
00644    }
00645 
00646    if (fGLPainter.get()) {
00647       fPlotType = option.fPlotType;
00648       fCoord.SetXLog(gPad->GetLogx());
00649       fCoord.SetYLog(gPad->GetLogy());
00650       fCoord.SetZLog(gPad->GetLogz());
00651       fCoord.SetCoordType(option.fCoordType);
00652       fGLPainter->AddOption(addOption);
00653    } else
00654       fPlotType = kGLDefaultPlot;
00655 }
00656 
00657 //______________________________________________________________________________
00658 void TGLHistPainter::SetShowProjection(const char *, Int_t)
00659 {
00660    // Set show projection.
00661 
00662    Warning("SetShowProjection", "Not yet implemented for GL canvases.");
00663 }
00664 
00665 //______________________________________________________________________________
00666 void TGLHistPainter::PadToViewport(Bool_t /*selectionPass*/)
00667 {
00668    if (!fGLPainter.get())
00669       return;
00670 
00671    TGLRect vp;
00672    vp.Width()  = Int_t(gPad->GetAbsWNDC() * gPad->GetWw());
00673    vp.Height() = Int_t(gPad->GetAbsHNDC() * gPad->GetWh());
00674    
00675    vp.X() = Int_t(gPad->XtoAbsPixel(gPad->GetX1()));
00676    vp.Y() = gPad->GetWh() - gPad->YtoAbsPixel(gPad->GetY1());
00677    
00678    fCamera.SetViewport(vp);
00679    if (fCamera.ViewportChanged() && fGLPainter.get())
00680       fGLPainter->InvalidateSelection();
00681 }

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