33 ClassImp(TGLAxisPainter);
 
   37 TGLAxisPainter::TGLAxisPainter():
 
   42    fAttAxis(0), fUseAxisColors(kTRUE),
 
   44    fFontMode(TGLFont::kTexture),
 
   47    fLabelPixelFontSize(14), fLabel3DFontSize(1.0),
 
   48    fTitlePixelFontSize(14), fTitle3DFontSize(1.0),
 
   50    fLabelAlignH(TGLFont::kCenterH),
 
   51    fLabelAlignV(TGLFont::kCenterV),
 
   56    fAllZeroesRE = 
new TPMERegexp(
"[-+]?0\\.0*$", 
"o");
 
   62 TGLAxisPainter::~TGLAxisPainter()
 
   70 void TGLAxisPainter::SetLabelAlign(TGLFont::ETextAlignH_e h, TGLFont::ETextAlignV_e v)
 
   79 void TGLAxisPainter::LabelsLimits(
const char *label, Int_t &first, Int_t &last)
 const 
   81    last = strlen(label) - 1;
 
   82    for (Int_t i = 0; i <= last; i++) {
 
   83       if (strchr(
"1234567890-+.", label[i])) {
 
   88    Error(
"LabelsLimits", 
"attempt to draw a blank label");
 
   94 void TGLAxisPainter::FormAxisValue(Double_t  val, TString &s)
 const 
   97    s = s.Strip(TString::kLeading);
 
   99    if (s == 
"-." || s == 
"-0")
 
  105    Ssiz_t ld = s.Last(
'.') + 1;
 
  106    if (s.Length() - ld > fDecimals)
 
  107       s.Remove(ld + fDecimals);
 
  110    if (fDecimals == 0 && s.EndsWith(
"."))
 
  111       s.Remove(s.Length() -1);
 
  113    fAllZeroesRE->Substitute(s, 
"0", kFALSE);
 
  119 void TGLAxisPainter::SetTextFormat(Double_t min, Double_t max, Double_t bw1)
 
  121    Double_t absMax = TMath::Max(TMath::Abs(min), TMath::Abs(max));
 
  122    Double_t epsilon = 1e-5;
 
  123    Double_t absMaxLog = TMath::Log10(absMax) + epsilon;
 
  127    Double_t xmicros = TMath::Power(10, -fMaxDigits);
 
  128    if (bw1 < xmicros && absMaxLog < 0) {
 
  130       fExp = (Int_t)absMaxLog;
 
  131       if (fExp % 3 == 1) fExp += TMath::Sign(2, fExp);
 
  132       if (fExp % 3 == 2) fExp += TMath::Sign(1, fExp);
 
  134       if2     = fMaxDigits - 2;
 
  137       Float_t af = (absMax > 1) ? absMaxLog : TMath::Log10(absMax * 0.0001);
 
  139       Int_t clog = Int_t(af) + 1;
 
  141       if (clog > fMaxDigits) {
 
  145             if (fExp % 3 == 0 && absMax <= TMath::Power(10, fMaxDigits - 1)) 
break;
 
  147       } 
else if (clog < -fMaxDigits) {
 
  148          Double_t rne   = 1 / TMath::Power(10, fMaxDigits - 2);
 
  152             if (fExp % 3 == 0 && absMax >= rne) 
break;
 
  157       for (Int_t i = fMaxDigits - 1; i > 0; i--) {
 
  158          if (TMath::Abs(absMax) < TMath::Power(10, i)) na = fMaxDigits - i;
 
  160       Double_t size =  TMath::Abs(max - min);
 
  161       Int_t ndyn = (Int_t)(size / bw1);
 
  163          if (size / ndyn <= 0.999 && na < fMaxDigits - 2) {
 
  169       if1 = TMath::Max(clog + na, fMaxDigits) + 1;
 
  173    if (TMath::Min(min, max) < 0)if1 = if1 + 1;
 
  174    if1 = TMath::Min(if1, 32);
 
  177    Double_t dwlabel = bw1 * TMath::Power(10, -fExp);
 
  178    while (dwlabel < TMath::Power(10, -if2)) {
 
  182    if (if1 > 14) if1 = 14;
 
  183    if (if2 > 14) if2 = 14;
 
  184    if (if2) fFormat.Form(
"%%%d.%df", if1, if2);
 
  185    else     fFormat.Form(
"%%%d.%df", if1 + 1, 1);
 
  189    chtemp.Form(
"%g", dwlabel);
 
  191    if (chtemp.First(
'.') != kNPOS)
 
  192       fDecimals = chtemp.Length() - chtemp.First(
'.') - 1;
 
  200 void TGLAxisPainter::RnrText(
const TString &txt, 
const TGLVector3 &p, TGLFont::ETextAlignH_e aH, TGLFont::ETextAlignV_e aV, 
const TGLFont &font)
 const 
  202    if (fFontMode == TGLFont::kPixmap || fFontMode ==  TGLFont::kBitmap)
 
  204      font.Render(txt, p.X(), p.Y(), p.Z(), aH, aV);
 
  212       glTranslated(p.X(), p.Y(), p.Z());
 
  213       Double_t sc = fLabel3DFontSize/fLabelPixelFontSize;
 
  215       font.Render(txt, 0, 0, 0, aH, aV);
 
  223 void TGLAxisPainter::SetLabelFont(TGLRnrCtx &rnrCtx, 
const char* fontName, Int_t fontSize, Double_t size3d)
 
  225    rnrCtx.RegisterFontNoScale(fontSize, fontName, fFontMode, fLabelFont);
 
  226    fLabel3DFontSize = size3d;
 
  227    fLabelPixelFontSize = fLabelFont.GetSize();
 
  233 void TGLAxisPainter::RnrLabels()
 const 
  236       TGLUtil::Color(fAttAxis->GetLabelColor());
 
  240    Float_t off = fAttAxis->GetLabelOffset() +  fAttAxis->GetTickLength();
 
  241    TGLVector3 offVec = fTMOff[0] * off;
 
  242    glTranslated(offVec.X(), offVec.Y(), offVec.Z());
 
  244    fLabelFont.PreRender();
 
  247    for (LabVec_t::const_iterator it = fLabVec.begin(); it != fLabVec.end(); ++it) {
 
  248       FormAxisValue((*it).second, s);
 
  250       RnrText(s, fDir*p, fLabelAlignH, fLabelAlignV, fLabelFont);
 
  253    fLabelFont.PostRender();
 
  260 void TGLAxisPainter::SetTitleFont(TGLRnrCtx &rnrCtx, 
const char* fontName,
 
  261                                   Int_t fontSize, Double_t size3d)
 
  263    rnrCtx.RegisterFontNoScale(fontSize, fontName, fFontMode, fTitleFont);
 
  264    fTitlePixelFontSize = fTitleFont.GetSize();
 
  265    fTitle3DFontSize = size3d;
 
  271 void TGLAxisPainter::RnrTitle(
const TString &txt, TGLVector3 &pos , TGLFont::ETextAlignH_e aH, TGLFont::ETextAlignV_e aV)
 const 
  274       TGLUtil::Color(fAttAxis->GetTitleColor());
 
  276    TString title = (fExp) ? Form(
"%s [10^%d]", txt.Data(), fExp) : txt;
 
  277    fTitleFont.PreRender();
 
  278    RnrText(title, pos, aH, aV, fTitleFont);
 
  279    fTitleFont.PostRender();
 
  285 void TGLAxisPainter::RnrLines()
 const 
  288       TGLUtil::Color(fAttAxis->GetAxisColor());
 
  290    TGLUtil::LineWidth(1);
 
  295    Float_t min = fTMVec.front().first;
 
  296    Float_t max = fTMVec.back().first;
 
  297    TGLVector3 start = fDir * min;
 
  298    TGLVector3 end   = fDir * max;
 
  299    glVertex3dv(start.Arr());
 
  300    glVertex3dv(end.Arr());
 
  305    Float_t tmsOrderFirst  = fAttAxis->GetTickLength();
 
  306    Float_t tmsOrderSecond = tmsOrderFirst * 0.5;
 
  308    TMVec_t::const_iterator it = fTMVec.begin();
 
  309    Int_t nt =  fTMVec.size()-1;
 
  311    for (Int_t t = 1; t < nt; ++t, ++it) {
 
  312       pos = fDir * ((*it).first);
 
  313       for (Int_t dim = 0; dim < fTMNDim; dim++) {
 
  314          glVertex3dv(pos.Arr());
 
  316             glVertex3dv((pos + fTMOff[dim]*tmsOrderSecond).Arr());
 
  318             glVertex3dv((pos + fTMOff[dim]*tmsOrderFirst).Arr());
 
  327 void TGLAxisPainter::PaintAxis(TGLRnrCtx &rnrCtx, TAxis* ax)
 
  330    Double_t min = ax->GetXmin();
 
  331    Double_t max = ax->GetXmax();
 
  334       Error(
"TGLAxisPainter::PaintAxis", 
"axis without range");
 
  341    Int_t n1a = TMath::FloorNint(fAttAxis->GetNdivisions() / 100);
 
  342    Int_t n2a = fAttAxis->GetNdivisions() - n1a * 100;
 
  345    Double_t bl1=0, bh1=0, bl2=0, bh2=0; 
 
  348    THLimitsFinder::Optimize(min, max,       n1a, bl1, bh1, bn1, bw1);
 
  349    THLimitsFinder::Optimize(bl1, bl1 + bw1, n2a, bl2, bh2, bn2, bw2);
 
  358    fTMVec.push_back(TM_t(min, -1));
 
  362    for (Int_t t1 = 0; t1 <= bn1; t1++)
 
  364       fTMVec.push_back(TM_t(v1, 0));
 
  365       fLabVec.push_back(Lab_t(v1, v1));
 
  367       for (Int_t t2 = 1; t2 < bn2; t2++)
 
  370          fTMVec.push_back(TM_t(v2, 1));
 
  379       fTMVec.push_back(TM_t(v2, 1));
 
  383    fTMVec.push_back(TM_t(max, -1));
 
  390    SetTextFormat(min, max, bw1);
 
  391    for (Int_t i = 0; i <= bn1; i++) {
 
  392       fLabVec.push_back(Lab_t(p, p));
 
  400    const char* labFontName   = TGLFontManager::GetFontNameFromId(fAttAxis->GetLabelFont());
 
  401    const char* titleFontName = TGLFontManager::GetFontNameFromId(fAttAxis->GetTitleFont());
 
  405    if (fFontMode == TGLFont::kPolygon || fFontMode == TGLFont::kTexture)
 
  407       GLdouble mm[16], pm[16];
 
  409       glGetDoublev(GL_MODELVIEW_MATRIX,  mm);
 
  410       glGetDoublev(GL_PROJECTION_MATRIX, pm);
 
  411       glGetIntegerv(GL_VIEWPORT, vp);
 
  413       GLdouble dn[3], up[3];
 
  414       gluProject(fDir.X()*min, fDir.Y()*min, fDir.Z()*min, mm, pm, vp, &dn[0], &dn[1], &dn[2]);
 
  415       gluProject(fDir.X()*max, fDir.Y()*max, fDir.Z()*max, mm, pm, vp, &up[0], &up[1], &up[2]);
 
  416       Double_t len = TMath::Sqrt((up[0] - dn[0]) * (up[0] - dn[0]) +
 
  417                                  (up[1] - dn[1]) * (up[1] - dn[1]) +
 
  418                                  (up[2] - dn[2]) * (up[2] - dn[2]));
 
  420       fLabelPixelFontSize = TMath::Nint(len*fAttAxis->GetLabelSize());
 
  421       fTitlePixelFontSize = TMath::Nint(len*fAttAxis->GetTitleSize());
 
  424    SetLabelFont(rnrCtx, labFontName,   fLabelPixelFontSize, (max - min)*fAttAxis->GetLabelSize());
 
  425    SetTitleFont(rnrCtx, titleFontName, fTitlePixelFontSize, (max - min)*fAttAxis->GetTitleSize());
 
  431       TGLUtil::Color(rnrCtx.ColorSet().Markup());
 
  433    glDisable(GL_LIGHTING);
 
  438       RnrTitle(ax->GetTitle(), fTitlePos, fLabelAlignH, fLabelAlignV);
 
  447 ClassImp(TGLAxisPainterBox);
 
  452 TGLAxisPainterBox::TGLAxisPainterBox() :
 
  455    fAxis[0] = fAxis[1] = fAxis[2] = 0;
 
  461 TGLAxisPainterBox::~TGLAxisPainterBox()
 
  468 void TGLAxisPainterBox::SetAxis3DTitlePos(TGLRnrCtx &rnrCtx)
 
  470    Double_t x0 =  fAxis[0]->GetXmin();
 
  471    Double_t x1 =  fAxis[0]->GetXmax();
 
  473    Double_t y0 =  fAxis[1]->GetXmin();
 
  474    Double_t y1 =  fAxis[1]->GetXmax();
 
  476    Double_t z0 =  fAxis[2]->GetXmin();
 
  477    Double_t z1 =  fAxis[2]->GetXmax();
 
  480    const GLdouble *pm = rnrCtx.RefCamera().RefLastNoPickProjM().CArr();
 
  483    glGetDoublev(GL_MODELVIEW_MATRIX,  mm);
 
  484    glGetIntegerv(GL_VIEWPORT, vp);
 
  485    GLdouble projX[4], projY[4], projZ[4];
 
  488    cornerX[0] = x0; cornerY[0] = y0;
 
  489    cornerX[1] = x1; cornerY[1] = y0;
 
  490    cornerX[2] = x1; cornerY[2] = y1;
 
  491    cornerX[3] = x0; cornerY[3] = y1;
 
  492    gluProject(cornerX[0], cornerY[0], z0, mm, pm, vp, &projX[0], &projY[0], &projZ[0]);
 
  493    gluProject(cornerX[1], cornerY[1], z0, mm, pm, vp, &projX[1], &projY[1], &projZ[1]);
 
  494    gluProject(cornerX[2], cornerY[2], z0, mm, pm, vp, &projX[2], &projY[2], &projZ[2]);
 
  495    gluProject(cornerX[3], cornerY[3], z0, mm, pm, vp, &projX[3], &projY[3], &projZ[3]);
 
  501    Float_t xt = projX[0];
 
  502    for (Int_t i = 1; i < 4; ++i) {
 
  508    fAxisTitlePos[2].Set(cornerX[idxLeft], cornerY[idxLeft], z1);
 
  516    for (Int_t i = 0; i < 4; ++i) {
 
  521       if (projZ[i] > zMin) zMin = projZ[i];
 
  523    Int_t xyIdx = idxFront;
 
  524    if (zMin - zt < 1e-2) xyIdx = 0; 
 
  529          fAxisTitlePos[0].Set(x1, y0, z0);
 
  530          fAxisTitlePos[1].Set(x0, y1, z0);
 
  533          fAxisTitlePos[0].Set(x1, y0, z0);
 
  534          fAxisTitlePos[1].Set(x0, y1, z0);
 
  537          fAxisTitlePos[0].Set(x0, y1, z0);
 
  538          fAxisTitlePos[1].Set(x1, y0, z0);
 
  541          fAxisTitlePos[0].Set(x1, y1, z0);
 
  542          fAxisTitlePos[1].Set(x0, y0, z0);
 
  550 void TGLAxisPainterBox::DrawAxis3D(TGLRnrCtx &rnrCtx)
 
  556    glGetDoublev(GL_MODELVIEW_MATRIX, mm.Arr());
 
  557    glGetDoublev(GL_PROJECTION_MATRIX, pm);
 
  558    glGetIntegerv(GL_VIEWPORT, vp);
 
  563    gluProject(fAxisTitlePos[2].X(), fAxisTitlePos[2].Y(), fAxis[2]->GetXmin(), mm.Arr(), pm, vp, &dn[0], &dn[1], &dn[2]);
 
  564    gluProject(fAxisTitlePos[2].X(), fAxisTitlePos[2].Y(), fAxis[2]->GetXmax(), mm.Arr(), pm, vp, &up[0], &up[1], &up[2]);
 
  565    Double_t len = TMath::Sqrt((up[0] - dn[0]) * (up[0] - dn[0]) +
 
  566                               (up[1] - dn[1]) * (up[1] - dn[1]) +
 
  567                               (up[2] - dn[2]) * (up[2] - dn[2]));
 
  568    SetLabelPixelFontSize(TMath::CeilNint(len*fAxis[2]->GetLabelSize()));
 
  569    SetTitlePixelFontSize(TMath::CeilNint(len*fAxis[2]->GetTitleSize()));
 
  575    fAxis[2]->SetTickLength(1.); 
 
  576    TGLVertex3 worldRef(fAxisTitlePos[2].X(), fAxisTitlePos[2].Y(), fAxisTitlePos[2].Z());
 
  577    RefTMOff(0) = rnrCtx.RefCamera().ViewportDeltaToWorld(worldRef, -10, 0, &mm);
 
  579    RefDir().Set(0., 0., 1.);
 
  580    SetLabelAlign(TGLFont::kRight,  TGLFont::kBottom);
 
  582    glTranslatef(fAxisTitlePos[2].X(), fAxisTitlePos[2].Y(), 0);
 
  583    RefTitlePos().Set(RefTMOff(0).X(), RefTMOff(0).Y(),fAxisTitlePos[2].Z());
 
  584    PaintAxis(rnrCtx, fAxis[2]);
 
  590    RefTMOff(1).Set(0, 0, fAxis[2]->GetXmin()- fAxis[2]->GetXmax());
 
  591    SetLabelAlign(TGLFont::kCenterH, TGLFont::kBottom);
 
  594    RefDir().Set(1, 0, 0);
 
  595    Float_t yOff = fAxis[0]->GetXmax() - fAxis[0]->GetXmin();
 
  597    if (fAxisTitlePos[0].Y() < fAxis[1]->GetXmax()) yOff = -yOff;
 
  598    RefTMOff(0).Set(0, yOff, 0);
 
  599    glTranslatef(0, fAxisTitlePos[0].Y(), fAxisTitlePos[0].Z());
 
  600    RefTitlePos().Set(fAxisTitlePos[0].X(), yOff*1.5*fAxis[0]->GetTickLength(), 0);
 
  601    PaintAxis(rnrCtx, fAxis[0]);
 
  606    RefDir().Set(0, 1, 0);
 
  607    Float_t xOff = fAxis[1]->GetXmax() - fAxis[1]->GetXmin();
 
  608    if (fAxisTitlePos[1].X() < fAxis[0]->GetXmax()) xOff = -xOff;
 
  609    RefTMOff(0).Set(xOff, 0, 0);
 
  610    glTranslatef(fAxisTitlePos[1].X(), 0, fAxisTitlePos[1].Z());
 
  611    RefTitlePos().Set(xOff*1.5*fAxis[1]->GetTickLength(), fAxisTitlePos[1].Y(), 0);
 
  612    PaintAxis(rnrCtx, fAxis[1]);
 
  618 void TGLAxisPainterBox::PlotStandard(      TGLRnrCtx      &rnrCtx,
 
  620                                      const TGLBoundingBox &bbox)
 
  622    fAxis[0] = histo->GetXaxis();
 
  623    fAxis[1] = histo->GetYaxis();
 
  624    fAxis[2] = histo->GetZaxis();
 
  629    Double_t sx = (bbox.XMax() - bbox.XMin()) / (fAxis[0]->GetXmax() - fAxis[0]->GetXmin());
 
  630    Double_t sy = (bbox.YMax() - bbox.YMin()) / (fAxis[1]->GetXmax() - fAxis[1]->GetXmin());
 
  631    Double_t sz = (bbox.ZMax() - bbox.ZMin()) / (fAxis[2]->GetXmax() - fAxis[2]->GetXmin());
 
  635    glScaled(sx, sy, sz);
 
  636    SetAxis3DTitlePos(rnrCtx);