source: Sophya/trunk/SophyaPI/PIext/pihisto.cc@ 4024

Last change on this file since 4024 was 3559, checked in by ansari, 17 years ago

Amelioration gestion taille de fonte ds PIHisto, PINTuple ... en utilisant le flag AutoFontSize mis ds la classe PIDrawer (attributs autofontsize=, fixedfontsize), Reza 24/12/2008

File size: 11.6 KB
Line 
1// Classe traceur d histogramme 96-99
2// C. Magneville , R. Ansari 2000-2007
3// (C) CEA-DAPNIA LAL-IN2P3/CNRS
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <iostream>
8#include <math.h>
9#include <typeinfo>
10
11#include "pihisto.h"
12
13//------ Implementation classe P1DHistoWrapper
14P1DHistoWrapper::P1DHistoWrapper(int_4 asx)
15 : P1DArrayAdapter(asx) ,
16 mScale(1.) , mOff(0.) , mRetFg(0)
17{
18}
19
20P1DHistoWrapper::~P1DHistoWrapper()
21{
22}
23
24int P1DHistoWrapper::GetStatInfoAsText(vector<string> & /* text */ )
25{
26 return 0;
27}
28
29int P1DHistoWrapper::DecodeOptionString(vector<string> & opt, bool rmdecopt)
30{
31 if(opt.size() < 1) return(0);
32
33 vector<string> udopt; // On gardera ici les options non decodees
34 unsigned int k = 0;
35 int ndec = opt.size();
36 for( k=0; k<opt.size(); k++ ) {
37 string & opts = opt[k];
38 if(opts.substr(0,7) == "hs1") {
39 mScale = 1.; mOff = 0.;
40 }
41 else if(opts.substr(0,7) == "hscale=") {
42 mScale = atof(opts.substr(7).c_str());
43 }
44 else if(opts.substr(0,8) == "hoffset=") {
45 mOff = atof(opts.substr(8).c_str());
46 }
47 else if(opts.substr(0,8) == "hbincont") {
48 mRetFg = 0;
49 }
50 else if(opts.substr(0,7) == "hbinerr") {
51 mRetFg = 1;
52 }
53 else if(opts.substr(0,7) == "hbinent") {
54 mRetFg = 2;
55 }
56 else {
57 ndec--;
58 // S'il faut supprimer les options decodees
59 if (rmdecopt) udopt.push_back(opts);
60 }
61 }
62 // S'il faut supprimer les options decodees, on remplace l'argument opt
63 // par le vecteur des options non decodees.
64 if (rmdecopt) opt = udopt;
65 return(ndec);
66}
67
68int
69P1DHistoWrapper::OptionToString(vector<string> & opt) const
70{
71 char buff[64];
72 sprintf(buff, "hscale=%g", mScale); opt.push_back(buff);
73 sprintf(buff, "hoffset=%g", mOff); opt.push_back(buff);
74 if (mRetFg == 2) opt.push_back("hbinent");
75 else if (mRetFg == 1) opt.push_back("hbinerr");
76 else opt.push_back("hbincont");
77
78 return 1;
79}
80
81
82//++
83// Class PIHisto
84// Lib PIext
85// include pihisto.h
86//
87// Classe traceur d'objet histogramme (classe *P1DHistoWrapper*)
88//--
89//++
90// Links Parents
91// PIDrawer
92//--
93//++
94// Titre Constructeur, méthodes
95//--
96//++
97// PIHisto(P1DHistoWrapper* histowp, bool ad=false)
98// Constructeur. Si "ad == true", l'objet "histowp" est détruit par
99// le destructeur de l'objet "PIHisto"
100// Note : "histowp" doit être créé par new si ad==true
101//
102//--
103
104
105PIHisto::PIHisto(P1DHistoWrapper* histowp, bool ad)
106: PIDrawer(), mHistoWp(histowp)
107{
108 mAdDO = ad; // Flag pour suppression automatique de mHistoWp
109 stats=true;
110 pline=true;
111 error=false;
112 filled=false;
113 spoX=-0.01; spoY=-0.01;
114 SetName("HistoDrw");
115}
116
117PIHisto::~PIHisto()
118{
119 if(mAdDO) delete mHistoWp;
120}
121
122void
123PIHisto::UpdateLimits()
124{
125 if (!mHistoWp) return;
126 if ( mHistoWp->NBins() < 1 ) {
127 SetLimits(mHistoWp->XMin(), mHistoWp->XMax(), 0., 1.);
128 }
129 double v,hmin,hmax;
130 hmin = hmax = (*mHistoWp)(0);
131 for (int_4 i=1; i<mHistoWp->NBins(); i++) {
132 v = (*mHistoWp)(i);
133 if(v<hmin) hmin = v;
134 if(v>hmax) hmax = v;
135 }
136 if ( isLogScaleY() ) {
137 if ( hmin >= 0.) {
138 if ( hmax <= hmin ) {
139 hmax = hmin*10.;
140 if (hmax <= 0.) hmax = 1.;
141 if (hmin <= 0.) hmin = hmax / 100.;
142 }
143 else if ( (hmin == 0.) && (hmax > hmin) ) hmin = hmax/1.e6;
144 else hmin /= 1.1;
145 }
146 else if (hmax > 0.) hmax *= 1.1;
147 }
148 else {
149 v = 0.05*(hmax-hmin);
150 hmin -= v; hmax += v;
151 }
152 if(hmax<=hmin) hmax = hmin+1.;
153
154 SetLimits(mHistoWp->XMin(), mHistoWp->XMax(), hmin, hmax);
155}
156
157void
158PIHisto::Draw(PIGraphicUC* g, double /*xmin*/, double /*ymin*/, double /*xmax*/, double /*ymax*/)
159{
160 if (axesFlags != kAxesNone) DrawAxes(g);
161
162 if (!mHistoWp) return;
163 if (mHistoWp->NBins()<=0) return;
164
165 mHistoWp->Update();
166
167 // Tracer d'une polyline si demandee
168 bool drawpline=false;
169 if (pline) drawpline=true;
170 // Tracer des marqueurs si demande ou si HProf
171 bool drawmarker=false;
172 if (GetGraphicAtt().GetMarker() != PI_NotDefMarker) drawmarker = true;
173 // Tracer des erreurs ?
174 bool drawerr=false;
175 if (error) drawerr = true;
176 // Fill de l'histo ?
177 bool drawfill=false;
178 if(filled) drawfill=true; else drawfill=false;
179 // Et aussi si on ne demande ni ligne ni marqueur ni erreur ni fill ?
180 if( !drawmarker && !drawfill && !drawerr ) drawpline=true;
181
182 // Remplissage des bins avec la couleur courante (trace en premier)
183 if(drawfill) {
184 for(int i=0; i<mHistoWp->NBins(); i++) {
185 double left = mHistoWp->BinLowEdge(i);
186 double width = mHistoWp->BinWidth();
187 double bottom = 0;
188 double height = (*mHistoWp)(i);
189 g->DrawFBox(left,bottom,width,height);
190 }
191 }
192
193 // Trace des marqeurs
194 if(drawmarker) {
195 double x1,y1;
196 for(int i=0; i<mHistoWp->NBins(); i++) {
197 x1 = mHistoWp->BinCenter(i);
198 y1 = (*mHistoWp)(i);
199 g->DrawMarker(x1,y1);
200 }
201 }
202
203 // Trace des erreurs
204 if(drawerr) {
205 if(GetGraphicAtt().GetLineAtt()==PI_NotDefLineAtt) g->SelLine(PI_ThinLine);
206 double x1,x2,y1,y2;
207 double bw = mHistoWp->BinWidth();
208 for(int i=0; i<mHistoWp->NBins(); i++) {
209 if(mHistoWp->Error(i)>0.) {
210 // barres d'erreur verticales
211 x1 = x2 = mHistoWp->BinCenter(i);
212 y1 = (*mHistoWp)(i) - mHistoWp->Error(i);
213 y2 = (*mHistoWp)(i) + mHistoWp->Error(i);
214 g->DrawLine(x1,y1, x1, y2);
215 // limites de barres d'erreurs (horizontales)
216 x1 -= bw/3.; x2 += bw/3.;
217 g->DrawLine(x1,y1, x2, y1);
218 g->DrawLine(x1,y2, x2, y2);
219 }
220 }
221 }
222
223 // Trace de la ligne continue si demandee
224 if(drawpline) {
225 if(GetGraphicAtt().GetLineAtt()==PI_NotDefLineAtt) g->SelLine(PI_ThinLine);
226 PIGrCoord* x1 = new PIGrCoord[2*mHistoWp->NBins()+2];
227 PIGrCoord* y1 = new PIGrCoord[2*mHistoWp->NBins()+2];
228 double dx = mHistoWp->BinWidth();
229 int npt=0;
230 x1[npt] = mHistoWp->BinLowEdge(0);
231 y1[npt] = 0;
232 npt++;
233 for(int i=0; i<mHistoWp->NBins(); i++) {
234 x1[npt] = mHistoWp->BinLowEdge(i);
235 y1[npt] = (*mHistoWp)(i);
236 npt++;
237 x1[npt] = (double)x1[npt-1] + dx;
238 y1[npt] = y1[npt-1];
239 npt++;
240 }
241 x1[npt] = x1[npt-1];
242 y1[npt] = 0;
243 npt++;
244 g->DrawPolygon(x1,y1,npt,false);
245 delete [] x1; delete [] y1;
246 }
247
248 // Trace/Ecriture des statistiques
249 // A faire a la fin - DrawStats change l'attribut de ligne
250 if(stats) DrawStats(g);
251}
252
253int
254PIHisto::DecodeOptionString(vector<string> & opt, bool rmdecopt)
255{
256 int optsz1 = opt.size();
257 if(optsz1<1) return(0);
258 int ndec1 = PIDrawer::DecodeOptionString(opt, rmdecopt);
259 if(optsz1-ndec1<1) return(ndec1); // si tout a ete decode
260
261 vector<string> udopt; // On gardera ici les options non decodees
262 unsigned int k = 0;
263 int ndec = opt.size();
264 for( k=0; k<opt.size(); k++ ) {
265 string opts = opt[k];
266 if(opts=="sta" || opts=="stat" || opts=="stats") stats=true;
267 else if( opts=="nsta" || opts=="nstat"
268 || opts=="nostat" || opts=="nostats") stats=false;
269 else if(opts=="err") error=true;
270 else if(opts=="noerr" || opts=="nerr") error=false;
271 else if(opts=="fill") { filled=true; pline=false; }
272 else if(opts=="nofill" || opts=="nfill") filled=false;
273 else if(opts=="pline") { pline=true; filled=false; }
274 else if(opts=="nopline") pline=false;
275 else if(opts.substr(0,11) == "statposoff=") {
276 double xo=0., yo=0.;
277 sscanf(opts.substr(11).c_str(),"%lf,%lf",&xo, &yo);
278 spoX=xo; spoY=yo;
279 }
280 else {
281 ndec--;
282 // S'il faut supprimer les options decodees
283 if (rmdecopt) udopt.push_back(opts);
284 }
285 }
286
287 // S'il faut supprimer les options decodees, on remplace l'argument opt
288 // par le vecteur des options non decodees.
289 if (rmdecopt) opt = udopt;
290
291 // Decodage des options par le histo-wrapper
292 int ndec2 = 0;
293 if ( ( optsz1-ndec1-ndec > 0) && (mHistoWp) ) {
294 ndec2 = mHistoWp->DecodeOptionString(opt, rmdecopt);
295 }
296 return(ndec+ndec1+ndec2);
297}
298
299int
300PIHisto::OptionToString(vector<string> & opt) const
301{
302 PIDrawer::OptionToString(opt);
303
304 if(stats) opt.push_back("stat"); else opt.push_back("nostat");
305 if(error) opt.push_back("err"); else opt.push_back("noerr");
306 if(filled) opt.push_back("fill"); else opt.push_back("nofill");
307 if(pline) opt.push_back("pline"); else opt.push_back("nopline");
308
309 char str[256]; sprintf(str,"statposoff=%g,%g",spoX,spoY);
310 opt.push_back(str);
311
312 if (mHistoWp) mHistoWp->OptionToString(opt);
313 return 1;
314}
315
316void
317PIHisto::GetOptionsHelpInfo(string& info)
318{
319info += " ---- PIHisto options help info : \n" ;
320info += " sta,stat,stats: activate statistic display\n";
321info += " nsta,nstat,nostat,nostats: deactivate statistic display\n";
322info += " pline/nopline: display/do not display as polyline (def= pline) \n";
323info += " err/noerr,nerr: draw/do not draw error bars (def= noerr) \n";
324info += " fill/nofill,nfill: fill/do not fill histo (def= nofill) \n";
325info += " - Use marker attribute (marker=...) to draw markers \n";
326info += " statposoff=OffsetX,OffsetY : Position offset for Stats drawing \n";
327info += " as a fraction of total size \n";
328info += " ---- HistoWrapper options : \n" ;
329info += " hbincont: select bin content as Y value for display (default) \n";
330info += " hbinerr: select bin error as Y value for display \n";
331info += " hbinent: select bin entries as Y value for display \n";
332info += " hscale=value : multiplicative factor for Y value \n" ;
333info += " hoffset=value : additive coefficient for Y value \n" ;
334info += " hs1: set hscale=1 hoffset=0 (default) \n" ;
335// On recupere ensuite la chaine info de la classe de base
336PIDrawer::GetOptionsHelpInfo(info);
337return;
338}
339
340void
341PIHisto::DrawStats(PIGraphicUC* g)
342{
343 if (!mHistoWp) return;
344 // if (mLAtt == PI_NotDefLineAtt) g->SelLine(PI_ThinLine);
345 g->SelLine(PI_ThinLine);
346// Reza(12/2008): utilisation de flag et fraction pour selection automatique taille de fonte
347 if (mAFSz) {
348 double fsz = (YMax() - YMin())*mFontSzF;
349 g->SelFontSz(fsz); // au lieu de 1/30*(ymax-ymin)
350 }
351 // La hauteur de la cellule
352 PIGrCoord a, d;
353 double cH = (double)g->GetFontHeight(a,d);
354 vector<string> lines;
355 int nlig = mHistoWp->GetStatInfoAsText(lines);
356 if (nlig < 1) return;
357
358 double cellHeight = nlig*1.2 * cH;
359
360 int idxll = 0;
361
362 int kl;
363 // on recherche la ligne la plus longue
364 for(kl=1; kl<nlig; kl++)
365 if ( lines[kl].length() > lines[idxll].length() ) idxll = kl;
366
367 double cellWidth = 1.1 * (double)g->CalcStringWidth(lines[idxll].c_str());
368
369 double ofpx = spoX*(XMax()-XMin());
370 double ofpy = spoY*(YMax()-YMin());
371
372 double xu, yu, cw;
373 // Les limites du cadre
374 xu = g->DeltaUCX(XMax(), -cellWidth);
375 yu = g->DeltaUCY(YMax(), -cellHeight);
376 double recw = XMax()-xu;
377 double rech = YMax()-yu;
378 xu += ofpx; yu += ofpy;
379 g->DrawBox(xu, yu, recw, rech);
380
381 // L'ecriture des labels (attention aux inversions possibles des axes!)
382 cw = (g->isAxeXDirRtoL()) ? -0.05*cellWidth : -0.95*cellWidth;
383 xu = g->DeltaUCX(XMax(),cw);
384
385 cw = (g->isAxeYDirUpDown()) ? -0.15*cH : -1.15*cH;
386 yu = g->DeltaUCY(YMax(),cw);
387 xu += ofpx; yu += ofpy;
388
389 for(kl=0; kl<nlig; kl++) {
390 g->DrawString(xu, yu, lines[kl].c_str() );
391 cw += -1.15*cH;
392 yu = g->DeltaUCY(YMax(),cw); yu += ofpy;
393 }
394
395}
396
397/* --Methode-- */
398double
399PIHisto::GetDistanceToPoint(double x, double y)
400{
401 if (!mHistoWp) return 1.e+9;
402
403 double dist = -1.e+18;
404 for(int i=0; i<mHistoWp->NBins(); i++) {
405 double xp=mHistoWp->BinCenter(i);
406 double yp=(*mHistoWp)(i);
407 xp = (xp-x)/(XMax()-XMin())/0.5;
408 yp = (yp-y)/(YMax()-YMin())/0.5;
409 xp = xp*xp+yp*yp;
410 if(dist<0. || xp<dist) dist = xp;
411 }
412 dist=sqrt(fabs(dist));
413 //cout<<dist<<"PIHisto: xlim="<<XMin()<<","<<XMax()<<" ylim="<<YMin()<<","<<YMax()
414 // <<" NBins="<<mHistoWp->NBins()<<endl;
415 //cout<<"....d="<<dist<<" x="<<x<<" y="<<y<<endl;
416
417 return dist;
418}
Note: See TracBrowser for help on using the repository browser.