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