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