pcl_plotter.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2010-2011, Willow Garage, Inc.
00006  *  Copyright (c) 2012-, Open Perception, Inc.
00007  *
00008  *  All rights reserved.
00009  *
00010  *  Redistribution and use in source and binary forms, with or without
00011  *  modification, are permitted provided that the following conditions
00012  *  are met:
00013  *
00014  *   * Redistributions of source code must retain the above copyright
00015  *     notice, this list of conditions and the following disclaimer.
00016  *   * Redistributions in binary form must reproduce the above
00017  *     copyright notice, this list of conditions and the following
00018  *     disclaimer in the documentation and/or other materials provided
00019  *     with the distribution.
00020  *   * Neither the name of the copyright holder(s) nor the names of its
00021  *     contributors may be used to endorse or promote products derived
00022  *     from this software without specific prior written permission.
00023  *
00024  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00027  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00028  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00029  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00030  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00031  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00032  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00033  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00034  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00035  *  POSSIBILITY OF SUCH DAMAGE.
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   //constructing
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   //connecting and mandatory bookkeeping
00073   view_->GetScene ()->AddItem (chart_);
00074   view_->GetRenderWindow ()->SetWindowName (name);
00075   
00076   //###WARNING: hardcoding logic ;) :-/.. please see plot() and spin*() functions for the logic
00077   exit_loop_timer_->interactor = view_->GetInteractor ();
00078   exit_callback_->plotter = this;
00079   
00080   //initializing default state values
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 /* = "Y Axis" */, 
00096     int type, char const* color)
00097 {
00098   //updating the current plot ID
00099   current_plot_++;
00100   
00101   //creating a permanent copy of the arrays
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   //transforming data to be fed to the vtkChartXY
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   //adding to chart
00121   //vtkPlot *line = chart_->AddPlot(vtkChart::LINE);
00122   vtkPlot *line = chart_->AddPlot (type);
00123   line->SetInput (table, 0, 1);
00124   line->SetWidth (1);
00125 
00126   if (color == NULL)    //color automatically based on the ColorScheme
00127   {
00128     vtkColor3ub vcolor = color_series_->GetColorRepeating (current_plot_);
00129     line->SetColor (vcolor[0], vcolor[1], vcolor[2], 255);
00130   }
00131   else                  //add the specific color
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 /* = "Y Axis" */, 
00141     int type /* = vtkChart::LINE */, 
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 /* = "Y Axis" */, 
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     //if (yval == DBL_MAX) continue; //handling dived by zero 
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   //getting the no of column
00247   string line;
00248   getline (fin, line);
00249   stringstream ss(line);
00250   
00251   vector<string> pnames;       //plot names
00252   string xname, temp;         //plot name of X axis
00253   
00254   //checking X axis name
00255   ss >> xname;
00256   //getting Y axis names
00257   while (ss >> temp)
00258     pnames.push_back(temp);
00259     
00260   int nop = int (pnames.size ());// number of plots (y coordinate vectors)  
00261   
00262   vector<double> xarray;      //array of X coordinates
00263   vector< vector<double> > yarrays (nop); //a set of array of Y coordinates
00264   
00265   //reading the entire table
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   //adding nop plot data
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   // Get the field
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   // Parse the cloud data and store it in the array
00314   for (int i = 0; i < hsize; ++i)
00315   {
00316     array_x[i] = i;
00317     float data;
00318     // TODO: replace float with the real data type
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   // Get the field
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   // Compute the total size of the fields
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   // Parse the cloud data and store it in the array
00359   for (int i = 0; i < hsize; ++i)
00360   {
00361     array_x[i] = i;
00362     float data;
00363     // TODO: replace float with the real data type
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   //apply current states
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   //apply current states
00408   view_->GetRenderer ()->SetBackground (bkg_color_[0], bkg_color_[1], bkg_color_[2]);
00409   view_->GetRenderWindow ()->SetSize (win_width_, win_height_);
00410   
00411   //start timer to spin
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   // Start spinning
00421   view_->GetRenderWindow ()->Render ();
00422         view_->GetInteractor()->Start();
00423 }
00424 
00426 void 
00427 pcl::visualization::PCLPlotter::renderOnce ()
00428 {
00429   //apply current states
00430   view_->GetRenderer ()->SetBackground (bkg_color_[0], bkg_color_[1], bkg_color_[2]);
00431   view_->GetRenderWindow ()->SetSize (win_width_, win_height_);
00432   
00433   //render
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   //resizing the vector to nbins to store histogram;
00563   histogram.resize (nbins);
00564 
00565   //find min and max in the data
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   //finding the size of each bins
00574   double size = (max - min) / nbins;
00575 
00576   //fill x values of each bins by bin center
00577   for (int i = 0; i < nbins; i++)
00578   {
00579     histogram[i].first = min + (size * i) + size / 2; //size/2 for the middle of the bins
00580     histogram[i].second = 0; //initializing the freq to zero
00581   }
00582 
00583   //fill the freq for each data
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; //including right boundary
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   //if (dres == 0) return DBL_MAX;  //return the max possible double value to represent infinity
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   // This tends to close the window...
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   // Stop vtk loop and send notification to app to wake it up
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 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:28:09