inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/hplot
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines