TEveCaloLegoGL.cxx

Go to the documentation of this file.
00001 // @(#)root/eve:$Id: TEveCaloLegoGL.cxx 37345 2010-12-06 16:53:39Z matevz $
00002 // Author: Alja Mrak-Tadel 2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, 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 "TAxis.h"
00013 #include "TH2.h"
00014 #include "THLimitsFinder.h"
00015 
00016 #include "TGLViewer.h"
00017 #include "TGLIncludes.h"
00018 #include "TGLPhysicalShape.h"
00019 #include "TGLRnrCtx.h"
00020 #include "TGLSelectRecord.h"
00021 #include "TGLScene.h"
00022 #include "TGLCamera.h"
00023 #include "TGLUtil.h"
00024 #include "TColor.h"
00025 #include "TROOT.h"
00026 
00027 
00028 #include "TEveCaloLegoGL.h"
00029 #include "TEveCalo.h"
00030 #include "TEveManager.h"
00031 #include "TEveRGBAPalette.h"
00032 
00033 #include <algorithm>
00034 
00035 //______________________________________________________________________________
00036 // OpenGL renderer class for TEveCaloLego.
00037 //
00038 
00039 ClassImp(TEveCaloLegoGL);
00040 
00041 //______________________________________________________________________________
00042 TEveCaloLegoGL::TEveCaloLegoGL() :
00043    TGLObject(),
00044 
00045    fGridColor(-1),
00046    fFontColor(-1),
00047 
00048    fEtaAxis(0),
00049    fPhiAxis(0),
00050    fZAxis(0),
00051    fM(0),
00052    fDLCacheOK(kFALSE),
00053    fMaxVal(0),
00054    fValToPixel(0),
00055    fCurrentPixelsPerBin(0),
00056    fCells3D(kTRUE),
00057    fBinStep(-1)
00058 {
00059    // Constructor.
00060 
00061    fDLCache = kFALSE;
00062 
00063    fEtaAxis = new TAxis();
00064    fPhiAxis = new TAxis();
00065    fZAxis   = new TAxis();
00066 
00067    fAxisPainter.SetFontMode(TGLFont::kPixmap);
00068 }
00069 
00070 //______________________________________________________________________________
00071 TEveCaloLegoGL::~TEveCaloLegoGL()
00072 {
00073    // Destructor.
00074 
00075    DLCachePurge();
00076 
00077    delete fEtaAxis;
00078    delete fPhiAxis;
00079    delete fZAxis;
00080 }
00081 
00082 //______________________________________________________________________________
00083 Bool_t TEveCaloLegoGL::SetModel(TObject* obj, const Option_t* /*opt*/)
00084 {
00085    // Set model object.
00086 
00087    fM = SetModelDynCast<TEveCaloLego>(obj);
00088    return kTRUE;
00089 }
00090 
00091 //______________________________________________________________________________
00092 void TEveCaloLegoGL::SetBBox()
00093 {
00094    // Set bounding box.
00095 
00096    SetAxisAlignedBBox(((TEveCaloLego*)fExternalObj)->AssertBBox());
00097 }
00098 
00099 //______________________________________________________________________________
00100 void TEveCaloLegoGL::DLCacheDrop()
00101 {
00102    // Drop all display-list definitions.
00103 
00104    fDLCacheOK = kFALSE;
00105    for (SliceDLMap_i i = fDLMap.begin(); i != fDLMap.end(); ++i)
00106       i->second = 0;
00107 
00108    TGLObject::DLCacheDrop();
00109 }
00110 
00111 //______________________________________________________________________________
00112 void TEveCaloLegoGL::DLCachePurge()
00113 {
00114    // Unregister all display-lists.
00115 
00116    // all lego cells
00117    fDLCacheOK = kFALSE;
00118    if (! fDLMap.empty()) {
00119       for (SliceDLMap_i i = fDLMap.begin(); i != fDLMap.end(); ++i) {
00120          if (i->second) {
00121             PurgeDLRange(i->second, 1);
00122             i->second = 0;
00123          }
00124       }
00125    }
00126    TGLObject::DLCachePurge();
00127 }
00128 
00129 //______________________________________________________________________________
00130 void TEveCaloLegoGL::MakeQuad(Float_t x1, Float_t y1, Float_t z1,
00131       Float_t xw, Float_t yw, Float_t h) const
00132 {
00133    // Draw an axis-aligned box using quads.
00134 
00135    //    z
00136    //    |
00137    //    |
00138    //    |________y
00139    //   /  6-------7
00140    //  /  /|      /|
00141    // x  5-------4 |
00142    //    | 2-----|-3
00143    //    |/      |/
00144    //    1-------0
00145    //
00146 
00147    Float_t x2 = x1 + xw;
00148    Float_t y2 = y1 + yw;
00149    Float_t z2 = z1 + h;
00150 
00151    if (x1 < fM->GetEtaMin()) x1 = fM->GetEtaMin();
00152    if (x2 > fM->GetEtaMax()) x2 = fM->GetEtaMax();
00153 
00154    if (y1 < fM->GetPhiMin()) y1 = fM->GetPhiMin();
00155    if (y2 > fM->GetPhiMax()) y2 = fM->GetPhiMax();
00156 
00157    glBegin(GL_QUADS);
00158    {
00159       // bottom 0123
00160       glNormal3f(0, 0, -1);
00161       glVertex3f(x2, y2, z1);
00162       glVertex3f(x2, y1, z1);
00163       glVertex3f(x1, y1, z1);
00164       glVertex3f(x1, y2, z1);
00165       // top 4765
00166       glNormal3f(0, 0, 1);
00167       glVertex3f(x2, y2, z2);
00168       glVertex3f(x1, y2, z2);
00169       glVertex3f(x1, y1, z2);
00170       glVertex3f(x2, y1, z2);
00171 
00172       // back 0451
00173       glNormal3f(1, 0, 0);
00174       glVertex3f(x2, y2, z1);
00175       glVertex3f(x2, y2, z2);
00176       glVertex3f(x2, y1, z2);
00177       glVertex3f(x2, y1, z1);
00178       // front 3267
00179       glNormal3f(-1, 0, 0);
00180       glVertex3f(x1, y2, z1);
00181       glVertex3f(x1, y1, z1);
00182       glVertex3f(x1, y1, z2);
00183       glVertex3f(x1, y2, z2);
00184 
00185       // left  0374
00186       glNormal3f(0, 1, 0);
00187       glVertex3f(x2, y2, z1);
00188       glVertex3f(x1, y2, z1);
00189       glVertex3f(x1, y2, z2);
00190       glVertex3f(x2, y2, z2);
00191       // right 1562
00192       glNormal3f(0, -1, 0);
00193       glVertex3f(x2, y1, z1);
00194       glVertex3f(x2, y1, z2);
00195       glVertex3f(x1, y1, z2);
00196       glVertex3f(x1, y1, z1);
00197    }
00198    glEnd();
00199 }
00200 
00201 //______________________________________________________________________________
00202 void TEveCaloLegoGL::Make3DDisplayList(TEveCaloData::vCellId_t& cellList, SliceDLMap_t& dlMap, Bool_t selection) const
00203 {
00204    // Create display-list that draws histogram bars for non-rebinned data.
00205    // It is used for filled and outline passes.
00206 
00207    TEveCaloData::CellData_t cellData;
00208    Int_t   prevTower = 0;
00209    Float_t offset = 0;
00210 
00211    // ids in eta phi rng
00212    Int_t nSlices = fM->fData->GetNSlices();
00213    for (Int_t s = 0; s < nSlices; ++s)
00214    {
00215       if (dlMap.empty() || dlMap[s] == 0)
00216          dlMap[s] = glGenLists(1);
00217 
00218       glNewList(dlMap[s], GL_COMPILE);
00219 
00220       for (UInt_t i = 0; i < cellList.size(); ++i)
00221       {
00222          if (cellList[i].fSlice > s) continue;
00223          if (cellList[i].fTower != prevTower) {
00224             offset = 0;
00225             prevTower = cellList[i].fTower;
00226          }
00227 
00228          fM->fData->GetCellData(cellList[i], cellData);
00229          if (s == cellList[i].fSlice)
00230          {
00231             if (selection) glLoadName(i);
00232 
00233             WrapTwoPi(cellData.fPhiMin, cellData.fPhiMax);
00234             MakeQuad(cellData.EtaMin(), cellData.PhiMin(), offset,
00235                      cellData.EtaDelta(), cellData.PhiDelta(), cellData.Value(fM->fPlotEt));
00236          }
00237          offset += cellData.Value(fM->fPlotEt);
00238       }
00239       glEndList();
00240    }
00241 }
00242 
00243 //______________________________________________________________________________
00244 void TEveCaloLegoGL::Make3DDisplayListRebin(TEveCaloData::RebinData_t& rebinData, SliceDLMap_t& dlMap, Bool_t selection) const
00245 {
00246    // Create display-list that draws histogram bars for rebinned data.
00247    // It is used for filled and outline passes.
00248 
00249    Int_t nSlices = fM->fData->GetNSlices();
00250    Float_t *vals;
00251    Float_t offset;
00252    Float_t y0, y1;
00253 
00254    for (Int_t s = 0; s < nSlices; ++s)
00255    {
00256       if (dlMap.empty() || dlMap[s] == 0)
00257          dlMap[s] = glGenLists(1);
00258 
00259       glNewList(dlMap[s], GL_COMPILE);
00260 
00261       for (Int_t i = 1; i <= fEtaAxis->GetNbins(); ++i)
00262       {
00263          for (Int_t j = 1; j <= fPhiAxis->GetNbins(); ++j)
00264          {
00265             const Int_t bin = (i)+(j)*(fEtaAxis->GetNbins()+2);
00266 
00267             if (rebinData.fBinData[bin] !=-1)
00268             {
00269                vals = rebinData.GetSliceVals(bin);
00270                offset =0;
00271                for (Int_t t = 0; t < s; ++t)
00272                   offset += vals[t];
00273 
00274                y0 = fPhiAxis->GetBinLowEdge(j);
00275                y1 = fPhiAxis->GetBinUpEdge(j);
00276                WrapTwoPi(y0, y1);
00277 
00278                if (selection) glLoadName(bin);
00279 
00280                MakeQuad(fEtaAxis->GetBinLowEdge(i), y0, offset,
00281                         fEtaAxis->GetBinWidth(i), y1-y0, vals[s]);
00282             }
00283          }
00284       }
00285       glEndList();
00286    }
00287 }
00288 
00289 //______________________________________________________________________________
00290 void TEveCaloLegoGL::SetAxis3DTitlePos(TGLRnrCtx &rnrCtx, Float_t x0, Float_t x1, Float_t y0, Float_t y1) const
00291 {
00292    const GLdouble *pm = rnrCtx.RefCamera().RefLastNoPickProjM().CArr();
00293    GLdouble mm[16];
00294    GLint    vp[4];
00295    glGetDoublev(GL_MODELVIEW_MATRIX,  mm);
00296    glGetIntegerv(GL_VIEWPORT, vp);
00297    GLdouble projX[4], projY[4], projZ[4];
00298 
00299    GLdouble cornerX[4];
00300    GLdouble cornerY[4];
00301    cornerX[0] = x0; cornerY[0] = y0;
00302    cornerX[1] = x1; cornerY[1] = y0;
00303    cornerX[2] = x1; cornerY[2] = y1;
00304    cornerX[3] = x0; cornerY[3] = y1;
00305 
00306    gluProject(cornerX[0], cornerY[0], 0, mm, pm, vp, &projX[0], &projY[0], &projZ[0]);
00307    gluProject(cornerX[1], cornerY[1], 0, mm, pm, vp, &projX[1], &projY[1], &projZ[1]);
00308    gluProject(cornerX[2], cornerY[2], 0, mm, pm, vp, &projX[2], &projY[2], &projZ[2]);
00309    gluProject(cornerX[3], cornerY[3], 0, mm, pm, vp, &projX[3], &projY[3], &projZ[3]);
00310 
00311 
00312    // Z axis location (left most corner)
00313    //
00314    Int_t idxLeft = 0;
00315    Float_t xt = projX[0];
00316    for (Int_t i = 1; i < 4; ++i) {
00317       if (projX[i] < xt) {
00318          xt  = projX[i];
00319          idxLeft = i;
00320       }
00321    }
00322    fZAxisTitlePos.Set(cornerX[idxLeft], cornerY[idxLeft], 1.05 * fMaxVal);
00323 
00324 
00325    // XY axis location (closest to eye) first
00326    //
00327    Float_t zt = 1.f;
00328    Float_t zMin = 0.f;
00329    Int_t idxFront = 0;
00330    for (Int_t i = 0; i < 4; ++i) {
00331       if (projZ[i] < zt) {
00332          zt  = projZ[i];
00333          idxFront = i;
00334       }
00335       if (projZ[i] > zMin) zMin = projZ[i];
00336    }
00337 
00338 
00339    Int_t xyIdx = idxFront;
00340    if (zMin - zt < 1e-2) xyIdx = 0; // avoid flipping in front view
00341 
00342 
00343    switch (xyIdx) {
00344       case 0:
00345          fXAxisTitlePos.fX = x1;
00346          fXAxisTitlePos.fY = y0;
00347          fYAxisTitlePos.fX = x0;
00348          fYAxisTitlePos.fY = y1;
00349          break;
00350       case 1:
00351          fXAxisTitlePos.fX = x0;
00352          fXAxisTitlePos.fY = y0;
00353          fYAxisTitlePos.fX = x1;
00354          fYAxisTitlePos.fY = y1;
00355          break;
00356       case 2:
00357          fXAxisTitlePos.fX = x0;
00358          fXAxisTitlePos.fY = y1;
00359          fYAxisTitlePos.fX = x1;
00360          fYAxisTitlePos.fY = y0;
00361          break;
00362       case 3:
00363          fXAxisTitlePos.fX = x1;
00364          fXAxisTitlePos.fY = y1;
00365          fYAxisTitlePos.fX = x0;
00366          fYAxisTitlePos.fY = y0;
00367          break;
00368    }
00369 
00370    // move title 5% over the axis length
00371    Float_t off = 0.05;
00372    Float_t tOffX = (x1-x0) * off; if (fYAxisTitlePos.fX > x0) tOffX = -tOffX;
00373    Float_t tOffY = (y1-y0) * off; if (fXAxisTitlePos.fY > y0) tOffY = -tOffY;
00374    fXAxisTitlePos.fX += tOffX;
00375    fYAxisTitlePos.fY += tOffY;
00376 
00377 
00378    // frame box
00379    //
00380    if (fM->fBoxMode)
00381    {
00382       // get corner closest to eye excluding left corner
00383       Double_t zm = 1.f;
00384       Int_t idxDepthT = 0;
00385       for (Int_t i = 0; i < 4; ++i)
00386       {
00387          if (projZ[i] < zm && projZ[i] >= zt && i != idxFront )
00388          {
00389             zm  = projZ[i];
00390             idxDepthT = i;
00391          }
00392       }
00393       if (idxFront == idxLeft)  idxFront =idxDepthT;
00394 
00395       switch (idxFront)
00396       {
00397          case 0:
00398             fBackPlaneXConst[0].Set(x1, y0, 0); fBackPlaneXConst[1].Set(x1, y1, 0);
00399             fBackPlaneYConst[0].Set(x0, y1, 0); fBackPlaneYConst[1].Set(x1, y1, 0);
00400             break;
00401          case 1:
00402             fBackPlaneXConst[0].Set(x0, y0, 0); fBackPlaneXConst[1].Set(x0, y1, 0);
00403             fBackPlaneYConst[0].Set(x0, y1, 0); fBackPlaneYConst[1].Set(x1, y1, 0);
00404             break;
00405          case 2:
00406             fBackPlaneXConst[0].Set(x0, y0, 0); fBackPlaneXConst[1].Set(x0, y1, 0);
00407             fBackPlaneYConst[0].Set(x0, y0, 0); fBackPlaneYConst[1].Set(x1, y0, 0);
00408             break;
00409          case 3:
00410             fBackPlaneXConst[0].Set(x1, y0, 0); fBackPlaneXConst[1].Set(x1, y1, 0);
00411             fBackPlaneYConst[0].Set(x0, y0, 0); fBackPlaneYConst[1].Set(x1, y0, 0);
00412             break;
00413       }
00414    }
00415 }
00416 
00417 //______________________________________________________________________________
00418 void TEveCaloLegoGL::DrawAxis3D(TGLRnrCtx & rnrCtx) const
00419 {
00420    // Draw z-axis and z-box at the appropriate grid corner-point including
00421    // tick-marks and labels.
00422 
00423    // set font size first depending on size of projected axis
00424  
00425    TGLMatrix mm;
00426    GLdouble pm[16];
00427    GLint    vp[4];
00428    glGetDoublev(GL_MODELVIEW_MATRIX, mm.Arr());
00429    glGetDoublev(GL_PROJECTION_MATRIX, pm);
00430    glGetIntegerv(GL_VIEWPORT, vp);
00431 
00432    GLdouble dn[3];
00433    GLdouble up[3];
00434    gluProject(fZAxisTitlePos.fX, fZAxisTitlePos.fY, 0                , mm.Arr(), pm, vp, &dn[0], &dn[1], &dn[2]);
00435    gluProject(fZAxisTitlePos.fX, fZAxisTitlePos.fY, fZAxisTitlePos.fZ, mm.Arr(), pm, vp, &up[0], &up[1], &up[2]);
00436    Double_t len = TMath::Sqrt((up[0] - dn[0]) * (up[0] - dn[0])
00437                               + (up[1] - dn[1]) * (up[1] - dn[1])
00438                               + (up[2] - dn[2]) * (up[2] - dn[2]));
00439 
00440    TGLVertex3 worldRef(fZAxisTitlePos.fX, fZAxisTitlePos.fY, fZAxisTitlePos.fZ);
00441 
00442    fAxisPainter.RefTMOff(0) = rnrCtx.RefCamera().ViewportDeltaToWorld(worldRef, -len, 0,  &mm);
00443    fAxisPainter.SetLabelPixelFontSize(TMath::Nint(len*fM->GetData()->GetEtaBins()->GetLabelSize()));
00444    fAxisPainter.SetTitlePixelFontSize(TMath::Nint(len*fM->GetData()->GetEtaBins()->GetTitleSize()));
00445 
00446    // Z axis
00447    //
00448    if (fM->fData->Empty() == kFALSE)
00449    {
00450       fZAxis->SetAxisColor(fGridColor);
00451       fZAxis->SetLabelColor(fFontColor);
00452       fZAxis->SetTitleColor(fFontColor);
00453       fZAxis->SetNdivisions(fM->fNZSteps*100 + 10);
00454       fZAxis->SetLimits(0, fMaxVal);
00455       fZAxis->SetTitle(fM->GetPlotEt() ? "Et[GeV]" : "E[GeV]");
00456 
00457       fAxisPainter.SetTMNDim(1);
00458       fAxisPainter.RefDir().Set(0., 0., 1.);
00459       fAxisPainter.SetLabelAlign(TGLFont::kRight, TGLFont::kCenterV);
00460       glPushMatrix();
00461       glTranslatef(fZAxisTitlePos.fX, fZAxisTitlePos.fY, 0);
00462 
00463       // tickmark vector = 10 pixels left
00464       fAxisPainter.RefTitlePos().Set(fAxisPainter.RefTMOff(0).X()*0.05,  fAxisPainter.RefTMOff(0).Y()*0.05, fZAxisTitlePos.fZ);
00465       fZAxis->SetLabelOffset(0.05);
00466       fZAxis->SetTickLength(0.05);
00467       fAxisPainter.PaintAxis(rnrCtx, fZAxis);
00468       glTranslated( fAxisPainter.RefTMOff(0).X(),  fAxisPainter.RefTMOff(0).Y(),  fAxisPainter.RefTMOff(0).Z());
00469       glPopMatrix();
00470 
00471       // draw box frame
00472       //
00473       if (fM->fBoxMode) {
00474 
00475          glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
00476 
00477          // box verticals
00478          TGLUtil::LineWidth(1);
00479          glBegin(GL_LINES);
00480          TGLUtil::Color(fGridColor);
00481 
00482          glVertex3f(fBackPlaneXConst[0].fX   ,fBackPlaneXConst[0].fY   ,0);
00483          glVertex3f(fBackPlaneXConst[0].fX   ,fBackPlaneXConst[0].fY   ,fMaxVal);
00484          glVertex3f(fBackPlaneXConst[1].fX   ,fBackPlaneXConst[1].fY   ,0);
00485          glVertex3f(fBackPlaneXConst[1].fX   ,fBackPlaneXConst[1].fY   ,fMaxVal);
00486 
00487 
00488          glVertex3f(fBackPlaneYConst[0].fX   ,fBackPlaneYConst[0].fY   ,0);
00489          glVertex3f(fBackPlaneYConst[0].fX   ,fBackPlaneYConst[0].fY   ,fMaxVal);
00490          glVertex3f(fBackPlaneYConst[1].fX   ,fBackPlaneYConst[1].fY   ,0);
00491          glVertex3f(fBackPlaneYConst[1].fX   ,fBackPlaneYConst[1].fY   ,fMaxVal);
00492 
00493          // box top
00494          glVertex3f(fBackPlaneXConst[0].fX   ,fBackPlaneXConst[0].fY   ,fMaxVal);
00495          glVertex3f(fBackPlaneXConst[1].fX   ,fBackPlaneXConst[1].fY   ,fMaxVal);
00496          glVertex3f(fBackPlaneYConst[0].fX   ,fBackPlaneYConst[0].fY   ,fMaxVal);
00497          glVertex3f(fBackPlaneYConst[1].fX   ,fBackPlaneYConst[1].fY   ,fMaxVal);
00498 
00499          glEnd();
00500 
00501          // box horizontals stippled
00502          glEnable(GL_LINE_STIPPLE);
00503          Int_t ondiv;
00504          Double_t omin, omax, bw1;
00505          THLimitsFinder::Optimize(0, fMaxVal, fM->fNZSteps, omin, omax, ondiv, bw1);
00506 
00507          glLineStipple(1, 0x5555);
00508          glBegin(GL_LINES);
00509          Float_t hz  = bw1;
00510          for (Int_t i = 1; i <= ondiv; ++i, hz += bw1) {
00511             glVertex3f(fBackPlaneXConst[0].fX   ,fBackPlaneXConst[0].fY   ,hz);
00512             glVertex3f(fBackPlaneXConst[1].fX   ,fBackPlaneXConst[1].fY   ,hz);
00513             glVertex3f(fBackPlaneYConst[0].fX   ,fBackPlaneYConst[0].fY   ,hz);
00514             glVertex3f(fBackPlaneYConst[1].fX   ,fBackPlaneYConst[1].fY   ,hz);
00515          }
00516          glEnd();
00517 
00518          glPopAttrib();
00519       }
00520    }
00521 
00522    // XY Axis
00523    //
00524 
00525    Float_t yOff  = fM->GetPhiRng();
00526    if (fXAxisTitlePos.fY < fM->GetPhiMax()) yOff = -yOff;
00527 
00528    Float_t xOff  = fM->GetEtaRng();
00529    if (fYAxisTitlePos.fX < fM->GetEtaMax()) xOff = -xOff;
00530 
00531    TAxis ax;
00532    ax.SetAxisColor(fGridColor);
00533    ax.SetLabelColor(fFontColor);
00534    ax.SetTitleColor(fFontColor);
00535    ax.SetTitleFont(fM->GetData()->GetEtaBins()->GetTitleFont());
00536    ax.SetLabelOffset(0.02);
00537    ax.SetTickLength(0.05);
00538    fAxisPainter.SetTMNDim(2);
00539    fAxisPainter.RefTMOff(1).Set(0, 0, -fMaxVal);
00540    fAxisPainter.SetLabelAlign(TGLFont::kCenterH, TGLFont::kBottom);
00541 
00542    // eta
00543    glPushMatrix();
00544    fAxisPainter.RefDir().Set(1, 0, 0);
00545    fAxisPainter.RefTMOff(0).Set(0, yOff, 0);
00546    glTranslatef(0, fXAxisTitlePos.fY, 0);
00547    ax.SetNdivisions(710);
00548    ax.SetLimits(fM->GetEtaMin(), fM->GetEtaMax());
00549    ax.SetTitle(fM->GetData()->GetEtaBins()->GetTitle());
00550    fAxisPainter.RefTitlePos().Set(fXAxisTitlePos.fX, yOff*1.5*ax.GetTickLength(), -fMaxVal*ax.GetTickLength());
00551    fAxisPainter.PaintAxis(rnrCtx, &ax);
00552    glPopMatrix();
00553 
00554    // phi
00555    fAxisPainter.RefDir().Set(0, 1, 0);
00556    fAxisPainter.RefTMOff(0).Set(xOff, 0, 0);
00557    ax.SetNdivisions(510);
00558    ax.SetLimits(fM->GetPhiMin(), fM->GetPhiMax());
00559    ax.SetTitle(fM->GetData()->GetPhiBins()->GetTitle());
00560    glPushMatrix();
00561    glTranslatef(fYAxisTitlePos.fX, 0, 0);
00562    fAxisPainter.RefTitlePos().Set( xOff*1.5*ax.GetTickLength(), fYAxisTitlePos.fY,  -fMaxVal*ax.GetTickLength());
00563    fAxisPainter.PaintAxis(rnrCtx, &ax);
00564    glPopMatrix();
00565 
00566 } // DrawAxis3D
00567 
00568 //______________________________________________________________________________
00569 void  TEveCaloLegoGL::GetScaleForMatrix(Float_t& sx, Float_t& sy, Float_t& sz) const
00570 {
00571    Double_t em, eM, pm, pM;
00572    fM->fData->GetEtaLimits(em, eM);
00573    fM->fData->GetPhiLimits(pm, pM);
00574    Double_t unit = ((eM - em) < (pM - pm)) ? (eM - em) : (pM - pm);
00575    sx = (eM - em) / (fM->GetEtaRng() * unit);
00576    sy = (pM - pm) / (fM->GetPhiRng() * unit);
00577 
00578    sz = 1;
00579    if (fM->fScaleAbs)
00580    {
00581       sz = fM->GetMaxTowerH() / fM->fMaxValAbs;
00582    }
00583    else if (!fM->fData->Empty())
00584    {
00585       sz = fM->GetMaxTowerH() / fMaxVal;
00586    }
00587 }
00588 
00589 //______________________________________________________________________________
00590 void TEveCaloLegoGL::DrawAxis2D(TGLRnrCtx & rnrCtx) const
00591 {
00592    // Draw XY axis.
00593 
00594    if (fM->GetData()->Empty())
00595       fAxisPainter.SetTMNDim(1);
00596 
00597    TGLCamera& cam  = rnrCtx.RefCamera();
00598 
00599    TAxis ax;
00600    ax.SetAxisColor(fGridColor);
00601    ax.SetLabelColor(fFontColor);
00602    ax.SetTitleColor(fFontColor);
00603    ax.SetTitleFont(fM->GetData()->GetEtaBins()->GetTitleFont());
00604    ax.SetLabelOffset(0.01);
00605    ax.SetTickLength(0.05);
00606 
00607    // set fonts
00608    fAxisPainter.SetAttAxis(&ax);
00609 
00610    // get projected length of diagonal to determine
00611    TGLMatrix mm;
00612    GLdouble pm[16];
00613    GLint    vp[4];
00614    glGetDoublev(GL_MODELVIEW_MATRIX, mm.Arr());
00615    glGetDoublev(GL_PROJECTION_MATRIX, pm);
00616    glGetIntegerv(GL_VIEWPORT, vp);
00617 
00618    GLdouble dn[3];
00619    GLdouble up[3];
00620    gluProject(fM->GetEtaMin(), fM->GetPhiMin(), 0, mm.Arr(), pm, vp, &dn[0], &dn[1], &dn[2]);
00621    gluProject(fM->GetEtaMax(), fM->GetPhiMax(), 0, mm.Arr(), pm, vp, &up[0], &up[1], &up[2]);
00622    Double_t len = TMath::Sqrt((up[0] - dn[0]) * (up[0] - dn[0])
00623                               + (up[1] - dn[1]) * (up[1] - dn[1])
00624                               + (up[2] - dn[2]) * (up[2] - dn[2]));
00625 
00626    // lock upper limit to of relative font size relative to viewport diagonal
00627    Double_t vpLimit = cam.RefViewport().Diagonal()*0.5/TMath::Sqrt2();
00628    len = TMath::Min(len, vpLimit);
00629 
00630    // eta
00631    fAxisPainter.SetLabelPixelFontSize(TMath::Nint(len*fM->GetData()->GetEtaBins()->GetLabelSize()));
00632    fAxisPainter.SetTitlePixelFontSize(TMath::Nint(len*fM->GetData()->GetEtaBins()->GetTitleSize()));
00633    ax.SetNdivisions(710);
00634    ax.SetLimits(fM->GetEtaMin(), fM->GetEtaMax());
00635    ax.SetTitle(fM->GetData()->GetEtaBins()->GetTitle());
00636    fAxisPainter.RefTitlePos().Set(fM->GetEtaMax(), -fM->GetPhiRng()*(ax.GetTickLength()+ ax.GetLabelOffset()), 0 );
00637    fAxisPainter.RefDir().Set(1, 0, 0);
00638 
00639    Float_t tmOffFrustX = cam.FrustumPlane(TGLCamera::kRight).D() + cam.FrustumPlane(TGLCamera::kLeft).D();
00640    fAxisPainter.RefTMOff(0).Set(0,  -TMath::Min(fM->GetPhiRng(), tmOffFrustX), 0);
00641    fAxisPainter.SetLabelAlign(TGLFont::kCenterH, TGLFont::kBottom);
00642 
00643    glPushMatrix();
00644    glTranslatef(0, fM->GetPhiMin(), 0);
00645    fAxisPainter.PaintAxis(rnrCtx, &ax);
00646    glPopMatrix();
00647 
00648    // phi
00649    ax.SetNdivisions(510);
00650    ax.SetLimits(fM->GetPhiMin(), fM->GetPhiMax());
00651    ax.SetTitle(fM->GetData()->GetPhiBins()->GetTitle());
00652    fAxisPainter.RefTitlePos().Set(-fM->GetEtaRng()*(ax.GetTickLength()+ ax.GetLabelOffset()), fM->GetPhiMax(), 0);
00653    fAxisPainter.RefDir().Set(0, 1, 0);
00654    Float_t tmOffFrustY = cam.FrustumPlane(TGLCamera::kTop).D() + cam.FrustumPlane(TGLCamera::kBottom).D();
00655    fAxisPainter.RefTMOff(0).Set(-TMath::Min(fM->GetEtaRng(), tmOffFrustY), 0, 0);
00656    fAxisPainter.SetLabelAlign(TGLFont::kRight, TGLFont::kCenterV);
00657 
00658    glPushMatrix();
00659    glTranslatef(fM->GetEtaMin(), 0, 0);
00660    fAxisPainter.PaintAxis(rnrCtx, &ax);
00661    glPopMatrix();
00662 
00663    fAxisPainter.SetTMNDim(2); 
00664 }
00665 
00666 //______________________________________________________________________________
00667 Int_t TEveCaloLegoGL::GetGridStep(TGLRnrCtx &rnrCtx) const
00668 {
00669    // Calculate view-dependent grid density.
00670 
00671    TGLCamera &camera = rnrCtx.RefCamera();
00672    Float_t l = -camera.FrustumPlane(TGLCamera::kLeft).D();
00673    Float_t r =  camera.FrustumPlane(TGLCamera::kRight).D();
00674    Float_t t =  camera.FrustumPlane(TGLCamera::kTop).D();
00675    Float_t b = -camera.FrustumPlane(TGLCamera::kBottom).D();
00676    Float_t frustD    = TMath::Hypot(r-l, t-b);
00677 
00678    GLint   vp[4]; glGetIntegerv(GL_VIEWPORT, vp);
00679    Float_t viewportD = TMath::Sqrt((vp[1] - vp[0]) * (vp[1] - vp[0]) + (vp[3] - vp[1]) * (vp[3] - vp[1]));
00680    Float_t deltaToViewport = viewportD/frustD;
00681 
00682    // average bin width
00683    GLdouble em, eM, pm, pM;
00684    fM->GetData()->GetEtaLimits(pm, pM);
00685    fM->GetData()->GetPhiLimits(em, eM);
00686    Int_t i0 = fM->fData->GetEtaBins()->FindBin(fM->GetEtaMin());
00687    Int_t i1 = fM->fData->GetEtaBins()->FindBin(fM->GetEtaMax());
00688    Int_t j0 = fM->fData->GetPhiBins()->FindBin(fM->GetPhiMin());
00689    Int_t j1 = fM->fData->GetPhiBins()->FindBin(fM->GetPhiMax());
00690 
00691    Float_t averageBinWidth = TMath::Hypot(eM - em, pM - pm)/TMath::Sqrt((i0 - i1) * (i0 - i1) + (j0 - j1) * (j0 - j1));
00692    Float_t ppb = deltaToViewport*averageBinWidth;
00693 
00694    Int_t ngroup = 1;
00695    if (fM->fAutoRebin && fM->fPixelsPerBin > ppb)
00696    {
00697       ngroup = TMath::Nint(fM->fPixelsPerBin*0.5/ppb); // symetrical rebin factor 2
00698       // limit rebin realtive to number of axis bins
00699       Int_t minN = TMath::Min(fM->fData->GetEtaBins()->GetNbins(), fM->fData->GetPhiBins()->GetNbins());
00700       if (ngroup * 4 > minN)
00701          ngroup = minN/4;
00702    }
00703    fCurrentPixelsPerBin = TMath::Nint(ppb);
00704 
00705    return ngroup;
00706 }
00707 
00708 //___________________________________________________________________________
00709 void TEveCaloLegoGL::RebinAxis(TAxis *orig, TAxis *curr) const
00710 {
00711    // Rebin eta, phi axis.
00712 
00713    Double_t center = 0.5 * (orig->GetXmin() + orig->GetXmax());
00714    Int_t    idx0   = orig->FindBin(center);
00715    Double_t bc     = orig->GetBinCenter(idx0);
00716    if (bc > center) --idx0;
00717 
00718    Int_t nbR = TMath::FloorNint(idx0/fBinStep) + TMath::FloorNint((orig->GetNbins() - idx0)/fBinStep);
00719    Int_t off = idx0 - TMath::FloorNint(idx0/fBinStep)*fBinStep;
00720    std::vector<Double_t> bins(nbR + 1);
00721    for (Int_t i = 0; i <= nbR; ++i)
00722    {
00723       bins[i] = orig->GetBinUpEdge(off + i*fBinStep);
00724    }
00725    curr->Set(nbR, &bins[0]);
00726 }
00727 
00728 //______________________________________________________________________________
00729 void TEveCaloLegoGL::DrawHistBase(TGLRnrCtx &rnrCtx) const
00730 {
00731    // Draw basic histogram components: x-y grid
00732 
00733    Float_t eta0 = fM->fEtaMin;
00734    Float_t eta1 = fM->fEtaMax;
00735    Float_t phi0 = fM->GetPhiMin();
00736    Float_t phi1 = fM->GetPhiMax();
00737 
00738    // XY grid
00739    //
00740    TGLUtil::Color(fGridColor);
00741    TGLUtil::LineWidth(1);
00742    glBegin(GL_LINES);
00743    glVertex2f(eta0, phi0);
00744    glVertex2f(eta0, phi1);
00745    glVertex2f(eta1, phi0);
00746    glVertex2f(eta1, phi1);
00747 
00748    glVertex2f(eta0, phi0);
00749    glVertex2f(eta1, phi0);
00750    glVertex2f(eta0, phi1);
00751    glVertex2f(eta1, phi1);
00752 
00753    // eta grid
00754    Float_t val;
00755    Int_t neb = fEtaAxis->GetNbins();
00756    for (Int_t i = 0; i<= neb; i++)
00757    {
00758       val = fEtaAxis->GetBinUpEdge(i);
00759       if (val > eta0 && val < eta1 )
00760       {
00761          glVertex2f(val, phi0);
00762          glVertex2f(val, phi1);
00763       }
00764    }
00765 
00766    // phi grid
00767    Int_t npb = fPhiAxis->GetNbins();
00768    for (Int_t i = 1; i <= npb; i++) {
00769        val = fPhiAxis->GetBinUpEdge(i);
00770       if (val > phi0 && val < phi1)
00771       {
00772          glVertex2f(eta0, val);
00773          glVertex2f(eta1, val);
00774       }
00775    }
00776 
00777    glEnd();
00778 
00779    // XYZ axes
00780    //
00781    glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_POLYGON_BIT);
00782    TGLUtil::LineWidth(2);
00783    if (fCells3D)
00784    {
00785       SetAxis3DTitlePos(rnrCtx, eta0, eta1, phi0, phi1);
00786       DrawAxis3D(rnrCtx);
00787    }
00788    else
00789    {
00790       DrawAxis2D(rnrCtx);
00791    }
00792    glPopAttrib();
00793 }
00794 
00795 //______________________________________________________________________________
00796 void TEveCaloLegoGL::DrawCells3D(TGLRnrCtx & rnrCtx) const
00797 {
00798    // Render the calo lego-plot with OpenGL.
00799 
00800    // quads
00801    {
00802       for (SliceDLMap_i i = fDLMap.begin(); i != fDLMap.end(); ++i) {
00803          TGLUtil::ColorTransparency(fM->GetDataSliceColor(i->first), fM->GetData()->GetSliceTransparency(i->first));
00804          glLoadName(i->first);
00805          glPushName(0);
00806          glCallList(i->second);
00807          glPopName();
00808       }
00809    }
00810    // outlines
00811    {
00812       if (rnrCtx.SceneStyle() == TGLRnrCtx::kFill) {
00813          glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00814          glDisable(GL_POLYGON_OFFSET_FILL);
00815          TGLUtil::Color(1);
00816          for (SliceDLMap_i i = fDLMap.begin(); i != fDLMap.end(); ++i)
00817             glCallList(i->second);
00818       }
00819    }
00820 }
00821 
00822 //______________________________________________________________________________
00823 void TEveCaloLegoGL::PrepareCell2DData(TEveCaloData::vCellId_t& cellList, vCell2D_t& cells2D) const
00824 {
00825    // Prepare cells 2D data non-rebinned for drawing.
00826 
00827    Int_t   max_energy_slice, cellID=0;
00828    Float_t sum, max_energy;
00829 
00830    TEveCaloData::vCellId_t::iterator currentCell = cellList.begin();
00831    TEveCaloData::vCellId_t::iterator nextCell    = currentCell;
00832    ++nextCell;
00833 
00834    while (true)
00835    {
00836       TEveCaloData::CellData_t currentCellData;
00837       TEveCaloData::CellData_t nextCellData;
00838 
00839       fM->fData->GetCellData(*currentCell, currentCellData);
00840       sum = max_energy = currentCellData.Value(fM->fPlotEt);
00841       max_energy_slice = currentCell->fSlice;
00842       while (nextCell != cellList.end() && currentCell->fTower == nextCell->fTower)
00843       {
00844          fM->fData->GetCellData(*nextCell, nextCellData);
00845          Float_t energy = nextCellData.Value(fM->fPlotEt);
00846          sum += energy;
00847          if (energy > max_energy)
00848          {
00849             max_energy       = energy;
00850             max_energy_slice = nextCell->fSlice;
00851          }
00852          ++nextCell;
00853          ++cellID;
00854       }
00855 
00856       WrapTwoPi(currentCellData.fPhiMin, currentCellData.fPhiMax);
00857       cells2D.push_back(Cell2D_t(cellID, sum, max_energy_slice));
00858       cells2D.back().SetGeom(currentCellData.fEtaMin, currentCellData.fEtaMax,
00859                              currentCellData.fPhiMin, currentCellData.fPhiMax);
00860 
00861       if (nextCell == cellList.end())
00862          break;
00863 
00864       currentCell = nextCell;
00865       ++nextCell;
00866       ++cellID;
00867    }
00868 }
00869 
00870 //______________________________________________________________________________
00871 void TEveCaloLegoGL::PrepareCell2DDataRebin(TEveCaloData::RebinData_t& rebinData, vCell2D_t& cells2D) const
00872 {
00873    // Prepare cells 2D rebinned data for drawing.
00874 
00875    const Int_t nEta = fEtaAxis->GetNbins();
00876    const Int_t nPhi = fPhiAxis->GetNbins();
00877    std::vector<Float_t> vec;
00878    vec.assign((nEta + 2)*(nPhi + 2), 0.f);
00879    std::vector<Float_t> max_e;
00880    std::vector<Int_t>   max_e_slice;
00881    max_e.assign((nEta + 2) * (nPhi + 2), 0.f);
00882    max_e_slice.assign((nEta + 2) * (nPhi + 2), -1);
00883 
00884    for (UInt_t bin = 0; bin < rebinData.fBinData.size(); ++bin) {
00885       Float_t ssum = 0;
00886       if (rebinData.fBinData[bin] != -1) {
00887          Float_t *val = rebinData.GetSliceVals(bin);
00888          for (Int_t s = 0; s < rebinData.fNSlices; ++s) {
00889             ssum += val[s];
00890             if (val[s] > max_e[bin]) {
00891                max_e[bin]       = val[s];
00892                max_e_slice[bin] = s;
00893             }
00894          }
00895       }
00896       vec[bin] = ssum;
00897    }
00898 
00899    // smallest threshold
00900    Float_t threshold = fM->GetDataSliceThreshold(0);
00901    for (Int_t s = 1; s < fM->fData->GetNSlices(); ++s) {
00902       if (threshold > fM->GetDataSliceThreshold(s))
00903          threshold = fM->GetDataSliceThreshold(s);
00904    }
00905 
00906    // write cells
00907    for (Int_t i = 1; i <= fEtaAxis->GetNbins(); ++i) {
00908       for (Int_t j = 1; j <= fPhiAxis->GetNbins(); ++j) {
00909          const Int_t bin = j * (nEta + 2) + i;
00910          if (vec[bin] > threshold && rebinData.fBinData[bin] != -1) {
00911             cells2D.push_back(Cell2D_t(bin, vec[bin], max_e_slice[bin]));
00912             cells2D.back().SetGeom(fEtaAxis->GetBinLowEdge(i), fEtaAxis->GetBinUpEdge(i),
00913                                    fPhiAxis->GetBinLowEdge(j), fPhiAxis->GetBinUpEdge(j));
00914          }
00915       }
00916    }
00917 }
00918 
00919 //--------------------------------------------------------------------------------
00920 void TEveCaloLegoGL::DrawCells2D(TGLRnrCtx &rnrCtx, vCell2D_t& cells2D) const
00921 {
00922    // Draw cells in top view.
00923 
00924    Float_t bws    = -1; //smallest bin
00925    Float_t logMax = -1;
00926 
00927    Float_t baseOffset = fM->GetFixedHeightValIn2DMode()*fMaxVal;
00928 
00929    if (fM->f2DMode == TEveCaloLego::kValColor)
00930    {
00931       fM->AssertPalette();
00932       UChar_t col[4];
00933 
00934       for (vCell2D_i i = cells2D.begin(); i != cells2D.end(); ++i)
00935       {
00936          if (rnrCtx.SecSelection()) glLoadName(i->fId);
00937          glBegin(GL_POLYGON);
00938          fM->fPalette->ColorFromValue(TMath::FloorNint(i->fSumVal), col);
00939          col[3] = fM->GetData()->GetSliceTransparency(i->fMaxSlice);
00940          TGLUtil::Color4ubv(col);
00941          Float_t z = fM->GetHasFixedHeightIn2DMode() ? baseOffset : i->fSumVal;
00942          glVertex3f(i->fX0, i->fY0, z);
00943          glVertex3f(i->fX1, i->fY0, z);
00944          glVertex3f(i->fX1, i->fY1, z);
00945          glVertex3f(i->fX0, i->fY1, z);
00946          glEnd();
00947       }
00948    }
00949    else
00950    {
00951       Float_t x, y;
00952       if (!rnrCtx.HighlightOutline())
00953       {
00954          Float_t maxv = 0;
00955          bws = 1e5;
00956          for (vCell2D_i i = fCells2D.begin(); i != fCells2D.end(); ++i)
00957          {
00958             if (i->MinSize() < bws)   bws  = i->MinSize();
00959             if (i->fSumVal   > maxv)  maxv = i->fSumVal;
00960          }
00961          bws   *= 0.5f;
00962          logMax = TMath::Log10(maxv + 1);
00963          fValToPixel =  bws/logMax;
00964       }
00965 
00966       // special draw for name stack
00967       if (rnrCtx.SecSelection())
00968       {
00969          for (vCell2D_i i = cells2D.begin(); i != cells2D.end(); ++i)
00970          {
00971             glLoadName(i->fMaxSlice);
00972             glPushName(i->fId);
00973 
00974             glBegin(GL_QUADS);
00975             Float_t z = fM->GetHasFixedHeightIn2DMode() ? baseOffset : i->fSumVal;
00976             glVertex3f(i->fX0, i->fY0, z);
00977             glVertex3f(i->fX1, i->fY0, z);
00978             glVertex3f(i->fX1, i->fY1, z);
00979             glVertex3f(i->fX0, i->fY1, z);
00980             glEnd();
00981 
00982             glPopName();
00983          }
00984       }
00985       else
00986       {// optimised draw without name stack
00987          if (!rnrCtx.HighlightOutline())
00988          {
00989             glBegin(GL_POINTS);
00990             for (vCell2D_i i = cells2D.begin(); i != cells2D.end(); ++i)
00991             {
00992                TGLUtil::ColorTransparency(fM->fData->GetSliceColor(i->fMaxSlice), fM->fData->GetSliceTransparency(i->fMaxSlice));
00993                Float_t z = fM->GetHasFixedHeightIn2DMode() ? baseOffset : i->fSumVal;
00994                glVertex3f(i->X(), i->Y() , z);
00995             }
00996             glEnd();
00997          }
00998 
00999          glBegin(GL_QUADS);
01000          for (vCell2D_i i = cells2D.begin(); i != cells2D.end(); ++i)
01001          {
01002             TGLUtil::ColorTransparency(fM->fData->GetSliceColor(i->fMaxSlice), fM->fData->GetSliceTransparency(i->fMaxSlice));
01003             Float_t bw = fValToPixel*TMath::Log10(i->fSumVal+1);
01004             x = i->X();
01005             y = i->Y();
01006             Float_t z = fM->GetHasFixedHeightIn2DMode() ? baseOffset : i->fSumVal;
01007             glVertex3f(x - bw, y - bw, z);
01008             glVertex3f(x + bw, y - bw, z);
01009             glVertex3f(x + bw, y + bw, z);
01010             glVertex3f(x - bw, y + bw, z);
01011          }
01012          glEnd();
01013 
01014          if (fM->f2DMode == TEveCaloLego::kValSizeOutline)
01015          { 
01016             glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);
01017             Float_t z    = 0;
01018             Float_t zOff = fMaxVal*0.001 ; // avoid polygon stipling
01019             glBegin(GL_QUADS);
01020             for ( vCell2D_i i = cells2D.begin(); i != cells2D.end(); ++i) {
01021                Char_t transp = TMath::Min(100, 80 + fM->fData->GetSliceTransparency(i->fMaxSlice) / 5);
01022                TGLUtil::ColorTransparency(fM->fData->GetSliceColor(i->fMaxSlice), transp);
01023                z = fM->GetHasFixedHeightIn2DMode() ? baseOffset : i->fSumVal;
01024                z -=  zOff;
01025                glVertex3f(i->fX0, i->fY0, z);
01026                glVertex3f(i->fX1, i->fY0, z);
01027                glVertex3f(i->fX1, i->fY1, z);
01028                glVertex3f(i->fX0, i->fY1, z);
01029             }
01030             glEnd();
01031 
01032             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
01033             glBegin(GL_QUADS);
01034             for ( vCell2D_i i = cells2D.begin(); i != cells2D.end(); ++i) {
01035                TGLUtil::ColorTransparency(fM->fData->GetSliceColor(i->fMaxSlice), 60);
01036                z = fM->GetHasFixedHeightIn2DMode() ? baseOffset : i->fSumVal;
01037                z +=  zOff;
01038                glVertex3f(i->fX0, i->fY0, z);
01039                glVertex3f(i->fX1, i->fY0, z);
01040                glVertex3f(i->fX1, i->fY1, z);
01041                glVertex3f(i->fX0, i->fY1, z);
01042             }
01043             glEnd();
01044             glPopAttrib();
01045          }
01046       }
01047    }
01048 
01049    // text
01050    if (fCurrentPixelsPerBin > fM->fDrawNumberCellPixels &&
01051        (rnrCtx.Selection() || rnrCtx.Highlight() || rnrCtx.HighlightOutline()) == kFALSE)
01052    {
01053       TGLUtil::Color(rnrCtx.ColorSet().Markup().GetColorIndex());
01054       TGLFont font;
01055       rnrCtx.RegisterFontNoScale(fM->fCellPixelFontSize, "arial", TGLFont::kPixmap, font);
01056       const char* txt;
01057       for (vCell2D_i i = cells2D.begin(); i != cells2D.end(); ++i) {
01058 
01059          Float_t val = i->fSumVal;
01060          if (val > 10)
01061             txt = Form("%d", TMath::Nint(val));
01062          else if (val > 1 )
01063             txt = Form("%.1f", val);
01064          else if (val > 0.01 )
01065             txt = Form("%.2f", 0.01*TMath::Nint(val*100));
01066          else
01067             txt = Form("~1e%d", TMath::Nint(TMath::Log10(val)));
01068 
01069          font.Render(txt, i->X(), i->Y(), val*1.2, TGLFont::kCenterH, TGLFont::kCenterV);
01070       }
01071    }
01072 }
01073 
01074 //______________________________________________________________________________
01075 void TEveCaloLegoGL::DrawHighlight(TGLRnrCtx& rnrCtx, const TGLPhysicalShape* /*pshp*/, Int_t /*lvl*/) const
01076 {
01077    // Draw highligted cells.
01078 
01079    if (fM->fData->GetCellsSelected().empty() && fM->fData->GetCellsHighlighted().empty())
01080    {
01081       return;
01082    }
01083 
01084    glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_POLYGON_BIT );
01085 
01086    // modelview matrix
01087    glPushMatrix();
01088    Float_t sx, sy, sz;
01089    GetScaleForMatrix(sx, sy, sz);
01090    glScalef(sx, sy, sz);
01091    glTranslatef(-fM->GetEta(), -fM->fPhi, 0);
01092 
01093    glDisable(GL_LIGHTING);
01094    glDisable(GL_CULL_FACE);
01095    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
01096 
01097    TGLUtil::LineWidth(2);
01098    TGLUtil::LockColor();
01099    if (!fM->fData->GetCellsHighlighted().empty()) 
01100    {
01101       glColor4ubv(rnrCtx.ColorSet().Selection(3).CArr());
01102       DrawSelectedCells(rnrCtx, fM->fData->GetCellsHighlighted());
01103    }
01104    if (!fM->fData->GetCellsSelected().empty())
01105    {
01106       Float_t dr[2];
01107       glGetFloatv(GL_DEPTH_RANGE,dr);
01108       glColor4ubv(rnrCtx.ColorSet().Selection(1).CArr());
01109       glDepthRange(dr[0], 0.8*dr[1]);
01110       DrawSelectedCells(rnrCtx, fM->fData->GetCellsSelected());
01111       glDepthRange(dr[0], dr[1]);
01112    }
01113 
01114    TGLUtil::UnlockColor();
01115    glPopMatrix();
01116    glPopAttrib();
01117 }
01118 
01119 
01120 //______________________________________________________________________________
01121 void TEveCaloLegoGL::DrawSelectedCells(TGLRnrCtx & rnrCtx, TEveCaloData::vCellId_t cellsSelectedInput) const
01122 {
01123    // Draw selected cells in highlight mode.
01124 
01125    // check eta&phi range of selected cells
01126    TEveCaloData::vCellId_t  cellsSelected;
01127    TEveCaloData::CellData_t cellData;
01128    for (TEveCaloData::vCellId_i i = cellsSelectedInput.begin(); i != cellsSelectedInput.end(); ++i)
01129    {
01130       fM->fData->GetCellData((*i), cellData);
01131       if (fM->CellInEtaPhiRng(cellData))
01132          cellsSelected.push_back(*i); 
01133    }
01134 
01135    // prepare rebin for 2D or 3D if necessary
01136    TEveCaloData::RebinData_t rebinDataSelected;
01137    if (fBinStep > 1)
01138    {
01139       fM->fData->Rebin(fEtaAxis, fPhiAxis, cellsSelected, fM->fPlotEt, rebinDataSelected);
01140       if (fM->fNormalizeRebin) {
01141          Float_t scale = 1.f / (fBinStep * fBinStep);
01142          for (std::vector<Float_t>::iterator it = rebinDataSelected.fSliceData.begin(); it != rebinDataSelected.fSliceData.end(); it++)
01143             (*it) *= scale;
01144       }
01145    }
01146 
01147    if (fCells3D)
01148    {
01149       Float_t offset =  0;
01150       if (fBinStep == 1)
01151       {
01152          for (TEveCaloData::vCellId_i j = cellsSelected.begin(); j != cellsSelected.end(); ++j)
01153          {
01154             offset = 0;
01155             {
01156                Int_t   orig_slice = j->fSlice;
01157                for (Int_t s = 0; s < orig_slice; ++s)
01158                {
01159                   j->fSlice = s;
01160                   fM->fData->GetCellData(*j, cellData);
01161                   offset += cellData.Value(fM->fPlotEt);
01162                }
01163                j->fSlice = orig_slice;
01164             }
01165             fM->fData->GetCellData(*j, cellData);
01166             WrapTwoPi(cellData.fPhiMin, cellData.fPhiMax);
01167             MakeQuad(cellData.EtaMin(), cellData.PhiMin(), offset,
01168                      cellData.EtaDelta(), cellData.PhiDelta(), cellData.Value(fM->fPlotEt));
01169          }
01170       }
01171       else
01172       {
01173          Float_t *vals;
01174          Float_t *valsRef;
01175          Float_t  y0, y1;
01176          Int_t    nSlices = fM->fData->GetNSlices();
01177          for (Int_t i = 1; i <= fEtaAxis->GetNbins(); ++i)
01178          {
01179             for (Int_t j = 1; j <= fPhiAxis->GetNbins(); ++j)
01180             {
01181                const Int_t bin = (i)+(j)*(fEtaAxis->GetNbins()+2);
01182                if (rebinDataSelected.fBinData[bin] !=-1)
01183                {
01184                   offset  = 0;
01185                   vals    = rebinDataSelected.GetSliceVals(bin);
01186                   valsRef = fRebinData.GetSliceVals(bin);
01187                   for (Int_t s = 0; s < nSlices; ++s)
01188                   {
01189                      if (vals[s] > 0)
01190                      {
01191                         y0 = fPhiAxis->GetBinLowEdge(j);
01192                         y1 = fPhiAxis->GetBinUpEdge(j);
01193                         WrapTwoPi(y0, y1);
01194                         MakeQuad(fEtaAxis->GetBinLowEdge(i), y0, offset,
01195                                  fEtaAxis->GetBinWidth(i), y1-y0, vals[s]);
01196                      }
01197                      offset += valsRef[s];
01198                   }
01199                }
01200             }
01201          }
01202       }
01203    }
01204    else
01205    {
01206       vCell2D_t cells2DSelected;
01207       if (fBinStep == 1)
01208       {
01209          // but is confusing since top view does not draw all slices at same time
01210          TEveCaloData::vCellId_i j    = cellsSelectedInput.begin();
01211          TEveCaloData::vCellId_i jEnd = cellsSelectedInput.end();
01212          std::set<Int_t> towers;
01213          while (j != jEnd)
01214          {
01215             towers.insert(j->fTower);
01216             ++j;
01217          }
01218          for (vCell2D_i i = fCells2D.begin(); i != fCells2D.end(); ++i)
01219          {
01220             TEveCaloData::CellId_t cell = fM->fCellList[i->fId];
01221             std::set<Int_t>::iterator ti = towers.find(cell.fTower);
01222             if (towers.find(cell.fTower) != towers.end())
01223             {
01224                cells2DSelected.push_back(*i);
01225             }
01226          }
01227       }
01228       else
01229       {
01230          PrepareCell2DDataRebin(rebinDataSelected, cells2DSelected);
01231       }
01232       DrawCells2D(rnrCtx, cells2DSelected);
01233    }
01234 }
01235 
01236 //______________________________________________________________________________
01237 void TEveCaloLegoGL::DirectDraw(TGLRnrCtx & rnrCtx) const
01238 {
01239    // Draw the object.
01240 
01241    if (! fM->fData || ! fM->fData->GetEtaBins() || ! fM->fData->GetPhiBins())
01242       return;
01243 
01244    // projection type
01245    if (fM->fProjection == TEveCaloLego::kAuto)
01246       fCells3D = (!(rnrCtx.RefCamera().IsOrthographic() && rnrCtx.RefCamera().GetCamBase().GetBaseVec(1).Z()));
01247    else if (fM->fProjection == TEveCaloLego::k2D)
01248       fCells3D = kFALSE;
01249    else if (fM->fProjection == TEveCaloLego::k3D)
01250       fCells3D = kTRUE;
01251 
01252    // rebin axsis , check limits, fix TwoPi cycling
01253    Int_t new_bin_step = GetGridStep(rnrCtx);
01254 
01255    // rebin data
01256    if (fM->AssertCellIdCache() || fBinStep != new_bin_step)
01257    {
01258       fBinStep = new_bin_step;
01259       fDLCacheOK   = kFALSE;
01260       fRebinData.Clear();
01261 
01262       RebinAxis(fM->fData->GetEtaBins(), fEtaAxis);
01263       RebinAxis(fM->fData->GetPhiBins(), fPhiAxis);
01264 
01265       if (fBinStep > 1)
01266       {
01267          fM->fData->Rebin(fEtaAxis, fPhiAxis, fM->fCellList, fM->fPlotEt, fRebinData);
01268 
01269          fMaxVal = 0;
01270          for (UInt_t i = 0; i < fRebinData.fSliceData.size(); i += fRebinData.fNSlices)
01271          {
01272             Double_t sum = 0;
01273             for (Int_t s = 0; s < fRebinData.fNSlices; s++)
01274             {
01275                sum += fRebinData.fSliceData[i+s];
01276             }
01277             if (sum > fMaxVal) fMaxVal = sum;
01278          }
01279 
01280          if (fM->fNormalizeRebin)
01281          {
01282             Float_t scale = 1.f / (fBinStep * fBinStep);
01283             for (std::vector<Float_t>::iterator it = fRebinData.fSliceData.begin(); it != fRebinData.fSliceData.end(); it++)
01284             {
01285                (*it) *= scale;
01286             }
01287             fMaxVal *= scale;
01288          }
01289       }
01290       else
01291       {
01292          fMaxVal = fM->GetMaxVal();
01293       }
01294    }
01295 
01296    // modelview matrix
01297    glPushMatrix();
01298    Float_t sx, sy, sz;
01299    GetScaleForMatrix(sx, sy, sz);
01300    glScalef(sx, sy, sz);
01301    glTranslatef(-fM->GetEta(), -fM->fPhi, 0);
01302 
01303    fFontColor = fM->fFontColor;
01304    fGridColor = fM->fGridColor;
01305    if (fGridColor < 0 || fFontColor < 0)
01306    {
01307       TColor* c1 = gROOT->GetColor(rnrCtx.ColorSet().Markup().GetColorIndex());
01308       TColor* c2 = gROOT->GetColor(rnrCtx.ColorSet().Background().GetColorIndex());
01309       Float_t f1, f2;
01310       if (fFontColor < 0) {
01311          f1 = 0.8; f2 = 0.2;
01312          fFontColor = TColor::GetColor(c1->GetRed()  *f1  + c2->GetRed()  *f2,
01313                                        c1->GetGreen()*f1  + c2->GetGreen()*f2,
01314                                        c1->GetBlue() *f1  + c2->GetBlue() *f2);
01315       }
01316       if (fGridColor < 0) {
01317          f1 = 0.3; f2 = 0.3;
01318          fGridColor = TColor::GetColor(c1->GetRed()  *f1  + c2->GetRed()  *f2,
01319                                        c1->GetGreen()*f1  + c2->GetGreen()*f2,
01320                                        c1->GetBlue() *f1  + c2->GetBlue() *f2);
01321       }
01322    }
01323 
01324    glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_POLYGON_BIT);
01325    TGLUtil::LineWidth(1);
01326    glEnable(GL_BLEND);
01327    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01328    if (!fM->fData->Empty())
01329    {
01330       glPushName(0);
01331       if (fCells3D)
01332       {
01333          if (fDLCacheOK == kFALSE)
01334          {
01335             if (fBinStep == 1)
01336                Make3DDisplayList(fM->fCellList, fDLMap, kTRUE);
01337             else
01338                Make3DDisplayListRebin(fRebinData, fDLMap, kTRUE);
01339             fDLCacheOK = kTRUE;
01340          }
01341          glEnable(GL_NORMALIZE);
01342          glEnable(GL_POLYGON_OFFSET_FILL);
01343          glPolygonOffset(0.8, 1);
01344 
01345          DrawCells3D(rnrCtx);
01346       }
01347       else
01348       {
01349          glDisable(GL_LIGHTING);
01350 
01351          fCells2D.clear();
01352          if (fBinStep == 1)
01353             PrepareCell2DData(fM->fCellList, fCells2D);
01354          else
01355             PrepareCell2DDataRebin(fRebinData, fCells2D);
01356 
01357          DrawCells2D(rnrCtx, fCells2D);
01358       }
01359       glPopName();
01360    }
01361    glPopAttrib();
01362 
01363    // draw histogram base
01364    if (rnrCtx.Selection() == kFALSE && rnrCtx.IsDrawPassFilled())
01365    {
01366       glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_POLYGON_BIT);
01367       glDisable(GL_LIGHTING);
01368       DrawHistBase(rnrCtx);
01369       if (fM->fDrawHPlane) {
01370          glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
01371          glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
01372          glDisable(GL_CULL_FACE);
01373          TGLUtil::ColorTransparency(fM->fPlaneColor, fM->fPlaneTransparency);
01374          Float_t zhp = fM->fHPlaneVal * fMaxVal;
01375          glBegin(GL_POLYGON);
01376          glVertex3f(fM->fEtaMin, fM->GetPhiMin(), zhp);
01377          glVertex3f(fM->fEtaMax, fM->GetPhiMin(), zhp);
01378          glVertex3f(fM->fEtaMax, fM->GetPhiMax(), zhp);
01379          glVertex3f(fM->fEtaMin, fM->GetPhiMax(), zhp);
01380          glEnd();
01381       }
01382       glPopAttrib();
01383    }
01384 
01385    glPopMatrix();
01386 }
01387 
01388 //______________________________________________________________________________
01389 void TEveCaloLegoGL::ProcessSelection(TGLRnrCtx & /*rnrCtx*/, TGLSelectRecord & rec)
01390 {
01391    // Processes tower selection from TGLViewer.
01392 
01393    TEveCaloData::vCellId_t sel;
01394    if (rec.GetN() > 2)
01395    {
01396       Int_t slice = rec.GetItem(1);
01397       Int_t cell  = rec.GetItem(2);
01398 
01399       if (fBinStep == 1)
01400       {
01401          Int_t tower = fM->fCellList[cell].fTower;
01402          while (cell > 0 && tower == fM->fCellList[cell].fTower)
01403          {
01404             sel.push_back(fM->fCellList[cell]);
01405             if (fCells3D) break;
01406             --cell;
01407          }
01408       }
01409       else
01410       {
01411          if (cell > 0)
01412          {
01413             Int_t nEta   = fEtaAxis->GetNbins();
01414             Int_t phiBin = Int_t(cell/(nEta+2));
01415             Int_t etaBin = cell - phiBin*(nEta+2);
01416             TEveCaloData::vCellId_t sl;
01417             fM->fData->GetCellList(fEtaAxis->GetBinCenter(etaBin), fEtaAxis->GetBinWidth(etaBin),
01418                                    fPhiAxis->GetBinCenter(phiBin), fPhiAxis->GetBinWidth(phiBin),
01419                                    sl);
01420 
01421             for (TEveCaloData::vCellId_i it = sl.begin(); it != sl.end(); ++it)
01422             {
01423                if (fCells3D) {
01424                   if ((*it).fSlice == slice ) sel.push_back(*it);
01425                } else {
01426                   if ((*it).fSlice <= slice ) sel.push_back(*it);
01427                }
01428             }
01429          }
01430       }
01431    }
01432    fM->fData->ProcessSelection(sel, rec);
01433 }

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