Point Cloud Library (PCL)  1.7.0
pcl_visualizer.hpp
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 the copyright holder(s) 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  */
37 
38 #ifndef PCL_PCL_VISUALIZER_IMPL_H_
39 #define PCL_PCL_VISUALIZER_IMPL_H_
40 
41 #include <vtkSmartPointer.h>
42 #include <vtkCellArray.h>
43 #include <vtkLeaderActor2D.h>
44 #include <vtkVectorText.h>
45 #include <vtkAlgorithmOutput.h>
46 #include <vtkFollower.h>
47 #include <vtkSphereSource.h>
48 #include <vtkProperty2D.h>
49 #include <vtkDataSetSurfaceFilter.h>
50 #include <vtkPointData.h>
51 #include <vtkPolyDataMapper.h>
52 #include <vtkProperty.h>
53 #include <vtkMapper.h>
54 #include <vtkCellData.h>
55 #include <vtkDataSetMapper.h>
56 #include <vtkRenderer.h>
57 #include <vtkRendererCollection.h>
58 #include <vtkAppendPolyData.h>
59 #include <vtkTextProperty.h>
60 #include <vtkLODActor.h>
61 
62 #include <pcl/visualization/common/shapes.h>
63 
64 //////////////////////////////////////////////////////////////////////////////////////////////
65 template <typename PointT> bool
67  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
68  const std::string &id, int viewport)
69 {
70  // Convert the PointCloud to VTK PolyData
71  PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
72  return (addPointCloud<PointT> (cloud, geometry_handler, id, viewport));
73 }
74 
75 //////////////////////////////////////////////////////////////////////////////////////////////
76 template <typename PointT> bool
78  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
79  const PointCloudGeometryHandler<PointT> &geometry_handler,
80  const std::string &id, int viewport)
81 {
82  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
83  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
84 
85  if (am_it != cloud_actor_map_->end ())
86  {
87  PCL_WARN ("[addPointCloud] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
88  return (false);
89  }
90 
91  //PointCloudColorHandlerRandom<PointT> color_handler (cloud);
92  PointCloudColorHandlerCustom<PointT> color_handler (cloud, 255, 255, 255);
93  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
94 }
95 
96 //////////////////////////////////////////////////////////////////////////////////////////////
97 template <typename PointT> bool
99  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
100  const GeometryHandlerConstPtr &geometry_handler,
101  const std::string &id, int viewport)
102 {
103  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
104  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
105 
106  if (am_it != cloud_actor_map_->end ())
107  {
108  // Here we're just pushing the handlers onto the queue. If needed, something fancier could
109  // be done such as checking if a specific handler already exists, etc.
110  am_it->second.geometry_handlers.push_back (geometry_handler);
111  return (true);
112  }
113 
114  //PointCloudColorHandlerRandom<PointT> color_handler (cloud);
115  PointCloudColorHandlerCustom<PointT> color_handler (cloud, 255, 255, 255);
116  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
117 }
118 
119 //////////////////////////////////////////////////////////////////////////////////////////////
120 template <typename PointT> bool
122  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
123  const PointCloudColorHandler<PointT> &color_handler,
124  const std::string &id, int viewport)
125 {
126  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
127  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
128 
129  if (am_it != cloud_actor_map_->end ())
130  {
131  PCL_WARN ("[addPointCloud] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
132 
133  // Here we're just pushing the handlers onto the queue. If needed, something fancier could
134  // be done such as checking if a specific handler already exists, etc.
135  //cloud_actor_map_[id].color_handlers.push_back (color_handler);
136  //style_->setCloudActorMap (boost::make_shared<CloudActorMap> (cloud_actor_map_));
137  return (false);
138  }
139  // Convert the PointCloud to VTK PolyData
140  PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
141  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
142 }
143 
144 //////////////////////////////////////////////////////////////////////////////////////////////
145 template <typename PointT> bool
147  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
148  const ColorHandlerConstPtr &color_handler,
149  const std::string &id, int viewport)
150 {
151  // Check to see if this entry already exists (has it been already added to the visualizer?)
152  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
153  if (am_it != cloud_actor_map_->end ())
154  {
155  // Here we're just pushing the handlers onto the queue. If needed, something fancier could
156  // be done such as checking if a specific handler already exists, etc.
157  am_it->second.color_handlers.push_back (color_handler);
158  return (true);
159  }
160 
161  PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
162  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
163 }
164 
165 //////////////////////////////////////////////////////////////////////////////////////////////
166 template <typename PointT> bool
168  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
169  const GeometryHandlerConstPtr &geometry_handler,
170  const ColorHandlerConstPtr &color_handler,
171  const std::string &id, int viewport)
172 {
173  // Check to see if this entry already exists (has it been already added to the visualizer?)
174  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
175  if (am_it != cloud_actor_map_->end ())
176  {
177  // Here we're just pushing the handlers onto the queue. If needed, something fancier could
178  // be done such as checking if a specific handler already exists, etc.
179  am_it->second.geometry_handlers.push_back (geometry_handler);
180  am_it->second.color_handlers.push_back (color_handler);
181  return (true);
182  }
183  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
184 }
185 
186 //////////////////////////////////////////////////////////////////////////////////////////////
187 template <typename PointT> bool
189  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
190  const PointCloudColorHandler<PointT> &color_handler,
191  const PointCloudGeometryHandler<PointT> &geometry_handler,
192  const std::string &id, int viewport)
193 {
194  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
195  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
196 
197  if (am_it != cloud_actor_map_->end ())
198  {
199  PCL_WARN ("[addPointCloud] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
200  // Here we're just pushing the handlers onto the queue. If needed, something fancier could
201  // be done such as checking if a specific handler already exists, etc.
202  //cloud_actor_map_[id].geometry_handlers.push_back (geometry_handler);
203  //cloud_actor_map_[id].color_handlers.push_back (color_handler);
204  //style_->setCloudActorMap (boost::make_shared<CloudActorMap> (cloud_actor_map_));
205  return (false);
206  }
207  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
208 }
209 
210 //////////////////////////////////////////////////////////////////////////////////////////////
211 template <typename PointT> void
212 pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData (
213  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
216 {
218  if (!polydata)
219  {
220  allocVtkPolyData (polydata);
222  polydata->SetVerts (vertices);
223  }
224 
225  // Create the supporting structures
226  vertices = polydata->GetVerts ();
227  if (!vertices)
229 
230  vtkIdType nr_points = cloud->points.size ();
231  // Create the point set
232  vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
233  if (!points)
234  {
236  points->SetDataTypeToFloat ();
237  polydata->SetPoints (points);
238  }
239  points->SetNumberOfPoints (nr_points);
240 
241  // Get a pointer to the beginning of the data array
242  float *data = (static_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
243 
244  // Set the points
245  if (cloud->is_dense)
246  {
247  for (vtkIdType i = 0; i < nr_points; ++i)
248  memcpy (&data[i * 3], &cloud->points[i].x, 12); // sizeof (float) * 3
249  }
250  else
251  {
252  vtkIdType j = 0; // true point index
253  for (vtkIdType i = 0; i < nr_points; ++i)
254  {
255  // Check if the point is invalid
256  if (!pcl_isfinite (cloud->points[i].x) ||
257  !pcl_isfinite (cloud->points[i].y) ||
258  !pcl_isfinite (cloud->points[i].z))
259  continue;
260 
261  memcpy (&data[j * 3], &cloud->points[i].x, 12); // sizeof (float) * 3
262  j++;
263  }
264  nr_points = j;
265  points->SetNumberOfPoints (nr_points);
266  }
267 
268  vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
269  updateCells (cells, initcells, nr_points);
270 
271  // Set the cells and the vertices
272  vertices->SetCells (nr_points, cells);
273 }
274 
275 //////////////////////////////////////////////////////////////////////////////////////////////
276 template <typename PointT> void
277 pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData (
281 {
283  if (!polydata)
284  {
285  allocVtkPolyData (polydata);
287  polydata->SetVerts (vertices);
288  }
289 
290  // Use the handler to obtain the geometry
292  geometry_handler.getGeometry (points);
293  polydata->SetPoints (points);
294 
295  vtkIdType nr_points = points->GetNumberOfPoints ();
296 
297  // Create the supporting structures
298  vertices = polydata->GetVerts ();
299  if (!vertices)
301 
302  vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
303  updateCells (cells, initcells, nr_points);
304  // Set the cells and the vertices
305  vertices->SetCells (nr_points, cells);
306 }
307 
308 ////////////////////////////////////////////////////////////////////////////////////////////
309 template <typename PointT> bool
311  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
312  double r, double g, double b, const std::string &id, int viewport)
313 {
314  vtkSmartPointer<vtkDataSet> data = createPolygon<PointT> (cloud);
315  if (!data)
316  return (false);
317 
318  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
319  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
320  if (am_it != shape_actor_map_->end ())
321  {
323 
324  // Add old data
325  all_data->AddInputData (reinterpret_cast<vtkPolyDataMapper*> ((vtkActor::SafeDownCast (am_it->second))->GetMapper ())->GetInput ());
326 
327  // Add new data
329  surface_filter->SetInputData (vtkUnstructuredGrid::SafeDownCast (data));
330  vtkSmartPointer<vtkPolyData> poly_data = surface_filter->GetOutput ();
331  all_data->AddInputData (poly_data);
332 
333  // Create an Actor
335  createActorFromVTKDataSet (all_data->GetOutput (), actor);
336  actor->GetProperty ()->SetRepresentationToWireframe ();
337  actor->GetProperty ()->SetColor (r, g, b);
338  actor->GetMapper ()->ScalarVisibilityOff ();
339  removeActorFromRenderer (am_it->second, viewport);
340  addActorToRenderer (actor, viewport);
341 
342  // Save the pointer/ID pair to the global actor map
343  (*shape_actor_map_)[id] = actor;
344  }
345  else
346  {
347  // Create an Actor
349  createActorFromVTKDataSet (data, actor);
350  actor->GetProperty ()->SetRepresentationToWireframe ();
351  actor->GetProperty ()->SetColor (r, g, b);
352  actor->GetMapper ()->ScalarVisibilityOff ();
353  addActorToRenderer (actor, viewport);
354 
355  // Save the pointer/ID pair to the global actor map
356  (*shape_actor_map_)[id] = actor;
357  }
358 
359  return (true);
360 }
361 
362 ////////////////////////////////////////////////////////////////////////////////////////////
363 template <typename PointT> bool
365  const pcl::PlanarPolygon<PointT> &polygon,
366  double r, double g, double b, const std::string &id, int viewport)
367 {
368  vtkSmartPointer<vtkDataSet> data = createPolygon<PointT> (polygon);
369  if (!data)
370  return (false);
371 
372  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
373  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
374  if (am_it != shape_actor_map_->end ())
375  {
377 
378  // Add old data
379  all_data->AddInputData (reinterpret_cast<vtkPolyDataMapper*> ((vtkActor::SafeDownCast (am_it->second))->GetMapper ())->GetInput ());
380 
381  // Add new data
383  surface_filter->SetInputData (vtkUnstructuredGrid::SafeDownCast (data));
384  vtkSmartPointer<vtkPolyData> poly_data = surface_filter->GetOutput ();
385  all_data->AddInputData (poly_data);
386 
387  // Create an Actor
389  createActorFromVTKDataSet (all_data->GetOutput (), actor);
390  actor->GetProperty ()->SetRepresentationToWireframe ();
391  actor->GetProperty ()->SetColor (r, g, b);
392  actor->GetMapper ()->ScalarVisibilityOn ();
393  actor->GetProperty ()->BackfaceCullingOff ();
394  removeActorFromRenderer (am_it->second, viewport);
395  addActorToRenderer (actor, viewport);
396 
397  // Save the pointer/ID pair to the global actor map
398  (*shape_actor_map_)[id] = actor;
399  }
400  else
401  {
402  // Create an Actor
404  createActorFromVTKDataSet (data, actor);
405  actor->GetProperty ()->SetRepresentationToWireframe ();
406  actor->GetProperty ()->SetColor (r, g, b);
407  actor->GetMapper ()->ScalarVisibilityOn ();
408  actor->GetProperty ()->BackfaceCullingOff ();
409  addActorToRenderer (actor, viewport);
410 
411  // Save the pointer/ID pair to the global actor map
412  (*shape_actor_map_)[id] = actor;
413  }
414  return (true);
415 }
416 
417 ////////////////////////////////////////////////////////////////////////////////////////////
418 template <typename PointT> bool
420  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
421  const std::string &id, int viewport)
422 {
423  return (!addPolygon<PointT> (cloud, 0.5, 0.5, 0.5, id, viewport));
424 }
425 
426 ////////////////////////////////////////////////////////////////////////////////////////////
427 template <typename P1, typename P2> bool
428 pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
429 {
430  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
431  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
432  if (am_it != shape_actor_map_->end ())
433  {
434  PCL_WARN ("[addLine] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
435  return (false);
436  }
437 
438  vtkSmartPointer<vtkDataSet> data = createLine (pt1.getVector4fMap (), pt2.getVector4fMap ());
439 
440  // Create an Actor
442  createActorFromVTKDataSet (data, actor);
443  actor->GetProperty ()->SetRepresentationToWireframe ();
444  actor->GetProperty ()->SetColor (r, g, b);
445  actor->GetMapper ()->ScalarVisibilityOff ();
446  addActorToRenderer (actor, viewport);
447 
448  // Save the pointer/ID pair to the global actor map
449  (*shape_actor_map_)[id] = actor;
450  return (true);
451 }
452 
453 ////////////////////////////////////////////////////////////////////////////////////////////
454 template <typename P1, typename P2> bool
455 pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
456 {
457  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
458  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
459  if (am_it != shape_actor_map_->end ())
460  {
461  PCL_WARN ("[addArrow] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
462  return (false);
463  }
464 
465  // Create an Actor
467  leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
468  leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
469  leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
470  leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
471  leader->SetArrowStyleToFilled ();
472  leader->AutoLabelOn ();
473 
474  leader->GetProperty ()->SetColor (r, g, b);
475  addActorToRenderer (leader, viewport);
476 
477  // Save the pointer/ID pair to the global actor map
478  (*shape_actor_map_)[id] = leader;
479  return (true);
480 }
481 
482 ////////////////////////////////////////////////////////////////////////////////////////////
483 template <typename P1, typename P2> bool
484 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)
485 {
486  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
487  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
488  if (am_it != shape_actor_map_->end ())
489  {
490  PCL_WARN ("[addArrow] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
491  return (false);
492  }
493 
494  // Create an Actor
496  leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
497  leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
498  leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
499  leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
500  leader->SetArrowStyleToFilled ();
501  leader->SetArrowPlacementToPoint1 ();
502  if (display_length)
503  leader->AutoLabelOn ();
504  else
505  leader->AutoLabelOff ();
506 
507  leader->GetProperty ()->SetColor (r, g, b);
508  addActorToRenderer (leader, viewport);
509 
510  // Save the pointer/ID pair to the global actor map
511  (*shape_actor_map_)[id] = leader;
512  return (true);
513 }
514 ////////////////////////////////////////////////////////////////////////////////////////////
515 template <typename P1, typename P2> bool
516 pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2,
517  double r_line, double g_line, double b_line,
518  double r_text, double g_text, double b_text,
519  const std::string &id, int viewport)
520 {
521  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
522  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
523  if (am_it != shape_actor_map_->end ())
524  {
525  PCL_WARN ("[addArrow] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
526  return (false);
527  }
528 
529  // Create an Actor
531  leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
532  leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
533  leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
534  leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
535  leader->SetArrowStyleToFilled ();
536  leader->AutoLabelOn ();
537 
538  leader->GetLabelTextProperty()->SetColor(r_text, g_text, b_text);
539 
540  leader->GetProperty ()->SetColor (r_line, g_line, b_line);
541  addActorToRenderer (leader, viewport);
542 
543  // Save the pointer/ID pair to the global actor map
544  (*shape_actor_map_)[id] = leader;
545  return (true);
546 }
547 
548 ////////////////////////////////////////////////////////////////////////////////////////////
549 template <typename P1, typename P2> bool
550 pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, const std::string &id, int viewport)
551 {
552  return (!addLine (pt1, pt2, 0.5, 0.5, 0.5, id, viewport));
553 }
554 
555 ////////////////////////////////////////////////////////////////////////////////////////////
556 template <typename PointT> bool
557 pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, double r, double g, double b, const std::string &id, int viewport)
558 {
559  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
560  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
561  if (am_it != shape_actor_map_->end ())
562  {
563  PCL_WARN ("[addSphere] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
564  return (false);
565  }
566 
568  data->SetRadius (radius);
569  data->SetCenter (double (center.x), double (center.y), double (center.z));
570  data->SetPhiResolution (10);
571  data->SetThetaResolution (10);
572  data->LatLongTessellationOff ();
573  data->Update ();
574 
575  // Setup actor and mapper
577  mapper->SetInputConnection (data->GetOutputPort ());
578 
579  // Create an Actor
581  actor->SetMapper (mapper);
582  //createActorFromVTKDataSet (data, actor);
583  actor->GetProperty ()->SetRepresentationToSurface ();
584  actor->GetProperty ()->SetInterpolationToFlat ();
585  actor->GetProperty ()->SetColor (r, g, b);
586  actor->GetMapper ()->ImmediateModeRenderingOn ();
587  actor->GetMapper ()->StaticOn ();
588  actor->GetMapper ()->ScalarVisibilityOff ();
589  actor->GetMapper ()->Update ();
590  addActorToRenderer (actor, viewport);
591 
592  // Save the pointer/ID pair to the global actor map
593  (*shape_actor_map_)[id] = actor;
594  return (true);
595 }
596 
597 ////////////////////////////////////////////////////////////////////////////////////////////
598 template <typename PointT> bool
599 pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, const std::string &id, int viewport)
600 {
601  return (addSphere (center, radius, 0.5, 0.5, 0.5, id, viewport));
602 }
603 
604 ////////////////////////////////////////////////////////////////////////////////////////////
605 template<typename PointT> bool
606 pcl::visualization::PCLVisualizer::updateSphere (const PointT &center, double radius, double r, double g, double b, const std::string &id)
607 {
608  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
609  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
610  if (am_it == shape_actor_map_->end ())
611  return (false);
612 
613  //////////////////////////////////////////////////////////////////////////
614  // Get the actor pointer
615  vtkLODActor* actor = vtkLODActor::SafeDownCast (am_it->second);
616  vtkAlgorithm *algo = actor->GetMapper ()->GetInput ();
617  vtkSphereSource *src = vtkSphereSource::SafeDownCast (algo);
618 
619  src->SetCenter (double (center.x), double (center.y), double (center.z));
620  src->SetRadius (radius);
621  src->Update ();
622  actor->GetProperty ()->SetColor (r, g, b);
623  actor->Modified ();
624 
625  return (true);
626 }
627 
628 //////////////////////////////////////////////////
629 template <typename PointT> bool
631  const std::string &text,
632  const PointT& position,
633  double textScale,
634  double r,
635  double g,
636  double b,
637  const std::string &id,
638  int viewport)
639 {
640  std::string tid;
641  if (id.empty ())
642  tid = text;
643  else
644  tid = id;
645 
646  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
647  ShapeActorMap::iterator am_it = shape_actor_map_->find (tid);
648  if (am_it != shape_actor_map_->end ())
649  {
650  pcl::console::print_warn (stderr, "[addText3d] A text with id <%s> already exists! Please choose a different id and retry.\n", tid.c_str ());
651  return (false);
652  }
653 
655  textSource->SetText (text.c_str());
656  textSource->Update ();
657 
659  textMapper->SetInputConnection (textSource->GetOutputPort ());
660 
661  // Since each follower may follow a different camera, we need different followers
662  rens_->InitTraversal ();
663  vtkRenderer* renderer = NULL;
664  int i = 1;
665  while ((renderer = rens_->GetNextItem ()) != NULL)
666  {
667  // Should we add the actor to all renderers or just to i-nth renderer?
668  if (viewport == 0 || viewport == i)
669  {
671  textActor->SetMapper (textMapper);
672  textActor->SetPosition (position.x, position.y, position.z);
673  textActor->SetScale (textScale);
674  textActor->GetProperty ()->SetColor (r, g, b);
675  textActor->SetCamera (renderer->GetActiveCamera ());
676 
677  renderer->AddActor (textActor);
678  renderer->Render ();
679 
680  // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
681  // for multiple viewport
682  std::string alternate_tid = tid;
683  alternate_tid.append(i, '*');
684 
685  (*shape_actor_map_)[(viewport == 0) ? tid : alternate_tid] = textActor;
686  }
687 
688  ++i;
689  }
690 
691  return (true);
692 }
693 
694 //////////////////////////////////////////////////////////////////////////////////////////////
695 template <typename PointNT> bool
697  const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
698  int level, float scale, const std::string &id, int viewport)
699 {
700  return (addPointCloudNormals<PointNT, PointNT> (cloud, cloud, level, scale, id, viewport));
701 }
702 
703 //////////////////////////////////////////////////////////////////////////////////////////////
704 template <typename PointT, typename PointNT> bool
706  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
707  const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
708  int level, float scale,
709  const std::string &id, int viewport)
710 {
711  if (normals->points.size () != cloud->points.size ())
712  {
713  PCL_ERROR ("[addPointCloudNormals] The number of points differs from the number of normals!\n");
714  return (false);
715  }
716  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
717  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
718 
719  if (am_it != cloud_actor_map_->end ())
720  {
721  PCL_WARN ("[addPointCloudNormals] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
722  return (false);
723  }
724 
727 
728  points->SetDataTypeToFloat ();
730  data->SetNumberOfComponents (3);
731 
732 
733  vtkIdType nr_normals = 0;
734  float* pts = 0;
735 
736  // If the cloud is organized, then distribute the normal step in both directions
737  if (cloud->isOrganized () && normals->isOrganized ())
738  {
739  vtkIdType point_step = static_cast<vtkIdType> (sqrt (double (level)));
740  nr_normals = (static_cast<vtkIdType> ((cloud->width - 1)/ point_step) + 1) *
741  (static_cast<vtkIdType> ((cloud->height - 1) / point_step) + 1);
742  pts = new float[2 * nr_normals * 3];
743 
744  vtkIdType cell_count = 0;
745  for (vtkIdType y = 0; y < normals->height; y += point_step)
746  for (vtkIdType x = 0; x < normals->width; x += point_step)
747  {
748  PointT p = (*cloud)(x, y);
749  p.x += (*normals)(x, y).normal[0] * scale;
750  p.y += (*normals)(x, y).normal[1] * scale;
751  p.z += (*normals)(x, y).normal[2] * scale;
752 
753  pts[2 * cell_count * 3 + 0] = (*cloud)(x, y).x;
754  pts[2 * cell_count * 3 + 1] = (*cloud)(x, y).y;
755  pts[2 * cell_count * 3 + 2] = (*cloud)(x, y).z;
756  pts[2 * cell_count * 3 + 3] = p.x;
757  pts[2 * cell_count * 3 + 4] = p.y;
758  pts[2 * cell_count * 3 + 5] = p.z;
759 
760  lines->InsertNextCell (2);
761  lines->InsertCellPoint (2 * cell_count);
762  lines->InsertCellPoint (2 * cell_count + 1);
763  cell_count ++;
764  }
765  }
766  else
767  {
768  nr_normals = (cloud->points.size () - 1) / level + 1 ;
769  pts = new float[2 * nr_normals * 3];
770 
771  for (vtkIdType i = 0, j = 0; j < nr_normals; j++, i = j * level)
772  {
773  PointT p = cloud->points[i];
774  p.x += normals->points[i].normal[0] * scale;
775  p.y += normals->points[i].normal[1] * scale;
776  p.z += normals->points[i].normal[2] * scale;
777 
778  pts[2 * j * 3 + 0] = cloud->points[i].x;
779  pts[2 * j * 3 + 1] = cloud->points[i].y;
780  pts[2 * j * 3 + 2] = cloud->points[i].z;
781  pts[2 * j * 3 + 3] = p.x;
782  pts[2 * j * 3 + 4] = p.y;
783  pts[2 * j * 3 + 5] = p.z;
784 
785  lines->InsertNextCell (2);
786  lines->InsertCellPoint (2 * j);
787  lines->InsertCellPoint (2 * j + 1);
788  }
789  }
790 
791  data->SetArray (&pts[0], 2 * nr_normals * 3, 0);
792  points->SetData (data);
793 
795  polyData->SetPoints (points);
796  polyData->SetLines (lines);
797 
799  mapper->SetInputData (polyData);
800  mapper->SetColorModeToMapScalars();
801  mapper->SetScalarModeToUsePointData();
802 
803  // create actor
805  actor->SetMapper (mapper);
806 
807  // Add it to all renderers
808  addActorToRenderer (actor, viewport);
809 
810  // Save the pointer/ID pair to the global actor map
811  (*cloud_actor_map_)[id].actor = actor;
812  return (true);
813 }
814 
815 //////////////////////////////////////////////////////////////////////////////////////////////
816 template <typename PointT, typename GradientT> bool
818  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
819  const typename pcl::PointCloud<GradientT>::ConstPtr &gradients,
820  int level, double scale,
821  const std::string &id, int viewport)
822 {
823  if (gradients->points.size () != cloud->points.size ())
824  {
825  PCL_ERROR ("[addPointCloudGradients] The number of points differs from the number of gradients!\n");
826  return (false);
827  }
828  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
829  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
830 
831  if (am_it != cloud_actor_map_->end ())
832  {
833  PCL_WARN ("[addPointCloudGradients] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
834  return (false);
835  }
836 
839 
840  points->SetDataTypeToFloat ();
842  data->SetNumberOfComponents (3);
843 
844  vtkIdType nr_gradients = (cloud->points.size () - 1) / level + 1 ;
845  float* pts = new float[2 * nr_gradients * 3];
846 
847  for (vtkIdType i = 0, j = 0; j < nr_gradients; j++, i = j * level)
848  {
849  PointT p = cloud->points[i];
850  p.x += gradients->points[i].gradient[0] * scale;
851  p.y += gradients->points[i].gradient[1] * scale;
852  p.z += gradients->points[i].gradient[2] * scale;
853 
854  pts[2 * j * 3 + 0] = cloud->points[i].x;
855  pts[2 * j * 3 + 1] = cloud->points[i].y;
856  pts[2 * j * 3 + 2] = cloud->points[i].z;
857  pts[2 * j * 3 + 3] = p.x;
858  pts[2 * j * 3 + 4] = p.y;
859  pts[2 * j * 3 + 5] = p.z;
860 
861  lines->InsertNextCell(2);
862  lines->InsertCellPoint(2*j);
863  lines->InsertCellPoint(2*j+1);
864  }
865 
866  data->SetArray (&pts[0], 2 * nr_gradients * 3, 0);
867  points->SetData (data);
868 
870  polyData->SetPoints(points);
871  polyData->SetLines(lines);
872 
874  mapper->SetInputData (polyData);
875  mapper->SetColorModeToMapScalars();
876  mapper->SetScalarModeToUsePointData();
877 
878  // create actor
880  actor->SetMapper (mapper);
881 
882  // Add it to all renderers
883  addActorToRenderer (actor, viewport);
884 
885  // Save the pointer/ID pair to the global actor map
886  (*cloud_actor_map_)[id].actor = actor;
887  return (true);
888 }
889 
890 //////////////////////////////////////////////////////////////////////////////////////////////
891 template <typename PointT> bool
893  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
894  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
895  const std::vector<int> &correspondences,
896  const std::string &id,
897  int viewport)
898 {
899  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
900  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
901  if (am_it != shape_actor_map_->end ())
902  {
903  PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
904  return (false);
905  }
906 
907  int n_corr = int (correspondences.size ());
909 
910  // Prepare colors
912  line_colors->SetNumberOfComponents (3);
913  line_colors->SetName ("Colors");
914  line_colors->SetNumberOfTuples (n_corr);
915  unsigned char* colors = line_colors->GetPointer (0);
916  memset (colors, 0, line_colors->GetNumberOfTuples () * line_colors->GetNumberOfComponents ());
917  pcl::RGB rgb;
918  // Will use random colors or RED by default
919  rgb.r = 255; rgb.g = rgb.b = 0;
920 
921  // Prepare coordinates
923  line_points->SetNumberOfPoints (2 * n_corr);
924 
926  line_cells_id->SetNumberOfComponents (3);
927  line_cells_id->SetNumberOfTuples (n_corr);
928  vtkIdType *line_cell_id = line_cells_id->GetPointer (0);
930 
932  line_tcoords->SetNumberOfComponents (1);
933  line_tcoords->SetNumberOfTuples (n_corr * 2);
934  line_tcoords->SetName ("Texture Coordinates");
935 
936  double tc[3] = {0.0, 0.0, 0.0};
937 
938  int j = 0, idx = 0;
939  // Draw lines between the best corresponding points
940  for (size_t i = 0; i < n_corr; ++i)
941  {
942  const PointT &p_src = source_points->points[i];
943  const PointT &p_tgt = target_points->points[correspondences[i]];
944 
945  int id1 = j * 2 + 0, id2 = j * 2 + 1;
946  // Set the points
947  line_points->SetPoint (id1, p_src.x, p_src.y, p_src.z);
948  line_points->SetPoint (id2, p_tgt.x, p_tgt.y, p_tgt.z);
949  // Set the cell ID
950  *line_cell_id++ = 2;
951  *line_cell_id++ = id1;
952  *line_cell_id++ = id2;
953  // Set the texture coords
954  tc[0] = 0.; line_tcoords->SetTuple (id1, tc);
955  tc[0] = 1.; line_tcoords->SetTuple (id2, tc);
956 
957  getRandomColors (rgb);
958  colors[idx+0] = rgb.r;
959  colors[idx+1] = rgb.g;
960  colors[idx+2] = rgb.b;
961  }
962  line_colors->SetNumberOfTuples (j);
963  line_cells_id->SetNumberOfTuples (j);
964  line_cells->SetCells (n_corr, line_cells_id);
965  line_points->SetNumberOfPoints (j*2);
966  line_tcoords->SetNumberOfTuples (j*2);
967 
968  // Fill in the lines
969  line_data->SetPoints (line_points);
970  line_data->SetLines (line_cells);
971  line_data->GetPointData ()->SetTCoords (line_tcoords);
972  line_data->GetCellData ()->SetScalars (line_colors);
973  //line_data->Update ();
974 
975  // Create an Actor
977  createActorFromVTKDataSet (line_data, actor);
978  actor->GetProperty ()->SetRepresentationToWireframe ();
979  actor->GetProperty ()->SetOpacity (0.5);
980  addActorToRenderer (actor, viewport);
981 
982  // Save the pointer/ID pair to the global actor map
983  (*shape_actor_map_)[id] = actor;
984 
985  return (true);
986 }
987 
988 //////////////////////////////////////////////////////////////////////////////////////////////
989 template <typename PointT> bool
991  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
992  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
993  const pcl::Correspondences &correspondences,
994  int nth,
995  const std::string &id,
996  int viewport)
997 {
998  if (correspondences.empty ())
999  {
1000  PCL_DEBUG ("[addCorrespondences] An empty set of correspondences given! Nothing to display.\n");
1001  return (false);
1002  }
1003 
1004  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1005  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
1006  if (am_it != shape_actor_map_->end ())
1007  {
1008  PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1009  return (false);
1010  }
1011 
1012  int n_corr = int (correspondences.size () / nth + 1);
1014 
1015  // Prepare colors
1017  line_colors->SetNumberOfComponents (3);
1018  line_colors->SetName ("Colors");
1019  line_colors->SetNumberOfTuples (n_corr);
1020  unsigned char* colors = line_colors->GetPointer (0);
1021  memset (colors, 0, line_colors->GetNumberOfTuples () * line_colors->GetNumberOfComponents ());
1022  pcl::RGB rgb;
1023  // Will use random colors or RED by default
1024  rgb.r = 255; rgb.g = rgb.b = 0;
1025 
1026  // Prepare coordinates
1028  line_points->SetNumberOfPoints (2 * n_corr);
1029 
1031  line_cells_id->SetNumberOfComponents (3);
1032  line_cells_id->SetNumberOfTuples (n_corr);
1033  vtkIdType *line_cell_id = line_cells_id->GetPointer (0);
1035 
1037  line_tcoords->SetNumberOfComponents (1);
1038  line_tcoords->SetNumberOfTuples (n_corr * 2);
1039  line_tcoords->SetName ("Texture Coordinates");
1040 
1041  double tc[3] = {0.0, 0.0, 0.0};
1042 
1043  int j = 0, idx = 0;
1044  // Draw lines between the best corresponding points
1045  for (size_t i = 0; i < correspondences.size (); i += nth, idx = j * 3, ++j)
1046  {
1047  const PointT &p_src = source_points->points[correspondences[i].index_query];
1048  const PointT &p_tgt = target_points->points[correspondences[i].index_match];
1049 
1050  int id1 = j * 2 + 0, id2 = j * 2 + 1;
1051  // Set the points
1052  line_points->SetPoint (id1, p_src.x, p_src.y, p_src.z);
1053  line_points->SetPoint (id2, p_tgt.x, p_tgt.y, p_tgt.z);
1054  // Set the cell ID
1055  *line_cell_id++ = 2;
1056  *line_cell_id++ = id1;
1057  *line_cell_id++ = id2;
1058  // Set the texture coords
1059  tc[0] = 0.; line_tcoords->SetTuple (id1, tc);
1060  tc[0] = 1.; line_tcoords->SetTuple (id2, tc);
1061 
1062  getRandomColors (rgb);
1063  colors[idx+0] = rgb.r;
1064  colors[idx+1] = rgb.g;
1065  colors[idx+2] = rgb.b;
1066  }
1067  line_colors->SetNumberOfTuples (j);
1068  line_cells_id->SetNumberOfTuples (j);
1069  line_cells->SetCells (n_corr, line_cells_id);
1070  line_points->SetNumberOfPoints (j*2);
1071  line_tcoords->SetNumberOfTuples (j*2);
1072 
1073  // Fill in the lines
1074  line_data->SetPoints (line_points);
1075  line_data->SetLines (line_cells);
1076  line_data->GetPointData ()->SetTCoords (line_tcoords);
1077  line_data->GetCellData ()->SetScalars (line_colors);
1078  //line_data->Update ();
1079 
1080  // Create an Actor
1082  createActorFromVTKDataSet (line_data, actor);
1083  actor->GetProperty ()->SetRepresentationToWireframe ();
1084  actor->GetProperty ()->SetOpacity (0.5);
1085  addActorToRenderer (actor, viewport);
1086 
1087  // Save the pointer/ID pair to the global actor map
1088  (*shape_actor_map_)[id] = actor;
1089 
1090  return (true);
1091 }
1092 
1093 //////////////////////////////////////////////////////////////////////////////////////////////
1094 template <typename PointT> bool
1096  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1097  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1098  const pcl::Correspondences &correspondences,
1099  int nth,
1100  const std::string &id)
1101 {
1102  if (correspondences.empty ())
1103  {
1104  PCL_DEBUG ("[updateCorrespondences] An empty set of correspondences given! Nothing to display.\n");
1105  return (false);
1106  }
1107 
1108  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1109  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
1110  if (am_it == shape_actor_map_->end ())
1111  return (false);
1112 
1113  vtkSmartPointer<vtkLODActor> actor = vtkLODActor::SafeDownCast (am_it->second);
1114  vtkSmartPointer<vtkPolyData> line_data = reinterpret_cast<vtkPolyDataMapper*>(actor->GetMapper ())->GetInput ();
1115 
1116  int n_corr = int (correspondences.size () / nth + 1);
1117 
1118  // Prepare colors
1120  line_colors->SetNumberOfComponents (3);
1121  line_colors->SetName ("Colors");
1122  line_colors->SetNumberOfTuples (n_corr);
1123  unsigned char* colors = line_colors->GetPointer (0);
1124  memset (colors, 0, line_colors->GetNumberOfTuples () * line_colors->GetNumberOfComponents ());
1125  pcl::RGB rgb;
1126  // Will use random colors or RED by default
1127  rgb.r = 255.0; rgb.g = rgb.b = 0.0;
1128 
1129  // Prepare coordinates
1131  line_points->SetNumberOfPoints (2 * n_corr);
1132 
1134  line_cells_id->SetNumberOfComponents (3);
1135  line_cells_id->SetNumberOfTuples (n_corr);
1136  vtkIdType *line_cell_id = line_cells_id->GetPointer (0);
1137  vtkSmartPointer<vtkCellArray> line_cells = line_data->GetLines ();
1138 
1140  line_tcoords->SetNumberOfComponents (1);
1141  line_tcoords->SetNumberOfTuples (n_corr * 2);
1142  line_tcoords->SetName ("Texture Coordinates");
1143 
1144  double tc[3] = {0.0, 0.0, 0.0};
1145 
1146  int j = 0, idx = 0;
1147  // Draw lines between the best corresponding points
1148  for (size_t i = 0; i < correspondences.size (); i += nth, idx = j * 3, ++j)
1149  {
1150  const PointT &p_src = source_points->points[correspondences[i].index_query];
1151  const PointT &p_tgt = target_points->points[correspondences[i].index_match];
1152 
1153  int id1 = j * 2 + 0, id2 = j * 2 + 1;
1154  // Set the points
1155  line_points->SetPoint (id1, p_src.x, p_src.y, p_src.z);
1156  line_points->SetPoint (id2, p_tgt.x, p_tgt.y, p_tgt.z);
1157  // Set the cell ID
1158  *line_cell_id++ = 2;
1159  *line_cell_id++ = id1;
1160  *line_cell_id++ = id2;
1161  // Set the texture coords
1162  tc[0] = 0.; line_tcoords->SetTuple (id1, tc);
1163  tc[0] = 1.; line_tcoords->SetTuple (id2, tc);
1164 
1165  getRandomColors (rgb);
1166  colors[idx+0] = rgb.r;
1167  colors[idx+1] = rgb.g;
1168  colors[idx+2] = rgb.b;
1169  }
1170  line_colors->SetNumberOfTuples (j);
1171  line_cells_id->SetNumberOfTuples (j);
1172  line_cells->SetCells (n_corr, line_cells_id);
1173  line_points->SetNumberOfPoints (j*2);
1174  line_tcoords->SetNumberOfTuples (j*2);
1175 
1176  // Fill in the lines
1177  line_data->SetPoints (line_points);
1178  line_data->SetLines (line_cells);
1179  line_data->GetPointData ()->SetTCoords (line_tcoords);
1180  line_data->GetCellData ()->SetScalars (line_colors);
1181  //line_data->Update ();
1182 
1183  // Update the mapper
1184  reinterpret_cast<vtkPolyDataMapper*>(actor->GetMapper ())->SetInputData (line_data);
1185 
1186  return (true);
1187 }
1188 
1189 //////////////////////////////////////////////////////////////////////////////////////////////
1190 template <typename PointT> bool
1191 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1192  const PointCloudGeometryHandler<PointT> &geometry_handler,
1193  const PointCloudColorHandler<PointT> &color_handler,
1194  const std::string &id,
1195  int viewport,
1196  const Eigen::Vector4f& sensor_origin,
1197  const Eigen::Quaternion<float>& sensor_orientation)
1198 {
1199  if (!geometry_handler.isCapable ())
1200  {
1201  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1202  return (false);
1203  }
1204 
1205  if (!color_handler.isCapable ())
1206  {
1207  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1208  return (false);
1209  }
1210 
1213  // Convert the PointCloud to VTK PolyData
1214  convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1215  // use the given geometry handler
1216  //polydata->Update ();
1217 
1218  // Get the colors from the handler
1219  bool has_colors = false;
1220  double minmax[2];
1222  if (color_handler.getColor (scalars))
1223  {
1224  polydata->GetPointData ()->SetScalars (scalars);
1225  scalars->GetRange (minmax);
1226  has_colors = true;
1227  }
1228 
1229  // Create an Actor
1231  createActorFromVTKDataSet (polydata, actor);
1232  if (has_colors)
1233  actor->GetMapper ()->SetScalarRange (minmax);
1234 
1235  // Add it to all renderers
1236  addActorToRenderer (actor, viewport);
1237 
1238  // Save the pointer/ID pair to the global actor map
1239  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1240  cloud_actor.actor = actor;
1241  cloud_actor.cells = initcells;
1242 
1243  // Save the viewpoint transformation matrix to the global actor map
1245  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1246  cloud_actor.viewpoint_transformation_ = transformation;
1247  cloud_actor.actor->SetUserMatrix (transformation);
1248  cloud_actor.actor->Modified ();
1249 
1250  return (true);
1251 }
1252 
1253 //////////////////////////////////////////////////////////////////////////////////////////////
1254 template <typename PointT> bool
1255 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1256  const PointCloudGeometryHandler<PointT> &geometry_handler,
1257  const ColorHandlerConstPtr &color_handler,
1258  const std::string &id,
1259  int viewport,
1260  const Eigen::Vector4f& sensor_origin,
1261  const Eigen::Quaternion<float>& sensor_orientation)
1262 {
1263  if (!geometry_handler.isCapable ())
1264  {
1265  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1266  return (false);
1267  }
1268 
1269  if (!color_handler->isCapable ())
1270  {
1271  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler->getName ().c_str ());
1272  return (false);
1273  }
1274 
1277  // Convert the PointCloud to VTK PolyData
1278  convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1279  // use the given geometry handler
1280  //polydata->Update ();
1281 
1282  // Get the colors from the handler
1283  bool has_colors = false;
1284  double minmax[2];
1286  if (color_handler->getColor (scalars))
1287  {
1288  polydata->GetPointData ()->SetScalars (scalars);
1289  scalars->GetRange (minmax);
1290  has_colors = true;
1291  }
1292 
1293  // Create an Actor
1295  createActorFromVTKDataSet (polydata, actor);
1296  if (has_colors)
1297  actor->GetMapper ()->SetScalarRange (minmax);
1298 
1299  // Add it to all renderers
1300  addActorToRenderer (actor, viewport);
1301 
1302  // Save the pointer/ID pair to the global actor map
1303  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1304  cloud_actor.actor = actor;
1305  cloud_actor.cells = initcells;
1306  cloud_actor.color_handlers.push_back (color_handler);
1307 
1308  // Save the viewpoint transformation matrix to the global actor map
1310  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1311  cloud_actor.viewpoint_transformation_ = transformation;
1312  cloud_actor.actor->SetUserMatrix (transformation);
1313  cloud_actor.actor->Modified ();
1314 
1315  return (true);
1316 }
1317 
1318 //////////////////////////////////////////////////////////////////////////////////////////////
1319 template <typename PointT> bool
1320 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1321  const GeometryHandlerConstPtr &geometry_handler,
1322  const PointCloudColorHandler<PointT> &color_handler,
1323  const std::string &id,
1324  int viewport,
1325  const Eigen::Vector4f& sensor_origin,
1326  const Eigen::Quaternion<float>& sensor_orientation)
1327 {
1328  if (!geometry_handler->isCapable ())
1329  {
1330  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler->getName ().c_str ());
1331  return (false);
1332  }
1333 
1334  if (!color_handler.isCapable ())
1335  {
1336  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1337  return (false);
1338  }
1339 
1342  // Convert the PointCloud to VTK PolyData
1343  convertPointCloudToVTKPolyData (geometry_handler, polydata, initcells);
1344  // use the given geometry handler
1345  //polydata->Update ();
1346 
1347  // Get the colors from the handler
1348  bool has_colors = false;
1349  double minmax[2];
1351  if (color_handler.getColor (scalars))
1352  {
1353  polydata->GetPointData ()->SetScalars (scalars);
1354  scalars->GetRange (minmax);
1355  has_colors = true;
1356  }
1357 
1358  // Create an Actor
1360  createActorFromVTKDataSet (polydata, actor);
1361  if (has_colors)
1362  actor->GetMapper ()->SetScalarRange (minmax);
1363 
1364  // Add it to all renderers
1365  addActorToRenderer (actor, viewport);
1366 
1367  // Save the pointer/ID pair to the global actor map
1368  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1369  cloud_actor.actor = actor;
1370  cloud_actor.cells = initcells;
1371  cloud_actor.geometry_handlers.push_back (geometry_handler);
1372 
1373  // Save the viewpoint transformation matrix to the global actor map
1375  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1376  cloud_actor.viewpoint_transformation_ = transformation;
1377  cloud_actor.actor->SetUserMatrix (transformation);
1378  cloud_actor.actor->Modified ();
1379 
1380  return (true);
1381 }
1382 
1383 //////////////////////////////////////////////////////////////////////////////////////////////
1384 template <typename PointT> bool
1386  const std::string &id)
1387 {
1388  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1389  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1390 
1391  if (am_it == cloud_actor_map_->end ())
1392  return (false);
1393 
1394  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1395  // Convert the PointCloud to VTK PolyData
1396  convertPointCloudToVTKPolyData<PointT> (cloud, polydata, am_it->second.cells);
1397  //polydata->Update ();
1398 
1399  // Set scalars to blank, since there is no way we can update them here.
1401  polydata->GetPointData ()->SetScalars (scalars);
1402  //polydata->Update ();
1403  double minmax[2];
1404  minmax[0] = std::numeric_limits<double>::min ();
1405  minmax[1] = std::numeric_limits<double>::max ();
1406  am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
1407  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1408 
1409  // Update the mapper
1410  reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInputData (polydata);
1411  return (true);
1412 }
1413 
1414 /////////////////////////////////////////////////////////////////////////////////////////////
1415 template <typename PointT> bool
1417  const PointCloudGeometryHandler<PointT> &geometry_handler,
1418  const std::string &id)
1419 {
1420  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1421  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1422 
1423  if (am_it == cloud_actor_map_->end ())
1424  return (false);
1425 
1426  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1427  if (!polydata)
1428  return (false);
1429  // Convert the PointCloud to VTK PolyData
1430  convertPointCloudToVTKPolyData (geometry_handler, polydata, am_it->second.cells);
1431 
1432  // Set scalars to blank, since there is no way we can update them here.
1434  polydata->GetPointData ()->SetScalars (scalars);
1435  //polydata->Update ();
1436  double minmax[2];
1437  minmax[0] = std::numeric_limits<double>::min ();
1438  minmax[1] = std::numeric_limits<double>::max ();
1439  am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
1440  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1441 
1442  // Update the mapper
1443  reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInputData (polydata);
1444  return (true);
1445 }
1446 
1447 
1448 /////////////////////////////////////////////////////////////////////////////////////////////
1449 template <typename PointT> bool
1451  const PointCloudColorHandler<PointT> &color_handler,
1452  const std::string &id)
1453 {
1454  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1455  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1456 
1457  if (am_it == cloud_actor_map_->end ())
1458  return (false);
1459 
1460  // Get the current poly data
1461  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1462  if (!polydata)
1463  return (false);
1464  vtkSmartPointer<vtkCellArray> vertices = polydata->GetVerts ();
1465  vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
1466  // Copy the new point array in
1467  vtkIdType nr_points = cloud->points.size ();
1468  points->SetNumberOfPoints (nr_points);
1469 
1470  // Get a pointer to the beginning of the data array
1471  float *data = (static_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
1472 
1473  int pts = 0;
1474  // If the dataset is dense (no NaNs)
1475  if (cloud->is_dense)
1476  {
1477  for (vtkIdType i = 0; i < nr_points; ++i, pts += 3)
1478  memcpy (&data[pts], &cloud->points[i].x, 12); // sizeof (float) * 3
1479  }
1480  else
1481  {
1482  vtkIdType j = 0; // true point index
1483  for (vtkIdType i = 0; i < nr_points; ++i)
1484  {
1485  // Check if the point is invalid
1486  if (!isFinite (cloud->points[i]))
1487  continue;
1488 
1489  memcpy (&data[pts], &cloud->points[i].x, 12); // sizeof (float) * 3
1490  pts += 3;
1491  j++;
1492  }
1493  nr_points = j;
1494  points->SetNumberOfPoints (nr_points);
1495  }
1496 
1497  vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
1498  updateCells (cells, am_it->second.cells, nr_points);
1499 
1500  // Set the cells and the vertices
1501  vertices->SetCells (nr_points, cells);
1502 
1503  // Get the colors from the handler
1505  color_handler.getColor (scalars);
1506  double minmax[2];
1507  scalars->GetRange (minmax);
1508  // Update the data
1509  polydata->GetPointData ()->SetScalars (scalars);
1510  //polydata->Update ();
1511 
1512  am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
1513  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1514 
1515  // Update the mapper
1516  reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInputData (polydata);
1517  return (true);
1518 }
1519 
1520 /////////////////////////////////////////////////////////////////////////////////////////////
1521 template <typename PointT> bool
1523  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1524  const std::vector<pcl::Vertices> &vertices,
1525  const std::string &id,
1526  int viewport)
1527 {
1528  if (vertices.empty () || cloud->points.empty ())
1529  return (false);
1530 
1531  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1532  if (am_it != cloud_actor_map_->end ())
1533  {
1534  pcl::console::print_warn (stderr,
1535  "[addPolygonMesh] A shape with id <%s> already exists! Please choose a different id and retry.\n",
1536  id.c_str ());
1537  return (false);
1538  }
1539 
1540  int rgb_idx = -1;
1541  std::vector<pcl::PCLPointField> fields;
1543  rgb_idx = pcl::getFieldIndex (*cloud, "rgb", fields);
1544  if (rgb_idx == -1)
1545  rgb_idx = pcl::getFieldIndex (*cloud, "rgba", fields);
1546  if (rgb_idx != -1)
1547  {
1549  colors->SetNumberOfComponents (3);
1550  colors->SetName ("Colors");
1551 
1552  pcl::RGB rgb_data;
1553  for (size_t i = 0; i < cloud->size (); ++i)
1554  {
1555  if (!isFinite (cloud->points[i]))
1556  continue;
1557  memcpy (&rgb_data, reinterpret_cast<const char*> (&cloud->points[i]) + fields[rgb_idx].offset, sizeof (pcl::RGB));
1558  unsigned char color[3];
1559  color[0] = rgb_data.r;
1560  color[1] = rgb_data.g;
1561  color[2] = rgb_data.b;
1562  colors->InsertNextTupleValue (color);
1563  }
1564  }
1565 
1566  // Create points from polyMesh.cloud
1568  vtkIdType nr_points = cloud->points.size ();
1569  points->SetNumberOfPoints (nr_points);
1571 
1572  // Get a pointer to the beginning of the data array
1573  float *data = static_cast<vtkFloatArray*> (points->GetData ())->GetPointer (0);
1574 
1575  int ptr = 0;
1576  std::vector<int> lookup;
1577  // If the dataset is dense (no NaNs)
1578  if (cloud->is_dense)
1579  {
1580  for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
1581  memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
1582  }
1583  else
1584  {
1585  lookup.resize (nr_points);
1586  vtkIdType j = 0; // true point index
1587  for (vtkIdType i = 0; i < nr_points; ++i)
1588  {
1589  // Check if the point is invalid
1590  if (!isFinite (cloud->points[i]))
1591  continue;
1592 
1593  lookup[i] = static_cast<int> (j);
1594  memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
1595  j++;
1596  ptr += 3;
1597  }
1598  nr_points = j;
1599  points->SetNumberOfPoints (nr_points);
1600  }
1601 
1602  // Get the maximum size of a polygon
1603  int max_size_of_polygon = -1;
1604  for (size_t i = 0; i < vertices.size (); ++i)
1605  if (max_size_of_polygon < static_cast<int> (vertices[i].vertices.size ()))
1606  max_size_of_polygon = static_cast<int> (vertices[i].vertices.size ());
1607 
1608  if (vertices.size () > 1)
1609  {
1610  // Create polys from polyMesh.polygons
1612  vtkIdType *cell = cell_array->WritePointer (vertices.size (), vertices.size () * (max_size_of_polygon + 1));
1613  int idx = 0;
1614  if (lookup.size () > 0)
1615  {
1616  for (size_t i = 0; i < vertices.size (); ++i, ++idx)
1617  {
1618  size_t n_points = vertices[i].vertices.size ();
1619  *cell++ = n_points;
1620  //cell_array->InsertNextCell (n_points);
1621  for (size_t j = 0; j < n_points; j++, ++idx)
1622  *cell++ = lookup[vertices[i].vertices[j]];
1623  //cell_array->InsertCellPoint (lookup[vertices[i].vertices[j]]);
1624  }
1625  }
1626  else
1627  {
1628  for (size_t i = 0; i < vertices.size (); ++i, ++idx)
1629  {
1630  size_t n_points = vertices[i].vertices.size ();
1631  *cell++ = n_points;
1632  //cell_array->InsertNextCell (n_points);
1633  for (size_t j = 0; j < n_points; j++, ++idx)
1634  *cell++ = vertices[i].vertices[j];
1635  //cell_array->InsertCellPoint (vertices[i].vertices[j]);
1636  }
1637  }
1639  allocVtkPolyData (polydata);
1640  cell_array->GetData ()->SetNumberOfValues (idx);
1641  cell_array->Squeeze ();
1642  polydata->SetStrips (cell_array);
1643  polydata->SetPoints (points);
1644 
1645  if (colors)
1646  polydata->GetPointData ()->SetScalars (colors);
1647 
1648  createActorFromVTKDataSet (polydata, actor, false);
1649  }
1650  else
1651  {
1653  size_t n_points = vertices[0].vertices.size ();
1654  polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
1655 
1656  if (lookup.size () > 0)
1657  {
1658  for (size_t j = 0; j < (n_points - 1); ++j)
1659  polygon->GetPointIds ()->SetId (j, lookup[vertices[0].vertices[j]]);
1660  }
1661  else
1662  {
1663  for (size_t j = 0; j < (n_points - 1); ++j)
1664  polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
1665  }
1667  allocVtkUnstructuredGrid (poly_grid);
1668  poly_grid->Allocate (1, 1);
1669  poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
1670  poly_grid->SetPoints (points);
1671  //poly_grid->Update ();
1672  if (colors)
1673  poly_grid->GetPointData ()->SetScalars (colors);
1674 
1675  createActorFromVTKDataSet (poly_grid, actor, false);
1676  }
1677  addActorToRenderer (actor, viewport);
1678  actor->GetProperty ()->SetRepresentationToSurface ();
1679  // Backface culling renders the visualization slower, but guarantees that we see all triangles
1680  actor->GetProperty ()->BackfaceCullingOff ();
1681  actor->GetProperty ()->SetInterpolationToFlat ();
1682  actor->GetProperty ()->EdgeVisibilityOff ();
1683  actor->GetProperty ()->ShadingOff ();
1684 
1685  // Save the pointer/ID pair to the global actor map
1686  (*cloud_actor_map_)[id].actor = actor;
1687 
1688  // Save the viewpoint transformation matrix to the global actor map
1690  convertToVtkMatrix (cloud->sensor_origin_, cloud->sensor_orientation_, transformation);
1691  (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
1692 
1693  return (true);
1694 }
1695 
1696 /////////////////////////////////////////////////////////////////////////////////////////////
1697 template <typename PointT> bool
1699  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1700  const std::vector<pcl::Vertices> &verts,
1701  const std::string &id)
1702 {
1703  if (verts.empty ())
1704  {
1705  pcl::console::print_error ("[addPolygonMesh] No vertices given!\n");
1706  return (false);
1707  }
1708 
1709  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1710  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1711  if (am_it == cloud_actor_map_->end ())
1712  return (false);
1713 
1714  // Get the current poly data
1715  vtkSmartPointer<vtkPolyData> polydata = static_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1716  if (!polydata)
1717  return (false);
1718  vtkSmartPointer<vtkCellArray> cells = polydata->GetStrips ();
1719  if (!cells)
1720  return (false);
1721  vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
1722  // Copy the new point array in
1723  vtkIdType nr_points = cloud->points.size ();
1724  points->SetNumberOfPoints (nr_points);
1725 
1726  // Get a pointer to the beginning of the data array
1727  float *data = (static_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
1728 
1729  int ptr = 0;
1730  std::vector<int> lookup;
1731  // If the dataset is dense (no NaNs)
1732  if (cloud->is_dense)
1733  {
1734  for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
1735  memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
1736  }
1737  else
1738  {
1739  lookup.resize (nr_points);
1740  vtkIdType j = 0; // true point index
1741  for (vtkIdType i = 0; i < nr_points; ++i)
1742  {
1743  // Check if the point is invalid
1744  if (!isFinite (cloud->points[i]))
1745  continue;
1746 
1747  lookup [i] = static_cast<int> (j);
1748  memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3);
1749  j++;
1750  ptr += 3;
1751  }
1752  nr_points = j;
1753  points->SetNumberOfPoints (nr_points);
1754  }
1755 
1756  // Update colors
1757  vtkUnsignedCharArray* colors = vtkUnsignedCharArray::SafeDownCast (polydata->GetPointData ()->GetScalars ());
1758  int rgb_idx = -1;
1759  std::vector<pcl::PCLPointField> fields;
1760  rgb_idx = pcl::getFieldIndex (*cloud, "rgb", fields);
1761  if (rgb_idx == -1)
1762  rgb_idx = pcl::getFieldIndex (*cloud, "rgba", fields);
1763  if (rgb_idx != -1 && colors)
1764  {
1765  pcl::RGB rgb_data;
1766  int j = 0;
1767  for (size_t i = 0; i < cloud->size (); ++i)
1768  {
1769  if (!isFinite (cloud->points[i]))
1770  continue;
1771  memcpy (&rgb_data,
1772  reinterpret_cast<const char*> (&cloud->points[i]) + fields[rgb_idx].offset,
1773  sizeof (pcl::RGB));
1774  unsigned char color[3];
1775  color[0] = rgb_data.r;
1776  color[1] = rgb_data.g;
1777  color[2] = rgb_data.b;
1778  colors->SetTupleValue (j++, color);
1779  }
1780  }
1781 
1782  // Get the maximum size of a polygon
1783  int max_size_of_polygon = -1;
1784  for (size_t i = 0; i < verts.size (); ++i)
1785  if (max_size_of_polygon < static_cast<int> (verts[i].vertices.size ()))
1786  max_size_of_polygon = static_cast<int> (verts[i].vertices.size ());
1787 
1788  // Update the cells
1790  vtkIdType *cell = cells->WritePointer (verts.size (), verts.size () * (max_size_of_polygon + 1));
1791  int idx = 0;
1792  if (lookup.size () > 0)
1793  {
1794  for (size_t i = 0; i < verts.size (); ++i, ++idx)
1795  {
1796  size_t n_points = verts[i].vertices.size ();
1797  *cell++ = n_points;
1798  for (size_t j = 0; j < n_points; j++, cell++, ++idx)
1799  *cell = lookup[verts[i].vertices[j]];
1800  }
1801  }
1802  else
1803  {
1804  for (size_t i = 0; i < verts.size (); ++i, ++idx)
1805  {
1806  size_t n_points = verts[i].vertices.size ();
1807  *cell++ = n_points;
1808  for (size_t j = 0; j < n_points; j++, cell++, ++idx)
1809  *cell = verts[i].vertices[j];
1810  }
1811  }
1812  cells->GetData ()->SetNumberOfValues (idx);
1813  cells->Squeeze ();
1814  // Set the the vertices
1815  polydata->SetStrips (cells);
1816  //polydata->Update ();
1817 
1818  return (true);
1819 }
1820 
1821 #endif
bool isCapable() const
Check if this handler is capable of handling the input data or not.
bool isFinite(const PointT &pt)
Tests if the 3D components of a point are all finite param[in] pt point to be tested.
Definition: point_tests.h:53
boost::shared_ptr< const PointCloud< PointT > > ConstPtr
Definition: point_cloud.h:429
Eigen::Vector4f sensor_origin_
Sensor acquisition pose (origin/translation).
Definition: point_cloud.h:421
int getFieldIndex(const pcl::PCLPointCloud2 &cloud, const std::string &field_name)
Get the index of a specified field (i.e., dimension/channel)
Definition: io.h:58
bool updateCorrespondences(const typename pcl::PointCloud< PointT >::ConstPtr &source_points, const typename pcl::PointCloud< PointT >::ConstPtr &target_points, const pcl::Correspondences &correspondences, int nth, const std::string &id="correspondences")
Update the specified correspondences to the display.
ColorHandler::ConstPtr ColorHandlerConstPtr
bool addPointCloud(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, const std::string &id="cloud", int viewport=0)
Add a Point Cloud (templated) to screen.
virtual void getGeometry(vtkSmartPointer< vtkPoints > &points) const =0
Obtain the actual point geometry for the input dataset in VTK format.
bool addPointCloudIntensityGradients(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, const typename pcl::PointCloud< GradientT >::ConstPtr &gradients, int level=100, double scale=1e-6, const std::string &id="cloud", int viewport=0)
Add the estimated surface intensity gradients of a Point Cloud to screen.
uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:413
bool addPolygon(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, double r, double g, double b, const std::string &id="polygon", int viewport=0)
Add a polygon (polyline) that represents the input point cloud (connects all points in order) ...
Base Handler class for PointCloud colors.
Eigen::Quaternionf sensor_orientation_
Sensor acquisition pose (rotation).
Definition: point_cloud.h:423
bool addSphere(const PointT &center, double radius, const std::string &id="sphere", int viewport=0)
Add a sphere shape from a point and a radius.
PCL_EXPORTS void getRandomColors(double &r, double &g, double &b, double min=0.2, double max=2.8)
Get (good) random values for R/G/B.
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
Definition: point_cloud.h:410
bool addCorrespondences(const typename pcl::PointCloud< PointT >::ConstPtr &source_points, const typename pcl::PointCloud< PointT >::ConstPtr &target_points, const std::vector< int > &correspondences, const std::string &id="correspondences", int viewport=0)
Add the specified correspondences to the display.
A structure representing RGB color information.
PlanarPolygon represents a planar (2D) polygon, potentially in a 3D space.
std::vector< pcl::Correspondence, Eigen::aligned_allocator< pcl::Correspondence > > Correspondences
bool addPolygonMesh(const pcl::PolygonMesh &polymesh, const std::string &id="polygon", int viewport=0)
Add a PolygonMesh object to screen.
size_t size() const
Definition: point_cloud.h:440
bool addArrow(const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id="arrow", int viewport=0)
Add a line arrow segment between two points, and display the distance between them.
PCL_EXPORTS void allocVtkUnstructuredGrid(vtkSmartPointer< vtkUnstructuredGrid > &polydata)
Allocate a new unstructured grid smartpointer.
PCL_EXPORTS void print_warn(const char *format,...)
Print a warning message on stream with colors.
bool updatePointCloud(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, const std::string &id="cloud")
Updates the XYZ data for an existing cloud object id on screen.
bool isCapable() const
Checl if this handler is capable of handling the input data or not.
Base handler class for PointCloud geometry.
virtual std::string getName() const =0
Abstract getName method.
GeometryHandler::ConstPtr GeometryHandlerConstPtr
bool addLine(const P1 &pt1, const P2 &pt2, const std::string &id="line", int viewport=0)
Add a line segment from two points.
bool isOrganized() const
Return whether a dataset is organized (e.g., arranged in a structured grid).
Definition: point_cloud.h:331
bool addText3D(const std::string &text, const PointT &position, double textScale=1.0, double r=1.0, double g=1.0, double b=1.0, const std::string &id="", int viewport=0)
Add a 3d text to the scene.
A point structure representing Euclidean xyz coordinates, and the RGB color.
virtual std::string getName() const =0
Abstract getName method.
bool updateSphere(const PointT &center, double radius, double r, double g, double b, const std::string &id="sphere")
Update an existing sphere shape from a point and a radius.
bool addPointCloudNormals(const typename pcl::PointCloud< PointNT >::ConstPtr &cloud, int level=100, float scale=0.02f, const std::string &id="cloud", int viewport=0)
Add the estimated surface normals of a Point Cloud to screen.
virtual bool getColor(vtkSmartPointer< vtkDataArray > &scalars) const =0
Obtain the actual color for the input dataset as vtk scalars.
PCL_EXPORTS vtkSmartPointer< vtkDataSet > createLine(const Eigen::Vector4f &pt1, const Eigen::Vector4f &pt2)
Create a line shape from two points.
bool updatePolygonMesh(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, const std::vector< pcl::Vertices > &vertices, const std::string &id="polygon")
Update a PolygonMesh object on screen.
PCL_EXPORTS void print_error(const char *format,...)
Print an error message on stream with colors.
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values).
Definition: point_cloud.h:418
uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:415