inlib
1.2.0
|
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved. 00002 // See the file inlib.license for terms. 00003 00004 #ifndef inlib_hplot 00005 #define inlib_hplot 00006 00007 // Used in exlib::sg::axis. 00008 // 00009 // Code extracted from ROOT-4.03.02/root/graf/stc/TGaxis.cxx. 00010 // Itself built from code extracted from HPLOT. 00011 // 00012 // Take care, all the below is highly disgusting... 00013 // (You can even find.. gotos !) 00014 // 00015 // Except for the public methods we let the style "as it". 00016 00017 #include "mnmx" 00018 #include "vec3f" 00019 #include "math" //pi 00020 00021 #include <string> 00022 #include <vector> 00023 00024 #include <cstring> 00025 #include <ctime> 00026 #include <cmath> 00027 #include <cfloat> 00028 #include <cstdarg> 00029 00030 namespace inlib { 00031 namespace hplot { 00032 00033 class _text { 00034 public: 00035 #ifdef ANDROID_NDK 00036 _text() //FIXME : for inlib/stl/vector. 00037 :fX(0),fY(0) 00038 ,fAngle(0),fSize(0) 00039 ,fString(""),fAlign(0) 00040 {} 00041 #endif 00042 _text(double aX,double aY, 00043 double aAngle,double aSize, 00044 const std::string& aString, 00045 short aAlign) 00046 :fX(aX),fY(aY) 00047 ,fAngle(aAngle),fSize(aSize) 00048 ,fString(aString),fAlign(aAlign) 00049 {} 00050 virtual ~_text(){} 00051 public: 00052 _text(const _text& aFrom) 00053 :fX(aFrom.fX),fY(aFrom.fY) 00054 ,fAngle(aFrom.fAngle),fSize(aFrom.fSize) 00055 ,fString(aFrom.fString) 00056 ,fAlign(aFrom.fAlign) 00057 {} 00058 _text& operator=(const _text& aFrom){ 00059 fX = aFrom.fX; 00060 fY = aFrom.fY; 00061 fAngle = aFrom.fAngle; 00062 fSize = aFrom.fSize; 00063 fString = aFrom.fString; 00064 fAlign = aFrom.fAlign; 00065 return *this; 00066 } 00067 public: 00068 double fX; 00069 double fY; 00070 double fAngle; //Degree 00071 double fSize; 00072 std::string fString; 00073 short fAlign; 00074 }; 00075 00076 00077 class axis { 00078 00079 // Ok, you really want to read all that. You had been warned... 00080 00081 enum { 00082 TAxis_kTickPlus = (1<<(9)), 00083 TAxis_kTickMinus = (1<<(10)), 00084 TAxis_kAxisRange = (1<<(11)), 00085 TAxis_kCenterTitle = (1<<(12)), 00086 TAxis_kCenterLabels = (1<<(14)), //bit 13 is used by TObject 00087 TAxis_kRotateTitle = (1<<(15)), 00088 TAxis_kPalette = (1<<(16)), 00089 TAxis_kNoExponent = (1<<(17)), 00090 TAxis_kLabelsHori = (1<<(18)), 00091 TAxis_kLabelsVert = (1<<(19)), 00092 TAxis_kLabelsDown = (1<<(20)), 00093 TAxis_kLabelsUp = (1<<(21)), 00094 TAxis_kIsInteger = (1<<(22)), 00095 TAxis_kMoreLogLabels = (1<<(23)), 00096 TAxis_kDecimals = (1<<(11)) 00097 }; //in fBits2 00098 00099 enum { 00100 kIsOnHeap = 0x01000000, // object is on heap 00101 kNotDeleted = 0x02000000, // object has not been deleted 00102 kZombie = 0x04000000, // object ctor failed 00103 kBitMask = 0x00ffffff 00104 }; 00105 00106 static int GetTextFont() { return 132;} 00107 static void Error(const char* location, const char* fmt,...) { 00108 va_list args; 00109 va_start(args,fmt); 00110 char s[1024]; 00111 #ifdef WIN32 00112 _vsnprintf(s,sizeof(s),fmt,args); 00113 #else 00114 ::vsnprintf(s,sizeof(s),fmt,args); 00115 #endif 00116 va_end(args); 00117 #ifdef ANDROID_NDK 00118 __android_log_print(ANDROID_LOG_INFO,location,s); 00119 #else 00120 ::printf("%s : %s\n",location,s); 00121 #endif 00122 } 00123 00124 static double TMath_ATan2(double y, double x) { 00125 if (x != 0) return ::atan2(y, x); 00126 if (y == 0) return 0; 00127 if (y > 0) return inlib::half_pi(); 00128 else return -inlib::half_pi(); 00129 } 00130 00131 //static short TMath_Abs(short d) { return (d >= 0) ? d : -d; } 00132 static int TMath_Abs(int d) { return (d >= 0) ? d : -d; } 00133 //static long TMath_Abs(long d) { return (d >= 0) ? d : -d; } 00134 //static float TMath_Abs(float d) { return (d >= 0) ? d : -d; } 00135 static double TMath_Abs(double d) { return (d >= 0) ? d : -d; } 00136 00137 static void TGaxis_Rotate( 00138 double X, double Y, double CFI, double SFI 00139 ,double XT, double YT, double &U, double &V) 00140 { 00141 U = CFI*X-SFI*Y+XT; 00142 V = SFI*X+CFI*Y+YT; 00143 } 00144 00145 public: 00146 axis() 00147 :fMaxDigits(5) 00148 ,fBits(kNotDeleted) 00149 ,fTickSize(0.03F) 00150 ,fLabelOffset(0.005F) 00151 ,fLabelSize(0.04F) 00152 ,fTitleOffset(1) 00153 ,fTitleSize(0.04F) 00154 ,fLabelFont(62) 00155 {} 00156 00157 virtual ~axis(){} 00158 private: //to discourage inheriting that. 00159 axis(const axis&){} 00160 axis& operator=(const axis&){return *this;} 00161 public: 00162 void set_title(const std::string& aTitle) { 00163 fTitle = aTitle; 00164 } 00165 private: 00166 bool testBit(unsigned int f) { 00167 return (bool) ((fBits & f) != 0); 00168 } 00169 00170 static void TGaxis_LabelsLimits(const char *label, 00171 int &first,int &last) { 00172 last = ::strlen(label)-1; 00173 for (int i=0; i<=last; i++) { 00174 if (::strchr("1234567890-+.", label[i]) ) { first = i; return; } 00175 } 00176 Error("LabelsLimits", "attempt to draw a blank label"); 00177 } 00178 static void SETOPT(const std::string& aCHOPT,char aChar,int& aOpt) { 00179 aOpt = aCHOPT.find(aChar)!=std::string::npos?1:0; 00180 } 00181 00182 public: 00183 void paint(double xmin, double ymin, 00184 double xmax, double ymax, 00185 double& wmin,double& wmax, 00186 int& ndiv,const std::string& aCHOPT, 00187 double gridlength,bool drawGridOnly, 00188 std::vector<float>& aLinesAxis, //n*(2+2) 00189 std::vector<float>& aLinesGrid, //n*(2+2) 00190 std::vector<_text>& aTexts){ 00191 // Control function to draw an axis 00192 // ================================ 00193 // 00194 //============> Original authors (O.Couet C.E.Vandoni N.Cremel-Somon) 00195 // largely modified and converted to C++ class by Rene Brun 00196 // 00197 // _Input parameters: 00198 // 00199 // xmin : X origin coordinate in WC space. 00200 // xmax : X end axis coordinate in WC space. 00201 // ymin : Y origin coordinate in WC space. 00202 // ymax : Y end axis coordinate in WC space. 00203 // wmin : Lowest value for the tick mark 00204 // labels written on the axis. 00205 // wmax : Highest value for the tick mark labels 00206 // written on the axis. 00207 // ndiv : Number of divisions. 00208 // 00209 // ndiv=N1 + 100*N2 + 10000*N3 00210 // N1=number of 1st divisions. 00211 // N2=number of 2nd divisions. 00212 // N3=number of 3rd divisions. 00213 // e.g.: 00214 // nndi=0 --> no tick marks. 00215 // nndi=2 --> 2 divisions, one tick mark in the middle 00216 // of the axis. 00217 // 00218 // chopt : Options (see below). 00219 // 00220 // chopt='G': loGarithmic scale, default is linear. 00221 // chopt='B': Blank axis. Useful to superpose axis. 00222 // 00223 // Orientation of tick marks on axis. 00224 // ---------------------------------- 00225 // 00226 // Tick marks are normally drawn on the positive side of the axis, 00227 // however, if X0=X1, then negative. 00228 // 00229 // chopt='+': tick marks are drawn on Positive side. (default) 00230 // chopt='-': tick mark are drawn on the negative side. 00231 // i.e: '+-' --> tick marks are drawn on both sides of the axis. 00232 // chopt='U': Unlabeled axis, default is labeled. 00233 // 00234 // Size of tick marks 00235 // ------------------ 00236 // By default, tick marks have a length equal to 3 per cent of the 00237 // axis length. 00238 // When the option "S" is specified, the length of the tick marks 00239 // is equal to fTickSize*axis_length, where fTickSize may be set 00240 // via TGaxis::SetTickSize. 00241 // 00242 // Position of labels on axis. 00243 // --------------------------- 00244 // 00245 // Labels are normally drawn on side opposite to tick marks. 00246 // However: 00247 // 00248 // chopt='=': on Equal side 00249 // 00250 // Orientation of labels on axis. 00251 // ------------------------------ 00252 // 00253 // Labels are normally drawn parallel to the axis. 00254 // However if X0=X1, then Orthogonal 00255 // if Y0=Y1, then Parallel 00256 // 00257 // Position of labels on tick marks. 00258 // --------------------------------- 00259 // 00260 // Labels are centered on tick marks. 00261 // However , if X0=X1, then they are right adjusted. 00262 // 00263 // chopt='R': labels are Right adjusted on tick mark. 00264 // (default is centered) 00265 // chopt='L': labels are Left adjusted on tick mark. 00266 // chopt='C': labels are Centered on tick mark. 00267 // chopt='M': In the Middle of the divisions. 00268 // 00269 // Format of labels. 00270 // ----------------- 00271 // 00272 // Blank characters are stripped, and then the 00273 // label is correctly aligned. the dot, if last 00274 // character of the string, is also stripped, 00275 // unless the option "." (a dot, or period) is specified. 00276 // if SetDecimals(true) has been called (bit TAxis_kDecimals set). 00277 // all labels have the same number of decimals after the "." 00278 // The same is true if gStyle->SetStripDecimals(false) has been called. 00279 // 00280 // In the following, we have some parameters, like 00281 // tick marks length and characters height (in percentage 00282 // of the length of the axis (WC)) 00283 // The default values are as follows: 00284 // 00285 // Primary tick marks: 3.0 % 00286 // Secondary tick marks: 1.5 % 00287 // Third order tick marks: .75 % 00288 // Characters height for labels: 4% 00289 // 00290 // Labels offset: 1.0 % 00291 // 00292 // Optional grid. 00293 // -------------- 00294 // 00295 // chopt='W': cross-Wire 00296 // In case of a log axis, the grid is only drawn for the primary 00297 // tick marks if the number of secondary and tertiary divisions is 0. 00298 // 00299 // Axis bining optimization. 00300 // ------------------------- 00301 // 00302 // By default the axis bining is optimized . 00303 // 00304 // chopt='N': No bining optimization 00305 // chopt='I': Integer labelling 00306 // 00307 // Maximum Number of Digits for the axis labels 00308 // -------------------------------------------- 00309 // See the static function TGaxis::SetMaxDigits 00310 // 00311 // Time representation. 00312 // -------------------- 00313 // 00314 // Axis labels may be considered as times, plotted in a defined 00315 // time format. 00316 // The format is set with SetTimeFormat(). 00317 // wmin and wmax are considered as two time values in seconds. 00318 // The time axis will be spread around the time offset value (set with 00319 // SetTimeOffset() ). Actually it will go from TimeOffset+wmin to 00320 // TimeOffset+wmax. 00321 // see examples in tutorials timeonaxis.C and timeonaxis2.C 00322 // 00323 // chopt='t': Plot times with a defined format instead of values 00324 // 00325 00326 aLinesAxis.clear(); 00327 aLinesGrid.clear(); 00328 aTexts.clear(); 00329 00330 double alfa, beta, ratio1, ratio2, grid_side; 00331 double axis_lengthN = 0; 00332 double axis_length0 = 0; 00333 double axis_length1 = 0; 00334 double charheight; 00335 double phil, phi, sinphi, cosphi, asinphi, acosphi; 00336 double BinLow, BinLow2, BinLow3; 00337 double BinHigh, BinHigh2, BinHigh3; 00338 double BinWidth, BinWidth2, BinWidth3; 00339 double xpl1, xpl2, ypl1, ypl2; 00340 double Xtick = 0; 00341 double Xtick0, Xtick1, DXtick=0; 00342 double Ytick, Ytick0, Ytick1; 00343 double Wlabel, DWlabel; 00344 double Xlabel, Ylabel; 00345 double DXlabel; 00346 double X0, X1, Y0, Y1, XX0, XX1, YY0, YY1; 00347 XX0 = XX1 = YY0 = YY1 = 0; 00348 double Xxmin, Xxmax, Yymin, Yymax; 00349 Xxmin = Xxmax = Yymin = Yymax = 0; 00350 double XLside,XMside; 00351 double WW, AF, RNE; 00352 double XX, YY; 00353 double Y; 00354 double Xtwo; 00355 int i, j, k, l, decade, ltick; 00356 int Mside, Lside; 00357 int IF1, IF2, NA, NF, NCH; 00358 int OptionLog,OptionBlank,OptionVert,OptionPlus,OptionMinus; 00359 int OptionUnlab,OptionPara; 00360 int OptionDown,OptionRight,OptionLeft,OptionCent,OptionEqual; 00361 int OptionDecimals=0,OptionDot; 00362 int OptionY,OptionText,OptionGrid,OptionSize,OptionNoopt; 00363 int OptionInt,OptionM,OptionUp,OptionX; 00364 int OptionTime; 00365 int first,last; 00366 int nbins; 00367 int N1Aold = 0; 00368 int NN1old = 0; 00369 int Xalign,Yalign; 00370 int ndyn; 00371 char LABEL[256]; 00372 char CHTEMP[256]; 00373 double rangeOffset = 0; 00374 00375 double epsilon = 1e-5; 00376 const double kPI = inlib::pi(); //GB 00377 double textSize = 0.05; //GB 00378 short textAlign = 11; //GB 00379 BinWidth = 0; //GB 00380 BinWidth2 = 0; //GB 00381 BinWidth3 = 0; //GB 00382 nbins = 0; //GB 00383 BinHigh = 0; //GB 00384 BinHigh2 = 0; //GB 00385 BinHigh3 = 0; //GB 00386 BinLow = 0; //GB 00387 BinLow2 = 0; //GB 00388 BinLow3 = 0; //GB 00389 first = 0; //GB 00390 last = 0; //GB 00391 00392 double rwmi = wmin; 00393 double rwma = wmax; 00394 00395 //Error("android_debug","start"); 00396 00397 bool noExponent = testBit(TAxis_kNoExponent); 00398 00399 // If MoreLogLabels = true more Log Intermediate Labels are drawn. 00400 bool MoreLogLabels = testBit(TAxis_kMoreLogLabels); 00401 00402 // the following parameters correspond to the pad range in NDC 00403 // and the WC coordinates in the pad 00404 00405 double padh = 1;//FIXME gPad->GetWh()*gPad->GetAbsHNDC(); 00406 double RWxmin = 0; 00407 double RWxmax = 1; 00408 double RWymin = 0; 00409 double RWymax = 1; 00410 00411 SETOPT(aCHOPT,'G',OptionLog); 00412 SETOPT(aCHOPT,'B',OptionBlank); 00413 SETOPT(aCHOPT,'V',OptionVert); 00414 SETOPT(aCHOPT,'+',OptionPlus); 00415 SETOPT(aCHOPT,'-',OptionMinus); 00416 SETOPT(aCHOPT,'U',OptionUnlab); 00417 SETOPT(aCHOPT,'P',OptionPara); 00418 SETOPT(aCHOPT,'O',OptionDown); 00419 SETOPT(aCHOPT,'R',OptionRight); 00420 SETOPT(aCHOPT,'L',OptionLeft); 00421 SETOPT(aCHOPT,'C',OptionCent); 00422 SETOPT(aCHOPT,'=',OptionEqual); 00423 SETOPT(aCHOPT,'Y',OptionY); 00424 SETOPT(aCHOPT,'T',OptionText); 00425 SETOPT(aCHOPT,'W',OptionGrid); 00426 SETOPT(aCHOPT,'S',OptionSize); 00427 SETOPT(aCHOPT,'N',OptionNoopt); 00428 SETOPT(aCHOPT,'I',OptionInt); 00429 SETOPT(aCHOPT,'M',OptionM); 00430 SETOPT(aCHOPT,'0',OptionUp); 00431 SETOPT(aCHOPT,'X',OptionX); 00432 SETOPT(aCHOPT,'t',OptionTime); 00433 SETOPT(aCHOPT,'.',OptionDot); 00434 00435 if (testBit(TAxis_kTickPlus)) OptionPlus = 2; 00436 if (testBit(TAxis_kTickMinus)) OptionMinus = 2; 00437 if (testBit(TAxis_kCenterLabels)) OptionM = 1; 00438 if (testBit(TAxis_kDecimals)) OptionDecimals = 1; 00439 /*FIXME if (fAxis) { 00440 if (fAxis->GetLabels()) { 00441 OptionM = 1; 00442 OptionText = 1; 00443 ndiv = fAxis->GetLast()-fAxis->GetFirst()+1; 00444 } 00445 }*/ 00446 00447 // Set the grid length 00448 00449 if (OptionGrid) { 00450 if (gridlength == 0) gridlength = 0.8; 00451 /*FIXME 00452 linegrid = new TLine(); 00453 linegrid->SetLineColor(gStyle->GetGridColor()); 00454 if (linegrid->GetLineColor() == 0) 00455 linegrid->SetLineColor(GetLineColor()); 00456 linegrid->SetLineStyle(gStyle->GetGridStyle()); 00457 linegrid->SetLineWidth(gStyle->GetGridWidth());*/ 00458 } 00459 00460 00461 if (OptionTime) { 00462 //printf("debug : SbAxisHPLOT::paint : fTimeFormat : \"%s\"\n", 00463 // fTimeFormat.c_str()); 00464 } 00465 00466 //Error("android_debug","0000"); 00467 // Determine time format 00468 std::string timeformat; 00469 std::string::size_type IdF = fTimeFormat.find("%F"); 00470 if (IdF!=std::string::npos) { 00471 timeformat = fTimeFormat.substr(0,IdF); 00472 } else { 00473 timeformat = fTimeFormat; 00474 } 00475 00476 //Error("android_debug","0001"); 00477 // determine the time offset and correct for time offset not being integer 00478 double timeoffset = 0; 00479 if (OptionTime) { 00480 if (IdF!=std::string::npos) { 00481 int LnF = fTimeFormat.size(); 00482 std::string stringtimeoffset = 00483 fTimeFormat.substr(IdF+2,LnF-(IdF+2)); 00484 int yy, mm, dd, hh, mi, ss; 00485 if (::sscanf(stringtimeoffset.c_str(), 00486 "%d-%d-%d %d:%d:%d", &yy, &mm, &dd, &hh, &mi, &ss) == 6) { 00487 struct tm tp; 00488 struct tm* tptest; 00489 time_t timeoffsettest; 00490 tp.tm_year = yy-1900; 00491 tp.tm_mon = mm-1; 00492 tp.tm_mday = dd; 00493 tp.tm_hour = hh; 00494 tp.tm_min = mi; 00495 tp.tm_sec = ss; 00496 tp.tm_isdst = 0; // daylight saving time is not in effect (see mktime man pages) 00497 timeoffset = mktime(&tp); 00498 // have to correct this time to go back to UTC 00499 timeoffsettest = (time_t)((long)timeoffset); 00500 tptest = gmtime(&timeoffsettest); 00501 timeoffset += timeoffsettest - mktime(tptest); 00502 // Add the time offset's decimal part if it is there 00503 std::string::size_type Ids = stringtimeoffset.find("s"); 00504 if (Ids != std::string::npos) { 00505 float dp; 00506 int Lns = stringtimeoffset.size(); 00507 std::string sdp = stringtimeoffset.substr(Ids+1,Lns-(Ids+1)); 00508 ::sscanf(sdp.c_str(),"%g",&dp); 00509 timeoffset += dp; 00510 } 00511 // if OptionTime = 2 gmtime will be used instead of localtime 00512 if (stringtimeoffset.find("GMT")!=std::string::npos) 00513 OptionTime =2; 00514 } else { 00515 Error("PaintAxis", "Time offset has not the right format"); 00516 } 00517 } else { 00518 Error("PaintAxis", "%%F not found in fTimeFormat."); 00519 //FIXME timeoffset = gStyle->GetTimeOffset(); 00520 } 00521 wmin += timeoffset - (int)(timeoffset); 00522 wmax += timeoffset - (int)(timeoffset); 00523 // correct for time offset at a good limit (min, hour, 00524 // day, month, year) 00525 struct tm* tp0; 00526 time_t timetp = (time_t)((long)(timeoffset)); 00527 double range = wmax - wmin; 00528 long rangeBase = 60; 00529 if (range>60) rangeBase = 60*20; // minutes 00530 if (range>3600) rangeBase = 3600*20; // hours 00531 if (range>86400) rangeBase = 86400*20; // days 00532 if (range>2419200) rangeBase = 31556736; // months (average # days) 00533 rangeOffset = (double) ((long)(timeoffset)%rangeBase); 00534 if (range>31536000) { 00535 tp0 = gmtime(&timetp); 00536 tp0->tm_mon = 0; 00537 tp0->tm_mday = 1; 00538 tp0->tm_hour = 0; 00539 tp0->tm_min = 0; 00540 tp0->tm_sec = 0; 00541 tp0->tm_isdst = 0; // daylight saving time is not in effect (see mktime man pages) 00542 rangeBase = (timetp-mktime(tp0)); // years 00543 rangeOffset = (double) (rangeBase); 00544 } 00545 wmax += rangeOffset; 00546 wmin += rangeOffset; 00547 } 00548 00549 // Determine number of divisions 1, 2 and 3 00550 int N1A = ndiv%100; 00551 int N2A = (ndiv%10000 - N1A)/100; 00552 int N3A = ndiv/10000; 00553 int NN3 = inlib::mx(N3A,1); 00554 int NN2 = inlib::mx(N2A,1)*NN3; 00555 int NN1 = inlib::mx(N1A,1)*NN2+1; 00556 int Nticks= NN1; 00557 00558 // Axis bining optimization is ignored if: 00559 // - the first and the last label are equal 00560 // - the number of divisions is 0 00561 // - less than 1 primary division is requested 00562 // - logarithmic scale is requested 00563 00564 if (wmin == wmax || ndiv == 0 || N1A <= 1 || OptionLog) { 00565 OptionNoopt = 1; 00566 OptionInt = 0; 00567 } 00568 00569 // Axis bining optimization 00570 if ( (wmax-wmin) < 1 && OptionInt) { 00571 Error("PaintAxis", "option I not available"); 00572 OptionInt = 0; 00573 } 00574 //Error("android_debug","0002"); 00575 if (!OptionNoopt || OptionInt ) { 00576 00577 // Primary divisions optimization 00578 // When integer labelling is required, Optimize is invoked first 00579 // and only if the result is not an integer labelling, AdjustBinSize 00580 // is invoked. 00581 00582 optimizeLimits(wmin,wmax,N1A, 00583 BinLow,BinHigh,nbins,BinWidth, 00584 aCHOPT); 00585 if (OptionInt) { 00586 if (BinLow != double(int(BinLow)) || 00587 BinWidth != double(int(BinWidth))) { 00588 adjustBinSize(wmin,wmax,N1A,BinLow,BinHigh,nbins,BinWidth); 00589 } 00590 } 00591 if ((wmin-BinLow) > epsilon) { BinLow += BinWidth; nbins--; } 00592 if ((BinHigh-wmax) > epsilon) { BinHigh -= BinWidth; nbins--; } 00593 if (xmax == xmin) { 00594 double rtyw = (ymax-ymin)/(wmax-wmin); 00595 Xxmin = xmin; 00596 Xxmax = xmax; 00597 Yymin = rtyw*(BinLow-wmin) + ymin; 00598 Yymax = rtyw*(BinHigh-wmin) + ymin; 00599 } else { 00600 double rtxw = (xmax-xmin)/(wmax-wmin); 00601 Xxmin = rtxw*(BinLow-wmin) + xmin; 00602 Xxmax = rtxw*(BinHigh-wmin) + xmin; 00603 if (ymax == ymin) { 00604 Yymin = ymin; 00605 Yymax = ymax; 00606 } else { 00607 alfa = (ymax-ymin)/(xmax-xmin); 00608 beta = (ymin*xmax-ymax*xmin)/(xmax-xmin); 00609 Yymin = alfa*Xxmin + beta; 00610 Yymax = alfa*Xxmax + beta; 00611 } 00612 } 00613 /*GB if (fFunction) { 00614 Yymin = ymin; 00615 Yymax = ymax; 00616 Xxmin = xmin; 00617 Xxmax = xmax; 00618 } else*/ { 00619 wmin = BinLow; 00620 wmax = BinHigh; 00621 } 00622 00623 // Secondary divisions optimization 00624 int NB2 = N2A; 00625 if (!OptionNoopt && N2A > 1 && BinWidth > 0) { 00626 optimizeLimits(wmin,wmin+BinWidth,N2A, 00627 BinLow2,BinHigh2,NB2,BinWidth2, 00628 aCHOPT); 00629 } 00630 00631 // Tertiary divisions optimization 00632 int NB3 = N3A; 00633 if (!OptionNoopt && N3A > 1 && BinWidth2 > 0) { 00634 optimizeLimits(BinLow2,BinLow2+BinWidth2,N3A, 00635 BinLow3,BinHigh3,NB3,BinWidth3, 00636 aCHOPT); 00637 } 00638 N1Aold = N1A; 00639 NN1old = NN1; 00640 N1A = nbins; 00641 NN3 = inlib::mx(NB3,1); 00642 NN2 = inlib::mx(NB2,1)*NN3; 00643 NN1 = inlib::mx(N1A,1)*NN2+1; 00644 Nticks = NN1; 00645 } 00646 00647 //Error("android_debug","0003"); 00648 // Coordinates are normalized 00649 00650 ratio1 = 1/(RWxmax-RWxmin); 00651 ratio2 = 1/(RWymax-RWymin); 00652 X0 = ratio1*(xmin-RWxmin); 00653 X1 = ratio1*(xmax-RWxmin); 00654 Y0 = ratio2*(ymin-RWymin); 00655 Y1 = ratio2*(ymax-RWymin); 00656 if (!OptionNoopt || OptionInt ) { 00657 XX0 = ratio1*(Xxmin-RWxmin); 00658 XX1 = ratio1*(Xxmax-RWxmin); 00659 YY0 = ratio2*(Yymin-RWymin); 00660 YY1 = ratio2*(Yymax-RWymin); 00661 } 00662 00663 //Error("android_debug","0004"); 00664 if ((X0 == X1) && (Y0 == Y1)) { 00665 Error("PaintAxis", "length of axis is 0"); 00666 return; 00667 } 00668 00669 // Return wmin, wmax and the number of primary divisions 00670 if (OptionX) { 00671 ndiv = N1A; 00672 return; 00673 } 00674 00675 int maxDigits = 5; 00676 //FIXME if (fAxis) maxDigits = fMaxDigits; 00677 00678 /*FIXME 00679 TLatex *textaxis = new TLatex(); 00680 lineaxis->SetLineColor(GetLineColor()); 00681 lineaxis->SetLineStyle(1); 00682 lineaxis->SetLineWidth(GetLineWidth()); 00683 textaxis->SetTextColor(GetTextColor()); 00684 textaxis->SetTextFont(GetTextFont()); 00685 00686 if (!gPad->IsBatch()) { 00687 float chupxvsav, chupyvsav; 00688 gVirtualX->GetCharacterUp(chupxvsav, chupyvsav); 00689 gVirtualX->SetClipOFF(gPad->GetCanvasID()); 00690 } 00691 */ 00692 00693 // Compute length of axis 00694 double axis_length = ::sqrt((X1-X0)*(X1-X0)+(Y1-Y0)*(Y1-Y0)); 00695 if (axis_length == 0) { 00696 Error("PaintAxis", "length of axis is 0"); 00697 return; //goto L210; 00698 } 00699 00700 //Error("android_debug","0005"); 00701 if (!OptionNoopt || OptionInt) { 00702 axis_lengthN = ::sqrt((XX1-XX0)*(XX1-XX0)+(YY1-YY0)*(YY1-YY0)); 00703 axis_length0 = ::sqrt((XX0-X0)*(XX0-X0)+(YY0-Y0)*(YY0-Y0)); 00704 axis_length1 = ::sqrt((X1-XX1)*(X1-XX1)+(Y1-YY1)*(Y1-YY1)); 00705 if (axis_lengthN < epsilon) { 00706 OptionNoopt = 1; 00707 OptionInt = 0; 00708 wmin = rwmi; 00709 wmax = rwma; 00710 N1A = N1Aold; 00711 NN1 = NN1old; 00712 Nticks = NN1; 00713 if (OptionTime) { 00714 wmin += timeoffset - (int)(timeoffset) + rangeOffset; 00715 wmax += timeoffset - (int)(timeoffset) + rangeOffset; 00716 } 00717 } 00718 } 00719 00720 //Error("android_debug","0006"); 00721 if (X0 == X1) { 00722 phi = 0.5*kPI; 00723 phil = phi; 00724 } else { 00725 phi = TMath_ATan2((Y1-Y0),(X1-X0)); 00726 int px0 = 0;//FIXME gPad->UtoPixel(X0); 00727 int py0 = 0;//FIXME gPad->VtoPixel(Y0); 00728 int px1 = 0;//FIXME gPad->UtoPixel(X1); 00729 int py1 = 0;//FIXME gPad->VtoPixel(Y1); 00730 if (X0 < X1) phil = TMath_ATan2(double(py0-py1), double(px1-px0)); 00731 else phil = TMath_ATan2(double(py1-py0), double(px0-px1)); 00732 } 00733 cosphi = ::cos(phi); 00734 sinphi = ::sin(phi); 00735 acosphi = TMath_Abs(cosphi); 00736 asinphi = TMath_Abs(sinphi); 00737 if (acosphi <= epsilon) { acosphi = 0; cosphi = 0; } 00738 if (asinphi <= epsilon) { asinphi = 0; sinphi = 0; } 00739 00740 //Error("android_debug","0007"); 00741 // Mside positive, tick marks on positive side 00742 // Mside negative, tick marks on negative side 00743 // Mside zero, tick marks on both sides 00744 // Default is positive except for vertical axis 00745 00746 Mside=1; 00747 if (X0 == X1 && Y1 > Y0) Mside = -1; 00748 if (OptionPlus) Mside = 1; 00749 if (OptionMinus) Mside = -1; 00750 if (OptionPlus && OptionMinus) Mside = 0; 00751 XMside = Mside; 00752 Lside = -Mside; 00753 if (OptionEqual) Lside = Mside; 00754 if (OptionPlus && OptionMinus) { 00755 Lside = -1; 00756 if (OptionEqual) Lside=1; 00757 } 00758 XLside = Lside; 00759 00760 // Tick marks size 00761 double tick_side; 00762 if(XMside >= 0) tick_side = 1; 00763 else tick_side = -1; 00764 00765 double atick[3]; 00766 if (OptionSize) atick[0] = tick_side*axis_length*fTickSize; 00767 else atick[0] = tick_side*axis_length*0.03; 00768 00769 atick[1] = 0.5*atick[0]; 00770 atick[2] = 0.5*atick[1]; 00771 00772 // Set the side of the grid 00773 if ((X0 == X1) && (Y1 > Y0)) grid_side =-1; 00774 else grid_side = 1; 00775 00776 00777 //Error("android_debug","0008"); 00778 // Compute Values if Function is given 00779 /*GB if(fFunction) { 00780 rwmi = fFunction->Eval(wmin); 00781 rwma = fFunction->Eval(wmax); 00782 if(rwmi > rwma) { 00783 double t = rwma; 00784 rwma = rwmi; 00785 rwmi = t; 00786 } 00787 }*/ 00788 00789 // Draw the axis if needed... 00790 if (!OptionBlank) { 00791 xpl1 = X0; 00792 xpl2 = X1; 00793 ypl1 = Y0; 00794 ypl2 = Y1; 00795 aLinesAxis.push_back((float)xpl1); 00796 aLinesAxis.push_back((float)ypl1); 00797 aLinesAxis.push_back((float)xpl2); 00798 aLinesAxis.push_back((float)ypl2); 00799 } 00800 00801 //Error("android_debug","0009"); 00802 // No bining 00803 00804 if (ndiv == 0) return; //goto L210; 00805 if (wmin == wmax) { 00806 Error("PaintAxis", "wmin (%f) == wmax (%f)", wmin, wmax); 00807 return; //goto L210; 00808 } 00809 00810 // Draw axis title if it exists 00811 if (!drawGridOnly && fTitle.size()) { 00812 textSize = fTitleSize; 00813 charheight = fTitleSize; 00814 if ((GetTextFont() % 10) > 2) { 00815 //FIXME charheight = charheight/gPad->GetWh(); 00816 } 00817 double toffset = fTitleOffset; 00818 if (toffset < 0.1) toffset = 1; 00819 if (X1 == X0) Ylabel = XLside*1.6*charheight*toffset; 00820 else Ylabel = XLside*1.3*charheight*toffset; 00821 if (Y1 == Y0) Ylabel = XLside*1.6*charheight*toffset; 00822 double axispos; 00823 if (testBit(TAxis_kCenterTitle)) axispos = 0.5*axis_length; 00824 else axispos = axis_length; 00825 if (testBit(TAxis_kRotateTitle)) { 00826 if (X1 >= X0) { 00827 if (testBit(TAxis_kCenterTitle)) textAlign = 22; 00828 else textAlign = 12; 00829 TGaxis_Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1); 00830 } else { 00831 if (testBit(TAxis_kCenterTitle)) textAlign = 22; 00832 else textAlign = 32; 00833 TGaxis_Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1); 00834 } 00835 Error("PaintAxis","debug : texts : dummy : 000\n"); 00836 aTexts.push_back(_text(xpl1,ypl1, 00837 phil=(kPI+phil)*180/kPI, 00838 fTitleSize, 00839 fTitle,textAlign)); 00840 } else { 00841 if (X1 >= X0) { 00842 if (testBit(TAxis_kCenterTitle)) textAlign = 22; 00843 else textAlign = 32; 00844 TGaxis_Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1); 00845 } else { 00846 if (testBit(TAxis_kCenterTitle)) textAlign = 22; 00847 else textAlign = 12; 00848 TGaxis_Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1); 00849 } 00850 aTexts.push_back(_text(xpl1,ypl1, 00851 phil*180/kPI,fTitleSize, 00852 fTitle,textAlign)); 00853 } 00854 } 00855 00856 //Error("android_debug","0010"); 00857 // Labels preparation: 00858 // Get character height 00859 // Compute the labels orientation in case of overlaps 00860 // with alphanumeric labels for horizontal axis). 00861 00862 charheight = fLabelSize; 00863 if (OptionText) charheight *= 0.66666; 00864 //FIXME textaxis->SetTextFont(fLabelFont); 00865 //FIXME textaxis->SetTextColor(GetLabelColor()); 00866 textSize = charheight; 00867 //FIXME textaxis->SetTextAngle(GetTextAngle()); 00868 if (fLabelFont%10 > 2) { 00869 charheight /= padh; 00870 } 00871 if (!OptionUp && !OptionDown && !OptionY) { 00872 if (!drawGridOnly && OptionText && ((ymin == ymax) || (xmin == xmax))) { 00873 textAlign = 32; 00874 OptionText = 2; 00875 //int nl = 0;//FIXME fAxis->GetLast()-fAxis->GetFirst()+1; 00876 //double angle = 0; 00877 Error("PaintAxis","debug : FIXME : 000\n"); 00878 /*FIXME 00879 for (i=fAxis->GetFirst(); i<=fAxis->GetLast(); i++) { 00880 textaxis->SetText(0,0,fAxis->GetBinLabel(i)); 00881 if (textaxis->GetXsize() < (xmax-xmin)/nl) continue; 00882 angle = -20; 00883 break; 00884 } 00885 for (i=fAxis->GetFirst(); i<=fAxis->GetLast(); i++) { 00886 if ((!::strcmp(fAxis->GetName(),"xaxis") && !gPad->testBit(kHori)) 00887 ||(!::strcmp(fAxis->GetName(),"yaxis") && gPad->testBit(kHori))) { 00888 if (nl > 50) angle = 90; 00889 if (fAxis->testBit(TAxis_kLabelsHori)) angle = 0; 00890 if (fAxis->testBit(TAxis_kLabelsVert)) angle = 90; 00891 if (fAxis->testBit(TAxis_kLabelsUp)) angle = 20; 00892 if (fAxis->testBit(TAxis_kLabelsDown)) angle =-20; 00893 if (angle== 0) textAlign = 23; 00894 if (angle== -20) textAlign = 12; 00895 Error("PaintAxis","debug : texts : dummy : 002\n"); 00896 textaxis->PaintLatex( 00897 fAxis->GetBinCenter(i), 00898 gPad->GetUymin() - 3*fAxis->GetLabelOffset()* 00899 (gPad->GetUymax()-gPad->GetUymin()), 00900 angle, 00901 charheight, 00902 fAxis->GetBinLabel(i)); 00903 } else if ((!::strcmp(fAxis->GetName(),"yaxis") && !gPad->testBit(kHori)) 00904 || (!::strcmp(fAxis->GetName(),"xaxis") && gPad->testBit(kHori))) { 00905 Error("PaintAxis","debug : texts : dummy : 003\n"); 00906 textaxis->PaintLatex( 00907 gPad->GetUxmin() - 3*fAxis->GetLabelOffset()* 00908 (gPad->GetUxmax()-gPad->GetUxmin()), 00909 fAxis->GetBinCenter(i), 00910 0, 00911 charheight, 00912 fAxis->GetBinLabel(i)); 00913 } else { 00914 Error("PaintAxis","debug : texts : dummy : 004\n"); 00915 textaxis->PaintLatex( 00916 xmin - 3*fAxis->GetLabelOffset()* 00917 (gPad->GetUxmax()-gPad->GetUxmin()), 00918 ymin +(i-0.5)*(ymax-ymin)/nl, 00919 0, 00920 charheight, 00921 fAxis->GetBinLabel(i)); 00922 } 00923 }*/ 00924 } 00925 } 00926 00927 //Error("android_debug","0011"); 00928 // Now determine orientation of labels on axis 00929 /*FIXME 00930 if (!gPad->IsBatch()) { 00931 if (cosphi > 0) gVirtualX->SetCharacterUp(-sinphi,cosphi); 00932 else gVirtualX->SetCharacterUp(sinphi,-cosphi); 00933 if (X0 == X1) gVirtualX->SetCharacterUp(0,1); 00934 if (OptionVert) gVirtualX->SetCharacterUp(0,1); 00935 if (OptionPara) gVirtualX->SetCharacterUp(-sinphi,cosphi); 00936 if (OptionDown) gVirtualX->SetCharacterUp(cosphi,sinphi); 00937 }*/ 00938 00939 // Now determine text alignment 00940 Xalign = 2; 00941 Yalign = 1; 00942 if (X0 == X1) Xalign = 3; 00943 if (Y0 != Y1) Yalign = 2; 00944 if (OptionCent) Xalign = 2; 00945 if (OptionRight) Xalign = 3; 00946 if (OptionLeft) Xalign = 1; 00947 if (TMath_Abs(cosphi) > 0.9) { 00948 Xalign = 2; 00949 } else { 00950 if (cosphi*sinphi > 0) Xalign = 1; 00951 if (cosphi*sinphi < 0) Xalign = 3; 00952 } 00953 textAlign = 10*Xalign+Yalign; 00954 00955 //Error("android_debug","0012"); 00956 // Position of labels in Y 00957 if (X0 == X1) { 00958 if (OptionPlus && !OptionMinus) { 00959 if (OptionEqual) Ylabel = fLabelOffset/2 + atick[0]; 00960 else Ylabel = -fLabelOffset; 00961 } else { 00962 Ylabel = fLabelOffset; 00963 if (Lside < 0) Ylabel += atick[0]; 00964 } 00965 } else if (Y0 == Y1) { 00966 if (OptionMinus && !OptionPlus) { 00967 Ylabel = fLabelOffset+0.5*fLabelSize; 00968 Ylabel += TMath_Abs(atick[0]); 00969 } else { 00970 Ylabel = -fLabelOffset; 00971 if (Mside <= 0) Ylabel -= TMath_Abs(atick[0]); 00972 } 00973 if (OptionLog) Ylabel -= 0.5*charheight; 00974 } else { 00975 if (Mside+Lside >= 0) Ylabel = fLabelOffset; 00976 else Ylabel = -fLabelOffset; 00977 } 00978 if (OptionText) Ylabel /= 2; 00979 00980 //Error("android_debug","0013"); 00981 // Draw the linear tick marks if needed... 00982 if (!OptionLog) { 00983 if (ndiv) { 00984 /*GB if (fFunction) { 00985 if (OptionNoopt && !OptionInt) { 00986 DXtick=(BinHigh-BinLow)/double(Nticks-1); 00987 } else { 00988 DXtick=(BinHigh-BinLow)/double(Nticks-1); 00989 } 00990 } else */ { 00991 if (OptionNoopt && !OptionInt) DXtick=axis_length/double(Nticks-1); 00992 else DXtick=axis_lengthN/double(Nticks-1); 00993 } 00994 for (k=0;k<Nticks; k++) { 00995 ltick = 2; 00996 if (k%NN3 == 0) ltick = 1; 00997 if (k%NN2 == 0) ltick = 0; 00998 /*GB if (fFunction) { 00999 double xx = BinLow+double(k)*DXtick; 01000 double zz = fFunction->Eval(xx)-rwmi; 01001 Xtick = zz* axis_length / TMath_Abs(rwma-rwmi); 01002 } else */ { 01003 Xtick = double(k)*DXtick; 01004 } 01005 Ytick = 0; 01006 if (!Mside) Ytick -= atick[ltick]; 01007 if ( OptionNoopt && !OptionInt) { 01008 TGaxis_Rotate(Xtick,Ytick,cosphi,sinphi,X0,Y0,xpl2,ypl2); 01009 TGaxis_Rotate(Xtick,atick[ltick],cosphi,sinphi,X0,Y0,xpl1,ypl1); 01010 } 01011 else { 01012 TGaxis_Rotate(Xtick,Ytick,cosphi,sinphi,XX0,YY0,xpl2,ypl2); 01013 TGaxis_Rotate(Xtick,atick[ltick],cosphi,sinphi,XX0,YY0,xpl1,ypl1); 01014 } 01015 if (OptionVert) { 01016 if ((X0 != X1) && (Y0 != Y1)) { 01017 if (Mside) { 01018 xpl1 = xpl2; 01019 if (cosphi > 0) ypl1 = ypl2 + atick[ltick]; 01020 else ypl1 = ypl2 - atick[ltick]; 01021 } 01022 else { 01023 xpl1 = 0.5*(xpl1 + xpl2); 01024 xpl2 = xpl1; 01025 ypl1 = 0.5*(ypl1 + ypl2) + atick[ltick]; 01026 ypl2 = 0.5*(ypl1 + ypl2) - atick[ltick]; 01027 } 01028 } 01029 } 01030 if (!drawGridOnly) { 01031 aLinesAxis.push_back((float)xpl1); 01032 aLinesAxis.push_back((float)ypl1); 01033 aLinesAxis.push_back((float)xpl2); 01034 aLinesAxis.push_back((float)ypl2); 01035 } 01036 01037 if (OptionGrid) { 01038 if (ltick == 0) { 01039 if (OptionNoopt && !OptionInt) { 01040 TGaxis_Rotate(Xtick,0,cosphi,sinphi,X0,Y0 ,xpl2,ypl2); 01041 TGaxis_Rotate 01042 (Xtick,grid_side*gridlength,cosphi,sinphi,X0,Y0, 01043 xpl1,ypl1); 01044 } else { 01045 TGaxis_Rotate(Xtick,0,cosphi ,sinphi,XX0,YY0,xpl2,ypl2); 01046 TGaxis_Rotate 01047 (Xtick,grid_side*gridlength ,cosphi,sinphi,XX0,YY0, 01048 xpl1,ypl1); 01049 } 01050 aLinesGrid.push_back((float)xpl1); 01051 aLinesGrid.push_back((float)ypl1); 01052 aLinesGrid.push_back((float)xpl2); 01053 aLinesGrid.push_back((float)ypl2); 01054 } 01055 } 01056 } 01057 Xtick0 = 0; 01058 Xtick1 = Xtick; 01059 01060 if ((!OptionNoopt || OptionInt) && axis_length0) { 01061 int Nticks0; 01062 /*GB if (fFunction) Nticks0 = int((BinLow-wmin)/DXtick); 01063 else */ Nticks0 = int(axis_length0/DXtick); 01064 if (Nticks0 > 1000) Nticks0 = 1000; 01065 for (k=0; k<=Nticks0; k++) { 01066 ltick = 2; 01067 if (k%NN3 == 0) ltick = 1; 01068 if (k%NN2 == 0) ltick = 0; 01069 Ytick0 = 0; 01070 if (!Mside) Ytick0 -= atick[ltick]; 01071 /*GB if (fFunction) { 01072 Xtick0 = (fFunction->Eval(BinLow - double(k)*DXtick)-rwmi) 01073 * axis_length / TMath_Abs(rwma-rwmi); 01074 }*/ 01075 TGaxis_Rotate(Xtick0,Ytick0,cosphi,sinphi,XX0,YY0 ,xpl2,ypl2); 01076 TGaxis_Rotate(Xtick0,atick[ltick],cosphi,sinphi,XX0,YY0 ,xpl1,ypl1); 01077 if (OptionVert) { 01078 if ((X0 != X1) && (Y0 != Y1)) { 01079 if (Mside) { 01080 xpl1 = xpl2; 01081 if (cosphi > 0) ypl1 = ypl2 + atick[ltick]; 01082 else ypl1 = ypl2 - atick[ltick]; 01083 } 01084 else { 01085 xpl1 = 0.5*(xpl1 + xpl2); 01086 xpl2 = xpl1; 01087 ypl1 = 0.5*(ypl1 + ypl2) + atick[ltick]; 01088 ypl2 = 0.5*(ypl1 + ypl2) - atick[ltick]; 01089 } 01090 } 01091 } 01092 if(!drawGridOnly) { 01093 aLinesAxis.push_back((float)xpl1); 01094 aLinesAxis.push_back((float)ypl1); 01095 aLinesAxis.push_back((float)xpl2); 01096 aLinesAxis.push_back((float)ypl2); 01097 } 01098 01099 if (OptionGrid) { 01100 if (ltick == 0) { 01101 TGaxis_Rotate(Xtick0,0,cosphi,sinphi,XX0,YY0,xpl2,ypl2); 01102 TGaxis_Rotate 01103 (Xtick0,grid_side*gridlength,cosphi,sinphi,XX0,YY0, 01104 xpl1,ypl1); 01105 aLinesGrid.push_back((float)xpl1); 01106 aLinesGrid.push_back((float)ypl1); 01107 aLinesGrid.push_back((float)xpl2); 01108 aLinesGrid.push_back((float)ypl2); 01109 } 01110 } 01111 Xtick0 -= DXtick; 01112 } 01113 } 01114 01115 if ((!OptionNoopt || OptionInt) && axis_length1) { 01116 int Nticks1; 01117 /*GB if (fFunction) Nticks1 = int((wmax-BinHigh)/DXtick); 01118 else */ Nticks1 = int(axis_length1/DXtick); 01119 if (Nticks1 > 1000) Nticks1 = 1000; 01120 for (k=0; k<=Nticks1; k++) { 01121 ltick = 2; 01122 if (k%NN3 == 0) ltick = 1; 01123 if (k%NN2 == 0) ltick = 0; 01124 Ytick1 = 0; 01125 if (!Mside) Ytick1 -= atick[ltick]; 01126 /*GB if (fFunction) { 01127 Xtick1 = (fFunction->Eval(BinHigh + double(k)*DXtick)-rwmi) 01128 * axis_length / TMath_Abs(rwma-rwmi); 01129 }*/ 01130 TGaxis_Rotate(Xtick1,Ytick1,cosphi,sinphi,XX0,YY0 ,xpl2,ypl2); 01131 TGaxis_Rotate(Xtick1,atick[ltick],cosphi,sinphi,XX0,YY0 ,xpl1,ypl1); 01132 if (OptionVert) { 01133 if ((X0 != X1) && (Y0 != Y1)) { 01134 if (Mside) { 01135 xpl1 = xpl2; 01136 if (cosphi > 0) ypl1 = ypl2 + atick[ltick]; 01137 else ypl1 = ypl2 - atick[ltick]; 01138 } 01139 else { 01140 xpl1 = 0.5*(xpl1 + xpl2); 01141 xpl2 = xpl1; 01142 ypl1 = 0.5*(ypl1 + ypl2) + atick[ltick]; 01143 ypl2 = 0.5*(ypl1 + ypl2) - atick[ltick]; 01144 } 01145 } 01146 } 01147 if(!drawGridOnly) { 01148 aLinesAxis.push_back((float)xpl1); 01149 aLinesAxis.push_back((float)ypl1); 01150 aLinesAxis.push_back((float)xpl2); 01151 aLinesAxis.push_back((float)ypl2); 01152 } 01153 01154 if (OptionGrid) { 01155 if (ltick == 0) { 01156 TGaxis_Rotate(Xtick1,0,cosphi,sinphi,XX0,YY0 ,xpl2,ypl2); 01157 TGaxis_Rotate 01158 (Xtick1,grid_side*gridlength,cosphi,sinphi,XX0,YY0, 01159 xpl1,ypl1); 01160 aLinesGrid.push_back((float)xpl1); 01161 aLinesGrid.push_back((float)ypl1); 01162 aLinesGrid.push_back((float)xpl2); 01163 aLinesGrid.push_back((float)ypl2); 01164 } 01165 } 01166 Xtick1 += DXtick; 01167 } 01168 } 01169 } 01170 } 01171 01172 //Error("android_debug","0014"); 01173 // Draw the numeric labels if needed... 01174 if (!drawGridOnly && !OptionUnlab) { 01175 if (!OptionLog) { 01176 if (N1A) { 01177 // Spacing of labels 01178 if ((wmin == wmax) || (ndiv == 0)) { 01179 Error("PaintAxis", "wmin (%f) == wmax (%f), or ndiv == 0", wmin, wmax); 01180 return; //goto L210; 01181 } 01182 Wlabel = wmin; 01183 DWlabel = (wmax-wmin)/double(N1A); 01184 if (OptionNoopt && !OptionInt) DXlabel = axis_length/double(N1A); 01185 else DXlabel = axis_lengthN/double(N1A); 01186 01187 char CHCODED[8]; 01188 int NEXE = 0; 01189 bool FLEXE = false; 01190 if (!OptionText && !OptionTime) { 01191 01192 // We have to decide what format to generate 01193 // for numeric labels only) 01194 // Test the magnitude, decide format 01195 FLEXE = false; 01196 NEXE = 0; 01197 bool FLEXPO = false; 01198 bool FLEXNE = false; 01199 WW = inlib::mx(TMath_Abs(wmin),TMath_Abs(wmax)); 01200 01201 // First case : (wmax-wmin)/N1A less than 0.001 01202 // 0.001 fMaxDigits of 5 (fMaxDigits) characters). 01203 // Then we use x 10 n 01204 // format. If AF >=0 x10 n cannot be used 01205 double xmicros = 0.00099; 01206 if (maxDigits) xmicros = ::pow(10.,-maxDigits); 01207 if (!noExponent && (TMath_Abs(wmax-wmin)/double(N1A)) < xmicros) { 01208 AF = ::log10(WW) + epsilon; 01209 if (AF < 0) { 01210 FLEXE = true; 01211 NEXE = int(AF); 01212 int IEXE = TMath_Abs(NEXE); 01213 if (IEXE%3 == 1) IEXE += 2; 01214 else if(IEXE%3 == 2) IEXE += 1; 01215 if (NEXE < 0) NEXE = -IEXE; 01216 else NEXE = IEXE; 01217 Wlabel = Wlabel*::pow(10.,IEXE); 01218 DWlabel = DWlabel*::pow(10.,IEXE); 01219 IF1 = maxDigits; 01220 IF2 = maxDigits-2; 01221 goto L110; 01222 } 01223 } 01224 if (WW >= 1) AF = ::log10(WW); 01225 else AF = ::log10(WW*0.0001); 01226 AF += epsilon; 01227 NF = int(AF)+1; 01228 if (!noExponent && NF > maxDigits) FLEXPO = true; 01229 if (!noExponent && NF < -maxDigits) FLEXNE = true; 01230 01231 // Use x 10 n format. (only powers of 3 allowed) 01232 01233 if (FLEXPO) { 01234 FLEXE = true; 01235 while (1) { 01236 NEXE++; 01237 WW /= 10; 01238 Wlabel /= 10; 01239 DWlabel /= 10; 01240 if (NEXE%3 == 0 && WW <= ::pow(10.,maxDigits-1)) break; 01241 } 01242 } 01243 01244 if (FLEXNE) { 01245 FLEXE = true; 01246 RNE = 1/::pow(10.,maxDigits-2); 01247 while (1) { 01248 NEXE--; 01249 WW *= 10; 01250 Wlabel *= 10; 01251 DWlabel *= 10; 01252 if (NEXE%3 == 0 && WW >= RNE) break; 01253 } 01254 } 01255 01256 NA = 0; 01257 for (i=maxDigits-1; i>0; i--) { 01258 if (TMath_Abs(WW) < ::pow(10.,i)) NA = maxDigits-i; 01259 } 01260 ndyn = N1A; 01261 while (ndyn) { 01262 double wdyn = TMath_Abs((wmax-wmin)/ndyn); 01263 if (wdyn <= 0.999 && NA < maxDigits-2) { 01264 NA++; 01265 ndyn /= 10; 01266 } 01267 else break; 01268 } 01269 01270 IF2 = NA; 01271 IF1 = inlib::mx(NF+NA,maxDigits)+1; 01272 L110: 01273 if (inlib::mn(wmin,wmax) < 0)IF1 = IF1+1; 01274 IF1 = inlib::mn(IF1,32); 01275 01276 // In some cases, IF1 and IF2 are too small.... 01277 while (DWlabel < ::pow(10.,-IF2)) { 01278 IF1++; 01279 IF2++; 01280 } 01281 //char* CODED = &CHCODED[0]; //GB : comment out. 01282 if (IF1 > 14) IF1=14; 01283 if (IF2 > 14) IF2=14; 01284 #ifdef WIN32 01285 if(IF2)_snprintf(CHCODED,sizeof(CHCODED),"%%%d.%df",IF1,IF2); 01286 else _snprintf(CHCODED,sizeof(CHCODED),"%%%d.%df",IF1+1,1); 01287 #else 01288 if(IF2)::snprintf(CHCODED,sizeof(CHCODED),"%%%d.%df",IF1,IF2); 01289 else ::snprintf(CHCODED,sizeof(CHCODED),"%%%d.%df",IF1+1,1); 01290 #endif 01291 } 01292 01293 // We draw labels 01294 01295 #ifdef WIN32 01296 _snprintf(CHTEMP,sizeof(CHTEMP),"%g",DWlabel); 01297 #else 01298 ::snprintf(CHTEMP,sizeof(CHTEMP),"%g",DWlabel); 01299 #endif 01300 int ndecimals = 0; 01301 if (OptionDecimals) { 01302 char *dot = ::strchr(CHTEMP,'.'); 01303 if (dot) ndecimals = CHTEMP + ::strlen(CHTEMP) -dot; 01304 } 01305 int Nlabels; 01306 if (OptionM) Nlabels = N1A-1; 01307 else Nlabels = N1A; 01308 double wTimeIni = Wlabel; 01309 for ( k=0; k<=Nlabels; k++) { 01310 /*FIXME if (fFunction) { 01311 double xx = BinLow+double(k*NN2)*DXtick; 01312 double zz = fFunction->Eval(xx)-rwmi; 01313 Wlabel = xx; 01314 Xlabel = zz* axis_length / TMath_Abs(rwma-rwmi); 01315 } else */{ 01316 Xlabel = DXlabel*k; 01317 } 01318 if (OptionM) Xlabel += 0.5*DXlabel; 01319 01320 if (!OptionText && !OptionTime) { 01321 #ifdef WIN32 01322 _snprintf(LABEL,sizeof(LABEL),&CHCODED[0],Wlabel); 01323 #else 01324 ::snprintf(LABEL,sizeof(LABEL),&CHCODED[0],Wlabel); 01325 #endif 01326 LABEL[28] = 0; 01327 Wlabel += DWlabel; 01328 01329 TGaxis_LabelsLimits(LABEL,first,last); //Eliminate blanks 01330 01331 if (LABEL[first] == '.') { //check if '.' is preceeded by a digit 01332 ::strcpy(CHTEMP, "0"); 01333 ::strcat(CHTEMP, &LABEL[first]); 01334 ::strcpy(LABEL, CHTEMP); 01335 first = 1; last = ::strlen(LABEL); 01336 } 01337 if (LABEL[first] == '-' && LABEL[first+1] == '.') { 01338 ::strcpy(CHTEMP, "-0"); 01339 ::strcat(CHTEMP, &LABEL[first+1]); 01340 ::strcpy(LABEL, CHTEMP); 01341 first = 1; last = ::strlen(LABEL); 01342 } 01343 01344 // We eliminate the non significant 0 after '.' 01345 if (ndecimals) { 01346 char *adot = ::strchr(LABEL,'.'); 01347 if (adot) adot[ndecimals] = 0; 01348 } else { 01349 while (LABEL[last] == '0') { LABEL[last] = 0; last--;} 01350 } 01351 // We eliminate the dot, unless dot is forced. 01352 if (LABEL[last] == '.') { 01353 if (!OptionDot) { LABEL[last] = 0; last--;} 01354 } 01355 } 01356 01357 // Generate the time labels 01358 01359 if (OptionTime) { 01360 double timed = Wlabel + (int)(timeoffset) - rangeOffset; 01361 time_t timelabel = (time_t)((long)(timed)); 01362 struct tm* utctis; 01363 if (OptionTime == 1) { 01364 utctis = localtime(&timelabel); 01365 } else { 01366 utctis = gmtime(&timelabel); 01367 } 01368 std::string timeformattmp; 01369 if (timeformat.size() < 220) timeformattmp = timeformat; 01370 else timeformattmp = "#splitline{Format}{too long}"; 01371 01372 // Appends fractionnal part if seconds displayed 01373 if (DWlabel<0.9) { 01374 double tmpdb; 01375 int tmplast; 01376 #ifdef WIN32 01377 _snprintf(LABEL,sizeof(LABEL), 01378 "%%S%7.5f",modf(timed,&tmpdb)); 01379 #else 01380 ::snprintf(LABEL,sizeof(LABEL), 01381 "%%S%7.5f",modf(timed,&tmpdb)); 01382 #endif 01383 tmplast = ::strlen(LABEL)-1; 01384 01385 // We eliminate the non significiant 0 after '.' 01386 while (LABEL[tmplast] == '0') { 01387 LABEL[tmplast] = 0; tmplast--; 01388 } 01389 01390 //FIXME timeformattmp.ReplaceAll("%S",LABEL); 01391 // Replace the "0." at the begining by "s" 01392 //FIXME timeformattmp.ReplaceAll("%S0.","%Ss"); 01393 01394 } 01395 01396 ::strftime(LABEL,256,timeformattmp.c_str(),utctis); 01397 ::strcpy(CHTEMP,&LABEL[0]); 01398 first = 0; last=::strlen(LABEL)-1; 01399 Wlabel = wTimeIni + (k+1)*DWlabel; 01400 } 01401 01402 // We generate labels (numeric or alphanumeric). 01403 01404 if (OptionNoopt && !OptionInt) 01405 TGaxis_Rotate (Xlabel,Ylabel,cosphi,sinphi,X0,Y0,XX,YY); 01406 else TGaxis_Rotate (Xlabel,Ylabel,cosphi,sinphi,XX0,YY0,XX,YY); 01407 if (Y0 == Y1 && !OptionDown && !OptionUp) { 01408 YY -= 0.80*charheight; 01409 } 01410 if (OptionVert) { 01411 if (X0 != X1 && Y0 != Y1) { 01412 if (OptionNoopt && !OptionInt) 01413 TGaxis_Rotate (Xlabel,0,cosphi,sinphi,X0,Y0,XX,YY); 01414 else TGaxis_Rotate (Xlabel,0,cosphi,sinphi,XX0,YY0,XX,YY); 01415 if (cosphi > 0 ) YY += Ylabel; 01416 if (cosphi < 0 ) YY -= Ylabel; 01417 } 01418 } 01419 if (!OptionY || (X0 == X1)) { 01420 if (!OptionText) { 01421 if (first > last) ::strcpy(CHTEMP, " "); 01422 else ::strcpy(CHTEMP, &LABEL[first]); 01423 aTexts.push_back(_text(XX,YY, 01424 0,textSize,CHTEMP, 01425 textAlign)); 01426 } 01427 else { 01428 if (OptionText == 1) { 01429 Error("PaintAxis","debug : texts : dummy : 006\n"); 01430 /*textaxis->PaintLatex 01431 (gPad->GetX1() + XX*(gPad->GetX2() - gPad->GetX1()), 01432 gPad->GetY1() + YY*(gPad->GetY2() - gPad->GetY1()), 01433 0, 01434 textaxis->GetTextSize(), 01435 fAxis->GetBinLabel(k+fAxis->GetFirst()));*/ 01436 } 01437 } 01438 } 01439 else { 01440 01441 // Text alignment is down 01442 int LNLEN = 0; 01443 if (!OptionText) LNLEN = last-first+1; 01444 else { 01445 int NHILAB = 0; 01446 if (k+1 > NHILAB) LNLEN = 0; 01447 } 01448 for ( l=1; l<=LNLEN; l++) { 01449 if (!OptionText) *CHTEMP = LABEL[first+l-2]; 01450 else { 01451 if (LNLEN == 0) ::strcpy(CHTEMP, " "); 01452 else ::strcpy(CHTEMP, "1"); 01453 } 01454 aTexts.push_back(_text(XX,YY, 01455 0,textSize,CHTEMP, 01456 textAlign)); 01457 YY -= charheight*1.3; 01458 } 01459 } 01460 } 01461 01462 // We use the format x 10 ** n 01463 01464 if (FLEXE && !OptionText && NEXE) { 01465 //G.Barrand ::sprintf(LABEL,"#times10^{%d}", NEXE); 01466 #ifdef WIN32 01467 _snprintf(LABEL,sizeof(LABEL), 01468 "x10^%d!", NEXE); //G.Barrand : PAW encoding. 01469 #else 01470 ::snprintf(LABEL,sizeof(LABEL), 01471 "x10^%d!", NEXE); //G.Barrand : PAW encoding. 01472 #endif 01473 double Xfactor, Yfactor; 01474 if (X0 != X1) { Xfactor = X1-X0+0.1*charheight; Yfactor = 0; } 01475 else { Xfactor = Y1-Y0+0.1*charheight; Yfactor = 0; } 01476 TGaxis_Rotate (Xfactor,Yfactor,cosphi,sinphi,X0,Y0,XX,YY); 01477 textAlign = 11; 01478 aTexts.push_back(_text(XX,YY, 01479 0,textSize,LABEL, 01480 textAlign)); 01481 } 01482 } 01483 } 01484 } 01485 01486 // Log axis 01487 01488 //Error("android_debug","0015"); 01489 if (OptionLog && ndiv) { 01490 unsigned int xi1=0,xi2 = 0,wi = 0,yi1=0,yi2,hi = 0; 01491 bool firstintlab = true, overlap = false; 01492 if ((wmin == wmax) || (ndiv == 0)) { 01493 Error("PaintAxis", "wmin (%f) == wmax (%f), or ndiv == 0", wmin, wmax); 01494 return; //goto L210; 01495 } 01496 if (wmin <= 0) { 01497 Error("PaintAxis", "negative logarithmic axis"); 01498 return; //goto L210; 01499 } 01500 if (wmax <= 0) { 01501 Error("PaintAxis", "negative logarithmic axis"); 01502 return; //goto L210; 01503 } 01504 double XMNLOG = ::log10(wmin); 01505 if (XMNLOG > 0) XMNLOG += 1.E-6; 01506 else XMNLOG -= 1.E-6; 01507 double X00 = 0; 01508 double X11 = axis_length; 01509 double H2 = ::log10(wmax); 01510 double H2SAV = H2; 01511 if (H2 > 0) H2 += 1.E-6; 01512 else H2 -= 1.E-6; 01513 int IH1 = int(XMNLOG); 01514 int IH2 = 1+int(H2); 01515 int NBININ = IH2-IH1+1; 01516 double AXMUL = (X11-X00)/(H2SAV-XMNLOG); 01517 01518 // Plot decade and intermediate tick marks 01519 decade = IH1-2; 01520 int labelnumber = IH1; 01521 if ( XMNLOG > 0 && (XMNLOG-double(IH1) > 0) ) labelnumber++; 01522 for (j=1; j<=NBININ; j++) { 01523 01524 // Plot decade 01525 firstintlab = true, overlap = false; 01526 decade++; 01527 if (X0 == X1 && j == 1) Ylabel += charheight*0.33; 01528 if (Y0 == Y1 && j == 1) Ylabel -= charheight*0.65; 01529 double Xone = X00+AXMUL*(double(decade)-XMNLOG); 01530 //the following statement is a trick to circumvent a gcc bug 01531 //GB if (j < 0) ::printf("j=%d\n",j); //G.Barrand : ??? 01532 if (X00 > Xone) goto L160; 01533 if (Xone > X11) break; 01534 Xtwo = Xone; 01535 Y = 0; 01536 if (!Mside) Y -= atick[0]; 01537 TGaxis_Rotate(Xone,Y,cosphi,sinphi,X0,Y0,xpl2,ypl2); 01538 TGaxis_Rotate(Xtwo,atick[0],cosphi,sinphi,X0,Y0,xpl1,ypl1); 01539 if (OptionVert) { 01540 if ((X0 != X1) && (Y0 != Y1)) { 01541 if (Mside) { 01542 xpl1=xpl2; 01543 if (cosphi > 0) ypl1 = ypl2 + atick[0]; 01544 else ypl1 = ypl2 - atick[0]; 01545 } 01546 else { 01547 xpl1 = 0.5*(xpl1 + xpl2); 01548 xpl2 = xpl1; 01549 ypl1 = 0.5*(ypl1 + ypl2) + atick[0]; 01550 ypl2 = 0.5*(ypl1 + ypl2) - atick[0]; 01551 } 01552 } 01553 } 01554 if (!drawGridOnly) { 01555 aLinesAxis.push_back((float)xpl1); 01556 aLinesAxis.push_back((float)ypl1); 01557 aLinesAxis.push_back((float)xpl2); 01558 aLinesAxis.push_back((float)ypl2); 01559 } 01560 01561 if (OptionGrid) { 01562 TGaxis_Rotate(Xone,0,cosphi,sinphi,X0,Y0,xpl2,ypl2); 01563 TGaxis_Rotate(Xone,grid_side*gridlength,cosphi,sinphi,X0,Y0, 01564 xpl1,ypl1); 01565 aLinesGrid.push_back((float)xpl1); 01566 aLinesGrid.push_back((float)ypl1); 01567 aLinesGrid.push_back((float)xpl2); 01568 aLinesGrid.push_back((float)ypl2); 01569 } 01570 01571 if (!drawGridOnly && !OptionUnlab) { 01572 01573 // We generate labels (numeric only). 01574 if (noExponent) { 01575 double rlab = ::pow(10.,labelnumber); 01576 #ifdef WIN32 01577 _snprintf(LABEL,sizeof(LABEL), "%f", rlab); 01578 #else 01579 ::snprintf(LABEL,sizeof(LABEL), "%f", rlab); 01580 #endif 01581 TGaxis_LabelsLimits(LABEL,first,last); 01582 while (last > first) { 01583 if (LABEL[last] != '0') break; 01584 LABEL[last] = 0; 01585 last--; 01586 } 01587 if (LABEL[last] == '.') {LABEL[last] = 0; last--;} 01588 } else { 01589 #ifdef WIN32 01590 _snprintf(LABEL,sizeof(LABEL), "%d", labelnumber); 01591 #else 01592 ::snprintf(LABEL,sizeof(LABEL), "%d", labelnumber); 01593 #endif 01594 TGaxis_LabelsLimits(LABEL,first,last); 01595 } 01596 TGaxis_Rotate (Xone,Ylabel,cosphi,sinphi,X0,Y0,XX,YY); 01597 if ((X0 == X1) && !OptionPara) { 01598 if (Lside < 0) { 01599 if (Mside < 0) { 01600 if (labelnumber == 0) NCH=1; 01601 else NCH=2; 01602 XX += NCH*charheight; 01603 } else { 01604 if (labelnumber >= 0) XX += 0.25*charheight; 01605 else XX += 0.50*charheight; 01606 } 01607 } 01608 XX += 0.25*charheight; 01609 } 01610 if ((Y0 == Y1) && !OptionDown && !OptionUp) { 01611 if (noExponent) YY += 0.33*charheight; 01612 } 01613 if (N1A == 0) return; //goto L210; 01614 int KMOD = NBININ/N1A; 01615 if (KMOD == 0) KMOD=1000000; 01616 if ((NBININ <= N1A) || (j == 1) || (j == NBININ) || ((NBININ > N1A) 01617 && (j%KMOD == 0))) { 01618 if (labelnumber == 0) { 01619 aTexts.push_back(_text(XX,YY, 01620 0,textSize,"1", 01621 textAlign)); 01622 } else if (labelnumber == 1) { 01623 aTexts.push_back(_text(XX,YY, 01624 0,textSize,"10", 01625 textAlign)); 01626 } else { 01627 if (noExponent) { 01628 Error("PaintAxis","debug : texts : FIXME : 003\n"); 01629 //FIXME textaxis->PaintTextNDC(XX,YY,&LABEL[first]); 01630 } else { 01631 //FIXME : support ROOT Latex encoding ? 01632 // ::sprintf(CHTEMP, "10^{%d}", labelnumber); 01633 #ifdef WIN32 01634 _snprintf(CHTEMP,sizeof(CHTEMP), 01635 "10^%d?", labelnumber); //PAW encoding. 01636 #else 01637 ::snprintf(CHTEMP,sizeof(CHTEMP), 01638 "10^%d?", labelnumber); //PAW encoding. 01639 #endif 01640 aTexts.push_back(_text(XX,YY, 01641 0,textSize,CHTEMP, 01642 textAlign)); 01643 } 01644 } 01645 } 01646 labelnumber++; 01647 } 01648 L160: 01649 for (k=2;k<10;k++) { 01650 01651 // Plot intermediate tick marks 01652 double Xone = X00+AXMUL*(::log10(double(k))+double(decade)-XMNLOG); 01653 if (X00 > Xone) continue; 01654 if (Xone > X11) goto L200; 01655 Y = 0; 01656 if (!Mside) Y -= atick[1]; 01657 Xtwo = Xone; 01658 TGaxis_Rotate(Xone,Y,cosphi,sinphi,X0,Y0,xpl2,ypl2); 01659 TGaxis_Rotate(Xtwo,atick[1],cosphi,sinphi,X0,Y0,xpl1,ypl1); 01660 if (OptionVert) { 01661 if ((X0 != X1) && (Y0 != Y1)) { 01662 if (Mside) { 01663 xpl1 = xpl2; 01664 if (cosphi > 0) ypl1 = ypl2 + atick[1]; 01665 else ypl1 = ypl2 - atick[1]; 01666 } 01667 else { 01668 xpl1 = 0.5*(xpl1+xpl2); 01669 xpl2 = xpl1; 01670 ypl1 = 0.5*(ypl1+ypl2) + atick[1]; 01671 ypl2 = 0.5*(ypl1+ypl2) - atick[1]; 01672 } 01673 } 01674 } 01675 int IDN = N1A*2; 01676 if ((NBININ <= IDN) || ((NBININ > IDN) && (k == 5))) { 01677 if(!drawGridOnly) { 01678 aLinesAxis.push_back((float)xpl1); 01679 aLinesAxis.push_back((float)ypl1); 01680 aLinesAxis.push_back((float)xpl2); 01681 aLinesAxis.push_back((float)ypl2); 01682 } 01683 01684 // Draw the intermediate LOG labels if requested 01685 01686 if (MoreLogLabels && !OptionUnlab && 01687 !drawGridOnly && !overlap) { 01688 if (noExponent) { 01689 double rlab = double(k)*::pow(10.,labelnumber-1); 01690 #ifdef WIN32 01691 _snprintf(CHTEMP,sizeof(CHTEMP), "%g", rlab); 01692 #else 01693 ::snprintf(CHTEMP,sizeof(CHTEMP), "%g", rlab); 01694 #endif 01695 } else { 01696 if (labelnumber-1 == 0) { 01697 #ifdef WIN32 01698 _snprintf(CHTEMP,sizeof(CHTEMP), "%d", k); 01699 #else 01700 ::snprintf(CHTEMP,sizeof(CHTEMP), "%d", k); 01701 #endif 01702 } else if (labelnumber-1 == 1) { 01703 #ifdef WIN32 01704 _snprintf(CHTEMP,sizeof(CHTEMP), "%d", 10*k); 01705 #else 01706 ::snprintf(CHTEMP,sizeof(CHTEMP), "%d", 10*k); 01707 #endif 01708 } else { 01709 //G.Barrand : 01710 //::sprintf(CHTEMP, "%d#times10^{%d}", k, labelnumber-1); 01711 #ifdef WIN32 01712 _snprintf(CHTEMP,sizeof(CHTEMP), 01713 "%dx10^%d!",k,labelnumber-1);//G.Barrand 01714 #else 01715 ::snprintf(CHTEMP,sizeof(CHTEMP), 01716 "%dx10^%d!",k,labelnumber-1);//G.Barrand 01717 #endif 01718 } 01719 } 01720 TGaxis_Rotate (Xone,Ylabel,cosphi,sinphi,X0,Y0,XX,YY); 01721 if ((Y0 == Y1) && !OptionDown && !OptionUp) { 01722 if (noExponent) YY += 0.33*charheight; 01723 } 01724 if ((X0 == X1)) XX += 0.25*charheight; 01725 if (OptionVert) { 01726 if ((X0 != X1) && (Y0 != Y1)) { 01727 TGaxis_Rotate(Xone,Ylabel,cosphi,sinphi,X0,Y0,XX,YY); 01728 if (cosphi > 0) YY += Ylabel; 01729 else YY -= Ylabel; 01730 } 01731 } 01732 //FIXME textaxis->SetTitle(CHTEMP); 01733 double u = XX; 01734 double v = YY; 01735 if (firstintlab) { 01736 //FIXME textaxis->GetBoundingBox(wi, hi); wi=(Uint)(wi*1.3); hi*=(Uint)(hi*1.3); 01737 xi1 = 0;//FIXME gPad->XtoAbsPixel(u); 01738 yi1 = 0;//FIXME gPad->YtoAbsPixel(v); 01739 firstintlab = false; 01740 Error("PaintAxis","debug : texts : dummy : 010\n"); 01741 aTexts.push_back(_text(u,v, 01742 0,textSize,CHTEMP, 01743 textAlign)); 01744 } else { 01745 xi2 = 0;//FIXME gPad->XtoAbsPixel(u); 01746 yi2 = 0;//FIXME gPad->YtoAbsPixel(v); 01747 if ((X0 == X1 && yi1-hi <= yi2) || (Y0 == Y1 && xi1+wi >= xi2)){ 01748 overlap = true; 01749 } else { 01750 xi1 = xi2; 01751 yi1 = yi2; 01752 //FIXME textaxis->GetBoundingBox(wi, hi); wi=(Uint)(wi*1.3); hi*=(Uint)(hi*1.3); 01753 Error("PaintAxis","debug : texts : dummy : 011\n"); 01754 aTexts.push_back(_text(u,v, 01755 0,textSize,CHTEMP, 01756 textAlign)); 01757 } 01758 } 01759 } 01760 01761 // Draw the intermediate LOG grid if only three 01762 // decades are requested 01763 if (OptionGrid && NBININ <= 5 && ndiv > 100) { 01764 TGaxis_Rotate(Xone,0,cosphi,sinphi,X0,Y0,xpl2, ypl2); 01765 TGaxis_Rotate 01766 (Xone,grid_side*gridlength,cosphi,sinphi,X0,Y0,xpl1,ypl1); 01767 aLinesGrid.push_back((float)xpl1); 01768 aLinesGrid.push_back((float)ypl1); 01769 aLinesGrid.push_back((float)xpl2); 01770 aLinesGrid.push_back((float)ypl2); 01771 } 01772 } //endif ((NBININ <= IDN) || 01773 } //endfor (k=2;k<10;k++) 01774 } //endfor (j=1; j<=NBININ; j++) 01775 L200: 01776 int kuku=0; if (kuku) { } 01777 } //endif (OptionLog && ndiv) 01778 01779 01780 //Error("android_debug","end"); 01781 //L210: 01782 } 01783 01784 /* 01785 void TGaxis_SetDecimals(bool dot) 01786 { 01787 // Set the Decimals flag 01788 // By default, blank characters are stripped, and then the 01789 // label is correctly aligned. The dot, if last character of the string, 01790 // is also stripped, unless this option is specified. 01791 // One can disable the option by calling axis.SetDecimals(true). 01792 // Note the bit is set in fBits (as opposed to fBits2 in TAxis!) 01793 01794 if (dot) SetBit(TAxis_kDecimals); 01795 else ResetBit(TAxis_kDecimals); 01796 } 01797 01798 void TGaxis_SetMaxDigits(int maxd) 01799 { 01800 // static function to set fMaxDigits for axis with the bin content 01801 // (y axis for 1-d histogram, z axis for 2-d histogram) 01802 //fMaxDigits is the maximum number of digits permitted for the axis 01803 //labels above which the notation with 10^N is used. 01804 //For example, to accept 6 digits number like 900000 on an axis 01805 //call TGaxis::SetMaxDigits(6). The default value is 5. 01806 //fMaxDigits must be greater than 0. 01807 01808 fMaxDigits = maxd; 01809 if (maxd < 1) fMaxDigits = 1; 01810 } 01811 01812 void TGaxis_SetMoreLogLabels(bool more) 01813 { 01814 // Set the kMoreLogLabels bit flag 01815 // When this option is selected more labels are drawn when in log scale 01816 // and there is a small number of decades (<3). 01817 // Note that this option is automatically inherited from TAxis 01818 01819 if (more) SetBit(TAxis_kMoreLogLabels); 01820 else ResetBit(TAxis_kMoreLogLabels); 01821 } 01822 void TGaxis_SetNoExponent(bool noExponent) 01823 { 01824 // Set the NoExponent flag 01825 // By default, an exponent of the form 10^N is used when the label values 01826 // are either all very small or very large. 01827 // One can disable the exponent by calling axis.SetNoExponent(true). 01828 01829 if (noExponent) SetBit(TAxis_kNoExponent); 01830 else ResetBit(TAxis_kNoExponent); 01831 } 01832 void TGaxis_SetOption(const std::string& option) 01833 { 01834 fCHOPT = option; 01835 } 01836 */ 01837 01838 void set_time_format(const std::string& a_format) 01839 // Change the format used for time plotting 01840 // ======================================== 01841 // The format string for date and time use the same options as the one used 01842 // in the standard strftime C function, i.e. : 01843 // for date : 01844 // %a abbreviated weekday name 01845 // %b abbreviated month name 01846 // %d day of the month (01-31) 01847 // %m month (01-12) 01848 // %y year without century 01849 // 01850 // for time : 01851 // %H hour (24-hour clock) 01852 // %I hour (12-hour clock) 01853 // %p local equivalent of AM or PM 01854 // %M minute (00-59) 01855 // %S seconds (00-61) 01856 // %% % 01857 // 01858 { 01859 if (a_format.find("%F")!=std::string::npos || !a_format.size()) { 01860 fTimeFormat = a_format; 01861 //::printf("debug : SbAxisHPLOT::setTimeFormat : 000 : \"%s\"\n", 01862 // fTimeFormat.c_str()); 01863 return; 01864 } 01865 01866 std::string::size_type IdF = fTimeFormat.find("%F"); 01867 if (IdF!=std::string::npos) { 01868 int LnF = fTimeFormat.size(); 01869 std::string stringtimeoffset = fTimeFormat.substr(IdF,LnF-IdF); 01870 fTimeFormat = a_format; 01871 fTimeFormat += stringtimeoffset; 01872 //::printf("debug : SbAxisHPLOT::setTimeFormat : 001 : \"%s\"\n", 01873 // fTimeFormat.c_str()); 01874 } else { 01875 fTimeFormat = a_format; 01876 01877 // In CERN-ROOT : 01878 //SetTimeOffset(gStyle->GetTimeOffset()); 01879 //TAxis::fTimeOffset = 788918400; // UTC time at 01/01/95 01880 //double UTC_time_1995_01_01__00_00_00 = 788918400; //CERN-ROOT 01881 //setTimeOffset(UTC_time_1995_01_01__00_00_00); 01882 01883 //Be consistent with SoAxis::timeOffset being 0. 01884 double UTC_time_1970_01_01__00_00_00 = 0; //UNIX 01885 set_time_offset(UTC_time_1970_01_01__00_00_00); 01886 01887 //::printf("debug : SbAxisHPLOT::setTimeFormat : 002 : \"%s\"\n", 01888 // fTimeFormat.c_str()); 01889 } 01890 } 01891 01892 void set_time_offset(double toffset,bool a_is_gmt = false) { 01893 // Change the time offse t 01894 01895 char tmp[20]; 01896 time_t timeoff; 01897 struct tm* utctis; 01898 std::string::size_type IdF = fTimeFormat.find("%F"); 01899 if (IdF!=std::string::npos) { 01900 fTimeFormat = fTimeFormat.substr(0,IdF); 01901 } 01902 fTimeFormat += "%F"; 01903 01904 timeoff = (time_t)((long)(toffset)); 01905 utctis = ::gmtime(&timeoff); 01906 01907 ::strftime(tmp,256,"%Y-%m-%d %H:%M:%S",utctis); 01908 fTimeFormat += tmp; 01909 01910 // append the decimal part of the time offset 01911 double ds = toffset-(int)toffset; 01912 if(ds!= 0) { 01913 #ifdef WIN32 01914 _snprintf(tmp,sizeof(tmp),"s%g",ds); 01915 #else 01916 ::snprintf(tmp,sizeof(tmp),"s%g",ds); 01917 #endif 01918 fTimeFormat += tmp; 01919 } 01920 01921 // If the time is GMT, stamp fTimeFormat 01922 if (a_is_gmt) fTimeFormat += " GMT"; 01923 01924 //::printf("debug : SbAxisHPLOT::setTimeOffset : \"%s\"\n", 01925 // fTimeFormat.c_str()); 01926 } 01927 01928 01929 01933 private: 01934 static void optimizeLimits( 01935 double A1,double A2,int nold 01936 ,double &BinLow, double &BinHigh 01937 ,int &nbins, double &BinWidth 01938 ,const std::string& aCHOPT 01939 ){ 01940 // static function to compute reasonable axis limits 01941 // 01942 // Input parameters: 01943 // 01944 // A1,A2 : Old WMIN,WMAX . 01945 // BinLow,BinHigh : New WMIN,WMAX . 01946 // nold : Old NDIV . 01947 // nbins : New NDIV . 01948 01949 int lwid, kwid; 01950 int ntemp = 0; 01951 int jlog = 0; 01952 double siground = 0; 01953 double alb, awidth, sigfig; 01954 double timemulti = 1; 01955 int roundmode =0; 01956 01957 int OptionTime; 01958 SETOPT(aCHOPT,'t',OptionTime); 01959 01960 double AL = inlib::mn(A1,A2); 01961 double AH = inlib::mx(A1,A2); 01962 if (AL == AH) AH = AL+1; 01963 // if nold == -1 , program uses binwidth input from calling routine 01964 if (nold == -1 && BinWidth > 0 ) goto L90; 01965 ntemp = inlib::mx(nold,2); 01966 if (ntemp < 1) ntemp = 1; 01967 01968 L20: 01969 awidth = (AH-AL)/double(ntemp); 01970 timemulti = 1; 01971 if (awidth >= FLT_MAX) goto LOK; //in float.h 01972 if (awidth <= 0) goto LOK; 01973 01974 // If time representation, bin width should be rounded to seconds 01975 // minutes, hours or days 01976 01977 if (OptionTime && awidth>=60) { // if width in seconds, treat it as normal 01978 // width in minutes 01979 awidth /= 60; timemulti *=60; 01980 roundmode = 1; // round minutes (60) 01981 // width in hours ? 01982 if (awidth>=60) { 01983 awidth /= 60; timemulti *= 60; 01984 roundmode = 2; // round hours (24) 01985 // width in days ? 01986 if (awidth>=24) { 01987 awidth /= 24; timemulti *= 24; 01988 roundmode = 3; // round days (30) 01989 // width in months ? 01990 if (awidth>=30.43685) { // Mean month length in 1900. 01991 awidth /= 30.43685; timemulti *= 30.43685; 01992 roundmode = 2; // round months (12) 01993 // width in years ? 01994 if (awidth>=12) { 01995 awidth /= 12; timemulti *= 12; 01996 roundmode = 0; // round years (10) 01997 } 01998 } 01999 } 02000 } 02001 } 02002 // Get nominal bin width in exponential for m 02003 02004 jlog = int(::log10(awidth)); 02005 if (jlog <-200 || jlog > 200) { 02006 BinLow = 0; 02007 BinHigh = 1; 02008 BinWidth = 0.01; 02009 nbins = 100; 02010 return; 02011 } 02012 if (awidth <= 1 && (!OptionTime || timemulti==1) ) jlog--; 02013 sigfig = awidth* ::pow(10.,-jlog) -1e-10; 02014 //in the above statement, it is important to substract 1e-10 02015 //to avoid precision problems if the tests below 02016 02017 // Round mantissa 02018 02019 switch (roundmode) { 02020 02021 // Round mantissa up to 1, 1.5, 2, 3, or 6 in case of minutes 02022 case 1: // case 60 02023 if (sigfig <= 1) siground = 1; 02024 else if (sigfig <= 1.5 && jlog==1) siground = 1.5; 02025 else if (sigfig <= 2) siground = 2; 02026 else if (sigfig <= 3 && jlog ==1) siground = 3; 02027 else if (sigfig <= 5 && sigfig>3 && jlog ==0) siground = 5; //added (Damir in 3.10/02) 02028 else if (jlog==0) {siground = 1; jlog++;} 02029 else siground = 6; 02030 break; 02031 case 2: // case 12 and 24 02032 02033 // Round mantissa up to 1, 1.2, 2, 2.4, 3 or 6 in case of hours or months 02034 if (sigfig <= 1 && jlog==0) siground = 1; 02035 else if (sigfig <= 1.2 && jlog==1) siground = 1.2; 02036 else if (sigfig <= 2 && jlog==0) siground = 2; 02037 else if (sigfig <= 2.4 && jlog==1) siground = 2.4; 02038 else if (sigfig <= 3) siground = 3; 02039 else if (sigfig <= 6) siground = 6; 02040 else if (jlog==0) siground = 12; 02041 else siground = 2.4; 02042 break; 02043 02044 //- Round mantissa up to 1, 1.4, 2, or 7 in case of days (weeks) 02045 case 3: // case 30 02046 if (sigfig <= 1 && jlog==0) siground = 1; 02047 else if (sigfig <= 1.4 && jlog==1) siground = 1.4; 02048 else if (sigfig <= 3 && jlog ==1) siground = 3; 02049 else siground = 7; 02050 break; 02051 default : 02052 02053 // Round mantissa up to 1, 2, 2.5, 5, or 10 in case of decimal number 02054 if (sigfig <= 1) siground = 1; 02055 else if (sigfig <= 2) siground = 2; 02056 else if (sigfig <= 5 && (!OptionTime || jlog<1)) siground = 5; 02057 else if (sigfig <= 6 && OptionTime && jlog==1) siground = 6; 02058 else {siground = 1; jlog++; } 02059 break; 02060 } 02061 02062 BinWidth = siground* ::pow(10.,jlog); 02063 if (OptionTime) BinWidth *= timemulti; 02064 02065 // Get new bounds from new width BinWidth 02066 02067 L90: 02068 alb = AL/BinWidth; 02069 if (TMath_Abs(alb) > 1e9) { 02070 BinLow = AL; 02071 BinHigh = AH; 02072 if (nbins > 10*nold && nbins > 10000) nbins = nold; 02073 return; 02074 } 02075 lwid = int(alb); 02076 if (alb < 0) lwid--; 02077 BinLow = BinWidth*double(lwid); 02078 alb = AH/BinWidth + 1.00001; 02079 kwid = int(alb); 02080 if (alb < 0) kwid--; 02081 BinHigh = BinWidth*double(kwid); 02082 nbins = kwid - lwid; 02083 if (nold == -1) goto LOK; 02084 if (nold <= 5) { // Request for one bin is difficult case 02085 if (nold > 1 || nbins == 1)goto LOK; 02086 BinWidth = BinWidth*2; 02087 nbins = 1; 02088 goto LOK; 02089 } 02090 if (2*nbins == nold && !OptionTime) {ntemp++; goto L20; } 02091 02092 LOK: 02093 double oldBinLow = BinLow; 02094 double oldBinHigh = BinHigh; 02095 int oldnbins = nbins; 02096 02097 double atest = BinWidth*0.0001; 02098 //if (TMath_Abs(BinLow-A1) >= atest) { BinLow += BinWidth; nbins--; } //replaced by Damir in 3.10/02 02099 //if (TMath_Abs(BinHigh-A2) >= atest) { BinHigh -= BinWidth; nbins--; } //by the next two lines 02100 if (AL-BinLow >= atest) { BinLow += BinWidth; nbins--; } 02101 if (BinHigh-AH >= atest) { BinHigh -= BinWidth; nbins--; } 02102 if (!OptionTime && BinLow >= BinHigh) { 02103 //this case may happen when nbins <=5 02104 BinLow = oldBinLow; 02105 BinHigh = oldBinHigh; 02106 nbins = oldnbins; 02107 } 02108 else if (OptionTime && BinLow>=BinHigh) { 02109 nbins = 2*oldnbins; 02110 BinHigh = oldBinHigh; 02111 BinLow = oldBinLow; 02112 BinWidth = (oldBinHigh - oldBinLow)/nbins; 02113 double atest = BinWidth*0.0001; 02114 if (AL-BinLow >= atest) { BinLow += BinWidth; nbins--; } 02115 if (BinHigh-AH >= atest) { BinHigh -= BinWidth; nbins--; } 02116 } 02117 } 02118 02119 static void adjustBinSize( 02120 double A1,double A2,int nold 02121 ,double &BinLow, double &BinHigh, int &nbins, double &BinWidth 02122 ){ 02123 // Axis labels optimisation 02124 // ======================== 02125 // 02126 // This routine adjusts the bining of the axis 02127 // in order to have integer values for the labels 02128 // 02129 // _Input parameters: 02130 // 02131 // A1,A2 : Old WMIN,WMAX . 02132 // BinLow,BinHigh : New WMIN,WMAX . 02133 // nold : Old NDIV (primary divisions) 02134 // nbins : New NDIV . 02135 // 02136 BinWidth = TMath_Abs(A2-A1)/double(nold); 02137 if (BinWidth <= 1) { BinWidth = 1; BinLow = int(A1); } 02138 else { 02139 int width = int(BinWidth/5) + 1; 02140 BinWidth = 5*width; 02141 BinLow = int(A1/BinWidth)*BinWidth ; 02142 02143 // We determine BinLow to have one tick mark at 0 02144 // if there are negative labels. 02145 02146 if (A1 < 0) { 02147 for (int ic=0; ic<1000; ic++) { 02148 double rbl = BinLow/BinWidth; 02149 int ibl = int(BinLow/BinWidth); 02150 if ( (rbl-ibl) == 0 || ic > width) { BinLow -= 5; break;} 02151 } 02152 } 02153 } 02154 BinHigh = int(A2); 02155 nbins = 0; 02156 double XB = BinLow; 02157 while (XB <= BinHigh) { 02158 XB += BinWidth; 02159 nbins++; 02160 } 02161 BinHigh = XB - BinWidth; 02162 } 02163 void setLabelOffset(float aValue) { fLabelOffset = aValue;} 02164 void setLabelSize(float aValue) { fLabelSize = aValue;} 02165 void setTitleOffset(float aValue) { fTitleOffset = aValue;} 02166 void setTitleSize(float aValue) { fTitleSize = aValue; } 02167 public: 02168 void set_tick_size(float aValue) { fTickSize = aValue;} 02169 02170 private: 02171 int fMaxDigits; 02172 private: 02173 //TObject : 02174 unsigned int fBits; //bit field status word 02175 float fTickSize; //Size of primary tick mark in NDC 02176 float fLabelOffset; //Offset of label wrt axis 02177 float fLabelSize; //Size of labels in NDC 02178 float fTitleOffset; //Offset of title wrt axis 02179 float fTitleSize; //Size of title in NDC 02180 int fLabelFont; //Font for labels 02181 std::string fTitle; //axis title 02182 std::string fTimeFormat; //Time format, ex: 09/12/99 12:34:00 02183 }; 02184 02185 }} 02186 02187 #endif