00001
00002 #include "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.0f)
00069 {
00070 if (scale <= 0)
00071 return def;
00072
00073 float separation = 50.0f / 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 ymin_ = xmin_ = vnl_numeric_traits<float>::maxval;
00123 ymax_ = xmax_ = -xmin_;
00124 for (unsigned i = 0; i<n_; ++i)
00125 {
00126 pos_[i]=static_cast<float>(pos[i]);
00127 xmin_ = vnl_math_min(xmin_, pos_[i]);
00128 xmax_ = vnl_math_max(xmax_, pos_[i]);
00129 vals_[i]=static_cast<float>(vals[i]);
00130 ymin_ = vnl_math_min(ymin_, vals_[i]);
00131 ymax_ = vnl_math_max(ymax_, vals_[i]);
00132 }
00133 compute_scale();
00134 draw_graph();
00135 }
00136
00137
00138 void bgui_graph_tableau::update(vcl_vector<float> const& pos,
00139 vcl_vector<float> const & vals)
00140 {
00141 n_ = pos.size();
00142 pos_ = new float[n_];
00143 vals_ = new float[n_];
00144 for (unsigned i = 0; i<n_; ++i)
00145 {
00146 pos_[i]=pos[i];
00147 xmin_ = vnl_math_min(xmin_, pos_[i]);
00148 xmax_ = vnl_math_max(xmax_, pos_[i]);
00149 vals_[i]=vals[i];
00150 ymin_ = vnl_math_min(ymin_, vals_[i]);
00151 ymax_ = vnl_math_max(ymax_, vals_[i]);
00152 }
00153 compute_scale();
00154 draw_graph();
00155 }
00156
00157
00158
00159
00160 void bgui_graph_tableau::update(vcl_vector<vcl_vector<double> > const& pos,
00161 vcl_vector<vcl_vector<double> >const & vals)
00162 {
00163 n_plots_ = pos.size();
00164 if (!n_plots_)
00165 return;
00166 n_ = pos[0].size();
00167 mpos_ = pos; mvals_=vals;
00168 double xmin, ymin, xmax, ymax;
00169 xmin = vnl_numeric_traits<double>::maxval;
00170 xmax = -xmin;
00171 ymin = xmin;
00172 ymax = xmax;
00173 for (unsigned p = 0; p<n_plots_; ++p)
00174 for (unsigned i = 0; i<n_; ++i)
00175 {
00176 xmin = vnl_math_min(xmin, pos[p][i]);
00177 xmax = vnl_math_max(xmax, pos[p][i]);
00178 ymin = vnl_math_min(ymin, vals[p][i]);
00179 ymax = vnl_math_max(ymax, vals[p][i]);
00180 }
00181 xmin_ = static_cast<float>(xmin);
00182 xmax_ = static_cast<float>(xmax);
00183 ymin_ = static_cast<float>(ymin);
00184 ymax_ = static_cast<float>(ymax);
00185 compute_scale();
00186 draw_multi_graph();
00187 }
00188
00189
00190 void bgui_graph_tableau::draw_tics()
00191 {
00192 float xs = xmin_;
00193 float ys = yorigin_;
00194 float tl = tic_length_;
00195 unsigned ix = 0, iy = 0;
00196
00197 float y0 = map_y_to_display(yorigin_);
00198
00199 while (xs <= xmax_+xinc_)
00200 {
00201 float xd = map_x_to_display(xs);
00202 if (ix%2!=0)
00203 xtics_.push_back(easy_->add_line(xd, y0, xd, y0-tl));
00204 else
00205 {
00206 easy_->set_foreground(1.0f, 0.0, 0.0);
00207 xtics_.push_back(easy_->add_line(xd, y0, xd, y0-1.5f*tl));
00208 easy_->set_foreground(0.0f, 1.0f, 0.0);
00209 }
00210 vcl_stringstream ts;
00211 ts<<xs;
00212 vcl_string xval = ts.str();
00213 unsigned nchars = xval.size();
00214 float offset = static_cast<float>(nchars)/2;
00215 offset *= 10.0f;
00216 tt_->add(xd-offset, y0+15, xval);
00217 xs += xinc_;
00218 ++ix;
00219 }
00220 xtics_.push_back(easy_->add_line(map_x_to_display(xmin_), y0,
00221 map_x_to_display(xmax_+xinc_), y0));
00222
00223
00224 while (ys <= ymax_+yinc_)
00225 {
00226 float yd = map_y_to_display(ys);
00227 if (iy%2!=0)
00228 ytics_.push_back(easy_->add_line(left_offset_,yd,
00229 tl+left_offset_,yd));
00230 else
00231 {
00232 easy_->set_foreground(1.0f, 0.0, 0.0);
00233 ytics_.push_back(easy_->add_line(left_offset_,yd,
00234 1.5f*tl+left_offset_,yd));
00235 easy_->set_foreground(0.0f, 1.0f, 0.0);
00236 }
00237 vcl_stringstream ts;
00238 ts<<ys;
00239 vcl_string yval = ts.str();
00240 float len = yval.size()+1;
00241 len*= 10.0f;
00242 tt_->add(left_offset_-len, yd+5.0f, yval);
00243
00244 ys += yinc_;
00245 ++iy;
00246 }
00247 ytics_.push_back(easy_->
00248 add_line(left_offset_,map_y_to_display(yorigin_),
00249 left_offset_,
00250 map_y_to_display(ymax_+yinc_)));
00251
00252
00253 for (vcl_vector<vgui_soview2D_lineseg*>::iterator cit = xtics_.begin();
00254 cit!=xtics_.end(); ++cit)
00255 (*cit)->set_selectable(false);
00256 for (vcl_vector<vgui_soview2D_lineseg*>::iterator cit = ytics_.begin();
00257 cit!=ytics_.end(); ++cit)
00258 (*cit)->set_selectable(false);
00259 }
00260
00261
00262 void bgui_graph_tableau::draw_graph()
00263 {
00264 if (n_ == 0)
00265 return;
00266 vcl_vector<float> x(n_), y(n_);
00267 if (m_plot_.size())
00268 {
00269 for (unsigned i =0; i<m_plot_.size(); ++i)
00270 easy_->remove(m_plot_[i]);
00271 m_plot_.clear();
00272 tt_->clear();
00273 }
00274 if (plot_)
00275 {
00276 easy_->remove(plot_);
00277 tt_->clear();
00278 delete plot_;
00279 plot_ = 0;
00280 }
00281 for (unsigned i = 0; i<n_; ++i)
00282 {
00283 x[i]=map_x_to_display(pos_[i]);
00284 y[i]=map_y_to_display(vals_[i]);
00285 }
00286 plot_ = easy_->add_linestrip(n_, &x[0], &y[0]);
00287 plot_->set_selectable(false);
00288 draw_tics();
00289 this->post_redraw();
00290 }
00291
00292
00293 void bgui_graph_tableau::draw_multi_graph()
00294 {
00295
00296 float r[7]={1,0,0,1,0,1,1};
00297 float g[7]={0,1,0,0,1,1,1};
00298 float b[7]={0,0,1,1,1,0,1};
00299 if (n_ == 0)
00300 return;
00301 if (m_plot_.size())
00302 {
00303 for (unsigned i =0; i<m_plot_.size(); ++i)
00304 easy_->remove(m_plot_[i]);
00305 m_plot_.clear();
00306 tt_->clear();
00307 }
00308 for (unsigned p = 0; p<n_plots_; ++p)
00309 {
00310 vcl_vector<float> x(n_), y(n_);
00311 for (unsigned i = 0; i<n_; ++i)
00312 {
00313 x[i]=map_x_to_display(static_cast<float>(mpos_[p][i]));
00314 y[i]=map_y_to_display(static_cast<float>(mvals_[p][i]));
00315 }
00316 unsigned c = p%7;
00317 easy_->set_foreground(r[c], g[c], b[c]);
00318 vgui_soview2D_linestrip* ls = easy_->add_linestrip(n_, &x[0], &y[0]);
00319 ls->set_selectable(false);
00320 m_plot_.push_back(ls);
00321 }
00322 draw_tics();
00323 this->post_redraw();
00324 }
00325
00326
00327 void bgui_graph_tableau::rem()
00328 {
00329 if (plot_)
00330 {
00331 easy_->remove(plot_);
00332
00333 plot_ = 0;
00334 }
00335 for (vcl_vector<vgui_soview2D_lineseg*>::iterator cit = xtics_.begin();
00336 cit!=xtics_.end(); ++cit)
00337 if (*cit)
00338 {
00339 easy_->remove(*cit);
00340
00341 }
00342 for (vcl_vector<vgui_soview2D_lineseg*>::iterator cit = ytics_.begin();
00343 cit!=ytics_.end(); ++cit)
00344 if (*cit)
00345 {
00346 easy_->remove(*cit);
00347
00348 }
00349 for (unsigned i = 0; i< m_plot_.size(); ++i)
00350 easy_->remove(m_plot_[i]);
00351 m_plot_.clear();
00352 }
00353
00354
00355 void bgui_graph_tableau::del()
00356 {
00357 if (pos_)
00358 {
00359 delete [] pos_;
00360 pos_ =0;
00361 }
00362 if (vals_)
00363 {
00364 delete [] vals_;
00365 vals_ = 0;
00366 }
00367 }
00368
00369
00370 void bgui_graph_tableau::clear()
00371 {
00372 this->rem();
00373 this->del();
00374 this->post_redraw();
00375 }
00376
00377
00378
00379 vgui_dialog* bgui_graph_tableau::popup_graph(vcl_string const& info,
00380 const unsigned sizex,
00381 const unsigned sizey)
00382 {
00383 unsigned w = graph_width_+25, h = graph_height_+25;
00384 if (sizex>0)
00385 w = sizex;
00386 if (sizey>0)
00387 h = sizey;
00388 vgui_viewer2D_tableau_sptr v = vgui_viewer2D_tableau_new(this);
00389 vgui_shell_tableau_sptr s = vgui_shell_tableau_new(v);
00390 vcl_string temp = info;
00391 vcl_stringstream xinc, yinc, ymin, ymax;
00392 xinc << xinc_; yinc << yinc_; ymin << ymin_; ymax<< ymax_;
00393 #if 0
00394 temp += " xinc:" + xinc.str();
00395 temp += " yinc:" + yinc.str();
00396 #endif
00397 temp += " ymin:" + ymin.str();
00398 temp += " ymax:" + ymax.str();
00399 vgui_dialog* d = new vgui_dialog(temp.c_str());
00400 d->inline_tableau(s, w, h);
00401 return d;
00402 }
00403
00404
00405
00406 bool bgui_graph_tableau::handle(const vgui_event& event)
00407 {
00408
00409 if (event.type == vgui_DRAW)
00410 {
00411 vcl_cout << "Graph Handle\n";
00412 easy_->handle(event);
00413 tt_->handle(event);
00414 }
00415 return false;
00416 }
00417