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