Point Cloud Library (PCL)  1.4.0
 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 3771 2012-01-01 06:58:14Z rusu $
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));
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));
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));
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));
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));
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));
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 {
00753   if (!geometry_handler.isCapable ())
00754   {
00755     PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
00756     return (false);
00757   }
00758 
00759   if (!color_handler.isCapable ())
00760   {
00761     PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
00762     return (false);
00763   }
00764 
00765   vtkSmartPointer<vtkPolyData> polydata;
00766   vtkSmartPointer<vtkIdTypeArray> initcells;
00767   // Convert the PointCloud to VTK PolyData
00768   convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
00769   // use the given geometry handler
00770   polydata->Update ();
00771 
00772   // Get the colors from the handler
00773   vtkSmartPointer<vtkDataArray> scalars;
00774   color_handler.getColor (scalars);
00775   polydata->GetPointData ()->SetScalars (scalars);
00776 
00777   // Create an Actor
00778   vtkSmartPointer<vtkLODActor> actor;
00779   createActorFromVTKDataSet (polydata, actor);
00780 
00781   // Add it to all renderers
00782   addActorToRenderer (actor, viewport);
00783 
00784   // Save the pointer/ID pair to the global actor map
00785   (*cloud_actor_map_)[id].actor = actor;
00786   (*cloud_actor_map_)[id].cells = initcells;
00787 
00788   // Save the viewpoint transformation matrix to the global actor map
00789   vtkSmartPointer<vtkMatrix4x4> transformation = vtkSmartPointer<vtkMatrix4x4>::New();
00790   Eigen::Vector4f origin = geometry_handler.getOrigin ();
00791   Eigen::Quaternion<float> orientation = geometry_handler.getOrientation ();
00792   convertToVtkMatrix (origin, orientation, transformation);
00793   (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
00794 
00795   return (true);
00796 }
00797 
00799 template <typename PointT> bool
00800 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
00801     const PointCloudGeometryHandler<PointT> &geometry_handler,
00802     const ColorHandlerConstPtr &color_handler, 
00803     const std::string &id,
00804     int viewport)
00805 {
00806   if (!geometry_handler.isCapable ())
00807   {
00808     PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
00809     return (false);
00810   }
00811 
00812   if (!color_handler->isCapable ())
00813   {
00814     PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler->getName ().c_str ());
00815     return (false);
00816   }
00817 
00818   vtkSmartPointer<vtkPolyData> polydata;
00819   vtkSmartPointer<vtkIdTypeArray> initcells;
00820   // Convert the PointCloud to VTK PolyData
00821   convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
00822   // use the given geometry handler
00823   polydata->Update ();
00824 
00825   // Get the colors from the handler
00826   vtkSmartPointer<vtkDataArray> scalars;
00827   color_handler->getColor (scalars);
00828   polydata->GetPointData ()->SetScalars (scalars);
00829 
00830   // Create an Actor
00831   vtkSmartPointer<vtkLODActor> actor;
00832   createActorFromVTKDataSet (polydata, actor);
00833 
00834   // Add it to all renderers
00835   addActorToRenderer (actor, viewport);
00836 
00837   // Save the pointer/ID pair to the global actor map
00838   (*cloud_actor_map_)[id].actor = actor;
00839   (*cloud_actor_map_)[id].cells = initcells;
00840   (*cloud_actor_map_)[id].color_handlers.push_back (color_handler);
00841 
00842   // Save the viewpoint transformation matrix to the global actor map
00843   // Save the viewpoint transformation matrix to the global actor map
00844   vtkSmartPointer<vtkMatrix4x4> transformation = vtkSmartPointer<vtkMatrix4x4>::New();
00845   Eigen::Vector4f origin = geometry_handler.getOrigin ();
00846   Eigen::Quaternion<float> orientation = geometry_handler.getOrientation ();
00847   convertToVtkMatrix (origin, orientation, transformation);
00848   (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
00849 
00850   return (true);
00851 }
00852 
00854 template <typename PointT> bool
00855 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
00856     const GeometryHandlerConstPtr &geometry_handler,
00857     const PointCloudColorHandler<PointT> &color_handler, 
00858     const std::string &id,
00859     int viewport)
00860 {
00861   if (!geometry_handler->isCapable ())
00862   {
00863     PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler->getName ().c_str ());
00864     return (false);
00865   }
00866 
00867   if (!color_handler.isCapable ())
00868   {
00869     PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
00870     return (false);
00871   }
00872 
00873   vtkSmartPointer<vtkPolyData> polydata;
00874   vtkSmartPointer<vtkIdTypeArray> initcells;
00875   // Convert the PointCloud to VTK PolyData
00876   convertPointCloudToVTKPolyData (geometry_handler, polydata, initcells);
00877   // use the given geometry handler
00878   polydata->Update ();
00879 
00880   // Get the colors from the handler
00881   vtkSmartPointer<vtkDataArray> scalars;
00882   color_handler.getColor (scalars);
00883   polydata->GetPointData ()->SetScalars (scalars);
00884 
00885   // Create an Actor
00886   vtkSmartPointer<vtkLODActor> actor;
00887   createActorFromVTKDataSet (polydata, actor);
00888 
00889   // Add it to all renderers
00890   addActorToRenderer (actor, viewport);
00891 
00892   // Save the pointer/ID pair to the global actor map
00893   (*cloud_actor_map_)[id].actor = actor;
00894   (*cloud_actor_map_)[id].cells = initcells;
00895   (*cloud_actor_map_)[id].geometry_handlers.push_back (geometry_handler);
00896   return (true);
00897 }
00898 
00900 template <typename PointT> bool
00901 pcl::visualization::PCLVisualizer::updatePointCloud (const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 
00902                                                      const std::string &id)
00903 {
00904   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00905   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
00906 
00907   if (am_it == cloud_actor_map_->end ())
00908     return (false);
00909 
00910   vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
00911   // Convert the PointCloud to VTK PolyData
00912   convertPointCloudToVTKPolyData<PointT> (cloud, polydata, am_it->second.cells);
00913   polydata->Update ();
00914 
00915   // Set scalars to blank, since there is no way we can update them here. 
00916   vtkSmartPointer<vtkDataArray> scalars;
00917   polydata->GetPointData ()->SetScalars (scalars);
00918   polydata->Update ();
00919   am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
00920 
00921   // Update the mapper
00922   reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata);
00923   return (true);
00924 }
00925 
00927 template <typename PointT> bool
00928 pcl::visualization::PCLVisualizer::updatePointCloud (const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 
00929                                                      const PointCloudGeometryHandler<PointT> &geometry_handler,
00930                                                      const std::string &id)
00931 {
00932   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00933   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
00934 
00935   if (am_it == cloud_actor_map_->end ())
00936     return (false);
00937 
00938   vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
00939   if (!polydata)
00940     return (false);
00941   // Convert the PointCloud to VTK PolyData
00942   convertPointCloudToVTKPolyData (geometry_handler, polydata, am_it->second.cells);
00943 
00944   // Set scalars to blank, since there is no way we can update them here. 
00945   vtkSmartPointer<vtkDataArray> scalars;
00946   polydata->GetPointData ()->SetScalars (scalars);
00947   polydata->Update ();
00948   am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
00949 
00950   // Update the mapper
00951   reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata);
00952   return (true);
00953 }
00954 
00955 
00957 template <typename PointT> bool
00958 pcl::visualization::PCLVisualizer::updatePointCloud (const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 
00959                                                      const PointCloudColorHandler<PointT> &color_handler,
00960                                                      const std::string &id)
00961 {
00962   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
00963   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
00964 
00965   if (am_it == cloud_actor_map_->end ())
00966     return (false);
00967 
00968   // Get the current poly data
00969   vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
00970   if (!polydata)
00971     return (false);
00972   vtkSmartPointer<vtkCellArray> vertices = polydata->GetVerts ();
00973   vtkSmartPointer<vtkPoints> points      = polydata->GetPoints ();
00974   // Copy the new point array in
00975   vtkIdType nr_points = cloud->points.size ();
00976   points->SetNumberOfPoints (nr_points);
00977   
00978   // Get a pointer to the beginning of the data array
00979   float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
00980 
00981   // If the dataset is dense (no NaNs)
00982   if (cloud->is_dense)
00983   {
00984     for (vtkIdType i = 0; i < nr_points; ++i)
00985       memcpy (&data[i * 3], &cloud->points[i].x, 12);    // sizeof (float) * 3
00986   }
00987   else
00988   {
00989     vtkIdType j = 0;    // true point index
00990     for (vtkIdType i = 0; i < nr_points; ++i)
00991     {
00992       // Check if the point is invalid
00993       if (!pcl_isfinite (cloud->points[i].x) || 
00994           !pcl_isfinite (cloud->points[i].y) || 
00995           !pcl_isfinite (cloud->points[i].z))
00996         continue;
00997 
00998       memcpy (&data[j * 3], &cloud->points[i].x, 12);    // sizeof (float) * 3
00999       j++;
01000     }
01001     nr_points = j;
01002     points->SetNumberOfPoints (nr_points);
01003   }
01004 
01005   vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
01006   updateCells (cells, am_it->second.cells, nr_points);
01007 
01008   // Set the cells and the vertices
01009   vertices->SetCells (nr_points, cells);
01010 
01011   // Get the colors from the handler
01012   vtkSmartPointer<vtkDataArray> scalars;
01013   color_handler.getColor (scalars);
01014   polydata->GetPointData ()->SetScalars (scalars);
01015   polydata->Update ();
01016   
01017   am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
01018 
01019   // Update the mapper
01020   reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata);
01021   return (true);
01022 }
01023 
01025 template <typename PointT> bool
01026 pcl::visualization::PCLVisualizer::addPolygonMesh (
01027     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
01028     const std::vector<pcl::Vertices> &vertices,
01029     const std::string &id,
01030     int viewport)
01031 {
01032   if (vertices.empty ())
01033   {
01034     pcl::console::print_error ("[addPolygonMesh] No vertices given!\n");
01035     return (false);
01036   }
01037 
01038   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
01039   if (am_it != cloud_actor_map_->end ())
01040   {
01041     pcl::console::print_warn (
01042                                 "[addPolygonMesh] A shape with id <%s> already exists! Please choose a different id and retry.\n",
01043                                 id.c_str ());
01044     return (false);
01045   }
01046 
01047   // Create points from polyMesh.cloud
01048   vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New ();
01049   vtkIdType nr_points = cloud->points.size ();
01050   points->SetNumberOfPoints (nr_points);
01051   vtkSmartPointer<vtkLODActor> actor;
01052 
01053   // Get a pointer to the beginning of the data array
01054   float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
01055 
01056   int ptr = 0;
01057   std::vector<int> lookup;
01058   // If the dataset is dense (no NaNs)
01059   if (cloud->is_dense)
01060   {
01061     for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
01062       memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
01063   }
01064   else
01065   {
01066     lookup.resize (nr_points);
01067     vtkIdType j = 0;    // true point index
01068     for (vtkIdType i = 0; i < nr_points; ++i)
01069     {
01070       // Check if the point is invalid
01071       if (!isFinite (cloud->points[i]))
01072         continue;
01073 
01074       lookup [i] = j;
01075       memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
01076       j++;
01077       ptr += 3;
01078     }
01079     nr_points = j;
01080     points->SetNumberOfPoints (nr_points);
01081   }
01082 
01083   // Get the maximum size of a polygon
01084   int max_size_of_polygon = -1;
01085   for (size_t i = 0; i < vertices.size (); ++i)
01086     if (max_size_of_polygon < (int)vertices[i].vertices.size ())
01087       max_size_of_polygon = vertices[i].vertices.size ();
01088 
01089   if (vertices.size () > 1) 
01090   {
01091     // Create polys from polyMesh.polygons
01092     vtkSmartPointer<vtkCellArray> cell_array = vtkSmartPointer<vtkCellArray>::New ();
01093     vtkIdType *cell = cell_array->WritePointer (vertices.size (), vertices.size () * (max_size_of_polygon + 1));
01094     int idx = 0;
01095     if (lookup.size () > 0)
01096     {
01097       for (size_t i = 0; i < vertices.size (); ++i, ++idx)
01098       {
01099         size_t n_points = vertices[i].vertices.size ();
01100         *cell++ = n_points;
01101         //cell_array->InsertNextCell (n_points);
01102         for (size_t j = 0; j < n_points; j++, ++idx)
01103           *cell++ = lookup[vertices[i].vertices[j]];
01104           //cell_array->InsertCellPoint (lookup[vertices[i].vertices[j]]);
01105       }
01106     }
01107     else
01108     {
01109       for (size_t i = 0; i < vertices.size (); ++i, ++idx)
01110       {
01111         size_t n_points = vertices[i].vertices.size ();
01112         *cell++ = n_points;
01113         //cell_array->InsertNextCell (n_points);
01114         for (size_t j = 0; j < n_points; j++, ++idx)
01115           *cell++ = lookup[vertices[i].vertices[j]];
01116           //cell_array->InsertCellPoint (vertices[i].vertices[j]);
01117       }
01118     }
01119     vtkSmartPointer<vtkPolyData> polydata;
01120     allocVtkPolyData (polydata);
01121     cell_array->GetData ()->SetNumberOfValues (idx);
01122     cell_array->Squeeze ();
01123     polydata->SetStrips (cell_array);
01124     polydata->SetPoints (points);
01125 
01126     createActorFromVTKDataSet (polydata, actor, false);
01127   } 
01128   else 
01129   {
01130     vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New ();
01131     size_t n_points = vertices[0].vertices.size ();
01132     polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
01133 
01134     if (lookup.size () > 0)
01135     {
01136       for (size_t j = 0; j < (n_points - 1); ++j)
01137         polygon->GetPointIds ()->SetId (j, lookup[vertices[0].vertices[j]]);
01138     }
01139     else
01140     {
01141       for (size_t j = 0; j < (n_points - 1); ++j)
01142         polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
01143     }
01144     vtkSmartPointer<vtkUnstructuredGrid> poly_grid;
01145     allocVtkUnstructuredGrid (poly_grid);
01146     poly_grid->Allocate (1, 1);
01147     poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
01148     poly_grid->SetPoints (points);
01149     poly_grid->Update ();
01150 
01151     createActorFromVTKDataSet (poly_grid, actor, false);
01152   }
01153 
01154   actor->GetProperty ()->SetRepresentationToSurface ();
01155   actor->GetProperty ()->BackfaceCullingOn ();
01156   actor->GetProperty ()->EdgeVisibilityOff ();
01157   actor->GetProperty ()->ShadingOff ();
01158   addActorToRenderer (actor, viewport);
01159 
01160   // Save the pointer/ID pair to the global actor map
01161   (*cloud_actor_map_)[id].actor = actor;
01162   (*cloud_actor_map_)[id].cells = static_cast<vtkPolyDataMapper*>(actor->GetMapper ())->GetInput ()->GetVerts ()->GetData ();
01163   return (true);
01164 }
01165 
01167 template <typename PointT> bool
01168 pcl::visualization::PCLVisualizer::updatePolygonMesh (
01169     const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
01170     const std::vector<pcl::Vertices> &verts,
01171     const std::string &id)
01172 {
01173   if (verts.empty ())
01174   {
01175      pcl::console::print_error ("[addPolygonMesh] No vertices given!\n");
01176      return (false);
01177   }
01178 
01179   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
01180   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
01181   if (am_it == cloud_actor_map_->end ())
01182     return (false);
01183 
01184   // Get the current poly data
01185   vtkSmartPointer<vtkPolyData> polydata = static_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
01186   if (!polydata)
01187     return (false);
01188   vtkSmartPointer<vtkCellArray> cells = polydata->GetStrips ();
01189   if (!cells)
01190     return (false);
01191   vtkSmartPointer<vtkPoints> points   = polydata->GetPoints ();
01192   // Copy the new point array in
01193   vtkIdType nr_points = cloud->points.size ();
01194   points->SetNumberOfPoints (nr_points);
01195 
01196   // Get a pointer to the beginning of the data array
01197   float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
01198 
01199   int ptr = 0;
01200   std::vector<int> lookup;
01201   // If the dataset is dense (no NaNs)
01202   if (cloud->is_dense)
01203   {
01204     for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
01205       memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
01206   }
01207   else
01208   {
01209     lookup.resize (nr_points);
01210     vtkIdType j = 0;    // true point index
01211     for (vtkIdType i = 0; i < nr_points; ++i)
01212     {
01213       // Check if the point is invalid
01214       if (!isFinite (cloud->points[i]))
01215         continue;
01216 
01217       lookup [i] = j;
01218       memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
01219       j++;
01220       ptr += 3;
01221     }
01222     nr_points = j;
01223     points->SetNumberOfPoints (nr_points);
01224   }
01225 
01226   // Get the maximum size of a polygon
01227   int max_size_of_polygon = -1;
01228   for (size_t i = 0; i < verts.size (); ++i)
01229     if (max_size_of_polygon < (int)verts[i].vertices.size ())
01230       max_size_of_polygon = verts[i].vertices.size ();
01231 
01232   // Update the cells
01233   cells = vtkSmartPointer<vtkCellArray>::New ();
01234   vtkIdType *cell = cells->WritePointer (verts.size (), verts.size () * (max_size_of_polygon + 1));
01235   int idx = 0;
01236   if (lookup.size () > 0)
01237   {
01238     for (size_t i = 0; i < verts.size (); ++i, ++idx) 
01239     {
01240       size_t n_points = verts[i].vertices.size ();
01241       *cell++ = n_points;
01242       for (size_t j = 0; j < n_points; j++, cell++, ++idx)
01243         *cell = lookup[verts[i].vertices[j]];
01244     }
01245   }
01246   else
01247   {
01248     for (size_t i = 0; i < verts.size (); ++i, ++idx) 
01249     {
01250       size_t n_points = verts[i].vertices.size ();
01251       *cell++ = n_points;
01252       for (size_t j = 0; j < n_points; j++, cell++, ++idx)
01253         *cell = verts[i].vertices[j];
01254     }
01255   }
01256   cells->GetData ()->SetNumberOfValues (idx);
01257   cells->Squeeze ();
01258   // Set the the vertices
01259   polydata->SetStrips (cells);
01260   polydata->Update ();
01261 
01262 /*  
01263   vtkSmartPointer<vtkLODActor> actor;
01264   if (vertices.size () > 1) 
01265   {
01266   } 
01267   else 
01268   {
01269     vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New ();
01270     size_t n_points = vertices[0].vertices.size ();
01271     polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
01272 
01273     for (size_t j = 0; j < (n_points - 1); ++j) 
01274       polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
01275 
01276     vtkSmartPointer<vtkUnstructuredGrid> poly_grid;
01277     allocVtkUnstructuredGrid (poly_grid);
01278     poly_grid->Allocate (1, 1);
01279     poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
01280     poly_grid->SetPoints (points);
01281     poly_grid->Update ();
01282 
01283     createActorFromVTKDataSet (poly_grid, actor);
01284   }
01285 */
01286 
01287   // Get the colors from the handler
01288   //vtkSmartPointer<vtkDataArray> scalars;
01289   //color_handler.getColor (scalars);
01290   //polydata->GetPointData ()->SetScalars (scalars);
01291 //  polydata->Update ();
01292   
01293   am_it->second.actor->GetProperty ()->BackfaceCullingOn ();
01294 //  am_it->second.actor->Modified ();
01295 
01296   return (true);
01297 }
01298 
01299 
01301 /* Optimized function: need to do something with the signature as it colides with the general T one
01302 bool
01303 pcl::visualization::PCLVisualizer::updatePointCloud (const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr &cloud, 
01304                                                      const PointCloudColorHandlerRGBField<pcl::PointXYZRGB> &color_handler,
01305                                                      const std::string &id)
01306 {
01307   win_->SetAbortRender (1);
01308   // Check to see if this ID entry already exists (has it been already added to the visualizer?)
01309   CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
01310 
01311   if (am_it == cloud_actor_map_->end ())
01312     return (false);
01313 
01314   // Get the current poly data
01315   vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
01316   if (!polydata)
01317     return (false);
01318   vtkSmartPointer<vtkCellArray> vertices = polydata->GetVerts ();
01319   vtkSmartPointer<vtkPoints> points      = polydata->GetPoints ();
01320 //  vtkUnsignedCharArray* scalars = vtkUnsignedCharArray::SafeDownCast (polydata->GetPointData ()->GetScalars ());
01321   vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New ();
01322   // Copy the new point array in
01323   vtkIdType nr_points = cloud->points.size ();
01324   points->SetNumberOfPoints (nr_points);
01325   scalars->SetNumberOfComponents (3);
01326   scalars->SetNumberOfTuples (nr_points);
01327   polydata->GetPointData ()->SetScalars (scalars);
01328   unsigned char* colors = scalars->GetPointer (0);
01329  
01330   // Get a pointer to the beginning of the data array
01331   float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
01332 
01333   // If the dataset is dense (no NaNs)
01334   if (cloud->is_dense)
01335   {
01336     for (vtkIdType i = 0; i < nr_points; ++i)
01337     {
01338       memcpy (&data[i * 3], &cloud->points[i].x, 12);    // sizeof (float) * 3
01339       int idx = i * 3;
01340       colors[idx    ] = cloud->points[i].r;
01341       colors[idx + 1] = cloud->points[i].g;
01342       colors[idx + 2] = cloud->points[i].b;
01343     }
01344   }
01345   else
01346   {
01347     vtkIdType j = 0;    // true point index
01348     for (vtkIdType i = 0; i < nr_points; ++i)
01349     {
01350       // Check if the point is invalid
01351       if (!pcl_isfinite (cloud->points[i].x) || 
01352           !pcl_isfinite (cloud->points[i].y) || 
01353           !pcl_isfinite (cloud->points[i].z))
01354         continue;
01355 
01356       memcpy (&data[j * 3], &cloud->points[i].x, 12);    // sizeof (float) * 3
01357       int idx = j * 3;
01358       colors[idx    ] = cloud->points[i].r;
01359       colors[idx + 1] = cloud->points[i].g;
01360       colors[idx + 2] = cloud->points[i].b;
01361       j++;
01362     }
01363     nr_points = j;
01364     points->SetNumberOfPoints (nr_points);
01365     scalars->SetNumberOfTuples (nr_points);
01366   }
01367 
01368   vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
01369   updateCells (cells, am_it->second.cells, nr_points);
01370 
01371   // Set the cells and the vertices
01372   vertices->SetCells (nr_points, cells);
01373 
01374   // Update the mapper
01375   reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata);
01376   return (true);
01377 }*/
01378 
01379 
01380 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines