00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TGLAxisPainter.h"
00013
00014 #include "TGLRnrCtx.h"
00015 #include "TGLCamera.h"
00016 #include "TGLIncludes.h"
00017 #include "TGLRnrCtx.h"
00018 #include "TGLFontManager.h"
00019
00020 #include "TAttAxis.h"
00021 #include "TAxis.h"
00022 #include "TH1.h"
00023 #include "THLimitsFinder.h"
00024
00025 #include "TMath.h"
00026 #include "TPRegexp.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 ClassImp(TGLAxisPainter);
00037
00038
00039 TGLAxisPainter::TGLAxisPainter():
00040 fExp(0),
00041 fMaxDigits(5),
00042 fDecimals(0),
00043
00044 fAttAxis(0), fUseAxisColors(kTRUE),
00045
00046 fFontMode(TGLFont::kTexture),
00047 fDir(1, 0, 0),
00048 fTMNDim(1),
00049 fLabelPixelFontSize(14), fLabel3DFontSize(1.0),
00050 fTitlePixelFontSize(14), fTitle3DFontSize(1.0),
00051
00052 fLabelAlignH(TGLFont::kCenterH),
00053 fLabelAlignV(TGLFont::kCenterV),
00054 fAllZeroesRE(0)
00055 {
00056
00057
00058 fAllZeroesRE = new TPMERegexp("[-+]?0\\.0*$", "o");
00059 }
00060
00061
00062
00063 TGLAxisPainter::~TGLAxisPainter()
00064 {
00065
00066
00067 delete fAllZeroesRE;
00068 }
00069
00070
00071 void TGLAxisPainter::SetLabelAlign(TGLFont::ETextAlignH_e h, TGLFont::ETextAlignV_e v)
00072 {
00073
00074
00075 fLabelAlignH = h;
00076 fLabelAlignV = v;
00077 }
00078
00079
00080 void TGLAxisPainter::LabelsLimits(const char *label, Int_t &first, Int_t &last) const
00081 {
00082
00083
00084 last = strlen(label) - 1;
00085 for (Int_t i = 0; i <= last; i++) {
00086 if (strchr("1234567890-+.", label[i])) {
00087 first = i;
00088 return;
00089 }
00090 }
00091 Error("LabelsLimits", "attempt to draw a blank label");
00092 }
00093
00094
00095 void TGLAxisPainter::FormAxisValue(Double_t val, TString &s) const
00096 {
00097
00098
00099 s.Form(fFormat, val);
00100 s = s.Strip(TString::kLeading);
00101
00102 if (s == "-." || s == "-0")
00103 {
00104 s = "0";
00105 return;
00106 }
00107
00108 Ssiz_t ld = s.Last('.') + 1;
00109 if (s.Length() - ld > fDecimals)
00110 s.Remove(ld + fDecimals);
00111
00112
00113 if (fDecimals == 0 && s.EndsWith("."))
00114 s.Remove(s.Length() -1);
00115
00116 fAllZeroesRE->Substitute(s, "0", kFALSE);
00117 }
00118
00119
00120 void TGLAxisPainter::SetTextFormat(Double_t min, Double_t max, Double_t bw1)
00121 {
00122
00123
00124 Double_t absMax = TMath::Max(TMath::Abs(min), TMath::Abs(max));
00125 Double_t epsilon = 1e-5;
00126 Double_t absMaxLog = TMath::Log10(absMax) + epsilon;
00127
00128 fExp = 0;
00129 Int_t if1, if2;
00130 Double_t xmicros = TMath::Power(10, -fMaxDigits);
00131 if (bw1 < xmicros && absMaxLog < 0) {
00132
00133 fExp = (Int_t)absMaxLog;
00134 if (fExp % 3 == 1) fExp += TMath::Sign(2, fExp);
00135 if (fExp % 3 == 2) fExp += TMath::Sign(1, fExp);
00136 if1 = fMaxDigits;
00137 if2 = fMaxDigits - 2;
00138 } else {
00139
00140 Float_t af = (absMax > 1) ? absMaxLog : TMath::Log10(absMax * 0.0001);
00141 af += epsilon;
00142 Int_t clog = Int_t(af) + 1;
00143
00144 if (clog > fMaxDigits) {
00145 while (1) {
00146 fExp++;
00147 absMax /= 10;
00148 if (fExp % 3 == 0 && absMax <= TMath::Power(10, fMaxDigits - 1)) break;
00149 }
00150 } else if (clog < -fMaxDigits) {
00151 Double_t rne = 1 / TMath::Power(10, fMaxDigits - 2);
00152 while (1) {
00153 fExp--;
00154 absMax *= 10;
00155 if (fExp % 3 == 0 && absMax >= rne) break;
00156 }
00157 }
00158
00159 Int_t na = 0;
00160 for (Int_t i = fMaxDigits - 1; i > 0; i--) {
00161 if (TMath::Abs(absMax) < TMath::Power(10, i)) na = fMaxDigits - i;
00162 }
00163 Double_t size = TMath::Abs(max - min);
00164 Int_t ndyn = (Int_t)(size / bw1);
00165 while (ndyn) {
00166 if (size / ndyn <= 0.999 && na < fMaxDigits - 2) {
00167 na++;
00168 ndyn /= 10;
00169 } else break;
00170 }
00171 if2 = na;
00172 if1 = TMath::Max(clog + na, fMaxDigits) + 1;
00173 }
00174
00175
00176 if (TMath::Min(min, max) < 0)if1 = if1 + 1;
00177 if1 = TMath::Min(if1, 32);
00178
00179
00180 Double_t dwlabel = bw1 * TMath::Power(10, -fExp);
00181 while (dwlabel < TMath::Power(10, -if2)) {
00182 if1++;
00183 if2++;
00184 }
00185 if (if1 > 14) if1 = 14;
00186 if (if2 > 14) if2 = 14;
00187 if (if2) fFormat.Form("%%%d.%df", if1, if2);
00188 else fFormat.Form("%%%d.%df", if1 + 1, 1);
00189
00190
00191 TString chtemp;
00192 chtemp.Form("%g", dwlabel);
00193 fDecimals = 0;
00194 if (chtemp.First('.') != kNPOS)
00195 fDecimals = chtemp.Length() - chtemp.First('.') - 1;
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 void TGLAxisPainter::RnrText(const TString &txt, const TGLVector3 &p, TGLFont::ETextAlignH_e aH, TGLFont::ETextAlignV_e aV, const TGLFont &font) const
00208 {
00209
00210
00211 if (fFontMode == TGLFont::kPixmap || fFontMode == TGLFont::kBitmap)
00212 {
00213 font.Render(txt, p.X(), p.Y(), p.Z(), aH, aV);
00214 }
00215 else
00216 {
00217
00218
00219
00220 glPushMatrix();
00221 glTranslated(p.X(), p.Y(), p.Z());
00222 Double_t sc = fLabel3DFontSize/fLabelPixelFontSize;
00223 glScaled(sc, sc, 1);
00224 font.Render(txt, 0, 0, 0, aH, aV);
00225 glPopMatrix();
00226 }
00227 }
00228
00229
00230 void TGLAxisPainter::SetLabelFont(TGLRnrCtx &rnrCtx, const char* fontName, Int_t fontSize, Double_t size3d)
00231 {
00232
00233
00234 rnrCtx.RegisterFontNoScale(fontSize, fontName, fFontMode, fLabelFont);
00235 fLabel3DFontSize = size3d;
00236 fLabelPixelFontSize = fLabelFont.GetSize();
00237 }
00238
00239
00240 void TGLAxisPainter::RnrLabels() const
00241 {
00242
00243
00244 if (fUseAxisColors)
00245 TGLUtil::Color(fAttAxis->GetLabelColor());
00246
00247 glPushMatrix();
00248
00249 Float_t off = fAttAxis->GetLabelOffset() + fAttAxis->GetTickLength();
00250 TGLVector3 offVec = fTMOff[0] * off;
00251 glTranslated(offVec.X(), offVec.Y(), offVec.Z());
00252
00253 fLabelFont.PreRender();
00254 Double_t p = 0.;
00255 TString s;
00256 for (LabVec_t::const_iterator it = fLabVec.begin(); it != fLabVec.end(); ++it) {
00257 FormAxisValue((*it).second, s);
00258 p = (*it).first;
00259 RnrText(s, fDir*p, fLabelAlignH, fLabelAlignV, fLabelFont);
00260 }
00261
00262 fLabelFont.PostRender();
00263 glPopMatrix();
00264 }
00265
00266
00267 void TGLAxisPainter::SetTitleFont(TGLRnrCtx &rnrCtx, const char* fontName,
00268 Int_t fontSize, Double_t size3d)
00269 {
00270
00271
00272 rnrCtx.RegisterFontNoScale(fontSize, fontName, fFontMode, fTitleFont);
00273 fTitlePixelFontSize = fTitleFont.GetSize();
00274 fTitle3DFontSize = size3d;
00275 }
00276
00277
00278 void TGLAxisPainter::RnrTitle(const TString &txt, TGLVector3 &pos , TGLFont::ETextAlignH_e aH, TGLFont::ETextAlignV_e aV) const
00279 {
00280
00281
00282 if (fUseAxisColors)
00283 TGLUtil::Color(fAttAxis->GetTitleColor());
00284
00285 TString title = (fExp) ? Form("%s [10^%d]", txt.Data(), fExp) : txt;
00286 fTitleFont.PreRender();
00287 RnrText(title, pos, aH, aV, fTitleFont);
00288 fTitleFont.PostRender();
00289 }
00290
00291
00292 void TGLAxisPainter::RnrLines() const
00293 {
00294
00295
00296 if (fUseAxisColors)
00297 TGLUtil::Color(fAttAxis->GetAxisColor());
00298
00299 TGLUtil::LineWidth(1);
00300 glBegin(GL_LINES);
00301
00302
00303
00304 Float_t min = fTMVec.front().first;
00305 Float_t max = fTMVec.back().first;
00306 TGLVector3 start = fDir * min;
00307 TGLVector3 end = fDir * max;
00308 glVertex3dv(start.Arr());
00309 glVertex3dv(end.Arr());
00310
00311
00312
00313
00314 Float_t tmsOrderFirst = fAttAxis->GetTickLength();
00315 Float_t tmsOrderSecond = tmsOrderFirst * 0.5;
00316 TGLVector3 pos;
00317 TMVec_t::const_iterator it = fTMVec.begin();
00318 Int_t nt = fTMVec.size()-1;
00319 it++;
00320 for (Int_t t = 1; t < nt; ++t, ++it) {
00321 pos = fDir * ((*it).first);
00322 for (Int_t dim = 0; dim < fTMNDim; dim++) {
00323 glVertex3dv(pos.Arr());
00324 if ((*it).second)
00325 glVertex3dv((pos + fTMOff[dim]*tmsOrderSecond).Arr());
00326 else
00327 glVertex3dv((pos + fTMOff[dim]*tmsOrderFirst).Arr());
00328 }
00329 }
00330 glEnd();
00331 }
00332
00333
00334 void TGLAxisPainter::PaintAxis(TGLRnrCtx &rnrCtx, TAxis* ax)
00335 {
00336
00337
00338 fAttAxis = ax;
00339 Double_t min = ax->GetXmin();
00340 Double_t max = ax->GetXmax();
00341 if (min == max)
00342 {
00343 Error("TGLAxisPainter::PaintAxis", "axis without range");
00344 return;
00345 }
00346
00347
00348
00349
00350 Int_t n1a = TMath::FloorNint(fAttAxis->GetNdivisions() / 100);
00351 Int_t n2a = fAttAxis->GetNdivisions() - n1a * 100;
00352 Int_t bn1, bn2;
00353 Double_t bw1, bw2;
00354 Double_t bl1, bh1, bl2, bh2;
00355
00356
00357 THLimitsFinder::Optimize(min, max, n1a, bl1, bh1, bn1, bw1);
00358 THLimitsFinder::Optimize(bl1, bl1 + bw1, n2a, bl2, bh2, bn2, bw2);
00359
00360
00361
00362
00363
00364 fTMVec.clear();
00365 fLabVec.clear();
00366
00367 fTMVec.push_back(TM_t(min, -1));
00368
00369 Double_t v1 = bl1;
00370 Double_t v2 = 0;
00371 for (Int_t t1 = 0; t1 <= bn1; t1++)
00372 {
00373 fTMVec.push_back(TM_t(v1, 0));
00374 fLabVec.push_back(Lab_t(v1, v1));
00375 v2 = v1 + bw2;
00376 for (Int_t t2 = 1; t2 < bn2; t2++)
00377 {
00378 if (v2 > max) break;
00379 fTMVec.push_back(TM_t(v2, 1));
00380 v2 += bw2;
00381 }
00382 v1 += bw1;
00383 }
00384
00385
00386 v2 = bl1 -bw2;
00387 while (v2 > min) {
00388 fTMVec.push_back(TM_t(v2, 1));
00389 v2 -= bw2;
00390 }
00391
00392 fTMVec.push_back(TM_t(max, -1));
00393
00394
00395
00396
00397 Double_t p = bl1;
00398 fLabVec.clear();
00399 SetTextFormat(min, max, bw1);
00400 for (Int_t i = 0; i <= bn1; i++) {
00401 fLabVec.push_back(Lab_t(p, p));
00402 p += bw1;
00403 }
00404
00405
00406
00407
00408
00409 const char* labFontName = TGLFontManager::GetFontNameFromId(fAttAxis->GetLabelFont());
00410 const char* titleFontName = TGLFontManager::GetFontNameFromId(fAttAxis->GetTitleFont());
00411
00412
00413
00414 if (fFontMode == TGLFont::kPolygon || fFontMode == TGLFont::kTexture)
00415 {
00416 GLdouble mm[16], pm[16];
00417 GLint vp[4];
00418 glGetDoublev(GL_MODELVIEW_MATRIX, mm);
00419 glGetDoublev(GL_PROJECTION_MATRIX, pm);
00420 glGetIntegerv(GL_VIEWPORT, vp);
00421
00422 GLdouble dn[3], up[3];
00423 gluProject(fDir.X()*min, fDir.Y()*min, fDir.Z()*min, mm, pm, vp, &dn[0], &dn[1], &dn[2]);
00424 gluProject(fDir.X()*max, fDir.Y()*max, fDir.Z()*max, mm, pm, vp, &up[0], &up[1], &up[2]);
00425 Double_t len = TMath::Sqrt((up[0] - dn[0]) * (up[0] - dn[0]) +
00426 (up[1] - dn[1]) * (up[1] - dn[1]) +
00427 (up[2] - dn[2]) * (up[2] - dn[2]));
00428
00429 fLabelPixelFontSize = TMath::Nint(len*fAttAxis->GetLabelSize());
00430 fTitlePixelFontSize = TMath::Nint(len*fAttAxis->GetTitleSize());
00431 }
00432
00433 SetLabelFont(rnrCtx, labFontName, fLabelPixelFontSize, (max - min)*fAttAxis->GetLabelSize());
00434 SetTitleFont(rnrCtx, titleFontName, fTitlePixelFontSize, (max - min)*fAttAxis->GetTitleSize());
00435
00436
00437
00438
00439 if (!fUseAxisColors)
00440 TGLUtil::Color(rnrCtx.ColorSet().Markup());
00441
00442 glDisable(GL_LIGHTING);
00443 RnrLines();
00444 RnrLabels();
00445
00446 if (ax->GetTitle())
00447 RnrTitle(ax->GetTitle(), fTitlePos, fLabelAlignH, fLabelAlignV);
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 ClassImp(TGLAxisPainterBox);
00460
00461
00462 TGLAxisPainterBox::TGLAxisPainterBox() :
00463 TGLAxisPainter()
00464 {
00465
00466
00467 fAxis[0] = fAxis[1] = fAxis[2] = 0;
00468 }
00469
00470
00471 TGLAxisPainterBox::~TGLAxisPainterBox()
00472 {
00473
00474 }
00475
00476
00477 void TGLAxisPainterBox::SetAxis3DTitlePos(TGLRnrCtx &rnrCtx)
00478 {
00479
00480
00481 Double_t x0 = fAxis[0]->GetXmin();
00482 Double_t x1 = fAxis[0]->GetXmax();
00483
00484 Double_t y0 = fAxis[1]->GetXmin();
00485 Double_t y1 = fAxis[1]->GetXmax();
00486
00487 Double_t z0 = fAxis[2]->GetXmin();
00488 Double_t z1 = fAxis[2]->GetXmax();
00489
00490
00491 const GLdouble *pm = rnrCtx.RefCamera().RefLastNoPickProjM().CArr();
00492 GLdouble mm[16];
00493 GLint vp[4];
00494 glGetDoublev(GL_MODELVIEW_MATRIX, mm);
00495 glGetIntegerv(GL_VIEWPORT, vp);
00496 GLdouble projX[4], projY[4], projZ[4];
00497 GLdouble cornerX[4];
00498 GLdouble cornerY[4];
00499 cornerX[0] = x0; cornerY[0] = y0;
00500 cornerX[1] = x1; cornerY[1] = y0;
00501 cornerX[2] = x1; cornerY[2] = y1;
00502 cornerX[3] = x0; cornerY[3] = y1;
00503 gluProject(cornerX[0], cornerY[0], z0, mm, pm, vp, &projX[0], &projY[0], &projZ[0]);
00504 gluProject(cornerX[1], cornerY[1], z0, mm, pm, vp, &projX[1], &projY[1], &projZ[1]);
00505 gluProject(cornerX[2], cornerY[2], z0, mm, pm, vp, &projX[2], &projY[2], &projZ[2]);
00506 gluProject(cornerX[3], cornerY[3], z0, mm, pm, vp, &projX[3], &projY[3], &projZ[3]);
00507
00508
00509
00510
00511 Int_t idxLeft = 0;
00512 Float_t xt = projX[0];
00513 for (Int_t i = 1; i < 4; ++i) {
00514 if (projX[i] < xt) {
00515 xt = projX[i];
00516 idxLeft = i;
00517 }
00518 }
00519 fAxisTitlePos[2].Set(cornerX[idxLeft], cornerY[idxLeft], z1);
00520
00521
00522
00523
00524 Float_t zt = 1.f;
00525 Float_t zMin = 0.f;
00526 Int_t idxFront = 0;
00527 for (Int_t i = 0; i < 4; ++i) {
00528 if (projZ[i] < zt) {
00529 zt = projZ[i];
00530 idxFront = i;
00531 }
00532 if (projZ[i] > zMin) zMin = projZ[i];
00533 }
00534 Int_t xyIdx = idxFront;
00535 if (zMin - zt < 1e-2) xyIdx = 0;
00536
00537
00538 switch (xyIdx) {
00539 case 0:
00540 fAxisTitlePos[0].Set(x1, y0, z0);
00541 fAxisTitlePos[1].Set(x0, y1, z0);
00542 break;
00543 case 1:
00544 fAxisTitlePos[0].Set(x1, y0, z0);
00545 fAxisTitlePos[1].Set(x0, y1, z0);
00546 break;
00547 case 2:
00548 fAxisTitlePos[0].Set(x0, y1, z0);
00549 fAxisTitlePos[1].Set(x1, y0, z0);
00550 break;
00551 case 3:
00552 fAxisTitlePos[0].Set(x1, y1, z0);
00553 fAxisTitlePos[1].Set(x0, y0, z0);
00554 break;
00555 }
00556 }
00557
00558
00559 void TGLAxisPainterBox::DrawAxis3D(TGLRnrCtx &rnrCtx)
00560 {
00561
00562
00563
00564 TGLMatrix mm;
00565 GLdouble pm[16];
00566 GLint vp[4];
00567 glGetDoublev(GL_MODELVIEW_MATRIX, mm.Arr());
00568 glGetDoublev(GL_PROJECTION_MATRIX, pm);
00569 glGetIntegerv(GL_VIEWPORT, vp);
00570
00571
00572 GLdouble dn[3];
00573 GLdouble up[3];
00574 gluProject(fAxisTitlePos[2].X(), fAxisTitlePos[2].Y(), fAxis[2]->GetXmin(), mm.Arr(), pm, vp, &dn[0], &dn[1], &dn[2]);
00575 gluProject(fAxisTitlePos[2].X(), fAxisTitlePos[2].Y(), fAxis[2]->GetXmax(), mm.Arr(), pm, vp, &up[0], &up[1], &up[2]);
00576 Double_t len = TMath::Sqrt((up[0] - dn[0]) * (up[0] - dn[0]) +
00577 (up[1] - dn[1]) * (up[1] - dn[1]) +
00578 (up[2] - dn[2]) * (up[2] - dn[2]));
00579 SetLabelPixelFontSize(TMath::CeilNint(len*fAxis[2]->GetLabelSize()));
00580 SetTitlePixelFontSize(TMath::CeilNint(len*fAxis[2]->GetTitleSize()));
00581
00582
00583
00584
00585
00586 fAxis[2]->SetTickLength(1.);
00587 TGLVertex3 worldRef(fAxisTitlePos[2].X(), fAxisTitlePos[2].Y(), fAxisTitlePos[2].Z());
00588 RefTMOff(0) = rnrCtx.RefCamera().ViewportDeltaToWorld(worldRef, -10, 0, &mm);
00589 SetTMNDim(1);
00590 RefDir().Set(0., 0., 1.);
00591 SetLabelAlign(TGLFont::kRight, TGLFont::kBottom);
00592 glPushMatrix();
00593 glTranslatef(fAxisTitlePos[2].X(), fAxisTitlePos[2].Y(), 0);
00594 RefTitlePos().Set(RefTMOff(0).X(), RefTMOff(0).Y(),fAxisTitlePos[2].Z());
00595 PaintAxis(rnrCtx, fAxis[2]);
00596 glPopMatrix();
00597
00598
00599
00600 SetTMNDim(2);
00601 RefTMOff(1).Set(0, 0, fAxis[2]->GetXmin()- fAxis[2]->GetXmax());
00602 SetLabelAlign(TGLFont::kCenterH, TGLFont::kBottom);
00603
00604 glPushMatrix();
00605 RefDir().Set(1, 0, 0);
00606 Float_t yOff = fAxis[0]->GetXmax() - fAxis[0]->GetXmin();
00607 yOff *= 0.5f;
00608 if (fAxisTitlePos[0].Y() < fAxis[1]->GetXmax()) yOff = -yOff;
00609 RefTMOff(0).Set(0, yOff, 0);
00610 glTranslatef(0, fAxisTitlePos[0].Y(), fAxisTitlePos[0].Z());
00611 RefTitlePos().Set(fAxisTitlePos[0].X(), yOff*1.5*fAxis[0]->GetTickLength(), 0);
00612 PaintAxis(rnrCtx, fAxis[0]);
00613 glPopMatrix();
00614
00615
00616 glPushMatrix();
00617 RefDir().Set(0, 1, 0);
00618 Float_t xOff = fAxis[1]->GetXmax() - fAxis[1]->GetXmin();
00619 if (fAxisTitlePos[1].X() < fAxis[0]->GetXmax()) xOff = -xOff;
00620 RefTMOff(0).Set(xOff, 0, 0);
00621 glTranslatef(fAxisTitlePos[1].X(), 0, fAxisTitlePos[1].Z());
00622 RefTitlePos().Set(xOff*1.5*fAxis[1]->GetTickLength(), fAxisTitlePos[1].Y(), 0);
00623 PaintAxis(rnrCtx, fAxis[1]);
00624 glPopMatrix();
00625 }
00626
00627
00628 void TGLAxisPainterBox::PlotStandard( TGLRnrCtx &rnrCtx,
00629 const TH1 *histo,
00630 const TGLBoundingBox &bbox)
00631 {
00632
00633
00634 fAxis[0] = histo->GetXaxis();
00635 fAxis[1] = histo->GetYaxis();
00636 fAxis[2] = histo->GetZaxis();
00637
00638
00639
00640
00641 Double_t sx = (bbox.XMax() - bbox.XMin()) / (fAxis[0]->GetXmax() - fAxis[0]->GetXmin());
00642 Double_t sy = (bbox.YMax() - bbox.YMin()) / (fAxis[1]->GetXmax() - fAxis[1]->GetXmin());
00643 Double_t sz = (bbox.ZMax() - bbox.ZMin()) / (fAxis[2]->GetXmax() - fAxis[2]->GetXmin());
00644
00645
00646 glPushMatrix();
00647 glScaled(sx, sy, sz);
00648 SetAxis3DTitlePos(rnrCtx);
00649 DrawAxis3D(rnrCtx);
00650 glPopMatrix();
00651 }