38#ifndef PCL_PCL_VISUALIZER_IMPL_H_
39#define PCL_PCL_VISUALIZER_IMPL_H_
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>
49#include <vtkSphereSource.h>
50#include <vtkProperty2D.h>
51#include <vtkDataSetSurfaceFilter.h>
52#include <vtkPointData.h>
53#include <vtkPolyDataMapper.h>
54#include <vtkProperty.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>
65#include <pcl/common/utils.h>
69#ifdef vtkGenericDataArray_h
70#define SetTupleValue SetTypedTuple
71#define InsertNextTupleValue InsertNextTypedTuple
72#define GetTupleValue GetTypedTuple
76template <
typename Po
intT>
bool
79 const std::string &
id,
int viewport)
83 return (addPointCloud<PointT> (cloud, geometry_handler,
id, viewport));
87template <
typename Po
intT>
bool
91 const std::string &
id,
int viewport)
95 PCL_WARN (
"[addPointCloud] The id <%s> already exists! Please choose a different id and retry.\n",
id.c_str ());
109template <
typename Po
intT>
bool
113 const std::string &
id,
int viewport)
119 auto am_it = cloud_actor_map_->find (
id);
120 am_it->second.geometry_handlers.push_back (geometry_handler);
130template <
typename Po
intT>
bool
134 const std::string &
id,
int viewport)
138 PCL_WARN (
"[addPointCloud] The id <%s> already exists! Please choose a different id and retry.\n",
id.c_str ());
152template <
typename Po
intT>
bool
156 const std::string &
id,
int viewport)
159 auto am_it = cloud_actor_map_->find (
id);
160 if (am_it != cloud_actor_map_->end ())
164 am_it->second.color_handlers.push_back (color_handler);
173template <
typename Po
intT>
bool
178 const std::string &
id,
int viewport)
181 auto am_it = cloud_actor_map_->find (
id);
182 if (am_it != cloud_actor_map_->end ())
186 am_it->second.geometry_handlers.push_back (geometry_handler);
187 am_it->second.color_handlers.push_back (color_handler);
194template <
typename Po
intT>
bool
199 const std::string &
id,
int viewport)
203 PCL_WARN (
"[addPointCloud] The id <%s> already exists! Please choose a different id and retry.\n",
id.c_str ());
215template <
typename Po
intT>
void
216pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData (
224 allocVtkPolyData (polydata);
226 polydata->SetVerts (vertices);
230#ifndef VTK_CELL_ARRAY_V2
231 vertices = polydata->GetVerts ();
236 vtkIdType nr_points = cloud->
size ();
242 points->SetDataTypeToFloat ();
243 polydata->SetPoints (points);
245 points->SetNumberOfPoints (nr_points);
248 float *data = (
dynamic_cast<vtkFloatArray*
> (points->GetData ()))->GetPointer (0);
254 for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3) {
255 std::copy(&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
261 for (vtkIdType i = 0; i < nr_points; ++i)
267 std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
272 points->SetNumberOfPoints (nr_points);
275#ifdef VTK_CELL_ARRAY_V2
279 auto numOfCells = vertices->GetNumberOfCells();
282 if (numOfCells < nr_points)
284 for (
int i = numOfCells; i < nr_points; i++)
286 vertices->InsertNextCell(1);
287 vertices->InsertCellPoint(i);
291 else if (numOfCells > nr_points)
293 vertices->ResizeExact(nr_points, nr_points);
296 polydata->SetPoints(points);
297 polydata->SetVerts(vertices);
301 updateCells (cells, initcells, nr_points);
304 vertices->SetCells (nr_points, cells);
307 vertices->SetNumberOfCells(nr_points);
312template <
typename Po
intT>
void
313pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData (
321 allocVtkPolyData (polydata);
323 polydata->SetVerts (vertices);
329 polydata->SetPoints (points);
331 vtkIdType nr_points = points->GetNumberOfPoints ();
334#ifndef VTK_CELL_ARRAY_V2
335 vertices = polydata->GetVerts ();
340#ifdef VTK_CELL_ARRAY_V2
344 auto numOfCells = vertices->GetNumberOfCells();
347 if (numOfCells < nr_points)
349 for (
int i = numOfCells; i < nr_points; i++)
351 vertices->InsertNextCell(1);
352 vertices->InsertCellPoint(i);
356 else if (numOfCells > nr_points)
358 vertices->ResizeExact(nr_points, nr_points);
361 polydata->SetPoints(points);
362 polydata->SetVerts(vertices);
366 updateCells (cells, initcells, nr_points);
368 vertices->SetCells (nr_points, cells);
373template <
typename Po
intT>
bool
376 double r,
double g,
double b,
const std::string &
id,
int viewport)
383 auto am_it = shape_actor_map_->find (
id);
384 if (am_it != shape_actor_map_->end ())
389 all_data->AddInputData (
reinterpret_cast<vtkPolyDataMapper*
> ((vtkActor::SafeDownCast (am_it->second))->GetMapper ())->GetInput ());
393 surface_filter->AddInputData (vtkUnstructuredGrid::SafeDownCast (data));
395 all_data->AddInputData (poly_data);
399 createActorFromVTKDataSet (all_data->GetOutput (), actor);
400 actor->GetProperty ()->SetRepresentationToWireframe ();
401 actor->GetProperty ()->SetColor (r, g, b);
402 actor->GetMapper ()->ScalarVisibilityOff ();
403 removeActorFromRenderer (am_it->second, viewport);
404 addActorToRenderer (actor, viewport);
407 (*shape_actor_map_)[id] = actor;
413 createActorFromVTKDataSet (data, actor);
414 actor->GetProperty ()->SetRepresentationToWireframe ();
415 actor->GetProperty ()->SetColor (r, g, b);
416 actor->GetMapper ()->ScalarVisibilityOff ();
417 addActorToRenderer (actor, viewport);
420 (*shape_actor_map_)[id] = actor;
427template <
typename Po
intT>
bool
430 double r,
double g,
double b,
const std::string &
id,
int viewport)
437 auto am_it = shape_actor_map_->find (
id);
438 if (am_it != shape_actor_map_->end ())
443 all_data->AddInputData (
reinterpret_cast<vtkPolyDataMapper*
> ((vtkActor::SafeDownCast (am_it->second))->GetMapper ())->GetInput ());
447 surface_filter->SetInputData (vtkUnstructuredGrid::SafeDownCast (data));
449 all_data->AddInputData (poly_data);
453 createActorFromVTKDataSet (all_data->GetOutput (), actor);
454 actor->GetProperty ()->SetRepresentationToWireframe ();
455 actor->GetProperty ()->SetColor (r, g, b);
456 actor->GetMapper ()->ScalarVisibilityOn ();
457 actor->GetProperty ()->BackfaceCullingOff ();
458 removeActorFromRenderer (am_it->second, viewport);
459 addActorToRenderer (actor, viewport);
462 (*shape_actor_map_)[id] = actor;
468 createActorFromVTKDataSet (data, actor);
469 actor->GetProperty ()->SetRepresentationToWireframe ();
470 actor->GetProperty ()->SetColor (r, g, b);
471 actor->GetMapper ()->ScalarVisibilityOn ();
472 actor->GetProperty ()->BackfaceCullingOff ();
473 addActorToRenderer (actor, viewport);
476 (*shape_actor_map_)[id] = actor;
482template <
typename Po
intT>
bool
485 const std::string &
id,
int viewport)
487 return (addPolygon<PointT> (cloud, 0.5, 0.5, 0.5,
id, viewport));
491template <
typename P1,
typename P2>
bool
496 PCL_WARN (
"[addLine] The id <%s> already exists! Please choose a different id and retry.\n",
id.c_str ());
504 createActorFromVTKDataSet (data, actor);
505 actor->GetProperty ()->SetRepresentationToWireframe ();
506 actor->GetProperty ()->SetColor (r, g, b);
507 actor->GetMapper ()->ScalarVisibilityOff ();
508 addActorToRenderer (actor, viewport);
511 (*shape_actor_map_)[id] = actor;
516template <
typename P1,
typename P2>
bool
521 PCL_WARN (
"[addArrow] The id <%s> already exists! Please choose a different id and retry.\n",
id.c_str ());
527 leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
528 leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
529 leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
530 leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
531 leader->SetArrowStyleToFilled ();
532 leader->AutoLabelOn ();
534 leader->GetProperty ()->SetColor (r, g, b);
535 addActorToRenderer (leader, viewport);
538 (*shape_actor_map_)[id] = leader;
543template <
typename P1,
typename P2>
bool
548 PCL_WARN (
"[addArrow] The id <%s> already exists! Please choose a different id and retry.\n",
id.c_str ());
554 leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
555 leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
556 leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
557 leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
558 leader->SetArrowStyleToFilled ();
559 leader->SetArrowPlacementToPoint1 ();
561 leader->AutoLabelOn ();
563 leader->AutoLabelOff ();
565 leader->GetProperty ()->SetColor (r, g, b);
566 addActorToRenderer (leader, viewport);
569 (*shape_actor_map_)[id] = leader;
573template <
typename P1,
typename P2>
bool
575 double r_line,
double g_line,
double b_line,
576 double r_text,
double g_text,
double b_text,
577 const std::string &
id,
int viewport)
581 PCL_WARN (
"[addArrow] The id <%s> already exists! Please choose a different id and retry.\n",
id.c_str ());
587 leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
588 leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
589 leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
590 leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
591 leader->SetArrowStyleToFilled ();
592 leader->AutoLabelOn ();
594 leader->GetLabelTextProperty()->SetColor(r_text, g_text, b_text);
596 leader->GetProperty ()->SetColor (r_line, g_line, b_line);
597 addActorToRenderer (leader, viewport);
600 (*shape_actor_map_)[id] = leader;
605template <
typename P1,
typename P2>
bool
608 return (addLine (pt1, pt2, 0.5, 0.5, 0.5,
id, viewport));
612template <
typename Po
intT>
bool
617 PCL_WARN (
"[addSphere] The id <%s> already exists! Please choose a different id and retry.\n",
id.c_str ());
622 data->SetRadius (radius);
623 data->SetCenter (
static_cast<double>(center.x),
static_cast<double>(center.y),
static_cast<double>(center.z));
624 data->SetPhiResolution (10);
625 data->SetThetaResolution (10);
626 data->LatLongTessellationOff ();
631 mapper->SetInputConnection (data->GetOutputPort ());
635 actor->SetMapper (mapper);
637 actor->GetProperty ()->SetRepresentationToSurface ();
638 actor->GetProperty ()->SetInterpolationToFlat ();
639 actor->GetProperty ()->SetColor (r, g, b);
640 actor->GetMapper ()->StaticOn ();
641 actor->GetMapper ()->ScalarVisibilityOff ();
642 actor->GetMapper ()->Update ();
643 addActorToRenderer (actor, viewport);
646 (*shape_actor_map_)[id] = actor;
651template <
typename Po
intT>
bool
654 return (addSphere (center, radius, 0.5, 0.5, 0.5,
id, viewport));
658template<
typename Po
intT>
bool
668 auto am_it = shape_actor_map_->find (
id);
669 vtkLODActor* actor = vtkLODActor::SafeDownCast (am_it->second);
672 vtkAlgorithm *algo = actor->GetMapper ()->GetInputAlgorithm ();
673 vtkSphereSource *src = vtkSphereSource::SafeDownCast (algo);
677 src->SetCenter (
double (center.x), double (center.y), double (center.z));
678 src->SetRadius (radius);
680 actor->GetProperty ()->SetColor (r, g, b);
687template <
typename Po
intT>
bool
689 const std::string &text,
695 const std::string &
id,
708 if (rens_->GetNumberOfItems () <= viewport)
710 PCL_ERROR (
"[addText3D] The viewport [%d] doesn't exist (id <%s>)! \n",
717 rens_->InitTraversal ();
718 for (std::size_t i = viewport; rens_->GetNextItem (); ++i)
720 const std::string uid = tid + std::string (i,
'*');
723 PCL_ERROR (
"[addText3D] The id <%s> already exists in viewport [%d]! \n"
724 "Please choose a different id and retry.\n",
735 textSource->SetText (text.c_str());
736 textSource->Update ();
739 textMapper->SetInputConnection (textSource->GetOutputPort ());
742 rens_->InitTraversal ();
743 vtkRenderer* renderer;
745 while ((renderer = rens_->GetNextItem ()))
748 if (viewport == 0 || viewport == i)
751 textActor->SetMapper (textMapper);
752 textActor->SetPosition (position.x, position.y, position.z);
753 textActor->SetScale (textScale);
754 textActor->GetProperty ()->SetColor (r, g, b);
755 textActor->SetCamera (renderer->GetActiveCamera ());
757 renderer->AddActor (textActor);
761 const std::string uid = tid + std::string (i,
'*');
762 (*shape_actor_map_)[uid] = textActor;
772template <
typename Po
intT>
bool
774 const std::string &text,
776 double orientation[3],
781 const std::string &
id,
794 if (rens_->GetNumberOfItems () <= viewport)
796 PCL_ERROR (
"[addText3D] The viewport [%d] doesn't exist (id <%s>)!\n",
803 rens_->InitTraversal ();
804 for (std::size_t i = viewport; rens_->GetNextItem (); ++i)
806 const std::string uid = tid + std::string (i,
'*');
809 PCL_ERROR (
"[addText3D] The id <%s> already exists in viewport [%d]! "
810 "Please choose a different id and retry.\n",
821 textSource->SetText (text.c_str());
822 textSource->Update ();
825 textMapper->SetInputConnection (textSource->GetOutputPort ());
828 textActor->SetMapper (textMapper);
829 textActor->SetPosition (position.x, position.y, position.z);
830 textActor->SetScale (textScale);
831 textActor->GetProperty ()->SetColor (r, g, b);
832 textActor->SetOrientation (orientation);
835 rens_->InitTraversal ();
837 for ( vtkRenderer* renderer = rens_->GetNextItem ();
839 renderer = rens_->GetNextItem (), ++i)
841 if (viewport == 0 || viewport == i)
843 renderer->AddActor (textActor);
844 const std::string uid = tid + std::string (i,
'*');
845 (*shape_actor_map_)[uid] = textActor;
853template <
typename Po
intNT>
bool
856 int level,
float scale,
const std::string &
id,
int viewport)
858 return (addPointCloudNormals<PointNT, PointNT> (cloud, cloud, level, scale,
id, viewport));
862template <
typename Po
intT,
typename Po
intNT>
bool
866 int level,
float scale,
867 const std::string &
id,
int viewport)
869 if (normals->
size () != cloud->
size ())
871 PCL_ERROR (
"[addPointCloudNormals] The number of points differs from the number of normals!\n");
875 if (normals->
empty ())
877 PCL_WARN (
"[addPointCloudNormals] An empty normal cloud is given! Nothing to display.\n");
883 PCL_WARN (
"[addPointCloudNormals] The id <%s> already exists! Please choose a different id and retry.\n",
id.c_str ());
890 points->SetDataTypeToFloat ();
892 data->SetNumberOfComponents (3);
895 vtkIdType nr_normals = 0;
896 float* pts =
nullptr;
901 auto point_step =
static_cast<vtkIdType
> (sqrt (
static_cast<double>(level)));
902 nr_normals = (
static_cast<vtkIdType
> ((cloud->
width - 1)/ point_step) + 1) *
903 (
static_cast<vtkIdType
> ((cloud->
height - 1) / point_step) + 1);
904 pts =
new float[2 * nr_normals * 3];
906 vtkIdType cell_count = 0;
907 for (vtkIdType y = 0; y < normals->
height; y += point_step)
908 for (vtkIdType x = 0; x < normals->
width; x += point_step)
910 PointT p = (*cloud)(x, y);
913 p.x += (*normals)(x, y).normal[0] * scale;
914 p.y += (*normals)(x, y).normal[1] * scale;
915 p.z += (*normals)(x, y).normal[2] * scale;
917 pts[2 * cell_count * 3 + 0] = (*cloud)(x, y).x;
918 pts[2 * cell_count * 3 + 1] = (*cloud)(x, y).y;
919 pts[2 * cell_count * 3 + 2] = (*cloud)(x, y).z;
920 pts[2 * cell_count * 3 + 3] = p.x;
921 pts[2 * cell_count * 3 + 4] = p.y;
922 pts[2 * cell_count * 3 + 5] = p.z;
924 lines->InsertNextCell (2);
925 lines->InsertCellPoint (2 * cell_count);
926 lines->InsertCellPoint (2 * cell_count + 1);
929 nr_normals = cell_count;
933 nr_normals = (cloud->
size () - 1) / level + 1 ;
934 pts =
new float[2 * nr_normals * 3];
937 for (vtkIdType i = 0; (j < nr_normals) && (i < static_cast<vtkIdType>(cloud->
size())); i += level)
942 p.x += (*normals)[i].normal[0] * scale;
943 p.y += (*normals)[i].normal[1] * scale;
944 p.z += (*normals)[i].normal[2] * scale;
946 pts[2 * j * 3 + 0] = (*cloud)[i].x;
947 pts[2 * j * 3 + 1] = (*cloud)[i].y;
948 pts[2 * j * 3 + 2] = (*cloud)[i].z;
949 pts[2 * j * 3 + 3] = p.x;
950 pts[2 * j * 3 + 4] = p.y;
951 pts[2 * j * 3 + 5] = p.z;
953 lines->InsertNextCell (2);
954 lines->InsertCellPoint (2 * j);
955 lines->InsertCellPoint (2 * j + 1);
961 data->SetArray (&pts[0], 2 * nr_normals * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
962 points->SetData (data);
965 polyData->SetPoints (points);
966 polyData->SetLines (lines);
969 mapper->SetInputData (polyData);
970 mapper->SetColorModeToMapScalars();
971 mapper->SetScalarModeToUsePointData();
975 actor->SetMapper (mapper);
980 actor->SetUserMatrix (transformation);
983 addActorToRenderer (actor, viewport);
986 (*cloud_actor_map_)[id].actor = actor;
991template <
typename Po
intNT>
bool
995 int level,
float scale,
996 const std::string &
id,
int viewport)
998 return (addPointCloudPrincipalCurvatures<PointNT, PointNT> (cloud, cloud, pcs, level, scale,
id, viewport));
1002template <
typename Po
intT,
typename Po
intNT>
bool
1007 int level,
float scale,
1008 const std::string &
id,
int viewport)
1012 pcl::console::print_error (
"[addPointCloudPrincipalCurvatures] The number of points differs from the number of principal curvatures/normals!\n");
1018 PCL_WARN (
"[addPointCloudPrincipalCurvatures] The id <%s> already exists! Please choose a different id and retry.\n",
id.c_str ());
1026 unsigned char green[3] = {0, 255, 0};
1027 unsigned char blue[3] = {0, 0, 255};
1031 line_1_colors->SetNumberOfComponents (3);
1032 line_1_colors->SetName (
"Colors");
1034 line_2_colors->SetNumberOfComponents (3);
1035 line_2_colors->SetName (
"Colors");
1038 for (std::size_t i = 0; i < cloud->
size (); i+=level)
1041 p.x += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[0]) * scale;
1042 p.y += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[1]) * scale;
1043 p.z += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[2]) * scale;
1046 line_1->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1047 line_1->SetPoint2 (p.x, p.y, p.z);
1049 polydata_1->AddInputData (line_1->GetOutput ());
1050 line_1_colors->InsertNextTupleValue (green);
1052 polydata_1->Update ();
1054 line_1_data->GetCellData ()->SetScalars (line_1_colors);
1057 for (std::size_t i = 0; i < cloud->
size (); i += level)
1059 Eigen::Vector3f pc ((*pcs)[i].principal_curvature[0],
1060 (*pcs)[i].principal_curvature[1],
1061 (*pcs)[i].principal_curvature[2]);
1062 Eigen::Vector3f normal ((*normals)[i].normal[0],
1063 (*normals)[i].normal[1],
1064 (*normals)[i].normal[2]);
1065 Eigen::Vector3f pc_c = pc.cross (normal);
1068 p.x += ((*pcs)[i].pc2 * pc_c[0]) * scale;
1069 p.y += ((*pcs)[i].pc2 * pc_c[1]) * scale;
1070 p.z += ((*pcs)[i].pc2 * pc_c[2]) * scale;
1073 line_2->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1074 line_2->SetPoint2 (p.x, p.y, p.z);
1076 polydata_2->AddInputData (line_2->GetOutput ());
1078 line_2_colors->InsertNextTupleValue (blue);
1080 polydata_2->Update ();
1082 line_2_data->GetCellData ()->SetScalars (line_2_colors);
1086 alldata->AddInputData (line_1_data);
1087 alldata->AddInputData (line_2_data);
1092 createActorFromVTKDataSet (alldata->GetOutput (), actor);
1093 actor->GetMapper ()->SetScalarModeToUseCellData ();
1096 addActorToRenderer (actor, viewport);
1101 (*cloud_actor_map_)[id] = act;
1106template <
typename Po
intT,
typename GradientT>
bool
1110 int level,
double scale,
1111 const std::string &
id,
int viewport)
1113 if (gradients->
size () != cloud->
size ())
1115 PCL_ERROR (
"[addPointCloudGradients] The number of points differs from the number of gradients!\n");
1120 PCL_WARN (
"[addPointCloudGradients] The id <%s> already exists! Please choose a different id and retry.\n",
id.c_str ());
1127 points->SetDataTypeToFloat ();
1129 data->SetNumberOfComponents (3);
1131 vtkIdType nr_gradients = (cloud->
size () - 1) / level + 1 ;
1132 float* pts =
new float[2 * nr_gradients * 3];
1134 for (vtkIdType i = 0, j = 0; j < nr_gradients; j++, i = j * level)
1137 p.x += (*gradients)[i].gradient[0] * scale;
1138 p.y += (*gradients)[i].gradient[1] * scale;
1139 p.z += (*gradients)[i].gradient[2] * scale;
1141 pts[2 * j * 3 + 0] = (*cloud)[i].x;
1142 pts[2 * j * 3 + 1] = (*cloud)[i].y;
1143 pts[2 * j * 3 + 2] = (*cloud)[i].z;
1144 pts[2 * j * 3 + 3] = p.x;
1145 pts[2 * j * 3 + 4] = p.y;
1146 pts[2 * j * 3 + 5] = p.z;
1148 lines->InsertNextCell(2);
1149 lines->InsertCellPoint(2*j);
1150 lines->InsertCellPoint(2*j+1);
1153 data->SetArray (&pts[0], 2 * nr_gradients * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
1154 points->SetData (data);
1157 polyData->SetPoints(points);
1158 polyData->SetLines(lines);
1161 mapper->SetInputData (polyData);
1162 mapper->SetColorModeToMapScalars();
1163 mapper->SetScalarModeToUsePointData();
1167 actor->SetMapper (mapper);
1170 addActorToRenderer (actor, viewport);
1173 (*cloud_actor_map_)[id].actor = actor;
1178template <
typename Po
intT>
bool
1182 const std::vector<int> &correspondences,
1183 const std::string &
id,
1187 corrs.resize (correspondences.size ());
1189 std::size_t index = 0;
1190 for (
auto &corr : corrs)
1192 corr.index_query = index;
1193 corr.index_match = correspondences[index];
1197 return (addCorrespondences<PointT> (source_points, target_points, corrs,
id, viewport));
1201template <
typename Po
intT>
bool
1207 const std::string &
id,
1211 if (correspondences.empty ())
1213 PCL_DEBUG (
"[addCorrespondences] An empty set of correspondences given! Nothing to display.\n");
1218 auto am_it = shape_actor_map_->find (
id);
1219 if (am_it != shape_actor_map_->end () && !overwrite)
1221 PCL_WARN (
"[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n",
id.c_str ());
1224 if (am_it == shape_actor_map_->end () && overwrite)
1229 int n_corr =
static_cast<int>(correspondences.size () / nth);
1234 line_colors->SetNumberOfComponents (3);
1235 line_colors->SetName (
"Colors");
1236 line_colors->SetNumberOfTuples (n_corr);
1240 line_points->SetNumberOfPoints (2 * n_corr);
1243 line_cells_id->SetNumberOfComponents (3);
1244 line_cells_id->SetNumberOfTuples (n_corr);
1245 vtkIdType *line_cell_id = line_cells_id->GetPointer (0);
1249 line_tcoords->SetNumberOfComponents (1);
1250 line_tcoords->SetNumberOfTuples (n_corr * 2);
1251 line_tcoords->SetName (
"Texture Coordinates");
1253 double tc[3] = {0.0, 0.0, 0.0};
1255 Eigen::Affine3f source_transformation;
1257 source_transformation.translation () = source_points->
sensor_origin_.template head<3> ();
1258 Eigen::Affine3f target_transformation;
1260 target_transformation.translation () = target_points->
sensor_origin_.template head<3> ();
1264 for (std::size_t i = 0; i < correspondences.size (); i += nth, ++j)
1266 if (correspondences[i].index_match ==
UNAVAILABLE)
1268 PCL_WARN (
"[addCorrespondences] No valid index_match for correspondence %d\n", i);
1272 PointT p_src ((*source_points)[correspondences[i].index_query]);
1273 PointT p_tgt ((*target_points)[correspondences[i].index_match]);
1275 p_src.getVector3fMap () = source_transformation * p_src.getVector3fMap ();
1276 p_tgt.getVector3fMap () = target_transformation * p_tgt.getVector3fMap ();
1278 int id1 = j * 2 + 0, id2 = j * 2 + 1;
1280 line_points->SetPoint (id1, p_src.x, p_src.y, p_src.z);
1281 line_points->SetPoint (id2, p_tgt.x, p_tgt.y, p_tgt.z);
1283 *line_cell_id++ = 2;
1284 *line_cell_id++ = id1;
1285 *line_cell_id++ = id2;
1287 tc[0] = 0.; line_tcoords->SetTuple (id1, tc);
1288 tc[0] = 1.; line_tcoords->SetTuple (id2, tc);
1291 rgb[0] = vtkMath::Random (32, 255);
1292 rgb[1] = vtkMath::Random (32, 255);
1293 rgb[2] = vtkMath::Random (32, 255);
1294 line_colors->InsertTuple (i, rgb);
1296 line_colors->SetNumberOfTuples (j);
1297 line_cells_id->SetNumberOfTuples (j);
1298 line_cells->SetCells (n_corr, line_cells_id);
1299 line_points->SetNumberOfPoints (j*2);
1300 line_tcoords->SetNumberOfTuples (j*2);
1303 line_data->SetPoints (line_points);
1304 line_data->SetLines (line_cells);
1305 line_data->GetPointData ()->SetTCoords (line_tcoords);
1306 line_data->GetCellData ()->SetScalars (line_colors);
1312 createActorFromVTKDataSet (line_data, actor);
1313 actor->GetProperty ()->SetRepresentationToWireframe ();
1314 actor->GetProperty ()->SetOpacity (0.5);
1315 addActorToRenderer (actor, viewport);
1318 (*shape_actor_map_)[id] = actor;
1326 reinterpret_cast<vtkPolyDataMapper*
> (actor->GetMapper ())->SetInputData (line_data);
1333template <
typename Po
intT>
bool
1339 const std::string &
id,
1342 return (addCorrespondences<PointT> (source_points, target_points, correspondences, nth,
id, viewport,
true));
1346template <
typename Po
intT>
bool
1347pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1350 const std::string &
id,
1352 const Eigen::Vector4f& sensor_origin,
1353 const Eigen::Quaternion<float>& sensor_orientation)
1357 PCL_WARN (
"[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n",
id.c_str (), geometry_handler.
getName ().c_str ());
1363 PCL_WARN (
"[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n",
id.c_str (), color_handler.
getName ().c_str ());
1370 convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1373 bool has_colors =
false;
1375 if (
auto scalars = color_handler.
getColor ())
1377 polydata->GetPointData ()->SetScalars (scalars);
1378 scalars->GetRange (minmax);
1384 createActorFromVTKDataSet (polydata, actor);
1386 actor->GetMapper ()->SetScalarRange (minmax);
1389 addActorToRenderer (actor, viewport);
1392 CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1393 cloud_actor.actor = actor;
1394 cloud_actor.cells = initcells;
1398 convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1399 cloud_actor.viewpoint_transformation_ = transformation;
1400 cloud_actor.actor->SetUserMatrix (transformation);
1401 cloud_actor.actor->Modified ();
1407template <
typename Po
intT>
bool
1408pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1409 const PointCloudGeometryHandler<PointT> &geometry_handler,
1410 const ColorHandlerConstPtr &color_handler,
1411 const std::string &
id,
1413 const Eigen::Vector4f& sensor_origin,
1414 const Eigen::Quaternion<float>& sensor_orientation)
1416 if (!geometry_handler.isCapable ())
1418 PCL_WARN (
"[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n",
id.c_str (), geometry_handler.getName ().c_str ());
1422 if (!color_handler->isCapable ())
1424 PCL_WARN (
"[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n",
id.c_str (), color_handler->getName ().c_str ());
1431 convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1435 bool has_colors =
false;
1437 if (
auto scalars = color_handler->getColor ())
1439 polydata->GetPointData ()->SetScalars (scalars);
1440 scalars->GetRange (minmax);
1446 createActorFromVTKDataSet (polydata, actor);
1448 actor->GetMapper ()->SetScalarRange (minmax);
1451 addActorToRenderer (actor, viewport);
1454 CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1455 cloud_actor.actor = actor;
1456 cloud_actor.cells = initcells;
1457 cloud_actor.color_handlers.push_back (color_handler);
1461 convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1462 cloud_actor.viewpoint_transformation_ = transformation;
1463 cloud_actor.actor->SetUserMatrix (transformation);
1464 cloud_actor.actor->Modified ();
1470template <
typename Po
intT>
bool
1471pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1472 const GeometryHandlerConstPtr &geometry_handler,
1473 const PointCloudColorHandler<PointT> &color_handler,
1474 const std::string &
id,
1476 const Eigen::Vector4f& sensor_origin,
1477 const Eigen::Quaternion<float>& sensor_orientation)
1479 if (!geometry_handler->isCapable ())
1481 PCL_WARN (
"[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n",
id.c_str (), geometry_handler->getName ().c_str ());
1485 if (!color_handler.isCapable ())
1487 PCL_WARN (
"[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n",
id.c_str (), color_handler.getName ().c_str ());
1494 convertPointCloudToVTKPolyData (geometry_handler, polydata, initcells);
1498 bool has_colors =
false;
1500 if (
auto scalars = color_handler.getColor ())
1502 polydata->GetPointData ()->SetScalars (scalars);
1503 scalars->GetRange (minmax);
1509 createActorFromVTKDataSet (polydata, actor);
1511 actor->GetMapper ()->SetScalarRange (minmax);
1514 addActorToRenderer (actor, viewport);
1517 CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1518 cloud_actor.actor = actor;
1519 cloud_actor.cells = initcells;
1520 cloud_actor.geometry_handlers.push_back (geometry_handler);
1524 convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1525 cloud_actor.viewpoint_transformation_ = transformation;
1526 cloud_actor.actor->SetUserMatrix (transformation);
1527 cloud_actor.actor->Modified ();
1533template <
typename Po
intT>
bool
1535 const std::string &
id)
1538 auto am_it = cloud_actor_map_->find (
id);
1540 if (am_it == cloud_actor_map_->end ())
1547 convertPointCloudToVTKPolyData<PointT> (cloud, polydata, am_it->second.cells);
1551 polydata->GetPointData ()->SetScalars (scalars);
1553 minmax[0] = std::numeric_limits<double>::min ();
1554 minmax[1] = std::numeric_limits<double>::max ();
1555 am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1558 reinterpret_cast<vtkPolyDataMapper*
> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1563template <
typename Po
intT>
bool
1566 const std::string &
id)
1569 auto am_it = cloud_actor_map_->find (
id);
1571 if (am_it == cloud_actor_map_->end ())
1578 convertPointCloudToVTKPolyData (geometry_handler, polydata, am_it->second.cells);
1582 polydata->GetPointData ()->SetScalars (scalars);
1584 minmax[0] = std::numeric_limits<double>::min ();
1585 minmax[1] = std::numeric_limits<double>::max ();
1586 am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1589 reinterpret_cast<vtkPolyDataMapper*
> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1595template <
typename Po
intT>
bool
1598 const std::string &
id)
1601 auto am_it = cloud_actor_map_->find (
id);
1603 if (am_it == cloud_actor_map_->end ())
1611 convertPointCloudToVTKPolyData<PointT>(cloud, polydata, am_it->second.cells);
1614 bool has_colors =
false;
1616 if (
auto scalars = color_handler.
getColor ())
1619 polydata->GetPointData ()->SetScalars (scalars);
1620 scalars->GetRange (minmax);
1625 am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1628 reinterpret_cast<vtkPolyDataMapper*
> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1633template <
typename Po
intT>
bool
1636 const std::vector<pcl::Vertices> &vertices,
1637 const std::string &
id,
1640 if (vertices.empty () || cloud->
points.empty ())
1645 PCL_WARN (
"[addPolygonMesh] The id <%s> already exists! Please choose a different id and retry.\n",
id.c_str ());
1650 std::vector<pcl::PCLPointField> fields;
1652 rgb_idx = pcl::getFieldIndex<PointT> (
"rgb", fields);
1654 rgb_idx = pcl::getFieldIndex<PointT> (
"rgba", fields);
1658 colors->SetNumberOfComponents (3);
1659 colors->SetName (
"Colors");
1660 std::uint32_t offset = fields[rgb_idx].offset;
1661 for (std::size_t i = 0; i < cloud->
size (); ++i)
1665 const auto*
const rgb_data =
reinterpret_cast<const pcl::RGB*
>(
reinterpret_cast<const char*
> (&(*cloud)[i]) + offset);
1666 unsigned char color[3];
1667 color[0] = rgb_data->r;
1668 color[1] = rgb_data->g;
1669 color[2] = rgb_data->b;
1670 colors->InsertNextTupleValue (color);
1676 vtkIdType nr_points = cloud->
size ();
1677 points->SetNumberOfPoints (nr_points);
1681 float *data =
dynamic_cast<vtkFloatArray*
> (points->GetData ())->GetPointer (0);
1684 std::vector<int> lookup;
1688 for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3) {
1689 std::copy(&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1694 lookup.resize (nr_points);
1696 for (vtkIdType i = 0; i < nr_points; ++i)
1702 lookup[i] =
static_cast<int> (j);
1703 std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1708 points->SetNumberOfPoints (nr_points);
1712 int max_size_of_polygon = -1;
1713 for (
const auto &vertex : vertices)
1714 if (max_size_of_polygon <
static_cast<int> (vertex.vertices.size ()))
1715 max_size_of_polygon =
static_cast<int> (vertex.vertices.size ());
1717 if (vertices.size () > 1)
1722 const auto idx =
details::fillCells(lookup,vertices,cell_array, max_size_of_polygon);
1725 allocVtkPolyData (polydata);
1726 cell_array->GetData ()->SetNumberOfValues (idx);
1727 cell_array->Squeeze ();
1728 polydata->SetPolys (cell_array);
1729 polydata->SetPoints (points);
1732 polydata->GetPointData ()->SetScalars (colors);
1734 createActorFromVTKDataSet (polydata, actor,
false);
1739 std::size_t n_points = vertices[0].vertices.size ();
1740 polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
1742 if (!lookup.empty ())
1744 for (std::size_t j = 0; j < (n_points - 1); ++j)
1745 polygon->GetPointIds ()->SetId (j, lookup[vertices[0].vertices[j]]);
1749 for (std::size_t j = 0; j < (n_points - 1); ++j)
1750 polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
1754 poly_grid->Allocate (1, 1);
1755 poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
1756 poly_grid->SetPoints (points);
1758 poly_grid->GetPointData ()->SetScalars (colors);
1760 createActorFromVTKDataSet (poly_grid, actor,
false);
1762 addActorToRenderer (actor, viewport);
1763 actor->GetProperty ()->SetRepresentationToSurface ();
1765 actor->GetProperty ()->BackfaceCullingOff ();
1766 actor->GetProperty ()->SetInterpolationToFlat ();
1767 actor->GetProperty ()->EdgeVisibilityOff ();
1768 actor->GetProperty ()->ShadingOff ();
1771 (*cloud_actor_map_)[id].actor = actor;
1776 (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
1782template <
typename Po
intT>
bool
1785 const std::vector<pcl::Vertices> &verts,
1786 const std::string &
id)
1795 auto am_it = cloud_actor_map_->find (
id);
1796 if (am_it == cloud_actor_map_->end ())
1808 vtkIdType nr_points = cloud->
size ();
1809 points->SetNumberOfPoints (nr_points);
1812 float *data = (
dynamic_cast<vtkFloatArray*
> (points->GetData ()))->GetPointer (0);
1815 std::vector<int> lookup;
1819 for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
1820 std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1824 lookup.resize (nr_points);
1826 for (vtkIdType i = 0; i < nr_points; ++i)
1832 lookup [i] =
static_cast<int> (j);
1833 std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1838 points->SetNumberOfPoints (nr_points);
1842 vtkUnsignedCharArray* colors = vtkUnsignedCharArray::SafeDownCast (polydata->GetPointData ()->GetScalars ());
1846 std::vector<pcl::PCLPointField> fields;
1847 rgb_idx = pcl::getFieldIndex<PointT> (
"rgb", fields);
1849 rgb_idx = pcl::getFieldIndex<PointT> (
"rgba", fields);
1850 if (rgb_idx != -1 && colors)
1853 std::uint32_t offset = fields[rgb_idx].offset;
1854 for (std::size_t i = 0; i < cloud->
size (); ++i)
1858 const auto*
const rgb_data =
reinterpret_cast<const pcl::RGB*
>(
reinterpret_cast<const char*
> (&(*cloud)[i]) + offset);
1859 unsigned char color[3];
1860 color[0] = rgb_data->r;
1861 color[1] = rgb_data->g;
1862 color[2] = rgb_data->b;
1863 colors->SetTupleValue (j++, color);
1868 int max_size_of_polygon = -1;
1869 for (
const auto &vertex : verts)
1870 if (max_size_of_polygon <
static_cast<int> (vertex.vertices.size ()))
1871 max_size_of_polygon =
static_cast<int> (vertex.vertices.size ());
1878 cells->GetData ()->SetNumberOfValues (idx);
1881 polydata->SetPolys (cells);
1886#ifdef vtkGenericDataArray_h
1888#undef InsertNextTupleValue
PlanarPolygon represents a planar (2D) polygon, potentially in a 3D space.
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields).
Eigen::Quaternionf sensor_orientation_
Sensor acquisition pose (rotation).
std::uint32_t width
The point cloud width (if organized as an image-structure).
bool isOrganized() const
Return whether a dataset is organized (e.g., arranged in a structured grid).
std::uint32_t height
The point cloud height (if organized as an image-structure).
Eigen::Vector4f sensor_origin_
Sensor acquisition pose (origin/translation).
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
shared_ptr< const PointCloud< PointT > > ConstPtr
vtkSmartPointer< vtkLODActor > actor
The actor holding the data to render.
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 ¢er, 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 ¢er, 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.
Handler for predefined user colors.
Base Handler class for PointCloud colors.
virtual vtkSmartPointer< vtkDataArray > getColor() const =0
Obtain the actual color for the input dataset as a VTK data array.
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.
RGB handler class for colors.
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.
XYZ handler class for PointCloud geometry.
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(FILE *stream, const std::string format, Args &&... args)
Print an error message on stream with colors.
void ignore(const T &...)
Utility function to eliminate unused variable warnings.
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...
static constexpr index_t UNAVAILABLE
std::vector< pcl::Correspondence, Eigen::aligned_allocator< pcl::Correspondence > > Correspondences
constexpr bool isNormalFinite(const PointT &) noexcept
constexpr bool isXYZFinite(const PointT &) noexcept
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.
Metafunction to check if a given point type has either rgb or rgba field.