Point Cloud Library (PCL)  1.12.0
pcl_visualizer.hpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2012, Open Perception, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of the copyright holder(s) nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 #ifndef PCL_PCL_VISUALIZER_IMPL_H_
39 #define PCL_PCL_VISUALIZER_IMPL_H_
40 
41 #include <vtkVersion.h>
42 #include <vtkSmartPointer.h>
43 #include <vtkCellArray.h>
44 #include <vtkLeaderActor2D.h>
45 #include <vtkVectorText.h>
46 #include <vtkAlgorithmOutput.h>
47 #include <vtkFollower.h>
48 #include <vtkMath.h>
49 #include <vtkSphereSource.h>
50 #include <vtkProperty2D.h>
51 #include <vtkDataSetSurfaceFilter.h>
52 #include <vtkPointData.h>
53 #include <vtkPolyDataMapper.h>
54 #include <vtkProperty.h>
55 #include <vtkMapper.h>
56 #include <vtkCellData.h>
57 #include <vtkDataSetMapper.h>
58 #include <vtkRenderer.h>
59 #include <vtkRendererCollection.h>
60 #include <vtkAppendPolyData.h>
61 #include <vtkTextProperty.h>
62 #include <vtkLODActor.h>
63 #include <vtkLineSource.h>
64 
65 #include <pcl/common/utils.h> // pcl::utils::ignore
67 
68 // Support for VTK 7.1 upwards
69 #ifdef vtkGenericDataArray_h
70 #define SetTupleValue SetTypedTuple
71 #define InsertNextTupleValue InsertNextTypedTuple
72 #define GetTupleValue GetTypedTuple
73 #endif
74 
75 //////////////////////////////////////////////////////////////////////////////////////////////
76 template <typename PointT> bool
78  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
79  const std::string &id, int viewport)
80 {
81  // Convert the PointCloud to VTK PolyData
82  PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
83  return (addPointCloud<PointT> (cloud, geometry_handler, id, viewport));
84 }
85 
86 //////////////////////////////////////////////////////////////////////////////////////////////
87 template <typename PointT> bool
89  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
90  const PointCloudGeometryHandler<PointT> &geometry_handler,
91  const std::string &id, int viewport)
92 {
93  if (contains (id))
94  {
95  PCL_WARN ("[addPointCloud] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
96  return (false);
97  }
98 
99  if (pcl::traits::has_color<PointT>())
100  {
101  PointCloudColorHandlerRGBField<PointT> color_handler_rgb_field (cloud);
102  return (fromHandlersToScreen (geometry_handler, color_handler_rgb_field, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
103  }
104  PointCloudColorHandlerCustom<PointT> color_handler (cloud, 255, 255, 255);
105  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
106 }
107 
108 //////////////////////////////////////////////////////////////////////////////////////////////
109 template <typename PointT> bool
111  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
112  const GeometryHandlerConstPtr &geometry_handler,
113  const std::string &id, int viewport)
114 {
115  if (contains (id))
116  {
117  // Here we're just pushing the handlers onto the queue. If needed, something fancier could
118  // be done such as checking if a specific handler already exists, etc.
119  CloudActorMap::iterator 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  CloudActorMap::iterator 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  CloudActorMap::iterator 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 = (static_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  else
256  {
257  vtkIdType j = 0; // true point index
258  for (vtkIdType i = 0; i < nr_points; ++i)
259  {
260  // Check if the point is invalid
261  if (!std::isfinite ((*cloud)[i].x) ||
262  !std::isfinite ((*cloud)[i].y) ||
263  !std::isfinite ((*cloud)[i].z))
264  continue;
265 
266  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
267  j++;
268  ptr += 3;
269  }
270  nr_points = j;
271  points->SetNumberOfPoints (nr_points);
272  }
273 
274 #ifdef VTK_CELL_ARRAY_V2
275  // TODO: Remove when VTK 6,7,8 is unsupported
276  pcl::utils::ignore(initcells);
277 
278  auto numOfCells = vertices->GetNumberOfCells();
279 
280  // If we have less cells than points, add new cells.
281  if (numOfCells < nr_points)
282  {
283  for (int i = numOfCells; i < nr_points; i++)
284  {
285  vertices->InsertNextCell(1);
286  vertices->InsertCellPoint(i);
287  }
288  }
289  // if we too many cells than points, set size (doesn't free excessive memory)
290  else if (numOfCells > nr_points)
291  {
292  vertices->ResizeExact(nr_points, nr_points);
293  }
294 
295  polydata->SetPoints(points);
296  polydata->SetVerts(vertices);
297 
298 #else
299  vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
300  updateCells (cells, initcells, nr_points);
301 
302  // Set the cells and the vertices
303  vertices->SetCells (nr_points, cells);
304 
305  // Set the cell count explicitly as the array doesn't get modified enough so the above method updates accordingly. See #4001 and #3452
306  vertices->SetNumberOfCells(nr_points);
307 #endif
308 }
309 
310 //////////////////////////////////////////////////////////////////////////////////////////////
311 template <typename PointT> void
312 pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData (
316 {
318  if (!polydata)
319  {
320  allocVtkPolyData (polydata);
322  polydata->SetVerts (vertices);
323  }
324 
325  // Use the handler to obtain the geometry
327  geometry_handler.getGeometry (points);
328  polydata->SetPoints (points);
329 
330  vtkIdType nr_points = points->GetNumberOfPoints ();
331 
332  // Create the supporting structures
333  vertices = polydata->GetVerts ();
334  if (!vertices)
336 
337 #ifdef VTK_CELL_ARRAY_V2
338  // TODO: Remove when VTK 6,7,8 is unsupported
339  pcl::utils::ignore(initcells);
340 
341  auto numOfCells = vertices->GetNumberOfCells();
342 
343  // If we have less cells than points, add new cells.
344  if (numOfCells < nr_points)
345  {
346  for (int i = numOfCells; i < nr_points; i++)
347  {
348  vertices->InsertNextCell(1);
349  vertices->InsertCellPoint(i);
350  }
351  }
352  // if we too many cells than points, set size (doesn't free excessive memory)
353  else if (numOfCells > nr_points)
354  {
355  vertices->ResizeExact(nr_points, nr_points);
356  }
357 
358  polydata->SetPoints(points);
359  polydata->SetVerts(vertices);
360 
361 #else
362  vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
363  updateCells (cells, initcells, nr_points);
364  // Set the cells and the vertices
365  vertices->SetCells (nr_points, cells);
366 #endif
367 }
368 
369 ////////////////////////////////////////////////////////////////////////////////////////////
370 template <typename PointT> bool
372  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
373  double r, double g, double b, const std::string &id, int viewport)
374 {
375  vtkSmartPointer<vtkDataSet> data = createPolygon<PointT> (cloud);
376  if (!data)
377  return (false);
378 
379  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
380  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
381  if (am_it != shape_actor_map_->end ())
382  {
384 
385  // Add old data
386  all_data->AddInputData (reinterpret_cast<vtkPolyDataMapper*> ((vtkActor::SafeDownCast (am_it->second))->GetMapper ())->GetInput ());
387 
388  // Add new data
390  surface_filter->AddInputData (vtkUnstructuredGrid::SafeDownCast (data));
391  vtkSmartPointer<vtkPolyData> poly_data = surface_filter->GetOutput ();
392  all_data->AddInputData (poly_data);
393 
394  // Create an Actor
396  createActorFromVTKDataSet (all_data->GetOutput (), actor);
397  actor->GetProperty ()->SetRepresentationToWireframe ();
398  actor->GetProperty ()->SetColor (r, g, b);
399  actor->GetMapper ()->ScalarVisibilityOff ();
400  removeActorFromRenderer (am_it->second, viewport);
401  addActorToRenderer (actor, viewport);
402 
403  // Save the pointer/ID pair to the global actor map
404  (*shape_actor_map_)[id] = actor;
405  }
406  else
407  {
408  // Create an Actor
410  createActorFromVTKDataSet (data, actor);
411  actor->GetProperty ()->SetRepresentationToWireframe ();
412  actor->GetProperty ()->SetColor (r, g, b);
413  actor->GetMapper ()->ScalarVisibilityOff ();
414  addActorToRenderer (actor, viewport);
415 
416  // Save the pointer/ID pair to the global actor map
417  (*shape_actor_map_)[id] = actor;
418  }
419 
420  return (true);
421 }
422 
423 ////////////////////////////////////////////////////////////////////////////////////////////
424 template <typename PointT> bool
426  const pcl::PlanarPolygon<PointT> &polygon,
427  double r, double g, double b, const std::string &id, int viewport)
428 {
429  vtkSmartPointer<vtkDataSet> data = createPolygon<PointT> (polygon);
430  if (!data)
431  return (false);
432 
433  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
434  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
435  if (am_it != shape_actor_map_->end ())
436  {
438 
439  // Add old data
440  all_data->AddInputData (reinterpret_cast<vtkPolyDataMapper*> ((vtkActor::SafeDownCast (am_it->second))->GetMapper ())->GetInput ());
441 
442  // Add new data
444  surface_filter->SetInputData (vtkUnstructuredGrid::SafeDownCast (data));
445  vtkSmartPointer<vtkPolyData> poly_data = surface_filter->GetOutput ();
446  all_data->AddInputData (poly_data);
447 
448  // Create an Actor
450  createActorFromVTKDataSet (all_data->GetOutput (), actor);
451  actor->GetProperty ()->SetRepresentationToWireframe ();
452  actor->GetProperty ()->SetColor (r, g, b);
453  actor->GetMapper ()->ScalarVisibilityOn ();
454  actor->GetProperty ()->BackfaceCullingOff ();
455  removeActorFromRenderer (am_it->second, viewport);
456  addActorToRenderer (actor, viewport);
457 
458  // Save the pointer/ID pair to the global actor map
459  (*shape_actor_map_)[id] = actor;
460  }
461  else
462  {
463  // Create an Actor
465  createActorFromVTKDataSet (data, actor);
466  actor->GetProperty ()->SetRepresentationToWireframe ();
467  actor->GetProperty ()->SetColor (r, g, b);
468  actor->GetMapper ()->ScalarVisibilityOn ();
469  actor->GetProperty ()->BackfaceCullingOff ();
470  addActorToRenderer (actor, viewport);
471 
472  // Save the pointer/ID pair to the global actor map
473  (*shape_actor_map_)[id] = actor;
474  }
475  return (true);
476 }
477 
478 ////////////////////////////////////////////////////////////////////////////////////////////
479 template <typename PointT> bool
481  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
482  const std::string &id, int viewport)
483 {
484  return (!addPolygon<PointT> (cloud, 0.5, 0.5, 0.5, id, viewport));
485 }
486 
487 ////////////////////////////////////////////////////////////////////////////////////////////
488 template <typename P1, typename P2> bool
489 pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
490 {
491  if (contains (id))
492  {
493  PCL_WARN ("[addLine] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
494  return (false);
495  }
496 
497  vtkSmartPointer<vtkDataSet> data = createLine (pt1.getVector4fMap (), pt2.getVector4fMap ());
498 
499  // Create an Actor
501  createActorFromVTKDataSet (data, actor);
502  actor->GetProperty ()->SetRepresentationToWireframe ();
503  actor->GetProperty ()->SetColor (r, g, b);
504  actor->GetMapper ()->ScalarVisibilityOff ();
505  addActorToRenderer (actor, viewport);
506 
507  // Save the pointer/ID pair to the global actor map
508  (*shape_actor_map_)[id] = actor;
509  return (true);
510 }
511 
512 ////////////////////////////////////////////////////////////////////////////////////////////
513 template <typename P1, typename P2> bool
514 pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
515 {
516  if (contains (id))
517  {
518  PCL_WARN ("[addArrow] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
519  return (false);
520  }
521 
522  // Create an Actor
524  leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
525  leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
526  leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
527  leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
528  leader->SetArrowStyleToFilled ();
529  leader->AutoLabelOn ();
530 
531  leader->GetProperty ()->SetColor (r, g, b);
532  addActorToRenderer (leader, viewport);
533 
534  // Save the pointer/ID pair to the global actor map
535  (*shape_actor_map_)[id] = leader;
536  return (true);
537 }
538 
539 ////////////////////////////////////////////////////////////////////////////////////////////
540 template <typename P1, typename P2> bool
541 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)
542 {
543  if (contains (id))
544  {
545  PCL_WARN ("[addArrow] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
546  return (false);
547  }
548 
549  // Create an Actor
551  leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
552  leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
553  leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
554  leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
555  leader->SetArrowStyleToFilled ();
556  leader->SetArrowPlacementToPoint1 ();
557  if (display_length)
558  leader->AutoLabelOn ();
559  else
560  leader->AutoLabelOff ();
561 
562  leader->GetProperty ()->SetColor (r, g, b);
563  addActorToRenderer (leader, viewport);
564 
565  // Save the pointer/ID pair to the global actor map
566  (*shape_actor_map_)[id] = leader;
567  return (true);
568 }
569 ////////////////////////////////////////////////////////////////////////////////////////////
570 template <typename P1, typename P2> bool
571 pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2,
572  double r_line, double g_line, double b_line,
573  double r_text, double g_text, double b_text,
574  const std::string &id, int viewport)
575 {
576  if (contains (id))
577  {
578  PCL_WARN ("[addArrow] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
579  return (false);
580  }
581 
582  // Create an Actor
584  leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
585  leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
586  leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
587  leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
588  leader->SetArrowStyleToFilled ();
589  leader->AutoLabelOn ();
590 
591  leader->GetLabelTextProperty()->SetColor(r_text, g_text, b_text);
592 
593  leader->GetProperty ()->SetColor (r_line, g_line, b_line);
594  addActorToRenderer (leader, viewport);
595 
596  // Save the pointer/ID pair to the global actor map
597  (*shape_actor_map_)[id] = leader;
598  return (true);
599 }
600 
601 ////////////////////////////////////////////////////////////////////////////////////////////
602 template <typename P1, typename P2> bool
603 pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, const std::string &id, int viewport)
604 {
605  return (!addLine (pt1, pt2, 0.5, 0.5, 0.5, id, viewport));
606 }
607 
608 ////////////////////////////////////////////////////////////////////////////////////////////
609 template <typename PointT> bool
610 pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, double r, double g, double b, const std::string &id, int viewport)
611 {
612  if (contains (id))
613  {
614  PCL_WARN ("[addSphere] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
615  return (false);
616  }
617 
619  data->SetRadius (radius);
620  data->SetCenter (double (center.x), double (center.y), double (center.z));
621  data->SetPhiResolution (10);
622  data->SetThetaResolution (10);
623  data->LatLongTessellationOff ();
624  data->Update ();
625 
626  // Setup actor and mapper
628  mapper->SetInputConnection (data->GetOutputPort ());
629 
630  // Create an Actor
632  actor->SetMapper (mapper);
633  //createActorFromVTKDataSet (data, actor);
634  actor->GetProperty ()->SetRepresentationToSurface ();
635  actor->GetProperty ()->SetInterpolationToFlat ();
636  actor->GetProperty ()->SetColor (r, g, b);
637 #if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
638  actor->GetMapper ()->ImmediateModeRenderingOn ();
639 #endif
640  actor->GetMapper ()->StaticOn ();
641  actor->GetMapper ()->ScalarVisibilityOff ();
642  actor->GetMapper ()->Update ();
643  addActorToRenderer (actor, viewport);
644 
645  // Save the pointer/ID pair to the global actor map
646  (*shape_actor_map_)[id] = actor;
647  return (true);
648 }
649 
650 ////////////////////////////////////////////////////////////////////////////////////////////
651 template <typename PointT> bool
652 pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, const std::string &id, int viewport)
653 {
654  return (addSphere (center, radius, 0.5, 0.5, 0.5, id, viewport));
655 }
656 
657 ////////////////////////////////////////////////////////////////////////////////////////////
658 template<typename PointT> bool
659 pcl::visualization::PCLVisualizer::updateSphere (const PointT &center, double radius, double r, double g, double b, const std::string &id)
660 {
661  if (!contains (id))
662  {
663  return (false);
664  }
665 
666  //////////////////////////////////////////////////////////////////////////
667  // Get the actor pointer
668  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
669  vtkLODActor* actor = vtkLODActor::SafeDownCast (am_it->second);
670  if (!actor)
671  return (false);
672  vtkAlgorithm *algo = actor->GetMapper ()->GetInputAlgorithm ();
673  vtkSphereSource *src = vtkSphereSource::SafeDownCast (algo);
674  if (!src)
675  return (false);
676 
677  src->SetCenter (double (center.x), double (center.y), double (center.z));
678  src->SetRadius (radius);
679  src->Update ();
680  actor->GetProperty ()->SetColor (r, g, b);
681  actor->Modified ();
682 
683  return (true);
684 }
685 
686 //////////////////////////////////////////////////
687 template <typename PointT> bool
689  const std::string &text,
690  const PointT& position,
691  double textScale,
692  double r,
693  double g,
694  double b,
695  const std::string &id,
696  int viewport)
697 {
698  std::string tid;
699  if (id.empty ())
700  tid = text;
701  else
702  tid = id;
703 
704  if (viewport < 0)
705  return false;
706 
707  // If there is no custom viewport and the viewport number is not 0, exit
708  if (rens_->GetNumberOfItems () <= viewport)
709  {
710  PCL_ERROR ("[addText3D] The viewport [%d] doesn't exist (id <%s>)! \n",
711  viewport,
712  tid.c_str ());
713  return false;
714  }
715 
716  // check all or an individual viewport for a similar id
717  rens_->InitTraversal ();
718  for (std::size_t i = viewport; rens_->GetNextItem (); ++i)
719  {
720  const std::string uid = tid + std::string (i, '*');
721  if (contains (uid))
722  {
723  PCL_ERROR ( "[addText3D] The id <%s> already exists in viewport [%d]! \n"
724  "Please choose a different id and retry.\n",
725  tid.c_str (),
726  i);
727  return false;
728  }
729 
730  if (viewport > 0)
731  break;
732  }
733 
735  textSource->SetText (text.c_str());
736  textSource->Update ();
737 
739  textMapper->SetInputConnection (textSource->GetOutputPort ());
740 
741  // Since each follower may follow a different camera, we need different followers
742  rens_->InitTraversal ();
743  vtkRenderer* renderer;
744  int i = 0;
745  while ((renderer = rens_->GetNextItem ()))
746  {
747  // Should we add the actor to all renderers or just to i-nth renderer?
748  if (viewport == 0 || viewport == i)
749  {
751  textActor->SetMapper (textMapper);
752  textActor->SetPosition (position.x, position.y, position.z);
753  textActor->SetScale (textScale);
754  textActor->GetProperty ()->SetColor (r, g, b);
755  textActor->SetCamera (renderer->GetActiveCamera ());
756 
757  renderer->AddActor (textActor);
758  renderer->Render ();
759 
760  // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
761  // for multiple viewport
762  const std::string uid = tid + std::string (i, '*');
763  (*shape_actor_map_)[uid] = textActor;
764  }
765 
766  ++i;
767  }
768 
769  return (true);
770 }
771 
772 //////////////////////////////////////////////////
773 template <typename PointT> bool
775  const std::string &text,
776  const PointT& position,
777  double orientation[3],
778  double textScale,
779  double r,
780  double g,
781  double b,
782  const std::string &id,
783  int viewport)
784 {
785  std::string tid;
786  if (id.empty ())
787  tid = text;
788  else
789  tid = id;
790 
791  if (viewport < 0)
792  return false;
793 
794  // If there is no custom viewport and the viewport number is not 0, exit
795  if (rens_->GetNumberOfItems () <= viewport)
796  {
797  PCL_ERROR ("[addText3D] The viewport [%d] doesn't exist (id <%s>)!\n",
798  viewport,
799  tid.c_str ());
800  return false;
801  }
802 
803  // check all or an individual viewport for a similar id
804  rens_->InitTraversal ();
805  for (std::size_t i = viewport; rens_->GetNextItem (); ++i)
806  {
807  const std::string uid = tid + std::string (i, '*');
808  if (contains (uid))
809  {
810  PCL_ERROR ( "[addText3D] The id <%s> already exists in viewport [%d]! "
811  "Please choose a different id and retry.\n",
812  tid.c_str (),
813  i);
814  return false;
815  }
816 
817  if (viewport > 0)
818  break;
819  }
820 
822  textSource->SetText (text.c_str());
823  textSource->Update ();
824 
826  textMapper->SetInputConnection (textSource->GetOutputPort ());
827 
829  textActor->SetMapper (textMapper);
830  textActor->SetPosition (position.x, position.y, position.z);
831  textActor->SetScale (textScale);
832  textActor->GetProperty ()->SetColor (r, g, b);
833  textActor->SetOrientation (orientation);
834 
835  // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
836  rens_->InitTraversal ();
837  int i = 0;
838  for ( vtkRenderer* renderer = rens_->GetNextItem ();
839  renderer;
840  renderer = rens_->GetNextItem (), ++i)
841  {
842  if (viewport == 0 || viewport == i)
843  {
844  renderer->AddActor (textActor);
845  const std::string uid = tid + std::string (i, '*');
846  (*shape_actor_map_)[uid] = textActor;
847  }
848  }
849 
850  return (true);
851 }
852 
853 //////////////////////////////////////////////////////////////////////////////////////////////
854 template <typename PointNT> bool
856  const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
857  int level, float scale, const std::string &id, int viewport)
858 {
859  return (addPointCloudNormals<PointNT, PointNT> (cloud, cloud, level, scale, id, viewport));
860 }
861 
862 //////////////////////////////////////////////////////////////////////////////////////////////
863 template <typename PointT, typename PointNT> bool
865  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
866  const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
867  int level, float scale,
868  const std::string &id, int viewport)
869 {
870  if (normals->size () != cloud->size ())
871  {
872  PCL_ERROR ("[addPointCloudNormals] The number of points differs from the number of normals!\n");
873  return (false);
874  }
875 
876  if (normals->empty ())
877  {
878  PCL_WARN ("[addPointCloudNormals] An empty normal cloud is given! Nothing to display.\n");
879  return (false);
880  }
881 
882  if (contains (id))
883  {
884  PCL_WARN ("[addPointCloudNormals] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
885  return (false);
886  }
887 
890 
891  points->SetDataTypeToFloat ();
893  data->SetNumberOfComponents (3);
894 
895 
896  vtkIdType nr_normals = 0;
897  float* pts = nullptr;
898 
899  // If the cloud is organized, then distribute the normal step in both directions
900  if (cloud->isOrganized () && normals->isOrganized ())
901  {
902  vtkIdType point_step = static_cast<vtkIdType> (sqrt (double (level)));
903  nr_normals = (static_cast<vtkIdType> ((cloud->width - 1)/ point_step) + 1) *
904  (static_cast<vtkIdType> ((cloud->height - 1) / point_step) + 1);
905  pts = new float[2 * nr_normals * 3];
906 
907  vtkIdType cell_count = 0;
908  for (vtkIdType y = 0; y < normals->height; y += point_step)
909  for (vtkIdType x = 0; x < normals->width; x += point_step)
910  {
911  PointT p = (*cloud)(x, y);
912  p.x += (*normals)(x, y).normal[0] * scale;
913  p.y += (*normals)(x, y).normal[1] * scale;
914  p.z += (*normals)(x, y).normal[2] * scale;
915 
916  pts[2 * cell_count * 3 + 0] = (*cloud)(x, y).x;
917  pts[2 * cell_count * 3 + 1] = (*cloud)(x, y).y;
918  pts[2 * cell_count * 3 + 2] = (*cloud)(x, y).z;
919  pts[2 * cell_count * 3 + 3] = p.x;
920  pts[2 * cell_count * 3 + 4] = p.y;
921  pts[2 * cell_count * 3 + 5] = p.z;
922 
923  lines->InsertNextCell (2);
924  lines->InsertCellPoint (2 * cell_count);
925  lines->InsertCellPoint (2 * cell_count + 1);
926  cell_count ++;
927  }
928  }
929  else
930  {
931  nr_normals = (cloud->size () - 1) / level + 1 ;
932  pts = new float[2 * nr_normals * 3];
933 
934  for (vtkIdType i = 0, j = 0; j < nr_normals; j++, i = j * level)
935  {
936  PointT p = (*cloud)[i];
937  p.x += (*normals)[i].normal[0] * scale;
938  p.y += (*normals)[i].normal[1] * scale;
939  p.z += (*normals)[i].normal[2] * scale;
940 
941  pts[2 * j * 3 + 0] = (*cloud)[i].x;
942  pts[2 * j * 3 + 1] = (*cloud)[i].y;
943  pts[2 * j * 3 + 2] = (*cloud)[i].z;
944  pts[2 * j * 3 + 3] = p.x;
945  pts[2 * j * 3 + 4] = p.y;
946  pts[2 * j * 3 + 5] = p.z;
947 
948  lines->InsertNextCell (2);
949  lines->InsertCellPoint (2 * j);
950  lines->InsertCellPoint (2 * j + 1);
951  }
952  }
953 
954  data->SetArray (&pts[0], 2 * nr_normals * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
955  points->SetData (data);
956 
958  polyData->SetPoints (points);
959  polyData->SetLines (lines);
960 
962  mapper->SetInputData (polyData);
963  mapper->SetColorModeToMapScalars();
964  mapper->SetScalarModeToUsePointData();
965 
966  // create actor
968  actor->SetMapper (mapper);
969 
970  // Use cloud view point info
972  convertToVtkMatrix (cloud->sensor_origin_, cloud->sensor_orientation_, transformation);
973  actor->SetUserMatrix (transformation);
974 
975  // Add it to all renderers
976  addActorToRenderer (actor, viewport);
977 
978  // Save the pointer/ID pair to the global actor map
979  (*cloud_actor_map_)[id].actor = actor;
980  return (true);
981 }
982 
983 //////////////////////////////////////////////////////////////////////////////////////////////
984 template <typename PointNT> bool
986  const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
988  int level, float scale,
989  const std::string &id, int viewport)
990 {
991  return (addPointCloudPrincipalCurvatures<PointNT, PointNT> (cloud, cloud, pcs, level, scale, id, viewport));
992 }
993 
994 //////////////////////////////////////////////////////////////////////////////////////////////
995 template <typename PointT, typename PointNT> bool
997  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
998  const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
1000  int level, float scale,
1001  const std::string &id, int viewport)
1002 {
1003  if (pcs->size () != cloud->size () || normals->size () != cloud->size ())
1004  {
1005  pcl::console::print_error ("[addPointCloudPrincipalCurvatures] The number of points differs from the number of principal curvatures/normals!\n");
1006  return (false);
1007  }
1008 
1009  if (contains (id))
1010  {
1011  PCL_WARN ("[addPointCloudPrincipalCurvatures] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1012  return (false);
1013  }
1014 
1017 
1018  // Setup two colors - one for each line
1019  unsigned char green[3] = {0, 255, 0};
1020  unsigned char blue[3] = {0, 0, 255};
1021 
1022  // Setup the colors array
1024  line_1_colors->SetNumberOfComponents (3);
1025  line_1_colors->SetName ("Colors");
1027  line_2_colors->SetNumberOfComponents (3);
1028  line_2_colors->SetName ("Colors");
1029 
1030  // Create the first sets of lines
1031  for (std::size_t i = 0; i < cloud->size (); i+=level)
1032  {
1033  PointT p = (*cloud)[i];
1034  p.x += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[0]) * scale;
1035  p.y += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[1]) * scale;
1036  p.z += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[2]) * scale;
1037 
1039  line_1->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1040  line_1->SetPoint2 (p.x, p.y, p.z);
1041  line_1->Update ();
1042  polydata_1->AddInputData (line_1->GetOutput ());
1043  line_1_colors->InsertNextTupleValue (green);
1044  }
1045  polydata_1->Update ();
1046  vtkSmartPointer<vtkPolyData> line_1_data = polydata_1->GetOutput ();
1047  line_1_data->GetCellData ()->SetScalars (line_1_colors);
1048 
1049  // Create the second sets of lines
1050  for (std::size_t i = 0; i < cloud->size (); i += level)
1051  {
1052  Eigen::Vector3f pc ((*pcs)[i].principal_curvature[0],
1053  (*pcs)[i].principal_curvature[1],
1054  (*pcs)[i].principal_curvature[2]);
1055  Eigen::Vector3f normal ((*normals)[i].normal[0],
1056  (*normals)[i].normal[1],
1057  (*normals)[i].normal[2]);
1058  Eigen::Vector3f pc_c = pc.cross (normal);
1059 
1060  PointT p = (*cloud)[i];
1061  p.x += ((*pcs)[i].pc2 * pc_c[0]) * scale;
1062  p.y += ((*pcs)[i].pc2 * pc_c[1]) * scale;
1063  p.z += ((*pcs)[i].pc2 * pc_c[2]) * scale;
1064 
1066  line_2->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1067  line_2->SetPoint2 (p.x, p.y, p.z);
1068  line_2->Update ();
1069  polydata_2->AddInputData (line_2->GetOutput ());
1070 
1071  line_2_colors->InsertNextTupleValue (blue);
1072  }
1073  polydata_2->Update ();
1074  vtkSmartPointer<vtkPolyData> line_2_data = polydata_2->GetOutput ();
1075  line_2_data->GetCellData ()->SetScalars (line_2_colors);
1076 
1077  // Assemble the two sets of lines
1079  alldata->AddInputData (line_1_data);
1080  alldata->AddInputData (line_2_data);
1081 
1082  // Create an Actor
1084  createActorFromVTKDataSet (alldata->GetOutput (), actor);
1085  actor->GetMapper ()->SetScalarModeToUseCellData ();
1086 
1087  // Add it to all renderers
1088  addActorToRenderer (actor, viewport);
1089 
1090  // Save the pointer/ID pair to the global actor map
1091  CloudActor act;
1092  act.actor = actor;
1093  (*cloud_actor_map_)[id] = act;
1094  return (true);
1095 }
1096 
1097 //////////////////////////////////////////////////////////////////////////////////////////////
1098 template <typename PointT, typename GradientT> bool
1100  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1101  const typename pcl::PointCloud<GradientT>::ConstPtr &gradients,
1102  int level, double scale,
1103  const std::string &id, int viewport)
1104 {
1105  if (gradients->size () != cloud->size ())
1106  {
1107  PCL_ERROR ("[addPointCloudGradients] The number of points differs from the number of gradients!\n");
1108  return (false);
1109  }
1110  if (contains (id))
1111  {
1112  PCL_WARN ("[addPointCloudGradients] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1113  return (false);
1114  }
1115 
1118 
1119  points->SetDataTypeToFloat ();
1121  data->SetNumberOfComponents (3);
1122 
1123  vtkIdType nr_gradients = (cloud->size () - 1) / level + 1 ;
1124  float* pts = new float[2 * nr_gradients * 3];
1125 
1126  for (vtkIdType i = 0, j = 0; j < nr_gradients; j++, i = j * level)
1127  {
1128  PointT p = (*cloud)[i];
1129  p.x += (*gradients)[i].gradient[0] * scale;
1130  p.y += (*gradients)[i].gradient[1] * scale;
1131  p.z += (*gradients)[i].gradient[2] * scale;
1132 
1133  pts[2 * j * 3 + 0] = (*cloud)[i].x;
1134  pts[2 * j * 3 + 1] = (*cloud)[i].y;
1135  pts[2 * j * 3 + 2] = (*cloud)[i].z;
1136  pts[2 * j * 3 + 3] = p.x;
1137  pts[2 * j * 3 + 4] = p.y;
1138  pts[2 * j * 3 + 5] = p.z;
1139 
1140  lines->InsertNextCell(2);
1141  lines->InsertCellPoint(2*j);
1142  lines->InsertCellPoint(2*j+1);
1143  }
1144 
1145  data->SetArray (&pts[0], 2 * nr_gradients * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
1146  points->SetData (data);
1147 
1149  polyData->SetPoints(points);
1150  polyData->SetLines(lines);
1151 
1153  mapper->SetInputData (polyData);
1154  mapper->SetColorModeToMapScalars();
1155  mapper->SetScalarModeToUsePointData();
1156 
1157  // create actor
1159  actor->SetMapper (mapper);
1160 
1161  // Add it to all renderers
1162  addActorToRenderer (actor, viewport);
1163 
1164  // Save the pointer/ID pair to the global actor map
1165  (*cloud_actor_map_)[id].actor = actor;
1166  return (true);
1167 }
1168 
1169 //////////////////////////////////////////////////////////////////////////////////////////////
1170 template <typename PointT> bool
1172  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1173  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1174  const std::vector<int> &correspondences,
1175  const std::string &id,
1176  int viewport)
1177 {
1178  pcl::Correspondences corrs;
1179  corrs.resize (correspondences.size ());
1180 
1181  std::size_t index = 0;
1182  for (auto &corr : corrs)
1183  {
1184  corr.index_query = index;
1185  corr.index_match = correspondences[index];
1186  index++;
1187  }
1188 
1189  return (addCorrespondences<PointT> (source_points, target_points, corrs, id, viewport));
1190 }
1191 
1192 //////////////////////////////////////////////////////////////////////////////////////////////
1193 template <typename PointT> bool
1195  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1196  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1197  const pcl::Correspondences &correspondences,
1198  int nth,
1199  const std::string &id,
1200  int viewport,
1201  bool overwrite)
1202 {
1203  if (correspondences.empty ())
1204  {
1205  PCL_DEBUG ("[addCorrespondences] An empty set of correspondences given! Nothing to display.\n");
1206  return (false);
1207  }
1208 
1209  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1210  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
1211  if (am_it != shape_actor_map_->end () && !overwrite)
1212  {
1213  PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1214  return (false);
1215  }
1216  if (am_it == shape_actor_map_->end () && overwrite)
1217  {
1218  overwrite = false; // Correspondences doesn't exist, add them instead of updating them
1219  }
1220 
1221  int n_corr = int (correspondences.size () / nth);
1223 
1224  // Prepare colors
1226  line_colors->SetNumberOfComponents (3);
1227  line_colors->SetName ("Colors");
1228  line_colors->SetNumberOfTuples (n_corr);
1229 
1230  // Prepare coordinates
1232  line_points->SetNumberOfPoints (2 * n_corr);
1233 
1235  line_cells_id->SetNumberOfComponents (3);
1236  line_cells_id->SetNumberOfTuples (n_corr);
1237  vtkIdType *line_cell_id = line_cells_id->GetPointer (0);
1239 
1241  line_tcoords->SetNumberOfComponents (1);
1242  line_tcoords->SetNumberOfTuples (n_corr * 2);
1243  line_tcoords->SetName ("Texture Coordinates");
1244 
1245  double tc[3] = {0.0, 0.0, 0.0};
1246 
1247  Eigen::Affine3f source_transformation;
1248  source_transformation.linear () = source_points->sensor_orientation_.matrix ();
1249  source_transformation.translation () = source_points->sensor_origin_.head (3);
1250  Eigen::Affine3f target_transformation;
1251  target_transformation.linear () = target_points->sensor_orientation_.matrix ();
1252  target_transformation.translation () = target_points->sensor_origin_.head (3);
1253 
1254  int j = 0;
1255  // Draw lines between the best corresponding points
1256  for (std::size_t i = 0; i < correspondences.size (); i += nth, ++j)
1257  {
1258  if (correspondences[i].index_match == UNAVAILABLE)
1259  {
1260  PCL_WARN ("[addCorrespondences] No valid index_match for correspondence %d\n", i);
1261  continue;
1262  }
1263 
1264  PointT p_src ((*source_points)[correspondences[i].index_query]);
1265  PointT p_tgt ((*target_points)[correspondences[i].index_match]);
1266 
1267  p_src.getVector3fMap () = source_transformation * p_src.getVector3fMap ();
1268  p_tgt.getVector3fMap () = target_transformation * p_tgt.getVector3fMap ();
1269 
1270  int id1 = j * 2 + 0, id2 = j * 2 + 1;
1271  // Set the points
1272  line_points->SetPoint (id1, p_src.x, p_src.y, p_src.z);
1273  line_points->SetPoint (id2, p_tgt.x, p_tgt.y, p_tgt.z);
1274  // Set the cell ID
1275  *line_cell_id++ = 2;
1276  *line_cell_id++ = id1;
1277  *line_cell_id++ = id2;
1278  // Set the texture coords
1279  tc[0] = 0.; line_tcoords->SetTuple (id1, tc);
1280  tc[0] = 1.; line_tcoords->SetTuple (id2, tc);
1281 
1282  float rgb[3];
1283  rgb[0] = vtkMath::Random (32, 255); // min / max
1284  rgb[1] = vtkMath::Random (32, 255);
1285  rgb[2] = vtkMath::Random (32, 255);
1286  line_colors->InsertTuple (i, rgb);
1287  }
1288  line_colors->SetNumberOfTuples (j);
1289  line_cells_id->SetNumberOfTuples (j);
1290  line_cells->SetCells (n_corr, line_cells_id);
1291  line_points->SetNumberOfPoints (j*2);
1292  line_tcoords->SetNumberOfTuples (j*2);
1293 
1294  // Fill in the lines
1295  line_data->SetPoints (line_points);
1296  line_data->SetLines (line_cells);
1297  line_data->GetPointData ()->SetTCoords (line_tcoords);
1298  line_data->GetCellData ()->SetScalars (line_colors);
1299 
1300  // Create an Actor
1301  if (!overwrite)
1302  {
1304  createActorFromVTKDataSet (line_data, actor);
1305  actor->GetProperty ()->SetRepresentationToWireframe ();
1306  actor->GetProperty ()->SetOpacity (0.5);
1307  addActorToRenderer (actor, viewport);
1308 
1309  // Save the pointer/ID pair to the global actor map
1310  (*shape_actor_map_)[id] = actor;
1311  }
1312  else
1313  {
1314  vtkSmartPointer<vtkLODActor> actor = vtkLODActor::SafeDownCast (am_it->second);
1315  if (!actor)
1316  return (false);
1317  // Update the mapper
1318  reinterpret_cast<vtkPolyDataMapper*> (actor->GetMapper ())->SetInputData (line_data);
1319  }
1320 
1321  return (true);
1322 }
1323 
1324 //////////////////////////////////////////////////////////////////////////////////////////////
1325 template <typename PointT> bool
1327  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1328  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1329  const pcl::Correspondences &correspondences,
1330  int nth,
1331  const std::string &id,
1332  int viewport)
1333 {
1334  return (addCorrespondences<PointT> (source_points, target_points, correspondences, nth, id, viewport, true));
1335 }
1336 
1337 //////////////////////////////////////////////////////////////////////////////////////////////
1338 template <typename PointT> bool
1339 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1340  const PointCloudGeometryHandler<PointT> &geometry_handler,
1341  const PointCloudColorHandler<PointT> &color_handler,
1342  const std::string &id,
1343  int viewport,
1344  const Eigen::Vector4f& sensor_origin,
1345  const Eigen::Quaternion<float>& sensor_orientation)
1346 {
1347  if (!geometry_handler.isCapable ())
1348  {
1349  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1350  return (false);
1351  }
1352 
1353  if (!color_handler.isCapable ())
1354  {
1355  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1356  return (false);
1357  }
1358 
1361  // Convert the PointCloud to VTK PolyData
1362  convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1363 
1364  // Get the colors from the handler
1365  bool has_colors = false;
1366  double minmax[2];
1367  if (auto scalars = color_handler.getColor ())
1368  {
1369  polydata->GetPointData ()->SetScalars (scalars);
1370  scalars->GetRange (minmax);
1371  has_colors = true;
1372  }
1373 
1374  // Create an Actor
1376  createActorFromVTKDataSet (polydata, actor);
1377  if (has_colors)
1378  actor->GetMapper ()->SetScalarRange (minmax);
1379 
1380  // Add it to all renderers
1381  addActorToRenderer (actor, viewport);
1382 
1383  // Save the pointer/ID pair to the global actor map
1384  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1385  cloud_actor.actor = actor;
1386  cloud_actor.cells = initcells;
1387 
1388  // Save the viewpoint transformation matrix to the global actor map
1390  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1391  cloud_actor.viewpoint_transformation_ = transformation;
1392  cloud_actor.actor->SetUserMatrix (transformation);
1393  cloud_actor.actor->Modified ();
1394 
1395  return (true);
1396 }
1397 
1398 //////////////////////////////////////////////////////////////////////////////////////////////
1399 template <typename PointT> bool
1400 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1401  const PointCloudGeometryHandler<PointT> &geometry_handler,
1402  const ColorHandlerConstPtr &color_handler,
1403  const std::string &id,
1404  int viewport,
1405  const Eigen::Vector4f& sensor_origin,
1406  const Eigen::Quaternion<float>& sensor_orientation)
1407 {
1408  if (!geometry_handler.isCapable ())
1409  {
1410  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1411  return (false);
1412  }
1413 
1414  if (!color_handler->isCapable ())
1415  {
1416  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler->getName ().c_str ());
1417  return (false);
1418  }
1419 
1422  // Convert the PointCloud to VTK PolyData
1423  convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1424  // use the given geometry handler
1425 
1426  // Get the colors from the handler
1427  bool has_colors = false;
1428  double minmax[2];
1429  if (auto scalars = color_handler->getColor ())
1430  {
1431  polydata->GetPointData ()->SetScalars (scalars);
1432  scalars->GetRange (minmax);
1433  has_colors = true;
1434  }
1435 
1436  // Create an Actor
1438  createActorFromVTKDataSet (polydata, actor);
1439  if (has_colors)
1440  actor->GetMapper ()->SetScalarRange (minmax);
1441 
1442  // Add it to all renderers
1443  addActorToRenderer (actor, viewport);
1444 
1445  // Save the pointer/ID pair to the global actor map
1446  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1447  cloud_actor.actor = actor;
1448  cloud_actor.cells = initcells;
1449  cloud_actor.color_handlers.push_back (color_handler);
1450 
1451  // Save the viewpoint transformation matrix to the global actor map
1453  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1454  cloud_actor.viewpoint_transformation_ = transformation;
1455  cloud_actor.actor->SetUserMatrix (transformation);
1456  cloud_actor.actor->Modified ();
1457 
1458  return (true);
1459 }
1460 
1461 //////////////////////////////////////////////////////////////////////////////////////////////
1462 template <typename PointT> bool
1463 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1464  const GeometryHandlerConstPtr &geometry_handler,
1465  const PointCloudColorHandler<PointT> &color_handler,
1466  const std::string &id,
1467  int viewport,
1468  const Eigen::Vector4f& sensor_origin,
1469  const Eigen::Quaternion<float>& sensor_orientation)
1470 {
1471  if (!geometry_handler->isCapable ())
1472  {
1473  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler->getName ().c_str ());
1474  return (false);
1475  }
1476 
1477  if (!color_handler.isCapable ())
1478  {
1479  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1480  return (false);
1481  }
1482 
1485  // Convert the PointCloud to VTK PolyData
1486  convertPointCloudToVTKPolyData (geometry_handler, polydata, initcells);
1487  // use the given geometry handler
1488 
1489  // Get the colors from the handler
1490  bool has_colors = false;
1491  double minmax[2];
1492  if (auto scalars = color_handler.getColor ())
1493  {
1494  polydata->GetPointData ()->SetScalars (scalars);
1495  scalars->GetRange (minmax);
1496  has_colors = true;
1497  }
1498 
1499  // Create an Actor
1501  createActorFromVTKDataSet (polydata, actor);
1502  if (has_colors)
1503  actor->GetMapper ()->SetScalarRange (minmax);
1504 
1505  // Add it to all renderers
1506  addActorToRenderer (actor, viewport);
1507 
1508  // Save the pointer/ID pair to the global actor map
1509  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1510  cloud_actor.actor = actor;
1511  cloud_actor.cells = initcells;
1512  cloud_actor.geometry_handlers.push_back (geometry_handler);
1513 
1514  // Save the viewpoint transformation matrix to the global actor map
1516  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1517  cloud_actor.viewpoint_transformation_ = transformation;
1518  cloud_actor.actor->SetUserMatrix (transformation);
1519  cloud_actor.actor->Modified ();
1520 
1521  return (true);
1522 }
1523 
1524 //////////////////////////////////////////////////////////////////////////////////////////////
1525 template <typename PointT> bool
1527  const std::string &id)
1528 {
1529  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1530  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1531 
1532  if (am_it == cloud_actor_map_->end ())
1533  return (false);
1534 
1535  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1536  if (!polydata)
1537  return false;
1538  // Convert the PointCloud to VTK PolyData
1539  convertPointCloudToVTKPolyData<PointT> (cloud, polydata, am_it->second.cells);
1540 
1541  // Set scalars to blank, since there is no way we can update them here.
1543  polydata->GetPointData ()->SetScalars (scalars);
1544  double minmax[2];
1545  minmax[0] = std::numeric_limits<double>::min ();
1546  minmax[1] = std::numeric_limits<double>::max ();
1547 #if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
1548  am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
1549 #endif
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  CloudActorMap::iterator 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 #if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
1582  am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
1583 #endif
1584  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1585 
1586  // Update the mapper
1587  reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1588  return (true);
1589 }
1590 
1591 
1592 /////////////////////////////////////////////////////////////////////////////////////////////
1593 template <typename PointT> bool
1595  const PointCloudColorHandler<PointT> &color_handler,
1596  const std::string &id)
1597 {
1598  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1599  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1600 
1601  if (am_it == cloud_actor_map_->end ())
1602  return (false);
1603 
1604  // Get the current poly data
1605  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1606  if (!polydata)
1607  return (false);
1608 
1609  convertPointCloudToVTKPolyData<PointT>(cloud, polydata, am_it->second.cells);
1610 
1611  // Get the colors from the handler
1612  bool has_colors = false;
1613  double minmax[2];
1614  if (auto scalars = color_handler.getColor ())
1615  {
1616  // Update the data
1617  polydata->GetPointData ()->SetScalars (scalars);
1618  scalars->GetRange (minmax);
1619  has_colors = true;
1620  }
1621 
1622 #if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
1623  am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
1624 #endif
1625 
1626  if (has_colors)
1627  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1628 
1629  // Update the mapper
1630  reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1631  return (true);
1632 }
1633 
1634 /////////////////////////////////////////////////////////////////////////////////////////////
1635 template <typename PointT> bool
1637  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1638  const std::vector<pcl::Vertices> &vertices,
1639  const std::string &id,
1640  int viewport)
1641 {
1642  if (vertices.empty () || cloud->points.empty ())
1643  return (false);
1644 
1645  if (contains (id))
1646  {
1647  PCL_WARN ("[addPolygonMesh] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1648  return (false);
1649  }
1650 
1651  int rgb_idx = -1;
1652  std::vector<pcl::PCLPointField> fields;
1654  rgb_idx = pcl::getFieldIndex<PointT> ("rgb", fields);
1655  if (rgb_idx == -1)
1656  rgb_idx = pcl::getFieldIndex<PointT> ("rgba", fields);
1657  if (rgb_idx != -1)
1658  {
1660  colors->SetNumberOfComponents (3);
1661  colors->SetName ("Colors");
1662  std::uint32_t offset = fields[rgb_idx].offset;
1663  for (std::size_t i = 0; i < cloud->size (); ++i)
1664  {
1665  if (!isFinite ((*cloud)[i]))
1666  continue;
1667  const pcl::RGB* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
1668  unsigned char color[3];
1669  color[0] = rgb_data->r;
1670  color[1] = rgb_data->g;
1671  color[2] = rgb_data->b;
1672  colors->InsertNextTupleValue (color);
1673  }
1674  }
1675 
1676  // Create points from polyMesh.cloud
1678  vtkIdType nr_points = cloud->size ();
1679  points->SetNumberOfPoints (nr_points);
1681 
1682  // Get a pointer to the beginning of the data array
1683  float *data = static_cast<vtkFloatArray*> (points->GetData ())->GetPointer (0);
1684 
1685  vtkIdType ptr = 0;
1686  std::vector<int> lookup;
1687  // If the dataset is dense (no NaNs)
1688  if (cloud->is_dense)
1689  {
1690  for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
1691  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1692  }
1693  else
1694  {
1695  lookup.resize (nr_points);
1696  vtkIdType j = 0; // true point index
1697  for (vtkIdType i = 0; i < nr_points; ++i)
1698  {
1699  // Check if the point is invalid
1700  if (!isFinite ((*cloud)[i]))
1701  continue;
1702 
1703  lookup[i] = static_cast<int> (j);
1704  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1705  j++;
1706  ptr += 3;
1707  }
1708  nr_points = j;
1709  points->SetNumberOfPoints (nr_points);
1710  }
1711 
1712  // Get the maximum size of a polygon
1713  int max_size_of_polygon = -1;
1714  for (const auto &vertex : vertices)
1715  if (max_size_of_polygon < static_cast<int> (vertex.vertices.size ()))
1716  max_size_of_polygon = static_cast<int> (vertex.vertices.size ());
1717 
1718  if (vertices.size () > 1)
1719  {
1720  // Create polys from polyMesh.polygons
1722 
1723  const auto idx = details::fillCells(lookup,vertices,cell_array, max_size_of_polygon);
1724 
1726  allocVtkPolyData (polydata);
1727  cell_array->GetData ()->SetNumberOfValues (idx);
1728  cell_array->Squeeze ();
1729  polydata->SetPolys (cell_array);
1730  polydata->SetPoints (points);
1731 
1732  if (colors)
1733  polydata->GetPointData ()->SetScalars (colors);
1734 
1735  createActorFromVTKDataSet (polydata, actor, false);
1736  }
1737  else
1738  {
1740  std::size_t n_points = vertices[0].vertices.size ();
1741  polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
1742 
1743  if (!lookup.empty ())
1744  {
1745  for (std::size_t j = 0; j < (n_points - 1); ++j)
1746  polygon->GetPointIds ()->SetId (j, lookup[vertices[0].vertices[j]]);
1747  }
1748  else
1749  {
1750  for (std::size_t j = 0; j < (n_points - 1); ++j)
1751  polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
1752  }
1754  allocVtkUnstructuredGrid (poly_grid);
1755  poly_grid->Allocate (1, 1);
1756  poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
1757  poly_grid->SetPoints (points);
1758  if (colors)
1759  poly_grid->GetPointData ()->SetScalars (colors);
1760 
1761  createActorFromVTKDataSet (poly_grid, actor, false);
1762  }
1763  addActorToRenderer (actor, viewport);
1764  actor->GetProperty ()->SetRepresentationToSurface ();
1765  // Backface culling renders the visualization slower, but guarantees that we see all triangles
1766  actor->GetProperty ()->BackfaceCullingOff ();
1767  actor->GetProperty ()->SetInterpolationToFlat ();
1768  actor->GetProperty ()->EdgeVisibilityOff ();
1769  actor->GetProperty ()->ShadingOff ();
1770 
1771  // Save the pointer/ID pair to the global actor map
1772  (*cloud_actor_map_)[id].actor = actor;
1773 
1774  // Save the viewpoint transformation matrix to the global actor map
1776  convertToVtkMatrix (cloud->sensor_origin_, cloud->sensor_orientation_, transformation);
1777  (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
1778 
1779  return (true);
1780 }
1781 
1782 /////////////////////////////////////////////////////////////////////////////////////////////
1783 template <typename PointT> bool
1785  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1786  const std::vector<pcl::Vertices> &verts,
1787  const std::string &id)
1788 {
1789  if (verts.empty ())
1790  {
1791  pcl::console::print_error ("[addPolygonMesh] No vertices given!\n");
1792  return (false);
1793  }
1794 
1795  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1796  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1797  if (am_it == cloud_actor_map_->end ())
1798  return (false);
1799 
1800  // Get the current poly data
1801  vtkSmartPointer<vtkPolyData> polydata = static_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1802  if (!polydata)
1803  return (false);
1804  vtkSmartPointer<vtkCellArray> cells = polydata->GetPolys ();
1805  if (!cells)
1806  return (false);
1807  vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
1808  // Copy the new point array in
1809  vtkIdType nr_points = cloud->size ();
1810  points->SetNumberOfPoints (nr_points);
1811 
1812  // Get a pointer to the beginning of the data array
1813  float *data = (static_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
1814 
1815  int ptr = 0;
1816  std::vector<int> lookup;
1817  // If the dataset is dense (no NaNs)
1818  if (cloud->is_dense)
1819  {
1820  for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
1821  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1822  }
1823  else
1824  {
1825  lookup.resize (nr_points);
1826  vtkIdType j = 0; // true point index
1827  for (vtkIdType i = 0; i < nr_points; ++i)
1828  {
1829  // Check if the point is invalid
1830  if (!isFinite ((*cloud)[i]))
1831  continue;
1832 
1833  lookup [i] = static_cast<int> (j);
1834  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1835  j++;
1836  ptr += 3;
1837  }
1838  nr_points = j;
1839  points->SetNumberOfPoints (nr_points);
1840  }
1841 
1842  // Update colors
1843  vtkUnsignedCharArray* colors = vtkUnsignedCharArray::SafeDownCast (polydata->GetPointData ()->GetScalars ());
1844  if (!colors)
1845  return (false);
1846  int rgb_idx = -1;
1847  std::vector<pcl::PCLPointField> fields;
1848  rgb_idx = pcl::getFieldIndex<PointT> ("rgb", fields);
1849  if (rgb_idx == -1)
1850  rgb_idx = pcl::getFieldIndex<PointT> ("rgba", fields);
1851  if (rgb_idx != -1 && colors)
1852  {
1853  int j = 0;
1854  std::uint32_t offset = fields[rgb_idx].offset;
1855  for (std::size_t i = 0; i < cloud->size (); ++i)
1856  {
1857  if (!isFinite ((*cloud)[i]))
1858  continue;
1859  const pcl::RGB* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
1860  unsigned char color[3];
1861  color[0] = rgb_data->r;
1862  color[1] = rgb_data->g;
1863  color[2] = rgb_data->b;
1864  colors->SetTupleValue (j++, color);
1865  }
1866  }
1867 
1868  // Get the maximum size of a polygon
1869  int max_size_of_polygon = -1;
1870  for (const auto &vertex : verts)
1871  if (max_size_of_polygon < static_cast<int> (vertex.vertices.size ()))
1872  max_size_of_polygon = static_cast<int> (vertex.vertices.size ());
1873 
1874  // Update the cells
1876 
1877  const auto idx = details::fillCells(lookup, verts, cells, max_size_of_polygon);
1878 
1879  cells->GetData ()->SetNumberOfValues (idx);
1880  cells->Squeeze ();
1881  // Set the the vertices
1882  polydata->SetPolys (cells);
1883 
1884  return (true);
1885 }
1886 
1887 #ifdef vtkGenericDataArray_h
1888 #undef SetTupleValue
1889 #undef InsertNextTupleValue
1890 #undef GetTupleValue
1891 #endif
1892 
1893 #endif
PlanarPolygon represents a planar (2D) polygon, potentially in a 3D space.
bool empty() const
Definition: point_cloud.h:446
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields).
Definition: point_cloud.h:403
Eigen::Quaternionf sensor_orientation_
Sensor acquisition pose (rotation).
Definition: point_cloud.h:408
std::uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:398
bool isOrganized() const
Return whether a dataset is organized (e.g., arranged in a structured grid).
Definition: point_cloud.h:310
std::uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:400
std::size_t size() const
Definition: point_cloud.h:443
Eigen::Vector4f sensor_origin_
Sensor acquisition pose (origin/translation).
Definition: point_cloud.h:406
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
Definition: point_cloud.h:395
shared_ptr< const PointCloud< PointT > > ConstPtr
Definition: point_cloud.h:414
vtkSmartPointer< vtkLODActor > actor
The actor holding the data to render.
Definition: actor_map.h:79
bool addPointCloudIntensityGradients(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, const typename pcl::PointCloud< GradientT >::ConstPtr &gradients, int level=100, double scale=1e-6, const std::string &id="cloud", int viewport=0)
Add the estimated surface intensity gradients of a Point Cloud to screen.
bool addPolygonMesh(const pcl::PolygonMesh &polymesh, const std::string &id="polygon", int viewport=0)
Add a PolygonMesh object to screen.
bool addSphere(const PointT &center, double radius, const std::string &id="sphere", int viewport=0)
Add a sphere shape from a point and a radius.
bool addPointCloud(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, const std::string &id="cloud", int viewport=0)
Add a Point Cloud (templated) to screen.
bool addCorrespondences(const typename pcl::PointCloud< PointT >::ConstPtr &source_points, const typename pcl::PointCloud< PointT >::ConstPtr &target_points, const std::vector< int > &correspondences, const std::string &id="correspondences", int viewport=0)
Add the specified correspondences to the display.
bool addPolygon(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, double r, double g, double b, const std::string &id="polygon", int viewport=0)
Add a polygon (polyline) that represents the input point cloud (connects all points in order)
bool updatePointCloud(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, const std::string &id="cloud")
Updates the XYZ data for an existing cloud object id on screen.
GeometryHandler::ConstPtr GeometryHandlerConstPtr
bool addPointCloudNormals(const typename pcl::PointCloud< PointNT >::ConstPtr &cloud, int level=100, float scale=0.02f, const std::string &id="cloud", int viewport=0)
Add the estimated surface normals of a Point Cloud to screen.
bool addText3D(const std::string &text, const PointT &position, double textScale=1.0, double r=1.0, double g=1.0, double b=1.0, const std::string &id="", int viewport=0)
Add a 3d text to the scene.
bool updateSphere(const PointT &center, double radius, double r, double g, double b, const std::string &id="sphere")
Update an existing sphere shape from a point and a radius.
ColorHandler::ConstPtr ColorHandlerConstPtr
bool addArrow(const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id="arrow", int viewport=0)
Add a line arrow segment between two points, and display the distance between them.
bool addLine(const P1 &pt1, const P2 &pt2, const std::string &id="line", int viewport=0)
Add a line segment from two points.
bool addPointCloudPrincipalCurvatures(const typename pcl::PointCloud< PointNT >::ConstPtr &cloud, const typename pcl::PointCloud< pcl::PrincipalCurvatures >::ConstPtr &pcs, int level=100, float scale=1.0f, const std::string &id="cloud", int viewport=0)
Add the estimated principal curvatures of a Point Cloud to screen.
bool updatePolygonMesh(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, const std::vector< pcl::Vertices > &vertices, const std::string &id="polygon")
Update a PolygonMesh object on screen.
bool updateCorrespondences(const typename pcl::PointCloud< PointT >::ConstPtr &source_points, const typename pcl::PointCloud< PointT >::ConstPtr &target_points, const pcl::Correspondences &correspondences, int nth, const std::string &id="correspondences", int viewport=0)
Update the specified correspondences to the display.
Base Handler class for PointCloud colors.
bool isCapable() const
Check if this handler is capable of handling the input data or not.
virtual std::string getName() const =0
Abstract getName method.
virtual vtkSmartPointer< vtkDataArray > getColor() const =0
Obtain the actual color for the input dataset as a VTK data array.
Base handler class for PointCloud geometry.
virtual std::string getName() const =0
Abstract getName method.
bool isCapable() const
Checl if this handler is capable of handling the input data or not.
virtual void getGeometry(vtkSmartPointer< vtkPoints > &points) const =0
Obtain the actual point geometry for the input dataset in VTK format.
PCL_EXPORTS vtkSmartPointer< vtkDataSet > createLine(const Eigen::Vector4f &pt1, const Eigen::Vector4f &pt2)
Create a line shape from two points.
PCL_EXPORTS void print_error(const char *format,...)
Print an error message on stream with colors.
void ignore(const T &...)
Utility function to eliminate unused variable warnings.
Definition: utils.h:62
PCL_EXPORTS vtkIdType fillCells(std::vector< int > &lookup, const std::vector< pcl::Vertices > &vertices, vtkSmartPointer< vtkCellArray > cell_array, int max_size_of_polygon)
PCL_EXPORTS void allocVtkUnstructuredGrid(vtkSmartPointer< vtkUnstructuredGrid > &polydata)
Allocate a new unstructured grid smartpointer.
bool isFinite(const PointT &pt)
Tests if the 3D components of a point are all finite param[in] pt point to be tested return true if f...
Definition: point_tests.h:55
static constexpr index_t UNAVAILABLE
Definition: pcl_base.h:62
std::vector< pcl::Correspondence, Eigen::aligned_allocator< pcl::Correspondence > > Correspondences
Define methods or creating 3D shapes from parametric models.
A point structure representing Euclidean xyz coordinates, and the RGB color.
A structure representing RGB color information.