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