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

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

Ajout classe PIAxes/Fonctions de trace d'axes - Reza 02/07/2002

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