source: Sophya/trunk/SophyaPI/PI/piaxes.cc@ 2119

Last change on this file since 2119 was 2119, checked in by ansari, 23 years ago

Amelioration/debud decodage options ds pieldrw.cc piimage.cc , dbg prise en change de l'option AxeLog lors de UpdateLimit par PIScDrawWdg, MAJ numero de version - Reza 18/7/2002

File size: 21.3 KB
RevLine 
[2080]1// Module PI : Peida Interactive PIAxes
2// Methodes de trace des axes
3// R. Ansari - 2002
4// LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA
5
6#include "machdefs.h"
[2085]7#include <stdio.h>
[2103]8#include <iostream.h>
[2096]9#include <strings.h>
[2080]10#include <math.h>
[2088]11#include "piaxes.h"
[2080]12
[2091]13inline void dble_SWAP(double& a,double& b) {double tmp=a; a=b; b=tmp;}
[2080]14
15/* --Methode-- */
16PIAxes::PIAxes()
17{
18}
19
20/* --Methode-- */
21PIAxes::~PIAxes()
22{
23}
24
25/* --Methode-- */
26void PIAxes::DrawXYAxes(PIGraphicUC* g, PIGraphicAtt& gratt,
27 unsigned int flags, bool afsz)
28{
29 PIGrCoord xmin, xmax, ymin, ymax;
30 g->GetGrSpace(xmin, xmax, ymin, ymax);
31 DrawXYAxes(g, gratt, flags, afsz, (double)xmin, (double)xmax,
32 (double)ymin, (double)ymax);
33}
34
35/* --Methode-- */
36void PIAxes::DrawXYAxes(PIGraphicUC* g, PIGraphicAtt& gratt,
37 unsigned int flags, bool afsz,
38 double xmin, double xmax, double ymin, double ymax)
39{
40 Setup(g, xmin, xmax, ymin, ymax);
41 // g->NoClip();
42
43 if (gratt.GetLineAtt() == PI_NotDefLineAtt) g->SelLine(PI_ThinLine);
44 else g->SelLine(gratt.GetLineAtt());
45 if (gratt.GetColor() == PI_NotDefColor) g->SelForeground(PI_Black);
46 else g->SelForeground(gratt.GetColor());
47
48 if(afsz) {
49 double fsz = xMajTickLen*3.5;
50 g->SelFontSz(fsz);
51 }
52
53 if (flags & kStdAxes) {
54
55 // Les axes
56
57 g->DrawLine(xMin, (yMin+yMax)/2., xMax, (yMin+yMax)/2.);
58 g->DrawLine((xMin+xMax)/2., yMin, (xMin+xMax)/2., yMax);
59
60 // La grille en pointilles
61
62 if (flags & kGridOn) DrawGrid(g);
63
64 // Les ticks majeurs
65
66 if (flags & kMajTicks) {
[2088]67 DrawHTicks(g, (yMin+yMax)/2., xMajTickLen, xMajTickLen, xMajTicks);
68 DrawVTicks(g, (xMin+xMax)/2., yMajTickLen, yMajTickLen, yMajTicks);
[2080]69 }
70
71 // Les ticks mineurs
72
73 if (flags & kMinTicks) {
[2088]74 DrawHTicks(g, (yMin+yMax)/2., xMinTickLen, xMinTickLen, xMinTicks);
75 DrawVTicks(g, (xMin+xMax)/2., yMinTickLen, yMinTickLen, yMinTicks);
[2080]76 }
77
78 // Les labels
79
80 if (flags & kLabels) {
81 if (!aYdir)
[2088]82 DrawHLabels(g, (yMin+yMax)/2.-xMajTickLen*2, xMajTicks, PI_VerticalTop);
[2080]83 else
[2088]84 DrawHLabels(g, (yMin+yMax)/2.+xMajTickLen*2, xMajTicks, PI_VerticalTop);
[2080]85 if (!aXdir)
[2088]86 DrawVLabels(g, (xMin+xMax)/2.-yMajTickLen*2, yMajTicks, PI_HorizontalRight);
[2080]87 else
[2088]88 DrawVLabels(g, (xMin+xMax)/2.+yMajTickLen*2, yMajTicks, PI_HorizontalRight);
[2080]89 }
90
91 }
92
93 if (flags & kBoxAxes) {
94
95 // La boite
96
97 g->DrawLine(xMin, yMin, xMax, yMin);
98 g->DrawLine(xMax, yMin, xMax, yMax);
99 g->DrawLine(xMax, yMax, xMin, yMax);
100 g->DrawLine(xMin, yMax, xMin, yMin);
101
102 // Longueur des ticks
103
104 double extXMajTickLen = flags&kExtTicks ? xMajTickLen : 0;
105 double intXMajTickLen = flags&kIntTicks ? xMajTickLen : 0;
106 double extXMinTickLen = flags&kExtTicks ? xMinTickLen : 0;
107 double intXMinTickLen = flags&kIntTicks ? xMinTickLen : 0;
108 double extYMajTickLen = flags&kExtTicks ? yMajTickLen : 0;
109 double intYMajTickLen = flags&kIntTicks ? yMajTickLen : 0;
110 double extYMinTickLen = flags&kExtTicks ? yMinTickLen : 0;
111 double intYMinTickLen = flags&kIntTicks ? yMinTickLen : 0;
112
113 // La grille en pointilles
114
115 if (flags & kGridOn) DrawGrid(g);
116
117 // Les ticks majeurs
118
119 if (flags & kMajTicks) {
[2088]120 DrawHTicks(g, yMin, intXMajTickLen, extXMajTickLen, xMajTicks);
121 DrawHTicks(g, yMax, extXMajTickLen, intXMajTickLen, xMajTicks);
122 DrawVTicks(g, xMin, extYMajTickLen, intYMajTickLen, yMajTicks);
123 DrawVTicks(g, xMax, intYMajTickLen, extYMajTickLen, yMajTicks);
[2080]124 }
125
126 // Les ticks mineurs
127
128 if (flags & kMinTicks) {
[2088]129 DrawHTicks(g, yMin, intXMinTickLen, extXMinTickLen, xMinTicks);
130 DrawHTicks(g, yMax, extXMinTickLen, intXMinTickLen, xMinTicks);
131 DrawVTicks(g, xMin, extYMinTickLen, intYMinTickLen, yMinTicks);
132 DrawVTicks(g, xMax, intYMinTickLen, extYMinTickLen, yMinTicks);
[2080]133 }
134
135
136 // Les labels
137
138 if (flags & kLabels) {
139 if (!aYdir) {
[2088]140 DrawHLabels(g, g->DeltaUCY(yMin, -xMajTickLen*2), xMajTicks, PI_VerticalTop);
[2080]141 }
142 else {
[2088]143 DrawHLabels(g, g->DeltaUCY(yMax, xMajTickLen*2), xMajTicks, PI_VerticalTop);
[2080]144 }
145 if (!aXdir) {
[2088]146 DrawVLabels(g, g->DeltaUCX(xMin, -yMajTickLen*2), yMajTicks, PI_HorizontalRight);
[2080]147 }
148 else {
[2088]149 DrawVLabels(g, g->DeltaUCX(xMax, yMajTickLen*2), yMajTicks, PI_HorizontalRight);
[2080]150 }
151 }
152 }
153 g->Clip();
154
155}
156
157/* --Methode-- */
158void PIAxes::Setup(PIGraphicUC* g, double xmin, double xmax,
159 double ymin, double ymax)
160{
161
162 xMin = xmin; xMax = xmax;
163 yMin = ymin; yMax = ymax;
164
165 aXdir = g->isAxeXDirRtoL();
166 aYdir = g->isAxeYDirUpDown();
167 aXlog = g->isLogScaleX();
168 aYlog = g->isLogScaleY();
169
[2091]170 int ntick_x = (aXlog) ? 10 : 10;
171 if(aXlog) BestTicksLog(xMin,xMax,ntick_x,xMajTicks,xMinTicks);
172 else BestTicks(xMin,xMax,ntick_x,xMajTicks,xMinTicks);
[2080]173
[2091]174 int ntick_y = (aYlog) ? 12 : 12;
175 if(aYlog) BestTicksLog(yMin,yMax,ntick_y,yMajTicks,yMinTicks);
176 else BestTicks(yMin,yMax,ntick_y,yMajTicks,yMinTicks);
[2080]177
178 yMajTickLen = (xMax-xMin)/100;
179 yMinTickLen = (xMax-xMin)/250;
180 xMajTickLen = (yMax-yMin)/100;
181 xMinTickLen = (yMax-yMin)/250;
182}
183
184
185/* --Methode-- */
186void PIAxes::DrawHTicks(PIGraphicUC* g, double y, double tickUp,
[2088]187 double tickDown, vector<double>& xticks)
[2080]188{
[2091]189 if(xticks.size()==0) return;
[2088]190 for(unsigned int i=0;i<xticks.size();i++) {
[2091]191 if(xticks[i]<xMin) continue;
[2088]192 if(xticks[i]>xMax) break;
193 g->DrawLine(xticks[i],g->DeltaUCY(y,-tickDown),xticks[i],g->DeltaUCY(y,tickUp));
194 }
[2080]195}
196
197/* --Methode-- */
198void PIAxes::DrawVTicks(PIGraphicUC* g, double x, double tickLeft,
[2088]199 double tickRight, vector<double>& yticks)
[2080]200{
[2091]201 if(yticks.size()==0) return;
[2088]202 for(unsigned int i=0;i<yticks.size();i++) {
[2091]203 if(yticks[i]<yMin) continue;
[2088]204 if(yticks[i]>yMax) break;
205 g->DrawLine(g->DeltaUCX(x,-tickLeft),yticks[i],g->DeltaUCX(x,tickRight),yticks[i]);
206 }
[2080]207}
208
209/* --Methode-- */
[2088]210void PIAxes::DrawHLabels(PIGraphicUC* g, double y, vector<double>& xticks, unsigned long just)
[2080]211{
[2091]212 if(xticks.size()==0) return;
[2080]213
[2091]214 // Choix du bon format pour les labels des axes
215 string format; double xstep;
216 int npuiss = Le_Bon_Format(xticks,format,xstep);
217 double fac=(npuiss!=0)? fac=pow(10.,(double)npuiss): 1.;
[2080]218
[2091]219 char label[64];
220 double dum,xpixdeb,xpixfin,largpix;
221 g->UC2GrC(xMin-2.*(xMax-xMin),y,xpixfin,dum);
[2088]222 for(unsigned int i=0;i<xticks.size();i++) {
[2091]223 if(xticks[i]<xMin) continue;
[2088]224 if(xticks[i]>xMax) break;
[2080]225 //Attention erreur d'arrondi x->0 (on code 5.1698e-26 au lieu de 0)
[2088]226 double xx = (fabs(xticks[i]/xstep)<1.e-5) ? 0.: xticks[i];
[2091]227 sprintf(label,format.c_str(),xx/fac); Arrange_Label(label);
[2080]228 double largeur = g->CalcStringWidth(label);
[2091]229 g->DUC2GrC(largeur,0.,largpix,dum);
230 g->UC2GrC(xticks[i],y,xpixdeb,dum); xpixdeb -= largpix/2.;
231 //cout<<"xticks="<<xticks[i]<<" largpix="<<largpix
232 // <<" xpixdeb="<<xpixdeb<<" xpixfin="<<xpixfin<<endl;
233 if((aXdir && xpixdeb<xpixfin) || (!aXdir && xpixdeb>xpixfin)) {
[2088]234 g->DrawString(xticks[i],y,label,PI_HorizontalCenter|just);
[2091]235 xpixfin = xpixdeb + 1.1*largpix;
[2080]236 }
237 }
238
[2091]239 if(npuiss!=0) {
[2080]240 PIGrCoord asc,desc;
241 double h = g->GetFontHeight(asc,desc);
[2091]242 if((aYdir && (just&PI_VerticalBottom)) || (!aYdir && (just&PI_VerticalTop))) h=-h;
[2080]243 double xm = (aXdir)? xMin: xMax;
244 double ym = g->DeltaUCY(y,1.5*h);
245 sprintf(label,"%d",npuiss);
246 g->DrawCompString(xm,ym,"x 10",label,NULL,PI_HorizontalCenter|just);
247 }
248
249}
250
251/* --Methode-- */
[2088]252void PIAxes::DrawVLabels(PIGraphicUC* g, double x, vector<double>& yticks, unsigned long just)
[2080]253{
[2091]254 if(yticks.size()==0) return;
[2080]255
256 // Choix du bon format pour les labels des axes;
[2091]257 string format; double ystep;
258 int npuiss = Le_Bon_Format(yticks,format,ystep);
259 double fac=(npuiss!=0)? fac=pow(10.,(double)npuiss): 1.;
[2080]260
[2091]261 char label[64];
262 PIGrCoord asc,desc;
263 double dum,ypixdeb,ypixfin,hautpix,hauteur=g->GetFontHeight(asc,desc);
264 g->DUC2GrC(0.,hauteur,dum,hautpix);
265 g->UC2GrC(x,yMin-2.*(yMax-yMin),dum,ypixfin);
[2088]266 for(unsigned int i=0;i<yticks.size();i++) {
[2091]267 if(yticks[i]<yMin) continue;
[2088]268 if(yticks[i]>yMax) break;
269 double yy = (fabs(yticks[i]/ystep)<1.e-5) ? 0.: yticks[i];
[2091]270 sprintf(label,format.c_str(),yy/fac); Arrange_Label(label);
271 g->UC2GrC(x,yticks[i],dum,ypixdeb); ypixdeb -= hautpix/2.;
272 // -- Attention: ypix=0 est en haut de l'ecran
273 // (ypix croissants vers le bas de l'ecran)
274 // donc bien que yMin<yMax on a yMinPix>yMaxPix
275 //cout<<"yticks="<<yticks[i]<<" hautpix="<<hautpix
276 // <<" ypixdeb="<<ypixdeb<<" ypixfin="<<ypixfin<<endl;
277 if((aYdir && ypixdeb>ypixfin) || (!aYdir && ypixdeb<ypixfin)) {
278 g->DrawString(x,yticks[i],label,PI_VerticalCenter|just);
279 ypixfin = ypixdeb + 1.1*hautpix;
280 }
[2080]281 }
282
[2091]283 if(npuiss!=0) {
284 if(aYdir) hauteur = -hauteur;
285 double ym = (aYdir)? yMin: yMax; ym = g->DeltaUCY(ym,hauteur);
[2080]286 sprintf(label,"%d",npuiss);
287 g->DrawCompString(x,ym,"x 10",label,NULL,PI_VerticalBottom|just);
288 }
289
290}
291
292/* --Methode-- */
293void PIAxes::DrawGrid(PIGraphicUC* g)
294{
295 PILineAtt savlineatt = g->GetLineAtt();
296 g->SelLine(PI_ThinDottedLine);
297
[2088]298 if(xMajTicks.size()>0)
299 for(unsigned int i=0;i<xMajTicks.size();i++) {
300 if(xMajTicks[i]>xMax) break;
301 g->DrawLine(xMajTicks[i], yMin, xMajTicks[i], yMax);
302 }
[2080]303
[2088]304 if(yMajTicks.size()>0)
305 for(unsigned int i=0;i<yMajTicks.size();i++) {
306 if(yMajTicks[i]>yMax) break;
307 g->DrawLine(xMin, yMajTicks[i], xMax, yMajTicks[i]);
308 }
[2080]309
310 g->SelLine(savlineatt);
311}
312
[2091]313////////////////////////////////////////////////////////////////////////
314//////////////////// METHODES STATIQUES ////////////////////////////////
315////////////////////////////////////////////////////////////////////////
[2080]316/* --Methode-Static-- */
[2115]317void PIAxes::ReSizeMinMax(bool axelog,double& vmin,double& vmax,double garde)
318// Calcul du min et du max du display a partir des valeurs min et max a plotter
319{
320 if(garde<0. || garde>=1.) garde = 0.025;
[2119]321 // cout<<"ReSizeMinMax[log="<<axelog<<",garde="<<garde<<"] vmin="<<vmin<<" vmax="<<vmax<<endl;
[2115]322 // Cas d'une echelle lineaire
323 if(!axelog || vmax<=0.) {
324 double dv = garde*(vmax-vmin);
325 vmin -= dv;
326 vmax += dv;
327 }
328
329 // Cas d'une echelle log avec un range raisonnable
330 else if(vmin>0.) {
331 double dv = pow(vmax/vmin,garde);
332 vmin /= dv;
333 vmax *= dv;
334 }
335
336 // Cas d'une echelle log avec un range de-raisonnable
337 else if(vmin<=0.) {
338 if(vmin<0.) vmin += garde*vmin;
339 if(vmax==1.) vmax = 1.+garde;
340 if(vmax>1.) vmax = pow(vmax,1.+garde);
341 else vmax = pow(vmax,1.-garde);
342 }
343
[2119]344 // cout<<" vmin="<<vmin<<" vmax="<<vmax<<endl;
[2115]345}
346
347/* --Methode-Static-- */
[2080]348void PIAxes::BestTicks(double xmin,double xmax,int nticks
[2088]349 ,vector<double>& majticks,vector<double>& minticks)
[2080]350// *** Calcul de l'intervalle entre les ticks et de la valeur du premier tick
[2091]351// pour un axe lineaire
[2080]352{
[2091]353 if(nticks<=0) nticks = 1;
354
355 double d=xmax-xmin; if(d<1.e-100) d=1.e-100;
[2088]356 double ld = log10(d);
357 double fld = floor( ((ld<0.)? -ld: ld) );
358 double del,del0;
[2091]359 fld = (ld>=0.)? fld-2.: -(fld+2.);
360 del0 = del = pow(10.,fld);
[2088]361 // *** Intervalle entre les ticks
362 // xmin xmax d ld fld -->fld del0
[2091]363 // 1 1500 1499 3.17 3 1 10^1
364 // 1 9500 9499 3.98 3 1 10^1
365 // 1 1.005 0.005 -2.3 3 -5 10^-5
366 // 1 1.995 0.995 -0.0022 1 -3 10^-3
367 // - Et recherche de la valeur del={del0,2*del0,...,20*del0,...}
368 // telle que "nticks*del" soit le plus petit nombre ">=xmax-xmin"
369 double fac[9] = {2.,5.,10.,20.,50.,100.,200.,500.,1000.};
370 for(int k=0;k<9;k++) {
371 //cout<<"BestTicks: "<<k<<" del="<<del<<" d/del="<<d/del<<"<"<<nticks<<endl;
372 if(d/del < (double)nticks) break;
373 del=fac[k]*del0;
374 }
[2088]375 double steptick=del;
376 //*** Valeur du premier tick
[2091]377 majticks.resize(0);
378 double xfirsttick = floor(fabs(xmin)/steptick)*steptick;
379 if(xmin<0.) xfirsttick *= -1.;
[2088]380 if(xfirsttick<xmin) xfirsttick += steptick;
[2091]381 while(xfirsttick<=xmax+steptick/10.)
382 {majticks.push_back(xfirsttick); xfirsttick+= steptick;}
[2088]383 //*** Gestion des ticks mineurs
[2091]384 minticks.resize(0);
385 if(majticks.size()>1) {
386 double steptickmin = steptick/5.;
387 double xfirsttickmin = majticks[0];
388 while(xfirsttickmin<=xmax+steptickmin/10.)
389 {minticks.push_back(xfirsttickmin); xfirsttickmin+= steptickmin;}
390 }
[2080]391}
[2091]392/* --Methode-Static-- */
393void PIAxes::BestTicksLog(double xmin,double xmax,int nticks
394 ,vector<double>& majticks,vector<double>& minticks)
395// *** Calcul des ticks pour un axe logarithmique
396{
[2115]397 long i;
[2091]398 if(nticks<=0) nticks = 1;
399 //cout<<"BestTicksLog: xmin="<<xmin<<" xmax="<<xmax<<" nticks="<<nticks<<endl;
[2080]400
[2115]401 // Si xmax<=0, on garde BestTicks
402 if(xmax<=0. ) {
403 //cout<<"Choix de BestTicks car xmax="<<xmax<<endl;
[2091]404 BestTicks(xmin,xmax,nticks,majticks,minticks);
405 return;
406 }
407
[2115]408 int dmin, dmax=int(floor(log10(xmax)));
409 if(xmin>0.) {
410 // Dynamique trop faible, on garde BestTicks
411 if(xmax/xmin<5.) {
412 //cout<<"Choix de BestTicks car xmax/xmin="<<xmax/xmin<<" <5"<<endl;
[2116]413 BestTicks(xmin,xmax,nticks,majticks,minticks);
[2115]414 return;
415 }
416 dmin=int(floor(log10(xmin)));
417 } else {
418 if(dmax>3) dmin = dmax/3;
419 else dmin = dmax-1;
420 }
[2091]421 if(dmax==dmin) dmax++; else if(dmax<dmin) dmax=dmin+1;
422 int inc = (dmax-dmin+1)/nticks; if(inc<1) inc=1;
423 //cout<<" dmin="<<dmin<<" dmax="<<dmax<<" inc="<<inc<<endl;
424
425 majticks.resize(0);
[2113]426 for(i=dmin;i<=dmax;i+=inc) {
[2091]427 double x = pow(10.,(double)i);
428 if(x<xmin || x>xmax) continue;
429 majticks.push_back(x);
430 }
431 //cout<<"majticks.size()="<<majticks.size()<<endl;
432
[2115]433 // Pas de puissance de 10 dans l'intervalle on garde BestTicks
[2091]434 if(majticks.size()==0) {
435 BestTicks(xmin,xmax,nticks,majticks,minticks);
436 return;
437 }
438
439 // Pas suffisamment de ticks majeurs
440 if((int)majticks.size()<=nticks/2) {
441 int nins = nticks/(majticks.size()+1);
442 if(nins<=0) nins=1;
443 //cout<<"nins="<<nins<<endl;
444 // Sequence judicieuse pour remplir les ticks manquants
445 // nins = 1 on insere 3
446 // 2 2 5
447 // 3 2 4 6
448 // 4 1.5 2 4 6
449 // >=5 on reste au cas precedent
450 double seqmaj[4][4] = {{3.,0,0,0},{2.,5.,0,0},{2.,4.,6.,0},{1.5,2.,4.,6.}};
451 if(nins>4) nins=4;
452 vector<double> tmp;
[2115]453 for(i=0;i<=(long)majticks.size();i++) {
[2091]454 double xt;
[2115]455 if(i<(long)majticks.size()) xt = majticks[i]/10.;
456 else xt = majticks[i-1];
[2091]457 for(int n=0;n<nins;n++) {
458 double xins = seqmaj[nins-1][n]*xt;
459 if(xins<xmin || xins>xmax) continue;
460 tmp.push_back(xins);
461 }
[2115]462 if(i<(long)majticks.size()) tmp.push_back(majticks[i]);
[2091]463 }
464 majticks = tmp;
465 }
466 //cout<<"...majticks.size()="<<majticks.size()<<endl;
467
[2115]468 // Les ticks mineurs
[2091]469 minticks.resize(0);
[2115]470 for(i=0;i<(long)majticks.size()-1;i++) {
[2091]471 double dx = (majticks[i+1]-majticks[i])/10.;
472 minticks.push_back(majticks[i]);
473 for(int j=2;j<=8;j+=2) {
474 double x = majticks[i] + j*dx;
475 if(x<xmin || x>xmax) continue;
476 minticks.push_back(x);
477 }
478 }
479 minticks.push_back(majticks[majticks.size()-1]);
480 //cout<<"...minticks.size()="<<minticks.size()<<endl;
481
[2115]482 // Si on a xmin<=0., on insere zero dans les ticks majeurs
483 if(xmin<=0.) {
484 vector<double> tmp = majticks;
485 majticks.resize(0); majticks.push_back(0.);
486 for(i=0;i<(long)tmp.size();i++) majticks.push_back(tmp[i]);
487 //cout<<"...xmin="<<xmin<<"<=0. add majticks[0]="<<majticks[0]<<endl;
488 }
489
[2091]490}
491
[2080]492/* --Methode-Static-- */
493int PIAxes::BonFormatAxes(double xmin,double xmax,double xstep
[2116]494 ,string& format,int typf,int add_digit)
[2080]495// *** Calcul format optimal pour ecrire les labels numeriques des axes:
496// ---- Input
497// . xmin,xmax : limites du plot sur l'axe considere.
498// . xstep : distance entre les ticks.
499// . add_digit : nombre de digits a ajouter au nombre de digits minimum.
500// . typf : type de format en sortie
501// 0 : format optimum %-nn.mme ou %-nn.mmf selon valeurs
502// 1 : format %-nn.mme
503// 2 : format %-nn.mmf pour imprimer x/10^npuiss
[2116]504// tel que x/10^npuiss soit entre [0,10]
505// 3 : format %-nn.mmf
[2080]506// ---- Output
507// . format : le format d'impression
508// ---- Return:
[2116]509// Si typ=0 ou 1 ou 3
[2080]510// "ndig" : nombre de digits necessaires pour distinguer
511// les valeurs xmin+k*dx (<=xmax)
512// Si typ=2
513// "npuiss" : tel que x/10^npuiss soit entre 0 et 10
514// Dans ce cas le format est celui qui imprime x/10^npuiss
515{
516 format = "%-5g"; // format par default
517 if(xmin>=xmax) {if(typf==2) return 0; else return -1;}
518
519 if(xstep<=0. || xstep>xmax-xmin) xstep = xmax-xmin;
520
521 double axmin=fabs(xmin), axmax=fabs(xmax);
522 if(axmin>axmax) dble_SWAP(axmin,axmax);
523
524 double l10amax = log10(axmax), l10xstep = log10(xstep);
525 int il10amax = int(floor(l10amax));
526
527 // choix du type de format
528 char ftype = 'e';
529 int npuiss = 0;
530 if(typf==2) {
[2116]531 npuiss = il10amax-1; // nombre entre [0,10]
532 //npuiss = il10amax; // nombre entre [0,1]
[2080]533 if(npuiss<-300 || npuiss>300) {
534 ftype='e'; npuiss=0;
535 } else {
536 // On recalcule les valeurs de decision pour axmax/10^npuiss, xstep/10^npuiss
537 l10amax -= (double)npuiss; l10xstep -= (double)npuiss;
538 il10amax = int(floor(l10amax));
539 ftype = 'f';
540 }
541 } else if(typf==1) {
542 ftype='e';
[2116]543 } else if(typf==3) {
544 ftype='f';
[2080]545 } else {
546 ftype='e';
547 // On evite d'ecrire +a.bbbe+ccc -> format %f
548 // Ex: 1.2345e+2 -> 123.45 / -1.2345e+2 -> -123.45
549 // 1.2345e-1 -> 0.12345 / -1.2345e-1 -> -0.12345
550 if((axmin>=1e-4 || axmin==0.) && axmax<1e4) ftype='f';
551 }
552
553 //printf("BonFormatAxes[npuiss=%d]: xmin=%-21.14e xmax=%-21.14e\n",npuiss,xmin,xmax);
554 //printf(" xstep=%-21.14e log10(xstep/10^%d)=%g\n",xstep,npuiss,l10xstep);
555 //printf(" axmax=%-21.14e log10(axmax/10^%d)=%g diff=%g\n"
556 // ,axmax,npuiss,l10amax,l10amax-l10xstep);
557
558 // Nombre de digits necessaires pour ecrire axmax et xstep
559 int ndig = il10amax - int(floor(l10xstep));
560 if(ndig<0) ndig *= -1; ndig += 1;
561 //printf("ndig=%d",ndig);
562
563 // Add more digits (or suppress digits)
564 ndig += add_digit; if(ndig<0) ndig=0;
565 //printf(" + %d ==> ndig=%d\n",add_digit,ndig);
566
567 // Calcul du bon format
568 char str[16];
569 if(ftype=='f') { // Calcul du format %-nn.mmf
570 int mm=-1, nn;
571 if(il10amax<0) { // +0.12345 +0.0012345 +0.0012345 ...
572 mm = ndig - il10amax - 1; nn = mm+3;
573 } else { // +1.2345 +12.345 +123.45 ...
574 mm = ndig - il10amax - 1; nn = ndig+2;
575 }
576 //printf("format %%f : mm=%d nn=%d\n",mm,nn);
577 if(mm<0.) mm=0; if(nn<mm+3) nn=mm+3;
578 sprintf(str,"%%-%d.%df",nn,mm);
579 } else if(ftype=='e') { // Calcul du format %-nn.mme
580 // +d.<--ddd-->e+123
581 // 1 2 34567 ==> nn=ndig+7 mm=ndig-1
582 sprintf(str,"%%-%d.%de",ndig+7,ndig-1);
583 }
584
585 format = str;
586 //printf("format=[%s]\n",format.c_str());
587
588 if(typf==2) return npuiss;
589 return ndig;
590}
591
[2091]592/* --Methode-- */
593int PIAxes::Le_Bon_Format(vector<double>& xticks,string& format,double& xstep)
594// Methode static de decision du bon format
595// Decide quel format est le mieux adapte pour ecrire les labels des axes
596// Decide si une puissance de 10 doit etre deportee en bout d'axe
597// - Input:
598// xticks : vecteur des ticks a ecrire (calcule par BestTicks)
599// - Output:
600// format : format a utiliser
601// xstep : step entre 2 graduations
602// - Return:
603// npuiss : si format choisit avec ecriture
604// avec label des puissances de 10 deporte
605// 0 : sinon
606{
607 format="%g"; xstep=1.;
608 if(xticks.size()<=1) return 0;
609
[2116]610 // On decide du format
[2091]611 xstep=xticks[1]-xticks[0];
612 int npuiss = BonFormatAxes(xticks[0],xticks[xticks.size()-1],xstep,format,2,1);
[2116]613 if(npuiss>=-2 && npuiss<=2) {
[2091]614 npuiss = 0;
[2116]615 BonFormatAxes(xticks[0],xticks[xticks.size()-1],xstep,format,3,1);
[2091]616 }
[2116]617
[2091]618 return npuiss;
619}
620
[2088]621void PIAxes::Arrange_Label(char *label)
[2091]622// --- Mise en forme optimale du label numerique
[2116]623// Enleve les blancs, les zeros, le point et les e00
624// inutiles a la fin d'un label
[2088]625{
626 size_t lenl=strlen(label);
627 if(lenl==0) return;
628
629 // --- On enleve les blancs et plus au debut du label
630 if(label[0]==' ' || label[0]=='+') {
631 char *str=new char[lenl+2];
632 strcpy(str,label);
633 unsigned i=0;
634 for(i=0;i<lenl;i++) if(str[i]!=' ' && str[i]!='+') break;
635 strcpy(label,&str[i]);
636 delete [] str;
637 lenl=strlen(label);
638 if(lenl==0) return;
639 }
640
641 // --- On enleve les blancs a la fin du label
642 if(label[lenl-1]==' ') {
[2096]643 for(int i=lenl-1;i>=0;i--) {
[2088]644 if(label[i]!=' ') break;
645 label[i]='\0';
646 }
647 lenl=strlen(label);
648 }
649
650 // --- On enleve les e... E... non-significatifs
651 // ex: a.be-zzz a.be+zzz a.bezzz avec zzz=0,00,000,...
652 // Attention on n'enleve pas si: a.be+10
653 // Attention on ne fait rien si: e+10
654 char* e=index(label,'e');
655 if(e==NULL) e=index(label,'E');
656 if(e) {
[2096]657 for(int i=lenl-1;i>=0;i--) {
[2088]658 if(isdigit(label[i]) && label[i]!='0') break;
659 if(label[i]=='e' || label[i]=='E')
660 {label[i]='\0'; lenl=strlen(label); break;}
661 }
662 }
663
664 // --- On enleve les zeros non-significatifs a la fin du label
665 // On enleve des zeros ou le point si: ab. ab.czzz avec zzz=0,00,000,...
666 // Attention on n'enleve pas de zeros si: abzzz
667 // Attention a ne pas enlever des zeros si on a ab.ccce+a0
668 // Attention on traite 0eaaa -> 0
669 if(index(label,'.')==NULL) return; // Recherche d'un point
670 string stre;
671 if(e) {if(e==label) return; stre=e; *e='\0'; lenl=strlen(label);}
[2096]672 for(int i=lenl-1;i>=0;i--) {
[2088]673 if(label[i]=='0') label[i]='\0';
674 else if(label[i]=='.') {
675 if(i>0) label[i]='\0';
676 else {
677 // Attention: ".e+10" -> "1e+10" MAIS "." -> "0"
678 if(e) strcpy(label,"1"); else strcpy(label,"0");
679 }
680 break;
681 }
682 else break; // Ni un point ni un zero
683 }
684 if(e) {
685 if(strlen(label)==1) if(label[0]=='0') return;
686 strcat(label,stre.c_str());
687 }
688
689}
Note: See TracBrowser for help on using the repository browser.