Point Cloud Library (PCL)  1.14.1
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
66 #include <pcl/visualization/common/shapes.h>
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 (static_cast<double>(center.x), static_cast<double>(center.y), static_cast<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 (static_cast<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  if (!pcl::isFinite(p) || !pcl::isNormalFinite((*normals)(x, y)))
910  continue;
911  p.x += (*normals)(x, y).normal[0] * scale;
912  p.y += (*normals)(x, y).normal[1] * scale;
913  p.z += (*normals)(x, y).normal[2] * scale;
914 
915  pts[2 * cell_count * 3 + 0] = (*cloud)(x, y).x;
916  pts[2 * cell_count * 3 + 1] = (*cloud)(x, y).y;
917  pts[2 * cell_count * 3 + 2] = (*cloud)(x, y).z;
918  pts[2 * cell_count * 3 + 3] = p.x;
919  pts[2 * cell_count * 3 + 4] = p.y;
920  pts[2 * cell_count * 3 + 5] = p.z;
921 
922  lines->InsertNextCell (2);
923  lines->InsertCellPoint (2 * cell_count);
924  lines->InsertCellPoint (2 * cell_count + 1);
925  cell_count ++;
926  }
927  }
928  else
929  {
930  nr_normals = (cloud->size () - 1) / level + 1 ;
931  pts = new float[2 * nr_normals * 3];
932 
933  for (vtkIdType i = 0, j = 0; (j < nr_normals) && (i < static_cast<vtkIdType>(cloud->size())); i += level)
934  {
935  if (!pcl::isFinite((*cloud)[i]) || !pcl::isNormalFinite((*normals)[i]))
936  continue;
937  PointT p = (*cloud)[i];
938  p.x += (*normals)[i].normal[0] * scale;
939  p.y += (*normals)[i].normal[1] * scale;
940  p.z += (*normals)[i].normal[2] * scale;
941 
942  pts[2 * j * 3 + 0] = (*cloud)[i].x;
943  pts[2 * j * 3 + 1] = (*cloud)[i].y;
944  pts[2 * j * 3 + 2] = (*cloud)[i].z;
945  pts[2 * j * 3 + 3] = p.x;
946  pts[2 * j * 3 + 4] = p.y;
947  pts[2 * j * 3 + 5] = p.z;
948 
949  lines->InsertNextCell (2);
950  lines->InsertCellPoint (2 * j);
951  lines->InsertCellPoint (2 * j + 1);
952  ++j;
953  }
954  }
955 
956  data->SetArray (&pts[0], 2 * nr_normals * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
957  points->SetData (data);
958 
960  polyData->SetPoints (points);
961  polyData->SetLines (lines);
962 
964  mapper->SetInputData (polyData);
965  mapper->SetColorModeToMapScalars();
966  mapper->SetScalarModeToUsePointData();
967 
968  // create actor
970  actor->SetMapper (mapper);
971 
972  // Use cloud view point info
974  convertToVtkMatrix (cloud->sensor_origin_, cloud->sensor_orientation_, transformation);
975  actor->SetUserMatrix (transformation);
976 
977  // Add it to all renderers
978  addActorToRenderer (actor, viewport);
979 
980  // Save the pointer/ID pair to the global actor map
981  (*cloud_actor_map_)[id].actor = actor;
982  return (true);
983 }
984 
985 //////////////////////////////////////////////////////////////////////////////////////////////
986 template <typename PointNT> bool
988  const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
990  int level, float scale,
991  const std::string &id, int viewport)
992 {
993  return (addPointCloudPrincipalCurvatures<PointNT, PointNT> (cloud, cloud, pcs, level, scale, id, viewport));
994 }
995 
996 //////////////////////////////////////////////////////////////////////////////////////////////
997 template <typename PointT, typename PointNT> bool
999  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1000  const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
1002  int level, float scale,
1003  const std::string &id, int viewport)
1004 {
1005  if (pcs->size () != cloud->size () || normals->size () != cloud->size ())
1006  {
1007  pcl::console::print_error ("[addPointCloudPrincipalCurvatures] The number of points differs from the number of principal curvatures/normals!\n");
1008  return (false);
1009  }
1010 
1011  if (contains (id))
1012  {
1013  PCL_WARN ("[addPointCloudPrincipalCurvatures] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1014  return (false);
1015  }
1016 
1019 
1020  // Setup two colors - one for each line
1021  unsigned char green[3] = {0, 255, 0};
1022  unsigned char blue[3] = {0, 0, 255};
1023 
1024  // Setup the colors array
1026  line_1_colors->SetNumberOfComponents (3);
1027  line_1_colors->SetName ("Colors");
1029  line_2_colors->SetNumberOfComponents (3);
1030  line_2_colors->SetName ("Colors");
1031 
1032  // Create the first sets of lines
1033  for (std::size_t i = 0; i < cloud->size (); i+=level)
1034  {
1035  PointT p = (*cloud)[i];
1036  p.x += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[0]) * scale;
1037  p.y += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[1]) * scale;
1038  p.z += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[2]) * scale;
1039 
1041  line_1->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1042  line_1->SetPoint2 (p.x, p.y, p.z);
1043  line_1->Update ();
1044  polydata_1->AddInputData (line_1->GetOutput ());
1045  line_1_colors->InsertNextTupleValue (green);
1046  }
1047  polydata_1->Update ();
1048  vtkSmartPointer<vtkPolyData> line_1_data = polydata_1->GetOutput ();
1049  line_1_data->GetCellData ()->SetScalars (line_1_colors);
1050 
1051  // Create the second sets of lines
1052  for (std::size_t i = 0; i < cloud->size (); i += level)
1053  {
1054  Eigen::Vector3f pc ((*pcs)[i].principal_curvature[0],
1055  (*pcs)[i].principal_curvature[1],
1056  (*pcs)[i].principal_curvature[2]);
1057  Eigen::Vector3f normal ((*normals)[i].normal[0],
1058  (*normals)[i].normal[1],
1059  (*normals)[i].normal[2]);
1060  Eigen::Vector3f pc_c = pc.cross (normal);
1061 
1062  PointT p = (*cloud)[i];
1063  p.x += ((*pcs)[i].pc2 * pc_c[0]) * scale;
1064  p.y += ((*pcs)[i].pc2 * pc_c[1]) * scale;
1065  p.z += ((*pcs)[i].pc2 * pc_c[2]) * scale;
1066 
1068  line_2->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1069  line_2->SetPoint2 (p.x, p.y, p.z);
1070  line_2->Update ();
1071  polydata_2->AddInputData (line_2->GetOutput ());
1072 
1073  line_2_colors->InsertNextTupleValue (blue);
1074  }
1075  polydata_2->Update ();
1076  vtkSmartPointer<vtkPolyData> line_2_data = polydata_2->GetOutput ();
1077  line_2_data->GetCellData ()->SetScalars (line_2_colors);
1078 
1079  // Assemble the two sets of lines
1081  alldata->AddInputData (line_1_data);
1082  alldata->AddInputData (line_2_data);
1083  alldata->Update ();
1084 
1085  // Create an Actor
1087  createActorFromVTKDataSet (alldata->GetOutput (), actor);
1088  actor->GetMapper ()->SetScalarModeToUseCellData ();
1089 
1090  // Add it to all renderers
1091  addActorToRenderer (actor, viewport);
1092 
1093  // Save the pointer/ID pair to the global actor map
1094  CloudActor act;
1095  act.actor = actor;
1096  (*cloud_actor_map_)[id] = act;
1097  return (true);
1098 }
1099 
1100 //////////////////////////////////////////////////////////////////////////////////////////////
1101 template <typename PointT, typename GradientT> bool
1103  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1104  const typename pcl::PointCloud<GradientT>::ConstPtr &gradients,
1105  int level, double scale,
1106  const std::string &id, int viewport)
1107 {
1108  if (gradients->size () != cloud->size ())
1109  {
1110  PCL_ERROR ("[addPointCloudGradients] The number of points differs from the number of gradients!\n");
1111  return (false);
1112  }
1113  if (contains (id))
1114  {
1115  PCL_WARN ("[addPointCloudGradients] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1116  return (false);
1117  }
1118 
1121 
1122  points->SetDataTypeToFloat ();
1124  data->SetNumberOfComponents (3);
1125 
1126  vtkIdType nr_gradients = (cloud->size () - 1) / level + 1 ;
1127  float* pts = new float[2 * nr_gradients * 3];
1128 
1129  for (vtkIdType i = 0, j = 0; j < nr_gradients; j++, i = j * level)
1130  {
1131  PointT p = (*cloud)[i];
1132  p.x += (*gradients)[i].gradient[0] * scale;
1133  p.y += (*gradients)[i].gradient[1] * scale;
1134  p.z += (*gradients)[i].gradient[2] * scale;
1135 
1136  pts[2 * j * 3 + 0] = (*cloud)[i].x;
1137  pts[2 * j * 3 + 1] = (*cloud)[i].y;
1138  pts[2 * j * 3 + 2] = (*cloud)[i].z;
1139  pts[2 * j * 3 + 3] = p.x;
1140  pts[2 * j * 3 + 4] = p.y;
1141  pts[2 * j * 3 + 5] = p.z;
1142 
1143  lines->InsertNextCell(2);
1144  lines->InsertCellPoint(2*j);
1145  lines->InsertCellPoint(2*j+1);
1146  }
1147 
1148  data->SetArray (&pts[0], 2 * nr_gradients * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
1149  points->SetData (data);
1150 
1152  polyData->SetPoints(points);
1153  polyData->SetLines(lines);
1154 
1156  mapper->SetInputData (polyData);
1157  mapper->SetColorModeToMapScalars();
1158  mapper->SetScalarModeToUsePointData();
1159 
1160  // create actor
1162  actor->SetMapper (mapper);
1163 
1164  // Add it to all renderers
1165  addActorToRenderer (actor, viewport);
1166 
1167  // Save the pointer/ID pair to the global actor map
1168  (*cloud_actor_map_)[id].actor = actor;
1169  return (true);
1170 }
1171 
1172 //////////////////////////////////////////////////////////////////////////////////////////////
1173 template <typename PointT> bool
1175  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1176  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1177  const std::vector<int> &correspondences,
1178  const std::string &id,
1179  int viewport)
1180 {
1181  pcl::Correspondences corrs;
1182  corrs.resize (correspondences.size ());
1183 
1184  std::size_t index = 0;
1185  for (auto &corr : corrs)
1186  {
1187  corr.index_query = index;
1188  corr.index_match = correspondences[index];
1189  index++;
1190  }
1191 
1192  return (addCorrespondences<PointT> (source_points, target_points, corrs, id, viewport));
1193 }
1194 
1195 //////////////////////////////////////////////////////////////////////////////////////////////
1196 template <typename PointT> bool
1198  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1199  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1200  const pcl::Correspondences &correspondences,
1201  int nth,
1202  const std::string &id,
1203  int viewport,
1204  bool overwrite)
1205 {
1206  if (correspondences.empty ())
1207  {
1208  PCL_DEBUG ("[addCorrespondences] An empty set of correspondences given! Nothing to display.\n");
1209  return (false);
1210  }
1211 
1212  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1213  auto am_it = shape_actor_map_->find (id);
1214  if (am_it != shape_actor_map_->end () && !overwrite)
1215  {
1216  PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1217  return (false);
1218  }
1219  if (am_it == shape_actor_map_->end () && overwrite)
1220  {
1221  overwrite = false; // Correspondences doesn't exist, add them instead of updating them
1222  }
1223 
1224  int n_corr = static_cast<int>(correspondences.size () / nth);
1226 
1227  // Prepare colors
1229  line_colors->SetNumberOfComponents (3);
1230  line_colors->SetName ("Colors");
1231  line_colors->SetNumberOfTuples (n_corr);
1232 
1233  // Prepare coordinates
1235  line_points->SetNumberOfPoints (2 * n_corr);
1236 
1238  line_cells_id->SetNumberOfComponents (3);
1239  line_cells_id->SetNumberOfTuples (n_corr);
1240  vtkIdType *line_cell_id = line_cells_id->GetPointer (0);
1242 
1244  line_tcoords->SetNumberOfComponents (1);
1245  line_tcoords->SetNumberOfTuples (n_corr * 2);
1246  line_tcoords->SetName ("Texture Coordinates");
1247 
1248  double tc[3] = {0.0, 0.0, 0.0};
1249 
1250  Eigen::Affine3f source_transformation;
1251  source_transformation.linear () = source_points->sensor_orientation_.matrix ();
1252  source_transformation.translation () = source_points->sensor_origin_.template head<3> ();
1253  Eigen::Affine3f target_transformation;
1254  target_transformation.linear () = target_points->sensor_orientation_.matrix ();
1255  target_transformation.translation () = target_points->sensor_origin_.template head<3> ();
1256 
1257  int j = 0;
1258  // Draw lines between the best corresponding points
1259  for (std::size_t i = 0; i < correspondences.size (); i += nth, ++j)
1260  {
1261  if (correspondences[i].index_match == UNAVAILABLE)
1262  {
1263  PCL_WARN ("[addCorrespondences] No valid index_match for correspondence %d\n", i);
1264  continue;
1265  }
1266 
1267  PointT p_src ((*source_points)[correspondences[i].index_query]);
1268  PointT p_tgt ((*target_points)[correspondences[i].index_match]);
1269 
1270  p_src.getVector3fMap () = source_transformation * p_src.getVector3fMap ();
1271  p_tgt.getVector3fMap () = target_transformation * p_tgt.getVector3fMap ();
1272 
1273  int id1 = j * 2 + 0, id2 = j * 2 + 1;
1274  // Set the points
1275  line_points->SetPoint (id1, p_src.x, p_src.y, p_src.z);
1276  line_points->SetPoint (id2, p_tgt.x, p_tgt.y, p_tgt.z);
1277  // Set the cell ID
1278  *line_cell_id++ = 2;
1279  *line_cell_id++ = id1;
1280  *line_cell_id++ = id2;
1281  // Set the texture coords
1282  tc[0] = 0.; line_tcoords->SetTuple (id1, tc);
1283  tc[0] = 1.; line_tcoords->SetTuple (id2, tc);
1284 
1285  float rgb[3];
1286  rgb[0] = vtkMath::Random (32, 255); // min / max
1287  rgb[1] = vtkMath::Random (32, 255);
1288  rgb[2] = vtkMath::Random (32, 255);
1289  line_colors->InsertTuple (i, rgb);
1290  }
1291  line_colors->SetNumberOfTuples (j);
1292  line_cells_id->SetNumberOfTuples (j);
1293  line_cells->SetCells (n_corr, line_cells_id);
1294  line_points->SetNumberOfPoints (j*2);
1295  line_tcoords->SetNumberOfTuples (j*2);
1296 
1297  // Fill in the lines
1298  line_data->SetPoints (line_points);
1299  line_data->SetLines (line_cells);
1300  line_data->GetPointData ()->SetTCoords (line_tcoords);
1301  line_data->GetCellData ()->SetScalars (line_colors);
1302 
1303  // Create an Actor
1304  if (!overwrite)
1305  {
1307  createActorFromVTKDataSet (line_data, actor);
1308  actor->GetProperty ()->SetRepresentationToWireframe ();
1309  actor->GetProperty ()->SetOpacity (0.5);
1310  addActorToRenderer (actor, viewport);
1311 
1312  // Save the pointer/ID pair to the global actor map
1313  (*shape_actor_map_)[id] = actor;
1314  }
1315  else
1316  {
1317  vtkSmartPointer<vtkLODActor> actor = vtkLODActor::SafeDownCast (am_it->second);
1318  if (!actor)
1319  return (false);
1320  // Update the mapper
1321  reinterpret_cast<vtkPolyDataMapper*> (actor->GetMapper ())->SetInputData (line_data);
1322  }
1323 
1324  return (true);
1325 }
1326 
1327 //////////////////////////////////////////////////////////////////////////////////////////////
1328 template <typename PointT> bool
1330  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1331  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1332  const pcl::Correspondences &correspondences,
1333  int nth,
1334  const std::string &id,
1335  int viewport)
1336 {
1337  return (addCorrespondences<PointT> (source_points, target_points, correspondences, nth, id, viewport, true));
1338 }
1339 
1340 //////////////////////////////////////////////////////////////////////////////////////////////
1341 template <typename PointT> bool
1342 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1343  const PointCloudGeometryHandler<PointT> &geometry_handler,
1344  const PointCloudColorHandler<PointT> &color_handler,
1345  const std::string &id,
1346  int viewport,
1347  const Eigen::Vector4f& sensor_origin,
1348  const Eigen::Quaternion<float>& sensor_orientation)
1349 {
1350  if (!geometry_handler.isCapable ())
1351  {
1352  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1353  return (false);
1354  }
1355 
1356  if (!color_handler.isCapable ())
1357  {
1358  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1359  return (false);
1360  }
1361 
1364  // Convert the PointCloud to VTK PolyData
1365  convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1366 
1367  // Get the colors from the handler
1368  bool has_colors = false;
1369  double minmax[2];
1370  if (auto scalars = color_handler.getColor ())
1371  {
1372  polydata->GetPointData ()->SetScalars (scalars);
1373  scalars->GetRange (minmax);
1374  has_colors = true;
1375  }
1376 
1377  // Create an Actor
1379  createActorFromVTKDataSet (polydata, actor);
1380  if (has_colors)
1381  actor->GetMapper ()->SetScalarRange (minmax);
1382 
1383  // Add it to all renderers
1384  addActorToRenderer (actor, viewport);
1385 
1386  // Save the pointer/ID pair to the global actor map
1387  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1388  cloud_actor.actor = actor;
1389  cloud_actor.cells = initcells;
1390 
1391  // Save the viewpoint transformation matrix to the global actor map
1393  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1394  cloud_actor.viewpoint_transformation_ = transformation;
1395  cloud_actor.actor->SetUserMatrix (transformation);
1396  cloud_actor.actor->Modified ();
1397 
1398  return (true);
1399 }
1400 
1401 //////////////////////////////////////////////////////////////////////////////////////////////
1402 template <typename PointT> bool
1403 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1404  const PointCloudGeometryHandler<PointT> &geometry_handler,
1405  const ColorHandlerConstPtr &color_handler,
1406  const std::string &id,
1407  int viewport,
1408  const Eigen::Vector4f& sensor_origin,
1409  const Eigen::Quaternion<float>& sensor_orientation)
1410 {
1411  if (!geometry_handler.isCapable ())
1412  {
1413  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1414  return (false);
1415  }
1416 
1417  if (!color_handler->isCapable ())
1418  {
1419  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler->getName ().c_str ());
1420  return (false);
1421  }
1422 
1425  // Convert the PointCloud to VTK PolyData
1426  convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1427  // use the given geometry handler
1428 
1429  // Get the colors from the handler
1430  bool has_colors = false;
1431  double minmax[2];
1432  if (auto scalars = color_handler->getColor ())
1433  {
1434  polydata->GetPointData ()->SetScalars (scalars);
1435  scalars->GetRange (minmax);
1436  has_colors = true;
1437  }
1438 
1439  // Create an Actor
1441  createActorFromVTKDataSet (polydata, actor);
1442  if (has_colors)
1443  actor->GetMapper ()->SetScalarRange (minmax);
1444 
1445  // Add it to all renderers
1446  addActorToRenderer (actor, viewport);
1447 
1448  // Save the pointer/ID pair to the global actor map
1449  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1450  cloud_actor.actor = actor;
1451  cloud_actor.cells = initcells;
1452  cloud_actor.color_handlers.push_back (color_handler);
1453 
1454  // Save the viewpoint transformation matrix to the global actor map
1456  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1457  cloud_actor.viewpoint_transformation_ = transformation;
1458  cloud_actor.actor->SetUserMatrix (transformation);
1459  cloud_actor.actor->Modified ();
1460 
1461  return (true);
1462 }
1463 
1464 //////////////////////////////////////////////////////////////////////////////////////////////
1465 template <typename PointT> bool
1466 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1467  const GeometryHandlerConstPtr &geometry_handler,
1468  const PointCloudColorHandler<PointT> &color_handler,
1469  const std::string &id,
1470  int viewport,
1471  const Eigen::Vector4f& sensor_origin,
1472  const Eigen::Quaternion<float>& sensor_orientation)
1473 {
1474  if (!geometry_handler->isCapable ())
1475  {
1476  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler->getName ().c_str ());
1477  return (false);
1478  }
1479 
1480  if (!color_handler.isCapable ())
1481  {
1482  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1483  return (false);
1484  }
1485 
1488  // Convert the PointCloud to VTK PolyData
1489  convertPointCloudToVTKPolyData (geometry_handler, polydata, initcells);
1490  // use the given geometry handler
1491 
1492  // Get the colors from the handler
1493  bool has_colors = false;
1494  double minmax[2];
1495  if (auto scalars = color_handler.getColor ())
1496  {
1497  polydata->GetPointData ()->SetScalars (scalars);
1498  scalars->GetRange (minmax);
1499  has_colors = true;
1500  }
1501 
1502  // Create an Actor
1504  createActorFromVTKDataSet (polydata, actor);
1505  if (has_colors)
1506  actor->GetMapper ()->SetScalarRange (minmax);
1507 
1508  // Add it to all renderers
1509  addActorToRenderer (actor, viewport);
1510 
1511  // Save the pointer/ID pair to the global actor map
1512  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1513  cloud_actor.actor = actor;
1514  cloud_actor.cells = initcells;
1515  cloud_actor.geometry_handlers.push_back (geometry_handler);
1516 
1517  // Save the viewpoint transformation matrix to the global actor map
1519  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1520  cloud_actor.viewpoint_transformation_ = transformation;
1521  cloud_actor.actor->SetUserMatrix (transformation);
1522  cloud_actor.actor->Modified ();
1523 
1524  return (true);
1525 }
1526 
1527 //////////////////////////////////////////////////////////////////////////////////////////////
1528 template <typename PointT> bool
1530  const std::string &id)
1531 {
1532  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1533  auto am_it = cloud_actor_map_->find (id);
1534 
1535  if (am_it == cloud_actor_map_->end ())
1536  return (false);
1537 
1538  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1539  if (!polydata)
1540  return false;
1541  // Convert the PointCloud to VTK PolyData
1542  convertPointCloudToVTKPolyData<PointT> (cloud, polydata, am_it->second.cells);
1543 
1544  // Set scalars to blank, since there is no way we can update them here.
1546  polydata->GetPointData ()->SetScalars (scalars);
1547  double minmax[2];
1548  minmax[0] = std::numeric_limits<double>::min ();
1549  minmax[1] = std::numeric_limits<double>::max ();
1550  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1551 
1552  // Update the mapper
1553  reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1554  return (true);
1555 }
1556 
1557 /////////////////////////////////////////////////////////////////////////////////////////////
1558 template <typename PointT> bool
1560  const PointCloudGeometryHandler<PointT> &geometry_handler,
1561  const std::string &id)
1562 {
1563  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1564  auto am_it = cloud_actor_map_->find (id);
1565 
1566  if (am_it == cloud_actor_map_->end ())
1567  return (false);
1568 
1569  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1570  if (!polydata)
1571  return (false);
1572  // Convert the PointCloud to VTK PolyData
1573  convertPointCloudToVTKPolyData (geometry_handler, polydata, am_it->second.cells);
1574 
1575  // Set scalars to blank, since there is no way we can update them here.
1577  polydata->GetPointData ()->SetScalars (scalars);
1578  double minmax[2];
1579  minmax[0] = std::numeric_limits<double>::min ();
1580  minmax[1] = std::numeric_limits<double>::max ();
1581  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1582 
1583  // Update the mapper
1584  reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1585  return (true);
1586 }
1587 
1588 
1589 /////////////////////////////////////////////////////////////////////////////////////////////
1590 template <typename PointT> bool
1592  const PointCloudColorHandler<PointT> &color_handler,
1593  const std::string &id)
1594 {
1595  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1596  auto am_it = cloud_actor_map_->find (id);
1597 
1598  if (am_it == cloud_actor_map_->end ())
1599  return (false);
1600 
1601  // Get the current poly data
1602  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1603  if (!polydata)
1604  return (false);
1605 
1606  convertPointCloudToVTKPolyData<PointT>(cloud, polydata, am_it->second.cells);
1607 
1608  // Get the colors from the handler
1609  bool has_colors = false;
1610  double minmax[2];
1611  if (auto scalars = color_handler.getColor ())
1612  {
1613  // Update the data
1614  polydata->GetPointData ()->SetScalars (scalars);
1615  scalars->GetRange (minmax);
1616  has_colors = true;
1617  }
1618 
1619  if (has_colors)
1620  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1621 
1622  // Update the mapper
1623  reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1624  return (true);
1625 }
1626 
1627 /////////////////////////////////////////////////////////////////////////////////////////////
1628 template <typename PointT> bool
1630  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1631  const std::vector<pcl::Vertices> &vertices,
1632  const std::string &id,
1633  int viewport)
1634 {
1635  if (vertices.empty () || cloud->points.empty ())
1636  return (false);
1637 
1638  if (contains (id))
1639  {
1640  PCL_WARN ("[addPolygonMesh] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1641  return (false);
1642  }
1643 
1644  int rgb_idx = -1;
1645  std::vector<pcl::PCLPointField> fields;
1647  rgb_idx = pcl::getFieldIndex<PointT> ("rgb", fields);
1648  if (rgb_idx == -1)
1649  rgb_idx = pcl::getFieldIndex<PointT> ("rgba", fields);
1650  if (rgb_idx != -1)
1651  {
1653  colors->SetNumberOfComponents (3);
1654  colors->SetName ("Colors");
1655  std::uint32_t offset = fields[rgb_idx].offset;
1656  for (std::size_t i = 0; i < cloud->size (); ++i)
1657  {
1658  if (!isFinite ((*cloud)[i]))
1659  continue;
1660  const auto* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
1661  unsigned char color[3];
1662  color[0] = rgb_data->r;
1663  color[1] = rgb_data->g;
1664  color[2] = rgb_data->b;
1665  colors->InsertNextTupleValue (color);
1666  }
1667  }
1668 
1669  // Create points from polyMesh.cloud
1671  vtkIdType nr_points = cloud->size ();
1672  points->SetNumberOfPoints (nr_points);
1674 
1675  // Get a pointer to the beginning of the data array
1676  float *data = dynamic_cast<vtkFloatArray*> (points->GetData ())->GetPointer (0);
1677 
1678  vtkIdType ptr = 0;
1679  std::vector<int> lookup;
1680  // If the dataset is dense (no NaNs)
1681  if (cloud->is_dense)
1682  {
1683  for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3) {
1684  std::copy(&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1685  }
1686  }
1687  else
1688  {
1689  lookup.resize (nr_points);
1690  vtkIdType j = 0; // true point index
1691  for (vtkIdType i = 0; i < nr_points; ++i)
1692  {
1693  // Check if the point is invalid
1694  if (!isFinite ((*cloud)[i]))
1695  continue;
1696 
1697  lookup[i] = static_cast<int> (j);
1698  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1699  j++;
1700  ptr += 3;
1701  }
1702  nr_points = j;
1703  points->SetNumberOfPoints (nr_points);
1704  }
1705 
1706  // Get the maximum size of a polygon
1707  int max_size_of_polygon = -1;
1708  for (const auto &vertex : vertices)
1709  if (max_size_of_polygon < static_cast<int> (vertex.vertices.size ()))
1710  max_size_of_polygon = static_cast<int> (vertex.vertices.size ());
1711 
1712  if (vertices.size () > 1)
1713  {
1714  // Create polys from polyMesh.polygons
1716 
1717  const auto idx = details::fillCells(lookup,vertices,cell_array, max_size_of_polygon);
1718 
1720  allocVtkPolyData (polydata);
1721  cell_array->GetData ()->SetNumberOfValues (idx);
1722  cell_array->Squeeze ();
1723  polydata->SetPolys (cell_array);
1724  polydata->SetPoints (points);
1725 
1726  if (colors)
1727  polydata->GetPointData ()->SetScalars (colors);
1728 
1729  createActorFromVTKDataSet (polydata, actor, false);
1730  }
1731  else
1732  {
1734  std::size_t n_points = vertices[0].vertices.size ();
1735  polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
1736 
1737  if (!lookup.empty ())
1738  {
1739  for (std::size_t j = 0; j < (n_points - 1); ++j)
1740  polygon->GetPointIds ()->SetId (j, lookup[vertices[0].vertices[j]]);
1741  }
1742  else
1743  {
1744  for (std::size_t j = 0; j < (n_points - 1); ++j)
1745  polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
1746  }
1748  allocVtkUnstructuredGrid (poly_grid);
1749  poly_grid->Allocate (1, 1);
1750  poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
1751  poly_grid->SetPoints (points);
1752  if (colors)
1753  poly_grid->GetPointData ()->SetScalars (colors);
1754 
1755  createActorFromVTKDataSet (poly_grid, actor, false);
1756  }
1757  addActorToRenderer (actor, viewport);
1758  actor->GetProperty ()->SetRepresentationToSurface ();
1759  // Backface culling renders the visualization slower, but guarantees that we see all triangles
1760  actor->GetProperty ()->BackfaceCullingOff ();
1761  actor->GetProperty ()->SetInterpolationToFlat ();
1762  actor->GetProperty ()->EdgeVisibilityOff ();
1763  actor->GetProperty ()->ShadingOff ();
1764 
1765  // Save the pointer/ID pair to the global actor map
1766  (*cloud_actor_map_)[id].actor = actor;
1767 
1768  // Save the viewpoint transformation matrix to the global actor map
1770  convertToVtkMatrix (cloud->sensor_origin_, cloud->sensor_orientation_, transformation);
1771  (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
1772 
1773  return (true);
1774 }
1775 
1776 /////////////////////////////////////////////////////////////////////////////////////////////
1777 template <typename PointT> bool
1779  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1780  const std::vector<pcl::Vertices> &verts,
1781  const std::string &id)
1782 {
1783  if (verts.empty ())
1784  {
1785  pcl::console::print_error ("[addPolygonMesh] No vertices given!\n");
1786  return (false);
1787  }
1788 
1789  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1790  auto am_it = cloud_actor_map_->find (id);
1791  if (am_it == cloud_actor_map_->end ())
1792  return (false);
1793 
1794  // Get the current poly data
1795  vtkSmartPointer<vtkPolyData> polydata = dynamic_cast<vtkPolyData*>(am_it->second.actor->GetMapper ()->GetInput ());
1796  if (!polydata)
1797  return (false);
1798  vtkSmartPointer<vtkCellArray> cells = polydata->GetPolys ();
1799  if (!cells)
1800  return (false);
1801  vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
1802  // Copy the new point array in
1803  vtkIdType nr_points = cloud->size ();
1804  points->SetNumberOfPoints (nr_points);
1805 
1806  // Get a pointer to the beginning of the data array
1807  float *data = (dynamic_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
1808 
1809  int ptr = 0;
1810  std::vector<int> lookup;
1811  // If the dataset is dense (no NaNs)
1812  if (cloud->is_dense)
1813  {
1814  for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
1815  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1816  }
1817  else
1818  {
1819  lookup.resize (nr_points);
1820  vtkIdType j = 0; // true point index
1821  for (vtkIdType i = 0; i < nr_points; ++i)
1822  {
1823  // Check if the point is invalid
1824  if (!isFinite ((*cloud)[i]))
1825  continue;
1826 
1827  lookup [i] = static_cast<int> (j);
1828  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1829  j++;
1830  ptr += 3;
1831  }
1832  nr_points = j;
1833  points->SetNumberOfPoints (nr_points);
1834  }
1835 
1836  // Update colors
1837  vtkUnsignedCharArray* colors = vtkUnsignedCharArray::SafeDownCast (polydata->GetPointData ()->GetScalars ());
1838  if (!colors)
1839  return (false);
1840  int rgb_idx = -1;
1841  std::vector<pcl::PCLPointField> fields;
1842  rgb_idx = pcl::getFieldIndex<PointT> ("rgb", fields);
1843  if (rgb_idx == -1)
1844  rgb_idx = pcl::getFieldIndex<PointT> ("rgba", fields);
1845  if (rgb_idx != -1 && colors)
1846  {
1847  int j = 0;
1848  std::uint32_t offset = fields[rgb_idx].offset;
1849  for (std::size_t i = 0; i < cloud->size (); ++i)
1850  {
1851  if (!isFinite ((*cloud)[i]))
1852  continue;
1853  const auto* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
1854  unsigned char color[3];
1855  color[0] = rgb_data->r;
1856  color[1] = rgb_data->g;
1857  color[2] = rgb_data->b;
1858  colors->SetTupleValue (j++, color);
1859  }
1860  }
1861 
1862  // Get the maximum size of a polygon
1863  int max_size_of_polygon = -1;
1864  for (const auto &vertex : verts)
1865  if (max_size_of_polygon < static_cast<int> (vertex.vertices.size ()))
1866  max_size_of_polygon = static_cast<int> (vertex.vertices.size ());
1867 
1868  // Update the cells
1870 
1871  const auto idx = details::fillCells(lookup, verts, cells, max_size_of_polygon);
1872 
1873  cells->GetData ()->SetNumberOfValues (idx);
1874  cells->Squeeze ();
1875  // Set the the vertices
1876  polydata->SetPolys (cells);
1877 
1878  return (true);
1879 }
1880 
1881 #ifdef vtkGenericDataArray_h
1882 #undef SetTupleValue
1883 #undef InsertNextTupleValue
1884 #undef GetTupleValue
1885 #endif
1886 
1887 #endif
bool isCapable() const
Check if this handler is capable of handling the input data or not.
static constexpr index_t UNAVAILABLE
Definition: pcl_base.h:62
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
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
Definition: point_cloud.h:395
virtual vtkSmartPointer< vtkDataArray > getColor() const =0
Obtain the actual color for the input dataset as a VTK data array.
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.
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 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.
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.
std::uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:398
Eigen::Vector4f sensor_origin_
Sensor acquisition pose (origin/translation).
Definition: point_cloud.h:406
A structure representing RGB color information.
ColorHandler::ConstPtr ColorHandlerConstPtr
void ignore(const T &...)
Utility function to eliminate unused variable warnings.
Definition: utils.h:62
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.
PlanarPolygon represents a planar (2D) polygon, potentially in a 3D space.
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:408
vtkSmartPointer< vtkLODActor > actor
The actor holding the data to render.
Definition: actor_map.h:75
std::uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:400
bool addArrow(const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id="arrow", int viewport=0)
Add a line arrow segment between two points, and display the distance between them.
PCL_EXPORTS void allocVtkUnstructuredGrid(vtkSmartPointer< vtkUnstructuredGrid > &polydata)
Allocate a new unstructured grid smartpointer.
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
Check 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 in any of their floating point fields)...
Definition: point_cloud.h:403
PCL_EXPORTS vtkIdType fillCells(std::vector< int > &lookup, const std::vector< pcl::Vertices > &vertices, vtkSmartPointer< vtkCellArray > cell_array, int max_size_of_polygon)
constexpr bool isNormalFinite(const PointT &) noexcept
Definition: point_tests.h:131
shared_ptr< const PointCloud< PointT > > ConstPtr
Definition: point_cloud.h:414
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:310
Base handler class for PointCloud geometry.
std::vector< pcl::Correspondence, Eigen::aligned_allocator< pcl::Correspondence > > Correspondences
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.
std::size_t size() const
Definition: point_cloud.h:443
bool updateSphere(const PointT &center, double radius, double r, double g, double b, const std::string &id="sphere")
Update an existing sphere shape from a point and a radius.
bool addPointCloudNormals(const typename pcl::PointCloud< PointNT >::ConstPtr &cloud, int level=100, float scale=0.02f, const std::string &id="cloud", int viewport=0)
Add the estimated surface normals of a Point Cloud to screen.
PCL_EXPORTS vtkSmartPointer< vtkDataSet > createLine(const Eigen::Vector4f &pt1, const Eigen::Vector4f &pt2)
Create a line shape from two points.
bool updatePolygonMesh(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, const std::vector< pcl::Vertices > &vertices, const std::string &id="polygon")
Update a PolygonMesh object on screen.
PCL_EXPORTS void print_error(const char *format,...)
Print an error message on stream with colors.
bool empty() const
Definition: point_cloud.h:446