ROOT logo
#include <ctype.h>

#include "KeySymbols.h"
#include "TVirtualX.h"
#include "Buttons.h"
#include "TString.h"
#include "TROOT.h"
#include "TClass.h"
#include "TColor.h"
#include "TStyle.h"
#include "TH3.h"

#include "TGLPlotCamera.h"
#include "TGLBoxPainter.h"
#include "TGLIncludes.h"

//______________________________________________________________________________
//
// Paints TH3 histograms by rendering variable-sized bozes matching the
// bin contents.

ClassImp(TGLBoxPainter)

//______________________________________________________________________________
TGLBoxPainter::TGLBoxPainter(TH1 *hist, TGLPlotCamera *cam, TGLPlotCoordinates *coord)
                  : TGLPlotPainter(hist, cam, coord, kTRUE, kTRUE, kTRUE),
                    fXOZSlice("XOZ", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kXOZ),
                    fYOZSlice("YOZ", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kYOZ),
                    fXOYSlice("XOY", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kXOY),
                    fType(kBox)
{
   // Normal constructor.
}


//______________________________________________________________________________
char *TGLBoxPainter::GetPlotInfo(Int_t, Int_t)
{
   //Show box info (i, j, k, binContent).

   fPlotInfo = "";

   if (fSelectedPart) {
      if (fSelectedPart < fSelectionBase) {
         if (fHist->Class())
            fPlotInfo += fHist->Class()->GetName();
         fPlotInfo += "::";
         fPlotInfo += fHist->GetName();
      } else if (!fHighColor){
         const Int_t arr2Dsize = fCoord->GetNYBins() * fCoord->GetNZBins();
         const Int_t binI = (fSelectedPart - fSelectionBase) / arr2Dsize + fCoord->GetFirstXBin();
         const Int_t binJ = (fSelectedPart - fSelectionBase) % arr2Dsize / fCoord->GetNZBins() + fCoord->GetFirstYBin();
         const Int_t binK = (fSelectedPart - fSelectionBase) % arr2Dsize % fCoord->GetNZBins() + fCoord->GetFirstZBin();

         fPlotInfo.Form("(binx = %d; biny = %d; binz = %d; binc = %f)", binI, binJ, binK,
                        fHist->GetBinContent(binI, binJ, binK));
      } else
         fPlotInfo = "Switch to true color mode to get correct info";
   }

   return (Char_t *)fPlotInfo.Data();
}


//______________________________________________________________________________
Bool_t TGLBoxPainter::InitGeometry()
{
  //Set ranges, find min and max bin content.

   fCoord->SetZLog(kFALSE);
   fCoord->SetYLog(kFALSE);
   fCoord->SetXLog(kFALSE);

   if (!fCoord->SetRanges(fHist, kFALSE, kTRUE))//kFALSE == drawErrors, kTRUE == zAsBins
      return kFALSE;

   fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
   if(fCamera) fCamera->SetViewVolume(fBackBox.Get3DBox());

   fMinMaxVal.second  = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin(), fCoord->GetFirstZBin());
   fMinMaxVal.first = fMinMaxVal.second;
   //Bad. You can up-date some bin value and get wrong picture.
   for (Int_t ir = fCoord->GetFirstXBin(); ir <= fCoord->GetLastXBin(); ++ir) {
      for (Int_t jr = fCoord->GetFirstYBin(); jr <= fCoord->GetLastYBin(); ++jr) {
         for (Int_t kr = fCoord->GetFirstZBin();  kr <= fCoord->GetLastZBin(); ++kr) {
            fMinMaxVal.second = TMath::Max(fMinMaxVal.second, fHist->GetBinContent(ir, jr, kr));
            fMinMaxVal.first = TMath::Min(fMinMaxVal.first, fHist->GetBinContent(ir, jr, kr));
         }
      }
   }

   fXOYSlice.SetMinMax(fMinMaxVal);
   fXOZSlice.SetMinMax(fMinMaxVal);
   fYOZSlice.SetMinMax(fMinMaxVal);

   if (fCoord->Modified()) {
      fUpdateSelection = kTRUE;
      fXOZSectionPos = fBackBox.Get3DBox()[0].Y();
      fYOZSectionPos = fBackBox.Get3DBox()[0].X();
      fXOYSectionPos = fBackBox.Get3DBox()[0].Z();
      fCoord->ResetModified();
   }

   return kTRUE;
}


//______________________________________________________________________________
void TGLBoxPainter::StartPan(Int_t px, Int_t py)
{
   // User clicks right mouse button (in a pad).

   fMousePosition.fX = px;
   fMousePosition.fY = fCamera->GetHeight() - py;
   fCamera->StartPan(px, py);
   fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
}


//______________________________________________________________________________
void TGLBoxPainter::Pan(Int_t px, Int_t py)
{
   // User's moving mouse cursor, with middle mouse button pressed (for pad).
   // Calculate 3d shift related to 2d mouse movement.
   if (fSelectedPart >= fSelectionBase) {//Pan camera.
      SaveModelviewMatrix();
      SaveProjectionMatrix();
      
      fCamera->SetCamera();
      fCamera->Apply(fPadPhi, fPadTheta);
      fCamera->Pan(px, py);

      RestoreProjectionMatrix();
      RestoreModelviewMatrix();
   } else if (fSelectedPart > 0) {
      //Convert py into bottom-top orientation.
      //Possibly, move box here
      py = fCamera->GetHeight() - py;
      SaveModelviewMatrix();
      SaveProjectionMatrix();
      
      fCamera->SetCamera();
      fCamera->Apply(fPadPhi, fPadTheta);
      
      
      if (!fHighColor) {
         if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis))
            fBoxCut.MoveBox(px, py, fSelectedPart);
         else
            MoveSection(px, py);
      } else {
         MoveSection(px, py);
      }
      
      RestoreProjectionMatrix();
      RestoreModelviewMatrix();
   }

   fMousePosition.fX = px, fMousePosition.fY = py;
   fUpdateSelection = kTRUE;
}


//______________________________________________________________________________
void TGLBoxPainter::AddOption(const TString &option)
{
   // Box1 == spheres.

   const Ssiz_t boxPos = option.Index("box");//"box" _already_ _exists_ in a string.
   if (boxPos + 3 < option.Length() && isdigit(option[boxPos + 3]))
      option[boxPos + 3] - '0' == 1 ? fType = kBox1 : fType = kBox;
   else
      fType = kBox;
   option.Index("z") == kNPOS ? fDrawPalette = kFALSE : fDrawPalette = kTRUE;
}

//______________________________________________________________________________
void TGLBoxPainter::ProcessEvent(Int_t event, Int_t /*px*/, Int_t py)
{
   // Remove sections.

   if (event == kButton1Double && (HasSections() || fBoxCut.IsActive())) {
      fXOZSectionPos = fBackBox.Get3DBox()[0].Y();
      fYOZSectionPos = fBackBox.Get3DBox()[0].X();
      fXOYSectionPos = fBackBox.Get3DBox()[0].Z();
      if (fBoxCut.IsActive())
         fBoxCut.TurnOnOff();
      if (!gVirtualX->IsCmdThread())
         gROOT->ProcessLineFast(Form("((TGLPlotPainter *)0x%lx)->Paint()", this));
      else
         Paint();
   } else if (event == kKeyPress && (py == kKey_c || py == kKey_C)) {
      if (fHighColor)
         Info("ProcessEvent", "Switch to true color mode to use box cut");
      else {
         fBoxCut.TurnOnOff();
         fUpdateSelection = kTRUE;
      }
   }
}

//______________________________________________________________________________
void TGLBoxPainter::InitGL()const
{
   // Initialize some gl state variables.
   glEnable(GL_DEPTH_TEST);
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
   //For box option back polygons are culled (but not for dynamic profiles).
   glEnable(GL_CULL_FACE);
   glCullFace(GL_BACK);

   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
}

//______________________________________________________________________________
void TGLBoxPainter::DeInitGL()const
{
   //Return back some gl state variables.
   glDisable(GL_DEPTH_TEST);
   glDisable(GL_LIGHTING);
   glDisable(GL_LIGHT0);
   glDisable(GL_CULL_FACE);
   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
}

namespace {

   //______________________________________________________________________________
   void DrawMinusSigns(Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax,
                       Double_t zMin, Double_t zMax, Int_t fp, Bool_t onSphere, Bool_t transp)
   {
      //
      const TGLDisableGuard depthTest(GL_DEPTH_TEST);
      const TGLDisableGuard cullFace(GL_CULL_FACE);

      const Double_t ratio  = onSphere ? 0.4 : 0.15;
      const Double_t leftX = xMin + ratio * (xMax - xMin), rightX = xMax - ratio * (xMax - xMin);
      const Double_t leftY = yMin + ratio * (yMax - yMin), rightY = yMax - ratio * (yMax - yMin);
      const Double_t lowZ = zMin / 2. + zMax / 2. - 0.1 * (zMax - zMin);
      const Double_t upZ = zMin / 2. + zMax / 2. + 0.1 * (zMax - zMin);


      const Double_t minusVerts[][3] = {{xMin, leftY, lowZ}, {xMin, leftY, upZ}, {xMin, rightY, upZ}, {xMin, rightY, lowZ},
                                        {leftX, yMin, lowZ}, {rightX, yMin, lowZ}, {rightX, yMin, upZ}, {leftX, yMin, upZ},
                                        {xMax, leftY, lowZ}, {xMax, rightY, lowZ}, {xMax, rightY, upZ}, {xMax, leftY, upZ},
                                        {rightX, yMax, lowZ}, {leftX, yMax, lowZ}, {leftX, yMax, upZ}, {rightX, yMax, upZ}};
      const Int_t minusQuads[][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}, {12, 13, 14, 15}};


      TGLDisableGuard light(GL_LIGHTING);
      glColor3d(1., 0., 0.);

      const Int_t    frontPlanes[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0}};//Code duplication again :(
      const Int_t *verts = minusQuads[frontPlanes[fp][0]];

      glBegin(GL_POLYGON);
      glVertex3dv(minusVerts[verts[0]]);
      glVertex3dv(minusVerts[verts[1]]);
      glVertex3dv(minusVerts[verts[2]]);
      glVertex3dv(minusVerts[verts[3]]);
      glEnd();

      verts = minusQuads[frontPlanes[fp][1]];

      glBegin(GL_POLYGON);
      glVertex3dv(minusVerts[verts[0]]);
      glVertex3dv(minusVerts[verts[1]]);
      glVertex3dv(minusVerts[verts[2]]);
      glVertex3dv(minusVerts[verts[3]]);
      glEnd();

      const Float_t nullEmission[] = {0.f, 0.f, 0.f, 1.f};
      glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, nullEmission);
      glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, nullEmission);

      glColor4d(0., 0., 0., 0.25);
      glPolygonMode(GL_FRONT, GL_LINE);

      if (!transp) {
         glEnable(GL_BLEND);
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      }

      glEnable(GL_LINE_SMOOTH);
      glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

      verts = minusQuads[frontPlanes[fp][0]];

      glBegin(GL_POLYGON);
      glVertex3dv(minusVerts[verts[0]]);
      glVertex3dv(minusVerts[verts[1]]);
      glVertex3dv(minusVerts[verts[2]]);
      glVertex3dv(minusVerts[verts[3]]);
      glEnd();

      verts = minusQuads[frontPlanes[fp][1]];

      glBegin(GL_POLYGON);
      glVertex3dv(minusVerts[verts[0]]);
      glVertex3dv(minusVerts[verts[1]]);
      glVertex3dv(minusVerts[verts[2]]);
      glVertex3dv(minusVerts[verts[3]]);
      glEnd();

      glPolygonMode(GL_FRONT, GL_FILL);

      if (!transp)
         glDisable(GL_BLEND);
   }

}

//______________________________________________________________________________
void TGLBoxPainter::DrawPlot()const
{
   // Draw set of boxes (spheres)

   //Shift plot to point of origin.
   const Rgl::PlotTranslation trGuard(this);

   fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
   glDisable(GL_CULL_FACE);
   DrawSections();
   glEnable(GL_CULL_FACE);

   if (!fSelectionPass) {
      glEnable(GL_POLYGON_OFFSET_FILL);//[0
      glPolygonOffset(1.f, 1.f);
      SetPlotColor();
      if (HasSections()) {
         //Boxes are semi-transparent if we have any sections.
         glEnable(GL_BLEND);//[1
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      }
   }

   //Using front point, find the correct order to draw boxes from
   //back to front/from bottom to top (it's important only for semi-transparent boxes).
   const Int_t frontPoint = fBackBox.GetFrontPoint();
   Int_t irInit = fCoord->GetFirstXBin(), iInit = 0;
   const Int_t nX = fCoord->GetNXBins();
   Int_t jrInit = fCoord->GetFirstYBin(), jInit = 0;
   const Int_t nY = fCoord->GetNYBins();
   Int_t krInit = fCoord->GetFirstZBin(), kInit = 0;
   const Int_t nZ = fCoord->GetNZBins();

   const Int_t addI = frontPoint == 2 || frontPoint == 1 ? 1 : (iInit = nX - 1, irInit = fCoord->GetLastXBin(), -1);
   const Int_t addJ = frontPoint == 2 || frontPoint == 3 ? 1 : (jInit = nY - 1, jrInit = fCoord->GetLastYBin(), -1);
   const Int_t addK = fBackBox.Get2DBox()[frontPoint + 4].Y() < fBackBox.Get2DBox()[frontPoint].Y() ? 1
                     : (kInit = nZ - 1, krInit = fCoord->GetLastZBin(),-1);
   const Double_t xScale = fCoord->GetXScale();
   const Double_t yScale = fCoord->GetYScale();
   const Double_t zScale = fCoord->GetZScale();
   const TAxis   *xA = fXAxis;
   const TAxis   *yA = fYAxis;
   const TAxis   *zA = fZAxis;

   if (fSelectionPass && fHighColor)
      Rgl::ObjectIDToColor(fSelectionBase, fHighColor);//base + 1 == 7

   Double_t maxContent = TMath::Max(TMath::Abs(fMinMaxVal.first), TMath::Abs(fMinMaxVal.second));
   if(!maxContent)//bad, find better way to check zero.
      maxContent = 1.;

   for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
      for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
         for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
            const Double_t binContent = fHist->GetBinContent(ir, jr, kr);
            const Double_t w = TMath::Abs(binContent) / maxContent;
            if (!w)
               continue;

            const Double_t xMin = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 - w * xA->GetBinWidth(ir) / 2);
            const Double_t xMax = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 + w * xA->GetBinWidth(ir) / 2);
            const Double_t yMin = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 - w * yA->GetBinWidth(jr) / 2);
            const Double_t yMax = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 + w * yA->GetBinWidth(jr) / 2);
            const Double_t zMin = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 - w * zA->GetBinWidth(kr) / 2);
            const Double_t zMax = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 + w * zA->GetBinWidth(kr) / 2);

            if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
               continue;

            const Int_t binID = fSelectionBase + i * fCoord->GetNZBins() * fCoord->GetNYBins() + j * fCoord->GetNZBins() + k;

            if (fSelectionPass && !fHighColor)
               Rgl::ObjectIDToColor(binID, fHighColor);
            else if(!fHighColor && fSelectedPart == binID)
               glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gOrangeEmission);

            if (fType == kBox) {
               Rgl::DrawBoxFront(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint);
            } else {
               Rgl::DrawSphere(&fQuadric, xMin, xMax, yMin, yMax, zMin, zMax);
            }

            if (binContent < 0. && !fSelectionPass)
               DrawMinusSigns(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint, fType != kBox, HasSections());

            if (!fSelectionPass && !fHighColor && fSelectedPart == binID)
               glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gNullEmission);
         }
      }
   }

   if (fBoxCut.IsActive())
      fBoxCut.DrawBox(fSelectionPass, fSelectedPart);

   if (!fSelectionPass && fType != kBox1) {
      glDisable(GL_POLYGON_OFFSET_FILL);//0]
      TGLDisableGuard lightGuard(GL_LIGHTING);//[2 - 2]
      glColor4d(0., 0., 0., 0.25);
      glPolygonMode(GL_FRONT, GL_LINE);//[3

      const TGLEnableGuard blendGuard(GL_BLEND);//[4-4] + 1]
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);//[5-5]
      glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

      for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
         for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
            for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
               const Double_t w = TMath::Abs(fHist->GetBinContent(ir, jr, kr)) / maxContent;
               if (!w)
                  continue;

               const Double_t xMin = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 - w * xA->GetBinWidth(ir) / 2);
               const Double_t xMax = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 + w * xA->GetBinWidth(ir) / 2);
               const Double_t yMin = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 - w * yA->GetBinWidth(jr) / 2);
               const Double_t yMax = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 + w * yA->GetBinWidth(jr) / 2);
               const Double_t zMin = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 - w * zA->GetBinWidth(kr) / 2);
               const Double_t zMax = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 + w * zA->GetBinWidth(kr) / 2);

               if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
                  continue;

               Rgl::DrawBoxFront(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint);
            }
         }
      }

      glPolygonMode(GL_FRONT, GL_FILL);//3]
   }

   if (!fSelectionPass && fDrawPalette && HasSections())
      DrawPalette();
}

//______________________________________________________________________________
void TGLBoxPainter::SetPlotColor()const
{
   // Set boxes color.

   Float_t diffColor[] = {0.8f, 0.8f, 0.8f, 0.05f};

   if (fHist->GetFillColor() != kWhite)
      if (const TColor *c = gROOT->GetColor(fHist->GetFillColor()))
         c->GetRGB(diffColor[0], diffColor[1], diffColor[2]);

   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffColor);
   const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
   glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
   glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
}

//______________________________________________________________________________
void TGLBoxPainter::DrawSectionXOZ()const
{
   // Draw XOZ parallel section.

   if (fSelectionPass)
      return;
   fXOZSlice.DrawSlice(fXOZSectionPos / fCoord->GetYScale());
}

//______________________________________________________________________________
void TGLBoxPainter::DrawSectionYOZ()const
{
   // Draw YOZ parallel section.
   if (fSelectionPass)
      return;
   fYOZSlice.DrawSlice(fYOZSectionPos / fCoord->GetXScale());
}


//______________________________________________________________________________
void TGLBoxPainter::DrawSectionXOY()const
{
   // Draw XOY parallel section.
   if (fSelectionPass)
      return;
   fXOYSlice.DrawSlice(fXOYSectionPos / fCoord->GetZScale());
}


//______________________________________________________________________________
Bool_t TGLBoxPainter::HasSections()const
{
   // Check, if any section exists.

   return fXOZSectionPos > fBackBox.Get3DBox()[0].Y() || fYOZSectionPos> fBackBox.Get3DBox()[0].X() ||
          fXOYSectionPos > fBackBox.Get3DBox()[0].Z();
}

//______________________________________________________________________________
void TGLBoxPainter::DrawPalette()const
{
   //Draw. Palette.
   const TGLLevelPalette * palette = 0;
   const TGLVertex3 *frame = fBackBox.Get3DBox();

   if (fXOZSectionPos > frame[0].Y())
      palette = &fXOZSlice.GetPalette();
   else if (fYOZSectionPos > frame[0].X())
      palette = &fYOZSlice.GetPalette();
   else if (fXOYSectionPos > frame[0].Z())
      palette = &fXOYSlice.GetPalette();

   if (!palette || !palette->GetPaletteSize()) {
      return;
   }

   Rgl::DrawPalette(fCamera, *palette);

   glFinish();

   fCamera->SetCamera();
   fCamera->Apply(fPadPhi, fPadTheta);
}

//______________________________________________________________________________
void TGLBoxPainter::DrawPaletteAxis()const
{
   //Draw. Palette. Axis.
   if (HasSections()) {
      gVirtualX->SetDrawMode(TVirtualX::kCopy);//TCanvas by default sets in kInverse
      Rgl::DrawPaletteAxis(fCamera, fMinMaxVal, fCoord->GetCoordType() == kGLCartesian ? fCoord->GetZLog() : kFALSE);
   }
}
 TGLBoxPainter.cxx:1
 TGLBoxPainter.cxx:2
 TGLBoxPainter.cxx:3
 TGLBoxPainter.cxx:4
 TGLBoxPainter.cxx:5
 TGLBoxPainter.cxx:6
 TGLBoxPainter.cxx:7
 TGLBoxPainter.cxx:8
 TGLBoxPainter.cxx:9
 TGLBoxPainter.cxx:10
 TGLBoxPainter.cxx:11
 TGLBoxPainter.cxx:12
 TGLBoxPainter.cxx:13
 TGLBoxPainter.cxx:14
 TGLBoxPainter.cxx:15
 TGLBoxPainter.cxx:16
 TGLBoxPainter.cxx:17
 TGLBoxPainter.cxx:18
 TGLBoxPainter.cxx:19
 TGLBoxPainter.cxx:20
 TGLBoxPainter.cxx:21
 TGLBoxPainter.cxx:22
 TGLBoxPainter.cxx:23
 TGLBoxPainter.cxx:24
 TGLBoxPainter.cxx:25
 TGLBoxPainter.cxx:26
 TGLBoxPainter.cxx:27
 TGLBoxPainter.cxx:28
 TGLBoxPainter.cxx:29
 TGLBoxPainter.cxx:30
 TGLBoxPainter.cxx:31
 TGLBoxPainter.cxx:32
 TGLBoxPainter.cxx:33
 TGLBoxPainter.cxx:34
 TGLBoxPainter.cxx:35
 TGLBoxPainter.cxx:36
 TGLBoxPainter.cxx:37
 TGLBoxPainter.cxx:38
 TGLBoxPainter.cxx:39
 TGLBoxPainter.cxx:40
 TGLBoxPainter.cxx:41
 TGLBoxPainter.cxx:42
 TGLBoxPainter.cxx:43
 TGLBoxPainter.cxx:44
 TGLBoxPainter.cxx:45
 TGLBoxPainter.cxx:46
 TGLBoxPainter.cxx:47
 TGLBoxPainter.cxx:48
 TGLBoxPainter.cxx:49
 TGLBoxPainter.cxx:50
 TGLBoxPainter.cxx:51
 TGLBoxPainter.cxx:52
 TGLBoxPainter.cxx:53
 TGLBoxPainter.cxx:54
 TGLBoxPainter.cxx:55
 TGLBoxPainter.cxx:56
 TGLBoxPainter.cxx:57
 TGLBoxPainter.cxx:58
 TGLBoxPainter.cxx:59
 TGLBoxPainter.cxx:60
 TGLBoxPainter.cxx:61
 TGLBoxPainter.cxx:62
 TGLBoxPainter.cxx:63
 TGLBoxPainter.cxx:64
 TGLBoxPainter.cxx:65
 TGLBoxPainter.cxx:66
 TGLBoxPainter.cxx:67
 TGLBoxPainter.cxx:68
 TGLBoxPainter.cxx:69
 TGLBoxPainter.cxx:70
 TGLBoxPainter.cxx:71
 TGLBoxPainter.cxx:72
 TGLBoxPainter.cxx:73
 TGLBoxPainter.cxx:74
 TGLBoxPainter.cxx:75
 TGLBoxPainter.cxx:76
 TGLBoxPainter.cxx:77
 TGLBoxPainter.cxx:78
 TGLBoxPainter.cxx:79
 TGLBoxPainter.cxx:80
 TGLBoxPainter.cxx:81
 TGLBoxPainter.cxx:82
 TGLBoxPainter.cxx:83
 TGLBoxPainter.cxx:84
 TGLBoxPainter.cxx:85
 TGLBoxPainter.cxx:86
 TGLBoxPainter.cxx:87
 TGLBoxPainter.cxx:88
 TGLBoxPainter.cxx:89
 TGLBoxPainter.cxx:90
 TGLBoxPainter.cxx:91
 TGLBoxPainter.cxx:92
 TGLBoxPainter.cxx:93
 TGLBoxPainter.cxx:94
 TGLBoxPainter.cxx:95
 TGLBoxPainter.cxx:96
 TGLBoxPainter.cxx:97
 TGLBoxPainter.cxx:98
 TGLBoxPainter.cxx:99
 TGLBoxPainter.cxx:100
 TGLBoxPainter.cxx:101
 TGLBoxPainter.cxx:102
 TGLBoxPainter.cxx:103
 TGLBoxPainter.cxx:104
 TGLBoxPainter.cxx:105
 TGLBoxPainter.cxx:106
 TGLBoxPainter.cxx:107
 TGLBoxPainter.cxx:108
 TGLBoxPainter.cxx:109
 TGLBoxPainter.cxx:110
 TGLBoxPainter.cxx:111
 TGLBoxPainter.cxx:112
 TGLBoxPainter.cxx:113
 TGLBoxPainter.cxx:114
 TGLBoxPainter.cxx:115
 TGLBoxPainter.cxx:116
 TGLBoxPainter.cxx:117
 TGLBoxPainter.cxx:118
 TGLBoxPainter.cxx:119
 TGLBoxPainter.cxx:120
 TGLBoxPainter.cxx:121
 TGLBoxPainter.cxx:122
 TGLBoxPainter.cxx:123
 TGLBoxPainter.cxx:124
 TGLBoxPainter.cxx:125
 TGLBoxPainter.cxx:126
 TGLBoxPainter.cxx:127
 TGLBoxPainter.cxx:128
 TGLBoxPainter.cxx:129
 TGLBoxPainter.cxx:130
 TGLBoxPainter.cxx:131
 TGLBoxPainter.cxx:132
 TGLBoxPainter.cxx:133
 TGLBoxPainter.cxx:134
 TGLBoxPainter.cxx:135
 TGLBoxPainter.cxx:136
 TGLBoxPainter.cxx:137
 TGLBoxPainter.cxx:138
 TGLBoxPainter.cxx:139
 TGLBoxPainter.cxx:140
 TGLBoxPainter.cxx:141
 TGLBoxPainter.cxx:142
 TGLBoxPainter.cxx:143
 TGLBoxPainter.cxx:144
 TGLBoxPainter.cxx:145
 TGLBoxPainter.cxx:146
 TGLBoxPainter.cxx:147
 TGLBoxPainter.cxx:148
 TGLBoxPainter.cxx:149
 TGLBoxPainter.cxx:150
 TGLBoxPainter.cxx:151
 TGLBoxPainter.cxx:152
 TGLBoxPainter.cxx:153
 TGLBoxPainter.cxx:154
 TGLBoxPainter.cxx:155
 TGLBoxPainter.cxx:156
 TGLBoxPainter.cxx:157
 TGLBoxPainter.cxx:158
 TGLBoxPainter.cxx:159
 TGLBoxPainter.cxx:160
 TGLBoxPainter.cxx:161
 TGLBoxPainter.cxx:162
 TGLBoxPainter.cxx:163
 TGLBoxPainter.cxx:164
 TGLBoxPainter.cxx:165
 TGLBoxPainter.cxx:166
 TGLBoxPainter.cxx:167
 TGLBoxPainter.cxx:168
 TGLBoxPainter.cxx:169
 TGLBoxPainter.cxx:170
 TGLBoxPainter.cxx:171
 TGLBoxPainter.cxx:172
 TGLBoxPainter.cxx:173
 TGLBoxPainter.cxx:174
 TGLBoxPainter.cxx:175
 TGLBoxPainter.cxx:176
 TGLBoxPainter.cxx:177
 TGLBoxPainter.cxx:178
 TGLBoxPainter.cxx:179
 TGLBoxPainter.cxx:180
 TGLBoxPainter.cxx:181
 TGLBoxPainter.cxx:182
 TGLBoxPainter.cxx:183
 TGLBoxPainter.cxx:184
 TGLBoxPainter.cxx:185
 TGLBoxPainter.cxx:186
 TGLBoxPainter.cxx:187
 TGLBoxPainter.cxx:188
 TGLBoxPainter.cxx:189
 TGLBoxPainter.cxx:190
 TGLBoxPainter.cxx:191
 TGLBoxPainter.cxx:192
 TGLBoxPainter.cxx:193
 TGLBoxPainter.cxx:194
 TGLBoxPainter.cxx:195
 TGLBoxPainter.cxx:196
 TGLBoxPainter.cxx:197
 TGLBoxPainter.cxx:198
 TGLBoxPainter.cxx:199
 TGLBoxPainter.cxx:200
 TGLBoxPainter.cxx:201
 TGLBoxPainter.cxx:202
 TGLBoxPainter.cxx:203
 TGLBoxPainter.cxx:204
 TGLBoxPainter.cxx:205
 TGLBoxPainter.cxx:206
 TGLBoxPainter.cxx:207
 TGLBoxPainter.cxx:208
 TGLBoxPainter.cxx:209
 TGLBoxPainter.cxx:210
 TGLBoxPainter.cxx:211
 TGLBoxPainter.cxx:212
 TGLBoxPainter.cxx:213
 TGLBoxPainter.cxx:214
 TGLBoxPainter.cxx:215
 TGLBoxPainter.cxx:216
 TGLBoxPainter.cxx:217
 TGLBoxPainter.cxx:218
 TGLBoxPainter.cxx:219
 TGLBoxPainter.cxx:220
 TGLBoxPainter.cxx:221
 TGLBoxPainter.cxx:222
 TGLBoxPainter.cxx:223
 TGLBoxPainter.cxx:224
 TGLBoxPainter.cxx:225
 TGLBoxPainter.cxx:226
 TGLBoxPainter.cxx:227
 TGLBoxPainter.cxx:228
 TGLBoxPainter.cxx:229
 TGLBoxPainter.cxx:230
 TGLBoxPainter.cxx:231
 TGLBoxPainter.cxx:232
 TGLBoxPainter.cxx:233
 TGLBoxPainter.cxx:234
 TGLBoxPainter.cxx:235
 TGLBoxPainter.cxx:236
 TGLBoxPainter.cxx:237
 TGLBoxPainter.cxx:238
 TGLBoxPainter.cxx:239
 TGLBoxPainter.cxx:240
 TGLBoxPainter.cxx:241
 TGLBoxPainter.cxx:242
 TGLBoxPainter.cxx:243
 TGLBoxPainter.cxx:244
 TGLBoxPainter.cxx:245
 TGLBoxPainter.cxx:246
 TGLBoxPainter.cxx:247
 TGLBoxPainter.cxx:248
 TGLBoxPainter.cxx:249
 TGLBoxPainter.cxx:250
 TGLBoxPainter.cxx:251
 TGLBoxPainter.cxx:252
 TGLBoxPainter.cxx:253
 TGLBoxPainter.cxx:254
 TGLBoxPainter.cxx:255
 TGLBoxPainter.cxx:256
 TGLBoxPainter.cxx:257
 TGLBoxPainter.cxx:258
 TGLBoxPainter.cxx:259
 TGLBoxPainter.cxx:260
 TGLBoxPainter.cxx:261
 TGLBoxPainter.cxx:262
 TGLBoxPainter.cxx:263
 TGLBoxPainter.cxx:264
 TGLBoxPainter.cxx:265
 TGLBoxPainter.cxx:266
 TGLBoxPainter.cxx:267
 TGLBoxPainter.cxx:268
 TGLBoxPainter.cxx:269
 TGLBoxPainter.cxx:270
 TGLBoxPainter.cxx:271
 TGLBoxPainter.cxx:272
 TGLBoxPainter.cxx:273
 TGLBoxPainter.cxx:274
 TGLBoxPainter.cxx:275
 TGLBoxPainter.cxx:276
 TGLBoxPainter.cxx:277
 TGLBoxPainter.cxx:278
 TGLBoxPainter.cxx:279
 TGLBoxPainter.cxx:280
 TGLBoxPainter.cxx:281
 TGLBoxPainter.cxx:282
 TGLBoxPainter.cxx:283
 TGLBoxPainter.cxx:284
 TGLBoxPainter.cxx:285
 TGLBoxPainter.cxx:286
 TGLBoxPainter.cxx:287
 TGLBoxPainter.cxx:288
 TGLBoxPainter.cxx:289
 TGLBoxPainter.cxx:290
 TGLBoxPainter.cxx:291
 TGLBoxPainter.cxx:292
 TGLBoxPainter.cxx:293
 TGLBoxPainter.cxx:294
 TGLBoxPainter.cxx:295
 TGLBoxPainter.cxx:296
 TGLBoxPainter.cxx:297
 TGLBoxPainter.cxx:298
 TGLBoxPainter.cxx:299
 TGLBoxPainter.cxx:300
 TGLBoxPainter.cxx:301
 TGLBoxPainter.cxx:302
 TGLBoxPainter.cxx:303
 TGLBoxPainter.cxx:304
 TGLBoxPainter.cxx:305
 TGLBoxPainter.cxx:306
 TGLBoxPainter.cxx:307
 TGLBoxPainter.cxx:308
 TGLBoxPainter.cxx:309
 TGLBoxPainter.cxx:310
 TGLBoxPainter.cxx:311
 TGLBoxPainter.cxx:312
 TGLBoxPainter.cxx:313
 TGLBoxPainter.cxx:314
 TGLBoxPainter.cxx:315
 TGLBoxPainter.cxx:316
 TGLBoxPainter.cxx:317
 TGLBoxPainter.cxx:318
 TGLBoxPainter.cxx:319
 TGLBoxPainter.cxx:320
 TGLBoxPainter.cxx:321
 TGLBoxPainter.cxx:322
 TGLBoxPainter.cxx:323
 TGLBoxPainter.cxx:324
 TGLBoxPainter.cxx:325
 TGLBoxPainter.cxx:326
 TGLBoxPainter.cxx:327
 TGLBoxPainter.cxx:328
 TGLBoxPainter.cxx:329
 TGLBoxPainter.cxx:330
 TGLBoxPainter.cxx:331
 TGLBoxPainter.cxx:332
 TGLBoxPainter.cxx:333
 TGLBoxPainter.cxx:334
 TGLBoxPainter.cxx:335
 TGLBoxPainter.cxx:336
 TGLBoxPainter.cxx:337
 TGLBoxPainter.cxx:338
 TGLBoxPainter.cxx:339
 TGLBoxPainter.cxx:340
 TGLBoxPainter.cxx:341
 TGLBoxPainter.cxx:342
 TGLBoxPainter.cxx:343
 TGLBoxPainter.cxx:344
 TGLBoxPainter.cxx:345
 TGLBoxPainter.cxx:346
 TGLBoxPainter.cxx:347
 TGLBoxPainter.cxx:348
 TGLBoxPainter.cxx:349
 TGLBoxPainter.cxx:350
 TGLBoxPainter.cxx:351
 TGLBoxPainter.cxx:352
 TGLBoxPainter.cxx:353
 TGLBoxPainter.cxx:354
 TGLBoxPainter.cxx:355
 TGLBoxPainter.cxx:356
 TGLBoxPainter.cxx:357
 TGLBoxPainter.cxx:358
 TGLBoxPainter.cxx:359
 TGLBoxPainter.cxx:360
 TGLBoxPainter.cxx:361
 TGLBoxPainter.cxx:362
 TGLBoxPainter.cxx:363
 TGLBoxPainter.cxx:364
 TGLBoxPainter.cxx:365
 TGLBoxPainter.cxx:366
 TGLBoxPainter.cxx:367
 TGLBoxPainter.cxx:368
 TGLBoxPainter.cxx:369
 TGLBoxPainter.cxx:370
 TGLBoxPainter.cxx:371
 TGLBoxPainter.cxx:372
 TGLBoxPainter.cxx:373
 TGLBoxPainter.cxx:374
 TGLBoxPainter.cxx:375
 TGLBoxPainter.cxx:376
 TGLBoxPainter.cxx:377
 TGLBoxPainter.cxx:378
 TGLBoxPainter.cxx:379
 TGLBoxPainter.cxx:380
 TGLBoxPainter.cxx:381
 TGLBoxPainter.cxx:382
 TGLBoxPainter.cxx:383
 TGLBoxPainter.cxx:384
 TGLBoxPainter.cxx:385
 TGLBoxPainter.cxx:386
 TGLBoxPainter.cxx:387
 TGLBoxPainter.cxx:388
 TGLBoxPainter.cxx:389
 TGLBoxPainter.cxx:390
 TGLBoxPainter.cxx:391
 TGLBoxPainter.cxx:392
 TGLBoxPainter.cxx:393
 TGLBoxPainter.cxx:394
 TGLBoxPainter.cxx:395
 TGLBoxPainter.cxx:396
 TGLBoxPainter.cxx:397
 TGLBoxPainter.cxx:398
 TGLBoxPainter.cxx:399
 TGLBoxPainter.cxx:400
 TGLBoxPainter.cxx:401
 TGLBoxPainter.cxx:402
 TGLBoxPainter.cxx:403
 TGLBoxPainter.cxx:404
 TGLBoxPainter.cxx:405
 TGLBoxPainter.cxx:406
 TGLBoxPainter.cxx:407
 TGLBoxPainter.cxx:408
 TGLBoxPainter.cxx:409
 TGLBoxPainter.cxx:410
 TGLBoxPainter.cxx:411
 TGLBoxPainter.cxx:412
 TGLBoxPainter.cxx:413
 TGLBoxPainter.cxx:414
 TGLBoxPainter.cxx:415
 TGLBoxPainter.cxx:416
 TGLBoxPainter.cxx:417
 TGLBoxPainter.cxx:418
 TGLBoxPainter.cxx:419
 TGLBoxPainter.cxx:420
 TGLBoxPainter.cxx:421
 TGLBoxPainter.cxx:422
 TGLBoxPainter.cxx:423
 TGLBoxPainter.cxx:424
 TGLBoxPainter.cxx:425
 TGLBoxPainter.cxx:426
 TGLBoxPainter.cxx:427
 TGLBoxPainter.cxx:428
 TGLBoxPainter.cxx:429
 TGLBoxPainter.cxx:430
 TGLBoxPainter.cxx:431
 TGLBoxPainter.cxx:432
 TGLBoxPainter.cxx:433
 TGLBoxPainter.cxx:434
 TGLBoxPainter.cxx:435
 TGLBoxPainter.cxx:436
 TGLBoxPainter.cxx:437
 TGLBoxPainter.cxx:438
 TGLBoxPainter.cxx:439
 TGLBoxPainter.cxx:440
 TGLBoxPainter.cxx:441
 TGLBoxPainter.cxx:442
 TGLBoxPainter.cxx:443
 TGLBoxPainter.cxx:444
 TGLBoxPainter.cxx:445
 TGLBoxPainter.cxx:446
 TGLBoxPainter.cxx:447
 TGLBoxPainter.cxx:448
 TGLBoxPainter.cxx:449
 TGLBoxPainter.cxx:450
 TGLBoxPainter.cxx:451
 TGLBoxPainter.cxx:452
 TGLBoxPainter.cxx:453
 TGLBoxPainter.cxx:454
 TGLBoxPainter.cxx:455
 TGLBoxPainter.cxx:456
 TGLBoxPainter.cxx:457
 TGLBoxPainter.cxx:458
 TGLBoxPainter.cxx:459
 TGLBoxPainter.cxx:460
 TGLBoxPainter.cxx:461
 TGLBoxPainter.cxx:462
 TGLBoxPainter.cxx:463
 TGLBoxPainter.cxx:464
 TGLBoxPainter.cxx:465
 TGLBoxPainter.cxx:466
 TGLBoxPainter.cxx:467
 TGLBoxPainter.cxx:468
 TGLBoxPainter.cxx:469
 TGLBoxPainter.cxx:470
 TGLBoxPainter.cxx:471
 TGLBoxPainter.cxx:472
 TGLBoxPainter.cxx:473
 TGLBoxPainter.cxx:474
 TGLBoxPainter.cxx:475
 TGLBoxPainter.cxx:476
 TGLBoxPainter.cxx:477
 TGLBoxPainter.cxx:478
 TGLBoxPainter.cxx:479
 TGLBoxPainter.cxx:480
 TGLBoxPainter.cxx:481
 TGLBoxPainter.cxx:482
 TGLBoxPainter.cxx:483
 TGLBoxPainter.cxx:484
 TGLBoxPainter.cxx:485
 TGLBoxPainter.cxx:486
 TGLBoxPainter.cxx:487
 TGLBoxPainter.cxx:488
 TGLBoxPainter.cxx:489
 TGLBoxPainter.cxx:490
 TGLBoxPainter.cxx:491
 TGLBoxPainter.cxx:492
 TGLBoxPainter.cxx:493
 TGLBoxPainter.cxx:494
 TGLBoxPainter.cxx:495
 TGLBoxPainter.cxx:496
 TGLBoxPainter.cxx:497
 TGLBoxPainter.cxx:498
 TGLBoxPainter.cxx:499
 TGLBoxPainter.cxx:500
 TGLBoxPainter.cxx:501
 TGLBoxPainter.cxx:502
 TGLBoxPainter.cxx:503
 TGLBoxPainter.cxx:504
 TGLBoxPainter.cxx:505
 TGLBoxPainter.cxx:506
 TGLBoxPainter.cxx:507
 TGLBoxPainter.cxx:508
 TGLBoxPainter.cxx:509
 TGLBoxPainter.cxx:510
 TGLBoxPainter.cxx:511
 TGLBoxPainter.cxx:512
 TGLBoxPainter.cxx:513
 TGLBoxPainter.cxx:514
 TGLBoxPainter.cxx:515
 TGLBoxPainter.cxx:516
 TGLBoxPainter.cxx:517
 TGLBoxPainter.cxx:518
 TGLBoxPainter.cxx:519
 TGLBoxPainter.cxx:520
 TGLBoxPainter.cxx:521
 TGLBoxPainter.cxx:522
 TGLBoxPainter.cxx:523
 TGLBoxPainter.cxx:524
 TGLBoxPainter.cxx:525
 TGLBoxPainter.cxx:526
 TGLBoxPainter.cxx:527
 TGLBoxPainter.cxx:528
 TGLBoxPainter.cxx:529
 TGLBoxPainter.cxx:530
 TGLBoxPainter.cxx:531
 TGLBoxPainter.cxx:532
 TGLBoxPainter.cxx:533
 TGLBoxPainter.cxx:534
 TGLBoxPainter.cxx:535
 TGLBoxPainter.cxx:536
 TGLBoxPainter.cxx:537
 TGLBoxPainter.cxx:538
 TGLBoxPainter.cxx:539