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

Last change on this file since 2085 was 2085, checked in by cmv, 23 years ago

stdoi.h pour sprintf cmv 6/7/2002

File size: 14.1 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 "piaxes.h"
8#include <stdio.h>
9#include <math.h>
10
11inline void dble_SWAP(double a, double b) {double tmp=a; a=b; b=tmp;}
12
13/* --Methode-- */
14PIAxes::PIAxes()
15{
16}
17
18/* --Methode-- */
19PIAxes::~PIAxes()
20{
21}
22
23/* --Methode-- */
24void PIAxes::DrawXYAxes(PIGraphicUC* g, PIGraphicAtt& gratt,
25 unsigned int flags, bool afsz)
26{
27 PIGrCoord xmin, xmax, ymin, ymax;
28 g->GetGrSpace(xmin, xmax, ymin, ymax);
29 DrawXYAxes(g, gratt, flags, afsz, (double)xmin, (double)xmax,
30 (double)ymin, (double)ymax);
31}
32
33/* --Methode-- */
34void PIAxes::DrawXYAxes(PIGraphicUC* g, PIGraphicAtt& gratt,
35 unsigned int flags, bool afsz,
36 double xmin, double xmax, double ymin, double ymax)
37{
38 Setup(g, xmin, xmax, ymin, ymax);
39 // g->NoClip();
40
41 if (gratt.GetLineAtt() == PI_NotDefLineAtt) g->SelLine(PI_ThinLine);
42 else g->SelLine(gratt.GetLineAtt());
43 if (gratt.GetColor() == PI_NotDefColor) g->SelForeground(PI_Black);
44 else g->SelForeground(gratt.GetColor());
45
46 if(afsz) {
47 double fsz = xMajTickLen*3.5;
48 g->SelFontSz(fsz);
49 }
50
51 if (flags & kStdAxes) {
52
53 // Les axes
54
55 g->DrawLine(xMin, (yMin+yMax)/2., xMax, (yMin+yMax)/2.);
56 g->DrawLine((xMin+xMax)/2., yMin, (xMin+xMax)/2., yMax);
57
58 // La grille en pointilles
59
60 if (flags & kGridOn) DrawGrid(g);
61
62 // Les ticks majeurs
63
64 if (flags & kMajTicks) {
65 DrawHTicks(g, (yMin+yMax)/2., xMajTickLen, xMajTickLen, xFirstMajTick, xMajTickStep);
66 DrawVTicks(g, (xMin+xMax)/2., yMajTickLen, yMajTickLen, yFirstMajTick, yMajTickStep);
67 }
68
69 // Les ticks mineurs
70
71 if (flags & kMinTicks) {
72 DrawHTicks(g, (yMin+yMax)/2., xMinTickLen, xMinTickLen, xFirstMinTick, xMinTickStep);
73 DrawVTicks(g, (xMin+xMax)/2., yMinTickLen, yMinTickLen, yFirstMinTick, yMinTickStep);
74 }
75
76 // Les labels
77
78 if (flags & kLabels) {
79 if (!aYdir)
80 DrawHLabels(g, (yMin+yMax)/2.-xMajTickLen*2, xFirstMajTick, xMajTickStep,PI_VerticalTop);
81 else
82 DrawHLabels(g, (yMin+yMax)/2.+xMajTickLen*2, xFirstMajTick, xMajTickStep,PI_VerticalTop);
83 if (!aXdir)
84 DrawVLabels(g, (xMin+xMax)/2.-yMajTickLen*2, yFirstMajTick, yMajTickStep,PI_HorizontalRight);
85 else
86 DrawVLabels(g, (xMin+xMax)/2.+yMajTickLen*2, yFirstMajTick, yMajTickStep,PI_HorizontalRight);
87 }
88
89 }
90
91 if (flags & kBoxAxes) {
92
93 // La boite
94
95 g->DrawLine(xMin, yMin, xMax, yMin);
96 g->DrawLine(xMax, yMin, xMax, yMax);
97 g->DrawLine(xMax, yMax, xMin, yMax);
98 g->DrawLine(xMin, yMax, xMin, yMin);
99
100 // Longueur des ticks
101
102 double extXMajTickLen = flags&kExtTicks ? xMajTickLen : 0;
103 double intXMajTickLen = flags&kIntTicks ? xMajTickLen : 0;
104 double extXMinTickLen = flags&kExtTicks ? xMinTickLen : 0;
105 double intXMinTickLen = flags&kIntTicks ? xMinTickLen : 0;
106 double extYMajTickLen = flags&kExtTicks ? yMajTickLen : 0;
107 double intYMajTickLen = flags&kIntTicks ? yMajTickLen : 0;
108 double extYMinTickLen = flags&kExtTicks ? yMinTickLen : 0;
109 double intYMinTickLen = flags&kIntTicks ? yMinTickLen : 0;
110
111 // La grille en pointilles
112
113 if (flags & kGridOn) DrawGrid(g);
114
115 // Les ticks majeurs
116
117 if (flags & kMajTicks) {
118 DrawHTicks(g, yMin, intXMajTickLen, extXMajTickLen, xFirstMajTick, xMajTickStep);
119 DrawHTicks(g, yMax, extXMajTickLen, intXMajTickLen, xFirstMajTick, xMajTickStep);
120 DrawVTicks(g, xMin, extYMajTickLen, intYMajTickLen, yFirstMajTick, yMajTickStep);
121 DrawVTicks(g, xMax, intYMajTickLen, extYMajTickLen, yFirstMajTick, yMajTickStep);
122 }
123
124 // Les ticks mineurs
125
126 if (flags & kMinTicks) {
127 DrawHTicks(g, yMin, intXMinTickLen, extXMinTickLen, xFirstMinTick, xMinTickStep);
128 DrawHTicks(g, yMax, extXMinTickLen, intXMinTickLen, xFirstMinTick, xMinTickStep);
129 DrawVTicks(g, xMin, extYMinTickLen, intYMinTickLen, yFirstMinTick, yMinTickStep);
130 DrawVTicks(g, xMax, intYMinTickLen, extYMinTickLen, yFirstMinTick, yMinTickStep);
131 }
132
133
134 // Les labels
135
136 if (flags & kLabels) {
137 if (!aYdir) {
138 DrawHLabels(g, g->DeltaUCY(yMin, -xMajTickLen*2), xFirstMajTick, xMajTickStep,PI_VerticalTop);
139 //DrawHLabels(g, g->DeltaUCY(yMax, xMajTickLen*2), xFirstMajTick, xMajTickStep,PI_VerticalBottom);
140 }
141 else {
142 //DrawHLabels(g, g->DeltaUCY(yMin, -xMajTickLen*2), xFirstMajTick, xMajTickStep,PI_VerticalBottom);
143 DrawHLabels(g, g->DeltaUCY(yMax, xMajTickLen*2), xFirstMajTick, xMajTickStep,PI_VerticalTop);
144 }
145 if (!aXdir) {
146 DrawVLabels(g, g->DeltaUCX(xMin, -yMajTickLen*2), yFirstMajTick, yMajTickStep,PI_HorizontalRight);
147 //DrawVLabels(g, g->DeltaUCX(xMax, yMajTickLen*2), yFirstMajTick, yMajTickStep,PI_HorizontalLeft);
148 }
149 else {
150 //DrawVLabels(g, g->DeltaUCX(xMin, -yMajTickLen*2), yFirstMajTick, yMajTickStep,PI_HorizontalLeft);
151 DrawVLabels(g, g->DeltaUCX(xMax, yMajTickLen*2), yFirstMajTick, yMajTickStep,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) ? 6 : 10;
173 BestTicks(xMin,xMax,ntick_x,xMajTickStep,xFirstMajTick);
174 xMinTickStep = xMajTickStep/5;
175 xFirstMinTick = floor(xMin / xMinTickStep) * xMinTickStep;
176 if(xFirstMinTick < xMin) xFirstMinTick += xMinTickStep;
177
178 int ntick_y = (aYlog) ? 6 : 12;
179 BestTicks(yMin,yMax,ntick_y,yMajTickStep,yFirstMajTick);
180 yMinTickStep = yMajTickStep/5;
181 yFirstMinTick = floor(yMin / yMinTickStep) * yMinTickStep;
182 if(yFirstMinTick < yMin) yFirstMinTick += yMinTickStep;
183
184 yMajTickLen = (xMax-xMin)/100;
185 yMinTickLen = (xMax-xMin)/250;
186 xMajTickLen = (yMax-yMin)/100;
187 xMinTickLen = (yMax-yMin)/250;
188}
189
190
191/* --Methode-- */
192void PIAxes::DrawHTicks(PIGraphicUC* g, double y, double tickUp,
193 double tickDown, double xBeg, double xStep)
194{
195 for (double x=xBeg; x<=xMax+xStep/10.; x += xStep)
196 g->DrawLine(x, g->DeltaUCY(y, -tickDown), x, g->DeltaUCY(y, tickUp));
197}
198
199/* --Methode-- */
200void PIAxes::DrawVTicks(PIGraphicUC* g, double x, double tickLeft,
201 double tickRight, double yBeg, double yStep)
202{
203 for (double y=yBeg; y<=yMax; y += yStep)
204 g->DrawLine(g->DeltaUCX(x, -tickLeft), y, g->DeltaUCX(x,tickRight), y);
205}
206
207/* --Methode-- */
208void PIAxes::DrawHLabels(PIGraphicUC* g, double y, double xBeg,
209 double xStep, unsigned long just)
210{
211
212 // Choix du bon format pour les labels des axes;
213 char label[64]; string format; double fac=1.; bool p10=false;
214 int npuiss = BonFormatAxes(xBeg,xMax,xStep,format,2,1);
215 if(npuiss<-2 || npuiss>3) {p10 = true; fac=pow(10.,(double)npuiss);}
216 else BonFormatAxes(xBeg,xMax,xStep,format,0,1);
217
218 double xOffset = 0;
219 double xlastlabelfin = xBeg - 2.*(xMax-xBeg);
220 for(double x=xBeg; x<=xMax+xStep/10.; x+=xStep) {
221 //Attention erreur d'arrondi x->0 (on code 5.1698e-26 au lieu de 0)
222 double xx = (fabs(x/xStep)<1.e-5) ? 0.: x;
223 sprintf(label,format.c_str(),xx/fac);
224 for(int kk=0;kk<64;kk++) if(label[kk]==' ') {label[kk]='\0'; break;}
225 double largeur = g->CalcStringWidth(label);
226 if(aXdir) xOffset = largeur/2; else xOffset=-largeur/2;
227 if(x+xOffset > xlastlabelfin) {
228 g->DrawString(x,y,label,PI_HorizontalCenter|just);
229 xlastlabelfin = x + xOffset + 1.1*largeur;
230 }
231 }
232
233 if(p10) {
234 PIGrCoord asc,desc;
235 double h = g->GetFontHeight(asc,desc);
236 if((aYdir && (just&PI_VerticalBottom)) || (!aYdir && (just&PI_VerticalTop)) ) h = -h;
237 double xm = (aXdir)? xMin: xMax;
238 double ym = g->DeltaUCY(y,1.5*h);
239 sprintf(label,"%d",npuiss);
240 g->DrawCompString(xm,ym,"x 10",label,NULL,PI_HorizontalCenter|just);
241 }
242
243}
244
245/* --Methode-- */
246void PIAxes::DrawVLabels(PIGraphicUC* g, double x, double yBeg,
247 double yStep, unsigned long just)
248{
249
250 // Choix du bon format pour les labels des axes;
251 char label[64]; string format; double fac=1.; bool p10=false;
252 int npuiss = BonFormatAxes(yBeg,yMax,yStep,format,2,1);
253 if(npuiss<-2 || npuiss>3) {p10 = true; fac=pow(10.,(double)npuiss);}
254 else BonFormatAxes(yBeg,yMax,yStep,format,0,1);
255
256 for(double y=yBeg; y<=yMax; y += yStep) {
257 double yy = (fabs(y/yStep)<1.e-5) ? 0.: y;
258 sprintf(label,format.c_str(),yy/fac);
259 for(int kk=0;kk<64;kk++) if(label[kk]==' ') {label[kk]='\0'; break;}
260 g->DrawString(x,y,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,"%d",npuiss);
269 g->DrawCompString(x,ym,"x 10",label,NULL,PI_VerticalBottom|just);
270 }
271
272}
273
274/* --Methode-- */
275void PIAxes::DrawGrid(PIGraphicUC* g)
276{
277 PILineAtt savlineatt = g->GetLineAtt();
278// g->SelLine(PI_ThinDashedLine);
279 g->SelLine(PI_ThinDottedLine);
280
281 for (double x=xFirstMajTick; x<=xMax; x += xMajTickStep)
282 g->DrawLine(x, yMin, x, yMax);
283
284 for (double y=yFirstMajTick; y<=yMax; y += yMajTickStep)
285 g->DrawLine(xMin, y, xMax, y);
286
287 g->SelLine(savlineatt);
288}
289
290
291///////////////////////////////////////////////////////////////////////////
292/* --Methode-Static-- */
293void PIAxes::BestTicks(double xmin,double xmax,int nticks
294 ,double& steptick,double& xfirsttick)
295// *** Calcul de l'intervalle entre les ticks et de la valeur du premier tick
296{
297double d=xmax-xmin; if(d<1.e-100) d=1.e-100; //if (d<1.e-39) d=1.e-39;
298double ld = log10(d);
299double fld = floor( ((ld<0.)? -ld: ld) );
300double del,del0;
301if(ld>=0.) {fld-=1.; del0=del=pow(10.,fld);}
302 else {fld+=2.; del0=del=pow(10.,-fld);}
303// *** Intervalle entre les ticks
304// xmin xmax d ld fld -->fld del0
305// 1 1500 1499 3.17 3 2 10^2
306// 1 9500 9499 3.98 3 2 10^2
307// 1 1.005 0.005 -2.3 2 4 10^-4
308// 1 1.995 0.995 -0.0022 0 2 10^-2
309// - Et recherche de la valeur del={del0,2*del0,...,20*del0}
310// telle que "nticks*del" soit le plus petit nombre ">=d"
311// Par exemple, si nticks=10:
312// 1-/ pour le 2sd cas ou d=9499 et del0=100 :
313// del = 100 200 500 1000 2000
314// nticks*del = 1000 2000 5000 10000 20000
315// d/del = 94.9 47.4 18.9 | 9.499 4.749 ==> majt = 1000
316// 2-/ pour le 3ieme cas ou d=5e-3 et del0=1e-4 :
317// del = 1e-4 2e-4 5e-4 1e-3 2e-3
318// nticks*del = 1e-3 2e-3 5e-3 1e-2 2e-2
319// d/del = 50 25 | 10 5 2.5 ==> majt = 5e-4
320int k=0;
321double fac[4] = {2.,5.,10.,20.};
322while(d/del>(double)nticks && k<4 ) {del=fac[k]*del0; k++;}
323steptick=del;
324//*** Valeur du premier tick
325xfirsttick = floor(xmin/steptick); if(xmin<0.) xfirsttick+=1.;
326xfirsttick *= steptick;
327if(xfirsttick<xmin) xfirsttick += steptick;
328}
329
330/* --Methode-Static-- */
331int PIAxes::BonFormatAxes(double xmin,double xmax,double xstep
332 ,string& format,int typf,int add_digit)
333// *** Calcul format optimal pour ecrire les labels numeriques des axes:
334// ---- Input
335// . xmin,xmax : limites du plot sur l'axe considere.
336// . xstep : distance entre les ticks.
337// . add_digit : nombre de digits a ajouter au nombre de digits minimum.
338// . typf : type de format en sortie
339// 0 : format optimum %-nn.mme ou %-nn.mmf selon valeurs
340// 1 : format %-nn.mme
341// 2 : format %-nn.mmf pour imprimer x/10^npuiss
342// tel que x/10^npuiss soit entre 0 et 10
343// ---- Output
344// . format : le format d'impression
345// ---- Return:
346// Si typ=0 ou 1
347// "ndig" : nombre de digits necessaires pour distinguer
348// les valeurs xmin+k*dx (<=xmax)
349// Si typ=2
350// "npuiss" : tel que x/10^npuiss soit entre 0 et 10
351// Dans ce cas le format est celui qui imprime x/10^npuiss
352{
353 format = "%-5g"; // format par default
354 if(xmin>=xmax) {if(typf==2) return 0; else return -1;}
355
356 if(xstep<=0. || xstep>xmax-xmin) xstep = xmax-xmin;
357
358 double axmin=fabs(xmin), axmax=fabs(xmax);
359 if(axmin>axmax) dble_SWAP(axmin,axmax);
360
361 double l10amax = log10(axmax), l10xstep = log10(xstep);
362 int il10amax = int(floor(l10amax));
363
364 // choix du type de format
365 char ftype = 'e';
366 int npuiss = 0;
367 if(typf==2) {
368 npuiss = il10amax;
369 if(npuiss<-300 || npuiss>300) {
370 ftype='e'; npuiss=0;
371 } else {
372 // On recalcule les valeurs de decision pour axmax/10^npuiss, xstep/10^npuiss
373 l10amax -= (double)npuiss; l10xstep -= (double)npuiss;
374 il10amax = int(floor(l10amax));
375 ftype = 'f';
376 }
377 } else if(typf==1) {
378 ftype='e';
379 } else {
380 ftype='e';
381 // On evite d'ecrire +a.bbbe+ccc -> format %f
382 // Ex: 1.2345e+2 -> 123.45 / -1.2345e+2 -> -123.45
383 // 1.2345e-1 -> 0.12345 / -1.2345e-1 -> -0.12345
384 if((axmin>=1e-4 || axmin==0.) && axmax<1e4) ftype='f';
385 }
386
387 //printf("BonFormatAxes[npuiss=%d]: xmin=%-21.14e xmax=%-21.14e\n",npuiss,xmin,xmax);
388 //printf(" xstep=%-21.14e log10(xstep/10^%d)=%g\n",xstep,npuiss,l10xstep);
389 //printf(" axmax=%-21.14e log10(axmax/10^%d)=%g diff=%g\n"
390 // ,axmax,npuiss,l10amax,l10amax-l10xstep);
391
392 // Nombre de digits necessaires pour ecrire axmax et xstep
393 int ndig = il10amax - int(floor(l10xstep));
394 if(ndig<0) ndig *= -1; ndig += 1;
395 //printf("ndig=%d",ndig);
396
397 // Add more digits (or suppress digits)
398 ndig += add_digit; if(ndig<0) ndig=0;
399 //printf(" + %d ==> ndig=%d\n",add_digit,ndig);
400
401 // Calcul du bon format
402 char str[16];
403 if(ftype=='f') { // Calcul du format %-nn.mmf
404 int mm=-1, nn;
405 if(il10amax<0) { // +0.12345 +0.0012345 +0.0012345 ...
406 mm = ndig - il10amax - 1; nn = mm+3;
407 } else { // +1.2345 +12.345 +123.45 ...
408 mm = ndig - il10amax - 1; nn = ndig+2;
409 }
410 //printf("format %%f : mm=%d nn=%d\n",mm,nn);
411 if(mm<0.) mm=0; if(nn<mm+3) nn=mm+3;
412 sprintf(str,"%%-%d.%df",nn,mm);
413 } else if(ftype=='e') { // Calcul du format %-nn.mme
414 // +d.<--ddd-->e+123
415 // 1 2 34567 ==> nn=ndig+7 mm=ndig-1
416 sprintf(str,"%%-%d.%de",ndig+7,ndig-1);
417 }
418
419 format = str;
420 //printf("format=[%s]\n",format.c_str());
421
422 if(typf==2) return npuiss;
423 return ndig;
424}
425
Note: See TracBrowser for help on using the repository browser.