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

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

pb compil SGI-CC , redeclaration int i / unsigned int i - Reza 17/7/2002

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