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