Point Cloud Library (PCL)  1.12.1-dev
pcl_visualizer.hpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2012, Open Perception, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of the copyright holder(s) nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 #ifndef PCL_PCL_VISUALIZER_IMPL_H_
39 #define PCL_PCL_VISUALIZER_IMPL_H_
40 
41 #include <vtkVersion.h>
42 #include <vtkSmartPointer.h>
43 #include <vtkCellArray.h>
44 #include <vtkLeaderActor2D.h>
45 #include <vtkVectorText.h>
46 #include <vtkAlgorithmOutput.h>
47 #include <vtkFollower.h>
48 #include <vtkMath.h>
49 #include <vtkSphereSource.h>
50 #include <vtkProperty2D.h>
51 #include <vtkDataSetSurfaceFilter.h>
52 #include <vtkPointData.h>
53 #include <vtkPolyDataMapper.h>
54 #include <vtkProperty.h>
55 #include <vtkMapper.h>
56 #include <vtkCellData.h>
57 #include <vtkDataSetMapper.h>
58 #include <vtkRenderer.h>
59 #include <vtkRendererCollection.h>
60 #include <vtkAppendPolyData.h>
61 #include <vtkTextProperty.h>
62 #include <vtkLODActor.h>
63 #include <vtkLineSource.h>
64 
65 #include <pcl/common/utils.h> // pcl::utils::ignore
67 
68 // Support for VTK 7.1 upwards
69 #ifdef vtkGenericDataArray_h
70 #define SetTupleValue SetTypedTuple
71 #define InsertNextTupleValue InsertNextTypedTuple
72 #define GetTupleValue GetTypedTuple
73 #endif
74 
75 //////////////////////////////////////////////////////////////////////////////////////////////
76 template <typename PointT> bool
78  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
79  const std::string &id, int viewport)
80 {
81  // Convert the PointCloud to VTK PolyData
82  PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
83  return (addPointCloud<PointT> (cloud, geometry_handler, id, viewport));
84 }
85 
86 //////////////////////////////////////////////////////////////////////////////////////////////
87 template <typename PointT> bool
89  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
90  const PointCloudGeometryHandler<PointT> &geometry_handler,
91  const std::string &id, int viewport)
92 {
93  if (contains (id))
94  {
95  PCL_WARN ("[addPointCloud] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
96  return (false);
97  }
98 
99  if (pcl::traits::has_color<PointT>())
100  {
101  PointCloudColorHandlerRGBField<PointT> color_handler_rgb_field (cloud);
102  return (fromHandlersToScreen (geometry_handler, color_handler_rgb_field, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
103  }
104  PointCloudColorHandlerCustom<PointT> color_handler (cloud, 255, 255, 255);
105  return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
106 }
107 
108 //////////////////////////////////////////////////////////////////////////////////////////////
109 template <typename PointT> bool
111  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
112  const GeometryHandlerConstPtr &geometry_handler,
113  const std::string &id, int viewport)
114 {
115  if (contains (id))
116  {
117  // Here we're just pushing the handlers onto the queue. If needed, something fancier could
118  // be done such as checking if a specific handler already exists, etc.
119  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 
759  // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
760  // for multiple viewport
761  const std::string uid = tid + std::string (i, '*');
762  (*shape_actor_map_)[uid] = textActor;
763  }
764 
765  ++i;
766  }
767 
768  return (true);
769 }
770 
771 //////////////////////////////////////////////////
772 template <typename PointT> bool
774  const std::string &text,
775  const PointT& position,
776  double orientation[3],
777  double textScale,
778  double r,
779  double g,
780  double b,
781  const std::string &id,
782  int viewport)
783 {
784  std::string tid;
785  if (id.empty ())
786  tid = text;
787  else
788  tid = id;
789 
790  if (viewport < 0)
791  return false;
792 
793  // If there is no custom viewport and the viewport number is not 0, exit
794  if (rens_->GetNumberOfItems () <= viewport)
795  {
796  PCL_ERROR ("[addText3D] The viewport [%d] doesn't exist (id <%s>)!\n",
797  viewport,
798  tid.c_str ());
799  return false;
800  }
801 
802  // check all or an individual viewport for a similar id
803  rens_->InitTraversal ();
804  for (std::size_t i = viewport; rens_->GetNextItem (); ++i)
805  {
806  const std::string uid = tid + std::string (i, '*');
807  if (contains (uid))
808  {
809  PCL_ERROR ( "[addText3D] The id <%s> already exists in viewport [%d]! "
810  "Please choose a different id and retry.\n",
811  tid.c_str (),
812  i);
813  return false;
814  }
815 
816  if (viewport > 0)
817  break;
818  }
819 
821  textSource->SetText (text.c_str());
822  textSource->Update ();
823 
825  textMapper->SetInputConnection (textSource->GetOutputPort ());
826 
828  textActor->SetMapper (textMapper);
829  textActor->SetPosition (position.x, position.y, position.z);
830  textActor->SetScale (textScale);
831  textActor->GetProperty ()->SetColor (r, g, b);
832  textActor->SetOrientation (orientation);
833 
834  // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
835  rens_->InitTraversal ();
836  int i = 0;
837  for ( vtkRenderer* renderer = rens_->GetNextItem ();
838  renderer;
839  renderer = rens_->GetNextItem (), ++i)
840  {
841  if (viewport == 0 || viewport == i)
842  {
843  renderer->AddActor (textActor);
844  const std::string uid = tid + std::string (i, '*');
845  (*shape_actor_map_)[uid] = textActor;
846  }
847  }
848 
849  return (true);
850 }
851 
852 //////////////////////////////////////////////////////////////////////////////////////////////
853 template <typename PointNT> bool
855  const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
856  int level, float scale, const std::string &id, int viewport)
857 {
858  return (addPointCloudNormals<PointNT, PointNT> (cloud, cloud, level, scale, id, viewport));
859 }
860 
861 //////////////////////////////////////////////////////////////////////////////////////////////
862 template <typename PointT, typename PointNT> bool
864  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
865  const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
866  int level, float scale,
867  const std::string &id, int viewport)
868 {
869  if (normals->size () != cloud->size ())
870  {
871  PCL_ERROR ("[addPointCloudNormals] The number of points differs from the number of normals!\n");
872  return (false);
873  }
874 
875  if (normals->empty ())
876  {
877  PCL_WARN ("[addPointCloudNormals] An empty normal cloud is given! Nothing to display.\n");
878  return (false);
879  }
880 
881  if (contains (id))
882  {
883  PCL_WARN ("[addPointCloudNormals] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
884  return (false);
885  }
886 
889 
890  points->SetDataTypeToFloat ();
892  data->SetNumberOfComponents (3);
893 
894 
895  vtkIdType nr_normals = 0;
896  float* pts = nullptr;
897 
898  // If the cloud is organized, then distribute the normal step in both directions
899  if (cloud->isOrganized () && normals->isOrganized ())
900  {
901  vtkIdType point_step = static_cast<vtkIdType> (sqrt (double (level)));
902  nr_normals = (static_cast<vtkIdType> ((cloud->width - 1)/ point_step) + 1) *
903  (static_cast<vtkIdType> ((cloud->height - 1) / point_step) + 1);
904  pts = new float[2 * nr_normals * 3];
905 
906  vtkIdType cell_count = 0;
907  for (vtkIdType y = 0; y < normals->height; y += point_step)
908  for (vtkIdType x = 0; x < normals->width; x += point_step)
909  {
910  PointT p = (*cloud)(x, y);
911  p.x += (*normals)(x, y).normal[0] * scale;
912  p.y += (*normals)(x, y).normal[1] * scale;
913  p.z += (*normals)(x, y).normal[2] * scale;
914 
915  pts[2 * cell_count * 3 + 0] = (*cloud)(x, y).x;
916  pts[2 * cell_count * 3 + 1] = (*cloud)(x, y).y;
917  pts[2 * cell_count * 3 + 2] = (*cloud)(x, y).z;
918  pts[2 * cell_count * 3 + 3] = p.x;
919  pts[2 * cell_count * 3 + 4] = p.y;
920  pts[2 * cell_count * 3 + 5] = p.z;
921 
922  lines->InsertNextCell (2);
923  lines->InsertCellPoint (2 * cell_count);
924  lines->InsertCellPoint (2 * cell_count + 1);
925  cell_count ++;
926  }
927  }
928  else
929  {
930  nr_normals = (cloud->size () - 1) / level + 1 ;
931  pts = new float[2 * nr_normals * 3];
932 
933  for (vtkIdType i = 0, j = 0; j < nr_normals; j++, i = j * level)
934  {
935  PointT p = (*cloud)[i];
936  p.x += (*normals)[i].normal[0] * scale;
937  p.y += (*normals)[i].normal[1] * scale;
938  p.z += (*normals)[i].normal[2] * scale;
939 
940  pts[2 * j * 3 + 0] = (*cloud)[i].x;
941  pts[2 * j * 3 + 1] = (*cloud)[i].y;
942  pts[2 * j * 3 + 2] = (*cloud)[i].z;
943  pts[2 * j * 3 + 3] = p.x;
944  pts[2 * j * 3 + 4] = p.y;
945  pts[2 * j * 3 + 5] = p.z;
946 
947  lines->InsertNextCell (2);
948  lines->InsertCellPoint (2 * j);
949  lines->InsertCellPoint (2 * j + 1);
950  }
951  }
952 
953  data->SetArray (&pts[0], 2 * nr_normals * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
954  points->SetData (data);
955 
957  polyData->SetPoints (points);
958  polyData->SetLines (lines);
959 
961  mapper->SetInputData (polyData);
962  mapper->SetColorModeToMapScalars();
963  mapper->SetScalarModeToUsePointData();
964 
965  // create actor
967  actor->SetMapper (mapper);
968 
969  // Use cloud view point info
971  convertToVtkMatrix (cloud->sensor_origin_, cloud->sensor_orientation_, transformation);
972  actor->SetUserMatrix (transformation);
973 
974  // Add it to all renderers
975  addActorToRenderer (actor, viewport);
976 
977  // Save the pointer/ID pair to the global actor map
978  (*cloud_actor_map_)[id].actor = actor;
979  return (true);
980 }
981 
982 //////////////////////////////////////////////////////////////////////////////////////////////
983 template <typename PointNT> bool
985  const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
987  int level, float scale,
988  const std::string &id, int viewport)
989 {
990  return (addPointCloudPrincipalCurvatures<PointNT, PointNT> (cloud, cloud, pcs, level, scale, id, viewport));
991 }
992 
993 //////////////////////////////////////////////////////////////////////////////////////////////
994 template <typename PointT, typename PointNT> bool
996  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
997  const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
999  int level, float scale,
1000  const std::string &id, int viewport)
1001 {
1002  if (pcs->size () != cloud->size () || normals->size () != cloud->size ())
1003  {
1004  pcl::console::print_error ("[addPointCloudPrincipalCurvatures] The number of points differs from the number of principal curvatures/normals!\n");
1005  return (false);
1006  }
1007 
1008  if (contains (id))
1009  {
1010  PCL_WARN ("[addPointCloudPrincipalCurvatures] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1011  return (false);
1012  }
1013 
1016 
1017  // Setup two colors - one for each line
1018  unsigned char green[3] = {0, 255, 0};
1019  unsigned char blue[3] = {0, 0, 255};
1020 
1021  // Setup the colors array
1023  line_1_colors->SetNumberOfComponents (3);
1024  line_1_colors->SetName ("Colors");
1026  line_2_colors->SetNumberOfComponents (3);
1027  line_2_colors->SetName ("Colors");
1028 
1029  // Create the first sets of lines
1030  for (std::size_t i = 0; i < cloud->size (); i+=level)
1031  {
1032  PointT p = (*cloud)[i];
1033  p.x += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[0]) * scale;
1034  p.y += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[1]) * scale;
1035  p.z += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[2]) * scale;
1036 
1038  line_1->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1039  line_1->SetPoint2 (p.x, p.y, p.z);
1040  line_1->Update ();
1041  polydata_1->AddInputData (line_1->GetOutput ());
1042  line_1_colors->InsertNextTupleValue (green);
1043  }
1044  polydata_1->Update ();
1045  vtkSmartPointer<vtkPolyData> line_1_data = polydata_1->GetOutput ();
1046  line_1_data->GetCellData ()->SetScalars (line_1_colors);
1047 
1048  // Create the second sets of lines
1049  for (std::size_t i = 0; i < cloud->size (); i += level)
1050  {
1051  Eigen::Vector3f pc ((*pcs)[i].principal_curvature[0],
1052  (*pcs)[i].principal_curvature[1],
1053  (*pcs)[i].principal_curvature[2]);
1054  Eigen::Vector3f normal ((*normals)[i].normal[0],
1055  (*normals)[i].normal[1],
1056  (*normals)[i].normal[2]);
1057  Eigen::Vector3f pc_c = pc.cross (normal);
1058 
1059  PointT p = (*cloud)[i];
1060  p.x += ((*pcs)[i].pc2 * pc_c[0]) * scale;
1061  p.y += ((*pcs)[i].pc2 * pc_c[1]) * scale;
1062  p.z += ((*pcs)[i].pc2 * pc_c[2]) * scale;
1063 
1065  line_2->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1066  line_2->SetPoint2 (p.x, p.y, p.z);
1067  line_2->Update ();
1068  polydata_2->AddInputData (line_2->GetOutput ());
1069 
1070  line_2_colors->InsertNextTupleValue (blue);
1071  }
1072  polydata_2->Update ();
1073  vtkSmartPointer<vtkPolyData> line_2_data = polydata_2->GetOutput ();
1074  line_2_data->GetCellData ()->SetScalars (line_2_colors);
1075 
1076  // Assemble the two sets of lines
1078  alldata->AddInputData (line_1_data);
1079  alldata->AddInputData (line_2_data);
1080 
1081  // Create an Actor
1083  createActorFromVTKDataSet (alldata->GetOutput (), actor);
1084  actor->GetMapper ()->SetScalarModeToUseCellData ();
1085 
1086  // Add it to all renderers
1087  addActorToRenderer (actor, viewport);
1088 
1089  // Save the pointer/ID pair to the global actor map
1090  CloudActor act;
1091  act.actor = actor;
1092  (*cloud_actor_map_)[id] = act;
1093  return (true);
1094 }
1095 
1096 //////////////////////////////////////////////////////////////////////////////////////////////
1097 template <typename PointT, typename GradientT> bool
1099  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1100  const typename pcl::PointCloud<GradientT>::ConstPtr &gradients,
1101  int level, double scale,
1102  const std::string &id, int viewport)
1103 {
1104  if (gradients->size () != cloud->size ())
1105  {
1106  PCL_ERROR ("[addPointCloudGradients] The number of points differs from the number of gradients!\n");
1107  return (false);
1108  }
1109  if (contains (id))
1110  {
1111  PCL_WARN ("[addPointCloudGradients] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1112  return (false);
1113  }
1114 
1117 
1118  points->SetDataTypeToFloat ();
1120  data->SetNumberOfComponents (3);
1121 
1122  vtkIdType nr_gradients = (cloud->size () - 1) / level + 1 ;
1123  float* pts = new float[2 * nr_gradients * 3];
1124 
1125  for (vtkIdType i = 0, j = 0; j < nr_gradients; j++, i = j * level)
1126  {
1127  PointT p = (*cloud)[i];
1128  p.x += (*gradients)[i].gradient[0] * scale;
1129  p.y += (*gradients)[i].gradient[1] * scale;
1130  p.z += (*gradients)[i].gradient[2] * scale;
1131 
1132  pts[2 * j * 3 + 0] = (*cloud)[i].x;
1133  pts[2 * j * 3 + 1] = (*cloud)[i].y;
1134  pts[2 * j * 3 + 2] = (*cloud)[i].z;
1135  pts[2 * j * 3 + 3] = p.x;
1136  pts[2 * j * 3 + 4] = p.y;
1137  pts[2 * j * 3 + 5] = p.z;
1138 
1139  lines->InsertNextCell(2);
1140  lines->InsertCellPoint(2*j);
1141  lines->InsertCellPoint(2*j+1);
1142  }
1143 
1144  data->SetArray (&pts[0], 2 * nr_gradients * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
1145  points->SetData (data);
1146 
1148  polyData->SetPoints(points);
1149  polyData->SetLines(lines);
1150 
1152  mapper->SetInputData (polyData);
1153  mapper->SetColorModeToMapScalars();
1154  mapper->SetScalarModeToUsePointData();
1155 
1156  // create actor
1158  actor->SetMapper (mapper);
1159 
1160  // Add it to all renderers
1161  addActorToRenderer (actor, viewport);
1162 
1163  // Save the pointer/ID pair to the global actor map
1164  (*cloud_actor_map_)[id].actor = actor;
1165  return (true);
1166 }
1167 
1168 //////////////////////////////////////////////////////////////////////////////////////////////
1169 template <typename PointT> bool
1171  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1172  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1173  const std::vector<int> &correspondences,
1174  const std::string &id,
1175  int viewport)
1176 {
1177  pcl::Correspondences corrs;
1178  corrs.resize (correspondences.size ());
1179 
1180  std::size_t index = 0;
1181  for (auto &corr : corrs)
1182  {
1183  corr.index_query = index;
1184  corr.index_match = correspondences[index];
1185  index++;
1186  }
1187 
1188  return (addCorrespondences<PointT> (source_points, target_points, corrs, id, viewport));
1189 }
1190 
1191 //////////////////////////////////////////////////////////////////////////////////////////////
1192 template <typename PointT> bool
1194  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1195  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1196  const pcl::Correspondences &correspondences,
1197  int nth,
1198  const std::string &id,
1199  int viewport,
1200  bool overwrite)
1201 {
1202  if (correspondences.empty ())
1203  {
1204  PCL_DEBUG ("[addCorrespondences] An empty set of correspondences given! Nothing to display.\n");
1205  return (false);
1206  }
1207 
1208  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1209  ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
1210  if (am_it != shape_actor_map_->end () && !overwrite)
1211  {
1212  PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1213  return (false);
1214  }
1215  if (am_it == shape_actor_map_->end () && overwrite)
1216  {
1217  overwrite = false; // Correspondences doesn't exist, add them instead of updating them
1218  }
1219 
1220  int n_corr = int (correspondences.size () / nth);
1222 
1223  // Prepare colors
1225  line_colors->SetNumberOfComponents (3);
1226  line_colors->SetName ("Colors");
1227  line_colors->SetNumberOfTuples (n_corr);
1228 
1229  // Prepare coordinates
1231  line_points->SetNumberOfPoints (2 * n_corr);
1232 
1234  line_cells_id->SetNumberOfComponents (3);
1235  line_cells_id->SetNumberOfTuples (n_corr);
1236  vtkIdType *line_cell_id = line_cells_id->GetPointer (0);
1238 
1240  line_tcoords->SetNumberOfComponents (1);
1241  line_tcoords->SetNumberOfTuples (n_corr * 2);
1242  line_tcoords->SetName ("Texture Coordinates");
1243 
1244  double tc[3] = {0.0, 0.0, 0.0};
1245 
1246  Eigen::Affine3f source_transformation;
1247  source_transformation.linear () = source_points->sensor_orientation_.matrix ();
1248  source_transformation.translation () = source_points->sensor_origin_.head (3);
1249  Eigen::Affine3f target_transformation;
1250  target_transformation.linear () = target_points->sensor_orientation_.matrix ();
1251  target_transformation.translation () = target_points->sensor_origin_.head (3);
1252 
1253  int j = 0;
1254  // Draw lines between the best corresponding points
1255  for (std::size_t i = 0; i < correspondences.size (); i += nth, ++j)
1256  {
1257  if (correspondences[i].index_match == UNAVAILABLE)
1258  {
1259  PCL_WARN ("[addCorrespondences] No valid index_match for correspondence %d\n", i);
1260  continue;
1261  }
1262 
1263  PointT p_src ((*source_points)[correspondences[i].index_query]);
1264  PointT p_tgt ((*target_points)[correspondences[i].index_match]);
1265 
1266  p_src.getVector3fMap () = source_transformation * p_src.getVector3fMap ();
1267  p_tgt.getVector3fMap () = target_transformation * p_tgt.getVector3fMap ();
1268 
1269  int id1 = j * 2 + 0, id2 = j * 2 + 1;
1270  // Set the points
1271  line_points->SetPoint (id1, p_src.x, p_src.y, p_src.z);
1272  line_points->SetPoint (id2, p_tgt.x, p_tgt.y, p_tgt.z);
1273  // Set the cell ID
1274  *line_cell_id++ = 2;
1275  *line_cell_id++ = id1;
1276  *line_cell_id++ = id2;
1277  // Set the texture coords
1278  tc[0] = 0.; line_tcoords->SetTuple (id1, tc);
1279  tc[0] = 1.; line_tcoords->SetTuple (id2, tc);
1280 
1281  float rgb[3];
1282  rgb[0] = vtkMath::Random (32, 255); // min / max
1283  rgb[1] = vtkMath::Random (32, 255);
1284  rgb[2] = vtkMath::Random (32, 255);
1285  line_colors->InsertTuple (i, rgb);
1286  }
1287  line_colors->SetNumberOfTuples (j);
1288  line_cells_id->SetNumberOfTuples (j);
1289  line_cells->SetCells (n_corr, line_cells_id);
1290  line_points->SetNumberOfPoints (j*2);
1291  line_tcoords->SetNumberOfTuples (j*2);
1292 
1293  // Fill in the lines
1294  line_data->SetPoints (line_points);
1295  line_data->SetLines (line_cells);
1296  line_data->GetPointData ()->SetTCoords (line_tcoords);
1297  line_data->GetCellData ()->SetScalars (line_colors);
1298 
1299  // Create an Actor
1300  if (!overwrite)
1301  {
1303  createActorFromVTKDataSet (line_data, actor);
1304  actor->GetProperty ()->SetRepresentationToWireframe ();
1305  actor->GetProperty ()->SetOpacity (0.5);
1306  addActorToRenderer (actor, viewport);
1307 
1308  // Save the pointer/ID pair to the global actor map
1309  (*shape_actor_map_)[id] = actor;
1310  }
1311  else
1312  {
1313  vtkSmartPointer<vtkLODActor> actor = vtkLODActor::SafeDownCast (am_it->second);
1314  if (!actor)
1315  return (false);
1316  // Update the mapper
1317  reinterpret_cast<vtkPolyDataMapper*> (actor->GetMapper ())->SetInputData (line_data);
1318  }
1319 
1320  return (true);
1321 }
1322 
1323 //////////////////////////////////////////////////////////////////////////////////////////////
1324 template <typename PointT> bool
1326  const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1327  const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1328  const pcl::Correspondences &correspondences,
1329  int nth,
1330  const std::string &id,
1331  int viewport)
1332 {
1333  return (addCorrespondences<PointT> (source_points, target_points, correspondences, nth, id, viewport, true));
1334 }
1335 
1336 //////////////////////////////////////////////////////////////////////////////////////////////
1337 template <typename PointT> bool
1338 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1339  const PointCloudGeometryHandler<PointT> &geometry_handler,
1340  const PointCloudColorHandler<PointT> &color_handler,
1341  const std::string &id,
1342  int viewport,
1343  const Eigen::Vector4f& sensor_origin,
1344  const Eigen::Quaternion<float>& sensor_orientation)
1345 {
1346  if (!geometry_handler.isCapable ())
1347  {
1348  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1349  return (false);
1350  }
1351 
1352  if (!color_handler.isCapable ())
1353  {
1354  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1355  return (false);
1356  }
1357 
1360  // Convert the PointCloud to VTK PolyData
1361  convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1362 
1363  // Get the colors from the handler
1364  bool has_colors = false;
1365  double minmax[2];
1366  if (auto scalars = color_handler.getColor ())
1367  {
1368  polydata->GetPointData ()->SetScalars (scalars);
1369  scalars->GetRange (minmax);
1370  has_colors = true;
1371  }
1372 
1373  // Create an Actor
1375  createActorFromVTKDataSet (polydata, actor);
1376  if (has_colors)
1377  actor->GetMapper ()->SetScalarRange (minmax);
1378 
1379  // Add it to all renderers
1380  addActorToRenderer (actor, viewport);
1381 
1382  // Save the pointer/ID pair to the global actor map
1383  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1384  cloud_actor.actor = actor;
1385  cloud_actor.cells = initcells;
1386 
1387  // Save the viewpoint transformation matrix to the global actor map
1389  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1390  cloud_actor.viewpoint_transformation_ = transformation;
1391  cloud_actor.actor->SetUserMatrix (transformation);
1392  cloud_actor.actor->Modified ();
1393 
1394  return (true);
1395 }
1396 
1397 //////////////////////////////////////////////////////////////////////////////////////////////
1398 template <typename PointT> bool
1399 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1400  const PointCloudGeometryHandler<PointT> &geometry_handler,
1401  const ColorHandlerConstPtr &color_handler,
1402  const std::string &id,
1403  int viewport,
1404  const Eigen::Vector4f& sensor_origin,
1405  const Eigen::Quaternion<float>& sensor_orientation)
1406 {
1407  if (!geometry_handler.isCapable ())
1408  {
1409  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1410  return (false);
1411  }
1412 
1413  if (!color_handler->isCapable ())
1414  {
1415  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler->getName ().c_str ());
1416  return (false);
1417  }
1418 
1421  // Convert the PointCloud to VTK PolyData
1422  convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1423  // use the given geometry handler
1424 
1425  // Get the colors from the handler
1426  bool has_colors = false;
1427  double minmax[2];
1428  if (auto scalars = color_handler->getColor ())
1429  {
1430  polydata->GetPointData ()->SetScalars (scalars);
1431  scalars->GetRange (minmax);
1432  has_colors = true;
1433  }
1434 
1435  // Create an Actor
1437  createActorFromVTKDataSet (polydata, actor);
1438  if (has_colors)
1439  actor->GetMapper ()->SetScalarRange (minmax);
1440 
1441  // Add it to all renderers
1442  addActorToRenderer (actor, viewport);
1443 
1444  // Save the pointer/ID pair to the global actor map
1445  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1446  cloud_actor.actor = actor;
1447  cloud_actor.cells = initcells;
1448  cloud_actor.color_handlers.push_back (color_handler);
1449 
1450  // Save the viewpoint transformation matrix to the global actor map
1452  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1453  cloud_actor.viewpoint_transformation_ = transformation;
1454  cloud_actor.actor->SetUserMatrix (transformation);
1455  cloud_actor.actor->Modified ();
1456 
1457  return (true);
1458 }
1459 
1460 //////////////////////////////////////////////////////////////////////////////////////////////
1461 template <typename PointT> bool
1462 pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1463  const GeometryHandlerConstPtr &geometry_handler,
1464  const PointCloudColorHandler<PointT> &color_handler,
1465  const std::string &id,
1466  int viewport,
1467  const Eigen::Vector4f& sensor_origin,
1468  const Eigen::Quaternion<float>& sensor_orientation)
1469 {
1470  if (!geometry_handler->isCapable ())
1471  {
1472  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler->getName ().c_str ());
1473  return (false);
1474  }
1475 
1476  if (!color_handler.isCapable ())
1477  {
1478  PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1479  return (false);
1480  }
1481 
1484  // Convert the PointCloud to VTK PolyData
1485  convertPointCloudToVTKPolyData (geometry_handler, polydata, initcells);
1486  // use the given geometry handler
1487 
1488  // Get the colors from the handler
1489  bool has_colors = false;
1490  double minmax[2];
1491  if (auto scalars = color_handler.getColor ())
1492  {
1493  polydata->GetPointData ()->SetScalars (scalars);
1494  scalars->GetRange (minmax);
1495  has_colors = true;
1496  }
1497 
1498  // Create an Actor
1500  createActorFromVTKDataSet (polydata, actor);
1501  if (has_colors)
1502  actor->GetMapper ()->SetScalarRange (minmax);
1503 
1504  // Add it to all renderers
1505  addActorToRenderer (actor, viewport);
1506 
1507  // Save the pointer/ID pair to the global actor map
1508  CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1509  cloud_actor.actor = actor;
1510  cloud_actor.cells = initcells;
1511  cloud_actor.geometry_handlers.push_back (geometry_handler);
1512 
1513  // Save the viewpoint transformation matrix to the global actor map
1515  convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1516  cloud_actor.viewpoint_transformation_ = transformation;
1517  cloud_actor.actor->SetUserMatrix (transformation);
1518  cloud_actor.actor->Modified ();
1519 
1520  return (true);
1521 }
1522 
1523 //////////////////////////////////////////////////////////////////////////////////////////////
1524 template <typename PointT> bool
1526  const std::string &id)
1527 {
1528  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1529  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1530 
1531  if (am_it == cloud_actor_map_->end ())
1532  return (false);
1533 
1534  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1535  if (!polydata)
1536  return false;
1537  // Convert the PointCloud to VTK PolyData
1538  convertPointCloudToVTKPolyData<PointT> (cloud, polydata, am_it->second.cells);
1539 
1540  // Set scalars to blank, since there is no way we can update them here.
1542  polydata->GetPointData ()->SetScalars (scalars);
1543  double minmax[2];
1544  minmax[0] = std::numeric_limits<double>::min ();
1545  minmax[1] = std::numeric_limits<double>::max ();
1546 #if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
1547  am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
1548 #endif
1549  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1550 
1551  // Update the mapper
1552  reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1553  return (true);
1554 }
1555 
1556 /////////////////////////////////////////////////////////////////////////////////////////////
1557 template <typename PointT> bool
1559  const PointCloudGeometryHandler<PointT> &geometry_handler,
1560  const std::string &id)
1561 {
1562  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1563  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1564 
1565  if (am_it == cloud_actor_map_->end ())
1566  return (false);
1567 
1568  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1569  if (!polydata)
1570  return (false);
1571  // Convert the PointCloud to VTK PolyData
1572  convertPointCloudToVTKPolyData (geometry_handler, polydata, am_it->second.cells);
1573 
1574  // Set scalars to blank, since there is no way we can update them here.
1576  polydata->GetPointData ()->SetScalars (scalars);
1577  double minmax[2];
1578  minmax[0] = std::numeric_limits<double>::min ();
1579  minmax[1] = std::numeric_limits<double>::max ();
1580 #if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
1581  am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
1582 #endif
1583  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1584 
1585  // Update the mapper
1586  reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1587  return (true);
1588 }
1589 
1590 
1591 /////////////////////////////////////////////////////////////////////////////////////////////
1592 template <typename PointT> bool
1594  const PointCloudColorHandler<PointT> &color_handler,
1595  const std::string &id)
1596 {
1597  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1598  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1599 
1600  if (am_it == cloud_actor_map_->end ())
1601  return (false);
1602 
1603  // Get the current poly data
1604  vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1605  if (!polydata)
1606  return (false);
1607 
1608  convertPointCloudToVTKPolyData<PointT>(cloud, polydata, am_it->second.cells);
1609 
1610  // Get the colors from the handler
1611  bool has_colors = false;
1612  double minmax[2];
1613  if (auto scalars = color_handler.getColor ())
1614  {
1615  // Update the data
1616  polydata->GetPointData ()->SetScalars (scalars);
1617  scalars->GetRange (minmax);
1618  has_colors = true;
1619  }
1620 
1621 #if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
1622  am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
1623 #endif
1624 
1625  if (has_colors)
1626  am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1627 
1628  // Update the mapper
1629  reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1630  return (true);
1631 }
1632 
1633 /////////////////////////////////////////////////////////////////////////////////////////////
1634 template <typename PointT> bool
1636  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1637  const std::vector<pcl::Vertices> &vertices,
1638  const std::string &id,
1639  int viewport)
1640 {
1641  if (vertices.empty () || cloud->points.empty ())
1642  return (false);
1643 
1644  if (contains (id))
1645  {
1646  PCL_WARN ("[addPolygonMesh] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1647  return (false);
1648  }
1649 
1650  int rgb_idx = -1;
1651  std::vector<pcl::PCLPointField> fields;
1653  rgb_idx = pcl::getFieldIndex<PointT> ("rgb", fields);
1654  if (rgb_idx == -1)
1655  rgb_idx = pcl::getFieldIndex<PointT> ("rgba", fields);
1656  if (rgb_idx != -1)
1657  {
1659  colors->SetNumberOfComponents (3);
1660  colors->SetName ("Colors");
1661  std::uint32_t offset = fields[rgb_idx].offset;
1662  for (std::size_t i = 0; i < cloud->size (); ++i)
1663  {
1664  if (!isFinite ((*cloud)[i]))
1665  continue;
1666  const pcl::RGB* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
1667  unsigned char color[3];
1668  color[0] = rgb_data->r;
1669  color[1] = rgb_data->g;
1670  color[2] = rgb_data->b;
1671  colors->InsertNextTupleValue (color);
1672  }
1673  }
1674 
1675  // Create points from polyMesh.cloud
1677  vtkIdType nr_points = cloud->size ();
1678  points->SetNumberOfPoints (nr_points);
1680 
1681  // Get a pointer to the beginning of the data array
1682  float *data = static_cast<vtkFloatArray*> (points->GetData ())->GetPointer (0);
1683 
1684  vtkIdType ptr = 0;
1685  std::vector<int> lookup;
1686  // If the dataset is dense (no NaNs)
1687  if (cloud->is_dense)
1688  {
1689  for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
1690  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1691  }
1692  else
1693  {
1694  lookup.resize (nr_points);
1695  vtkIdType j = 0; // true point index
1696  for (vtkIdType i = 0; i < nr_points; ++i)
1697  {
1698  // Check if the point is invalid
1699  if (!isFinite ((*cloud)[i]))
1700  continue;
1701 
1702  lookup[i] = static_cast<int> (j);
1703  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1704  j++;
1705  ptr += 3;
1706  }
1707  nr_points = j;
1708  points->SetNumberOfPoints (nr_points);
1709  }
1710 
1711  // Get the maximum size of a polygon
1712  int max_size_of_polygon = -1;
1713  for (const auto &vertex : vertices)
1714  if (max_size_of_polygon < static_cast<int> (vertex.vertices.size ()))
1715  max_size_of_polygon = static_cast<int> (vertex.vertices.size ());
1716 
1717  if (vertices.size () > 1)
1718  {
1719  // Create polys from polyMesh.polygons
1721 
1722  const auto idx = details::fillCells(lookup,vertices,cell_array, max_size_of_polygon);
1723 
1725  allocVtkPolyData (polydata);
1726  cell_array->GetData ()->SetNumberOfValues (idx);
1727  cell_array->Squeeze ();
1728  polydata->SetPolys (cell_array);
1729  polydata->SetPoints (points);
1730 
1731  if (colors)
1732  polydata->GetPointData ()->SetScalars (colors);
1733 
1734  createActorFromVTKDataSet (polydata, actor, false);
1735  }
1736  else
1737  {
1739  std::size_t n_points = vertices[0].vertices.size ();
1740  polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
1741 
1742  if (!lookup.empty ())
1743  {
1744  for (std::size_t j = 0; j < (n_points - 1); ++j)
1745  polygon->GetPointIds ()->SetId (j, lookup[vertices[0].vertices[j]]);
1746  }
1747  else
1748  {
1749  for (std::size_t j = 0; j < (n_points - 1); ++j)
1750  polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
1751  }
1753  allocVtkUnstructuredGrid (poly_grid);
1754  poly_grid->Allocate (1, 1);
1755  poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
1756  poly_grid->SetPoints (points);
1757  if (colors)
1758  poly_grid->GetPointData ()->SetScalars (colors);
1759 
1760  createActorFromVTKDataSet (poly_grid, actor, false);
1761  }
1762  addActorToRenderer (actor, viewport);
1763  actor->GetProperty ()->SetRepresentationToSurface ();
1764  // Backface culling renders the visualization slower, but guarantees that we see all triangles
1765  actor->GetProperty ()->BackfaceCullingOff ();
1766  actor->GetProperty ()->SetInterpolationToFlat ();
1767  actor->GetProperty ()->EdgeVisibilityOff ();
1768  actor->GetProperty ()->ShadingOff ();
1769 
1770  // Save the pointer/ID pair to the global actor map
1771  (*cloud_actor_map_)[id].actor = actor;
1772 
1773  // Save the viewpoint transformation matrix to the global actor map
1775  convertToVtkMatrix (cloud->sensor_origin_, cloud->sensor_orientation_, transformation);
1776  (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
1777 
1778  return (true);
1779 }
1780 
1781 /////////////////////////////////////////////////////////////////////////////////////////////
1782 template <typename PointT> bool
1784  const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1785  const std::vector<pcl::Vertices> &verts,
1786  const std::string &id)
1787 {
1788  if (verts.empty ())
1789  {
1790  pcl::console::print_error ("[addPolygonMesh] No vertices given!\n");
1791  return (false);
1792  }
1793 
1794  // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1795  CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
1796  if (am_it == cloud_actor_map_->end ())
1797  return (false);
1798 
1799  // Get the current poly data
1800  vtkSmartPointer<vtkPolyData> polydata = static_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1801  if (!polydata)
1802  return (false);
1803  vtkSmartPointer<vtkCellArray> cells = polydata->GetPolys ();
1804  if (!cells)
1805  return (false);
1806  vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
1807  // Copy the new point array in
1808  vtkIdType nr_points = cloud->size ();
1809  points->SetNumberOfPoints (nr_points);
1810 
1811  // Get a pointer to the beginning of the data array
1812  float *data = (static_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
1813 
1814  int ptr = 0;
1815  std::vector<int> lookup;
1816  // If the dataset is dense (no NaNs)
1817  if (cloud->is_dense)
1818  {
1819  for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
1820  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1821  }
1822  else
1823  {
1824  lookup.resize (nr_points);
1825  vtkIdType j = 0; // true point index
1826  for (vtkIdType i = 0; i < nr_points; ++i)
1827  {
1828  // Check if the point is invalid
1829  if (!isFinite ((*cloud)[i]))
1830  continue;
1831 
1832  lookup [i] = static_cast<int> (j);
1833  std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1834  j++;
1835  ptr += 3;
1836  }
1837  nr_points = j;
1838  points->SetNumberOfPoints (nr_points);
1839  }
1840 
1841  // Update colors
1842  vtkUnsignedCharArray* colors = vtkUnsignedCharArray::SafeDownCast (polydata->GetPointData ()->GetScalars ());
1843  if (!colors)
1844  return (false);
1845  int rgb_idx = -1;
1846  std::vector<pcl::PCLPointField> fields;
1847  rgb_idx = pcl::getFieldIndex<PointT> ("rgb", fields);
1848  if (rgb_idx == -1)
1849  rgb_idx = pcl::getFieldIndex<PointT> ("rgba", fields);
1850  if (rgb_idx != -1 && colors)
1851  {
1852  int j = 0;
1853  std::uint32_t offset = fields[rgb_idx].offset;
1854  for (std::size_t i = 0; i < cloud->size (); ++i)
1855  {
1856  if (!isFinite ((*cloud)[i]))
1857  continue;
1858  const pcl::RGB* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
1859  unsigned char color[3];
1860  color[0] = rgb_data->r;
1861  color[1] = rgb_data->g;
1862  color[2] = rgb_data->b;
1863  colors->SetTupleValue (j++, color);
1864  }
1865  }
1866 
1867  // Get the maximum size of a polygon
1868  int max_size_of_polygon = -1;
1869  for (const auto &vertex : verts)
1870  if (max_size_of_polygon < static_cast<int> (vertex.vertices.size ()))
1871  max_size_of_polygon = static_cast<int> (vertex.vertices.size ());
1872 
1873  // Update the cells
1875 
1876  const auto idx = details::fillCells(lookup, verts, cells, max_size_of_polygon);
1877 
1878  cells->GetData ()->SetNumberOfValues (idx);
1879  cells->Squeeze ();
1880  // Set the the vertices
1881  polydata->SetPolys (cells);
1882 
1883  return (true);
1884 }
1885 
1886 #ifdef vtkGenericDataArray_h
1887 #undef SetTupleValue
1888 #undef InsertNextTupleValue
1889 #undef GetTupleValue
1890 #endif
1891 
1892 #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.