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);