Point Cloud Library (PCL)  1.15.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 (!pcl::isXYZFinite((*cloud)[i]))
263  continue;
264 
265  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
266  j++;
267  ptr += 3;
268  }
269  nr_points = j;
270  points->SetNumberOfPoints (nr_points);
271  }
272 
273 #ifdef VTK_CELL_ARRAY_V2
274  // TODO: Remove when VTK 6,7,8 is unsupported
275  pcl::utils::ignore(initcells);
276 
277  auto numOfCells = vertices->GetNumberOfCells();
278 
279  // If we have less cells than points, add new cells.
280  if (numOfCells < nr_points)
281  {
282  for (int i = numOfCells; i < nr_points; i++)
283  {
284  vertices->InsertNextCell(1);
285  vertices->InsertCellPoint(i);
286  }
287  }
288  // if we too many cells than points, set size (doesn't free excessive memory)
289  else if (numOfCells > nr_points)
290  {
291  vertices->ResizeExact(nr_points, nr_points);
292  }
293 
294  polydata->SetPoints(points);
295  polydata->SetVerts(vertices);
296 
297 #else
298  vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
299  updateCells (cells, initcells, nr_points);
300 
301  // Set the cells and the vertices
302  vertices->SetCells (nr_points, cells);
303 
304  // Set the cell count explicitly as the array doesn't get modified enough so the above method updates accordingly. See #4001 and #3452
305  vertices->SetNumberOfCells(nr_points);
306 #endif
307 }
308 
309 //////////////////////////////////////////////////////////////////////////////////////////////
310 template <typename PointT> void
311 pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData (
315 {
317  if (!polydata)
318  {
319  allocVtkPolyData (polydata);
321  polydata->SetVerts (vertices);
322  }
323 
324  // Use the handler to obtain the geometry
326  geometry_handler.getGeometry (points);
327  polydata->SetPoints (points);
328 
329  vtkIdType nr_points = points->GetNumberOfPoints ();
330 
331  // Create the supporting structures
332  vertices = polydata->GetVerts ();
333  if (!vertices)
335 
336 #ifdef VTK_CELL_ARRAY_V2
337  // TODO: Remove when VTK 6,7,8 is unsupported
338  pcl::utils::ignore(initcells);
339 
340  auto numOfCells = vertices->GetNumberOfCells();
341 
342  // If we have less cells than points, add new cells.
343  if (numOfCells < nr_points)
344  {
345  for (int i = numOfCells; i < nr_points; i++)
346  {
347  vertices->InsertNextCell(1);
348  vertices->InsertCellPoint(i);
349  }
350  }
351  // if we too many cells than points, set size (doesn't free excessive memory)
352  else if (numOfCells > nr_points)
353  {
354  vertices->ResizeExact(nr_points, nr_points);
355  }
356 
357  polydata->SetPoints(points);
358  polydata->SetVerts(vertices);
359 
360 #else
361  vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
362  updateCells (cells, initcells, nr_points);
363  // Set the cells and the vertices
364  vertices->SetCells (nr_points, cells);
365 #endif
366 }
367 
368 ////////////////////////////////////////////////////////////////////////////////////////////
369 template <typename PointT> bool
371  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
372  double r, double g, double b, const std::string &id, int viewport)
373 {
374  vtkSmartPointer<vtkDataSet> data = createPolygon<PointT> (cloud);
375  if (!data)
376  return (false);
377 
378  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
379  auto am_it = shape_actor_map_->find (id);
380  if (am_it != shape_actor_map_->end ())
381  {
383 
384  // Add old data
385  all_data->AddInputData (reinterpret_cast<vtkPolyDataMapper*> ((vtkActor::SafeDownCast (am_it->second))->GetMapper ())->GetInput ());
386 
387  // Add new data
389  surface_filter->AddInputData (vtkUnstructuredGrid::SafeDownCast (data));
390  vtkSmartPointer<vtkPolyData> poly_data = surface_filter->GetOutput ();
391  all_data->AddInputData (poly_data);
392 
393  // Create an Actor
395  createActorFromVTKDataSet (all_data->GetOutput (), actor);
396  actor->GetProperty ()->SetRepresentationToWireframe ();
397  actor->GetProperty ()->SetColor (r, g, b);
398  actor->GetMapper ()->ScalarVisibilityOff ();
399  removeActorFromRenderer (am_it->second, viewport);
400  addActorToRenderer (actor, viewport);
401 
402  // Save the pointer/ID pair to the global actor map
403  (*shape_actor_map_)[id] = actor;
404  }
405  else
406  {
407  // Create an Actor
409  createActorFromVTKDataSet (data, actor);
410  actor->GetProperty ()->SetRepresentationToWireframe ();
411  actor->GetProperty ()->SetColor (r, g, b);
412  actor->GetMapper ()->ScalarVisibilityOff ();
413  addActorToRenderer (actor, viewport);
414 
415  // Save the pointer/ID pair to the global actor map
416  (*shape_actor_map_)[id] = actor;
417  }
418 
419  return (true);
420 }
421 
422 ////////////////////////////////////////////////////////////////////////////////////////////
423 template <typename PointT> bool
425  const pcl::PlanarPolygon<PointT> &polygon,
426  double r, double g, double b, const std::string &id, int viewport)
427 {
428  vtkSmartPointer<vtkDataSet> data = createPolygon<PointT> (polygon);
429  if (!data)
430  return (false);
431 
432  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
433  auto am_it = shape_actor_map_->find (id);
434  if (am_it != shape_actor_map_->end ())
435  {
437 
438  // Add old data
439  all_data->AddInputData (reinterpret_cast<vtkPolyDataMapper*> ((vtkActor::SafeDownCast (am_it->second))->GetMapper ())->GetInput ());
440 
441  // Add new data
443  surface_filter->SetInputData (vtkUnstructuredGrid::SafeDownCast (data));
444  vtkSmartPointer<vtkPolyData> poly_data = surface_filter->GetOutput ();
445  all_data->AddInputData (poly_data);
446 
447  // Create an Actor
449  createActorFromVTKDataSet (all_data->GetOutput (), actor);
450  actor->GetProperty ()->SetRepresentationToWireframe ();
451  actor->GetProperty ()->SetColor (r, g, b);
452  actor->GetMapper ()->ScalarVisibilityOn ();
453  actor->GetProperty ()->BackfaceCullingOff ();
454  removeActorFromRenderer (am_it->second, viewport);
455  addActorToRenderer (actor, viewport);
456 
457  // Save the pointer/ID pair to the global actor map
458  (*shape_actor_map_)[id] = actor;
459  }
460  else
461  {
462  // Create an Actor
464  createActorFromVTKDataSet (data, actor);
465  actor->GetProperty ()->SetRepresentationToWireframe ();
466  actor->GetProperty ()->SetColor (r, g, b);
467  actor->GetMapper ()->ScalarVisibilityOn ();
468  actor->GetProperty ()->BackfaceCullingOff ();
469  addActorToRenderer (actor, viewport);
470 
471  // Save the pointer/ID pair to the global actor map
472  (*shape_actor_map_)[id] = actor;
473  }
474  return (true);
475 }
476 
477 ////////////////////////////////////////////////////////////////////////////////////////////
478 template <typename PointT> bool
480  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
481  const std::string &id, int viewport)
482 {
483  return (addPolygon<PointT> (cloud, 0.5, 0.5, 0.5, id, viewport));
484 }
485 
486 ////////////////////////////////////////////////////////////////////////////////////////////
487 template <typename P1, typename P2> bool
488 pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
489 {
490  if (contains (id))
491  {
492  PCL_WARN ("[addLine] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
493  return (false);
494  }
495 
496  vtkSmartPointer<vtkDataSet> data = createLine (pt1.getVector4fMap (), pt2.getVector4fMap ());
497 
498  // Create an Actor
500  createActorFromVTKDataSet (data, actor);
501  actor->GetProperty ()->SetRepresentationToWireframe ();
502  actor->GetProperty ()->SetColor (r, g, b);
503  actor->GetMapper ()->ScalarVisibilityOff ();
504  addActorToRenderer (actor, viewport);
505 
506  // Save the pointer/ID pair to the global actor map
507  (*shape_actor_map_)[id] = actor;
508  return (true);
509 }
510 
511 ////////////////////////////////////////////////////////////////////////////////////////////
512 template <typename P1, typename P2> bool
513 pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
514 {
515  if (contains (id))
516  {
517  PCL_WARN ("[addArrow] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
518  return (false);
519  }
520 
521  // Create an Actor
523  leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
524  leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
525  leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
526  leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
527  leader->SetArrowStyleToFilled ();
528  leader->AutoLabelOn ();
529 
530  leader->GetProperty ()->SetColor (r, g, b);
531  addActorToRenderer (leader, viewport);
532 
533  // Save the pointer/ID pair to the global actor map
534  (*shape_actor_map_)[id] = leader;
535  return (true);
536 }
537 
538 ////////////////////////////////////////////////////////////////////////////////////////////
539 template <typename P1, typename P2> bool
540 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)
541 {
542  if (contains (id))
543  {
544  PCL_WARN ("[addArrow] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
545  return (false);
546  }
547 
548  // Create an Actor
550  leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
551  leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
552  leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
553  leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
554  leader->SetArrowStyleToFilled ();
555  leader->SetArrowPlacementToPoint1 ();
556  if (display_length)
557  leader->AutoLabelOn ();
558  else
559  leader->AutoLabelOff ();
560 
561  leader->GetProperty ()->SetColor (r, g, b);
562  addActorToRenderer (leader, viewport);
563 
564  // Save the pointer/ID pair to the global actor map
565  (*shape_actor_map_)[id] = leader;
566  return (true);
567 }
568 ////////////////////////////////////////////////////////////////////////////////////////////
569 template <typename P1, typename P2> bool
570 pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2,
571  double r_line, double g_line, double b_line,
572  double r_text, double g_text, double b_text,
573  const std::string &id, int viewport)
574 {
575  if (contains (id))
576  {
577  PCL_WARN ("[addArrow] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
578  return (false);
579  }
580 
581  // Create an Actor
583  leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
584  leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
585  leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
586  leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
587  leader->SetArrowStyleToFilled ();
588  leader->AutoLabelOn ();
589 
590  leader->GetLabelTextProperty()->SetColor(r_text, g_text, b_text);
591 
592  leader->GetProperty ()->SetColor (r_line, g_line, b_line);
593  addActorToRenderer (leader, viewport);
594 
595  // Save the pointer/ID pair to the global actor map
596  (*shape_actor_map_)[id] = leader;
597  return (true);
598 }
599 
600 ////////////////////////////////////////////////////////////////////////////////////////////
601 template <typename P1, typename P2> bool
602 pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, const std::string &id, int viewport)
603 {
604  return (addLine (pt1, pt2, 0.5, 0.5, 0.5, id, viewport));
605 }
606 
607 ////////////////////////////////////////////////////////////////////////////////////////////
608 template <typename PointT> bool
609 pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, double r, double g, double b, const std::string &id, int viewport)
610 {
611  if (contains (id))
612  {
613  PCL_WARN ("[addSphere] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
614  return (false);
615  }
616 
618  data->SetRadius (radius);
619  data->SetCenter (static_cast<double>(center.x), static_cast<double>(center.y), static_cast<double>(center.z));
620  data->SetPhiResolution (10);
621  data->SetThetaResolution (10);
622  data->LatLongTessellationOff ();
623  data->Update ();
624 
625  // Setup actor and mapper
627  mapper->SetInputConnection (data->GetOutputPort ());
628 
629  // Create an Actor
631  actor->SetMapper (mapper);
632  //createActorFromVTKDataSet (data, actor);
633  actor->GetProperty ()->SetRepresentationToSurface ();
634  actor->GetProperty ()->SetInterpolationToFlat ();
635  actor->GetProperty ()->SetColor (r, g, b);
636  actor->GetMapper ()->StaticOn ();
637  actor->GetMapper ()->ScalarVisibilityOff ();
638  actor->GetMapper ()->Update ();
639  addActorToRenderer (actor, viewport);
640 
641  // Save the pointer/ID pair to the global actor map
642  (*shape_actor_map_)[id] = actor;
643  return (true);
644 }
645 
646 ////////////////////////////////////////////////////////////////////////////////////////////
647 template <typename PointT> bool
648 pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, const std::string &id, int viewport)
649 {
650  return (addSphere (center, radius, 0.5, 0.5, 0.5, id, viewport));
651 }
652 
653 ////////////////////////////////////////////////////////////////////////////////////////////
654 template<typename PointT> bool
655 pcl::visualization::PCLVisualizer::updateSphere (const PointT &center, double radius, double r, double g, double b, const std::string &id)
656 {
657  if (!contains (id))
658  {
659  return (false);
660  }
661 
662  //////////////////////////////////////////////////////////////////////////
663  // Get the actor pointer
664  auto am_it = shape_actor_map_->find (id);
665  vtkLODActor* actor = vtkLODActor::SafeDownCast (am_it->second);
666  if (!actor)
667  return (false);
668  vtkAlgorithm *algo = actor->GetMapper ()->GetInputAlgorithm ();
669  vtkSphereSource *src = vtkSphereSource::SafeDownCast (algo);
670  if (!src)
671  return (false);
672 
673  src->SetCenter (double (center.x), double (center.y), double (center.z));
674  src->SetRadius (radius);
675  src->Update ();
676  actor->GetProperty ()->SetColor (r, g, b);
677  actor->Modified ();
678 
679  return (true);
680 }
681 
682 //////////////////////////////////////////////////
683 template <typename PointT> bool
685  const std::string &text,
686  const PointT& position,
687  double textScale,
688  double r,
689  double g,
690  double b,
691  const std::string &id,
692  int viewport)
693 {
694  std::string tid;
695  if (id.empty ())
696  tid = text;
697  else
698  tid = id;
699 
700  if (viewport < 0)
701  return false;
702 
703  // If there is no custom viewport and the viewport number is not 0, exit
704  if (rens_->GetNumberOfItems () <= viewport)
705  {
706  PCL_ERROR ("[addText3D] The viewport [%d] doesn't exist (id <%s>)! \n",
707  viewport,
708  tid.c_str ());
709  return false;
710  }
711 
712  // check all or an individual viewport for a similar id
713  rens_->InitTraversal ();
714  for (std::size_t i = viewport; rens_->GetNextItem (); ++i)
715  {
716  const std::string uid = tid + std::string (i, '*');
717  if (contains (uid))
718  {
719  PCL_ERROR ( "[addText3D] The id <%s> already exists in viewport [%d]! \n"
720  "Please choose a different id and retry.\n",
721  tid.c_str (),
722  i);
723  return false;
724  }
725 
726  if (viewport > 0)
727  break;
728  }
729 
731  textSource->SetText (text.c_str());
732  textSource->Update ();
733 
735  textMapper->SetInputConnection (textSource->GetOutputPort ());
736 
737  // Since each follower may follow a different camera, we need different followers
738  rens_->InitTraversal ();
739  vtkRenderer* renderer;
740  int i = 0;
741  while ((renderer = rens_->GetNextItem ()))
742  {
743  // Should we add the actor to all renderers or just to i-nth renderer?
744  if (viewport == 0 || viewport == i)
745  {
747  textActor->SetMapper (textMapper);
748  textActor->SetPosition (position.x, position.y, position.z);
749  textActor->SetScale (textScale);
750  textActor->GetProperty ()->SetColor (r, g, b);
751  textActor->SetCamera (renderer->GetActiveCamera ());
752 
753  renderer->AddActor (textActor);
754 
755  // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
756  // for multiple viewport
757  const std::string uid = tid + std::string (i, '*');
758  (*shape_actor_map_)[uid] = textActor;
759  }
760 
761  ++i;
762  }
763 
764  return (true);
765 }
766 
767 //////////////////////////////////////////////////
768 template <typename PointT> bool
770  const std::string &text,
771  const PointT& position,
772  double orientation[3],
773  double textScale,
774  double r,
775  double g,
776  double b,
777  const std::string &id,
778  int viewport)
779 {
780  std::string tid;
781  if (id.empty ())
782  tid = text;
783  else
784  tid = id;
785 
786  if (viewport < 0)
787  return false;
788 
789  // If there is no custom viewport and the viewport number is not 0, exit
790  if (rens_->GetNumberOfItems () <= viewport)
791  {
792  PCL_ERROR ("[addText3D] The viewport [%d] doesn't exist (id <%s>)!\n",
793  viewport,
794  tid.c_str ());
795  return false;
796  }
797 
798  // check all or an individual viewport for a similar id
799  rens_->InitTraversal ();
800  for (std::size_t i = viewport; rens_->GetNextItem (); ++i)
801  {
802  const std::string uid = tid + std::string (i, '*');
803  if (contains (uid))
804  {
805  PCL_ERROR ( "[addText3D] The id <%s> already exists in viewport [%d]! "
806  "Please choose a different id and retry.\n",
807  tid.c_str (),
808  i);
809  return false;
810  }
811 
812  if (viewport > 0)
813  break;
814  }
815 
817  textSource->SetText (text.c_str());
818  textSource->Update ();
819 
821  textMapper->SetInputConnection (textSource->GetOutputPort ());
822 
824  textActor->SetMapper (textMapper);
825  textActor->SetPosition (position.x, position.y, position.z);
826  textActor->SetScale (textScale);
827  textActor->GetProperty ()->SetColor (r, g, b);
828  textActor->SetOrientation (orientation);
829 
830  // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
831  rens_->InitTraversal ();
832  int i = 0;
833  for ( vtkRenderer* renderer = rens_->GetNextItem ();
834  renderer;
835  renderer = rens_->GetNextItem (), ++i)
836  {
837  if (viewport == 0 || viewport == i)
838  {
839  renderer->AddActor (textActor);
840  const std::string uid = tid + std::string (i, '*');
841  (*shape_actor_map_)[uid] = textActor;
842  }
843  }
844 
845  return (true);
846 }
847 
848 //////////////////////////////////////////////////////////////////////////////////////////////
849 template <typename PointNT> bool
851  const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
852  int level, float scale, const std::string &id, int viewport)
853 {
854  return (addPointCloudNormals<PointNT, PointNT> (cloud, cloud, level, scale, id, viewport));
855 }
856 
857 //////////////////////////////////////////////////////////////////////////////////////////////
858 template <typename PointT, typename PointNT> bool
860  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
861  const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
862  int level, float scale,
863  const std::string &id, int viewport)
864 {
865  if (normals->size () != cloud->size ())
866  {
867  PCL_ERROR ("[addPointCloudNormals] The number of points differs from the number of normals!\n");
868  return (false);
869  }
870 
871  if (normals->empty ())
872  {
873  PCL_WARN ("[addPointCloudNormals] An empty normal cloud is given! Nothing to display.\n");
874  return (false);
875  }
876 
877  if (contains (id))
878  {
879  PCL_WARN ("[addPointCloudNormals] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
880  return (false);
881  }
882 
885 
886  points->SetDataTypeToFloat ();
888  data->SetNumberOfComponents (3);
889 
890 
891  vtkIdType nr_normals = 0;
892  float* pts = nullptr;
893 
894  // If the cloud is organized, then distribute the normal step in both directions
895  if (cloud->isOrganized () && normals->isOrganized ())
896  {
897  auto point_step = static_cast<vtkIdType> (sqrt (static_cast<double>(level)));
898  nr_normals = (static_cast<vtkIdType> ((cloud->width - 1)/ point_step) + 1) *
899  (static_cast<vtkIdType> ((cloud->height - 1) / point_step) + 1);
900  pts = new float[2 * nr_normals * 3];
901 
902  vtkIdType cell_count = 0;
903  for (vtkIdType y = 0; y < normals->height; y += point_step)
904  for (vtkIdType x = 0; x < normals->width; x += point_step)
905  {
906  PointT p = (*cloud)(x, y);
907  if (!pcl::isFinite(p) || !pcl::isNormalFinite((*normals)(x, y)))
908  continue;
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  nr_normals = cell_count;
926  }
927  else
928  {
929  nr_normals = (cloud->size () - 1) / level + 1 ;
930  pts = new float[2 * nr_normals * 3];
931 
932  vtkIdType j = 0;
933  for (vtkIdType i = 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  nr_normals = j;
955  }
956 
957  data->SetArray (&pts[0], 2 * nr_normals * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
958  points->SetData (data);
959 
961  polyData->SetPoints (points);
962  polyData->SetLines (lines);
963 
965  mapper->SetInputData (polyData);
966  mapper->SetColorModeToMapScalars();
967  mapper->SetScalarModeToUsePointData();
968 
969  // create actor
971  actor->SetMapper (mapper);
972 
973  // Use cloud view point info
975  convertToVtkMatrix (cloud->sensor_origin_, cloud->sensor_orientation_, transformation);
976  actor->SetUserMatrix (transformation);
977 
978  // Add it to all renderers
979  addActorToRenderer (actor, viewport);
980 
981  // Save the pointer/ID pair to the global actor map
982  (*cloud_actor_map_)[id].actor = actor;
983  return (true);
984 }
985 
986 //////////////////////////////////////////////////////////////////////////////////////////////
987 template <typename PointNT> bool
989  const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
991  int level, float scale,
992  const std::string &id, int viewport)
993 {
994  return (addPointCloudPrincipalCurvatures<PointNT, PointNT> (cloud, cloud, pcs, level, scale, id, viewport));
995 }
996 
997 //////////////////////////////////////////////////////////////////////////////////////////////
998 template <typename PointT, typename PointNT> bool
1000  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1001  const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
1003  int level, float scale,
1004  const std::string &id, int viewport)
1005 {
1006  if (pcs->size () != cloud->size () || normals->size () != cloud->size ())
1007  {
1008  pcl::console::print_error ("[addPointCloudPrincipalCurvatures] The number of points differs from the number of principal curvatures/normals!\n");
1009  return (false);
1010  }
1011 
1012  if (contains (id))
1013  {
1014  PCL_WARN ("[addPointCloudPrincipalCurvatures] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1015  return (false);
1016  }
1017 
1020 
1021  // Setup two colors - one for each line
1022  unsigned char green[3] = {0, 255, 0};
1023  unsigned char blue[3] = {0, 0, 255};
1024 
1025  // Setup the colors array
1027  line_1_colors->SetNumberOfComponents (3);
1028  line_1_colors->SetName ("Colors");
1030  line_2_colors->SetNumberOfComponents (3);
1031  line_2_colors->SetName ("Colors");
1032 
1033  // Create the first sets of lines
1034  for (std::size_t i = 0; i < cloud->size (); i+=level)
1035  {
1036  PointT p = (*cloud)[i];
1037  p.x += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[0]) * scale;
1038  p.y += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[1]) * scale;
1039  p.z += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[2]) * scale;
1040 
1042  line_1->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1043  line_1->SetPoint2 (p.x, p.y, p.z);
1044  line_1->Update ();
1045  polydata_1->AddInputData (line_1->GetOutput ());
1046  line_1_colors->InsertNextTupleValue (green);
1047  }
1048  polydata_1->Update ();
1049  vtkSmartPointer<vtkPolyData> line_1_data = polydata_1->GetOutput ();
1050  line_1_data->GetCellData ()->SetScalars (line_1_colors);
1051 
1052  // Create the second sets of lines
1053  for (std::size_t i = 0; i < cloud->size (); i += level)
1054  {
1055  Eigen::Vector3f pc ((*pcs)[i].principal_curvature[0],
1056  (*pcs)[i].principal_curvature[1],
1057  (*pcs)[i].principal_curvature[2]);
1058  Eigen::Vector3f normal ((*normals)[i].normal[0],
1059  (*normals)[i].normal[1],
1060  (*normals)[i].normal[2]);
1061  Eigen::Vector3f pc_c = pc.cross (normal);
1062 
1063  PointT p = (*cloud)[i];
1064  p.x += ((*pcs)[i].pc2 * pc_c[0]) * scale;
1065  p.y += ((*pcs)[i].pc2 * pc_c[1]) * scale;
1066  p.z += ((*pcs)[i].pc2 * pc_c[2]) * scale;
1067 
1069  line_2->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1070  line_2->SetPoint2 (p.x, p.y, p.z);
1071  line_2->Update ();
1072  polydata_2->AddInputData (line_2->GetOutput ());
1073 
1074  line_2_colors->InsertNextTupleValue (blue);
1075  }
1076  polydata_2->Update ();
1077  vtkSmartPointer<vtkPolyData> line_2_data = polydata_2->GetOutput ();
1078  line_2_data->GetCellData ()->SetScalars (line_2_colors);
1079 
1080  // Assemble the two sets of lines
1082  alldata->AddInputData (line_1_data);
1083  alldata->AddInputData (line_2_data);
1084  alldata->Update ();
1085 
1086  // Create an Actor
1088  createActorFromVTKDataSet (alldata->GetOutput (), actor);
1089  actor->GetMapper ()->SetScalarModeToUseCellData ();
1090 
1091  // Add it to all renderers
1092  addActorToRenderer (actor, viewport);
1093 
1094  // Save the pointer/ID pair to the global actor map
1095  CloudActor act;
1096  act.actor = actor;
1097  (*cloud_actor_map_)[id] = act;
1098  return (true);
1099 }
1100 
1101 //////////////////////////////////////////////////////////////////////////////////////////////
1102 template <typename PointT, typename GradientT> bool
1104  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1105  const typename pcl::PointCloud<GradientT>::ConstPtr &gradients,
1106  int level, double scale,
1107  const std::string &id, int viewport)
1108 {
1109  if (gradients->size () != cloud->size ())
1110  {
1111  PCL_ERROR ("[addPointCloudGradients] The number of points differs from the number of gradients!\n");
1112  return (false);
1113  }
1114  if (contains (id))
1115  {
1116  PCL_WARN ("[addPointCloudGradients] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1117  return (false);
1118  }
1119 
1122 
1123  points->SetDataTypeToFloat ();
1125  data->SetNumberOfComponents (3);
1126 
1127  vtkIdType nr_gradients = (cloud->size () - 1) / level + 1 ;
1128  float* pts = new float[2 * nr_gradients * 3];
1129 
1130  for (vtkIdType i = 0, j = 0; j < nr_gradients; j++, i = j * level)
1131  {
1132  PointT p = (*cloud)[i];
1133  p.x += (*gradients)[i].gradient[0] * scale;
1134  p.y += (*gradients)[i].gradient[1] * scale;
1135  p.z += (*gradients)[i].gradient[2] * scale;
1136 
1137  pts[2 * j * 3 + 0] = (*cloud)[i].x;
1138  pts[2 * j * 3 + 1] = (*cloud)[i].y;
1139  pts[2 * j * 3 + 2] = (*cloud)[i].z;
1140  pts[2 * j * 3 + 3] = p.x;
1141  pts[2 * j * 3 + 4] = p.y;
1142  pts[2 * j * 3 + 5] = p.z;
1143 
1144  lines->InsertNextCell(2);
1145  lines->InsertCellPoint(2*j);
1146  lines->InsertCellPoint(2*j+1);
1147  }
1148 
1149  data->SetArray (&pts[0], 2 * nr_gradients * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
1150  points->SetData (data);
1151 
1153  polyData->SetPoints(points);
1154  polyData->SetLines(lines);
1155 
1157  mapper->SetInputData (polyData);
1158  mapper->SetColorModeToMapScalars();
1159  mapper->SetScalarModeToUsePointData();
1160 
1161  // create actor
1163  actor->SetMapper (mapper);
1164 
1165  // Add it to all renderers
1166  addActorToRenderer (actor, viewport);
1167 
1168  // Save the pointer/ID pair to the global actor map
1169  (*cloud_actor_map_)[id].actor = actor;
1170  return (true);
1171 }
1172 
1173 //////////////////////////////////////////////////////////////////////////////////////////////
1174 template <typename PointT> bool
1176  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1177  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1178  const std::vector<int> &correspondences,
1179  const std::string &id,
1180  int viewport)
1181 {
1182  pcl::Correspondences corrs;
1183  corrs.resize (correspondences.size ());
1184 
1185  std::size_t index = 0;
1186  for (auto &corr : corrs)
1187  {
1188  corr.index_query = index;
1189  corr.index_match = correspondences[index];
1190  index++;
1191  }
1192 
1193  return (addCorrespondences<PointT> (source_points, target_points, corrs, id, viewport));
1194 }
1195 
1196 //////////////////////////////////////////////////////////////////////////////////////////////
1197 template <typename PointT> bool
1199  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1200  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1201  const pcl::Correspondences &correspondences,
1202  int nth,
1203  const std::string &id,
1204  int viewport,
1205  bool overwrite)
1206 {
1207  if (correspondences.empty ())
1208  {
1209  PCL_DEBUG ("[addCorrespondences] An empty set of correspondences given! Nothing to display.\n");
1210  return (false);
1211  }
1212 
1213  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1214  auto am_it = shape_actor_map_->find (id);
1215  if (am_it != shape_actor_map_->end () && !overwrite)
1216  {
1217  PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1218  return (false);
1219  }
1220  if (am_it == shape_actor_map_->end () && overwrite)
1221  {
1222  overwrite = false; // Correspondences doesn't exist, add them instead of updating them
1223  }
1224 
1225  int n_corr = static_cast<int>(correspondences.size () / nth);
1227 
1228  // Prepare colors
1230  line_colors->SetNumberOfComponents (3);
1231  line_colors->SetName ("Colors");
1232  line_colors->SetNumberOfTuples (n_corr);
1233 
1234  // Prepare coordinates
1236  line_points->SetNumberOfPoints (2 * n_corr);
1237 
1239  line_cells_id->SetNumberOfComponents (3);
1240  line_cells_id->SetNumberOfTuples (n_corr);
1241  vtkIdType *line_cell_id = line_cells_id->GetPointer (0);
1243 
1245  line_tcoords->SetNumberOfComponents (1);
1246  line_tcoords->SetNumberOfTuples (n_corr * 2);
1247  line_tcoords->SetName ("Texture Coordinates");
1248 
1249  double tc[3] = {0.0, 0.0, 0.0};
1250 
1251  Eigen::Affine3f source_transformation;
1252  source_transformation.linear () = source_points->sensor_orientation_.matrix ();
1253  source_transformation.translation () = source_points->sensor_origin_.template head<3> ();
1254  Eigen::Affine3f target_transformation;
1255  target_transformation.linear () = target_points->sensor_orientation_.matrix ();
1256  target_transformation.translation () = target_points->sensor_origin_.template head<3> ();
1257 
1258  int j = 0;
1259  // Draw lines between the best corresponding points
1260  for (std::size_t i = 0; i < correspondences.size (); i += nth, ++j)
1261  {
1262  if (correspondences[i].index_match == UNAVAILABLE)
1263  {
1264  PCL_WARN ("[addCorrespondences] No valid index_match for correspondence %d\n", i);
1265  continue;
1266  }
1267 
1268  PointT p_src ((*source_points)[correspondences[i].index_query]);
1269  PointT p_tgt ((*target_points)[correspondences[i].index_match]);
1270 
1271  p_src.getVector3fMap () = source_transformation * p_src.getVector3fMap ();
1272  p_tgt.getVector3fMap () = target_transformation * p_tgt.getVector3fMap ();
1273 
1274  int id1 = j * 2 + 0, id2 = j * 2 + 1;
1275  // Set the points
1276  line_points->SetPoint (id1, p_src.x, p_src.y, p_src.z);
1277  line_points->SetPoint (id2, p_tgt.x, p_tgt.y, p_tgt.z);
1278  // Set the cell ID
1279  *line_cell_id++ = 2;
1280  *line_cell_id++ = id1;
1281  *line_cell_id++ = id2;
1282  // Set the texture coords
1283  tc[0] = 0.; line_tcoords->SetTuple (id1, tc);
1284  tc[0] = 1.; line_tcoords->SetTuple (id2, tc);
1285 
1286  float rgb[3];
1287  rgb[0] = vtkMath::Random (32, 255); // min / max
1288  rgb[1] = vtkMath::Random (32, 255);
1289  rgb[2] = vtkMath::Random (32, 255);
1290  line_colors->InsertTuple (i, rgb);
1291  }
1292  line_colors->SetNumberOfTuples (j);
1293  line_cells_id->SetNumberOfTuples (j);
1294  line_cells->SetCells (n_corr, line_cells_id);
1295  line_points->SetNumberOfPoints (j*2);
1296  line_tcoords->SetNumberOfTuples (j*2);
1297 
1298  // Fill in the lines
1299  line_data->SetPoints (line_points);
1300  line_data->SetLines (line_cells);
1301  line_data->GetPointData ()->SetTCoords (line_tcoords);
1302  line_data->GetCellData ()->SetScalars (line_colors);
1303 
1304  // Create an Actor
1305  if (!overwrite)
1306  {
1308  createActorFromVTKDataSet (line_data, actor);
1309  actor->GetProperty ()->SetRepresentationToWireframe ();
1310  actor->GetProperty ()->SetOpacity (0.5);
1311  addActorToRenderer (actor, viewport);
1312 
1313  // Save the pointer/ID pair to the global actor map
1314  (*shape_actor_map_)[id] = actor;
1315  }
1316  else
1317  {
1318  vtkSmartPointer<vtkLODActor> actor = vtkLODActor::SafeDownCast (am_it->second);
1319  if (!actor)
1320  return (false);
1321  // Update the mapper
1322  reinterpret_cast<vtkPolyDataMapper*> (actor->GetMapper ())->SetInputData (line_data);
1323  }
1324 
1325  return (true);
1326 }
1327 
1328 //////////////////////////////////////////////////////////////////////////////////////////////
1329 template <typename PointT> bool
1331  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1332  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1333  const pcl::Correspondences &correspondences,
1334  int nth,
1335  const std::string &id,
1336  int viewport)
1337 {
1338  return (addCorrespondences<PointT> (source_points, target_points, correspondences, nth, id, viewport, true));
1339 }
1340 
1341 //////////////////////////////////////////////////////////////////////////////////////////////
1342 template <typename PointT> bool
1343 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1344  const PointCloudGeometryHandler<PointT> &geometry_handler,
1345  const PointCloudColorHandler<PointT> &color_handler,
1346  const std::string &id,
1347  int viewport,
1348  const Eigen::Vector4f& sensor_origin,
1349  const Eigen::Quaternion<float>& sensor_orientation)
1350 {
1351  if (!geometry_handler.isCapable ())
1352  {
1353  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1354  return (false);
1355  }
1356 
1357  if (!color_handler.isCapable ())
1358  {
1359  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1360  return (false);
1361  }
1362 
1365  // Convert the PointCloud to VTK PolyData
1366  convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1367 
1368  // Get the colors from the handler
1369  bool has_colors = false;
1370  double minmax[2];
1371  if (auto scalars = color_handler.getColor ())
1372  {
1373  polydata->GetPointData ()->SetScalars (scalars);
1374  scalars->GetRange (minmax);
1375  has_colors = true;
1376  }
1377 
1378  // Create an Actor
1380  createActorFromVTKDataSet (polydata, actor);
1381  if (has_colors)
1382  actor->GetMapper ()->SetScalarRange (minmax);
1383 
1384  // Add it to all renderers
1385  addActorToRenderer (actor, viewport);
1386 
1387  // Save the pointer/ID pair to the global actor map
1388  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1389  cloud_actor.actor = actor;
1390  cloud_actor.cells = initcells;
1391 
1392  // Save the viewpoint transformation matrix to the global actor map
1394  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1395  cloud_actor.viewpoint_transformation_ = transformation;
1396  cloud_actor.actor->SetUserMatrix (transformation);
1397  cloud_actor.actor->Modified ();
1398 
1399  return (true);
1400 }
1401 
1402 //////////////////////////////////////////////////////////////////////////////////////////////
1403 template <typename PointT> bool
1404 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1405  const PointCloudGeometryHandler<PointT> &geometry_handler,
1406  const ColorHandlerConstPtr &color_handler,
1407  const std::string &id,
1408  int viewport,
1409  const Eigen::Vector4f& sensor_origin,
1410  const Eigen::Quaternion<float>& sensor_orientation)
1411 {
1412  if (!geometry_handler.isCapable ())
1413  {
1414  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1415  return (false);
1416  }
1417 
1418  if (!color_handler->isCapable ())
1419  {
1420  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler->getName ().c_str ());
1421  return (false);
1422  }
1423 
1426  // Convert the PointCloud to VTK PolyData
1427  convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1428  // use the given geometry handler
1429 
1430  // Get the colors from the handler
1431  bool has_colors = false;
1432  double minmax[2];
1433  if (auto scalars = color_handler->getColor ())
1434  {
1435  polydata->GetPointData ()->SetScalars (scalars);
1436  scalars->GetRange (minmax);
1437  has_colors = true;
1438  }
1439 
1440  // Create an Actor
1442  createActorFromVTKDataSet (polydata, actor);
1443  if (has_colors)
1444  actor->GetMapper ()->SetScalarRange (minmax);
1445 
1446  // Add it to all renderers
1447  addActorToRenderer (actor, viewport);
1448 
1449  // Save the pointer/ID pair to the global actor map
1450  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1451  cloud_actor.actor = actor;
1452  cloud_actor.cells = initcells;
1453  cloud_actor.color_handlers.push_back (color_handler);
1454 
1455  // Save the viewpoint transformation matrix to the global actor map
1457  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1458  cloud_actor.viewpoint_transformation_ = transformation;
1459  cloud_actor.actor->SetUserMatrix (transformation);
1460  cloud_actor.actor->Modified ();
1461 
1462  return (true);
1463 }
1464 
1465 //////////////////////////////////////////////////////////////////////////////////////////////
1466 template <typename PointT> bool
1467 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1468  const GeometryHandlerConstPtr &geometry_handler,
1469  const PointCloudColorHandler<PointT> &color_handler,
1470  const std::string &id,
1471  int viewport,
1472  const Eigen::Vector4f& sensor_origin,
1473  const Eigen::Quaternion<float>& sensor_orientation)
1474 {
1475  if (!geometry_handler->isCapable ())
1476  {
1477  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler->getName ().c_str ());
1478  return (false);
1479  }
1480 
1481  if (!color_handler.isCapable ())
1482  {
1483  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1484  return (false);
1485  }
1486 
1489  // Convert the PointCloud to VTK PolyData
1490  convertPointCloudToVTKPolyData (geometry_handler, polydata, initcells);
1491  // use the given geometry handler
1492 
1493  // Get the colors from the handler
1494  bool has_colors = false;
1495  double minmax[2];
1496  if (auto scalars = color_handler.getColor ())
1497  {
1498  polydata->GetPointData ()->SetScalars (scalars);
1499  scalars->GetRange (minmax);
1500  has_colors = true;
1501  }
1502 
1503  // Create an Actor
1505  createActorFromVTKDataSet (polydata, actor);
1506  if (has_colors)
1507  actor->GetMapper ()->SetScalarRange (minmax);
1508 
1509  // Add it to all renderers
1510  addActorToRenderer (actor, viewport);
1511 
1512  // Save the pointer/ID pair to the global actor map
1513  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1514  cloud_actor.actor = actor;
1515  cloud_actor.cells = initcells;
1516  cloud_actor.geometry_handlers.push_back (geometry_handler);
1517 
1518  // Save the viewpoint transformation matrix to the global actor map
1520  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1521  cloud_actor.viewpoint_transformation_ = transformation;
1522  cloud_actor.actor->SetUserMatrix (transformation);
1523  cloud_actor.actor->Modified ();
1524 
1525  return (true);
1526 }
1527 
1528 //////////////////////////////////////////////////////////////////////////////////////////////
1529 template <typename PointT> bool
1531  const std::string &id)
1532 {
1533  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1534  auto am_it = cloud_actor_map_->find (id);
1535 
1536  if (am_it == cloud_actor_map_->end ())
1537  return (false);
1538 
1539  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1540  if (!polydata)
1541  return false;
1542  // Convert the PointCloud to VTK PolyData
1543  convertPointCloudToVTKPolyData<PointT> (cloud, polydata, am_it->second.cells);
1544 
1545  // Set scalars to blank, since there is no way we can update them here.
1547  polydata->GetPointData ()->SetScalars (scalars);
1548  double minmax[2];
1549  minmax[0] = std::numeric_limits<double>::min ();
1550  minmax[1] = std::numeric_limits<double>::max ();
1551  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1552 
1553  // Update the mapper
1554  reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1555  return (true);
1556 }
1557 
1558 /////////////////////////////////////////////////////////////////////////////////////////////
1559 template <typename PointT> bool
1561  const PointCloudGeometryHandler<PointT> &geometry_handler,
1562  const std::string &id)
1563 {
1564  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1565  auto am_it = cloud_actor_map_->find (id);
1566 
1567  if (am_it == cloud_actor_map_->end ())
1568  return (false);
1569 
1570  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1571  if (!polydata)
1572  return (false);
1573  // Convert the PointCloud to VTK PolyData
1574  convertPointCloudToVTKPolyData (geometry_handler, polydata, am_it->second.cells);
1575 
1576  // Set scalars to blank, since there is no way we can update them here.
1578  polydata->GetPointData ()->SetScalars (scalars);
1579  double minmax[2];
1580  minmax[0] = std::numeric_limits<double>::min ();
1581  minmax[1] = std::numeric_limits<double>::max ();
1582  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1583 
1584  // Update the mapper
1585  reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1586  return (true);
1587 }
1588 
1589 
1590 /////////////////////////////////////////////////////////////////////////////////////////////
1591 template <typename PointT> bool
1593  const PointCloudColorHandler<PointT> &color_handler,
1594  const std::string &id)
1595 {
1596  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1597  auto am_it = cloud_actor_map_->find (id);
1598 
1599  if (am_it == cloud_actor_map_->end ())
1600  return (false);
1601 
1602  // Get the current poly data
1603  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1604  if (!polydata)
1605  return (false);
1606 
1607  convertPointCloudToVTKPolyData<PointT>(cloud, polydata, am_it->second.cells);
1608 
1609  // Get the colors from the handler
1610  bool has_colors = false;
1611  double minmax[2];
1612  if (auto scalars = color_handler.getColor ())
1613  {
1614  // Update the data
1615  polydata->GetPointData ()->SetScalars (scalars);
1616  scalars->GetRange (minmax);
1617  has_colors = true;
1618  }
1619 
1620  if (has_colors)
1621  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1622 
1623  // Update the mapper
1624  reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1625  return (true);
1626 }
1627 
1628 /////////////////////////////////////////////////////////////////////////////////////////////
1629 template <typename PointT> bool
1631  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1632  const std::vector<pcl::Vertices> &vertices,
1633  const std::string &id,
1634  int viewport)
1635 {
1636  if (vertices.empty () || cloud->points.empty ())
1637  return (false);
1638 
1639  if (contains (id))
1640  {
1641  PCL_WARN ("[addPolygonMesh] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1642  return (false);
1643  }
1644 
1645  int rgb_idx = -1;
1646  std::vector<pcl::PCLPointField> fields;
1648  rgb_idx = pcl::getFieldIndex<PointT> ("rgb", fields);
1649  if (rgb_idx == -1)
1650  rgb_idx = pcl::getFieldIndex<PointT> ("rgba", fields);
1651  if (rgb_idx != -1)
1652  {
1654  colors->SetNumberOfComponents (3);
1655  colors->SetName ("Colors");
1656  std::uint32_t offset = fields[rgb_idx].offset;
1657  for (std::size_t i = 0; i < cloud->size (); ++i)
1658  {
1659  if (!isFinite ((*cloud)[i]))
1660  continue;
1661  const auto* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
1662  unsigned char color[3];
1663  color[0] = rgb_data->r;
1664  color[1] = rgb_data->g;
1665  color[2] = rgb_data->b;
1666  colors->InsertNextTupleValue (color);
1667  }
1668  }
1669 
1670  // Create points from polyMesh.cloud
1672  vtkIdType nr_points = cloud->size ();
1673  points->SetNumberOfPoints (nr_points);
1675 
1676  // Get a pointer to the beginning of the data array
1677  float *data = dynamic_cast<vtkFloatArray*> (points->GetData ())->GetPointer (0);
1678 
1679  vtkIdType ptr = 0;
1680  std::vector<int> lookup;
1681  // If the dataset is dense (no NaNs)
1682  if (cloud->is_dense)
1683  {
1684  for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3) {
1685  std::copy(&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1686  }
1687  }
1688  else
1689  {
1690  lookup.resize (nr_points);
1691  vtkIdType j = 0; // true point index
1692  for (vtkIdType i = 0; i < nr_points; ++i)
1693  {
1694  // Check if the point is invalid
1695  if (!isFinite ((*cloud)[i]))
1696  continue;
1697 
1698  lookup[i] = static_cast<int> (j);
1699  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1700  j++;
1701  ptr += 3;
1702  }
1703  nr_points = j;
1704  points->SetNumberOfPoints (nr_points);
1705  }
1706 
1707  // Get the maximum size of a polygon
1708  int max_size_of_polygon = -1;
1709  for (const auto &vertex : vertices)
1710  if (max_size_of_polygon < static_cast<int> (vertex.vertices.size ()))
1711  max_size_of_polygon = static_cast<int> (vertex.vertices.size ());
1712 
1713  if (vertices.size () > 1)
1714  {
1715  // Create polys from polyMesh.polygons
1717 
1718  const auto idx = details::fillCells(lookup,vertices,cell_array, max_size_of_polygon);
1719 
1721  allocVtkPolyData (polydata);
1722  cell_array->GetData ()->SetNumberOfValues (idx);
1723  cell_array->Squeeze ();
1724  polydata->SetPolys (cell_array);
1725  polydata->SetPoints (points);
1726 
1727  if (colors)
1728  polydata->GetPointData ()->SetScalars (colors);
1729 
1730  createActorFromVTKDataSet (polydata, actor, false);
1731  }
1732  else
1733  {
1735  std::size_t n_points = vertices[0].vertices.size ();
1736  polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
1737 
1738  if (!lookup.empty ())
1739  {
1740  for (std::size_t j = 0; j < (n_points - 1); ++j)
1741  polygon->GetPointIds ()->SetId (j, lookup[vertices[0].vertices[j]]);
1742  }
1743  else
1744  {
1745  for (std::size_t j = 0; j < (n_points - 1); ++j)
1746  polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
1747  }
1749  allocVtkUnstructuredGrid (poly_grid);
1750  poly_grid->Allocate (1, 1);
1751  poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
1752  poly_grid->SetPoints (points);
1753  if (colors)
1754  poly_grid->GetPointData ()->SetScalars (colors);
1755 
1756  createActorFromVTKDataSet (poly_grid, actor, false);
1757  }
1758  addActorToRenderer (actor, viewport);
1759  actor->GetProperty ()->SetRepresentationToSurface ();
1760  // Backface culling renders the visualization slower, but guarantees that we see all triangles
1761  actor->GetProperty ()->BackfaceCullingOff ();
1762  actor->GetProperty ()->SetInterpolationToFlat ();
1763  actor->GetProperty ()->EdgeVisibilityOff ();
1764  actor->GetProperty ()->ShadingOff ();
1765 
1766  // Save the pointer/ID pair to the global actor map
1767  (*cloud_actor_map_)[id].actor = actor;
1768 
1769  // Save the viewpoint transformation matrix to the global actor map
1771  convertToVtkMatrix (cloud->sensor_origin_, cloud->sensor_orientation_, transformation);
1772  (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
1773 
1774  return (true);
1775 }
1776 
1777 /////////////////////////////////////////////////////////////////////////////////////////////
1778 template <typename PointT> bool
1780  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1781  const std::vector<pcl::Vertices> &verts,
1782  const std::string &id)
1783 {
1784  if (verts.empty ())
1785  {
1786  pcl::console::print_error ("[addPolygonMesh] No vertices given!\n");
1787  return (false);
1788  }
1789 
1790  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1791  auto am_it = cloud_actor_map_->find (id);
1792  if (am_it == cloud_actor_map_->end ())
1793  return (false);
1794 
1795  // Get the current poly data
1796  vtkSmartPointer<vtkPolyData> polydata = dynamic_cast<vtkPolyData*>(am_it->second.actor->GetMapper ()->GetInput ());
1797  if (!polydata)
1798  return (false);
1799  vtkSmartPointer<vtkCellArray> cells = polydata->GetPolys ();
1800  if (!cells)
1801  return (false);
1802  vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
1803  // Copy the new point array in
1804  vtkIdType nr_points = cloud->size ();
1805  points->SetNumberOfPoints (nr_points);
1806 
1807  // Get a pointer to the beginning of the data array
1808  float *data = (dynamic_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
1809 
1810  int ptr = 0;
1811  std::vector<int> lookup;
1812  // If the dataset is dense (no NaNs)
1813  if (cloud->is_dense)
1814  {
1815  for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
1816  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1817  }
1818  else
1819  {
1820  lookup.resize (nr_points);
1821  vtkIdType j = 0; // true point index
1822  for (vtkIdType i = 0; i < nr_points; ++i)
1823  {
1824  // Check if the point is invalid
1825  if (!isFinite ((*cloud)[i]))
1826  continue;
1827 
1828  lookup [i] = static_cast<int> (j);
1829  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1830  j++;
1831  ptr += 3;
1832  }
1833  nr_points = j;
1834  points->SetNumberOfPoints (nr_points);
1835  }
1836 
1837  // Update colors
1838  vtkUnsignedCharArray* colors = vtkUnsignedCharArray::SafeDownCast (polydata->GetPointData ()->GetScalars ());
1839  if (!colors)
1840  return (false);
1841  int rgb_idx = -1;
1842  std::vector<pcl::PCLPointField> fields;
1843  rgb_idx = pcl::getFieldIndex<PointT> ("rgb", fields);
1844  if (rgb_idx == -1)
1845  rgb_idx = pcl::getFieldIndex<PointT> ("rgba", fields);
1846  if (rgb_idx != -1 && colors)
1847  {
1848  int j = 0;
1849  std::uint32_t offset = fields[rgb_idx].offset;
1850  for (std::size_t i = 0; i < cloud->size (); ++i)
1851  {
1852  if (!isFinite ((*cloud)[i]))
1853  continue;
1854  const auto* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
1855  unsigned char color[3];
1856  color[0] = rgb_data->r;
1857  color[1] = rgb_data->g;
1858  color[2] = rgb_data->b;
1859  colors->SetTupleValue (j++, color);
1860  }
1861  }
1862 
1863  // Get the maximum size of a polygon
1864  int max_size_of_polygon = -1;
1865  for (const auto &vertex : verts)
1866  if (max_size_of_polygon < static_cast<int> (vertex.vertices.size ()))
1867  max_size_of_polygon = static_cast<int> (vertex.vertices.size ());
1868 
1869  // Update the cells
1871 
1872  const auto idx = details::fillCells(lookup, verts, cells, max_size_of_polygon);
1873 
1874  cells->GetData ()->SetNumberOfValues (idx);
1875  cells->Squeeze ();
1876  // Set the the vertices
1877  polydata->SetPolys (cells);
1878 
1879  return (true);
1880 }
1881 
1882 #ifdef vtkGenericDataArray_h
1883 #undef SetTupleValue
1884 #undef InsertNextTupleValue
1885 #undef GetTupleValue
1886 #endif
1887 
1888 #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:396
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.
constexpr bool isXYZFinite(const PointT &) noexcept
Definition: point_tests.h:125
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:399
Eigen::Vector4f sensor_origin_
Sensor acquisition pose (origin/translation).
Definition: point_cloud.h:407
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:409
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:401
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:404
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:415
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:311
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:444
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:447