00001
00002 #include <bgui/bgui_graph_tableau.h>
00003
00004
00005 #include <vcl_cmath.h>
00006 #include <vcl_sstream.h>
00007 #include <vnl/vnl_numeric_traits.h>
00008 #include <vnl/vnl_math.h>
00009 #include <vgui/vgui.h>
00010 #include <vgui/vgui_gl.h>
00011 #include <vgui/vgui_easy2D_tableau.h>
00012 #include <vgui/vgui_viewer2D_tableau.h>
00013 #include <vgui/vgui_shell_tableau.h>
00014
00015 void bgui_graph_tableau::init()
00016 {
00017 tt_ = vgui_text_tableau_new();
00018 tt_->set_colour(1,1,1);
00019 easy_ = vgui_easy2D_tableau_new();
00020 easy_->set_foreground(0.0, 1.0f, 0.0);
00021 easy_->set_line_width(2.0f);
00022 n_ = 0;
00023 pos_ = 0;
00024 vals_ = 0;
00025 tic_length_ = 10.0f;
00026 left_offset_ = 75;
00027 top_offset_ = 20;
00028 n_plots_ = 1;
00029 }
00030
00031
00032
00033
00034 bgui_graph_tableau::bgui_graph_tableau(const unsigned gwidth,
00035 const unsigned gheight) :
00036 graph_width_(gwidth), graph_height_(gheight), plot_(0)
00037 { this->init(); }
00038
00039
00040 bgui_graph_tableau::~bgui_graph_tableau()
00041 {
00042 this->rem();
00043 this->del();
00044 }
00045
00046
00047 float bgui_graph_tableau::map_x_to_display(const float xpos)
00048 {
00049 return left_offset_+ (xpos - xmin_)*xscale_;
00050 }
00051
00052
00053 float bgui_graph_tableau::map_y_to_display(const float ypos)
00054 {
00055 return tic_length_ + graph_height_ - (ypos - yorigin_)*yscale_ + top_offset_;
00056 }
00057
00058
00059 static float find_y_origin(const float ymin, const float yinc)
00060 {
00061 if (yinc==0)
00062 return 0;
00063 float nincs = vcl_floor(ymin/yinc);
00064 return nincs*yinc;
00065 }
00066
00067
00068 static float find_increment(float scale, float def = 1.0)
00069 {
00070 if (scale <= 0)
00071 return def;
00072
00073 float separation = 50.0 / scale;
00074
00075
00076
00077 float inc = 1;
00078
00079 while (inc < separation)
00080 inc *= 10;
00081
00082
00083
00084 while (inc > separation)
00085 inc /= 10;
00086
00087
00088
00089 if (2 * inc > separation)
00090 inc *= 2;
00091 else if (5 * inc > separation)
00092 inc *= 5;
00093 else
00094 inc *= 10;
00095
00096 return inc;
00097 }
00098
00099 void bgui_graph_tableau::compute_scale()
00100 {
00101 xscale_=1.0f; yscale_=1.0f;
00102 if (vcl_fabs(xmax_-xmin_)>0)
00103 xscale_ = (graph_width_-left_offset_)/(xmax_-xmin_);
00104 if (vcl_fabs(ymax_-ymin_)>0)
00105 yscale_ = (graph_height_-top_offset_)/(ymax_-ymin_);
00106
00107 yinc_ = find_increment(yscale_);
00108 xinc_ = find_increment(xscale_);
00109 if (yinc_ == 0.0)
00110 yinc_ = 1;
00111 if (xinc_ == 0.0)
00112 xinc_ = 1;
00113 yorigin_ = find_y_origin(ymin_,yinc_);
00114 }
00115
00116 void bgui_graph_tableau::update(vcl_vector<double> const& pos,
00117 vcl_vector<double> const & vals)
00118 {
00119 n_ = pos.size();
00120 pos_ = new float[n_];
00121 vals_ = new float[n_];
00122 xmin_ = vnl_numeric_traits<float>::maxval;
00123 xmax_ = -xmin_;
00124 ymin_ = xmin_;
00125 ymax_ = ymax_;
00126 for (unsigned i = 0; i<n_; ++i)
00127 {
00128 pos_[i]=static_cast<float>(pos[i]);
00129 xmin_ = vnl_math_min(xmin_, pos_[i]);
00130 xmax_ = vnl_math_max(xmax_, pos_[i]);
00131 vals_[i]=static_cast<float>(vals[i]);
00132 ymin_ = vnl_math_min(ymin_, vals_[i]);
00133 ymax_ = vnl_math_max(ymax_, vals_[i]);
00134 }
00135 compute_scale();
00136 draw_graph();
00137 }
00138
00139
00140 void bgui_graph_tableau::update(vcl_vector<float> const& pos,
00141 vcl_vector<float> const & vals)
00142 {
00143 n_ = pos.size();
00144 pos_ = new float[n_];
00145 vals_ = new float[n_];
00146 for (unsigned i = 0; i<n_; ++i)
00147 {
00148 pos_[i]=pos[i];
00149 xmin_ = vnl_math_min(xmin_, pos_[i]);
00150 xmax_ = vnl_math_max(xmax_, pos_[i]);
00151 vals_[i]=vals[i];
00152 ymin_ = vnl_math_min(ymin_, vals_[i]);
00153 ymax_ = vnl_math_max(ymax_, vals_[i]);
00154 }
00155 compute_scale();
00156 draw_graph();
00157 }
00158
00159
00160
00161
00162 void bgui_graph_tableau::update(vcl_vector<vcl_vector<double> > const& pos,
00163 vcl_vector<vcl_vector<double> >const & vals)
00164 {
00165 n_plots_ = pos.size();
00166 if (!n_plots_)
00167 return;
00168 n_ = pos[0].size();
00169 mpos_ = pos; mvals_=vals;
00170 double xmin, ymin, xmax, ymax;
00171 xmin = vnl_numeric_traits<double>::maxval;
00172 xmax = -xmin;
00173 ymin = xmin;
00174 ymax = xmax;
00175 for (unsigned p = 0; p<n_plots_; ++p)
00176 for (unsigned i = 0; i<n_; ++i)
00177 {
00178 xmin = vnl_math_min(xmin, pos[p][i]);
00179 xmax = vnl_math_max(xmax, pos[p][i]);
00180 ymin = vnl_math_min(ymin, vals[p][i]);
00181 ymax = vnl_math_max(ymax, vals[p][i]);
00182 }
00183 xmin_ = static_cast<float>(xmin);
00184 xmax_ = static_cast<float>(xmax);
00185 ymin_ = static_cast<float>(ymin);
00186 ymax_ = static_cast<float>(ymax);
00187 compute_scale();
00188 draw_multi_graph();
00189 }
00190
00191
00192 void bgui_graph_tableau::draw_tics()
00193 {
00194 float xs = xmin_;
00195 float ys = yorigin_;
00196 float tl = tic_length_;
00197 unsigned ix = 0, iy = 0;
00198
00199 float y0 = map_y_to_display(yorigin_);
00200
00201 while (xs <= xmax_+xinc_)
00202 {
00203 float xd = map_x_to_display(xs);
00204 if (ix%2!=0)
00205 xtics_.push_back(easy_->add_line(xd, y0, xd, y0-tl));
00206 else
00207 {
00208 easy_->set_foreground(1.0f, 0.0, 0.0);
00209 xtics_.push_back(easy_->add_line(xd, y0, xd, y0-1.5f*tl));
00210 easy_->set_foreground(0.0f, 1.0f, 0.0);
00211 }
00212 vcl_stringstream ts;
00213 ts<<xs;
00214 vcl_string xval = ts.str();
00215 unsigned nchars = xval.size();
00216 float offset = static_cast<float>(nchars)/2;
00217 offset *= 10.0f;
00218 tt_->add(xd-offset, y0+15, xval);
00219 xs += xinc_;
00220 ++ix;
00221 }
00222 xtics_.push_back(easy_->add_line(map_x_to_display(xmin_), y0,
00223 map_x_to_display(xmax_+xinc_), y0));
00224
00225
00226 while (ys <= ymax_+yinc_)
00227 {
00228 float yd = map_y_to_display(ys);
00229 if (iy%2!=0)
00230 ytics_.push_back(easy_->add_line(left_offset_,yd,
00231 tl+left_offset_,yd));
00232 else
00233 {
00234 easy_->set_foreground(1.0f, 0.0, 0.0);
00235 ytics_.push_back(easy_->add_line(left_offset_,yd,
00236 1.5f*tl+left_offset_,yd));
00237 easy_->set_foreground(0.0f, 1.0f, 0.0);
00238 }
00239 vcl_stringstream ts;
00240 ts<<ys;
00241 vcl_string yval = ts.str();
00242 float len = yval.size()+1;
00243 len*= 10.0f;
00244 tt_->add(left_offset_-len, yd+5.0f, yval);
00245
00246 ys += yinc_;
00247 ++iy;
00248 }
00249 ytics_.push_back(easy_->
00250 add_line(left_offset_,map_y_to_display(yorigin_),
00251 left_offset_,
00252 map_y_to_display(ymax_+yinc_)));
00253
00254
00255 for (vcl_vector<vgui_soview2D_lineseg*>::iterator cit = xtics_.begin();
00256 cit!=xtics_.end(); ++cit)
00257 (*cit)->set_selectable(false);
00258 for (vcl_vector<vgui_soview2D_lineseg*>::iterator cit = ytics_.begin();
00259 cit!=ytics_.end(); ++cit)
00260 (*cit)->set_selectable(false);
00261 }
00262
00263
00264 void bgui_graph_tableau::draw_graph()
00265 {
00266 if (n_ == 0)
00267 return;
00268 vcl_vector<float> x(n_), y(n_);
00269 if (m_plot_.size())
00270 {
00271 for (unsigned i =0; i<m_plot_.size(); ++i)
00272 easy_->remove(m_plot_[i]);
00273 m_plot_.clear();
00274 tt_->clear();
00275 }
00276 if (plot_)
00277 {
00278 easy_->remove(plot_);
00279 tt_->clear();
00280 delete plot_;
00281 plot_ = 0;
00282 }
00283 for (unsigned i = 0; i<n_; ++i)
00284 {
00285 x[i]=map_x_to_display(pos_[i]);
00286 y[i]=map_y_to_display(vals_[i]);
00287 }
00288 plot_ = easy_->add_linestrip(n_, &x[0], &y[0]);
00289 plot_->set_selectable(false);
00290 draw_tics();
00291 this->post_redraw();
00292 }
00293
00294
00295 void bgui_graph_tableau::draw_multi_graph()
00296 {
00297
00298 float r[7]={1,0,0,1,0,1,1};
00299 float g[7]={0,1,0,0,1,1,1};
00300 float b[7]={0,0,1,1,1,0,1};
00301 if (n_ == 0)
00302 return;
00303 if (m_plot_.size())
00304 {
00305 for (unsigned i =0; i<m_plot_.size(); ++i)
00306 easy_->remove(m_plot_[i]);
00307 m_plot_.clear();
00308 tt_->clear();
00309 }
00310 for (unsigned p = 0; p<n_plots_; ++p)
00311 {
00312 vcl_vector<float> x(n_), y(n_);
00313 for (unsigned i = 0; i<n_; ++i)
00314 {
00315 x[i]=map_x_to_display(static_cast<float>(mpos_[p][i]));
00316 y[i]=map_y_to_display(static_cast<float>(mvals_[p][i]));
00317 }
00318 unsigned c = p%7;
00319 easy_->set_foreground(r[c], g[c], b[c]);
00320 vgui_soview2D_linestrip* ls = easy_->add_linestrip(n_, &x[0], &y[0]);
00321 ls->set_selectable(false);
00322 m_plot_.push_back(ls);
00323 }
00324 draw_tics();
00325 this->post_redraw();
00326 }
00327
00328
00329 void bgui_graph_tableau::rem()
00330 {
00331 if (plot_)
00332 {
00333 easy_->remove(plot_);
00334
00335 plot_ = 0;
00336 }
00337 for (vcl_vector<vgui_soview2D_lineseg*>::iterator cit = xtics_.begin();
00338 cit!=xtics_.end(); ++cit)
00339 if (*cit)
00340 {
00341 easy_->remove(*cit);
00342
00343 }
00344 for (vcl_vector<vgui_soview2D_lineseg*>::iterator cit = ytics_.begin();
00345 cit!=ytics_.end(); ++cit)
00346 if (*cit)
00347 {
00348 easy_->remove(*cit);
00349
00350 }
00351 for (unsigned i = 0; i< m_plot_.size(); ++i)
00352 easy_->remove(m_plot_[i]);
00353 m_plot_.clear();
00354 }
00355
00356
00357 void bgui_graph_tableau::del()
00358 {
00359 if (pos_)
00360 {
00361 delete [] pos_;
00362 pos_ =0;
00363 }
00364 if (vals_)
00365 {
00366 delete [] vals_;
00367 vals_ = 0;
00368 }
00369 }
00370
00371
00372 void bgui_graph_tableau::clear()
00373 {
00374 this->rem();
00375 this->del();
00376 this->post_redraw();
00377 }
00378
00379
00380
00381 vgui_dialog* bgui_graph_tableau::popup_graph(vcl_string const& info,
00382 const unsigned sizex,
00383 const unsigned sizey)
00384 {
00385 unsigned w = graph_width_+25, h = graph_height_+25;
00386 if (sizex>0)
00387 w = sizex;
00388 if (sizey>0)
00389 h = sizey;
00390 vgui_viewer2D_tableau_sptr v = vgui_viewer2D_tableau_new(this);
00391 vgui_shell_tableau_sptr s = vgui_shell_tableau_new(v);
00392 vcl_string temp = info;
00393 vcl_stringstream xinc, yinc, ymin, ymax;
00394 xinc << xinc_; yinc << yinc_; ymin << ymin_; ymax<< ymax_;
00395 #if 0
00396 temp += " xinc:" + xinc.str();
00397 temp += " yinc:" + yinc.str();
00398 #endif
00399 temp += " ymin:" + ymin.str();
00400 temp += " ymax:" + ymax.str();
00401 vgui_dialog* d = new vgui_dialog(temp.c_str());
00402 d->inline_tableau(s, w, h);
00403 return d;
00404 }
00405
00406
00407
00408 bool bgui_graph_tableau::handle(const vgui_event& event)
00409 {
00410
00411 if (event.type == vgui_DRAW)
00412 {
00413 vcl_cout << "Graph Handle\n";
00414 easy_->handle(event);
00415 tt_->handle(event);
00416 }
00417 return false;
00418 }
00419