Point Cloud Library (PCL)  1.4.0
 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 3771 2012-01-01 06:58:14Z rusu $
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, sizeof (float));
00363       memcpy (&field_data, pt_data + fields_[field_idx_].offset, pcl::getFieldSize (fields_[field_idx_].datatype));
00364 
00365       if (!pcl_isfinite (field_data))
00366         continue;
00367 
00368       colors[j] = field_data;
00369       j++;
00370     }
00371   }
00372   else
00373   {
00374     // Color every point
00375     for (vtkIdType cp = 0; cp < nr_points; ++cp)
00376     {
00377       uint8_t* pt_data = (uint8_t*)&cloud_->points[cp];
00378       //memcpy (&field_data, pt_data + fields_[field_idx_].offset, sizeof (float));
00379       memcpy (&field_data, pt_data + fields_[field_idx_].offset, pcl::getFieldSize (fields_[field_idx_].datatype));
00380 
00381       if (!pcl_isfinite (field_data))
00382         continue;
00383 
00384       colors[j] = field_data;
00385       j++;
00386     }
00387   }
00388   reinterpret_cast<vtkFloatArray*>(&(*scalars))->SetArray (colors, j, 0);
00389 }
00390 
00392 template <typename PointT>
00393 pcl::visualization::PointCloudGeometryHandlerXYZ<PointT>::PointCloudGeometryHandlerXYZ (const PointCloudConstPtr &cloud) 
00394   : pcl::visualization::PointCloudGeometryHandler<PointT>::PointCloudGeometryHandler (cloud)
00395 {
00396   field_x_idx_ = pcl::getFieldIndex (*cloud, "x", fields_);
00397   if (field_x_idx_ == -1)
00398     return;
00399   field_y_idx_ = pcl::getFieldIndex (*cloud, "y", fields_);
00400   if (field_y_idx_ == -1)
00401     return;
00402   field_z_idx_ = pcl::getFieldIndex (*cloud, "z", fields_);
00403   if (field_z_idx_ == -1)
00404     return;
00405   capable_ = true;
00406 }
00407 
00409 template <typename PointT> void 
00410 pcl::visualization::PointCloudGeometryHandlerXYZ<PointT>::getGeometry (vtkSmartPointer<vtkPoints> &points) const
00411 {
00412   if (!capable_)
00413     return;
00414 
00415   if (!points)
00416     points = vtkSmartPointer<vtkPoints>::New ();
00417   points->SetDataTypeToFloat ();
00418 
00419   vtkSmartPointer<vtkFloatArray> data = vtkSmartPointer<vtkFloatArray>::New ();
00420   data->SetNumberOfComponents (3);
00421   vtkIdType nr_points = cloud_->points.size ();
00422 
00423   // Add all points
00424   vtkIdType j = 0;    // true point index
00425   float* pts = new float[nr_points * 3];
00426 
00427   // If the dataset has no invalid values, just copy all of them
00428   if (cloud_->is_dense)
00429   {
00430     for (vtkIdType i = 0; i < nr_points; ++i)
00431     {
00432       pts[i * 3 + 0] = cloud_->points[i].x;
00433       pts[i * 3 + 1] = cloud_->points[i].y;
00434       pts[i * 3 + 2] = cloud_->points[i].z;
00435     }
00436     data->SetArray (&pts[0], nr_points * 3, 0);
00437     points->SetData (data);
00438   }
00439   // Need to check for NaNs, Infs, ec
00440   else
00441   {
00442     for (vtkIdType i = 0; i < nr_points; ++i)
00443     {
00444       // Check if the point is invalid
00445       if (!pcl_isfinite (cloud_->points[i].x) || !pcl_isfinite (cloud_->points[i].y) || !pcl_isfinite (cloud_->points[i].z))
00446         continue;
00447 
00448       pts[j * 3 + 0] = cloud_->points[i].x;
00449       pts[j * 3 + 1] = cloud_->points[i].y;
00450       pts[j * 3 + 2] = cloud_->points[i].z;
00451       // Set j and increment
00452       j++;
00453     }
00454     data->SetArray (&pts[0], j * 3, 0);
00455     points->SetData (data);
00456   }
00457 }
00458 
00460 template <typename PointT>
00461 pcl::visualization::PointCloudGeometryHandlerSurfaceNormal<PointT>::PointCloudGeometryHandlerSurfaceNormal (const PointCloudConstPtr &cloud) 
00462   : pcl::visualization::PointCloudGeometryHandler<PointT>::PointCloudGeometryHandler (cloud)
00463 {
00464   field_x_idx_ = pcl::getFieldIndex (*cloud, "normal_x", fields_);
00465   if (field_x_idx_ == -1)
00466     return;
00467   field_y_idx_ = pcl::getFieldIndex (*cloud, "normal_y", fields_);
00468   if (field_y_idx_ == -1)
00469     return;
00470   field_z_idx_ = pcl::getFieldIndex (*cloud, "normal_z", fields_);
00471   if (field_z_idx_ == -1)
00472     return;
00473   capable_ = true;
00474 }
00475 
00477 template <typename PointT> void 
00478 pcl::visualization::PointCloudGeometryHandlerSurfaceNormal<PointT>::getGeometry (vtkSmartPointer<vtkPoints> &points) const
00479 {
00480   if (!capable_)
00481     return;
00482 
00483   if (!points)
00484     points = vtkSmartPointer<vtkPoints>::New ();
00485   points->SetDataTypeToFloat ();
00486   points->SetNumberOfPoints (cloud_->points.size ());
00487 
00488   // Add all points
00489   double p[3];
00490   for (vtkIdType i = 0; i < (int)cloud_->points.size (); ++i)
00491   {
00492     p[0] = cloud_->points[i].normal[0];
00493     p[1] = cloud_->points[i].normal[1];
00494     p[2] = cloud_->points[i].normal[2];
00495 
00496     points->SetPoint (i, p);
00497   }
00498 }
00499 
00501 template <typename PointT>
00502 pcl::visualization::PointCloudGeometryHandlerCustom<PointT>::PointCloudGeometryHandlerCustom (const PointCloudConstPtr &cloud,
00503     const std::string &x_field_name, const std::string &y_field_name, const std::string &z_field_name) : pcl::visualization::PointCloudGeometryHandler<PointT>::PointCloudGeometryHandler (cloud)
00504 {
00505   field_x_idx_ = pcl::getFieldIndex (*cloud, x_field_name, fields_);
00506   if (field_x_idx_ == -1)
00507     return;
00508   field_y_idx_ = pcl::getFieldIndex (*cloud, y_field_name, fields_);
00509   if (field_y_idx_ == -1)
00510     return;
00511   field_z_idx_ = pcl::getFieldIndex (*cloud, z_field_name, fields_);
00512   if (field_z_idx_ == -1)
00513     return;
00514   field_name_ = x_field_name + y_field_name + z_field_name;
00515   capable_ = true;
00516 }
00517 
00519 template <typename PointT> void 
00520 pcl::visualization::PointCloudGeometryHandlerCustom<PointT>::getGeometry (vtkSmartPointer<vtkPoints> &points) const
00521 {
00522   if (!capable_)
00523     return;
00524 
00525   if (!points)
00526     points = vtkSmartPointer<vtkPoints>::New ();
00527   points->SetDataTypeToFloat ();
00528   points->SetNumberOfPoints (cloud_->points.size ());
00529 
00530   float data;
00531   // Add all points
00532   double p[3];
00533   for (vtkIdType i = 0; i < (int)cloud_->points.size (); ++i)
00534   {
00535     // Copy the value at the specified field
00536     uint8_t* pt_data = (uint8_t*)&cloud_->points[i];
00537     memcpy (&data, pt_data + fields_[field_x_idx_].offset, sizeof (float));
00538     p[0] = data;
00539 
00540     memcpy (&data, pt_data + fields_[field_y_idx_].offset, sizeof (float));
00541     p[1] = data;
00542 
00543     memcpy (&data, pt_data + fields_[field_z_idx_].offset, sizeof (float));
00544     p[2] = data;
00545 
00546     points->SetPoint (i, p);
00547   }
00548 }
00549 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines