00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __MULTIPLOT__
00025 #define __MULTIPLOT__
00026
00027 #include <FL/Fl.H>
00028 #include <FL/Fl_Gl_Window.H>
00029 #include <FL/gl.h>
00030 #include <float.h>
00031 #include <time.h>
00032 #include <math.h>
00033 #include <vector>
00034 #include <string>
00035 #include <sstream>
00036
00037
00038 #ifndef min
00039 #define min(a,b)( (a) < (b) ) ? (a) : (b) )
00040 #endif
00041
00042
00043
00044 using namespace std;
00045
00046 enum MULTIPLOT_GRIDSTYLE
00047 {
00048 MP_NO_GRID,
00049 MP_LINEAR_GRID,
00050 MP_LOG_GRID
00051 };
00052
00057 class PLOT_POINT
00058 {
00059 public:
00060 float x;
00061 float y;
00062 float r;
00063 float g;
00064 float b;
00065 PLOT_POINT();
00066 PLOT_POINT(float xx, float yy, float rr=1, float gg=1, float bb=1);
00067 };
00068
00073 class MULTIPLOT : public Fl_Gl_Window
00074 {
00075 public:
00080 MULTIPLOT(int x, int y, int w, int h, const char *title="MULTIPLOT - updates on www.andre-krause.net");
00085 void add(unsigned int trace, const PLOT_POINT &p);
00091 void set_max_points(int mx);
00097 void set_scrolling(int max_points_to_plot);
00105 void set_grid(int gridx, int gridy, float gridx_step=-1, float gridy_step=-1);
00106
00107 protected:
00108 string title;
00109 vector< vector<PLOT_POINT> > traces;
00110 PLOT_POINT minimum, maximum;
00111 PLOT_POINT scale;
00112 PLOT_POINT offset;
00113 unsigned int max_points;
00114 bool scroll;
00115 vector<unsigned int> pos;
00116
00117
00118 int gridx, gridy;
00119 float gridx_step, gridy_step;
00120
00121 void initgl();
00122 PLOT_POINT draw_grid();
00123 void draw();
00124 };
00125
00126
00127
00128
00129 inline PLOT_POINT::PLOT_POINT() { x=y=0.0;r=g=b=1; }
00130 inline PLOT_POINT::PLOT_POINT(float xx, float yy, float rr, float gg, float bb) { x=xx;y=yy;r=rr;g=gg;b=bb; }
00131
00132 inline MULTIPLOT::MULTIPLOT(int x, int y, int w, int h, const char *ttitle) : Fl_Gl_Window(x,y,w,h,ttitle)
00133 {
00134 title=string(ttitle);
00135
00136 maximum.x=maximum.y=-FLT_MAX;
00137 minimum.x=minimum.y=FLT_MAX;
00138 max_points=max(w,h);
00139 traces.push_back( vector<PLOT_POINT>() );
00140 pos.push_back(0);
00141
00142 scroll=false;
00143
00144 gridx=MP_NO_GRID;
00145 gridy=MP_NO_GRID;
00146 gridx_step=-1;
00147 gridy_step=-1;
00148
00149
00150 show();
00151 }
00152
00153 inline void MULTIPLOT::add(unsigned int trace, const PLOT_POINT &p)
00154 {
00155 if(traces.size()<=trace)
00156 {
00157 int n=trace-traces.size()+1;
00158 for(int a=0;a<n;a++)
00159 {
00160 traces.push_back(vector<PLOT_POINT>());
00161 pos.push_back(0);
00162 }
00163 }
00164
00165 if(scroll)
00166 {
00167
00168 if(pos[trace]<traces[trace].size())
00169 traces[trace][pos[trace]]=p;
00170 else
00171 traces[trace].push_back(p);
00172 pos[trace]++;
00173 if(pos[trace]>=max_points)
00174 pos[trace]=0;
00175 }
00176 else
00177 {
00178 traces[trace].push_back(p);
00179 }
00180 }
00181
00182 inline void MULTIPLOT::set_max_points(int mx)
00183 {
00184 max_points=mx;
00185 }
00186
00187 inline void MULTIPLOT::set_scrolling(int max_points_to_plot)
00188 {
00189 if(max_points_to_plot<=0)
00190 {
00191 scroll=false;
00192 return;
00193 }
00194
00195 scroll=true;
00196 max_points=max_points_to_plot;
00197 for(unsigned int t=0;t<traces.size();t++)
00198 if(traces[t].capacity()<max_points)
00199 traces[t].reserve(max_points);
00200
00201 }
00202
00203 inline void MULTIPLOT::set_grid(int ggridx, int ggridy, float ggridx_step, float ggridy_step)
00204 {
00205 gridx=ggridx;
00206 gridy=ggridy;
00207 gridx_step=ggridx_step;
00208 gridy_step=ggridy_step;
00209 }
00210
00211
00212 inline void MULTIPLOT::initgl()
00213 {
00214 glViewport(0 , 0,w() ,h());
00215 glMatrixMode(GL_PROJECTION);
00216 glLoadIdentity();
00217 glOrtho( 0, w(), 0, h(), -1, 1 );
00218
00219 glMatrixMode(GL_MODELVIEW);
00220 glLoadIdentity();
00221 glDisable(GL_DEPTH_TEST);
00222 glDisable(GL_LIGHTING);
00223 glShadeModel(GL_SMOOTH);
00224 glClearColor(0.0f, 0.0f, 0.0f, 1);
00225 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00226 }
00227
00228
00229
00230 inline PLOT_POINT MULTIPLOT::draw_grid()
00231 {
00232 double xstep,ystep;
00233 if(gridx==MP_LINEAR_GRID)
00234 {
00235 double diff=maximum.x - minimum.x;
00236 if(diff==0)return PLOT_POINT(0,0);
00237 double exp=floor(log10(fabs(diff)));
00238 double shiftscale=pow(10,exp);
00239
00240 double startx=shiftscale*floor(minimum.x / shiftscale);
00241
00242 if(gridx_step>0)
00243 {
00244 xstep=gridx_step;
00245 }
00246 else
00247 {
00248 xstep=shiftscale*1.0;
00249 if(diff/xstep < 4)
00250 xstep*=0.5;
00251
00252
00253
00254
00255
00256
00257
00258 }
00259 double x=startx;
00260 glColor3f(0.8f,0.8f,0.8f);
00261 glBegin(GL_LINES);
00262 int bailout=0;
00263 while(x<maximum.x && bailout<100)
00264 {
00265 x+=xstep;
00266 bailout++;
00267 glVertex2f((GLfloat)(x-offset.x)*scale.x ,0.0f );
00268 glVertex2f((GLfloat)(x-offset.x)*scale.x ,(float)h());
00269 }
00270 glEnd();
00271 }
00272 if(gridy==MP_LINEAR_GRID)
00273 {
00274 double diff=maximum.y - minimum.y;
00275 if(diff==0)return PLOT_POINT(0,0);
00276 double exp=floor(log10(fabs(diff)));
00277 double shiftscale=pow(10,exp);
00278
00279 double starty=shiftscale*floor(minimum.y / shiftscale);
00280
00281 if(gridy_step>0)
00282 {
00283 ystep=gridy_step;
00284 }
00285 else
00286 {
00287 ystep=shiftscale*1.0;
00288 if(diff/ystep < 4)
00289 ystep*=0.5;
00290
00291
00292
00293
00294
00295
00296
00297 }
00298 double y=starty;
00299 glColor3f(0.8f,0.8f,0.8f);
00300 glBegin(GL_LINES);
00301 int bailout=0;
00302 while(y<maximum.y && bailout<100)
00303 {
00304 y+=ystep;
00305 bailout++;
00306 glVertex2f(0.0f ,(GLfloat)(y-offset.y)*scale.y);
00307 glVertex2f((float)w() ,(GLfloat)(y-offset.y)*scale.y);
00308 }
00309 glEnd();
00310 }
00311
00312 return PLOT_POINT((float)xstep,(float)ystep);
00313 }
00314
00315 inline void MULTIPLOT::draw()
00316 {
00317 if(!valid())
00318 {
00319 initgl();
00320 valid(1);
00321 }
00322
00323 glClear(GL_COLOR_BUFFER_BIT);
00324
00325
00326
00327
00328 draw_grid();
00329
00330
00331 glColor3f(1,1,1);
00332 glBegin(GL_LINES);
00333 glVertex2f(0.0f ,0-offset.y*scale.y);
00334 glVertex2f((float)w() ,0-offset.y*scale.y);
00335 glVertex2f(0-offset.x*scale.x ,0.0f );
00336 glVertex2f(0-offset.x*scale.x ,(float)h());
00337 glEnd();
00338
00339
00340
00341 maximum.x=maximum.y=-FLT_MAX;
00342 minimum.x=minimum.y=FLT_MAX;
00343 if(scroll)
00344 {
00345 PLOT_POINT p;
00346 for(unsigned int t=0;t<traces.size();t++)
00347 {
00348 glBegin(GL_LINE_STRIP);
00349 unsigned int ps=pos[t];
00350 unsigned int n=traces[t].size();
00351 if(max_points<n)n=max_points;
00352 for(unsigned int a=0;a<n;a++)
00353 {
00354 if(ps>=traces[t].size())
00355 ps=0;
00356 p=traces[t][ps];
00357 glColor3f(p.r,p.g,p.b);
00358 glVertex2f((p.x-offset.x)*scale.x,(p.y-offset.y)*scale.y);
00359 if(p.x>maximum.x)maximum.x=p.x;
00360 if(p.x<minimum.x)minimum.x=p.x;
00361 if(p.y>maximum.y)maximum.y=p.y;
00362 if(p.y<minimum.y)minimum.y=p.y;
00363
00364 ps++;
00365 }
00366 glEnd();
00367 }
00368
00369 }
00370 else
00371 {
00372
00373 PLOT_POINT p;
00374
00375 float step=1;
00376
00377 for(unsigned int t=0;t<traces.size();t++)
00378 {
00379 if(traces[t].size()>max_points)
00380 step=traces[t].size()/float(max_points);
00381
00382 glBegin(GL_LINE_STRIP);
00383 for(float a=0;a<traces[t].size();a+=step)
00384 {
00385 p=traces[t][int(a)];
00386 glColor3f(p.r,p.g,p.b);
00387 glVertex2f((p.x-offset.x)*scale.x,(p.y-offset.y)*scale.y);
00388 if(p.x>maximum.x)maximum.x=p.x;
00389 if(p.x<minimum.x)minimum.x=p.x;
00390 if(p.y>maximum.y)maximum.y=p.y;
00391 if(p.y<minimum.y)minimum.y=p.y;
00392 }
00393 glEnd();
00394 }
00395 }
00396
00397 float diff;
00398 diff=maximum.x-minimum.x; if(diff!=0.0)scale.x=w()/diff;
00399 diff=maximum.y-minimum.y; if(diff!=0.0)scale.y=h()/diff;
00400 offset.x=minimum.x;
00401 offset.y=minimum.y;
00402
00403
00404 stringstream ss;
00405 ss << "range: x=[" << minimum.x << "; " << maximum.x << "] ";
00406 ss << "y=[" << minimum.y << "; " << maximum.y << "] ";
00407 this->label((ss.str() + title).c_str());
00408
00409
00410 }
00411
00412 #endif