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