Point Cloud Library (PCL)  1.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
pcl_visualizer.hpp
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  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Willow Garage, Inc. nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  * $Id: pcl_visualizer.hpp 4702 2012-02-23 09:39:33Z gedikli $
00037  *
00038  */
00039 
00040 #ifndef PCL_PCL_VISUALIZER_IMPL_H_
00041 #define PCL_PCL_VISUALIZER_IMPL_H_
00042 
00043 #include <vtkCellData.h>
00044 #include <vtkSmartPointer.h>
00045 #include <vtkCellArray.h>
00046 #include <vtkProperty2D.h>
00047 #include <vtkMapper2D.h>
00048 #include <vtkLeaderActor2D.h>
00049 #include <pcl/common/time.h>
00050 
00052 template <typename PointT> bool
00053 pcl::visualization::PCLVisualizer::addPointCloud (
00054     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00055     const std::string &id, int viewport)
00056 {
00057   // Convert the PointCloud to VTK PolyData
00058   PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
00059   return (addPointCloud<PointT> (cloud, geometry_handler, id, viewport));
00060 }
00061 
00063 template <typename PointT> bool
00064 pcl::visualization::PCLVisualizer::addPointCloud (
00065     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00066     const PointCloudGeometryHandler<PointT> &geometry_handler,
00067     const std::string &id, int viewport)
00068 {
00069   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00070   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
00071 
00072   if (am_it != cloud_actor_map_->end ())
00073   {
00074     PCL_WARN ("[addPointCloud] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
00075     return (false);
00076   }
00077 
00078   //PointCloudColorHandlerRandom<PointT> color_handler (cloud);
00079   PointCloudColorHandlerCustom<PointT> color_handler (cloud, 255, 255, 255);
00080   return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
00081 }
00082 
00084 template <typename PointT> bool
00085 pcl::visualization::PCLVisualizer::addPointCloud (
00086     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00087     const GeometryHandlerConstPtr &geometry_handler,
00088     const std::string &id, int viewport)
00089 {
00090   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00091   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
00092 
00093   if (am_it != cloud_actor_map_->end ())
00094   {
00095     // Here we're just pushing the handlers onto the queue. If needed, something fancier could
00096     // be done such as checking if a specific handler already exists, etc.
00097     am_it->second.geometry_handlers.push_back (geometry_handler);
00098     return (true);
00099   }
00100 
00101   //PointCloudColorHandlerRandom<PointT> color_handler (cloud);
00102   PointCloudColorHandlerCustom<PointT> color_handler (cloud, 255, 255, 255);
00103   return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
00104 }
00105 
00107 template <typename PointT> bool
00108 pcl::visualization::PCLVisualizer::addPointCloud (
00109     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00110     const PointCloudColorHandler<PointT> &color_handler,
00111     const std::string &id, int viewport)
00112 {
00113   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00114   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
00115 
00116   if (am_it != cloud_actor_map_->end ())
00117   {
00118     PCL_WARN ("[addPointCloud] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
00119 
00120     // Here we're just pushing the handlers onto the queue. If needed, something fancier could
00121     // be done such as checking if a specific handler already exists, etc.
00122     //cloud_actor_map_[id].color_handlers.push_back (color_handler);
00123     //style_->setCloudActorMap (boost::make_shared<CloudActorMap> (cloud_actor_map_));
00124     return (false);
00125   }
00126   // Convert the PointCloud to VTK PolyData
00127   PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
00128   return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
00129 }
00130 
00132 template <typename PointT> bool
00133 pcl::visualization::PCLVisualizer::addPointCloud (
00134     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00135     const ColorHandlerConstPtr &color_handler,
00136     const std::string &id, int viewport)
00137 {
00138   // Check to see if this entry already exists (has it been already added to the visualizer?)
00139   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
00140   if (am_it != cloud_actor_map_->end ())
00141   {
00142     // Here we're just pushing the handlers onto the queue. If needed, something fancier could
00143     // be done such as checking if a specific handler already exists, etc.
00144     am_it->second.color_handlers.push_back (color_handler);
00145     return (true);
00146   }
00147 
00148   PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
00149   return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
00150 }
00151 
00153 template <typename PointT> bool
00154 pcl::visualization::PCLVisualizer::addPointCloud (
00155     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00156     const GeometryHandlerConstPtr &geometry_handler,
00157     const ColorHandlerConstPtr &color_handler,
00158     const std::string &id, int viewport)
00159 {
00160   // Check to see if this entry already exists (has it been already added to the visualizer?)
00161   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
00162   if (am_it != cloud_actor_map_->end ())
00163   {
00164     // Here we're just pushing the handlers onto the queue. If needed, something fancier could
00165     // be done such as checking if a specific handler already exists, etc.
00166     am_it->second.geometry_handlers.push_back (geometry_handler);
00167     am_it->second.color_handlers.push_back (color_handler);
00168     return (true);
00169   }
00170   return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
00171 }
00172 
00174 template <typename PointT> bool
00175 pcl::visualization::PCLVisualizer::addPointCloud (
00176     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00177     const PointCloudColorHandler<PointT> &color_handler,
00178     const PointCloudGeometryHandler<PointT> &geometry_handler,
00179     const std::string &id, int viewport)
00180 {
00181   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00182   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
00183 
00184   if (am_it != cloud_actor_map_->end ())
00185   {
00186     PCL_WARN ("[addPointCloud] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
00187     // Here we're just pushing the handlers onto the queue. If needed, something fancier could
00188     // be done such as checking if a specific handler already exists, etc.
00189     //cloud_actor_map_[id].geometry_handlers.push_back (geometry_handler);
00190     //cloud_actor_map_[id].color_handlers.push_back (color_handler);
00191     //style_->setCloudActorMap (boost::make_shared<CloudActorMap> (cloud_actor_map_));
00192     return (false);
00193   }
00194   return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
00195 }
00196 
00198 template <typename PointT> void
00199 pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData (
00200     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00201     vtkSmartPointer<vtkPolyData> &polydata,
00202     vtkSmartPointer<vtkIdTypeArray> &initcells)
00203 {
00204   vtkSmartPointer<vtkCellArray> vertices;
00205   if (!polydata)
00206   {
00207     allocVtkPolyData (polydata);
00208     vertices = vtkSmartPointer<vtkCellArray>::New ();
00209     polydata->SetVerts (vertices);
00210   }
00211 
00212   // Create the supporting structures
00213   vertices = polydata->GetVerts ();
00214   if (!vertices)
00215     vertices = vtkSmartPointer<vtkCellArray>::New ();
00216 
00217   vtkIdType nr_points = cloud->points.size ();
00218   // Create the point set
00219   vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
00220   if (!points)
00221   {
00222     points = vtkSmartPointer<vtkPoints>::New ();
00223     points->SetDataTypeToFloat ();
00224     polydata->SetPoints (points);
00225   }
00226   points->SetNumberOfPoints (nr_points);
00227 
00228   // Get a pointer to the beginning of the data array
00229   float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
00230 
00231   // Set the points
00232   if (cloud->is_dense)
00233   {
00234     for (vtkIdType i = 0; i < nr_points; ++i)
00235       memcpy (&data[i * 3], &cloud->points[i].x, 12);    // sizeof (float) * 3
00236   }
00237   else
00238   {
00239     vtkIdType j = 0;    // true point index
00240     for (vtkIdType i = 0; i < nr_points; ++i)
00241     {
00242       // Check if the point is invalid
00243       if (!pcl_isfinite (cloud->points[i].x) ||
00244           !pcl_isfinite (cloud->points[i].y) ||
00245           !pcl_isfinite (cloud->points[i].z))
00246         continue;
00247 
00248       memcpy (&data[j * 3], &cloud->points[i].x, 12);    // sizeof (float) * 3
00249       j++;
00250     }
00251     nr_points = j;
00252     points->SetNumberOfPoints (nr_points);
00253   }
00254 
00255   vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
00256   updateCells (cells, initcells, nr_points);
00257 
00258   // Set the cells and the vertices
00259   vertices->SetCells (nr_points, cells);
00260 }
00261 
00263 template <typename PointT> void
00264 pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData (
00265     const pcl::visualization::PointCloudGeometryHandler<PointT> &geometry_handler,
00266     vtkSmartPointer<vtkPolyData> &polydata,
00267     vtkSmartPointer<vtkIdTypeArray> &initcells)
00268 {
00269   vtkSmartPointer<vtkCellArray> vertices;
00270   if (!polydata)
00271   {
00272     allocVtkPolyData (polydata);
00273     vertices = vtkSmartPointer<vtkCellArray>::New ();
00274     polydata->SetVerts (vertices);
00275   }
00276 
00277   // Use the handler to obtain the geometry
00278   vtkSmartPointer<vtkPoints> points;
00279   geometry_handler.getGeometry (points);
00280   polydata->SetPoints (points);
00281 
00282   vtkIdType nr_points = points->GetNumberOfPoints ();
00283 
00284   // Create the supporting structures
00285   vertices = polydata->GetVerts ();
00286   if (!vertices)
00287     vertices = vtkSmartPointer<vtkCellArray>::New ();
00288 
00289   vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
00290   updateCells (cells, initcells, nr_points);
00291   // Set the cells and the vertices
00292   vertices->SetCells (nr_points, cells);
00293 }
00294 
00296 template <typename PointT> bool
00297 pcl::visualization::PCLVisualizer::addPolygon (
00298     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00299     double r, double g, double b, const std::string &id, int viewport)
00300 {
00301   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00302   ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
00303   if (am_it != shape_actor_map_->end ())
00304   {
00305     PCL_WARN ("[addPolygon] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
00306     return (false);
00307   }
00308 
00309   vtkSmartPointer<vtkDataSet> data = createPolygon<PointT> (cloud);
00310 
00311   // Create an Actor
00312   vtkSmartPointer<vtkLODActor> actor;
00313   createActorFromVTKDataSet (data, actor);
00314   actor->GetProperty ()->SetRepresentationToWireframe ();
00315   actor->GetProperty ()->SetColor (r, g, b);
00316   actor->GetMapper ()->ScalarVisibilityOff ();
00317   addActorToRenderer (actor, viewport);
00318 
00319   // Save the pointer/ID pair to the global actor map
00320   (*shape_actor_map_)[id] = actor;
00321   return (true);
00322 }
00323 
00325 template <typename PointT> bool
00326 pcl::visualization::PCLVisualizer::addPolygon (
00327     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00328     const std::string &id, int viewport)
00329 {
00330   return (!addPolygon<PointT> (cloud, 0.5, 0.5, 0.5, id, viewport));
00331     return (false);
00332 }
00333 
00335 template <typename P1, typename P2> bool
00336 pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
00337 {
00338   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00339   ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
00340   if (am_it != shape_actor_map_->end ())
00341   {
00342     PCL_WARN ("[addLine] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
00343     return (false);
00344   }
00345 
00346   vtkSmartPointer<vtkDataSet> data = createLine (pt1.getVector4fMap (), pt2.getVector4fMap ());
00347 
00348   // Create an Actor
00349   vtkSmartPointer<vtkLODActor> actor;
00350   createActorFromVTKDataSet (data, actor);
00351   actor->GetProperty ()->SetRepresentationToWireframe ();
00352   actor->GetProperty ()->SetColor (r, g, b);
00353   actor->GetMapper ()->ScalarVisibilityOff ();
00354   addActorToRenderer (actor, viewport);
00355 
00356   // Save the pointer/ID pair to the global actor map
00357   (*shape_actor_map_)[id] = actor;
00358   return (true);
00359 }
00360 
00362 template <typename P1, typename P2> bool
00363 pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
00364 {
00365   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00366   ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
00367   if (am_it != shape_actor_map_->end ())
00368   {
00369     PCL_WARN ("[addArrow] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
00370     return (false);
00371   }
00372 
00373   // Create an Actor
00374   vtkSmartPointer<vtkLeaderActor2D> leader = vtkSmartPointer<vtkLeaderActor2D>::New ();
00375   leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
00376   leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
00377   leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
00378   leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
00379   leader->SetArrowStyleToFilled ();
00380   leader->AutoLabelOn ();
00381 
00382   leader->GetProperty ()->SetColor (r, g, b);
00383   addActorToRenderer (leader, viewport);
00384 
00385   // Save the pointer/ID pair to the global actor map
00386   (*shape_actor_map_)[id] = leader;
00387   return (true);
00388 }
00389 
00391 template <typename P1, typename P2> bool
00392 pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, const std::string &id, int viewport)
00393 {
00394   return (!addLine (pt1, pt2, 0.5, 0.5, 0.5, id, viewport));
00395 }
00396 
00398 /*template <typename P1, typename P2> bool
00399   pcl::visualization::PCLVisualizer::addLineToGroup (const P1 &pt1, const P2 &pt2, const std::string &group_id, int viewport)
00400 {
00401   vtkSmartPointer<vtkDataSet> data = createLine<P1, P2> (pt1, pt2);
00402 
00403   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00404   ShapeActorMap::iterator am_it = shape_actor_map_->find (group_id);
00405   if (am_it != shape_actor_map_->end ())
00406   {
00407     // Get the old data
00408     vtkPolyDataMapper* mapper = static_cast<vtkPolyDataMapper*>(am_it->second->GetMapper ());
00409     vtkPolyData* olddata = static_cast<vtkPolyData*>(mapper->GetInput ());
00410     // Add it to the current data
00411     vtkSmartPointer<vtkAppendPolyData> alldata = vtkSmartPointer<vtkAppendPolyData>::New ();
00412     alldata->AddInput (olddata);
00413 
00414     // Convert to vtkPolyData
00415     vtkSmartPointer<vtkPolyData> curdata = (vtkPolyData::SafeDownCast (data));
00416     alldata->AddInput (curdata);
00417 
00418     mapper->SetInput (alldata->GetOutput ());
00419 
00420     am_it->second->SetMapper (mapper);
00421     am_it->second->Modified ();
00422     return (true);
00423   }
00424 
00425   // Create an Actor
00426   vtkSmartPointer<vtkLODActor> actor;
00427   createActorFromVTKDataSet (data, actor);
00428   actor->GetProperty ()->SetRepresentationToWireframe ();
00429   actor->GetProperty ()->SetColor (1, 0, 0);
00430   addActorToRenderer (actor, viewport);
00431 
00432   // Save the pointer/ID pair to the global actor map
00433   (*shape_actor_map_)[group_id] = actor;
00434 
00435 //ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
00436 //vtkSmartPointer<vtkLODActor> actor = am_it->second;
00437   //actor->GetProperty ()->SetColor (r, g, b);
00438 //actor->Modified ();
00439   return (true);
00440 }*/
00441 
00443 template <typename PointT> bool
00444 pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, double r, double g, double b, const std::string &id, int viewport)
00445 {
00446   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00447   ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
00448   if (am_it != shape_actor_map_->end ())
00449   {
00450     PCL_WARN ("[addSphere] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
00451     return (false);
00452   }
00453 
00454   vtkSmartPointer<vtkDataSet> data = createSphere (center.getVector4fMap (), radius);
00455 
00456   // Create an Actor
00457   vtkSmartPointer<vtkLODActor> actor;
00458   createActorFromVTKDataSet (data, actor);
00459   actor->GetProperty ()->SetRepresentationToWireframe ();
00460   actor->GetProperty ()->SetInterpolationToGouraud ();
00461   actor->GetMapper ()->ScalarVisibilityOff ();
00462   actor->GetProperty ()->SetColor (r, g, b);
00463   addActorToRenderer (actor, viewport);
00464 
00465   // Save the pointer/ID pair to the global actor map
00466   (*shape_actor_map_)[id] = actor;
00467   return (true);
00468 }
00469 
00471 template <typename PointT> bool
00472 pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, const std::string &id, int viewport)
00473 {
00474   return (addSphere (center, radius, 0.5, 0.5, 0.5, id, viewport));
00475 }
00476 
00478 template <typename PointT> bool
00479 pcl::visualization::PCLVisualizer::addText3D (
00480     const std::string &text,
00481     const PointT& position,
00482     double textScale,
00483     double r,
00484     double g,
00485     double b,
00486     const std::string &id,
00487     int viewport)
00488 {
00489   std::string tid;
00490   if (id.empty ())
00491     tid = text;
00492   else
00493     tid = id;
00494 
00495   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00496   ShapeActorMap::iterator am_it = shape_actor_map_->find (tid);
00497   if (am_it != shape_actor_map_->end ())
00498   {
00499     pcl::console::print_warn ("[addText3d] A text with id <%s> already exists! Please choose a different id and retry.\n", tid.c_str ());
00500     return (false);
00501   }
00502 
00503   vtkSmartPointer<vtkVectorText> textSource = vtkSmartPointer<vtkVectorText>::New ();
00504   textSource->SetText (text.c_str());
00505   textSource->Update ();
00506 
00507   vtkSmartPointer<vtkPolyDataMapper> textMapper = vtkSmartPointer<vtkPolyDataMapper>::New ();
00508   textMapper->SetInputConnection (textSource->GetOutputPort ());
00509 
00510   // Since each follower may follow a different camera, we need different followers
00511   rens_->InitTraversal ();
00512   vtkRenderer* renderer = NULL;
00513   int i = 1;
00514   while ((renderer = rens_->GetNextItem ()) != NULL)
00515   {
00516     // Should we add the actor to all renderers or just to i-nth renderer?
00517     if (viewport == 0 || viewport == i)
00518     {
00519       vtkSmartPointer<vtkFollower> textActor = vtkSmartPointer<vtkFollower>::New ();
00520       textActor->SetMapper (textMapper);
00521       textActor->SetPosition (position.x, position.y, position.z);
00522       textActor->SetScale (textScale);
00523       textActor->GetProperty ()->SetColor (r, g, b);
00524       textActor->SetCamera (renderer->GetActiveCamera ());
00525 
00526       renderer->AddActor (textActor);
00527       renderer->Render ();
00528 
00529       // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
00530       // for multiple viewport
00531       std::string alternate_tid = tid;
00532       alternate_tid.append(i, '*');
00533 
00534       (*shape_actor_map_)[(viewport == 0) ? tid : alternate_tid] = textActor;
00535     }
00536 
00537     ++i;
00538   }
00539 
00540   return (true);
00541 }
00542 
00544 template <typename PointNT> bool
00545 pcl::visualization::PCLVisualizer::addPointCloudNormals (
00546     const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
00547     int level, double scale, const std::string &id, int viewport)
00548 {
00549   return (addPointCloudNormals<PointNT, PointNT>(cloud, cloud, level, scale, id, viewport));
00550 }
00551 
00553 template <typename PointT, typename PointNT> bool
00554 pcl::visualization::PCLVisualizer::addPointCloudNormals (
00555     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00556     const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
00557     int level, double scale,
00558     const std::string &id, int viewport)
00559 {
00560   if (normals->points.size () != cloud->points.size ())
00561   {
00562     PCL_ERROR ("[addPointCloudNormals] The number of points differs from the number of normals!\n");
00563     return (false);
00564   }
00565   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00566   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
00567 
00568   if (am_it != cloud_actor_map_->end ())
00569   {
00570     PCL_WARN ("[addPointCloudNormals] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
00571     return (false);
00572   }
00573 
00574   vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
00575   vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
00576 
00577   points->SetDataTypeToFloat ();
00578   vtkSmartPointer<vtkFloatArray> data = vtkSmartPointer<vtkFloatArray>::New ();
00579   data->SetNumberOfComponents (3);
00580 
00581   vtkIdType nr_normals = (cloud->points.size () - 1) / level + 1 ;
00582   float* pts = new float[2 * nr_normals * 3];
00583 
00584   for (vtkIdType i = 0, j = 0; j < nr_normals; j++, i = j * level)
00585   {
00586     PointT p = cloud->points[i];
00587     p.x += normals->points[i].normal[0] * scale;
00588     p.y += normals->points[i].normal[1] * scale;
00589     p.z += normals->points[i].normal[2] * scale;
00590 
00591     pts[2 * j * 3 + 0] = cloud->points[i].x;
00592     pts[2 * j * 3 + 1] = cloud->points[i].y;
00593     pts[2 * j * 3 + 2] = cloud->points[i].z;
00594     pts[2 * j * 3 + 3] = p.x;
00595     pts[2 * j * 3 + 4] = p.y;
00596     pts[2 * j * 3 + 5] = p.z;
00597 
00598     lines->InsertNextCell(2);
00599     lines->InsertCellPoint(2*j);
00600     lines->InsertCellPoint(2*j+1);
00601   }
00602 
00603   data->SetArray (&pts[0], 2 * nr_normals * 3, 0);
00604   points->SetData (data);
00605 
00606   vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
00607   polyData->SetPoints(points);
00608   polyData->SetLines(lines);
00609 
00610   vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New ();
00611   mapper->SetInput (polyData);
00612   mapper->SetColorModeToMapScalars();
00613   mapper->SetScalarModeToUsePointData();
00614 
00615   // create actor
00616   vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New ();
00617   actor->SetMapper (mapper);
00618 
00619   // Add it to all renderers
00620   addActorToRenderer (actor, viewport);
00621 
00622   // Save the pointer/ID pair to the global actor map
00623   (*cloud_actor_map_)[id].actor = actor;
00624   return (true);
00625 }
00626 
00628 template <typename PointT> bool
00629 pcl::visualization::PCLVisualizer::addCorrespondences (
00630    const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
00631    const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
00632    const std::vector<int> &correspondences,
00633    const std::string &id,
00634    int viewport)
00635 {
00636   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00637   ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
00638   if (am_it != shape_actor_map_->end ())
00639   {
00640     PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
00641     return (false);
00642   }
00643 
00644   vtkSmartPointer<vtkAppendPolyData> polydata = vtkSmartPointer<vtkAppendPolyData>::New ();
00645 
00646   vtkSmartPointer<vtkUnsignedCharArray> line_colors = vtkSmartPointer<vtkUnsignedCharArray>::New ();
00647   line_colors->SetNumberOfComponents (3);
00648   line_colors->SetName ("Colors");
00649   // Use Red by default (can be changed later)
00650   unsigned char rgb[3];
00651   rgb[0] = 1 * 255.0;
00652   rgb[1] = 0 * 255.0;
00653   rgb[2] = 0 * 255.0;
00654 
00655   // Draw lines between the best corresponding points
00656   for (size_t i = 0; i < source_points->size (); ++i)
00657   {
00658     const PointT &p_src = source_points->points[i];
00659     const PointT &p_tgt = target_points->points[correspondences[i]];
00660 
00661     // Add the line
00662     vtkSmartPointer<vtkLineSource> line = vtkSmartPointer<vtkLineSource>::New ();
00663     line->SetPoint1 (p_src.x, p_src.y, p_src.z);
00664     line->SetPoint2 (p_tgt.x, p_tgt.y, p_tgt.z);
00665     line->Update ();
00666     polydata->AddInput (line->GetOutput ());
00667     line_colors->InsertNextTupleValue (rgb);
00668   }
00669   polydata->Update ();
00670   vtkSmartPointer<vtkPolyData> line_data = polydata->GetOutput ();
00671   line_data->GetCellData ()->SetScalars (line_colors);
00672 
00673   // Create an Actor
00674   vtkSmartPointer<vtkLODActor> actor;
00675   createActorFromVTKDataSet (line_data, actor);
00676   actor->GetProperty ()->SetRepresentationToWireframe ();
00677   actor->GetProperty ()->SetOpacity (0.5);
00678   addActorToRenderer (actor, viewport);
00679 
00680   // Save the pointer/ID pair to the global actor map
00681   (*shape_actor_map_)[id] = actor;
00682 
00683   return (true);
00684 }
00685 
00687 template <typename PointT> bool
00688 pcl::visualization::PCLVisualizer::addCorrespondences (
00689    const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
00690    const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
00691    const pcl::Correspondences &correspondences,
00692    const std::string &id,
00693    int viewport)
00694 {
00695   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00696   ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
00697   if (am_it != shape_actor_map_->end ())
00698   {
00699     PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
00700     return (false);
00701   }
00702 
00703   vtkSmartPointer<vtkAppendPolyData> polydata = vtkSmartPointer<vtkAppendPolyData>::New ();
00704 
00705   vtkSmartPointer<vtkUnsignedCharArray> line_colors = vtkSmartPointer<vtkUnsignedCharArray>::New ();
00706   line_colors->SetNumberOfComponents (3);
00707   line_colors->SetName ("Colors");
00708   unsigned char rgb[3];
00709   // Use Red by default (can be changed later)
00710   rgb[0] = 1 * 255.0;
00711   rgb[1] = 0 * 255.0;
00712   rgb[2] = 0 * 255.0;
00713 
00714   // Draw lines between the best corresponding points
00715   for (size_t i = 0; i < correspondences.size (); ++i)
00716   {
00717     const PointT &p_src = source_points->points[correspondences[i].index_query];
00718     const PointT &p_tgt = target_points->points[correspondences[i].index_match];
00719 
00720     // Add the line
00721     vtkSmartPointer<vtkLineSource> line = vtkSmartPointer<vtkLineSource>::New ();
00722     line->SetPoint1 (p_src.x, p_src.y, p_src.z);
00723     line->SetPoint2 (p_tgt.x, p_tgt.y, p_tgt.z);
00724     line->Update ();
00725     polydata->AddInput (line->GetOutput ());
00726     line_colors->InsertNextTupleValue (rgb);
00727   }
00728   polydata->Update ();
00729   vtkSmartPointer<vtkPolyData> line_data = polydata->GetOutput ();
00730   line_data->GetCellData ()->SetScalars (line_colors);
00731 
00732   // Create an Actor
00733   vtkSmartPointer<vtkLODActor> actor;
00734   createActorFromVTKDataSet (line_data, actor);
00735   actor->GetProperty ()->SetRepresentationToWireframe ();
00736   actor->GetProperty ()->SetOpacity (0.5);
00737   addActorToRenderer (actor, viewport);
00738 
00739   // Save the pointer/ID pair to the global actor map
00740   (*shape_actor_map_)[id] = actor;
00741 
00742   return (true);
00743 }
00744 
00746 template <typename PointT> bool
00747 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
00748     const PointCloudGeometryHandler<PointT> &geometry_handler,
00749     const PointCloudColorHandler<PointT> &color_handler,
00750     const std::string &id,
00751     int viewport,
00752     const Eigen::Vector4f& sensor_origin,
00753     const Eigen::Quaternion<float>& sensor_orientation)
00754 {
00755   if (!geometry_handler.isCapable ())
00756   {
00757     PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
00758     return (false);
00759   }
00760 
00761   if (!color_handler.isCapable ())
00762   {
00763     PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
00764     return (false);
00765   }
00766 
00767   vtkSmartPointer<vtkPolyData> polydata;
00768   vtkSmartPointer<vtkIdTypeArray> initcells;
00769   // Convert the PointCloud to VTK PolyData
00770   convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
00771   // use the given geometry handler
00772   polydata->Update ();
00773 
00774   // Get the colors from the handler
00775   vtkSmartPointer<vtkDataArray> scalars;
00776   color_handler.getColor (scalars);
00777   polydata->GetPointData ()->SetScalars (scalars);
00778   double minmax[2];
00779   scalars->GetRange (minmax);
00780 
00781   // Create an Actor
00782   vtkSmartPointer<vtkLODActor> actor;
00783   createActorFromVTKDataSet (polydata, actor);
00784   actor->GetMapper ()->SetScalarRange (minmax);
00785 
00786   // Add it to all renderers
00787   addActorToRenderer (actor, viewport);
00788 
00789   // Save the pointer/ID pair to the global actor map
00790   (*cloud_actor_map_)[id].actor = actor;
00791   (*cloud_actor_map_)[id].cells = initcells;
00792 
00793   // Save the viewpoint transformation matrix to the global actor map
00794   vtkSmartPointer<vtkMatrix4x4> transformation = vtkSmartPointer<vtkMatrix4x4>::New();
00795   convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
00796   (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
00797 
00798   return (true);
00799 }
00800 
00802 template <typename PointT> bool
00803 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
00804     const PointCloudGeometryHandler<PointT> &geometry_handler,
00805     const ColorHandlerConstPtr &color_handler,
00806     const std::string &id,
00807     int viewport,
00808     const Eigen::Vector4f& sensor_origin,
00809     const Eigen::Quaternion<float>& sensor_orientation)
00810 {
00811   if (!geometry_handler.isCapable ())
00812   {
00813     PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
00814     return (false);
00815   }
00816 
00817   if (!color_handler->isCapable ())
00818   {
00819     PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler->getName ().c_str ());
00820     return (false);
00821   }
00822 
00823   vtkSmartPointer<vtkPolyData> polydata;
00824   vtkSmartPointer<vtkIdTypeArray> initcells;
00825   // Convert the PointCloud to VTK PolyData
00826   convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
00827   // use the given geometry handler
00828   polydata->Update ();
00829 
00830   // Get the colors from the handler
00831   vtkSmartPointer<vtkDataArray> scalars;
00832   color_handler->getColor (scalars);
00833   polydata->GetPointData ()->SetScalars (scalars);
00834   double minmax[2];
00835   scalars->GetRange (minmax);
00836 
00837   // Create an Actor
00838   vtkSmartPointer<vtkLODActor> actor;
00839   createActorFromVTKDataSet (polydata, actor);
00840   actor->GetMapper ()->SetScalarRange (minmax);
00841 
00842   // Add it to all renderers
00843   addActorToRenderer (actor, viewport);
00844 
00845   // Save the pointer/ID pair to the global actor map
00846   (*cloud_actor_map_)[id].actor = actor;
00847   (*cloud_actor_map_)[id].cells = initcells;
00848   (*cloud_actor_map_)[id].color_handlers.push_back (color_handler);
00849 
00850   // Save the viewpoint transformation matrix to the global actor map
00851   // Save the viewpoint transformation matrix to the global actor map
00852   vtkSmartPointer<vtkMatrix4x4> transformation = vtkSmartPointer<vtkMatrix4x4>::New();
00853   convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
00854   (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
00855 
00856   return (true);
00857 }
00858 
00860 template <typename PointT> bool
00861 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
00862     const GeometryHandlerConstPtr &geometry_handler,
00863     const PointCloudColorHandler<PointT> &color_handler,
00864     const std::string &id,
00865     int viewport,
00866     const Eigen::Vector4f& sensor_origin,
00867     const Eigen::Quaternion<float>& sensor_orientation)
00868 {
00869   if (!geometry_handler->isCapable ())
00870   {
00871     PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler->getName ().c_str ());
00872     return (false);
00873   }
00874 
00875   if (!color_handler.isCapable ())
00876   {
00877     PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
00878     return (false);
00879   }
00880 
00881   vtkSmartPointer<vtkPolyData> polydata;
00882   vtkSmartPointer<vtkIdTypeArray> initcells;
00883   // Convert the PointCloud to VTK PolyData
00884   convertPointCloudToVTKPolyData (geometry_handler, polydata, initcells);
00885   // use the given geometry handler
00886   polydata->Update ();
00887 
00888   // Get the colors from the handler
00889   vtkSmartPointer<vtkDataArray> scalars;
00890   color_handler.getColor (scalars);
00891   polydata->GetPointData ()->SetScalars (scalars);
00892   double minmax[2];
00893   scalars->GetRange (minmax);
00894 
00895   // Create an Actor
00896   vtkSmartPointer<vtkLODActor> actor;
00897   createActorFromVTKDataSet (polydata, actor);
00898   actor->GetMapper ()->SetScalarRange (minmax);
00899 
00900   // Add it to all renderers
00901   addActorToRenderer (actor, viewport);
00902 
00903   // Save the pointer/ID pair to the global actor map
00904   (*cloud_actor_map_)[id].actor = actor;
00905   (*cloud_actor_map_)[id].cells = initcells;
00906   (*cloud_actor_map_)[id].geometry_handlers.push_back (geometry_handler);
00907 
00908   // Save the viewpoint transformation matrix to the global actor map
00909   vtkSmartPointer<vtkMatrix4x4> transformation = vtkSmartPointer<vtkMatrix4x4>::New();
00910   convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
00911   (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
00912 
00913   return (true);
00914 }
00915 
00917 template <typename PointT> bool
00918 pcl::visualization::PCLVisualizer::updatePointCloud (const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00919                                                      const std::string &id)
00920 {
00921   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00922   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
00923 
00924   if (am_it == cloud_actor_map_->end ())
00925     return (false);
00926 
00927   vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
00928   // Convert the PointCloud to VTK PolyData
00929   convertPointCloudToVTKPolyData<PointT> (cloud, polydata, am_it->second.cells);
00930   polydata->Update ();
00931 
00932   // Set scalars to blank, since there is no way we can update them here.
00933   vtkSmartPointer<vtkDataArray> scalars;
00934   polydata->GetPointData ()->SetScalars (scalars);
00935   polydata->Update ();
00936   double minmax[2];
00937   minmax[0] = std::numeric_limits<double>::min ();
00938   minmax[1] = std::numeric_limits<double>::max ();
00939   am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
00940   am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
00941 
00942   // Update the mapper
00943   reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata);
00944   return (true);
00945 }
00946 
00948 template <typename PointT> bool
00949 pcl::visualization::PCLVisualizer::updatePointCloud (const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00950                                                      const PointCloudGeometryHandler<PointT> &geometry_handler,
00951                                                      const std::string &id)
00952 {
00953   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00954   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
00955 
00956   if (am_it == cloud_actor_map_->end ())
00957     return (false);
00958 
00959   vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
00960   if (!polydata)
00961     return (false);
00962   // Convert the PointCloud to VTK PolyData
00963   convertPointCloudToVTKPolyData (geometry_handler, polydata, am_it->second.cells);
00964 
00965   // Set scalars to blank, since there is no way we can update them here.
00966   vtkSmartPointer<vtkDataArray> scalars;
00967   polydata->GetPointData ()->SetScalars (scalars);
00968   polydata->Update ();
00969   double minmax[2];
00970   minmax[0] = std::numeric_limits<double>::min ();
00971   minmax[1] = std::numeric_limits<double>::max ();
00972   am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
00973   am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
00974 
00975   // Update the mapper
00976   reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata);
00977   return (true);
00978 }
00979 
00980 
00982 template <typename PointT> bool
00983 pcl::visualization::PCLVisualizer::updatePointCloud (const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
00984                                                      const PointCloudColorHandler<PointT> &color_handler,
00985                                                      const std::string &id)
00986 {
00987   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00988   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
00989 
00990   if (am_it == cloud_actor_map_->end ())
00991     return (false);
00992 
00993   // Get the current poly data
00994   vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
00995   if (!polydata)
00996     return (false);
00997   vtkSmartPointer<vtkCellArray> vertices = polydata->GetVerts ();
00998   vtkSmartPointer<vtkPoints> points      = polydata->GetPoints ();
00999   // Copy the new point array in
01000   vtkIdType nr_points = cloud->points.size ();
01001   points->SetNumberOfPoints (nr_points);
01002 
01003   // Get a pointer to the beginning of the data array
01004   float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
01005 
01006   int pts = 0;
01007   // If the dataset is dense (no NaNs)
01008   if (cloud->is_dense)
01009   {
01010     for (vtkIdType i = 0; i < nr_points; ++i, pts += 3)
01011       memcpy (&data[pts], &cloud->points[i].x, 12);    // sizeof (float) * 3
01012   }
01013   else
01014   {
01015     vtkIdType j = 0;    // true point index
01016     for (vtkIdType i = 0; i < nr_points; ++i)
01017     {
01018       // Check if the point is invalid
01019       if (!isFinite (cloud->points[i]))
01020         continue;
01021 
01022       memcpy (&data[pts], &cloud->points[i].x, 12);    // sizeof (float) * 3
01023       pts += 3;
01024       j++;
01025     }
01026     nr_points = j;
01027     points->SetNumberOfPoints (nr_points);
01028   }
01029 
01030   vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
01031   updateCells (cells, am_it->second.cells, nr_points);
01032 
01033   // Set the cells and the vertices
01034   vertices->SetCells (nr_points, cells);
01035 
01036   // Get the colors from the handler
01037   vtkSmartPointer<vtkDataArray> scalars;
01038   color_handler.getColor (scalars);
01039   double minmax[2];
01040   scalars->GetRange (minmax);
01041   // Update the data
01042   polydata->GetPointData ()->SetScalars (scalars);
01043   polydata->Update ();
01044 
01045   am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
01046   am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
01047 
01048   // Update the mapper
01049   reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata);
01050   return (true);
01051 }
01052 
01054 template <typename PointT> bool
01055 pcl::visualization::PCLVisualizer::addPolygonMesh (
01056     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
01057     const std::vector<pcl::Vertices> &vertices,
01058     const std::string &id,
01059     int viewport)
01060 {
01061   if (vertices.empty () || cloud->points.empty ())
01062     return (false);
01063 
01064   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
01065   if (am_it != cloud_actor_map_->end ())
01066   {
01067     pcl::console::print_warn (
01068                                 "[addPolygonMesh] A shape with id <%s> already exists! Please choose a different id and retry.\n",
01069                                 id.c_str ());
01070     return (false);
01071   }
01072 
01073   // Create points from polyMesh.cloud
01074   vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New ();
01075   vtkIdType nr_points = cloud->points.size ();
01076   points->SetNumberOfPoints (nr_points);
01077   vtkSmartPointer<vtkLODActor> actor;
01078 
01079   // Get a pointer to the beginning of the data array
01080   float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
01081 
01082   int ptr = 0;
01083   std::vector<int> lookup;
01084   // If the dataset is dense (no NaNs)
01085   if (cloud->is_dense)
01086   {
01087     for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
01088       memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
01089   }
01090   else
01091   {
01092     lookup.resize (nr_points);
01093     vtkIdType j = 0;    // true point index
01094     for (vtkIdType i = 0; i < nr_points; ++i)
01095     {
01096       // Check if the point is invalid
01097       if (!isFinite (cloud->points[i]))
01098         continue;
01099 
01100       lookup[i] = j;
01101       memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
01102       j++;
01103       ptr += 3;
01104     }
01105     nr_points = j;
01106     points->SetNumberOfPoints (nr_points);
01107   }
01108 
01109   // Get the maximum size of a polygon
01110   int max_size_of_polygon = -1;
01111   for (size_t i = 0; i < vertices.size (); ++i)
01112     if (max_size_of_polygon < (int)vertices[i].vertices.size ())
01113       max_size_of_polygon = vertices[i].vertices.size ();
01114 
01115   if (vertices.size () > 1)
01116   {
01117     // Create polys from polyMesh.polygons
01118     vtkSmartPointer<vtkCellArray> cell_array = vtkSmartPointer<vtkCellArray>::New ();
01119     vtkIdType *cell = cell_array->WritePointer (vertices.size (), vertices.size () * (max_size_of_polygon + 1));
01120     int idx = 0;
01121     if (lookup.size () > 0)
01122     {
01123       for (size_t i = 0; i < vertices.size (); ++i, ++idx)
01124       {
01125         size_t n_points = vertices[i].vertices.size ();
01126         *cell++ = n_points;
01127         //cell_array->InsertNextCell (n_points);
01128         for (size_t j = 0; j < n_points; j++, ++idx)
01129           *cell++ = lookup[vertices[i].vertices[j]];
01130           //cell_array->InsertCellPoint (lookup[vertices[i].vertices[j]]);
01131       }
01132     }
01133     else
01134     {
01135       for (size_t i = 0; i < vertices.size (); ++i, ++idx)
01136       {
01137         size_t n_points = vertices[i].vertices.size ();
01138         *cell++ = n_points;
01139         //cell_array->InsertNextCell (n_points);
01140         for (size_t j = 0; j < n_points; j++, ++idx)
01141           *cell++ = vertices[i].vertices[j];
01142           //cell_array->InsertCellPoint (vertices[i].vertices[j]);
01143       }
01144     }
01145     vtkSmartPointer<vtkPolyData> polydata;
01146     allocVtkPolyData (polydata);
01147     cell_array->GetData ()->SetNumberOfValues (idx);
01148     cell_array->Squeeze ();
01149     polydata->SetStrips (cell_array);
01150     polydata->SetPoints (points);
01151 
01152     createActorFromVTKDataSet (polydata, actor, false);
01153   }
01154   else
01155   {
01156     vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New ();
01157     size_t n_points = vertices[0].vertices.size ();
01158     polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
01159 
01160     if (lookup.size () > 0)
01161     {
01162       for (size_t j = 0; j < (n_points - 1); ++j)
01163         polygon->GetPointIds ()->SetId (j, lookup[vertices[0].vertices[j]]);
01164     }
01165     else
01166     {
01167       for (size_t j = 0; j < (n_points - 1); ++j)
01168         polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
01169     }
01170     vtkSmartPointer<vtkUnstructuredGrid> poly_grid;
01171     allocVtkUnstructuredGrid (poly_grid);
01172     poly_grid->Allocate (1, 1);
01173     poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
01174     poly_grid->SetPoints (points);
01175     poly_grid->Update ();
01176 
01177     createActorFromVTKDataSet (poly_grid, actor, false);
01178   }
01179   actor->GetProperty ()->SetRepresentationToSurface ();
01180   actor->GetProperty ()->BackfaceCullingOn ();
01181   actor->GetProperty ()->EdgeVisibilityOff ();
01182   actor->GetProperty ()->ShadingOff ();
01183   addActorToRenderer (actor, viewport);
01184 
01185   // Save the pointer/ID pair to the global actor map
01186   (*cloud_actor_map_)[id].actor = actor;
01187   //if (vertices.size () > 1)
01188   //  (*cloud_actor_map_)[id].cells = static_cast<vtkPolyDataMapper*>(actor->GetMapper ())->GetInput ()->GetVerts ()->GetData ();
01189   return (true);
01190 }
01191 
01193 template <typename PointT> bool
01194 pcl::visualization::PCLVisualizer::updatePolygonMesh (
01195     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
01196     const std::vector<pcl::Vertices> &verts,
01197     const std::string &id)
01198 {
01199   if (verts.empty ())
01200   {
01201      pcl::console::print_error ("[addPolygonMesh] No vertices given!\n");
01202      return (false);
01203   }
01204 
01205   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
01206   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
01207   if (am_it == cloud_actor_map_->end ())
01208     return (false);
01209 
01210   // Get the current poly data
01211   vtkSmartPointer<vtkPolyData> polydata = static_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
01212   if (!polydata)
01213     return (false);
01214   vtkSmartPointer<vtkCellArray> cells = polydata->GetStrips ();
01215   if (!cells)
01216     return (false);
01217   vtkSmartPointer<vtkPoints> points   = polydata->GetPoints ();
01218   // Copy the new point array in
01219   vtkIdType nr_points = cloud->points.size ();
01220   points->SetNumberOfPoints (nr_points);
01221 
01222   // Get a pointer to the beginning of the data array
01223   float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
01224 
01225   int ptr = 0;
01226   std::vector<int> lookup;
01227   // If the dataset is dense (no NaNs)
01228   if (cloud->is_dense)
01229   {
01230     for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
01231       memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
01232   }
01233   else
01234   {
01235     lookup.resize (nr_points);
01236     vtkIdType j = 0;    // true point index
01237     for (vtkIdType i = 0; i < nr_points; ++i)
01238     {
01239       // Check if the point is invalid
01240       if (!isFinite (cloud->points[i]))
01241         continue;
01242 
01243       lookup [i] = j;
01244       memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
01245       j++;
01246       ptr += 3;
01247     }
01248     nr_points = j;
01249     points->SetNumberOfPoints (nr_points);
01250   }
01251 
01252   // Get the maximum size of a polygon
01253   int max_size_of_polygon = -1;
01254   for (size_t i = 0; i < verts.size (); ++i)
01255     if (max_size_of_polygon < (int)verts[i].vertices.size ())
01256       max_size_of_polygon = verts[i].vertices.size ();
01257 
01258   // Update the cells
01259   cells = vtkSmartPointer<vtkCellArray>::New ();
01260   vtkIdType *cell = cells->WritePointer (verts.size (), verts.size () * (max_size_of_polygon + 1));
01261   int idx = 0;
01262   if (lookup.size () > 0)
01263   {
01264     for (size_t i = 0; i < verts.size (); ++i, ++idx)
01265     {
01266       size_t n_points = verts[i].vertices.size ();
01267       *cell++ = n_points;
01268       for (size_t j = 0; j < n_points; j++, cell++, ++idx)
01269         *cell = lookup[verts[i].vertices[j]];
01270     }
01271   }
01272   else
01273   {
01274     for (size_t i = 0; i < verts.size (); ++i, ++idx)
01275     {
01276       size_t n_points = verts[i].vertices.size ();
01277       *cell++ = n_points;
01278       for (size_t j = 0; j < n_points; j++, cell++, ++idx)
01279         *cell = verts[i].vertices[j];
01280     }
01281   }
01282   cells->GetData ()->SetNumberOfValues (idx);
01283   cells->Squeeze ();
01284   // Set the the vertices
01285   polydata->SetStrips (cells);
01286   polydata->Update ();
01287 
01288 /*
01289   vtkSmartPointer<vtkLODActor> actor;
01290   if (vertices.size () > 1)
01291   {
01292   }
01293   else
01294   {
01295     vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New ();
01296     size_t n_points = vertices[0].vertices.size ();
01297     polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
01298 
01299     for (size_t j = 0; j < (n_points - 1); ++j)
01300       polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
01301 
01302     vtkSmartPointer<vtkUnstructuredGrid> poly_grid;
01303     allocVtkUnstructuredGrid (poly_grid);
01304     poly_grid->Allocate (1, 1);
01305     poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
01306     poly_grid->SetPoints (points);
01307     poly_grid->Update ();
01308 
01309     createActorFromVTKDataSet (poly_grid, actor);
01310   }
01311 */
01312 
01313   // Get the colors from the handler
01314   //vtkSmartPointer<vtkDataArray> scalars;
01315   //color_handler.getColor (scalars);
01316   //polydata->GetPointData ()->SetScalars (scalars);
01317 //  polydata->Update ();
01318 
01319   am_it->second.actor->GetProperty ()->BackfaceCullingOn ();
01320 //  am_it->second.actor->Modified ();
01321 
01322   return (true);
01323 }
01324 
01325 
01327 /* Optimized function: need to do something with the signature as it colides with the general T one
01328 bool
01329 pcl::visualization::PCLVisualizer::updatePointCloud (const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr &cloud,
01330                                                      const PointCloudColorHandlerRGBField<pcl::PointXYZRGB> &color_handler,
01331                                                      const std::string &id)
01332 {
01333   win_->SetAbortRender (1);
01334   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
01335   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
01336 
01337   if (am_it == cloud_actor_map_->end ())
01338     return (false);
01339 
01340   // Get the current poly data
01341   vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
01342   if (!polydata)
01343     return (false);
01344   vtkSmartPointer<vtkCellArray> vertices = polydata->GetVerts ();
01345   vtkSmartPointer<vtkPoints> points      = polydata->GetPoints ();
01346 //  vtkUnsignedCharArray* scalars = vtkUnsignedCharArray::SafeDownCast (polydata->GetPointData ()->GetScalars ());
01347   vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New ();
01348   // Copy the new point array in
01349   vtkIdType nr_points = cloud->points.size ();
01350   points->SetNumberOfPoints (nr_points);
01351   scalars->SetNumberOfComponents (3);
01352   scalars->SetNumberOfTuples (nr_points);
01353   polydata->GetPointData ()->SetScalars (scalars);
01354   unsigned char* colors = scalars->GetPointer (0);
01355 
01356   // Get a pointer to the beginning of the data array
01357   float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
01358 
01359   // If the dataset is dense (no NaNs)
01360   if (cloud->is_dense)
01361   {
01362     for (vtkIdType i = 0; i < nr_points; ++i)
01363     {
01364       memcpy (&data[i * 3], &cloud->points[i].x, 12);    // sizeof (float) * 3
01365       int idx = i * 3;
01366       colors[idx    ] = cloud->points[i].r;
01367       colors[idx + 1] = cloud->points[i].g;
01368       colors[idx + 2] = cloud->points[i].b;
01369     }
01370   }
01371   else
01372   {
01373     vtkIdType j = 0;    // true point index
01374     for (vtkIdType i = 0; i < nr_points; ++i)
01375     {
01376       // Check if the point is invalid
01377       if (!pcl_isfinite (cloud->points[i].x) ||
01378           !pcl_isfinite (cloud->points[i].y) ||
01379           !pcl_isfinite (cloud->points[i].z))
01380         continue;
01381 
01382       memcpy (&data[j * 3], &cloud->points[i].x, 12);    // sizeof (float) * 3
01383       int idx = j * 3;
01384       colors[idx    ] = cloud->points[i].r;
01385       colors[idx + 1] = cloud->points[i].g;
01386       colors[idx + 2] = cloud->points[i].b;
01387       j++;
01388     }
01389     nr_points = j;
01390     points->SetNumberOfPoints (nr_points);
01391     scalars->SetNumberOfTuples (nr_points);
01392   }
01393 
01394   vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
01395   updateCells (cells, am_it->second.cells, nr_points);
01396 
01397   // Set the cells and the vertices
01398   vertices->SetCells (nr_points, cells);
01399 
01400   // Update the mapper
01401   reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata);
01402   return (true);
01403 }*/
01404 
01405 
01406 #endif