00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <vtkSmartPointer.h>
00040 #include <vtkRenderWindowInteractor.h>
00041 #include <vtkRenderWindow.h>
00042 #include <vtkRenderer.h>
00043 #include <vtkContextView.h>
00044 #include <vtkChartXY.h>
00045 #include <vtkColorSeries.h>
00046 #include <vtkContextScene.h>
00047 #include <vtkAxis.h>
00048 #include <vtkPlot.h>
00049 #include <vtkDoubleArray.h>
00050 #include <vtkTable.h>
00051
00052 #include <fstream>
00053 #include <sstream>
00054
00055 #include <pcl/visualization/interactor.h>
00056 #include <pcl/visualization/pcl_plotter.h>
00057 #include <pcl/common/common_headers.h>
00058
00059 #define VTK_CREATE(type, name) \
00060 vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
00061
00063 pcl::visualization::PCLPlotter::PCLPlotter (char const *name)
00064 {
00065
00066 view_ = vtkSmartPointer<vtkContextView>::New ();
00067 chart_=vtkSmartPointer<vtkChartXY>::New();
00068 color_series_ = vtkSmartPointer<vtkColorSeries>::New ();
00069 exit_loop_timer_ = vtkSmartPointer<ExitMainLoopTimerCallback>::New ();
00070 exit_callback_ = vtkSmartPointer<ExitCallback>::New ();
00071
00072
00073 view_->GetScene ()->AddItem (chart_);
00074 view_->GetRenderWindow ()->SetWindowName (name);
00075
00076
00077 exit_loop_timer_->interactor = view_->GetInteractor ();
00078 exit_callback_->plotter = this;
00079
00080
00081 win_width_ = 640;
00082 win_height_ = 480;
00083 bkg_color_[0] = 1; bkg_color_[1] = 1; bkg_color_[2] = 1;
00084 current_plot_ = -1;
00085 color_series_->SetColorScheme (vtkColorSeries::SPECTRUM);
00086 }
00087
00089 pcl::visualization::PCLPlotter::~PCLPlotter() {}
00090
00092 void
00093 pcl::visualization::PCLPlotter::addPlotData (
00094 double const* array_X, double const* array_Y,
00095 unsigned long size, char const * name ,
00096 int type, char const* color)
00097 {
00098
00099 current_plot_++;
00100
00101
00102 double *permanent_X = new double[size];
00103 double *permanent_Y = new double[size];
00104 memcpy(permanent_X, array_X, size*sizeof(double));
00105 memcpy(permanent_Y, array_Y, size*sizeof(double));
00106
00107
00108 VTK_CREATE (vtkTable, table);
00109
00110 VTK_CREATE (vtkDoubleArray, varray_X);
00111 varray_X->SetName ("X Axis");
00112 varray_X->SetArray (permanent_X, size, 1);
00113 table->AddColumn (varray_X);
00114
00115 VTK_CREATE (vtkDoubleArray, varray_Y);
00116 varray_Y->SetName (name);
00117 varray_Y->SetArray (permanent_Y, size, 1);
00118 table->AddColumn (varray_Y);
00119
00120
00121
00122 vtkPlot *line = chart_->AddPlot (type);
00123 line->SetInput (table, 0, 1);
00124 line->SetWidth (1);
00125
00126 if (color == NULL)
00127 {
00128 vtkColor3ub vcolor = color_series_->GetColorRepeating (current_plot_);
00129 line->SetColor (vcolor[0], vcolor[1], vcolor[2], 255);
00130 }
00131 else
00132 line->SetColor (color[0], color[1], color[2], color[3]);
00133 }
00134
00136 void
00137 pcl::visualization::PCLPlotter::addPlotData (
00138 std::vector<double> const &array_X,
00139 std::vector<double> const &array_Y,
00140 char const * name ,
00141 int type ,
00142 std::vector<char> const &color)
00143 {
00144 this->addPlotData (&array_X[0], &array_Y[0], static_cast<unsigned long> (array_X.size ()), name, type, (color.size () == 0) ? NULL : &color[0]);
00145 }
00146
00148 void
00149 pcl::visualization::PCLPlotter::addPlotData (
00150 std::vector<std::pair<double, double> > const &plot_data,
00151 char const * name ,
00152 int type,
00153 std::vector<char> const &color)
00154 {
00155 double *array_x = new double[plot_data.size ()];
00156 double *array_y = new double[plot_data.size ()];
00157
00158 for (unsigned int i = 0; i < plot_data.size (); i++)
00159 {
00160 array_x[i] = plot_data[i].first;
00161 array_y[i] = plot_data[i].second;
00162 }
00163 this->addPlotData (array_x, array_y, static_cast<unsigned long> (plot_data.size ()), name, type, (color.size () == 0) ? NULL : &color[0]);
00164 }
00165
00167 void
00168 pcl::visualization::PCLPlotter::addPlotData (
00169 PolynomialFunction const & p_function,
00170 double x_min, double x_max,
00171 char const *name,
00172 int num_points,
00173 int type,
00174 std::vector<char> const &color)
00175 {
00176 std::vector<double> array_x (num_points), array_y (num_points);
00177 double incr = (x_max - x_min)/num_points;
00178
00179 for (int i = 0; i < num_points; i++)
00180 {
00181 double xval = i*incr + x_min;
00182 array_x[i] = xval;
00183 array_y[i] = compute(p_function, xval);
00184 }
00185
00186 this->addPlotData (array_x, array_y, name, type, color);
00187 }
00188
00190 void
00191 pcl::visualization::PCLPlotter::addPlotData (
00192 RationalFunction const & r_function,
00193 double x_min, double x_max,
00194 char const *name,
00195 int num_points,
00196 int type,
00197 std::vector<char> const &color)
00198 {
00199 std::vector<double> array_x(num_points), array_y(num_points);
00200 double incr = (x_max - x_min)/num_points;
00201
00202 for (int i = 0; i < num_points; i++)
00203 {
00204 double xval = i*incr + x_min;
00205 double yval = compute(r_function, xval);
00206
00207
00208 array_x[i] = xval;
00209 array_y[i] = yval;
00210 }
00211
00212 this->addPlotData (array_x, array_y, name, type, color);
00213 }
00214
00216 void
00217 pcl::visualization::PCLPlotter::addPlotData (
00218 double (*function)(double),
00219 double x_min, double x_max,
00220 char const *name,
00221 int num_points,
00222 int type,
00223 std::vector<char> const &color)
00224 {
00225 std::vector<double> array_x(num_points), array_y(num_points);
00226 double incr = (x_max - x_min)/num_points;
00227
00228 for (int i = 0; i < num_points; i++)
00229 {
00230 double xval = i*incr + x_min;
00231 array_x[i] = xval;
00232 array_y[i] = function(xval);
00233 }
00234
00235 this->addPlotData (array_x, array_y, name, type, color);
00236 }
00237
00238 void
00239 pcl::visualization::PCLPlotter::addPlotData (
00240 char const *filename,
00241 int type)
00242 {
00243 using namespace std;
00244 ifstream fin(filename);
00245
00246
00247 string line;
00248 getline (fin, line);
00249 stringstream ss(line);
00250
00251 vector<string> pnames;
00252 string xname, temp;
00253
00254
00255 ss >> xname;
00256
00257 while (ss >> temp)
00258 pnames.push_back(temp);
00259
00260 int nop = int (pnames.size ());
00261
00262 vector<double> xarray;
00263 vector< vector<double> > yarrays (nop);
00264
00265
00266 double x, y;
00267 while (fin >> x)
00268 {
00269 xarray.push_back(x);
00270
00271 for (int i = 0; i < nop; i++)
00272 {
00273 fin >> y;
00274 yarrays[i].push_back (y);
00275 }
00276 }
00277
00278
00279 for (int i = 0; i < nop; i++)
00280 this->addPlotData (xarray, yarrays[i], pnames[i].c_str(), type);
00281 }
00282
00284 void
00285 pcl::visualization::PCLPlotter::addHistogramData (
00286 std::vector<double> const& data,
00287 int const nbins,
00288 char const *name,
00289 std::vector<char> const &color)
00290 {
00291 std::vector<std::pair<double, double> > histogram;
00292 computeHistogram (data, nbins, histogram);
00293 this->addPlotData (histogram, name, vtkChart::BAR, color);
00294 }
00295
00297 bool
00298 pcl::visualization::PCLPlotter::addFeatureHistogram (
00299 const pcl::PCLPointCloud2 &cloud, const std::string &field_name,
00300 const std::string &id, int win_width, int win_height)
00301 {
00302
00303 int field_idx = pcl::getFieldIndex (cloud, field_name);
00304 if (field_idx == -1)
00305 {
00306 PCL_ERROR ("[addFeatureHistogram] Invalid field (%s) given!", field_name.c_str ());
00307 return (false);
00308 }
00309
00310 int hsize = cloud.fields[field_idx].count;
00311 std::vector<double> array_x (hsize), array_y (hsize);
00312
00313
00314 for (int i = 0; i < hsize; ++i)
00315 {
00316 array_x[i] = i;
00317 float data;
00318
00319 memcpy (&data, &cloud.data[cloud.fields[field_idx].offset + i * sizeof (float)], sizeof (float));
00320 array_y[i] = data;
00321 }
00322
00323 this->addPlotData(array_x, array_y, id.c_str(), vtkChart::LINE);
00324 setWindowSize (win_width, win_height);
00325 return (true);
00326 }
00327
00329 bool
00330 pcl::visualization::PCLPlotter::addFeatureHistogram (
00331 const pcl::PCLPointCloud2 &cloud,
00332 const std::string &field_name,
00333 const int index,
00334 const std::string &id, int win_width, int win_height)
00335 {
00336 if (index < 0 || index >= static_cast<int> (cloud.width * cloud.height))
00337 {
00338 PCL_ERROR ("[addFeatureHistogram] Invalid point index (%d) given!\n", index);
00339 return (false);
00340 }
00341
00342
00343 int field_idx = pcl::getFieldIndex (cloud, field_name);
00344 if (field_idx == -1)
00345 {
00346 PCL_ERROR ("[addFeatureHistogram] Invalid field (%s) given!", field_name.c_str ());
00347 return (false);
00348 }
00349
00350
00351 unsigned int fsize = 0;
00352 for (size_t i = 0; i < cloud.fields.size (); ++i)
00353 fsize += cloud.fields[i].count * pcl::getFieldSize (cloud.fields[i].datatype);
00354
00355 int hsize = cloud.fields[field_idx].count;
00356 std::vector<double> array_x (hsize), array_y (hsize);
00357
00358
00359 for (int i = 0; i < hsize; ++i)
00360 {
00361 array_x[i] = i;
00362 float data;
00363
00364 memcpy (&data, &cloud.data[index * fsize + cloud.fields[field_idx].offset + i * sizeof (float)], sizeof (float));
00365 array_y[i] = data;
00366 }
00367
00368 this->addPlotData (array_x, array_y, id.c_str(), vtkChart::LINE);
00369 setWindowSize (win_width, win_height);
00370 return (true);
00371 }
00372
00374
00375
00377 void
00378 pcl::visualization::PCLPlotter::setColorScheme (int scheme)
00379 {
00380 color_series_->SetColorScheme (scheme);
00381 }
00382
00384 int
00385 pcl::visualization::PCLPlotter::getColorScheme ()
00386 {
00387 return (color_series_->GetColorScheme ());
00388 }
00389
00391 void
00392 pcl::visualization::PCLPlotter::plot ()
00393 {
00394
00395 view_->GetRenderer ()->SetBackground (bkg_color_[0], bkg_color_[1], bkg_color_[2]);
00396 view_->GetRenderWindow ()->SetSize (win_width_, win_height_);
00397
00398 view_->GetInteractor ()->Initialize ();
00399 view_->GetRenderWindow ()->Render();
00400 view_->GetInteractor ()->Start ();
00401 }
00402
00404 void
00405 pcl::visualization::PCLPlotter::spinOnce (const int spin_time)
00406 {
00407
00408 view_->GetRenderer ()->SetBackground (bkg_color_[0], bkg_color_[1], bkg_color_[2]);
00409 view_->GetRenderWindow ()->SetSize (win_width_, win_height_);
00410
00411
00412 if (!view_->GetInteractor ()->GetEnabled ())
00413 {
00414 view_->GetInteractor ()->Initialize ();
00415 view_->GetInteractor ()->AddObserver (vtkCommand::TimerEvent, exit_loop_timer_);
00416 view_->GetInteractor ()->AddObserver (vtkCommand::ExitEvent, exit_callback_);
00417 }
00418 exit_loop_timer_->right_timer_id = view_->GetInteractor()->CreateOneShotTimer (spin_time);
00419
00420
00421 view_->GetRenderWindow ()->Render ();
00422 view_->GetInteractor()->Start();
00423 }
00424
00426 void
00427 pcl::visualization::PCLPlotter::renderOnce ()
00428 {
00429
00430 view_->GetRenderer ()->SetBackground (bkg_color_[0], bkg_color_[1], bkg_color_[2]);
00431 view_->GetRenderWindow ()->SetSize (win_width_, win_height_);
00432
00433
00434 view_->GetInteractor ()->Initialize ();
00435 view_->GetRenderWindow ()->Render();
00436 }
00437
00439 void
00440 pcl::visualization::PCLPlotter::spin ()
00441 {
00442 this->plot ();
00443 }
00444
00446 void
00447 pcl::visualization::PCLPlotter::clearPlots ()
00448 {
00449 chart_->ClearPlots ();
00450 current_plot_ = 0;
00451 }
00452
00454 void
00455 pcl::visualization::PCLPlotter::setBackgroundColor (const double r, const double g, const double b)
00456 {
00457 bkg_color_[0] = r;
00458 bkg_color_[1] = g;
00459 bkg_color_[2] = b;
00460 }
00461
00463 void
00464 pcl::visualization::PCLPlotter::setBackgroundColor (const double color[3])
00465 {
00466 bkg_color_[0] = color[0];
00467 bkg_color_[1] = color[1];
00468 bkg_color_[2] = color[2];
00469 }
00470
00472 double*
00473 pcl::visualization::PCLPlotter::getBackgroundColor ()
00474 {
00475 double *bc = new double[3];
00476 bc[0] = bkg_color_[0];
00477 bc[1] = bkg_color_[1];
00478 bc[2] = bkg_color_[2];
00479 return (bc);
00480 }
00481
00483 void
00484 pcl::visualization::PCLPlotter::setYRange (double min, double max)
00485 {
00486 chart_->GetAxis (vtkAxis::LEFT)->SetRange (min, max);
00487 chart_->GetAxis (vtkAxis::LEFT)->SetBehavior (vtkAxis::FIXED);
00488 }
00489
00491 void
00492 pcl::visualization::PCLPlotter::setXRange (double min, double max)
00493 {
00494 chart_->GetAxis (vtkAxis::BOTTOM)->SetRange (min, max);
00495 chart_->GetAxis (vtkAxis::BOTTOM)->SetBehavior (vtkAxis::FIXED);
00496 }
00497
00499 void
00500 pcl::visualization::PCLPlotter::setTitle (const char *title)
00501 {
00502 chart_->SetTitle (title);
00503 chart_->SetShowLegend (true);
00504 }
00505
00507 void
00508 pcl::visualization::PCLPlotter::setXTitle (const char *title)
00509 {
00510 chart_->GetAxis (vtkAxis::BOTTOM)->SetTitle (title);
00511 chart_->SetShowLegend (true);
00512 }
00513
00515 void
00516 pcl::visualization::PCLPlotter::setYTitle (const char *title)
00517 {
00518 chart_->GetAxis (vtkAxis::LEFT)->SetTitle (title);
00519 chart_->SetShowLegend (true);
00520 }
00521
00523 void
00524 pcl::visualization::PCLPlotter::setShowLegend (bool flag)
00525 {
00526 chart_->SetShowLegend (flag);
00527 }
00528
00530 void
00531 pcl::visualization::PCLPlotter::setWindowSize (int w, int h)
00532 {
00533 win_width_ = w;
00534 win_height_ = h;
00535 }
00536
00538 int*
00539 pcl::visualization::PCLPlotter::getWindowSize ()
00540 {
00541 int *sz = new int[2];
00542 sz[0] = win_width_;
00543 sz[1] = win_height_;
00544 return (sz);
00545 }
00546
00548 void
00549 pcl::visualization::PCLPlotter::startInteractor ()
00550 {
00551 view_->GetInteractor()->Initialize ();
00552 view_->GetInteractor()->Start ();
00553 }
00554
00556 void
00557 pcl::visualization::PCLPlotter::computeHistogram (
00558 std::vector<double> const &data,
00559 int const nbins,
00560 std::vector<std::pair<double, double> > &histogram)
00561 {
00562
00563 histogram.resize (nbins);
00564
00565
00566 double min = data[0], max = data[0];
00567 for (int i = 1; i < data.size (); i++)
00568 {
00569 if (data[i] < min) min = data[i];
00570 if (data[i] > max) max = data[i];
00571 }
00572
00573
00574 double size = (max - min) / nbins;
00575
00576
00577 for (int i = 0; i < nbins; i++)
00578 {
00579 histogram[i].first = min + (size * i) + size / 2;
00580 histogram[i].second = 0;
00581 }
00582
00583
00584 for (int i = 0; i < data.size (); i++)
00585 {
00586 int index = int (floor ((data[i] - min) / size));
00587 if (index == nbins) index = nbins - 1;
00588 histogram[index ].second++;
00589 }
00590 }
00591
00593 double
00594 pcl::visualization::PCLPlotter::compute (
00595 pcl::visualization::PCLPlotter::PolynomialFunction const & p_function,
00596 double val)
00597 {
00598 double res = 0;
00599 for (size_t i = 0; i < p_function.size (); i++)
00600 res += (p_function[i] * pow (val, static_cast<double> (i)) );
00601 return (res);
00602 }
00603
00605 double
00606 pcl::visualization::PCLPlotter::compute (RationalFunction const & r_function, double val)
00607 {
00608 PolynomialFunction numerator = r_function.first, denominator = r_function.second;
00609
00610 double dres = this->compute (denominator,val);
00611
00612 double nres = this->compute (numerator,val);
00613 return (nres/dres);
00614 }
00615
00617 void
00618 pcl::visualization::PCLPlotter::setViewInteractor (
00619 vtkSmartPointer<vtkRenderWindowInteractor> interactor)
00620 {
00621 view_->SetInteractor (interactor);
00622 }
00623
00625 bool
00626 pcl::visualization::PCLPlotter::wasStopped () const
00627 {
00628 if (view_->GetInteractor() != NULL)
00629 return (stopped_);
00630 else
00631 return (true);
00632 }
00633
00635 void
00636 pcl::visualization::PCLPlotter::close ()
00637 {
00638 stopped_ = true;
00639
00640 view_->GetInteractor()->TerminateApp ();
00641 }
00642
00644 vtkSmartPointer<vtkRenderWindow>
00645 pcl::visualization::PCLPlotter::getRenderWindow ()
00646 {
00647 return (view_->GetRenderWindow ());
00648 }
00649
00651 void
00652 pcl::visualization::PCLPlotter::ExitMainLoopTimerCallback::Execute (
00653 vtkObject*, unsigned long event_id, void* call_data)
00654 {
00655 if (event_id != vtkCommand::TimerEvent)
00656 return;
00657 int timer_id = *(reinterpret_cast<int*> (call_data));
00658
00659 if (timer_id != right_timer_id)
00660 return;
00661
00662
00663 #if ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION <= 4))
00664 interactor->stopLoop ();
00665 #else
00666 interactor->TerminateApp ();
00667 #endif
00668 }
00669
00671 void
00672 pcl::visualization::PCLPlotter::ExitCallback::Execute (
00673 vtkObject*, unsigned long event_id, void*)
00674 {
00675 if (event_id != vtkCommand::ExitEvent)
00676 return;
00677 plotter->stopped_ = true;
00678 plotter->view_->GetInteractor ()->TerminateApp ();
00679 }