Changeset 2091 in Sophya for trunk/SophyaPI


Ignore:
Timestamp:
Jul 13, 2002, 6:08:49 PM (23 years ago)
Author:
cmv
Message:
  • gestion des ticks et des labels pour les axes log
  • gestion plus precise des ecriture de labels

--> chgnt PIVERSION = 3.69 cmv 13/07/2002

Location:
trunk/SophyaPI/PI
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/SophyaPI/PI/piaxes.cc

    r2088 r2091  
    99#include "piaxes.h"
    1010
    11 inline void dble_SWAP(double a, double b) {double tmp=a; a=b; b=tmp;}
     11inline void dble_SWAP(double& a,double& b) {double tmp=a; a=b; b=tmp;}
    1212
    1313/* --Methode-- */
     
    166166  aYlog = g->isLogScaleY();
    167167
    168   int ntick_x = (aXlog) ? 6 : 10;
    169   BestTicks(xMin,xMax,ntick_x,xMajTicks,xMinTicks);
    170 
    171   int ntick_y = (aYlog) ? 6 : 12;
    172   BestTicks(yMin,yMax,ntick_y,yMajTicks,yMinTicks);
     168  int ntick_x = (aXlog) ? 10 : 10;
     169  if(aXlog) BestTicksLog(xMin,xMax,ntick_x,xMajTicks,xMinTicks);
     170  else BestTicks(xMin,xMax,ntick_x,xMajTicks,xMinTicks);
     171
     172  int ntick_y = (aYlog) ? 12 : 12;
     173  if(aYlog) BestTicksLog(yMin,yMax,ntick_y,yMajTicks,yMinTicks);
     174  else BestTicks(yMin,yMax,ntick_y,yMajTicks,yMinTicks);
    173175
    174176  yMajTickLen = (xMax-xMin)/100;
     
    183185                        double tickDown, vector<double>& xticks)
    184186{
    185   if(xticks.size()<=0) return;
     187  if(xticks.size()==0) return;
    186188  for(unsigned int i=0;i<xticks.size();i++) {
     189    if(xticks[i]<xMin) continue;
    187190    if(xticks[i]>xMax) break;
    188191    g->DrawLine(xticks[i],g->DeltaUCY(y,-tickDown),xticks[i],g->DeltaUCY(y,tickUp));
     
    194197                        double tickRight, vector<double>& yticks)
    195198{
    196   if(yticks.size()<=0) return;
     199  if(yticks.size()==0) return;
    197200  for(unsigned int i=0;i<yticks.size();i++) {
     201    if(yticks[i]<yMin) continue;
    198202    if(yticks[i]>yMax) break;
    199203    g->DrawLine(g->DeltaUCX(x,-tickLeft),yticks[i],g->DeltaUCX(x,tickRight),yticks[i]);
     
    204208void PIAxes::DrawHLabels(PIGraphicUC* g, double y, vector<double>& xticks, unsigned long just)
    205209{
    206 
    207   if(xticks.size()<=1) return;
    208   // Choix du bon format pour les labels des axes;
    209   char label[64]; string format; double fac=1.; bool p10=false;
    210   double xstep=xticks[1]-xticks[0];
    211   int npuiss = BonFormatAxes(xticks[0],xMax,xstep,format,2,1);
    212   if(npuiss<-2 || npuiss>3) {p10 = true; fac=pow(10.,(double)npuiss);}
    213   else BonFormatAxes(xticks[0],xMax,xstep,format,0,1);
    214 
    215   double xOffset = 0;
    216   double xlastlabelfin = xticks[0] - 2.*(xMax-xticks[0]);
     210  if(xticks.size()==0) return;
     211
     212  // Choix du bon format pour les labels des axes
     213  string format; double xstep;
     214  int npuiss = Le_Bon_Format(xticks,format,xstep);
     215  double fac=(npuiss!=0)? fac=pow(10.,(double)npuiss): 1.;
     216
     217  char label[64];
     218  double dum,xpixdeb,xpixfin,largpix;
     219  g->UC2GrC(xMin-2.*(xMax-xMin),y,xpixfin,dum);
    217220  for(unsigned int i=0;i<xticks.size();i++) {
     221    if(xticks[i]<xMin) continue;
    218222    if(xticks[i]>xMax) break;
    219223    //Attention erreur d'arrondi x->0 (on code 5.1698e-26 au lieu de 0)
    220224    double xx = (fabs(xticks[i]/xstep)<1.e-5) ? 0.: xticks[i];
    221     sprintf(label,format.c_str(),xx/fac);
    222     Arrange_Label(label);
     225    sprintf(label,format.c_str(),xx/fac); Arrange_Label(label);
    223226    double largeur = g->CalcStringWidth(label);
    224     if(aXdir) xOffset = largeur/2; else xOffset=-largeur/2;
    225     if(xticks[i]+xOffset > xlastlabelfin) {
     227    g->DUC2GrC(largeur,0.,largpix,dum);
     228    g->UC2GrC(xticks[i],y,xpixdeb,dum);   xpixdeb -= largpix/2.;
     229    //cout<<"xticks="<<xticks[i]<<" largpix="<<largpix
     230    //    <<" xpixdeb="<<xpixdeb<<" xpixfin="<<xpixfin<<endl;
     231    if((aXdir && xpixdeb<xpixfin) || (!aXdir && xpixdeb>xpixfin)) {
    226232      g->DrawString(xticks[i],y,label,PI_HorizontalCenter|just);
    227       xlastlabelfin = xticks[i] + xOffset + 1.1*largeur;
    228     }
    229   }
    230 
    231   if(p10) {
     233      xpixfin = xpixdeb + 1.1*largpix;
     234    }
     235  }
     236
     237  if(npuiss!=0) {
    232238    PIGrCoord asc,desc;
    233239    double h = g->GetFontHeight(asc,desc);
    234     if((aYdir && (just&PI_VerticalBottom)) || (!aYdir && (just&PI_VerticalTop)) ) h = -h;
     240    if((aYdir && (just&PI_VerticalBottom)) || (!aYdir && (just&PI_VerticalTop))) h=-h;
    235241    double xm = (aXdir)? xMin: xMax;
    236242    double ym = g->DeltaUCY(y,1.5*h);
     
    244250void PIAxes::DrawVLabels(PIGraphicUC* g, double x, vector<double>& yticks, unsigned long just)
    245251{
    246 
    247   if(yticks.size()<=1) return;
     252  if(yticks.size()==0) return;
     253
    248254  // Choix du bon format pour les labels des axes;
    249   char label[64]; string format; double fac=1.; bool p10=false;
    250   double ystep=yticks[1]-yticks[0];
    251   int npuiss = BonFormatAxes(yticks[0],yMax,ystep,format,2,1);
    252   if(npuiss<-2 || npuiss>3) {p10 = true; fac=pow(10.,(double)npuiss);}
    253   else BonFormatAxes(yticks[0],yMax,ystep,format,0,1);
    254 
     255  string format; double ystep;
     256  int npuiss = Le_Bon_Format(yticks,format,ystep);
     257  double fac=(npuiss!=0)? fac=pow(10.,(double)npuiss): 1.;
     258
     259  char label[64];
     260  PIGrCoord asc,desc;
     261  double dum,ypixdeb,ypixfin,hautpix,hauteur=g->GetFontHeight(asc,desc);
     262  g->DUC2GrC(0.,hauteur,dum,hautpix);
     263  g->UC2GrC(x,yMin-2.*(yMax-yMin),dum,ypixfin);
    255264  for(unsigned int i=0;i<yticks.size();i++) {
     265    if(yticks[i]<yMin) continue;
    256266    if(yticks[i]>yMax) break;
    257267    double yy = (fabs(yticks[i]/ystep)<1.e-5) ? 0.: yticks[i];
    258     sprintf(label,format.c_str(),yy/fac);
    259     Arrange_Label(label);
    260     g->DrawString(x,yticks[i],label,PI_VerticalCenter|just);
    261   }
    262 
    263   if(p10) {
    264     PIGrCoord asc,desc;
    265     double h = g->GetFontHeight(asc,desc);
    266     if(aYdir) h = -h;
    267     double ym = (aYdir)? yMin: yMax; ym = g->DeltaUCY(ym,h);
     268    sprintf(label,format.c_str(),yy/fac); Arrange_Label(label);
     269    g->UC2GrC(x,yticks[i],dum,ypixdeb);   ypixdeb -= hautpix/2.;
     270    // -- Attention: ypix=0 est en haut de l'ecran
     271    //               (ypix croissants vers le bas de l'ecran)
     272    //    donc bien que yMin<yMax on a yMinPix>yMaxPix
     273    //cout<<"yticks="<<yticks[i]<<" hautpix="<<hautpix
     274    //    <<" ypixdeb="<<ypixdeb<<" ypixfin="<<ypixfin<<endl;
     275    if((aYdir && ypixdeb>ypixfin) || (!aYdir && ypixdeb<ypixfin)) {
     276      g->DrawString(x,yticks[i],label,PI_VerticalCenter|just);
     277      ypixfin = ypixdeb + 1.1*hautpix;
     278    }
     279  }
     280
     281  if(npuiss!=0) {
     282    if(aYdir) hauteur = -hauteur;
     283    double ym = (aYdir)? yMin: yMax; ym = g->DeltaUCY(ym,hauteur);
    268284    sprintf(label,"%d",npuiss);
    269285    g->DrawCompString(x,ym,"x 10",label,NULL,PI_VerticalBottom|just);
     
    293309}
    294310
    295 
    296 ///////////////////////////////////////////////////////////////////////////
     311////////////////////////////////////////////////////////////////////////
     312//////////////////// METHODES STATIQUES ////////////////////////////////
     313////////////////////////////////////////////////////////////////////////
    297314/* --Methode-Static-- */
    298315void PIAxes::BestTicks(double xmin,double xmax,int nticks
    299316                      ,vector<double>& majticks,vector<double>& minticks)
    300317// *** Calcul de l'intervalle entre les ticks et de la valeur du premier tick
    301 {
    302  double d=xmax-xmin; if(d<1.e-100) d=1.e-100; //if (d<1.e-39) d=1.e-39;
     318//     pour un axe lineaire
     319{
     320 if(nticks<=0) nticks = 1;
     321
     322 double d=xmax-xmin; if(d<1.e-100) d=1.e-100;
    303323 double ld  = log10(d);
    304324 double fld = floor( ((ld<0.)? -ld: ld) );
    305325 double del,del0;
    306  majticks.resize(0); minticks.resize(0);
    307  if(ld>=0.) {fld-=1.; del0=del=pow(10.,fld);}
    308    else     {fld+=2.; del0=del=pow(10.,-fld);}
     326 fld = (ld>=0.)? fld-2.: -(fld+2.);
     327 del0 = del = pow(10.,fld);
    309328 // *** Intervalle entre les ticks
    310329 // xmin  xmax    d       ld       fld -->fld  del0
    311  // 1     1500    1499    3.17     3      2    10^2
    312  // 1     9500    9499    3.98     3      2    10^2
    313  // 1     1.005   0.005   -2.3     2      4    10^-4
    314  // 1     1.995   0.995   -0.0022  0      2    10^-2
    315  // - Et recherche de la valeur del={del0,2*del0,...,20*del0}
    316  // telle que "nticks*del" soit le plus petit nombre ">=d"
    317  // Par exemple, si nticks=10:
    318  // 1-/ pour le 2sd cas ou d=9499 et del0=100 :
    319  // del        =    100    200    500    1000    2000
    320  // nticks*del =   1000   2000   5000   10000   20000
    321  // d/del      =   94.9   47.4   18.9 | 9.499   4.749  ==> majt = 1000
    322  // 2-/ pour le 3ieme cas ou d=5e-3 et del0=1e-4 :
    323  // del        =  1e-4   2e-4   5e-4  1e-3   2e-3
    324  // nticks*del =  1e-3   2e-3   5e-3  1e-2   2e-2
    325  // d/del      =  50     25   | 10    5      2.5       ==> majt = 5e-4
    326  int k=0;
    327  double fac[4] = {2.,5.,10.,20.};
    328  while(d/del>(double)nticks && k<4 ) {del=fac[k]*del0; k++;}
     330 // 1     1500    1499    3.17     3      1    10^1
     331 // 1     9500    9499    3.98     3      1    10^1
     332 // 1     1.005   0.005  -2.3      3     -5    10^-5
     333 // 1     1.995   0.995  -0.0022   1     -3    10^-3
     334 // - Et recherche de la valeur del={del0,2*del0,...,20*del0,...}
     335 // telle que "nticks*del" soit le plus petit nombre ">=xmax-xmin"
     336 double fac[9] = {2.,5.,10.,20.,50.,100.,200.,500.,1000.};
     337 for(int k=0;k<9;k++) {
     338   //cout<<"BestTicks: "<<k<<" del="<<del<<" d/del="<<d/del<<"<"<<nticks<<endl;
     339   if(d/del < (double)nticks) break;
     340   del=fac[k]*del0;
     341 }
    329342 double steptick=del;
    330343 //***  Valeur du premier tick
    331  double xfirsttick = floor(xmin/steptick); if(xmin<0.) xfirsttick+=1.;
    332  xfirsttick *= steptick;
     344 majticks.resize(0);
     345 double xfirsttick = floor(fabs(xmin)/steptick)*steptick;
     346   if(xmin<0.) xfirsttick *= -1.;
    333347 if(xfirsttick<xmin) xfirsttick += steptick;
    334  majticks.push_back(xfirsttick);
    335  while(xfirsttick<=xmax)
    336    {xfirsttick+= steptick; majticks.push_back(xfirsttick);}
     348 while(xfirsttick<=xmax+steptick/10.)
     349   {majticks.push_back(xfirsttick); xfirsttick+= steptick;}
    337350 //***  Gestion des ticks mineurs
    338  double steptickmin = steptick/5.;
    339  double xfirsttickmin = floor(xmin/steptickmin) * steptickmin;
    340  if(xfirsttickmin<xmin) xfirsttickmin += steptickmin;
    341  minticks.push_back(xfirsttickmin);
    342  while(xfirsttickmin<=xmax)
    343    {xfirsttickmin+= steptickmin; minticks.push_back(xfirsttickmin);}
     351 minticks.resize(0);
     352 if(majticks.size()>1) {
     353   double steptickmin = steptick/5.;
     354   double xfirsttickmin = majticks[0];
     355   while(xfirsttickmin<=xmax+steptickmin/10.)
     356     {minticks.push_back(xfirsttickmin); xfirsttickmin+= steptickmin;}
     357 }
     358}
     359/* --Methode-Static-- */
     360void PIAxes::BestTicksLog(double xmin,double xmax,int nticks
     361                      ,vector<double>& majticks,vector<double>& minticks)
     362// *** Calcul des ticks pour un axe logarithmique
     363{
     364 if(nticks<=0) nticks = 1;
     365 //cout<<"BestTicksLog: xmin="<<xmin<<" xmax="<<xmax<<" nticks="<<nticks<<endl;
     366
     367 // CMV_BUG: quand on fait func 1 100 ..., Reza renvoit xmin=-0.9602 !!!
     368 // Ceci est un bricolo qui permet d'obtenir un resultat moyen.
     369 // A CORRIGER: pour Reza, ne pas surdimensionner la fenetre
     370 //       vers les xmin,ymin SI on demande une echelle log
     371 //       pour etre sur que xmin,ymin sera bien ce qui est demande.
     372 if(xmin<=0.) {
     373   cout<<"Error_BestTicksLog: xmin="<<xmin;
     374   double percor=0.05;
     375   // On suppose que: xmin = xmin0 - percor*(xmax0-xmin0)
     376   xmin = fabs((xmin+percor*xmax)/(1.+percor));
     377   cout<<" corrected to xmin="<<xmin<<endl
     378       <<"      ===> First labels may be WRONG"<<endl;
     379 }
     380
     381 // Si xmax<=0 ou si dynamique trop faible on garde BestTicks
     382 if(xmax<=0. || xmax/xmin<5.) {
     383   //cout<<"Choix de BestTicks xmax="<<xmax<<" xmax/xmin="<<xmax/xmin<<" <5"<<endl;;
     384   BestTicks(xmin,xmax,nticks,majticks,minticks);
     385   return;
     386 }
     387
     388 int dmin=int(floor(log10(xmin)));
     389 int dmax=int(floor(log10(xmax)));
     390 if(dmax==dmin) dmax++; else if(dmax<dmin) dmax=dmin+1;
     391 int inc = (dmax-dmin+1)/nticks; if(inc<1) inc=1;
     392 //cout<<" dmin="<<dmin<<" dmax="<<dmax<<" inc="<<inc<<endl;
     393
     394 majticks.resize(0);
     395 for(int i=dmin;i<=dmax;i+=inc) {
     396   double x = pow(10.,(double)i);
     397   if(x<xmin || x>xmax) continue;
     398   majticks.push_back(x);
     399 }
     400 //cout<<"majticks.size()="<<majticks.size()<<endl;
     401
     402 // Pas de puissance de 10 dans l'intervalle
     403 if(majticks.size()==0) {
     404   BestTicks(xmin,xmax,nticks,majticks,minticks);
     405   return;
     406 }
     407
     408 // Pas suffisamment de ticks majeurs
     409 if((int)majticks.size()<=nticks/2) {
     410   int nins = nticks/(majticks.size()+1);
     411   if(nins<=0) nins=1;
     412   //cout<<"nins="<<nins<<endl;
     413   // Sequence judicieuse pour remplir les ticks manquants
     414   // nins = 1 on insere 3
     415   //        2           2 5
     416   //        3           2 4 6
     417   //        4           1.5 2 4 6
     418   //      >=5 on reste au cas precedent 
     419   double seqmaj[4][4] = {{3.,0,0,0},{2.,5.,0,0},{2.,4.,6.,0},{1.5,2.,4.,6.}};
     420   if(nins>4) nins=4;
     421   vector<double> tmp;
     422   for(unsigned int i=0;i<=majticks.size();i++) {
     423     double xt;
     424     if(i<majticks.size()) xt = majticks[i]/10.;
     425       else                xt = majticks[i-1];
     426     for(int n=0;n<nins;n++) {
     427       double xins = seqmaj[nins-1][n]*xt;
     428       if(xins<xmin || xins>xmax) continue;
     429       tmp.push_back(xins);
     430     }
     431     if(i<majticks.size()) tmp.push_back(majticks[i]);
     432   }
     433   majticks = tmp;
     434 }
     435 //cout<<"...majticks.size()="<<majticks.size()<<endl;
     436
     437 // Les ticks mimneurs
     438 minticks.resize(0);
     439 for(unsigned int i=0;i<majticks.size()-1;i++) {
     440   double dx = (majticks[i+1]-majticks[i])/10.;
     441   minticks.push_back(majticks[i]);
     442   for(int j=2;j<=8;j+=2)  {
     443     double x = majticks[i] + j*dx;
     444     if(x<xmin || x>xmax) continue;
     445     minticks.push_back(x);
     446   }
     447 }
     448 minticks.push_back(majticks[majticks.size()-1]);
     449 //cout<<"...minticks.size()="<<minticks.size()<<endl;
     450
    344451}
    345452
     
    440547}
    441548
     549/* --Methode-- */
     550int PIAxes::Le_Bon_Format(vector<double>& xticks,string& format,double& xstep)
     551// Methode static de decision du bon format
     552// Decide quel format est le mieux adapte pour ecrire les labels des axes
     553// Decide si une puissance de 10 doit etre deportee en bout d'axe
     554// - Input:
     555//   xticks : vecteur des ticks a ecrire (calcule par BestTicks)
     556// - Output:
     557//   format : format a utiliser
     558//   xstep  : step entre 2 graduations
     559// - Return:
     560//   npuiss : si format choisit avec ecriture
     561//            avec label des puissances de 10 deporte
     562//   0      : sinon
     563{
     564 format="%g"; xstep=1.;
     565 if(xticks.size()<=1) return 0;
     566
     567 xstep=xticks[1]-xticks[0];
     568 int npuiss = BonFormatAxes(xticks[0],xticks[xticks.size()-1],xstep,format,2,1);
     569 if(npuiss>=-2 && npuiss<=3) {
     570   npuiss = 0;
     571   BonFormatAxes(xticks[0],xticks[xticks.size()-1],xstep,format,0,1);
     572 }
     573 return npuiss;
     574}
     575
    442576void PIAxes::Arrange_Label(char *label)
     577// --- Mise en forme optimale du label numerique
    443578// Enleve les blancs et les zeros inutiles a la fin d'un label
    444579{
  • trunk/SophyaPI/PI/piaxes.h

    r2088 r2091  
    4545  static void BestTicks(double xmin,double xmax,int nticks
    4646                        ,vector<double>& majticks,vector<double>& minticks);
     47  static void BestTicksLog(double xmin,double xmax,int nticks
     48                           ,vector<double>& majticks,vector<double>& minticks);
    4749
    48 //  Calcul du format optimal pour les axes (STATIC)
     50//  Calcul du format optimal (STATIC)
    4951  static int BonFormatAxes(double xmin,double xmax,double xstep
    5052                           ,string& format,int typf=0,int add_digit=0);
    5153
    52 //  Mise en forme optimale du format (STATIC)
     54//  Decision du format optimal pour les axes (STATIC)
     55  static int Le_Bon_Format(vector<double>& xticks,string& format,double& xstep);
     56
     57//  Mise en forme optimale du label numerique (STATIC)
    5358  static void Arrange_Label(char *label);
    5459
    5560protected:
    56   void Setup(PIGraphicUC* g, double xmin, double xmax,
    57              double ymin, double ymax);
     61  void Setup(PIGraphicUC* g,double xmin,double xmax,double ymin,double ymax);
    5862
    5963  void DrawHTicks(PIGraphicUC* g, double y, double tickUp, double tickDown, vector<double>& xticks);
  • trunk/SophyaPI/PI/piversion.h

    r2042 r2091  
    22#define PIVERSION_H_SEEN
    33
    4 #define PI_VERSIONNUMBER  3.68
     4#define PI_VERSIONNUMBER  3.69
    55
    66#endif
Note: See TracChangeset for help on using the changeset viewer.