Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pcl_visualizer.hpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2012, Open Perception, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * $Id: pcl_visualizer.hpp 6220 2012-07-06 22:34:56Z rusu $
37  *
38  */
39 
40 #ifndef PCL_PCL_VISUALIZER_IMPL_H_
41 #define PCL_PCL_VISUALIZER_IMPL_H_
42 
43 #include <vtkCellData.h>
44 #include <vtkSmartPointer.h>
45 #include <vtkCellArray.h>
46 #include <vtkProperty2D.h>
47 #include <vtkMapper2D.h>
48 #include <vtkLeaderActor2D.h>
49 #include <pcl/common/time.h>
50 #include <vtkAlgorithmOutput.h>
51 
53 template <typename PointT> bool
55  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
56  const std::string &id, int viewport)
57 {
58  // Convert the PointCloud to VTK PolyData
59  PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
60  return (addPointCloud<PointT> (cloud, geometry_handler, id, viewport));
61 }
62 
64 template <typename PointT> bool
66  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
67  const PointCloudGeometryHandler<PointT> &geometry_handler,
68  const std::string &id, int viewport)
69 {
70  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
71  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
72 
73  if (am_it != cloud_actor_map_->end ())
74  {
75  PCL_WARN ("[addPointCloud] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
76  return (false);
77  }
78 
79  //PointCloudColorHandlerRandom<PointT> color_handler (cloud);
80  PointCloudColorHandlerCustom<PointT> color_handler (cloud, 255, 255, 255);
81  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
82 }
83 
85 template <typename PointT> bool
87  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
88  const GeometryHandlerConstPtr &geometry_handler,
89  const std::string &id, int viewport)
90 {
91  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
92  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
93 
94  if (am_it != cloud_actor_map_->end ())
95  {
96  // Here we're just pushing the handlers onto the queue. If needed, something fancier could
97  // be done such as checking if a specific handler already exists, etc.
98  am_it->second.geometry_handlers.push_back (geometry_handler);
99  return (true);
100  }
101 
102  //PointCloudColorHandlerRandom<PointT> color_handler (cloud);
103  PointCloudColorHandlerCustom<PointT> color_handler (cloud, 255, 255, 255);
104  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
105 }
106 
108 template <typename PointT> bool
110  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
111  const PointCloudColorHandler<PointT> &color_handler,
112  const std::string &id, int viewport)
113 {
114  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
115  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
116 
117  if (am_it != cloud_actor_map_->end ())
118  {
119  PCL_WARN ("[addPointCloud] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
120 
121  // Here we're just pushing the handlers onto the queue. If needed, something fancier could
122  // be done such as checking if a specific handler already exists, etc.
123  //cloud_actor_map_[id].color_handlers.push_back (color_handler);
124  //style_->setCloudActorMap (boost::make_shared<CloudActorMap> (cloud_actor_map_));
125  return (false);
126  }
127  // Convert the PointCloud to VTK PolyData
128  PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
129  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
130 }
131 
133 template <typename PointT> bool
135  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
136  const ColorHandlerConstPtr &color_handler,
137  const std::string &id, int viewport)
138 {
139  // Check to see if this entry already exists (has it been already added to the visualizer?)
140  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
141  if (am_it != cloud_actor_map_->end ())
142  {
143  // Here we're just pushing the handlers onto the queue. If needed, something fancier could
144  // be done such as checking if a specific handler already exists, etc.
145  am_it->second.color_handlers.push_back (color_handler);
146  return (true);
147  }
148 
149  PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
150  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
151 }
152 
154 template <typename PointT> bool
156  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
157  const GeometryHandlerConstPtr &geometry_handler,
158  const ColorHandlerConstPtr &color_handler,
159  const std::string &id, int viewport)
160 {
161  // Check to see if this entry already exists (has it been already added to the visualizer?)
162  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
163  if (am_it != cloud_actor_map_->end ())
164  {
165  // Here we're just pushing the handlers onto the queue. If needed, something fancier could
166  // be done such as checking if a specific handler already exists, etc.
167  am_it->second.geometry_handlers.push_back (geometry_handler);
168  am_it->second.color_handlers.push_back (color_handler);
169  return (true);
170  }
171  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
172 }
173 
175 template <typename PointT> bool
177  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
178  const PointCloudColorHandler<PointT> &color_handler,
179  const PointCloudGeometryHandler<PointT> &geometry_handler,
180  const std::string &id, int viewport)
181 {
182  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
183  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
184 
185  if (am_it != cloud_actor_map_->end ())
186  {
187  PCL_WARN ("[addPointCloud] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
188  // Here we're just pushing the handlers onto the queue. If needed, something fancier could
189  // be done such as checking if a specific handler already exists, etc.
190  //cloud_actor_map_[id].geometry_handlers.push_back (geometry_handler);
191  //cloud_actor_map_[id].color_handlers.push_back (color_handler);
192  //style_->setCloudActorMap (boost::make_shared<CloudActorMap> (cloud_actor_map_));
193  return (false);
194  }
195  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
196 }
197 
199 template <typename PointT> void
200 pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData (
201  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
202  vtkSmartPointer<vtkPolyData> &polydata,
203  vtkSmartPointer<vtkIdTypeArray> &initcells)
204 {
205  vtkSmartPointer<vtkCellArray> vertices;
206  if (!polydata)
207  {
208  allocVtkPolyData (polydata);
209  vertices = vtkSmartPointer<vtkCellArray>::New ();
210  polydata->SetVerts (vertices);
211  }
212 
213  // Create the supporting structures
214  vertices = polydata->GetVerts ();
215  if (!vertices)
216  vertices = vtkSmartPointer<vtkCellArray>::New ();
217 
218  vtkIdType nr_points = cloud->points.size ();
219  // Create the point set
220  vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
221  if (!points)
222  {
223  points = vtkSmartPointer<vtkPoints>::New ();
224  points->SetDataTypeToFloat ();
225  polydata->SetPoints (points);
226  }
227  points->SetNumberOfPoints (nr_points);
228 
229  // Get a pointer to the beginning of the data array
230  float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
231 
232  // Set the points
233  if (cloud->is_dense)
234  {
235  for (vtkIdType i = 0; i < nr_points; ++i)
236  memcpy (&data[i * 3], &cloud->points[i].x, 12); // sizeof (float) * 3
237  }
238  else
239  {
240  vtkIdType j = 0; // true point index
241  for (vtkIdType i = 0; i < nr_points; ++i)
242  {
243  // Check if the point is invalid
244  if (!pcl_isfinite (cloud->points[i].x) ||
245  !pcl_isfinite (cloud->points[i].y) ||
246  !pcl_isfinite (cloud->points[i].z))
247  continue;
248 
249  memcpy (&data[j * 3], &cloud->points[i].x, 12); // sizeof (float) * 3
250  j++;
251  }
252  nr_points = j;
253  points->SetNumberOfPoints (nr_points);
254  }
255 
256  vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
257  updateCells (cells, initcells, nr_points);
258 
259  // Set the cells and the vertices
260  vertices->SetCells (nr_points, cells);
261 }
262 
264 template <typename PointT> void
265 pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData (
267  vtkSmartPointer<vtkPolyData> &polydata,
268  vtkSmartPointer<vtkIdTypeArray> &initcells)
269 {
270  vtkSmartPointer<vtkCellArray> vertices;
271  if (!polydata)
272  {
273  allocVtkPolyData (polydata);
274  vertices = vtkSmartPointer<vtkCellArray>::New ();
275  polydata->SetVerts (vertices);
276  }
277 
278  // Use the handler to obtain the geometry
279  vtkSmartPointer<vtkPoints> points;
280  geometry_handler.getGeometry (points);
281  polydata->SetPoints (points);
282 
283  vtkIdType nr_points = points->GetNumberOfPoints ();
284 
285  // Create the supporting structures
286  vertices = polydata->GetVerts ();
287  if (!vertices)
288  vertices = vtkSmartPointer<vtkCellArray>::New ();
289 
290  vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
291  updateCells (cells, initcells, nr_points);
292  // Set the cells and the vertices
293  vertices->SetCells (nr_points, cells);
294 }
295 
297 template <typename PointT> bool
299  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
300  double r, double g, double b, const std::string &id, int viewport)
301 {
302  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
303  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
304  if (am_it != shape_actor_map_->end ())
305  {
306  PCL_WARN ("[addPolygon] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
307  return (false);
308  }
309 
310  vtkSmartPointer<vtkDataSet> data = createPolygon<PointT> (cloud);
311 
312  // Create an Actor
313  vtkSmartPointer<vtkLODActor> actor;
314  createActorFromVTKDataSet (data, actor);
315  actor->GetProperty ()->SetRepresentationToWireframe ();
316  actor->GetProperty ()->SetColor (r, g, b);
317  actor->GetMapper ()->ScalarVisibilityOff ();
318  addActorToRenderer (actor, viewport);
319 
320  // Save the pointer/ID pair to the global actor map
321  (*shape_actor_map_)[id] = actor;
322  return (true);
323 }
324 
326 template <typename PointT> bool
328  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
329  const std::string &id, int viewport)
330 {
331  return (!addPolygon<PointT> (cloud, 0.5, 0.5, 0.5, id, viewport));
332  return (false);
333 }
334 
336 template <typename P1, typename P2> bool
337 pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
338 {
339  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
340  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
341  if (am_it != shape_actor_map_->end ())
342  {
343  PCL_WARN ("[addLine] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
344  return (false);
345  }
346 
347  vtkSmartPointer<vtkDataSet> data = createLine (pt1.getVector4fMap (), pt2.getVector4fMap ());
348 
349  // Create an Actor
350  vtkSmartPointer<vtkLODActor> actor;
351  createActorFromVTKDataSet (data, actor);
352  actor->GetProperty ()->SetRepresentationToWireframe ();
353  actor->GetProperty ()->SetColor (r, g, b);
354  actor->GetMapper ()->ScalarVisibilityOff ();
355  addActorToRenderer (actor, viewport);
356 
357  // Save the pointer/ID pair to the global actor map
358  (*shape_actor_map_)[id] = actor;
359  return (true);
360 }
361 
363 template <typename P1, typename P2> bool
364 pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
365 {
366  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
367  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
368  if (am_it != shape_actor_map_->end ())
369  {
370  PCL_WARN ("[addArrow] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
371  return (false);
372  }
373 
374  // Create an Actor
375  vtkSmartPointer<vtkLeaderActor2D> leader = vtkSmartPointer<vtkLeaderActor2D>::New ();
376  leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
377  leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
378  leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
379  leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
380  leader->SetArrowStyleToFilled ();
381  leader->AutoLabelOn ();
382 
383  leader->GetProperty ()->SetColor (r, g, b);
384  addActorToRenderer (leader, viewport);
385 
386  // Save the pointer/ID pair to the global actor map
387  (*shape_actor_map_)[id] = leader;
388  return (true);
389 }
390 
392 template <typename P1, typename P2> bool
393 pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2, double r, double g, double b, bool display_length, const std::string &id, int viewport)
394 {
395  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
396  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
397  if (am_it != shape_actor_map_->end ())
398  {
399  PCL_WARN ("[addArrow] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
400  return (false);
401  }
402 
403  // Create an Actor
404  vtkSmartPointer<vtkLeaderActor2D> leader = vtkSmartPointer<vtkLeaderActor2D>::New ();
405  leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
406  leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
407  leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
408  leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
409  leader->SetArrowStyleToFilled ();
410  leader->SetArrowPlacementToPoint1 ();
411  if (display_length)
412  leader->AutoLabelOn ();
413  else
414  leader->AutoLabelOff ();
415 
416  leader->GetProperty ()->SetColor (r, g, b);
417  addActorToRenderer (leader, viewport);
418 
419  // Save the pointer/ID pair to the global actor map
420  (*shape_actor_map_)[id] = leader;
421  return (true);
422 }
423 
425 template <typename P1, typename P2> bool
426 pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, const std::string &id, int viewport)
427 {
428  return (!addLine (pt1, pt2, 0.5, 0.5, 0.5, id, viewport));
429 }
430 
432 /*template <typename P1, typename P2> bool
433  pcl::visualization::PCLVisualizer::addLineToGroup (const P1 &pt1, const P2 &pt2, const std::string &group_id, int viewport)
434 {
435  vtkSmartPointer<vtkDataSet> data = createLine<P1, P2> (pt1, pt2);
436 
437  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
438  ShapeActorMap::iterator am_it = shape_actor_map_->find (group_id);
439  if (am_it != shape_actor_map_->end ())
440  {
441  // Get the old data
442  vtkPolyDataMapper* mapper = static_cast<vtkPolyDataMapper*>(am_it->second->GetMapper ());
443  vtkPolyData* olddata = static_cast<vtkPolyData*>(mapper->GetInput ());
444  // Add it to the current data
445  vtkSmartPointer<vtkAppendPolyData> alldata = vtkSmartPointer<vtkAppendPolyData>::New ();
446  alldata->AddInput (olddata);
447 
448  // Convert to vtkPolyData
449  vtkSmartPointer<vtkPolyData> curdata = (vtkPolyData::SafeDownCast (data));
450  alldata->AddInput (curdata);
451 
452  mapper->SetInput (alldata->GetOutput ());
453 
454  am_it->second->SetMapper (mapper);
455  am_it->second->Modified ();
456  return (true);
457  }
458 
459  // Create an Actor
460  vtkSmartPointer<vtkLODActor> actor;
461  createActorFromVTKDataSet (data, actor);
462  actor->GetProperty ()->SetRepresentationToWireframe ();
463  actor->GetProperty ()->SetColor (1, 0, 0);
464  addActorToRenderer (actor, viewport);
465 
466  // Save the pointer/ID pair to the global actor map
467  (*shape_actor_map_)[group_id] = actor;
468 
469 //ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
470 //vtkSmartPointer<vtkLODActor> actor = am_it->second;
471  //actor->GetProperty ()->SetColor (r, g, b);
472 //actor->Modified ();
473  return (true);
474 }*/
475 
477 template <typename PointT> bool
478 pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, double r, double g, double b, const std::string &id, int viewport)
479 {
480  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
481  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
482  if (am_it != shape_actor_map_->end ())
483  {
484  PCL_WARN ("[addSphere] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
485  return (false);
486  }
487 
488  //vtkSmartPointer<vtkDataSet> data = createSphere (center.getVector4fMap (), radius);
489  vtkSmartPointer<vtkSphereSource> data = vtkSmartPointer<vtkSphereSource>::New ();
490  data->SetRadius (radius);
491  data->SetCenter (double (center.x), double (center.y), double (center.z));
492  data->SetPhiResolution (10);
493  data->SetThetaResolution (10);
494  data->LatLongTessellationOff ();
495  data->Update ();
496 
497  // Setup actor and mapper
498  vtkSmartPointer <vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New ();
499  mapper->SetInputConnection (data->GetOutputPort ());
500 
501  // Create an Actor
502  vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New ();
503  actor->SetMapper (mapper);
504  //createActorFromVTKDataSet (data, actor);
505  actor->GetProperty ()->SetRepresentationToWireframe ();
506  actor->GetProperty ()->SetInterpolationToGouraud ();
507  actor->GetMapper ()->ScalarVisibilityOff ();
508  actor->GetProperty ()->SetColor (r, g, b);
509  addActorToRenderer (actor, viewport);
510 
511  // Save the pointer/ID pair to the global actor map
512  (*shape_actor_map_)[id] = actor;
513  return (true);
514 }
515 
517 template <typename PointT> bool
518 pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, const std::string &id, int viewport)
519 {
520  return (addSphere (center, radius, 0.5, 0.5, 0.5, id, viewport));
521 }
522 
524 template<typename PointT> bool
525 pcl::visualization::PCLVisualizer::updateSphere (const PointT &center, double radius, double r, double g, double b, const std::string &id)
526 {
527  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
528  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
529  if (am_it == shape_actor_map_->end ())
530  return (false);
531 
533  // Get the actor pointer
534  vtkLODActor* actor = vtkLODActor::SafeDownCast (am_it->second);
535  vtkAlgorithm *algo = actor->GetMapper ()->GetInput ()->GetProducerPort ()->GetProducer ();
536  vtkSphereSource *src = vtkSphereSource::SafeDownCast (algo);
537 
538  src->SetCenter (double (center.x), double (center.y), double (center.z));
539  src->SetRadius (radius);
540  src->Update ();
541  actor->GetProperty ()->SetColor (r, g, b);
542  actor->Modified ();
543 
544  return (true);
545 }
546 
548 template <typename PointT> bool
550  const std::string &text,
551  const PointT& position,
552  double textScale,
553  double r,
554  double g,
555  double b,
556  const std::string &id,
557  int viewport)
558 {
559  std::string tid;
560  if (id.empty ())
561  tid = text;
562  else
563  tid = id;
564 
565  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
566  ShapeActorMap::iterator am_it = shape_actor_map_->find (tid);
567  if (am_it != shape_actor_map_->end ())
568  {
569  pcl::console::print_warn ("[addText3d] A text with id <%s> already exists! Please choose a different id and retry.\n", tid.c_str ());
570  return (false);
571  }
572 
573  vtkSmartPointer<vtkVectorText> textSource = vtkSmartPointer<vtkVectorText>::New ();
574  textSource->SetText (text.c_str());
575  textSource->Update ();
576 
577  vtkSmartPointer<vtkPolyDataMapper> textMapper = vtkSmartPointer<vtkPolyDataMapper>::New ();
578  textMapper->SetInputConnection (textSource->GetOutputPort ());
579 
580  // Since each follower may follow a different camera, we need different followers
581  rens_->InitTraversal ();
582  vtkRenderer* renderer = NULL;
583  int i = 1;
584  while ((renderer = rens_->GetNextItem ()) != NULL)
585  {
586  // Should we add the actor to all renderers or just to i-nth renderer?
587  if (viewport == 0 || viewport == i)
588  {
589  vtkSmartPointer<vtkFollower> textActor = vtkSmartPointer<vtkFollower>::New ();
590  textActor->SetMapper (textMapper);
591  textActor->SetPosition (position.x, position.y, position.z);
592  textActor->SetScale (textScale);
593  textActor->GetProperty ()->SetColor (r, g, b);
594  textActor->SetCamera (renderer->GetActiveCamera ());
595 
596  renderer->AddActor (textActor);
597  renderer->Render ();
598 
599  // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
600  // for multiple viewport
601  std::string alternate_tid = tid;
602  alternate_tid.append(i, '*');
603 
604  (*shape_actor_map_)[(viewport == 0) ? tid : alternate_tid] = textActor;
605  }
606 
607  ++i;
608  }
609 
610  return (true);
611 }
612 
614 template <typename PointNT> bool
616  const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
617  int level, double scale, const std::string &id, int viewport)
618 {
619  return (addPointCloudNormals<PointNT, PointNT>(cloud, cloud, level, scale, id, viewport));
620 }
621 
623 template <typename PointT, typename PointNT> bool
625  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
626  const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
627  int level, double scale,
628  const std::string &id, int viewport)
629 {
630  if (normals->points.size () != cloud->points.size ())
631  {
632  PCL_ERROR ("[addPointCloudNormals] The number of points differs from the number of normals!\n");
633  return (false);
634  }
635  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
636  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
637 
638  if (am_it != cloud_actor_map_->end ())
639  {
640  PCL_WARN ("[addPointCloudNormals] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
641  return (false);
642  }
643 
644  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
645  vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
646 
647  points->SetDataTypeToFloat ();
648  vtkSmartPointer<vtkFloatArray> data = vtkSmartPointer<vtkFloatArray>::New ();
649  data->SetNumberOfComponents (3);
650 
651  vtkIdType nr_normals = (cloud->points.size () - 1) / level + 1 ;
652  float* pts = new float[2 * nr_normals * 3];
653 
654  for (vtkIdType i = 0, j = 0; j < nr_normals; j++, i = j * level)
655  {
656  PointT p = cloud->points[i];
657  p.x += normals->points[i].normal[0] * scale;
658  p.y += normals->points[i].normal[1] * scale;
659  p.z += normals->points[i].normal[2] * scale;
660 
661  pts[2 * j * 3 + 0] = cloud->points[i].x;
662  pts[2 * j * 3 + 1] = cloud->points[i].y;
663  pts[2 * j * 3 + 2] = cloud->points[i].z;
664  pts[2 * j * 3 + 3] = p.x;
665  pts[2 * j * 3 + 4] = p.y;
666  pts[2 * j * 3 + 5] = p.z;
667 
668  lines->InsertNextCell(2);
669  lines->InsertCellPoint(2*j);
670  lines->InsertCellPoint(2*j+1);
671  }
672 
673  data->SetArray (&pts[0], 2 * nr_normals * 3, 0);
674  points->SetData (data);
675 
676  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
677  polyData->SetPoints(points);
678  polyData->SetLines(lines);
679 
680  vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New ();
681  mapper->SetInput (polyData);
682  mapper->SetColorModeToMapScalars();
683  mapper->SetScalarModeToUsePointData();
684 
685  // create actor
686  vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New ();
687  actor->SetMapper (mapper);
688 
689  // Add it to all renderers
690  addActorToRenderer (actor, viewport);
691 
692  // Save the pointer/ID pair to the global actor map
693  (*cloud_actor_map_)[id].actor = actor;
694  return (true);
695 }
696 
698 template <typename PointT> bool
700  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
701  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
702  const std::vector<int> &correspondences,
703  const std::string &id,
704  int viewport)
705 {
706  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
707  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
708  if (am_it != shape_actor_map_->end ())
709  {
710  PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
711  return (false);
712  }
713 
714  vtkSmartPointer<vtkAppendPolyData> polydata = vtkSmartPointer<vtkAppendPolyData>::New ();
715 
716  vtkSmartPointer<vtkUnsignedCharArray> line_colors = vtkSmartPointer<vtkUnsignedCharArray>::New ();
717  line_colors->SetNumberOfComponents (3);
718  line_colors->SetName ("Colors");
719  // Use Red by default (can be changed later)
720  unsigned char rgb[3];
721  rgb[0] = 1 * 255.0;
722  rgb[1] = 0 * 255.0;
723  rgb[2] = 0 * 255.0;
724 
725  // Draw lines between the best corresponding points
726  for (size_t i = 0; i < source_points->size (); ++i)
727  {
728  const PointT &p_src = source_points->points[i];
729  const PointT &p_tgt = target_points->points[correspondences[i]];
730 
731  // Add the line
732  vtkSmartPointer<vtkLineSource> line = vtkSmartPointer<vtkLineSource>::New ();
733  line->SetPoint1 (p_src.x, p_src.y, p_src.z);
734  line->SetPoint2 (p_tgt.x, p_tgt.y, p_tgt.z);
735  line->Update ();
736  polydata->AddInput (line->GetOutput ());
737  line_colors->InsertNextTupleValue (rgb);
738  }
739  polydata->Update ();
740  vtkSmartPointer<vtkPolyData> line_data = polydata->GetOutput ();
741  line_data->GetCellData ()->SetScalars (line_colors);
742 
743  // Create an Actor
744  vtkSmartPointer<vtkLODActor> actor;
745  createActorFromVTKDataSet (line_data, actor);
746  actor->GetProperty ()->SetRepresentationToWireframe ();
747  actor->GetProperty ()->SetOpacity (0.5);
748  addActorToRenderer (actor, viewport);
749 
750  // Save the pointer/ID pair to the global actor map
751  (*shape_actor_map_)[id] = actor;
752 
753  return (true);
754 }
755 
757 template <typename PointT> bool
759  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
760  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
761  const pcl::Correspondences &correspondences,
762  const std::string &id,
763  int viewport)
764 {
765  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
766  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
767  if (am_it != shape_actor_map_->end ())
768  {
769  PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
770  return (false);
771  }
772 
773  vtkSmartPointer<vtkAppendPolyData> polydata = vtkSmartPointer<vtkAppendPolyData>::New ();
774 
775  vtkSmartPointer<vtkUnsignedCharArray> line_colors = vtkSmartPointer<vtkUnsignedCharArray>::New ();
776  line_colors->SetNumberOfComponents (3);
777  line_colors->SetName ("Colors");
778  unsigned char rgb[3];
779  // Use Red by default (can be changed later)
780  rgb[0] = 1 * 255.0;
781  rgb[1] = 0 * 255.0;
782  rgb[2] = 0 * 255.0;
783 
784  // Draw lines between the best corresponding points
785  for (size_t i = 0; i < correspondences.size (); ++i)
786  {
787  const PointT &p_src = source_points->points[correspondences[i].index_query];
788  const PointT &p_tgt = target_points->points[correspondences[i].index_match];
789 
790  // Add the line
791  vtkSmartPointer<vtkLineSource> line = vtkSmartPointer<vtkLineSource>::New ();
792  line->SetPoint1 (p_src.x, p_src.y, p_src.z);
793  line->SetPoint2 (p_tgt.x, p_tgt.y, p_tgt.z);
794  line->Update ();
795  polydata->AddInput (line->GetOutput ());
796  line_colors->InsertNextTupleValue (rgb);
797  }
798  polydata->Update ();
799  vtkSmartPointer<vtkPolyData> line_data = polydata->GetOutput ();
800  line_data->GetCellData ()->SetScalars (line_colors);
801 
802  // Create an Actor
803  vtkSmartPointer<vtkLODActor> actor;
804  createActorFromVTKDataSet (line_data, actor);
805  actor->GetProperty ()->SetRepresentationToWireframe ();
806  actor->GetProperty ()->SetOpacity (0.5);
807  addActorToRenderer (actor, viewport);
808 
809  // Save the pointer/ID pair to the global actor map
810  (*shape_actor_map_)[id] = actor;
811 
812  return (true);
813 }
814 
816 template <typename PointT> bool
817 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
818  const PointCloudGeometryHandler<PointT> &geometry_handler,
819  const PointCloudColorHandler<PointT> &color_handler,
820  const std::string &id,
821  int viewport,
822  const Eigen::Vector4f& sensor_origin,
823  const Eigen::Quaternion<float>& sensor_orientation)
824 {
825  if (!geometry_handler.isCapable ())
826  {
827  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
828  return (false);
829  }
830 
831  if (!color_handler.isCapable ())
832  {
833  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
834  return (false);
835  }
836 
837  vtkSmartPointer<vtkPolyData> polydata;
838  vtkSmartPointer<vtkIdTypeArray> initcells;
839  // Convert the PointCloud to VTK PolyData
840  convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
841  // use the given geometry handler
842  polydata->Update ();
843 
844  // Get the colors from the handler
845  vtkSmartPointer<vtkDataArray> scalars;
846  color_handler.getColor (scalars);
847  polydata->GetPointData ()->SetScalars (scalars);
848  double minmax[2];
849  scalars->GetRange (minmax);
850 
851  // Create an Actor
852  vtkSmartPointer<vtkLODActor> actor;
853  createActorFromVTKDataSet (polydata, actor);
854  actor->GetMapper ()->SetScalarRange (minmax);
855 
856  // Add it to all renderers
857  addActorToRenderer (actor, viewport);
858 
859  // Save the pointer/ID pair to the global actor map
860  (*cloud_actor_map_)[id].actor = actor;
861  (*cloud_actor_map_)[id].cells = initcells;
862 
863  // Save the viewpoint transformation matrix to the global actor map
864  vtkSmartPointer<vtkMatrix4x4> transformation = vtkSmartPointer<vtkMatrix4x4>::New();
865  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
866  (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
867 
868  return (true);
869 }
870 
872 template <typename PointT> bool
873 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
874  const PointCloudGeometryHandler<PointT> &geometry_handler,
875  const ColorHandlerConstPtr &color_handler,
876  const std::string &id,
877  int viewport,
878  const Eigen::Vector4f& sensor_origin,
879  const Eigen::Quaternion<float>& sensor_orientation)
880 {
881  if (!geometry_handler.isCapable ())
882  {
883  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
884  return (false);
885  }
886 
887  if (!color_handler->isCapable ())
888  {
889  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler->getName ().c_str ());
890  return (false);
891  }
892 
893  vtkSmartPointer<vtkPolyData> polydata;
894  vtkSmartPointer<vtkIdTypeArray> initcells;
895  // Convert the PointCloud to VTK PolyData
896  convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
897  // use the given geometry handler
898  polydata->Update ();
899 
900  // Get the colors from the handler
901  vtkSmartPointer<vtkDataArray> scalars;
902  color_handler->getColor (scalars);
903  polydata->GetPointData ()->SetScalars (scalars);
904  double minmax[2];
905  scalars->GetRange (minmax);
906 
907  // Create an Actor
908  vtkSmartPointer<vtkLODActor> actor;
909  createActorFromVTKDataSet (polydata, actor);
910  actor->GetMapper ()->SetScalarRange (minmax);
911 
912  // Add it to all renderers
913  addActorToRenderer (actor, viewport);
914 
915  // Save the pointer/ID pair to the global actor map
916  (*cloud_actor_map_)[id].actor = actor;
917  (*cloud_actor_map_)[id].cells = initcells;
918  (*cloud_actor_map_)[id].color_handlers.push_back (color_handler);
919 
920  // Save the viewpoint transformation matrix to the global actor map
921  // Save the viewpoint transformation matrix to the global actor map
922  vtkSmartPointer<vtkMatrix4x4> transformation = vtkSmartPointer<vtkMatrix4x4>::New();
923  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
924  (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
925 
926  return (true);
927 }
928 
930 template <typename PointT> bool
931 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
932  const GeometryHandlerConstPtr &geometry_handler,
933  const PointCloudColorHandler<PointT> &color_handler,
934  const std::string &id,
935  int viewport,
936  const Eigen::Vector4f& sensor_origin,
937  const Eigen::Quaternion<float>& sensor_orientation)
938 {
939  if (!geometry_handler->isCapable ())
940  {
941  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler->getName ().c_str ());
942  return (false);
943  }
944 
945  if (!color_handler.isCapable ())
946  {
947  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
948  return (false);
949  }
950 
951  vtkSmartPointer<vtkPolyData> polydata;
952  vtkSmartPointer<vtkIdTypeArray> initcells;
953  // Convert the PointCloud to VTK PolyData
954  convertPointCloudToVTKPolyData (geometry_handler, polydata, initcells);
955  // use the given geometry handler
956  polydata->Update ();
957 
958  // Get the colors from the handler
959  vtkSmartPointer<vtkDataArray> scalars;
960  color_handler.getColor (scalars);
961  polydata->GetPointData ()->SetScalars (scalars);
962  double minmax[2];
963  scalars->GetRange (minmax);
964 
965  // Create an Actor
966  vtkSmartPointer<vtkLODActor> actor;
967  createActorFromVTKDataSet (polydata, actor);
968  actor->GetMapper ()->SetScalarRange (minmax);
969 
970  // Add it to all renderers
971  addActorToRenderer (actor, viewport);
972 
973  // Save the pointer/ID pair to the global actor map
974  (*cloud_actor_map_)[id].actor = actor;
975  (*cloud_actor_map_)[id].cells = initcells;
976  (*cloud_actor_map_)[id].geometry_handlers.push_back (geometry_handler);
977 
978  // Save the viewpoint transformation matrix to the global actor map
979  vtkSmartPointer<vtkMatrix4x4> transformation = vtkSmartPointer<vtkMatrix4x4>::New();
980  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
981  (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
982 
983  return (true);
984 }
985 
987 template <typename PointT> bool
989  const std::string &id)
990 {
991  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
992  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
993 
994  if (am_it == cloud_actor_map_->end ())
995  return (false);
996 
997  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
998  // Convert the PointCloud to VTK PolyData
999  convertPointCloudToVTKPolyData<PointT> (cloud, polydata, am_it->second.cells);
1000  polydata->Update ();
1001 
1002  // Set scalars to blank, since there is no way we can update them here.
1003  vtkSmartPointer<vtkDataArray> scalars;
1004  polydata->GetPointData ()->SetScalars (scalars);
1005  polydata->Update ();
1006  double minmax[2];
1007  minmax[0] = std::numeric_limits<double>::min ();
1008  minmax[1] = std::numeric_limits<double>::max ();
1009  am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
1010  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1011 
1012  // Update the mapper
1013  reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata);
1014  return (true);
1015 }
1016 
1018 template <typename PointT> bool
1020  const PointCloudGeometryHandler<PointT> &geometry_handler,
1021  const std::string &id)
1022 {
1023  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1024  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1025 
1026  if (am_it == cloud_actor_map_->end ())
1027  return (false);
1028 
1029  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1030  if (!polydata)
1031  return (false);
1032  // Convert the PointCloud to VTK PolyData
1033  convertPointCloudToVTKPolyData (geometry_handler, polydata, am_it->second.cells);
1034 
1035  // Set scalars to blank, since there is no way we can update them here.
1036  vtkSmartPointer<vtkDataArray> scalars;
1037  polydata->GetPointData ()->SetScalars (scalars);
1038  polydata->Update ();
1039  double minmax[2];
1040  minmax[0] = std::numeric_limits<double>::min ();
1041  minmax[1] = std::numeric_limits<double>::max ();
1042  am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
1043  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1044 
1045  // Update the mapper
1046  reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata);
1047  return (true);
1048 }
1049 
1050 
1052 template <typename PointT> bool
1054  const PointCloudColorHandler<PointT> &color_handler,
1055  const std::string &id)
1056 {
1057  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1058  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1059 
1060  if (am_it == cloud_actor_map_->end ())
1061  return (false);
1062 
1063  // Get the current poly data
1064  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1065  if (!polydata)
1066  return (false);
1067  vtkSmartPointer<vtkCellArray> vertices = polydata->GetVerts ();
1068  vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
1069  // Copy the new point array in
1070  vtkIdType nr_points = cloud->points.size ();
1071  points->SetNumberOfPoints (nr_points);
1072 
1073  // Get a pointer to the beginning of the data array
1074  float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
1075 
1076  int pts = 0;
1077  // If the dataset is dense (no NaNs)
1078  if (cloud->is_dense)
1079  {
1080  for (vtkIdType i = 0; i < nr_points; ++i, pts += 3)
1081  memcpy (&data[pts], &cloud->points[i].x, 12); // sizeof (float) * 3
1082  }
1083  else
1084  {
1085  vtkIdType j = 0; // true point index
1086  for (vtkIdType i = 0; i < nr_points; ++i)
1087  {
1088  // Check if the point is invalid
1089  if (!isFinite (cloud->points[i]))
1090  continue;
1091 
1092  memcpy (&data[pts], &cloud->points[i].x, 12); // sizeof (float) * 3
1093  pts += 3;
1094  j++;
1095  }
1096  nr_points = j;
1097  points->SetNumberOfPoints (nr_points);
1098  }
1099 
1100  vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
1101  updateCells (cells, am_it->second.cells, nr_points);
1102 
1103  // Set the cells and the vertices
1104  vertices->SetCells (nr_points, cells);
1105 
1106  // Get the colors from the handler
1107  vtkSmartPointer<vtkDataArray> scalars;
1108  color_handler.getColor (scalars);
1109  double minmax[2];
1110  scalars->GetRange (minmax);
1111  // Update the data
1112  polydata->GetPointData ()->SetScalars (scalars);
1113  polydata->Update ();
1114 
1115  am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
1116  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1117 
1118  // Update the mapper
1119  reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata);
1120  return (true);
1121 }
1122 
1124 template <typename PointT> bool
1126  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1127  const std::vector<pcl::Vertices> &vertices,
1128  const std::string &id,
1129  int viewport)
1130 {
1131  if (vertices.empty () || cloud->points.empty ())
1132  return (false);
1133 
1134  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1135  if (am_it != cloud_actor_map_->end ())
1136  {
1138  "[addPolygonMesh] A shape with id <%s> already exists! Please choose a different id and retry.\n",
1139  id.c_str ());
1140  return (false);
1141  }
1142 
1143  // Create points from polyMesh.cloud
1144  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New ();
1145  vtkIdType nr_points = cloud->points.size ();
1146  points->SetNumberOfPoints (nr_points);
1147  vtkSmartPointer<vtkLODActor> actor;
1148 
1149  // Get a pointer to the beginning of the data array
1150  float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
1151 
1152  int ptr = 0;
1153  std::vector<int> lookup;
1154  // If the dataset is dense (no NaNs)
1155  if (cloud->is_dense)
1156  {
1157  for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
1158  memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
1159  }
1160  else
1161  {
1162  lookup.resize (nr_points);
1163  vtkIdType j = 0; // true point index
1164  for (vtkIdType i = 0; i < nr_points; ++i)
1165  {
1166  // Check if the point is invalid
1167  if (!isFinite (cloud->points[i]))
1168  continue;
1169 
1170  lookup[i] = j;
1171  memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
1172  j++;
1173  ptr += 3;
1174  }
1175  nr_points = j;
1176  points->SetNumberOfPoints (nr_points);
1177  }
1178 
1179  // Get the maximum size of a polygon
1180  int max_size_of_polygon = -1;
1181  for (size_t i = 0; i < vertices.size (); ++i)
1182  if (max_size_of_polygon < (int)vertices[i].vertices.size ())
1183  max_size_of_polygon = vertices[i].vertices.size ();
1184 
1185  if (vertices.size () > 1)
1186  {
1187  // Create polys from polyMesh.polygons
1188  vtkSmartPointer<vtkCellArray> cell_array = vtkSmartPointer<vtkCellArray>::New ();
1189  vtkIdType *cell = cell_array->WritePointer (vertices.size (), vertices.size () * (max_size_of_polygon + 1));
1190  int idx = 0;
1191  if (lookup.size () > 0)
1192  {
1193  for (size_t i = 0; i < vertices.size (); ++i, ++idx)
1194  {
1195  size_t n_points = vertices[i].vertices.size ();
1196  *cell++ = n_points;
1197  //cell_array->InsertNextCell (n_points);
1198  for (size_t j = 0; j < n_points; j++, ++idx)
1199  *cell++ = lookup[vertices[i].vertices[j]];
1200  //cell_array->InsertCellPoint (lookup[vertices[i].vertices[j]]);
1201  }
1202  }
1203  else
1204  {
1205  for (size_t i = 0; i < vertices.size (); ++i, ++idx)
1206  {
1207  size_t n_points = vertices[i].vertices.size ();
1208  *cell++ = n_points;
1209  //cell_array->InsertNextCell (n_points);
1210  for (size_t j = 0; j < n_points; j++, ++idx)
1211  *cell++ = vertices[i].vertices[j];
1212  //cell_array->InsertCellPoint (vertices[i].vertices[j]);
1213  }
1214  }
1215  vtkSmartPointer<vtkPolyData> polydata;
1216  allocVtkPolyData (polydata);
1217  cell_array->GetData ()->SetNumberOfValues (idx);
1218  cell_array->Squeeze ();
1219  polydata->SetStrips (cell_array);
1220  polydata->SetPoints (points);
1221 
1222  createActorFromVTKDataSet (polydata, actor, false);
1223  }
1224  else
1225  {
1226  vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New ();
1227  size_t n_points = vertices[0].vertices.size ();
1228  polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
1229 
1230  if (lookup.size () > 0)
1231  {
1232  for (size_t j = 0; j < (n_points - 1); ++j)
1233  polygon->GetPointIds ()->SetId (j, lookup[vertices[0].vertices[j]]);
1234  }
1235  else
1236  {
1237  for (size_t j = 0; j < (n_points - 1); ++j)
1238  polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
1239  }
1240  vtkSmartPointer<vtkUnstructuredGrid> poly_grid;
1241  allocVtkUnstructuredGrid (poly_grid);
1242  poly_grid->Allocate (1, 1);
1243  poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
1244  poly_grid->SetPoints (points);
1245  poly_grid->Update ();
1246 
1247  createActorFromVTKDataSet (poly_grid, actor, false);
1248  }
1249  actor->GetProperty ()->SetRepresentationToSurface ();
1250  actor->GetProperty ()->BackfaceCullingOn ();
1251  actor->GetProperty ()->EdgeVisibilityOff ();
1252  actor->GetProperty ()->ShadingOff ();
1253  addActorToRenderer (actor, viewport);
1254 
1255  // Save the pointer/ID pair to the global actor map
1256  (*cloud_actor_map_)[id].actor = actor;
1257  //if (vertices.size () > 1)
1258  // (*cloud_actor_map_)[id].cells = static_cast<vtkPolyDataMapper*>(actor->GetMapper ())->GetInput ()->GetVerts ()->GetData ();
1259  return (true);
1260 }
1261 
1263 template <typename PointT> bool
1265  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1266  const std::vector<pcl::Vertices> &verts,
1267  const std::string &id)
1268 {
1269  if (verts.empty ())
1270  {
1271  pcl::console::print_error ("[addPolygonMesh] No vertices given!\n");
1272  return (false);
1273  }
1274 
1275  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1276  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1277  if (am_it == cloud_actor_map_->end ())
1278  return (false);
1279 
1280  // Get the current poly data
1281  vtkSmartPointer<vtkPolyData> polydata = static_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1282  if (!polydata)
1283  return (false);
1284  vtkSmartPointer<vtkCellArray> cells = polydata->GetStrips ();
1285  if (!cells)
1286  return (false);
1287  vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
1288  // Copy the new point array in
1289  vtkIdType nr_points = cloud->points.size ();
1290  points->SetNumberOfPoints (nr_points);
1291 
1292  // Get a pointer to the beginning of the data array
1293  float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
1294 
1295  int ptr = 0;
1296  std::vector<int> lookup;
1297  // If the dataset is dense (no NaNs)
1298  if (cloud->is_dense)
1299  {
1300  for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
1301  memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
1302  }
1303  else
1304  {
1305  lookup.resize (nr_points);
1306  vtkIdType j = 0; // true point index
1307  for (vtkIdType i = 0; i < nr_points; ++i)
1308  {
1309  // Check if the point is invalid
1310  if (!isFinite (cloud->points[i]))
1311  continue;
1312 
1313  lookup [i] = j;
1314  memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
1315  j++;
1316  ptr += 3;
1317  }
1318  nr_points = j;
1319  points->SetNumberOfPoints (nr_points);
1320  }
1321 
1322  // Get the maximum size of a polygon
1323  int max_size_of_polygon = -1;
1324  for (size_t i = 0; i < verts.size (); ++i)
1325  if (max_size_of_polygon < (int)verts[i].vertices.size ())
1326  max_size_of_polygon = verts[i].vertices.size ();
1327 
1328  // Update the cells
1329  cells = vtkSmartPointer<vtkCellArray>::New ();
1330  vtkIdType *cell = cells->WritePointer (verts.size (), verts.size () * (max_size_of_polygon + 1));
1331  int idx = 0;
1332  if (lookup.size () > 0)
1333  {
1334  for (size_t i = 0; i < verts.size (); ++i, ++idx)
1335  {
1336  size_t n_points = verts[i].vertices.size ();
1337  *cell++ = n_points;
1338  for (size_t j = 0; j < n_points; j++, cell++, ++idx)
1339  *cell = lookup[verts[i].vertices[j]];
1340  }
1341  }
1342  else
1343  {
1344  for (size_t i = 0; i < verts.size (); ++i, ++idx)
1345  {
1346  size_t n_points = verts[i].vertices.size ();
1347  *cell++ = n_points;
1348  for (size_t j = 0; j < n_points; j++, cell++, ++idx)
1349  *cell = verts[i].vertices[j];
1350  }
1351  }
1352  cells->GetData ()->SetNumberOfValues (idx);
1353  cells->Squeeze ();
1354  // Set the the vertices
1355  polydata->SetStrips (cells);
1356  polydata->Update ();
1357 
1358 /*
1359  vtkSmartPointer<vtkLODActor> actor;
1360  if (vertices.size () > 1)
1361  {
1362  }
1363  else
1364  {
1365  vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New ();
1366  size_t n_points = vertices[0].vertices.size ();
1367  polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
1368 
1369  for (size_t j = 0; j < (n_points - 1); ++j)
1370  polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
1371 
1372  vtkSmartPointer<vtkUnstructuredGrid> poly_grid;
1373  allocVtkUnstructuredGrid (poly_grid);
1374  poly_grid->Allocate (1, 1);
1375  poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
1376  poly_grid->SetPoints (points);
1377  poly_grid->Update ();
1378 
1379  createActorFromVTKDataSet (poly_grid, actor);
1380  }
1381 */
1382 
1383  // Get the colors from the handler
1384  //vtkSmartPointer<vtkDataArray> scalars;
1385  //color_handler.getColor (scalars);
1386  //polydata->GetPointData ()->SetScalars (scalars);
1387 // polydata->Update ();
1388 
1389  am_it->second.actor->GetProperty ()->BackfaceCullingOn ();
1390 // am_it->second.actor->Modified ();
1391 
1392  return (true);
1393 }
1394 
1395 
1397 /* Optimized function: need to do something with the signature as it colides with the general T one
1398 bool
1399 pcl::visualization::PCLVisualizer::updatePointCloud (const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr &cloud,
1400  const PointCloudColorHandlerRGBField<pcl::PointXYZRGB> &color_handler,
1401  const std::string &id)
1402 {
1403  win_->SetAbortRender (1);
1404  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1405  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1406 
1407  if (am_it == cloud_actor_map_->end ())
1408  return (false);
1409 
1410  // Get the current poly data
1411  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1412  if (!polydata)
1413  return (false);
1414  vtkSmartPointer<vtkCellArray> vertices = polydata->GetVerts ();
1415  vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
1416 // vtkUnsignedCharArray* scalars = vtkUnsignedCharArray::SafeDownCast (polydata->GetPointData ()->GetScalars ());
1417  vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New ();
1418  // Copy the new point array in
1419  vtkIdType nr_points = cloud->points.size ();
1420  points->SetNumberOfPoints (nr_points);
1421  scalars->SetNumberOfComponents (3);
1422  scalars->SetNumberOfTuples (nr_points);
1423  polydata->GetPointData ()->SetScalars (scalars);
1424  unsigned char* colors = scalars->GetPointer (0);
1425 
1426  // Get a pointer to the beginning of the data array
1427  float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0);
1428 
1429  // If the dataset is dense (no NaNs)
1430  if (cloud->is_dense)
1431  {
1432  for (vtkIdType i = 0; i < nr_points; ++i)
1433  {
1434  memcpy (&data[i * 3], &cloud->points[i].x, 12); // sizeof (float) * 3
1435  int idx = i * 3;
1436  colors[idx ] = cloud->points[i].r;
1437  colors[idx + 1] = cloud->points[i].g;
1438  colors[idx + 2] = cloud->points[i].b;
1439  }
1440  }
1441  else
1442  {
1443  vtkIdType j = 0; // true point index
1444  for (vtkIdType i = 0; i < nr_points; ++i)
1445  {
1446  // Check if the point is invalid
1447  if (!pcl_isfinite (cloud->points[i].x) ||
1448  !pcl_isfinite (cloud->points[i].y) ||
1449  !pcl_isfinite (cloud->points[i].z))
1450  continue;
1451 
1452  memcpy (&data[j * 3], &cloud->points[i].x, 12); // sizeof (float) * 3
1453  int idx = j * 3;
1454  colors[idx ] = cloud->points[i].r;
1455  colors[idx + 1] = cloud->points[i].g;
1456  colors[idx + 2] = cloud->points[i].b;
1457  j++;
1458  }
1459  nr_points = j;
1460  points->SetNumberOfPoints (nr_points);
1461  scalars->SetNumberOfTuples (nr_points);
1462  }
1463 
1464  vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
1465  updateCells (cells, am_it->second.cells, nr_points);
1466 
1467  // Set the cells and the vertices
1468  vertices->SetCells (nr_points, cells);
1469 
1470  // Update the mapper
1471  reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata);
1472  return (true);
1473 }*/
1474 
1475 
1476 #endif