Point Cloud Library (PCL)  1.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
point_cloud_handlers.hpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage, Inc. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  * $Id: point_cloud_handlers.hpp 4702 2012-02-23 09:39:33Z gedikli $
00035  *
00036  */
00037 
00038 #include <pcl/console/time.h>
00039 #include <pcl/pcl_macros.h>
00040 
00042 template <typename PointT> void
00043 pcl::visualization::PointCloudColorHandlerCustom<PointT>::getColor (vtkSmartPointer<vtkDataArray> &scalars) const
00044 {
00045   if (!capable_)
00046     return;
00047 
00048   if (!scalars)
00049     scalars = vtkSmartPointer<vtkUnsignedCharArray>::New ();
00050   scalars->SetNumberOfComponents (3);
00051   
00052   vtkIdType nr_points = cloud_->points.size ();
00053   reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->SetNumberOfTuples (nr_points);
00054 
00055   // Get a random color
00056   unsigned char* colors = new unsigned char[nr_points * 3];
00057 
00058   // Color every point
00059   for (vtkIdType cp = 0; cp < nr_points; ++cp)
00060   {
00061     colors[cp * 3 + 0] = r_;
00062     colors[cp * 3 + 1] = g_;
00063     colors[cp * 3 + 2] = b_;
00064   }
00065   reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->SetArray (colors, 3 * nr_points, 0);
00066 }
00067 
00069 template <typename PointT> void
00070 pcl::visualization::PointCloudColorHandlerRandom<PointT>::getColor (vtkSmartPointer<vtkDataArray> &scalars) const
00071 {
00072   if (!capable_)
00073     return;
00074 
00075   if (!scalars)
00076     scalars = vtkSmartPointer<vtkUnsignedCharArray>::New ();
00077   scalars->SetNumberOfComponents (3);
00078   
00079   vtkIdType nr_points = cloud_->points.size ();
00080   reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->SetNumberOfTuples (nr_points);
00081 
00082   // Get a random color
00083   unsigned char* colors = new unsigned char[nr_points * 3];
00084   double r, g, b;
00085   pcl::visualization::getRandomColors (r, g, b);
00086 
00087   int r_ = pcl_lrint (r * 255.0), g_ = pcl_lrint (g * 255.0), b_ = pcl_lrint (b * 255.0);
00088 
00089   // Color every point
00090   for (vtkIdType cp = 0; cp < nr_points; ++cp)
00091   {
00092     colors[cp * 3 + 0] = r_;
00093     colors[cp * 3 + 1] = g_;
00094     colors[cp * 3 + 2] = b_;
00095   }
00096   reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->SetArray (colors, 3 * nr_points, 0);
00097 }
00098 
00100 template <typename PointT>
00101 pcl::visualization::PointCloudColorHandlerRGBField<PointT>::PointCloudColorHandlerRGBField (const PointCloudConstPtr &cloud) : 
00102   pcl::visualization::PointCloudColorHandler<PointT>::PointCloudColorHandler (cloud)
00103 {
00104   // Handle the 24-bit packed RGB values
00105   field_idx_ = pcl::getFieldIndex (*cloud, "rgb", fields_);
00106   if (field_idx_ != -1)
00107   {
00108     capable_ = true;
00109     return;
00110   }
00111   else
00112   {
00113     field_idx_ = pcl::getFieldIndex (*cloud, "rgba", fields_);
00114     if (field_idx_ != -1)
00115       capable_ = true;
00116     else
00117       capable_ = false;
00118   }
00119 }
00120 
00122 template <typename PointT> void 
00123 pcl::visualization::PointCloudColorHandlerRGBField<PointT>::getColor (vtkSmartPointer<vtkDataArray> &scalars) const
00124 {
00125   if (!capable_)
00126     return;
00127 
00128   if (!scalars)
00129     scalars = vtkSmartPointer<vtkUnsignedCharArray>::New ();
00130   scalars->SetNumberOfComponents (3);
00131 
00132   vtkIdType nr_points = cloud_->points.size ();
00133   reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->SetNumberOfTuples (nr_points);
00134   unsigned char* colors = reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->GetPointer (0);
00135 
00136   int j = 0;
00137   // If XYZ present, check if the points are invalid
00138   int x_idx = -1;
00139   for (size_t d = 0; d < fields_.size (); ++d)
00140     if (fields_[d].name == "x")
00141       x_idx = (int) d;
00142 
00143   if (x_idx != -1)
00144   {
00145     // Color every point
00146     for (vtkIdType cp = 0; cp < nr_points; ++cp)
00147     {
00148       // Copy the value at the specified field
00149       if (!pcl_isfinite (cloud_->points[cp].x) ||
00150           !pcl_isfinite (cloud_->points[cp].y) || 
00151           !pcl_isfinite (cloud_->points[cp].z))
00152         continue;
00153 
00154       int idx = j * 3;
00155       colors[idx    ] = cloud_->points[cp].r;
00156       colors[idx + 1] = cloud_->points[cp].g;
00157       colors[idx + 2] = cloud_->points[cp].b;
00158       j++;
00159     }
00160   }
00161   else
00162   {
00163     // Color every point
00164     for (vtkIdType cp = 0; cp < nr_points; ++cp)
00165     {
00166       int idx = cp * 3;
00167       colors[idx    ] = cloud_->points[cp].r;
00168       colors[idx + 1] = cloud_->points[cp].g;
00169       colors[idx + 2] = cloud_->points[cp].b;
00170     }
00171   }
00172 }
00173 
00175 template <typename PointT>
00176 pcl::visualization::PointCloudColorHandlerHSVField<PointT>::PointCloudColorHandlerHSVField (const PointCloudConstPtr &cloud) : 
00177   pcl::visualization::PointCloudColorHandler<PointT>::PointCloudColorHandler (cloud)
00178 {
00179   // Check for the presence of the "H" field
00180   field_idx_ = pcl::getFieldIndex (*cloud, "h", fields_);
00181   if (field_idx_ == -1)
00182   {
00183     capable_ = false;
00184     return;
00185   }
00186 
00187   // Check for the presence of the "S" field
00188   s_field_idx_ = pcl::getFieldIndex (*cloud, "s", fields_);
00189   if (s_field_idx_ == -1)
00190   {
00191     capable_ = false;
00192     return;
00193   }
00194 
00195   // Check for the presence of the "V" field
00196   v_field_idx_ = pcl::getFieldIndex (*cloud, "v", fields_);
00197   if (v_field_idx_ == -1)
00198   {
00199     capable_ = false;
00200     return;
00201   }
00202   capable_ = true;
00203 }
00204 
00206 template <typename PointT> void 
00207 pcl::visualization::PointCloudColorHandlerHSVField<PointT>::getColor (vtkSmartPointer<vtkDataArray> &scalars) const
00208 {
00209   if (!capable_)
00210     return;
00211 
00212   if (!scalars)
00213     scalars = vtkSmartPointer<vtkUnsignedCharArray>::New ();
00214   scalars->SetNumberOfComponents (3);
00215 
00216   vtkIdType nr_points = cloud_->points.size ();
00217   reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->SetNumberOfTuples (nr_points);
00218   unsigned char* colors = reinterpret_cast<vtkUnsignedCharArray*>(&(*scalars))->GetPointer (0);
00219 
00220   int j = 0;
00221   // If XYZ present, check if the points are invalid
00222   int x_idx = -1;
00223   
00224   for (size_t d = 0; d < fields_.size (); ++d)
00225     if (fields_[d].name == "x")
00226       x_idx = (int) d;
00227 
00228   if (x_idx != -1)
00229   {
00230     // Color every point
00231     for (vtkIdType cp = 0; cp < nr_points; ++cp)
00232     {
00233       // Copy the value at the specified field
00234       if (!pcl_isfinite (cloud_->points[cp].x) ||
00235           !pcl_isfinite (cloud_->points[cp].y) || 
00236           !pcl_isfinite (cloud_->points[cp].z))
00237         continue;
00238 
00239       int idx = j * 3;
00240 
00242 
00243       // Fill color data with HSV here:
00244       if (cloud_->points[cp].s == 0)
00245       {
00246         colors[idx] = colors[idx+1] = colors[idx+2] = cloud_->points[cp].v;
00247         return;
00248       } 
00249       float a = cloud_->points[cp].h / 60;
00250       int   i = floor (a);
00251       float f = a - i;
00252       float p = cloud_->points[cp].v * (1 - cloud_->points[cp].s);
00253       float q = cloud_->points[cp].v * (1 - cloud_->points[cp].s * f);
00254       float t = cloud_->points[cp].v * (1 - cloud_->points[cp].s * (1 - f));
00255 
00256       switch (i) 
00257       {
00258         case 0:
00259           colors[idx] = cloud_->points[cp].v; colors[idx+1] = t; colors[idx+2] = p; break;
00260         case 1:
00261           colors[idx] = q; colors[idx+1] = cloud_->points[cp].v; colors[idx+2] = p; break;
00262         case 2:
00263           colors[idx] = p; colors[idx+1] = cloud_->points[cp].v; colors[idx+2] = t; break;
00264         case 3:
00265           colors[idx] = p; colors[idx+1] = q; colors[idx+2] = cloud_->points[cp].v; break;
00266         case 4:
00267           colors[idx] = t; colors[idx+1] = p; colors[idx+2] = cloud_->points[cp].v; break;
00268         default:
00269           colors[idx] = cloud_->points[cp].v; colors[idx+1] = p; colors[idx+2] = q; break;
00270       }
00271       j++;
00272     }
00273   }
00274   else
00275   {
00276     // Color every point
00277     for (vtkIdType cp = 0; cp < nr_points; ++cp)
00278     {
00279       int idx = cp * 3;
00280 
00281       // Fill color data with HSV here:
00282       if (cloud_->points[cp].s == 0)
00283       {
00284         colors[idx] = colors[idx+1] = colors[idx+2] = cloud_->points[cp].v;
00285         return;
00286       } 
00287       float a = cloud_->points[cp].h / 60;
00288       int   i = floor (a);
00289       float f = a - i;
00290       float p = cloud_->points[cp].v * (1 - cloud_->points[cp].s);
00291       float q = cloud_->points[cp].v * (1 - cloud_->points[cp].s * f);
00292       float t = cloud_->points[cp].v * (1 - cloud_->points[cp].s * (1 - f));
00293 
00294       switch (i) 
00295       {
00296         case 0:
00297           colors[idx] = cloud_->points[cp].v; colors[idx+1] = t; colors[idx+2] = p; break;
00298         case 1:
00299           colors[idx] = q; colors[idx+1] = cloud_->points[cp].v; colors[idx+2] = p; break;
00300         case 2:
00301           colors[idx] = p; colors[idx+1] = cloud_->points[cp].v; colors[idx+2] = t; break;
00302         case 3:
00303           colors[idx] = p; colors[idx+1] = q; colors[idx+2] = cloud_->points[cp].v; break;
00304         case 4:
00305           colors[idx] = t; colors[idx+1] = p; colors[idx+2] = cloud_->points[cp].v; break;
00306         default:
00307           colors[idx] = cloud_->points[cp].v; colors[idx+1] = p; colors[idx+2] = q; break;
00308       }
00309     }
00310   }
00311 }
00312 
00314 template <typename PointT>
00315 pcl::visualization::PointCloudColorHandlerGenericField<PointT>::PointCloudColorHandlerGenericField (const PointCloudConstPtr &cloud, 
00316     const std::string &field_name) : pcl::visualization::PointCloudColorHandler<PointT>::PointCloudColorHandler (cloud)
00317 {
00318   field_name_ = field_name;
00319   field_idx_  = pcl::getFieldIndex (*cloud, field_name, fields_);
00320   if (field_idx_ != -1)
00321     capable_ = true;
00322   else
00323     capable_ = false;
00324 }
00325 
00327 template <typename PointT> void 
00328 pcl::visualization::PointCloudColorHandlerGenericField<PointT>::getColor (vtkSmartPointer<vtkDataArray> &scalars) const
00329 {
00330   if (!capable_)
00331     return;
00332 
00333   if (!scalars)
00334     scalars = vtkSmartPointer<vtkFloatArray>::New ();
00335   scalars->SetNumberOfComponents (1);
00336 
00337   vtkIdType nr_points = cloud_->points.size ();
00338   reinterpret_cast<vtkFloatArray*>(&(*scalars))->SetNumberOfTuples (nr_points);
00339 
00340   typedef typename pcl::traits::fieldList<PointT>::type FieldList;
00341 
00342   float* colors = new float[nr_points];
00343   float field_data;
00344 
00345   int j = 0;
00346   // If XYZ present, check if the points are invalid
00347   int x_idx = -1;
00348   for (size_t d = 0; d < fields_.size (); ++d)
00349     if (fields_[d].name == "x")
00350       x_idx = d;
00351 
00352   if (x_idx != -1)
00353   {
00354     // Color every point
00355     for (vtkIdType cp = 0; cp < nr_points; ++cp)
00356     {
00357       // Copy the value at the specified field
00358       if (!pcl_isfinite (cloud_->points[cp].x) || !pcl_isfinite (cloud_->points[cp].y) || !pcl_isfinite (cloud_->points[cp].z))
00359         continue;
00360 
00361       uint8_t* pt_data = (uint8_t*)&cloud_->points[cp];
00362       memcpy (&field_data, pt_data + fields_[field_idx_].offset, pcl::getFieldSize (fields_[field_idx_].datatype));
00363 
00364       colors[j] = field_data;
00365       j++;
00366     }
00367   }
00368   else
00369   {
00370     // Color every point
00371     for (vtkIdType cp = 0; cp < nr_points; ++cp)
00372     {
00373       uint8_t* pt_data = (uint8_t*)&cloud_->points[cp];
00374       memcpy (&field_data, pt_data + fields_[field_idx_].offset, pcl::getFieldSize (fields_[field_idx_].datatype));
00375 
00376       if (!pcl_isfinite (field_data))
00377         continue;
00378 
00379       colors[j] = field_data;
00380       j++;
00381     }
00382   }
00383   reinterpret_cast<vtkFloatArray*>(&(*scalars))->SetArray (colors, j, 0);
00384 }
00385 
00387 template <typename PointT>
00388 pcl::visualization::PointCloudGeometryHandlerXYZ<PointT>::PointCloudGeometryHandlerXYZ (const PointCloudConstPtr &cloud) 
00389   : pcl::visualization::PointCloudGeometryHandler<PointT>::PointCloudGeometryHandler (cloud)
00390 {
00391   field_x_idx_ = pcl::getFieldIndex (*cloud, "x", fields_);
00392   if (field_x_idx_ == -1)
00393     return;
00394   field_y_idx_ = pcl::getFieldIndex (*cloud, "y", fields_);
00395   if (field_y_idx_ == -1)
00396     return;
00397   field_z_idx_ = pcl::getFieldIndex (*cloud, "z", fields_);
00398   if (field_z_idx_ == -1)
00399     return;
00400   capable_ = true;
00401 }
00402 
00404 template <typename PointT> void 
00405 pcl::visualization::PointCloudGeometryHandlerXYZ<PointT>::getGeometry (vtkSmartPointer<vtkPoints> &points) const
00406 {
00407   if (!capable_)
00408     return;
00409 
00410   if (!points)
00411     points = vtkSmartPointer<vtkPoints>::New ();
00412   points->SetDataTypeToFloat ();
00413 
00414   vtkSmartPointer<vtkFloatArray> data = vtkSmartPointer<vtkFloatArray>::New ();
00415   data->SetNumberOfComponents (3);
00416   vtkIdType nr_points = cloud_->points.size ();
00417 
00418   // Add all points
00419   vtkIdType j = 0;    // true point index
00420   float* pts = new float[nr_points * 3];
00421 
00422   // If the dataset has no invalid values, just copy all of them
00423   if (cloud_->is_dense)
00424   {
00425     for (vtkIdType i = 0; i < nr_points; ++i)
00426     {
00427       pts[i * 3 + 0] = cloud_->points[i].x;
00428       pts[i * 3 + 1] = cloud_->points[i].y;
00429       pts[i * 3 + 2] = cloud_->points[i].z;
00430     }
00431     data->SetArray (&pts[0], nr_points * 3, 0);
00432     points->SetData (data);
00433   }
00434   // Need to check for NaNs, Infs, ec
00435   else
00436   {
00437     for (vtkIdType i = 0; i < nr_points; ++i)
00438     {
00439       // Check if the point is invalid
00440       if (!pcl_isfinite (cloud_->points[i].x) || !pcl_isfinite (cloud_->points[i].y) || !pcl_isfinite (cloud_->points[i].z))
00441         continue;
00442 
00443       pts[j * 3 + 0] = cloud_->points[i].x;
00444       pts[j * 3 + 1] = cloud_->points[i].y;
00445       pts[j * 3 + 2] = cloud_->points[i].z;
00446       // Set j and increment
00447       j++;
00448     }
00449     data->SetArray (&pts[0], j * 3, 0);
00450     points->SetData (data);
00451   }
00452 }
00453 
00455 template <typename PointT>
00456 pcl::visualization::PointCloudGeometryHandlerSurfaceNormal<PointT>::PointCloudGeometryHandlerSurfaceNormal (const PointCloudConstPtr &cloud) 
00457   : pcl::visualization::PointCloudGeometryHandler<PointT>::PointCloudGeometryHandler (cloud)
00458 {
00459   field_x_idx_ = pcl::getFieldIndex (*cloud, "normal_x", fields_);
00460   if (field_x_idx_ == -1)
00461     return;
00462   field_y_idx_ = pcl::getFieldIndex (*cloud, "normal_y", fields_);
00463   if (field_y_idx_ == -1)
00464     return;
00465   field_z_idx_ = pcl::getFieldIndex (*cloud, "normal_z", fields_);
00466   if (field_z_idx_ == -1)
00467     return;
00468   capable_ = true;
00469 }
00470 
00472 template <typename PointT> void 
00473 pcl::visualization::PointCloudGeometryHandlerSurfaceNormal<PointT>::getGeometry (vtkSmartPointer<vtkPoints> &points) const
00474 {
00475   if (!capable_)
00476     return;
00477 
00478   if (!points)
00479     points = vtkSmartPointer<vtkPoints>::New ();
00480   points->SetDataTypeToFloat ();
00481   points->SetNumberOfPoints (cloud_->points.size ());
00482 
00483   // Add all points
00484   double p[3];
00485   for (vtkIdType i = 0; i < (int)cloud_->points.size (); ++i)
00486   {
00487     p[0] = cloud_->points[i].normal[0];
00488     p[1] = cloud_->points[i].normal[1];
00489     p[2] = cloud_->points[i].normal[2];
00490 
00491     points->SetPoint (i, p);
00492   }
00493 }
00494 
00496 template <typename PointT>
00497 pcl::visualization::PointCloudGeometryHandlerCustom<PointT>::PointCloudGeometryHandlerCustom (const PointCloudConstPtr &cloud,
00498     const std::string &x_field_name, const std::string &y_field_name, const std::string &z_field_name) : pcl::visualization::PointCloudGeometryHandler<PointT>::PointCloudGeometryHandler (cloud)
00499 {
00500   field_x_idx_ = pcl::getFieldIndex (*cloud, x_field_name, fields_);
00501   if (field_x_idx_ == -1)
00502     return;
00503   field_y_idx_ = pcl::getFieldIndex (*cloud, y_field_name, fields_);
00504   if (field_y_idx_ == -1)
00505     return;
00506   field_z_idx_ = pcl::getFieldIndex (*cloud, z_field_name, fields_);
00507   if (field_z_idx_ == -1)
00508     return;
00509   field_name_ = x_field_name + y_field_name + z_field_name;
00510   capable_ = true;
00511 }
00512 
00514 template <typename PointT> void 
00515 pcl::visualization::PointCloudGeometryHandlerCustom<PointT>::getGeometry (vtkSmartPointer<vtkPoints> &points) const
00516 {
00517   if (!capable_)
00518     return;
00519 
00520   if (!points)
00521     points = vtkSmartPointer<vtkPoints>::New ();
00522   points->SetDataTypeToFloat ();
00523   points->SetNumberOfPoints (cloud_->points.size ());
00524 
00525   float data;
00526   // Add all points
00527   double p[3];
00528   for (vtkIdType i = 0; i < (int)cloud_->points.size (); ++i)
00529   {
00530     // Copy the value at the specified field
00531     uint8_t* pt_data = (uint8_t*)&cloud_->points[i];
00532     memcpy (&data, pt_data + fields_[field_x_idx_].offset, sizeof (float));
00533     p[0] = data;
00534 
00535     memcpy (&data, pt_data + fields_[field_y_idx_].offset, sizeof (float));
00536     p[1] = data;
00537 
00538     memcpy (&data, pt_data + fields_[field_z_idx_].offset, sizeof (float));
00539     p[2] = data;
00540 
00541     points->SetPoint (i, p);
00542   }
00543 }
00544