37 double aAngle,
double aSize,
38 const std::string& aString,
76 TAxis_kTickPlus = (1<<(9)),
77 TAxis_kTickMinus = (1<<(10)),
78 TAxis_kAxisRange = (1<<(11)),
79 TAxis_kCenterTitle = (1<<(12)),
80 TAxis_kCenterLabels = (1<<(14)),
81 TAxis_kRotateTitle = (1<<(15)),
82 TAxis_kPalette = (1<<(16)),
83 TAxis_kNoExponent = (1<<(17)),
84 TAxis_kLabelsHori = (1<<(18)),
85 TAxis_kLabelsVert = (1<<(19)),
86 TAxis_kLabelsDown = (1<<(20)),
87 TAxis_kLabelsUp = (1<<(21)),
88 TAxis_kIsInteger = (1<<(22)),
89 TAxis_kMoreLogLabels = (1<<(23)),
90 TAxis_kDecimals = (1<<(11))
94 kIsOnHeap = 0x01000000,
95 kNotDeleted = 0x02000000,
100 static int GetTextFont() {
return 132;}
102 static double TMath_ATan2(
double y,
double x) {
103 if (x != 0) return ::atan2(y, x);
104 if (y == 0)
return 0;
110 static int TMath_Abs(
int d) {
return (d >= 0) ? d : -d; }
113 static double TMath_Abs(
double d) {
return (d >= 0) ? d : -d; }
115 static void TGaxis_Rotate(
116 double X,
double Y,
double CFI,
double SFI
117 ,
double XT,
double YT,
double &U,
double &V)
129 ,fLabelOffset(0.005F)
138 axis(
const axis& a_from):m_out(a_from.m_out){}
139 axis& operator=(
const axis&){
return *
this;}
145 bool testBit(
unsigned int f) {
146 return (
bool) ((fBits & f) != 0);
149 static void TGaxis_LabelsLimits(std::ostream& a_out,
const char *label,
150 int &first,
int &last) {
151 last = int(::strlen(label))-1;
152 for (
int i=0; i<=last; i++) {
153 if (::strchr(
"1234567890-+.", label[i]) ) { first = i;
return; }
155 out_error(a_out,
"LabelsLimits",
"attempt to draw a blank label");
157 static void SETOPT(
const std::string& aCHOPT,
char aChar,
int& aOpt) {
158 aOpt = aCHOPT.find(aChar)!=std::string::npos?1:0;
162 void paint(
double xmin,
double ymin,
163 double xmax,
double ymax,
164 double& wmin,
double& wmax,
165 int& ndiv,
const std::string& aCHOPT,
166 double gridlength,
bool drawGridOnly,
167 std::vector<float>& aLinesAxis,
168 std::vector<float>& aLinesGrid,
169 std::vector<_text>& aTexts){
309 double alfa, beta, ratio1, ratio2, grid_side;
310 double axis_lengthN = 0;
311 double axis_length0 = 0;
312 double axis_length1 = 0;
314 double phil, phi, sinphi, cosphi, asinphi, acosphi;
315 double BinLow, BinLow2, BinLow3;
316 double BinHigh, BinHigh2, BinHigh3;
317 double BinWidth, BinWidth2, BinWidth3;
318 double xpl1, xpl2, ypl1, ypl2;
320 double Xtick0, Xtick1, DXtick=0;
321 double Ytick, Ytick0, Ytick1;
322 double Wlabel, DWlabel;
323 double Xlabel, Ylabel;
325 double X0, X1, Y0, Y1, XX0, XX1, YY0, YY1;
326 XX0 = XX1 = YY0 = YY1 = 0;
327 double Xxmin, Xxmax, Yymin, Yymax;
328 Xxmin = Xxmax = Yymin = Yymax = 0;
329 double XLside,XMside;
334 int i, j, k, l, decade, ltick;
336 int IF1, IF2, NA, NF, NCH;
337 int OptionLog,OptionBlank,OptionVert,OptionPlus,OptionMinus;
338 int OptionUnlab,OptionPara;
339 int OptionDown,OptionRight,OptionLeft,OptionCent,OptionEqual;
340 int OptionDecimals=0,OptionDot;
341 int OptionY,OptionText,OptionGrid,OptionSize,OptionNoopt;
342 int OptionInt,OptionM,OptionUp,OptionX;
352 double rangeOffset = 0;
354 double epsilon = 1e-5;
355 const double kPI =
pi();
356 double textSize = 0.05;
357 short textAlign = 11;
376 bool noExponent = testBit(TAxis_kNoExponent);
379 bool MoreLogLabels = testBit(TAxis_kMoreLogLabels);
390 SETOPT(aCHOPT,
'G',OptionLog);
391 SETOPT(aCHOPT,
'B',OptionBlank);
392 SETOPT(aCHOPT,
'V',OptionVert);
393 SETOPT(aCHOPT,
'+',OptionPlus);
394 SETOPT(aCHOPT,
'-',OptionMinus);
395 SETOPT(aCHOPT,
'U',OptionUnlab);
396 SETOPT(aCHOPT,
'P',OptionPara);
397 SETOPT(aCHOPT,
'O',OptionDown);
398 SETOPT(aCHOPT,
'R',OptionRight);
399 SETOPT(aCHOPT,
'L',OptionLeft);
400 SETOPT(aCHOPT,
'C',OptionCent);
401 SETOPT(aCHOPT,
'=',OptionEqual);
402 SETOPT(aCHOPT,
'Y',OptionY);
403 SETOPT(aCHOPT,
'T',OptionText);
404 SETOPT(aCHOPT,
'W',OptionGrid);
405 SETOPT(aCHOPT,
'S',OptionSize);
406 SETOPT(aCHOPT,
'N',OptionNoopt);
407 SETOPT(aCHOPT,
'I',OptionInt);
408 SETOPT(aCHOPT,
'M',OptionM);
409 SETOPT(aCHOPT,
'0',OptionUp);
410 SETOPT(aCHOPT,
'X',OptionX);
411 SETOPT(aCHOPT,
't',OptionTime);
412 SETOPT(aCHOPT,
'.',OptionDot);
414 if (testBit(TAxis_kTickPlus)) OptionPlus = 2;
415 if (testBit(TAxis_kTickMinus)) OptionMinus = 2;
416 if (testBit(TAxis_kCenterLabels)) OptionM = 1;
417 if (testBit(TAxis_kDecimals)) OptionDecimals = 1;
429 if (gridlength == 0) gridlength = 0.8;
447 std::string timeformat;
448 std::string::size_type IdF = fTimeFormat.find(
"%F");
449 if (IdF!=std::string::npos) {
450 timeformat = fTimeFormat.substr(0,IdF);
452 timeformat = fTimeFormat;
457 double timeoffset = 0;
459 if (IdF!=std::string::npos) {
460 int LnF = int(fTimeFormat.size());
461 std::string stringtimeoffset = fTimeFormat.substr(IdF+2,LnF-(IdF+2));
462 int yy, mm, dd, hh, mi, ss;
463 if (::sscanf(stringtimeoffset.c_str(),
464 "%d-%d-%d %d:%d:%d", &yy, &mm, &dd, &hh, &mi, &ss) == 6) {
467 time_t timeoffsettest;
468 tp.tm_year = yy-1900;
475 timeoffset = double(mktime(&tp));
477 timeoffsettest = (time_t)((
long)timeoffset);
478 tptest = gmtime(&timeoffsettest);
479 timeoffset += timeoffsettest - mktime(tptest);
481 std::string::size_type Ids = stringtimeoffset.find(
"s");
482 if (Ids != std::string::npos) {
484 size_t Lns = stringtimeoffset.size();
485 std::string sdp = stringtimeoffset.substr(Ids+1,Lns-(Ids+1));
486 ::sscanf(sdp.c_str(),
"%g",&dp);
490 if (stringtimeoffset.find(
"GMT")!=std::string::npos)
493 out_error(m_out,
"PaintAxis",
"Time offset has not the right format");
496 out_error(m_out,
"PaintAxis",
"%%F not found in fTimeFormat.");
499 wmin += timeoffset - (int)(timeoffset);
500 wmax += timeoffset - (int)(timeoffset);
504 time_t timetp = (time_t)((
long)(timeoffset));
505 double range = wmax - wmin;
507 if (range>60) rangeBase = 60*20;
508 if (range>3600) rangeBase = 3600*20;
509 if (range>86400) rangeBase = 86400*20;
510 if (range>2419200) rangeBase = 31556736;
511 rangeOffset = (double) ((
long)(timeoffset)%rangeBase);
512 if (range>31536000) {
513 tp0 = gmtime(&timetp);
520 rangeBase = long(timetp-mktime(tp0));
521 rangeOffset = (double) (rangeBase);
529 int N2A = (ndiv%10000 - N1A)/100;
530 int N3A = ndiv/10000;
531 int NN3 = mx<int>(N3A,1);
532 int NN2 = mx<int>(N2A,1)*NN3;
533 int NN1 = mx<int>(N1A,1)*NN2+1;
542 if (wmin == wmax || ndiv == 0 || N1A <= 1 || OptionLog) {
548 if ( (wmax-wmin) < 1 && OptionInt) {
549 out_error(m_out,
"PaintAxis",
"option I not available");
553 if (!OptionNoopt || OptionInt ) {
560 optimizeLimits(wmin,wmax,N1A,
561 BinLow,BinHigh,nbins,BinWidth,
564 if (BinLow !=
double(
int(BinLow)) ||
565 BinWidth !=
double(
int(BinWidth))) {
566 adjustBinSize(wmin,wmax,N1A,BinLow,BinHigh,nbins,BinWidth);
569 if ((wmin-BinLow) > epsilon) { BinLow += BinWidth; nbins--; }
570 if ((BinHigh-wmax) > epsilon) { BinHigh -= BinWidth; nbins--; }
572 double rtyw = (ymax-ymin)/(wmax-wmin);
575 Yymin = rtyw*(BinLow-wmin) + ymin;
576 Yymax = rtyw*(BinHigh-wmin) + ymin;
578 double rtxw = (xmax-xmin)/(wmax-wmin);
579 Xxmin = rtxw*(BinLow-wmin) + xmin;
580 Xxmax = rtxw*(BinHigh-wmin) + xmin;
585 alfa = (ymax-ymin)/(xmax-xmin);
586 beta = (ymin*xmax-ymax*xmin)/(xmax-xmin);
587 Yymin = alfa*Xxmin + beta;
588 Yymax = alfa*Xxmax + beta;
603 if (!OptionNoopt && N2A > 1 && BinWidth > 0) {
604 optimizeLimits(wmin,wmin+BinWidth,N2A,
605 BinLow2,BinHigh2,NB2,BinWidth2,
611 if (!OptionNoopt && N3A > 1 && BinWidth2 > 0) {
612 optimizeLimits(BinLow2,BinLow2+BinWidth2,N3A,
613 BinLow3,BinHigh3,NB3,BinWidth3,
619 NN3 = mx<int>(NB3,1);
620 NN2 = mx<int>(NB2,1)*NN3;
621 NN1 = mx<int>(N1A,1)*NN2+1;
628 ratio1 = 1/(RWxmax-RWxmin);
629 ratio2 = 1/(RWymax-RWymin);
630 X0 = ratio1*(xmin-RWxmin);
631 X1 = ratio1*(xmax-RWxmin);
632 Y0 = ratio2*(ymin-RWymin);
633 Y1 = ratio2*(ymax-RWymin);
634 if (!OptionNoopt || OptionInt ) {
635 XX0 = ratio1*(Xxmin-RWxmin);
636 XX1 = ratio1*(Xxmax-RWxmin);
637 YY0 = ratio2*(Yymin-RWymin);
638 YY1 = ratio2*(Yymax-RWymin);
642 if ((X0 == X1) && (Y0 == Y1)) {
643 out_error(m_out,
"PaintAxis",
"length of axis is 0");
672 double axis_length = ::sqrt((X1-X0)*(X1-X0)+(Y1-Y0)*(Y1-Y0));
673 if (axis_length == 0) {
674 out_error(m_out,
"PaintAxis",
"length of axis is 0");
679 if (!OptionNoopt || OptionInt) {
680 axis_lengthN = ::sqrt((XX1-XX0)*(XX1-XX0)+(YY1-YY0)*(YY1-YY0));
681 axis_length0 = ::sqrt((XX0-X0)*(XX0-X0)+(YY0-Y0)*(YY0-Y0));
682 axis_length1 = ::sqrt((X1-XX1)*(X1-XX1)+(Y1-YY1)*(Y1-YY1));
683 if (axis_lengthN < epsilon) {
692 wmin += timeoffset - (int)(timeoffset) + rangeOffset;
693 wmax += timeoffset - (int)(timeoffset) + rangeOffset;
703 phi = TMath_ATan2((Y1-Y0),(X1-X0));
708 if (X0 < X1) phil = TMath_ATan2(
double(py0-py1),
double(px1-px0));
709 else phil = TMath_ATan2(
double(py1-py0),
double(px0-px1));
713 acosphi = TMath_Abs(cosphi);
714 asinphi = TMath_Abs(sinphi);
715 if (acosphi <= epsilon) { acosphi = 0; cosphi = 0; }
716 if (asinphi <= epsilon) { asinphi = 0; sinphi = 0; }
725 if (X0 == X1 && Y1 > Y0) Mside = -1;
726 if (OptionPlus) Mside = 1;
727 if (OptionMinus) Mside = -1;
728 if (OptionPlus && OptionMinus) Mside = 0;
731 if (OptionEqual) Lside = Mside;
732 if (OptionPlus && OptionMinus) {
734 if (OptionEqual) Lside=1;
740 if(XMside >= 0) tick_side = 1;
744 if (OptionSize) atick[0] = tick_side*axis_length*fTickSize;
745 else atick[0] = tick_side*axis_length*0.03;
747 atick[1] = 0.5*atick[0];
748 atick[2] = 0.5*atick[1];
751 if ((X0 == X1) && (Y1 > Y0)) grid_side =-1;
773 aLinesAxis.push_back((
float)xpl1);
774 aLinesAxis.push_back((
float)ypl1);
775 aLinesAxis.push_back((
float)xpl2);
776 aLinesAxis.push_back((
float)ypl2);
782 if (ndiv == 0)
return;
784 out_error(m_out,
"PaintAxis",
"wmin (%f) == wmax (%f)", wmin, wmax);
789 if (!drawGridOnly && fTitle.size()) {
790 textSize = fTitleSize;
791 charheight = fTitleSize;
792 if ((GetTextFont() % 10) > 2) {
795 double toffset = fTitleOffset;
796 if (toffset < 0.1) toffset = 1;
797 if (X1 == X0) Ylabel = XLside*1.6*charheight*toffset;
798 else Ylabel = XLside*1.3*charheight*toffset;
799 if (Y1 == Y0) Ylabel = XLside*1.6*charheight*toffset;
801 if (testBit(TAxis_kCenterTitle)) axispos = 0.5*axis_length;
802 else axispos = axis_length;
803 if (testBit(TAxis_kRotateTitle)) {
805 if (testBit(TAxis_kCenterTitle)) textAlign = 22;
807 TGaxis_Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1);
809 if (testBit(TAxis_kCenterTitle)) textAlign = 22;
811 TGaxis_Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1);
813 out_error(m_out,
"PaintAxis",
"debug : texts : dummy : 000\n");
814 aTexts.push_back(
_text(xpl1,ypl1,
815 phil=(kPI+phil)*180/kPI,
820 if (testBit(TAxis_kCenterTitle)) textAlign = 22;
822 TGaxis_Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1);
824 if (testBit(TAxis_kCenterTitle)) textAlign = 22;
826 TGaxis_Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1);
828 aTexts.push_back(
_text(xpl1,ypl1,
829 phil*180/kPI,fTitleSize,
840 charheight = fLabelSize;
841 if (OptionText) charheight *= 0.66666;
844 textSize = charheight;
846 if (fLabelFont%10 > 2) {
849 if (!OptionUp && !OptionDown && !OptionY) {
850 if (!drawGridOnly && OptionText && ((ymin == ymax) || (xmin == xmax))) {
855 out_error(m_out,
"PaintAxis",
"debug : FIXME : 000\n");
920 if (X0 == X1) Xalign = 3;
921 if (Y0 != Y1) Yalign = 2;
922 if (OptionCent) Xalign = 2;
923 if (OptionRight) Xalign = 3;
924 if (OptionLeft) Xalign = 1;
925 if (TMath_Abs(cosphi) > 0.9) {
928 if (cosphi*sinphi > 0) Xalign = 1;
929 if (cosphi*sinphi < 0) Xalign = 3;
931 textAlign = 10*Xalign+Yalign;
936 if (OptionPlus && !OptionMinus) {
937 if (OptionEqual) Ylabel = fLabelOffset/2 + atick[0];
938 else Ylabel = -fLabelOffset;
940 Ylabel = fLabelOffset;
941 if (Lside < 0) Ylabel += atick[0];
943 }
else if (Y0 == Y1) {
944 if (OptionMinus && !OptionPlus) {
945 Ylabel = fLabelOffset+0.5*fLabelSize;
946 Ylabel += TMath_Abs(atick[0]);
948 Ylabel = -fLabelOffset;
949 if (Mside <= 0) Ylabel -= TMath_Abs(atick[0]);
951 if (OptionLog) Ylabel -= 0.5*charheight;
953 if (Mside+Lside >= 0) Ylabel = fLabelOffset;
954 else Ylabel = -fLabelOffset;
956 if (OptionText) Ylabel /= 2;
969 if (OptionNoopt && !OptionInt) DXtick=axis_length/double(Nticks-1);
970 else DXtick=axis_lengthN/double(Nticks-1);
972 for (k=0;k<Nticks; k++) {
974 if (k%NN3 == 0) ltick = 1;
975 if (k%NN2 == 0) ltick = 0;
981 Xtick = double(k)*DXtick;
984 if (!Mside) Ytick -= atick[ltick];
985 if ( OptionNoopt && !OptionInt) {
986 TGaxis_Rotate(Xtick,Ytick,cosphi,sinphi,X0,Y0,xpl2,ypl2);
987 TGaxis_Rotate(Xtick,atick[ltick],cosphi,sinphi,X0,Y0,xpl1,ypl1);
990 TGaxis_Rotate(Xtick,Ytick,cosphi,sinphi,XX0,YY0,xpl2,ypl2);
991 TGaxis_Rotate(Xtick,atick[ltick],cosphi,sinphi,XX0,YY0,xpl1,ypl1);
994 if ((X0 != X1) && (Y0 != Y1)) {
997 if (cosphi > 0) ypl1 = ypl2 + atick[ltick];
998 else ypl1 = ypl2 - atick[ltick];
1001 xpl1 = 0.5*(xpl1 + xpl2);
1003 ypl1 = 0.5*(ypl1 + ypl2) + atick[ltick];
1004 ypl2 = 0.5*(ypl1 + ypl2) - atick[ltick];
1008 if (!drawGridOnly) {
1009 aLinesAxis.push_back((
float)xpl1);
1010 aLinesAxis.push_back((
float)ypl1);
1011 aLinesAxis.push_back((
float)xpl2);
1012 aLinesAxis.push_back((
float)ypl2);
1017 if (OptionNoopt && !OptionInt) {
1018 TGaxis_Rotate(Xtick,0,cosphi,sinphi,X0,Y0 ,xpl2,ypl2);
1020 (Xtick,grid_side*gridlength,cosphi,sinphi,X0,Y0,
1023 TGaxis_Rotate(Xtick,0,cosphi ,sinphi,XX0,YY0,xpl2,ypl2);
1025 (Xtick,grid_side*gridlength ,cosphi,sinphi,XX0,YY0,
1028 aLinesGrid.push_back((
float)xpl1);
1029 aLinesGrid.push_back((
float)ypl1);
1030 aLinesGrid.push_back((
float)xpl2);
1031 aLinesGrid.push_back((
float)ypl2);
1038 if ((!OptionNoopt || OptionInt) && axis_length0) {
1041 Nticks0 = int(axis_length0/DXtick);
1042 if (Nticks0 > 1000) Nticks0 = 1000;
1043 for (k=0; k<=Nticks0; k++) {
1045 if (k%NN3 == 0) ltick = 1;
1046 if (k%NN2 == 0) ltick = 0;
1048 if (!Mside) Ytick0 -= atick[ltick];
1053 TGaxis_Rotate(Xtick0,Ytick0,cosphi,sinphi,XX0,YY0 ,xpl2,ypl2);
1054 TGaxis_Rotate(Xtick0,atick[ltick],cosphi,sinphi,XX0,YY0 ,xpl1,ypl1);
1056 if ((X0 != X1) && (Y0 != Y1)) {
1059 if (cosphi > 0) ypl1 = ypl2 + atick[ltick];
1060 else ypl1 = ypl2 - atick[ltick];
1063 xpl1 = 0.5*(xpl1 + xpl2);
1065 ypl1 = 0.5*(ypl1 + ypl2) + atick[ltick];
1066 ypl2 = 0.5*(ypl1 + ypl2) - atick[ltick];
1071 aLinesAxis.push_back((
float)xpl1);
1072 aLinesAxis.push_back((
float)ypl1);
1073 aLinesAxis.push_back((
float)xpl2);
1074 aLinesAxis.push_back((
float)ypl2);
1079 TGaxis_Rotate(Xtick0,0,cosphi,sinphi,XX0,YY0,xpl2,ypl2);
1081 (Xtick0,grid_side*gridlength,cosphi,sinphi,XX0,YY0,
1083 aLinesGrid.push_back((
float)xpl1);
1084 aLinesGrid.push_back((
float)ypl1);
1085 aLinesGrid.push_back((
float)xpl2);
1086 aLinesGrid.push_back((
float)ypl2);
1093 if ((!OptionNoopt || OptionInt) && axis_length1) {
1096 Nticks1 = int(axis_length1/DXtick);
1097 if (Nticks1 > 1000) Nticks1 = 1000;
1098 for (k=0; k<=Nticks1; k++) {
1100 if (k%NN3 == 0) ltick = 1;
1101 if (k%NN2 == 0) ltick = 0;
1103 if (!Mside) Ytick1 -= atick[ltick];
1108 TGaxis_Rotate(Xtick1,Ytick1,cosphi,sinphi,XX0,YY0 ,xpl2,ypl2);
1109 TGaxis_Rotate(Xtick1,atick[ltick],cosphi,sinphi,XX0,YY0 ,xpl1,ypl1);
1111 if ((X0 != X1) && (Y0 != Y1)) {
1114 if (cosphi > 0) ypl1 = ypl2 + atick[ltick];
1115 else ypl1 = ypl2 - atick[ltick];
1118 xpl1 = 0.5*(xpl1 + xpl2);
1120 ypl1 = 0.5*(ypl1 + ypl2) + atick[ltick];
1121 ypl2 = 0.5*(ypl1 + ypl2) - atick[ltick];
1126 aLinesAxis.push_back((
float)xpl1);
1127 aLinesAxis.push_back((
float)ypl1);
1128 aLinesAxis.push_back((
float)xpl2);
1129 aLinesAxis.push_back((
float)ypl2);
1134 TGaxis_Rotate(Xtick1,0,cosphi,sinphi,XX0,YY0 ,xpl2,ypl2);
1136 (Xtick1,grid_side*gridlength,cosphi,sinphi,XX0,YY0,
1138 aLinesGrid.push_back((
float)xpl1);
1139 aLinesGrid.push_back((
float)ypl1);
1140 aLinesGrid.push_back((
float)xpl2);
1141 aLinesGrid.push_back((
float)ypl2);
1152 if (!drawGridOnly && !OptionUnlab) {
1156 if ((wmin == wmax) || (ndiv == 0)) {
1157 out_error(m_out,
"PaintAxis",
"wmin (%f) == wmax (%f), or ndiv == 0", wmin, wmax);
1161 DWlabel = (wmax-wmin)/
double(N1A);
1162 if (OptionNoopt && !OptionInt) DXlabel = axis_length/double(N1A);
1163 else DXlabel = axis_lengthN/double(N1A);
1168 if (!OptionText && !OptionTime) {
1175 bool FLEXPO =
false;
1176 bool FLEXNE =
false;
1177 WW = mx<double>(TMath_Abs(wmin),TMath_Abs(wmax));
1183 double xmicros = 0.00099;
1184 if (maxDigits) xmicros = ::pow(10.,-maxDigits);
1185 if (!noExponent && (TMath_Abs(wmax-wmin)/
double(N1A)) < xmicros) {
1186 AF = ::log10(WW) + epsilon;
1190 int IEXE = TMath_Abs(NEXE);
1191 if (IEXE%3 == 1) IEXE += 2;
1192 else if(IEXE%3 == 2) IEXE += 1;
1193 if (NEXE < 0) NEXE = -IEXE;
1195 Wlabel = Wlabel*::pow(10.,IEXE);
1196 DWlabel = DWlabel*::pow(10.,IEXE);
1202 if (WW >= 1) AF = ::log10(WW);
1203 else AF = ::log10(WW*0.0001);
1206 if (!noExponent && NF > maxDigits) FLEXPO =
true;
1207 if (!noExponent && NF < -maxDigits) FLEXNE =
true;
1218 if (NEXE%3 == 0 && WW <= ::pow(10.,maxDigits-1))
break;
1224 RNE = 1/::pow(10.,maxDigits-2);
1230 if (NEXE%3 == 0 && WW >= RNE)
break;
1235 for (i=maxDigits-1; i>0; i--) {
1236 if (TMath_Abs(WW) < ::pow(10.,i)) NA = maxDigits-i;
1240 double wdyn = TMath_Abs((wmax-wmin)/ndyn);
1241 if (wdyn <= 0.999 && NA < maxDigits-2) {
1249 IF1 = mx<int>(NF+NA,maxDigits)+1;
1251 if (mn<double>(wmin,wmax) < 0)IF1 = IF1+1;
1252 IF1 = mn<int>(IF1,32);
1255 while (DWlabel < ::pow(10.,-IF2)) {
1260 if (IF1 > 14) IF1=14;
1261 if (IF2 > 14) IF2=14;
1262 if(IF2)
snpf(CHCODED,
sizeof(CHCODED),
"%%%d.%df",IF1,IF2);
1263 else snpf(CHCODED,
sizeof(CHCODED),
"%%%d.%df",IF1+1,1);
1268 snpf(CHTEMP,
sizeof(CHTEMP),
"%g",DWlabel);
1270 size_t ndecimals = 0;
1271 if (OptionDecimals) {
1272 char *dot = ::strchr(CHTEMP,
'.');
1273 if (dot) ndecimals = CHTEMP + ::strlen(CHTEMP) -dot;
1276 if (OptionM) Nlabels = N1A-1;
1278 double wTimeIni = Wlabel;
1279 for ( k=0; k<=Nlabels; k++) {
1288 if (OptionM) Xlabel += 0.5*DXlabel;
1290 if (!OptionText && !OptionTime) {
1291 snpf(LABEL,
sizeof(LABEL),&CHCODED[0],Wlabel);
1295 TGaxis_LabelsLimits(m_out,LABEL,first,last);
1297 if (LABEL[first] ==
'.') {
1298 ::strcpy(CHTEMP,
"0");
1299 ::strcat(CHTEMP, &LABEL[first]);
1300 ::strcpy(LABEL, CHTEMP);
1301 first = 1; last = int(::strlen(LABEL));
1303 if (LABEL[first] ==
'-' && LABEL[first+1] ==
'.') {
1304 ::strcpy(CHTEMP,
"-0");
1305 ::strcat(CHTEMP, &LABEL[first+1]);
1306 ::strcpy(LABEL, CHTEMP);
1307 first = 1; last = int(::strlen(LABEL));
1312 char *adot = ::strchr(LABEL,
'.');
1313 if (adot) adot[ndecimals] = 0;
1315 while (LABEL[last] ==
'0') { LABEL[last] = 0; last--;}
1318 if (LABEL[last] ==
'.') {
1319 if (!OptionDot) { LABEL[last] = 0; last--;}
1326 double timed = Wlabel + (int)(timeoffset) - rangeOffset;
1327 time_t timelabel = (time_t)((
long)(timed));
1329 if (OptionTime == 1) {
1330 utctis = localtime(&timelabel);
1332 utctis = gmtime(&timelabel);
1334 std::string timeformattmp;
1335 if (timeformat.size() < 220) timeformattmp = timeformat;
1336 else timeformattmp =
"#splitline{Format}{too long}";
1342 snpf(LABEL,
sizeof(LABEL),
"%%S%7.5f",modf(timed,&tmpdb));
1343 tmplast = ::strlen(LABEL)-1;
1346 while (LABEL[tmplast] ==
'0') {
1347 LABEL[tmplast] = 0; tmplast--;
1356 ::strftime(LABEL,256,timeformattmp.c_str(),utctis);
1357 ::strcpy(CHTEMP,&LABEL[0]);
1358 first = 0; last=int(::strlen(LABEL))-1;
1359 Wlabel = wTimeIni + (k+1)*DWlabel;
1364 if (OptionNoopt && !OptionInt)
1365 TGaxis_Rotate (Xlabel,Ylabel,cosphi,sinphi,X0,Y0,XX,YY);
1366 else TGaxis_Rotate (Xlabel,Ylabel,cosphi,sinphi,XX0,YY0,XX,YY);
1367 if (Y0 == Y1 && !OptionDown && !OptionUp) {
1368 YY -= 0.80*charheight;
1371 if (X0 != X1 && Y0 != Y1) {
1372 if (OptionNoopt && !OptionInt)
1373 TGaxis_Rotate (Xlabel,0,cosphi,sinphi,X0,Y0,XX,YY);
1374 else TGaxis_Rotate (Xlabel,0,cosphi,sinphi,XX0,YY0,XX,YY);
1375 if (cosphi > 0 ) YY += Ylabel;
1376 if (cosphi < 0 ) YY -= Ylabel;
1379 if (!OptionY || (X0 == X1)) {
1381 if (first > last) ::strcpy(CHTEMP,
" ");
1382 else ::strcpy(CHTEMP, &LABEL[first]);
1383 aTexts.push_back(
_text(XX,YY,
1388 if (OptionText == 1) {
1389 out_error(m_out,
"PaintAxis",
"debug : texts : dummy : 006\n");
1403 if (!OptionText) LNLEN = last-first+1;
1406 if (k+1 > NHILAB) LNLEN = 0;
1408 for ( l=1; l<=LNLEN; l++) {
1409 if (!OptionText) *CHTEMP = LABEL[first+l-2];
1411 if (LNLEN == 0) ::strcpy(CHTEMP,
" ");
1412 else ::strcpy(CHTEMP,
"1");
1414 aTexts.push_back(
_text(XX,YY,
1417 YY -= charheight*1.3;
1424 if (FLEXE && !OptionText && NEXE) {
1426 snpf(LABEL,
sizeof(LABEL),
1428 double Xfactor, Yfactor;
1429 if (X0 != X1) { Xfactor = X1-X0+0.1*charheight; Yfactor = 0; }
1430 else { Xfactor = Y1-Y0+0.1*charheight; Yfactor = 0; }
1431 TGaxis_Rotate (Xfactor,Yfactor,cosphi,sinphi,X0,Y0,XX,YY);
1433 aTexts.push_back(
_text(XX,YY,
1444 if (OptionLog && ndiv) {
1445 unsigned int xi1=0,xi2 = 0,wi = 0,yi1=0,yi2,hi = 0;
1446 bool firstintlab =
true, overlap =
false;
1447 if ((wmin == wmax) || (ndiv == 0)) {
1448 out_error(m_out,
"PaintAxis",
"wmin (%f) == wmax (%f), or ndiv == 0", wmin, wmax);
1452 out_error(m_out,
"PaintAxis",
"negative logarithmic axis");
1456 out_error(m_out,
"PaintAxis",
"negative logarithmic axis");
1459 double XMNLOG = ::log10(wmin);
1460 if (XMNLOG > 0) XMNLOG += 1.E-6;
1461 else XMNLOG -= 1.E-6;
1463 double X11 = axis_length;
1464 double H2 = ::log10(wmax);
1466 if (H2 > 0) H2 += 1.E-6;
1468 int IH1 = int(XMNLOG);
1469 int IH2 = 1+int(H2);
1470 int NBININ = IH2-IH1+1;
1471 double AXMUL = (X11-X00)/(H2SAV-XMNLOG);
1475 int labelnumber = IH1;
1476 if ( XMNLOG > 0 && (XMNLOG-
double(IH1) > 0) ) labelnumber++;
1477 for (j=1; j<=NBININ; j++) {
1480 firstintlab =
true, overlap =
false;
1482 if (X0 == X1 && j == 1) Ylabel += charheight*0.33;
1483 if (Y0 == Y1 && j == 1) Ylabel -= charheight*0.65;
1484 double Xone = X00+AXMUL*(double(decade)-XMNLOG);
1487 if (X00 > Xone)
goto L160;
1488 if (Xone > X11)
break;
1491 if (!Mside) Y -= atick[0];
1492 TGaxis_Rotate(Xone,Y,cosphi,sinphi,X0,Y0,xpl2,ypl2);
1493 TGaxis_Rotate(Xtwo,atick[0],cosphi,sinphi,X0,Y0,xpl1,ypl1);
1495 if ((X0 != X1) && (Y0 != Y1)) {
1498 if (cosphi > 0) ypl1 = ypl2 + atick[0];
1499 else ypl1 = ypl2 - atick[0];
1502 xpl1 = 0.5*(xpl1 + xpl2);
1504 ypl1 = 0.5*(ypl1 + ypl2) + atick[0];
1505 ypl2 = 0.5*(ypl1 + ypl2) - atick[0];
1509 if (!drawGridOnly) {
1510 aLinesAxis.push_back((
float)xpl1);
1511 aLinesAxis.push_back((
float)ypl1);
1512 aLinesAxis.push_back((
float)xpl2);
1513 aLinesAxis.push_back((
float)ypl2);
1517 TGaxis_Rotate(Xone,0,cosphi,sinphi,X0,Y0,xpl2,ypl2);
1518 TGaxis_Rotate(Xone,grid_side*gridlength,cosphi,sinphi,X0,Y0,
1520 aLinesGrid.push_back((
float)xpl1);
1521 aLinesGrid.push_back((
float)ypl1);
1522 aLinesGrid.push_back((
float)xpl2);
1523 aLinesGrid.push_back((
float)ypl2);
1526 if (!drawGridOnly && !OptionUnlab) {
1530 double rlab = ::pow(10.,labelnumber);
1531 snpf(LABEL,
sizeof(LABEL),
"%f", rlab);
1532 TGaxis_LabelsLimits(m_out,LABEL,first,last);
1533 while (last > first) {
1534 if (LABEL[last] !=
'0')
break;
1538 if (LABEL[last] ==
'.') {LABEL[last] = 0; last--;}
1540 snpf(LABEL,
sizeof(LABEL),
"%d", labelnumber);
1541 TGaxis_LabelsLimits(m_out,LABEL,first,last);
1543 TGaxis_Rotate (Xone,Ylabel,cosphi,sinphi,X0,Y0,XX,YY);
1544 if ((X0 == X1) && !OptionPara) {
1547 if (labelnumber == 0) NCH=1;
1549 XX += NCH*charheight;
1551 if (labelnumber >= 0) XX += 0.25*charheight;
1552 else XX += 0.50*charheight;
1555 XX += 0.25*charheight;
1557 if ((Y0 == Y1) && !OptionDown && !OptionUp) {
1558 if (noExponent) YY += 0.33*charheight;
1560 if (N1A == 0)
return;
1561 int KMOD = NBININ/N1A;
1562 if (KMOD == 0) KMOD=1000000;
1563 if ((NBININ <= N1A) || (j == 1) || (j == NBININ) || ((NBININ > N1A)
1564 && (j%KMOD == 0))) {
1565 if (labelnumber == 0) {
1566 aTexts.push_back(
_text(XX,YY,
1569 }
else if (labelnumber == 1) {
1570 aTexts.push_back(
_text(XX,YY,
1575 out_error(m_out,
"PaintAxis",
"debug : texts : FIXME : 003\n");
1580 snpf(CHTEMP,
sizeof(CHTEMP),
1581 "10^%d?", labelnumber);
1582 aTexts.push_back(
_text(XX,YY,
1591 for (k=2;k<10;k++) {
1595 Xone = X00+AXMUL*(::log10(
double(k))+double(decade)-XMNLOG);
1596 if (X00 > Xone)
continue;
1597 if (Xone > X11)
goto L200;
1599 if (!Mside) Y -= atick[1];
1601 TGaxis_Rotate(Xone,Y,cosphi,sinphi,X0,Y0,xpl2,ypl2);
1602 TGaxis_Rotate(Xtwo,atick[1],cosphi,sinphi,X0,Y0,xpl1,ypl1);
1604 if ((X0 != X1) && (Y0 != Y1)) {
1607 if (cosphi > 0) ypl1 = ypl2 + atick[1];
1608 else ypl1 = ypl2 - atick[1];
1611 xpl1 = 0.5*(xpl1+xpl2);
1613 ypl1 = 0.5*(ypl1+ypl2) + atick[1];
1614 ypl2 = 0.5*(ypl1+ypl2) - atick[1];
1619 if ((NBININ <= IDN) || ((NBININ > IDN) && (k == 5))) {
1621 aLinesAxis.push_back((
float)xpl1);
1622 aLinesAxis.push_back((
float)ypl1);
1623 aLinesAxis.push_back((
float)xpl2);
1624 aLinesAxis.push_back((
float)ypl2);
1629 if (MoreLogLabels && !OptionUnlab &&
1630 !drawGridOnly && !overlap) {
1632 double rlab = double(k)*::pow(10.,labelnumber-1);
1633 snpf(CHTEMP,
sizeof(CHTEMP),
"%g", rlab);
1635 if (labelnumber-1 == 0) {
1636 snpf(CHTEMP,
sizeof(CHTEMP),
"%d", k);
1637 }
else if (labelnumber-1 == 1) {
1638 snpf(CHTEMP,
sizeof(CHTEMP),
"%d", 10*k);
1642 snpf(CHTEMP,
sizeof(CHTEMP),
1643 "%dx10^%d!",k,labelnumber-1);
1646 TGaxis_Rotate (Xone,Ylabel,cosphi,sinphi,X0,Y0,XX,YY);
1647 if ((Y0 == Y1) && !OptionDown && !OptionUp) {
1648 if (noExponent) YY += 0.33*charheight;
1650 if (X0 == X1) XX += 0.25*charheight;
1652 if ((X0 != X1) && (Y0 != Y1)) {
1653 TGaxis_Rotate(Xone,Ylabel,cosphi,sinphi,X0,Y0,XX,YY);
1654 if (cosphi > 0) YY += Ylabel;
1665 firstintlab =
false;
1666 out_error(m_out,
"PaintAxis",
"debug : texts : dummy : 010\n");
1667 aTexts.push_back(
_text(u,v,
1673 if ((X0 == X1 && yi1-hi <= yi2) || (Y0 == Y1 && xi1+wi >= xi2)){
1679 out_error(m_out,
"PaintAxis",
"debug : texts : dummy : 011\n");
1680 aTexts.push_back(
_text(u,v,
1689 if (OptionGrid && NBININ <= 5 && ndiv > 100) {
1690 TGaxis_Rotate(Xone,0,cosphi,sinphi,X0,Y0,xpl2, ypl2);
1692 (Xone,grid_side*gridlength,cosphi,sinphi,X0,Y0,xpl1,ypl1);
1693 aLinesGrid.push_back((
float)xpl1);
1694 aLinesGrid.push_back((
float)ypl1);
1695 aLinesGrid.push_back((
float)xpl2);
1696 aLinesGrid.push_back((
float)ypl2);
1702 int kuku=0;
if (kuku) { }
1785 if (a_format.find(
"%F")!=std::string::npos || !a_format.size()) {
1786 fTimeFormat = a_format;
1792 std::string::size_type IdF = fTimeFormat.find(
"%F");
1793 if (IdF!=std::string::npos) {
1794 size_t LnF = fTimeFormat.size();
1795 std::string stringtimeoffset = fTimeFormat.substr(IdF,LnF-IdF);
1796 fTimeFormat = a_format;
1797 fTimeFormat += stringtimeoffset;
1801 fTimeFormat = a_format;
1810 double UTC_time_1970_01_01__00_00_00 = 0;
1821 std::string::size_type IdF = fTimeFormat.find(
"%F");
1822 if (IdF!=std::string::npos) {
1823 fTimeFormat = fTimeFormat.substr(0,IdF);
1825 fTimeFormat +=
"%F";
1827 time_t timeoff = (time_t)((
long)(toffset));
1828 struct tm* utctis = ::gmtime(&timeoff);
1831 ::strftime(tmp,256,
"%Y-%m-%d %H:%M:%S",utctis);
1835 double ds = toffset-(int)toffset;
1837 snpf(tmp,
sizeof(tmp),
"s%g",ds);
1842 if (a_is_gmt) fTimeFormat +=
" GMT";
1854 static void optimizeLimits(
1855 double A1,
double A2,
int nold
1856 ,
double &BinLow,
double &BinHigh
1857 ,
int &nbins,
double &BinWidth
1858 ,
const std::string& aCHOPT
1872 double siground = 0;
1873 double alb, awidth, sigfig;
1874 double timemulti = 1;
1878 SETOPT(aCHOPT,
't',OptionTime);
1880 double AL = mn<double>(A1,A2);
1881 double AH = mx<double>(A1,A2);
1882 if (AL == AH) AH = AL+1;
1884 if (nold == -1 && BinWidth > 0 )
goto L90;
1885 ntemp = (int)mx<double>(nold,2);
1886 if (ntemp < 1) ntemp = 1;
1889 awidth = (AH-AL)/
double(ntemp);
1891 if (awidth >= FLT_MAX)
goto LOK;
1892 if (awidth <= 0)
goto LOK;
1897 if (OptionTime && awidth>=60) {
1899 awidth /= 60; timemulti *=60;
1903 awidth /= 60; timemulti *= 60;
1907 awidth /= 24; timemulti *= 24;
1910 if (awidth>=30.43685) {
1911 awidth /= 30.43685; timemulti *= 30.43685;
1915 awidth /= 12; timemulti *= 12;
1924 jlog = int(::log10(awidth));
1925 if (jlog <-200 || jlog > 200) {
1932 if (awidth <= 1 && (!OptionTime || timemulti==1) ) jlog--;
1933 sigfig = awidth* ::pow(10.,-jlog) -1e-10;
1939 switch (roundmode) {
1943 if (sigfig <= 1) siground = 1;
1944 else if (sigfig <= 1.5 && jlog==1) siground = 1.5;
1945 else if (sigfig <= 2) siground = 2;
1946 else if (sigfig <= 3 && jlog ==1) siground = 3;
1947 else if (sigfig <= 5 && sigfig>3 && jlog ==0) siground = 5;
1948 else if (jlog==0) {siground = 1; jlog++;}
1954 if (sigfig <= 1 && jlog==0) siground = 1;
1955 else if (sigfig <= 1.2 && jlog==1) siground = 1.2;
1956 else if (sigfig <= 2 && jlog==0) siground = 2;
1957 else if (sigfig <= 2.4 && jlog==1) siground = 2.4;
1958 else if (sigfig <= 3) siground = 3;
1959 else if (sigfig <= 6) siground = 6;
1960 else if (jlog==0) siground = 12;
1961 else siground = 2.4;
1966 if (sigfig <= 1 && jlog==0) siground = 1;
1967 else if (sigfig <= 1.4 && jlog==1) siground = 1.4;
1968 else if (sigfig <= 3 && jlog ==1) siground = 3;
1974 if (sigfig <= 1) siground = 1;
1975 else if (sigfig <= 2) siground = 2;
1976 else if (sigfig <= 5 && (!OptionTime || jlog<1)) siground = 5;
1977 else if (sigfig <= 6 && OptionTime && jlog==1) siground = 6;
1978 else {siground = 1; jlog++; }
1982 BinWidth = siground* ::pow(10.,jlog);
1983 if (OptionTime) BinWidth *= timemulti;
1989 if (TMath_Abs(alb) > 1e9) {
1992 if (nbins > 10*nold && nbins > 10000) nbins = nold;
1996 if (alb < 0) lwid--;
1997 BinLow = BinWidth*double(lwid);
1998 alb = AH/BinWidth + 1.00001;
2000 if (alb < 0) kwid--;
2001 BinHigh = BinWidth*double(kwid);
2002 nbins = kwid - lwid;
2003 if (nold == -1)
goto LOK;
2005 if (nold > 1 || nbins == 1)
goto LOK;
2006 BinWidth = BinWidth*2;
2010 if (2*nbins == nold && !OptionTime) {ntemp++;
goto L20; }
2013 double oldBinLow = BinLow;
2014 double oldBinHigh = BinHigh;
2015 int oldnbins = nbins;
2017 double atest = BinWidth*0.0001;
2020 if (AL-BinLow >= atest) { BinLow += BinWidth; nbins--; }
2021 if (BinHigh-AH >= atest) { BinHigh -= BinWidth; nbins--; }
2022 if (!OptionTime && BinLow >= BinHigh) {
2025 BinHigh = oldBinHigh;
2028 else if (OptionTime && BinLow>=BinHigh) {
2030 BinHigh = oldBinHigh;
2032 BinWidth = (oldBinHigh - oldBinLow)/nbins;
2033 atest = BinWidth*0.0001;
2034 if (AL-BinLow >= atest) { BinLow += BinWidth; nbins--; }
2035 if (BinHigh-AH >= atest) { BinHigh -= BinWidth; nbins--; }
2039 static void adjustBinSize(
2040 double A1,
double A2,
int nold
2041 ,
double &BinLow,
double &BinHigh,
int &nbins,
double &BinWidth
2056 BinWidth = TMath_Abs(A2-A1)/double(nold);
2057 if (BinWidth <= 1) { BinWidth = 1; BinLow = int(A1); }
2059 int width = int(BinWidth/5) + 1;
2061 BinLow = int(A1/BinWidth)*BinWidth ;
2067 for (
int ic=0; ic<1000; ic++) {
2068 double rbl = BinLow/BinWidth;
2069 int ibl = int(BinLow/BinWidth);
2070 if ( (rbl-ibl) == 0 || ic > width) { BinLow -= 5;
break;}
2077 while (XB <= BinHigh) {
2081 BinHigh = XB - BinWidth;
2083 void setLabelOffset(
float aValue) { fLabelOffset = aValue;}
2084 void setLabelSize(
float aValue) { fLabelSize = aValue;}
2085 void setTitleOffset(
float aValue) { fTitleOffset = aValue;}
2086 void setTitleSize(
float aValue) { fTitleSize = aValue; }
2091 std::ostream& m_out;
2103 std::string fTimeFormat;