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

Last change on this file since 3487 was 3153, checked in by ansari, 19 years ago

Adaptation+petites corrections, suite gestion P1D,P2DArrayAdapter::DecodeOptionString() ::OptionToString() par PIImage et PISurfDrawer, Reza 19/01/2007

File size: 11.4 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 g->SelFontSz((YMax() - YMin())/30);
347
348 // La hauteur de la cellule
349 PIGrCoord a, d;
350 double cH = (double)g->GetFontHeight(a,d);
351 vector<string> lines;
352 int nlig = mHistoWp->GetStatInfoAsText(lines);
353 if (nlig < 1) return;
354
355 double cellHeight = nlig*1.2 * cH;
356
357 int idxll = 0;
358
359 int kl;
360 // on recherche la ligne la plus longue
361 for(kl=1; kl<nlig; kl++)
362 if ( lines[kl].length() > lines[idxll].length() ) idxll = kl;
363
364 double cellWidth = 1.1 * (double)g->CalcStringWidth(lines[idxll].c_str());
365
366 double ofpx = spoX*(XMax()-XMin());
367 double ofpy = spoY*(YMax()-YMin());
368
369 double xu, yu, cw;
370 // Les limites du cadre
371 xu = g->DeltaUCX(XMax(), -cellWidth);
372 yu = g->DeltaUCY(YMax(), -cellHeight);
373 double recw = XMax()-xu;
374 double rech = YMax()-yu;
375 xu += ofpx; yu += ofpy;
376 g->DrawBox(xu, yu, recw, rech);
377
378 // L'ecriture des labels (attention aux inversions possibles des axes!)
379 cw = (g->isAxeXDirRtoL()) ? -0.05*cellWidth : -0.95*cellWidth;
380 xu = g->DeltaUCX(XMax(),cw);
381
382 cw = (g->isAxeYDirUpDown()) ? -0.15*cH : -1.15*cH;
383 yu = g->DeltaUCY(YMax(),cw);
384 xu += ofpx; yu += ofpy;
385
386 for(kl=0; kl<nlig; kl++) {
387 g->DrawString(xu, yu, lines[kl].c_str() );
388 cw += -1.15*cH;
389 yu = g->DeltaUCY(YMax(),cw); yu += ofpy;
390 }
391
392}
393
394/* --Methode-- */
395double
396PIHisto::GetDistanceToPoint(double x, double y)
397{
398 if (!mHistoWp) return 1.e+9;
399
400 double dist = -1.e+18;
401 for(int i=0; i<mHistoWp->NBins(); i++) {
402 double xp=mHistoWp->BinCenter(i);
403 double yp=(*mHistoWp)(i);
404 xp = (xp-x)/(XMax()-XMin())/0.5;
405 yp = (yp-y)/(YMax()-YMin())/0.5;
406 xp = xp*xp+yp*yp;
407 if(dist<0. || xp<dist) dist = xp;
408 }
409 dist=sqrt(fabs(dist));
410 //cout<<dist<<"PIHisto: xlim="<<XMin()<<","<<XMax()<<" ylim="<<YMin()<<","<<YMax()
411 // <<" NBins="<<mHistoWp->NBins()<<endl;
412 //cout<<"....d="<<dist<<" x="<<x<<" y="<<y<<endl;
413
414 return dist;
415}
Note: See TracBrowser for help on using the repository browser.