Point Cloud Library (PCL) 1.15.1-dev
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
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#ifndef VTK_CELL_ARRAY_V2
231 vertices = polydata->GetVerts (); // Using the return value of GetVerts() in SetVerts() does not guarantee consistent internal data in polydata
232#endif
233 if (!vertices)
235
236 vtkIdType nr_points = cloud->size ();
237 // Create the point set
238 vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
239 if (!points)
240 {
242 points->SetDataTypeToFloat ();
243 polydata->SetPoints (points);
244 }
245 points->SetNumberOfPoints (nr_points);
246
247 // Get a pointer to the beginning of the data array
248 float *data = (dynamic_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
249
250 // Set the points
251 vtkIdType ptr = 0;
252 if (cloud->is_dense)
253 {
254 for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3) {
255 std::copy(&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
256 }
257 }
258 else
259 {
260 vtkIdType j = 0; // true point index
261 for (vtkIdType i = 0; i < nr_points; ++i)
262 {
263 // Check if the point is invalid
264 if (!pcl::isXYZFinite((*cloud)[i]))
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#ifndef VTK_CELL_ARRAY_V2
335 vertices = polydata->GetVerts (); // Using the return value of GetVerts() in SetVerts() does not guarantee consistent internal data in polydata
336#endif
337 if (!vertices)
339
340#ifdef VTK_CELL_ARRAY_V2
341 // TODO: Remove when VTK 6,7,8 is unsupported
342 pcl::utils::ignore(initcells);
343
344 auto numOfCells = vertices->GetNumberOfCells();
345
346 // If we have less cells than points, add new cells.
347 if (numOfCells < nr_points)
348 {
349 for (int i = numOfCells; i < nr_points; i++)
350 {
351 vertices->InsertNextCell(1);
352 vertices->InsertCellPoint(i);
353 }
354 }
355 // if we too many cells than points, set size (doesn't free excessive memory)
356 else if (numOfCells > nr_points)
357 {
358 vertices->ResizeExact(nr_points, nr_points);
359 }
360
361 polydata->SetPoints(points);
362 polydata->SetVerts(vertices);
363
364#else
365 vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
366 updateCells (cells, initcells, nr_points);
367 // Set the cells and the vertices
368 vertices->SetCells (nr_points, cells);
369#endif
370}
371
372////////////////////////////////////////////////////////////////////////////////////////////
373template <typename PointT> bool
375 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
376 double r, double g, double b, const std::string &id, int viewport)
377{
378 vtkSmartPointer<vtkDataSet> data = createPolygon<PointT> (cloud);
379 if (!data)
380 return (false);
381
382 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
383 auto am_it = shape_actor_map_->find (id);
384 if (am_it != shape_actor_map_->end ())
385 {
387
388 // Add old data
389 all_data->AddInputData (reinterpret_cast<vtkPolyDataMapper*> ((vtkActor::SafeDownCast (am_it->second))->GetMapper ())->GetInput ());
390
391 // Add new data
393 surface_filter->AddInputData (vtkUnstructuredGrid::SafeDownCast (data));
394 vtkSmartPointer<vtkPolyData> poly_data = surface_filter->GetOutput ();
395 all_data->AddInputData (poly_data);
396
397 // Create an Actor
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);
405
406 // Save the pointer/ID pair to the global actor map
407 (*shape_actor_map_)[id] = actor;
408 }
409 else
410 {
411 // Create an Actor
413 createActorFromVTKDataSet (data, actor);
414 actor->GetProperty ()->SetRepresentationToWireframe ();
415 actor->GetProperty ()->SetColor (r, g, b);
416 actor->GetMapper ()->ScalarVisibilityOff ();
417 addActorToRenderer (actor, viewport);
418
419 // Save the pointer/ID pair to the global actor map
420 (*shape_actor_map_)[id] = actor;
421 }
422
423 return (true);
424}
425
426////////////////////////////////////////////////////////////////////////////////////////////
427template <typename PointT> bool
429 const pcl::PlanarPolygon<PointT> &polygon,
430 double r, double g, double b, const std::string &id, int viewport)
431{
432 vtkSmartPointer<vtkDataSet> data = createPolygon<PointT> (polygon);
433 if (!data)
434 return (false);
435
436 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
437 auto am_it = shape_actor_map_->find (id);
438 if (am_it != shape_actor_map_->end ())
439 {
441
442 // Add old data
443 all_data->AddInputData (reinterpret_cast<vtkPolyDataMapper*> ((vtkActor::SafeDownCast (am_it->second))->GetMapper ())->GetInput ());
444
445 // Add new data
447 surface_filter->SetInputData (vtkUnstructuredGrid::SafeDownCast (data));
448 vtkSmartPointer<vtkPolyData> poly_data = surface_filter->GetOutput ();
449 all_data->AddInputData (poly_data);
450
451 // Create an Actor
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);
460
461 // Save the pointer/ID pair to the global actor map
462 (*shape_actor_map_)[id] = actor;
463 }
464 else
465 {
466 // Create an 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);
474
475 // Save the pointer/ID pair to the global actor map
476 (*shape_actor_map_)[id] = actor;
477 }
478 return (true);
479}
480
481////////////////////////////////////////////////////////////////////////////////////////////
482template <typename PointT> bool
484 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
485 const std::string &id, int viewport)
486{
487 return (addPolygon<PointT> (cloud, 0.5, 0.5, 0.5, id, viewport));
488}
489
490////////////////////////////////////////////////////////////////////////////////////////////
491template <typename P1, typename P2> bool
492pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
493{
494 if (contains (id))
495 {
496 PCL_WARN ("[addLine] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
497 return (false);
498 }
499
500 vtkSmartPointer<vtkDataSet> data = createLine (pt1.getVector4fMap (), pt2.getVector4fMap ());
501
502 // Create an Actor
504 createActorFromVTKDataSet (data, actor);
505 actor->GetProperty ()->SetRepresentationToWireframe ();
506 actor->GetProperty ()->SetColor (r, g, b);
507 actor->GetMapper ()->ScalarVisibilityOff ();
508 addActorToRenderer (actor, viewport);
509
510 // Save the pointer/ID pair to the global actor map
511 (*shape_actor_map_)[id] = actor;
512 return (true);
513}
514
515////////////////////////////////////////////////////////////////////////////////////////////
516template <typename P1, typename P2> bool
517pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
518{
519 if (contains (id))
520 {
521 PCL_WARN ("[addArrow] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
522 return (false);
523 }
524
525 // Create an Actor
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 ();
533
534 leader->GetProperty ()->SetColor (r, g, b);
535 addActorToRenderer (leader, viewport);
536
537 // Save the pointer/ID pair to the global actor map
538 (*shape_actor_map_)[id] = leader;
539 return (true);
540}
541
542////////////////////////////////////////////////////////////////////////////////////////////
543template <typename P1, typename P2> bool
544pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2, double r, double g, double b, bool display_length, const std::string &id, int viewport)
545{
546 if (contains (id))
547 {
548 PCL_WARN ("[addArrow] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
549 return (false);
550 }
551
552 // Create an Actor
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 ();
560 if (display_length)
561 leader->AutoLabelOn ();
562 else
563 leader->AutoLabelOff ();
564
565 leader->GetProperty ()->SetColor (r, g, b);
566 addActorToRenderer (leader, viewport);
567
568 // Save the pointer/ID pair to the global actor map
569 (*shape_actor_map_)[id] = leader;
570 return (true);
571}
572////////////////////////////////////////////////////////////////////////////////////////////
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)
578{
579 if (contains (id))
580 {
581 PCL_WARN ("[addArrow] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
582 return (false);
583 }
584
585 // Create an Actor
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 ();
593
594 leader->GetLabelTextProperty()->SetColor(r_text, g_text, b_text);
595
596 leader->GetProperty ()->SetColor (r_line, g_line, b_line);
597 addActorToRenderer (leader, viewport);
598
599 // Save the pointer/ID pair to the global actor map
600 (*shape_actor_map_)[id] = leader;
601 return (true);
602}
603
604////////////////////////////////////////////////////////////////////////////////////////////
605template <typename P1, typename P2> bool
606pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, const std::string &id, int viewport)
607{
608 return (addLine (pt1, pt2, 0.5, 0.5, 0.5, id, viewport));
609}
610
611////////////////////////////////////////////////////////////////////////////////////////////
612template <typename PointT> bool
613pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, double r, double g, double b, const std::string &id, int viewport)
614{
615 if (contains (id))
616 {
617 PCL_WARN ("[addSphere] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
618 return (false);
619 }
620
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 ();
627 data->Update ();
628
629 // Setup actor and mapper
630 vtkSmartPointer <vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New ();
631 mapper->SetInputConnection (data->GetOutputPort ());
632
633 // Create an Actor
635 actor->SetMapper (mapper);
636 //createActorFromVTKDataSet (data, actor);
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);
644
645 // Save the pointer/ID pair to the global actor map
646 (*shape_actor_map_)[id] = actor;
647 return (true);
648}
649
650////////////////////////////////////////////////////////////////////////////////////////////
651template <typename PointT> bool
652pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, const std::string &id, int viewport)
653{
654 return (addSphere (center, radius, 0.5, 0.5, 0.5, id, viewport));
655}
656
657////////////////////////////////////////////////////////////////////////////////////////////
658template<typename PointT> bool
659pcl::visualization::PCLVisualizer::updateSphere (const PointT &center, double radius, double r, double g, double b, const std::string &id)
660{
661 if (!contains (id))
662 {
663 return (false);
664 }
665
666 //////////////////////////////////////////////////////////////////////////
667 // Get the actor pointer
668 auto am_it = shape_actor_map_->find (id);
669 vtkLODActor* actor = vtkLODActor::SafeDownCast (am_it->second);
670 if (!actor)
671 return (false);
672 vtkAlgorithm *algo = actor->GetMapper ()->GetInputAlgorithm ();
673 vtkSphereSource *src = vtkSphereSource::SafeDownCast (algo);
674 if (!src)
675 return (false);
676
677 src->SetCenter (double (center.x), double (center.y), double (center.z));
678 src->SetRadius (radius);
679 src->Update ();
680 actor->GetProperty ()->SetColor (r, g, b);
681 actor->Modified ();
682
683 return (true);
684}
685
686//////////////////////////////////////////////////
687template <typename PointT> bool
689 const std::string &text,
690 const PointT& position,
691 double textScale,
692 double r,
693 double g,
694 double b,
695 const std::string &id,
696 int viewport)
697{
698 std::string tid;
699 if (id.empty ())
700 tid = text;
701 else
702 tid = id;
703
704 if (viewport < 0)
705 return false;
706
707 // If there is no custom viewport and the viewport number is not 0, exit
708 if (rens_->GetNumberOfItems () <= viewport)
709 {
710 PCL_ERROR ("[addText3D] The viewport [%d] doesn't exist (id <%s>)! \n",
711 viewport,
712 tid.c_str ());
713 return false;
714 }
715
716 // check all or an individual viewport for a similar id
717 rens_->InitTraversal ();
718 for (std::size_t i = viewport; rens_->GetNextItem (); ++i)
719 {
720 const std::string uid = tid + std::string (i, '*');
721 if (contains (uid))
722 {
723 PCL_ERROR ( "[addText3D] The id <%s> already exists in viewport [%d]! \n"
724 "Please choose a different id and retry.\n",
725 tid.c_str (),
726 i);
727 return false;
728 }
729
730 if (viewport > 0)
731 break;
732 }
733
735 textSource->SetText (text.c_str());
736 textSource->Update ();
737
739 textMapper->SetInputConnection (textSource->GetOutputPort ());
740
741 // Since each follower may follow a different camera, we need different followers
742 rens_->InitTraversal ();
743 vtkRenderer* renderer;
744 int i = 0;
745 while ((renderer = rens_->GetNextItem ()))
746 {
747 // Should we add the actor to all renderers or just to i-nth renderer?
748 if (viewport == 0 || viewport == i)
749 {
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 ());
756
757 renderer->AddActor (textActor);
758
759 // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
760 // for multiple viewport
761 const std::string uid = tid + std::string (i, '*');
762 (*shape_actor_map_)[uid] = textActor;
763 }
764
765 ++i;
766 }
767
768 return (true);
769}
770
771//////////////////////////////////////////////////
772template <typename PointT> bool
774 const std::string &text,
775 const PointT& position,
776 double orientation[3],
777 double textScale,
778 double r,
779 double g,
780 double b,
781 const std::string &id,
782 int viewport)
783{
784 std::string tid;
785 if (id.empty ())
786 tid = text;
787 else
788 tid = id;
789
790 if (viewport < 0)
791 return false;
792
793 // If there is no custom viewport and the viewport number is not 0, exit
794 if (rens_->GetNumberOfItems () <= viewport)
795 {
796 PCL_ERROR ("[addText3D] The viewport [%d] doesn't exist (id <%s>)!\n",
797 viewport,
798 tid.c_str ());
799 return false;
800 }
801
802 // check all or an individual viewport for a similar id
803 rens_->InitTraversal ();
804 for (std::size_t i = viewport; rens_->GetNextItem (); ++i)
805 {
806 const std::string uid = tid + std::string (i, '*');
807 if (contains (uid))
808 {
809 PCL_ERROR ( "[addText3D] The id <%s> already exists in viewport [%d]! "
810 "Please choose a different id and retry.\n",
811 tid.c_str (),
812 i);
813 return false;
814 }
815
816 if (viewport > 0)
817 break;
818 }
819
821 textSource->SetText (text.c_str());
822 textSource->Update ();
823
825 textMapper->SetInputConnection (textSource->GetOutputPort ());
826
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);
833
834 // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
835 rens_->InitTraversal ();
836 int i = 0;
837 for ( vtkRenderer* renderer = rens_->GetNextItem ();
838 renderer;
839 renderer = rens_->GetNextItem (), ++i)
840 {
841 if (viewport == 0 || viewport == i)
842 {
843 renderer->AddActor (textActor);
844 const std::string uid = tid + std::string (i, '*');
845 (*shape_actor_map_)[uid] = textActor;
846 }
847 }
848
849 return (true);
850}
851
852//////////////////////////////////////////////////////////////////////////////////////////////
853template <typename PointNT> bool
855 const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
856 int level, float scale, const std::string &id, int viewport)
857{
858 return (addPointCloudNormals<PointNT, PointNT> (cloud, cloud, level, scale, id, viewport));
859}
860
861//////////////////////////////////////////////////////////////////////////////////////////////
862template <typename PointT, typename PointNT> bool
864 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
865 const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
866 int level, float scale,
867 const std::string &id, int viewport)
868{
869 if (normals->size () != cloud->size ())
870 {
871 PCL_ERROR ("[addPointCloudNormals] The number of points differs from the number of normals!\n");
872 return (false);
873 }
874
875 if (normals->empty ())
876 {
877 PCL_WARN ("[addPointCloudNormals] An empty normal cloud is given! Nothing to display.\n");
878 return (false);
879 }
880
881 if (contains (id))
882 {
883 PCL_WARN ("[addPointCloudNormals] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
884 return (false);
885 }
886
889
890 points->SetDataTypeToFloat ();
892 data->SetNumberOfComponents (3);
893
894
895 vtkIdType nr_normals = 0;
896 float* pts = nullptr;
897
898 // If the cloud is organized, then distribute the normal step in both directions
899 if (cloud->isOrganized () && normals->isOrganized ())
900 {
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];
905
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)
909 {
910 PointT p = (*cloud)(x, y);
911 if (!pcl::isFinite(p) || !pcl::isNormalFinite((*normals)(x, y)))
912 continue;
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;
916
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;
923
924 lines->InsertNextCell (2);
925 lines->InsertCellPoint (2 * cell_count);
926 lines->InsertCellPoint (2 * cell_count + 1);
927 cell_count ++;
928 }
929 nr_normals = cell_count;
930 }
931 else
932 {
933 nr_normals = (cloud->size () - 1) / level + 1 ;
934 pts = new float[2 * nr_normals * 3];
935
936 vtkIdType j = 0;
937 for (vtkIdType i = 0; (j < nr_normals) && (i < static_cast<vtkIdType>(cloud->size())); i += level)
938 {
939 if (!pcl::isFinite((*cloud)[i]) || !pcl::isNormalFinite((*normals)[i]))
940 continue;
941 PointT p = (*cloud)[i];
942 p.x += (*normals)[i].normal[0] * scale;
943 p.y += (*normals)[i].normal[1] * scale;
944 p.z += (*normals)[i].normal[2] * scale;
945
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;
952
953 lines->InsertNextCell (2);
954 lines->InsertCellPoint (2 * j);
955 lines->InsertCellPoint (2 * j + 1);
956 ++j;
957 }
958 nr_normals = j;
959 }
960
961 data->SetArray (&pts[0], 2 * nr_normals * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
962 points->SetData (data);
963
965 polyData->SetPoints (points);
966 polyData->SetLines (lines);
967
969 mapper->SetInputData (polyData);
970 mapper->SetColorModeToMapScalars();
971 mapper->SetScalarModeToUsePointData();
972
973 // create actor
975 actor->SetMapper (mapper);
976
977 // Use cloud view point info
979 convertToVtkMatrix (cloud->sensor_origin_, cloud->sensor_orientation_, transformation);
980 actor->SetUserMatrix (transformation);
981
982 // Add it to all renderers
983 addActorToRenderer (actor, viewport);
984
985 // Save the pointer/ID pair to the global actor map
986 (*cloud_actor_map_)[id].actor = actor;
987 return (true);
988}
989
990//////////////////////////////////////////////////////////////////////////////////////////////
991template <typename PointNT> bool
993 const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
995 int level, float scale,
996 const std::string &id, int viewport)
997{
998 return (addPointCloudPrincipalCurvatures<PointNT, PointNT> (cloud, cloud, pcs, level, scale, id, viewport));
999}
1000
1001//////////////////////////////////////////////////////////////////////////////////////////////
1002template <typename PointT, typename PointNT> bool
1004 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1005 const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
1007 int level, float scale,
1008 const std::string &id, int viewport)
1009{
1010 if (pcs->size () != cloud->size () || normals->size () != cloud->size ())
1011 {
1012 pcl::console::print_error ("[addPointCloudPrincipalCurvatures] The number of points differs from the number of principal curvatures/normals!\n");
1013 return (false);
1014 }
1015
1016 if (contains (id))
1017 {
1018 PCL_WARN ("[addPointCloudPrincipalCurvatures] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1019 return (false);
1020 }
1021
1024
1025 // Setup two colors - one for each line
1026 unsigned char green[3] = {0, 255, 0};
1027 unsigned char blue[3] = {0, 0, 255};
1028
1029 // Setup the colors array
1031 line_1_colors->SetNumberOfComponents (3);
1032 line_1_colors->SetName ("Colors");
1034 line_2_colors->SetNumberOfComponents (3);
1035 line_2_colors->SetName ("Colors");
1036
1037 // Create the first sets of lines
1038 for (std::size_t i = 0; i < cloud->size (); i+=level)
1039 {
1040 PointT p = (*cloud)[i];
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;
1044
1046 line_1->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1047 line_1->SetPoint2 (p.x, p.y, p.z);
1048 line_1->Update ();
1049 polydata_1->AddInputData (line_1->GetOutput ());
1050 line_1_colors->InsertNextTupleValue (green);
1051 }
1052 polydata_1->Update ();
1053 vtkSmartPointer<vtkPolyData> line_1_data = polydata_1->GetOutput ();
1054 line_1_data->GetCellData ()->SetScalars (line_1_colors);
1055
1056 // Create the second sets of lines
1057 for (std::size_t i = 0; i < cloud->size (); i += level)
1058 {
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);
1066
1067 PointT p = (*cloud)[i];
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;
1071
1073 line_2->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1074 line_2->SetPoint2 (p.x, p.y, p.z);
1075 line_2->Update ();
1076 polydata_2->AddInputData (line_2->GetOutput ());
1077
1078 line_2_colors->InsertNextTupleValue (blue);
1079 }
1080 polydata_2->Update ();
1081 vtkSmartPointer<vtkPolyData> line_2_data = polydata_2->GetOutput ();
1082 line_2_data->GetCellData ()->SetScalars (line_2_colors);
1083
1084 // Assemble the two sets of lines
1086 alldata->AddInputData (line_1_data);
1087 alldata->AddInputData (line_2_data);
1088 alldata->Update ();
1089
1090 // Create an Actor
1092 createActorFromVTKDataSet (alldata->GetOutput (), actor);
1093 actor->GetMapper ()->SetScalarModeToUseCellData ();
1094
1095 // Add it to all renderers
1096 addActorToRenderer (actor, viewport);
1097
1098 // Save the pointer/ID pair to the global actor map
1099 CloudActor act;
1100 act.actor = actor;
1101 (*cloud_actor_map_)[id] = act;
1102 return (true);
1103}
1104
1105//////////////////////////////////////////////////////////////////////////////////////////////
1106template <typename PointT, typename GradientT> bool
1108 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1109 const typename pcl::PointCloud<GradientT>::ConstPtr &gradients,
1110 int level, double scale,
1111 const std::string &id, int viewport)
1112{
1113 if (gradients->size () != cloud->size ())
1114 {
1115 PCL_ERROR ("[addPointCloudGradients] The number of points differs from the number of gradients!\n");
1116 return (false);
1117 }
1118 if (contains (id))
1119 {
1120 PCL_WARN ("[addPointCloudGradients] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1121 return (false);
1122 }
1123
1126
1127 points->SetDataTypeToFloat ();
1129 data->SetNumberOfComponents (3);
1130
1131 vtkIdType nr_gradients = (cloud->size () - 1) / level + 1 ;
1132 float* pts = new float[2 * nr_gradients * 3];
1133
1134 for (vtkIdType i = 0, j = 0; j < nr_gradients; j++, i = j * level)
1135 {
1136 PointT p = (*cloud)[i];
1137 p.x += (*gradients)[i].gradient[0] * scale;
1138 p.y += (*gradients)[i].gradient[1] * scale;
1139 p.z += (*gradients)[i].gradient[2] * scale;
1140
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;
1147
1148 lines->InsertNextCell(2);
1149 lines->InsertCellPoint(2*j);
1150 lines->InsertCellPoint(2*j+1);
1151 }
1152
1153 data->SetArray (&pts[0], 2 * nr_gradients * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
1154 points->SetData (data);
1155
1157 polyData->SetPoints(points);
1158 polyData->SetLines(lines);
1159
1161 mapper->SetInputData (polyData);
1162 mapper->SetColorModeToMapScalars();
1163 mapper->SetScalarModeToUsePointData();
1164
1165 // create actor
1167 actor->SetMapper (mapper);
1168
1169 // Add it to all renderers
1170 addActorToRenderer (actor, viewport);
1171
1172 // Save the pointer/ID pair to the global actor map
1173 (*cloud_actor_map_)[id].actor = actor;
1174 return (true);
1175}
1176
1177//////////////////////////////////////////////////////////////////////////////////////////////
1178template <typename PointT> bool
1180 const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1181 const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1182 const std::vector<int> &correspondences,
1183 const std::string &id,
1184 int viewport)
1185{
1187 corrs.resize (correspondences.size ());
1188
1189 std::size_t index = 0;
1190 for (auto &corr : corrs)
1191 {
1192 corr.index_query = index;
1193 corr.index_match = correspondences[index];
1194 index++;
1195 }
1196
1197 return (addCorrespondences<PointT> (source_points, target_points, corrs, id, viewport));
1198}
1199
1200//////////////////////////////////////////////////////////////////////////////////////////////
1201template <typename PointT> bool
1203 const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1204 const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1205 const pcl::Correspondences &correspondences,
1206 int nth,
1207 const std::string &id,
1208 int viewport,
1209 bool overwrite)
1210{
1211 if (correspondences.empty ())
1212 {
1213 PCL_DEBUG ("[addCorrespondences] An empty set of correspondences given! Nothing to display.\n");
1214 return (false);
1215 }
1216
1217 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1218 auto am_it = shape_actor_map_->find (id);
1219 if (am_it != shape_actor_map_->end () && !overwrite)
1220 {
1221 PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1222 return (false);
1223 }
1224 if (am_it == shape_actor_map_->end () && overwrite)
1225 {
1226 overwrite = false; // Correspondences doesn't exist, add them instead of updating them
1227 }
1228
1229 int n_corr = static_cast<int>(correspondences.size () / nth);
1231
1232 // Prepare colors
1234 line_colors->SetNumberOfComponents (3);
1235 line_colors->SetName ("Colors");
1236 line_colors->SetNumberOfTuples (n_corr);
1237
1238 // Prepare coordinates
1240 line_points->SetNumberOfPoints (2 * n_corr);
1241
1243 line_cells_id->SetNumberOfComponents (3);
1244 line_cells_id->SetNumberOfTuples (n_corr);
1245 vtkIdType *line_cell_id = line_cells_id->GetPointer (0);
1247
1249 line_tcoords->SetNumberOfComponents (1);
1250 line_tcoords->SetNumberOfTuples (n_corr * 2);
1251 line_tcoords->SetName ("Texture Coordinates");
1252
1253 double tc[3] = {0.0, 0.0, 0.0};
1254
1255 Eigen::Affine3f source_transformation;
1256 source_transformation.linear () = source_points->sensor_orientation_.matrix ();
1257 source_transformation.translation () = source_points->sensor_origin_.template head<3> ();
1258 Eigen::Affine3f target_transformation;
1259 target_transformation.linear () = target_points->sensor_orientation_.matrix ();
1260 target_transformation.translation () = target_points->sensor_origin_.template head<3> ();
1261
1262 int j = 0;
1263 // Draw lines between the best corresponding points
1264 for (std::size_t i = 0; i < correspondences.size (); i += nth, ++j)
1265 {
1266 if (correspondences[i].index_match == UNAVAILABLE)
1267 {
1268 PCL_WARN ("[addCorrespondences] No valid index_match for correspondence %d\n", i);
1269 continue;
1270 }
1271
1272 PointT p_src ((*source_points)[correspondences[i].index_query]);
1273 PointT p_tgt ((*target_points)[correspondences[i].index_match]);
1274
1275 p_src.getVector3fMap () = source_transformation * p_src.getVector3fMap ();
1276 p_tgt.getVector3fMap () = target_transformation * p_tgt.getVector3fMap ();
1277
1278 int id1 = j * 2 + 0, id2 = j * 2 + 1;
1279 // Set the points
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);
1282 // Set the cell ID
1283 *line_cell_id++ = 2;
1284 *line_cell_id++ = id1;
1285 *line_cell_id++ = id2;
1286 // Set the texture coords
1287 tc[0] = 0.; line_tcoords->SetTuple (id1, tc);
1288 tc[0] = 1.; line_tcoords->SetTuple (id2, tc);
1289
1290 float rgb[3];
1291 rgb[0] = vtkMath::Random (32, 255); // min / max
1292 rgb[1] = vtkMath::Random (32, 255);
1293 rgb[2] = vtkMath::Random (32, 255);
1294 line_colors->InsertTuple (i, rgb);
1295 }
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);
1301
1302 // Fill in the lines
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);
1307
1308 // Create an Actor
1309 if (!overwrite)
1310 {
1312 createActorFromVTKDataSet (line_data, actor);
1313 actor->GetProperty ()->SetRepresentationToWireframe ();
1314 actor->GetProperty ()->SetOpacity (0.5);
1315 addActorToRenderer (actor, viewport);
1316
1317 // Save the pointer/ID pair to the global actor map
1318 (*shape_actor_map_)[id] = actor;
1319 }
1320 else
1321 {
1322 vtkSmartPointer<vtkLODActor> actor = vtkLODActor::SafeDownCast (am_it->second);
1323 if (!actor)
1324 return (false);
1325 // Update the mapper
1326 reinterpret_cast<vtkPolyDataMapper*> (actor->GetMapper ())->SetInputData (line_data);
1327 }
1328
1329 return (true);
1330}
1331
1332//////////////////////////////////////////////////////////////////////////////////////////////
1333template <typename PointT> bool
1335 const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1336 const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1337 const pcl::Correspondences &correspondences,
1338 int nth,
1339 const std::string &id,
1340 int viewport)
1341{
1342 return (addCorrespondences<PointT> (source_points, target_points, correspondences, nth, id, viewport, true));
1343}
1344
1345//////////////////////////////////////////////////////////////////////////////////////////////
1346template <typename PointT> bool
1347pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1348 const PointCloudGeometryHandler<PointT> &geometry_handler,
1349 const PointCloudColorHandler<PointT> &color_handler,
1350 const std::string &id,
1351 int viewport,
1352 const Eigen::Vector4f& sensor_origin,
1353 const Eigen::Quaternion<float>& sensor_orientation)
1354{
1355 if (!geometry_handler.isCapable ())
1356 {
1357 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1358 return (false);
1359 }
1360
1361 if (!color_handler.isCapable ())
1362 {
1363 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1364 return (false);
1365 }
1366
1369 // Convert the PointCloud to VTK PolyData
1370 convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1371
1372 // Get the colors from the handler
1373 bool has_colors = false;
1374 double minmax[2];
1375 if (auto scalars = color_handler.getColor ())
1376 {
1377 polydata->GetPointData ()->SetScalars (scalars);
1378 scalars->GetRange (minmax);
1379 has_colors = true;
1380 }
1381
1382 // Create an Actor
1384 createActorFromVTKDataSet (polydata, actor);
1385 if (has_colors)
1386 actor->GetMapper ()->SetScalarRange (minmax);
1387
1388 // Add it to all renderers
1389 addActorToRenderer (actor, viewport);
1390
1391 // Save the pointer/ID pair to the global actor map
1392 CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1393 cloud_actor.actor = actor;
1394 cloud_actor.cells = initcells;
1395
1396 // Save the viewpoint transformation matrix to the global actor map
1398 convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1399 cloud_actor.viewpoint_transformation_ = transformation;
1400 cloud_actor.actor->SetUserMatrix (transformation);
1401 cloud_actor.actor->Modified ();
1402
1403 return (true);
1404}
1405
1406//////////////////////////////////////////////////////////////////////////////////////////////
1407template <typename PointT> bool
1408pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1409 const PointCloudGeometryHandler<PointT> &geometry_handler,
1410 const ColorHandlerConstPtr &color_handler,
1411 const std::string &id,
1412 int viewport,
1413 const Eigen::Vector4f& sensor_origin,
1414 const Eigen::Quaternion<float>& sensor_orientation)
1415{
1416 if (!geometry_handler.isCapable ())
1417 {
1418 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1419 return (false);
1420 }
1421
1422 if (!color_handler->isCapable ())
1423 {
1424 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler->getName ().c_str ());
1425 return (false);
1426 }
1427
1430 // Convert the PointCloud to VTK PolyData
1431 convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1432 // use the given geometry handler
1433
1434 // Get the colors from the handler
1435 bool has_colors = false;
1436 double minmax[2];
1437 if (auto scalars = color_handler->getColor ())
1438 {
1439 polydata->GetPointData ()->SetScalars (scalars);
1440 scalars->GetRange (minmax);
1441 has_colors = true;
1442 }
1443
1444 // Create an Actor
1446 createActorFromVTKDataSet (polydata, actor);
1447 if (has_colors)
1448 actor->GetMapper ()->SetScalarRange (minmax);
1449
1450 // Add it to all renderers
1451 addActorToRenderer (actor, viewport);
1452
1453 // Save the pointer/ID pair to the global actor map
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);
1458
1459 // Save the viewpoint transformation matrix to the global actor map
1461 convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1462 cloud_actor.viewpoint_transformation_ = transformation;
1463 cloud_actor.actor->SetUserMatrix (transformation);
1464 cloud_actor.actor->Modified ();
1465
1466 return (true);
1467}
1468
1469//////////////////////////////////////////////////////////////////////////////////////////////
1470template <typename PointT> bool
1471pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1472 const GeometryHandlerConstPtr &geometry_handler,
1473 const PointCloudColorHandler<PointT> &color_handler,
1474 const std::string &id,
1475 int viewport,
1476 const Eigen::Vector4f& sensor_origin,
1477 const Eigen::Quaternion<float>& sensor_orientation)
1478{
1479 if (!geometry_handler->isCapable ())
1480 {
1481 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler->getName ().c_str ());
1482 return (false);
1483 }
1484
1485 if (!color_handler.isCapable ())
1486 {
1487 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1488 return (false);
1489 }
1490
1493 // Convert the PointCloud to VTK PolyData
1494 convertPointCloudToVTKPolyData (geometry_handler, polydata, initcells);
1495 // use the given geometry handler
1496
1497 // Get the colors from the handler
1498 bool has_colors = false;
1499 double minmax[2];
1500 if (auto scalars = color_handler.getColor ())
1501 {
1502 polydata->GetPointData ()->SetScalars (scalars);
1503 scalars->GetRange (minmax);
1504 has_colors = true;
1505 }
1506
1507 // Create an Actor
1509 createActorFromVTKDataSet (polydata, actor);
1510 if (has_colors)
1511 actor->GetMapper ()->SetScalarRange (minmax);
1512
1513 // Add it to all renderers
1514 addActorToRenderer (actor, viewport);
1515
1516 // Save the pointer/ID pair to the global actor map
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);
1521
1522 // Save the viewpoint transformation matrix to the global actor map
1524 convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1525 cloud_actor.viewpoint_transformation_ = transformation;
1526 cloud_actor.actor->SetUserMatrix (transformation);
1527 cloud_actor.actor->Modified ();
1528
1529 return (true);
1530}
1531
1532//////////////////////////////////////////////////////////////////////////////////////////////
1533template <typename PointT> bool
1535 const std::string &id)
1536{
1537 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1538 auto am_it = cloud_actor_map_->find (id);
1539
1540 if (am_it == cloud_actor_map_->end ())
1541 return (false);
1542
1543 vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1544 if (!polydata)
1545 return false;
1546 // Convert the PointCloud to VTK PolyData
1547 convertPointCloudToVTKPolyData<PointT> (cloud, polydata, am_it->second.cells);
1548
1549 // Set scalars to blank, since there is no way we can update them here.
1551 polydata->GetPointData ()->SetScalars (scalars);
1552 double minmax[2];
1553 minmax[0] = std::numeric_limits<double>::min ();
1554 minmax[1] = std::numeric_limits<double>::max ();
1555 am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1556
1557 // Update the mapper
1558 reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1559 return (true);
1560}
1561
1562/////////////////////////////////////////////////////////////////////////////////////////////
1563template <typename PointT> bool
1565 const PointCloudGeometryHandler<PointT> &geometry_handler,
1566 const std::string &id)
1567{
1568 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1569 auto am_it = cloud_actor_map_->find (id);
1570
1571 if (am_it == cloud_actor_map_->end ())
1572 return (false);
1573
1574 vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1575 if (!polydata)
1576 return (false);
1577 // Convert the PointCloud to VTK PolyData
1578 convertPointCloudToVTKPolyData (geometry_handler, polydata, am_it->second.cells);
1579
1580 // Set scalars to blank, since there is no way we can update them here.
1582 polydata->GetPointData ()->SetScalars (scalars);
1583 double minmax[2];
1584 minmax[0] = std::numeric_limits<double>::min ();
1585 minmax[1] = std::numeric_limits<double>::max ();
1586 am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1587
1588 // Update the mapper
1589 reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1590 return (true);
1591}
1592
1593
1594/////////////////////////////////////////////////////////////////////////////////////////////
1595template <typename PointT> bool
1597 const PointCloudColorHandler<PointT> &color_handler,
1598 const std::string &id)
1599{
1600 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1601 auto am_it = cloud_actor_map_->find (id);
1602
1603 if (am_it == cloud_actor_map_->end ())
1604 return (false);
1605
1606 // Get the current poly data
1607 vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1608 if (!polydata)
1609 return (false);
1610
1611 convertPointCloudToVTKPolyData<PointT>(cloud, polydata, am_it->second.cells);
1612
1613 // Get the colors from the handler
1614 bool has_colors = false;
1615 double minmax[2];
1616 if (auto scalars = color_handler.getColor ())
1617 {
1618 // Update the data
1619 polydata->GetPointData ()->SetScalars (scalars);
1620 scalars->GetRange (minmax);
1621 has_colors = true;
1622 }
1623
1624 if (has_colors)
1625 am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1626
1627 // Update the mapper
1628 reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1629 return (true);
1630}
1631
1632/////////////////////////////////////////////////////////////////////////////////////////////
1633template <typename PointT> bool
1635 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1636 const std::vector<pcl::Vertices> &vertices,
1637 const std::string &id,
1638 int viewport)
1639{
1640 if (vertices.empty () || cloud->points.empty ())
1641 return (false);
1642
1643 if (contains (id))
1644 {
1645 PCL_WARN ("[addPolygonMesh] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1646 return (false);
1647 }
1648
1649 int rgb_idx = -1;
1650 std::vector<pcl::PCLPointField> fields;
1652 rgb_idx = pcl::getFieldIndex<PointT> ("rgb", fields);
1653 if (rgb_idx == -1)
1654 rgb_idx = pcl::getFieldIndex<PointT> ("rgba", fields);
1655 if (rgb_idx != -1)
1656 {
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)
1662 {
1663 if (!isFinite ((*cloud)[i]))
1664 continue;
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);
1671 }
1672 }
1673
1674 // Create points from polyMesh.cloud
1676 vtkIdType nr_points = cloud->size ();
1677 points->SetNumberOfPoints (nr_points);
1679
1680 // Get a pointer to the beginning of the data array
1681 float *data = dynamic_cast<vtkFloatArray*> (points->GetData ())->GetPointer (0);
1682
1683 vtkIdType ptr = 0;
1684 std::vector<int> lookup;
1685 // If the dataset is dense (no NaNs)
1686 if (cloud->is_dense)
1687 {
1688 for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3) {
1689 std::copy(&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1690 }
1691 }
1692 else
1693 {
1694 lookup.resize (nr_points);
1695 vtkIdType j = 0; // true point index
1696 for (vtkIdType i = 0; i < nr_points; ++i)
1697 {
1698 // Check if the point is invalid
1699 if (!isFinite ((*cloud)[i]))
1700 continue;
1701
1702 lookup[i] = static_cast<int> (j);
1703 std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1704 j++;
1705 ptr += 3;
1706 }
1707 nr_points = j;
1708 points->SetNumberOfPoints (nr_points);
1709 }
1710
1711 // Get the maximum size of a polygon
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 ());
1716
1717 if (vertices.size () > 1)
1718 {
1719 // Create polys from polyMesh.polygons
1721
1722 const auto idx = details::fillCells(lookup,vertices,cell_array, max_size_of_polygon);
1723
1725 allocVtkPolyData (polydata);
1726 cell_array->GetData ()->SetNumberOfValues (idx);
1727 cell_array->Squeeze ();
1728 polydata->SetPolys (cell_array);
1729 polydata->SetPoints (points);
1730
1731 if (colors)
1732 polydata->GetPointData ()->SetScalars (colors);
1733
1734 createActorFromVTKDataSet (polydata, actor, false);
1735 }
1736 else
1737 {
1739 std::size_t n_points = vertices[0].vertices.size ();
1740 polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
1741
1742 if (!lookup.empty ())
1743 {
1744 for (std::size_t j = 0; j < (n_points - 1); ++j)
1745 polygon->GetPointIds ()->SetId (j, lookup[vertices[0].vertices[j]]);
1746 }
1747 else
1748 {
1749 for (std::size_t j = 0; j < (n_points - 1); ++j)
1750 polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
1751 }
1753 allocVtkUnstructuredGrid (poly_grid);
1754 poly_grid->Allocate (1, 1);
1755 poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
1756 poly_grid->SetPoints (points);
1757 if (colors)
1758 poly_grid->GetPointData ()->SetScalars (colors);
1759
1760 createActorFromVTKDataSet (poly_grid, actor, false);
1761 }
1762 addActorToRenderer (actor, viewport);
1763 actor->GetProperty ()->SetRepresentationToSurface ();
1764 // Backface culling renders the visualization slower, but guarantees that we see all triangles
1765 actor->GetProperty ()->BackfaceCullingOff ();
1766 actor->GetProperty ()->SetInterpolationToFlat ();
1767 actor->GetProperty ()->EdgeVisibilityOff ();
1768 actor->GetProperty ()->ShadingOff ();
1769
1770 // Save the pointer/ID pair to the global actor map
1771 (*cloud_actor_map_)[id].actor = actor;
1772
1773 // Save the viewpoint transformation matrix to the global actor map
1775 convertToVtkMatrix (cloud->sensor_origin_, cloud->sensor_orientation_, transformation);
1776 (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
1777
1778 return (true);
1779}
1780
1781/////////////////////////////////////////////////////////////////////////////////////////////
1782template <typename PointT> bool
1784 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1785 const std::vector<pcl::Vertices> &verts,
1786 const std::string &id)
1787{
1788 if (verts.empty ())
1789 {
1790 pcl::console::print_error ("[addPolygonMesh] No vertices given!\n");
1791 return (false);
1792 }
1793
1794 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1795 auto am_it = cloud_actor_map_->find (id);
1796 if (am_it == cloud_actor_map_->end ())
1797 return (false);
1798
1799 // Get the current poly data
1800 vtkSmartPointer<vtkPolyData> polydata = dynamic_cast<vtkPolyData*>(am_it->second.actor->GetMapper ()->GetInput ());
1801 if (!polydata)
1802 return (false);
1803 vtkSmartPointer<vtkCellArray> cells = polydata->GetPolys ();
1804 if (!cells)
1805 return (false);
1806 vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
1807 // Copy the new point array in
1808 vtkIdType nr_points = cloud->size ();
1809 points->SetNumberOfPoints (nr_points);
1810
1811 // Get a pointer to the beginning of the data array
1812 float *data = (dynamic_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
1813
1814 int ptr = 0;
1815 std::vector<int> lookup;
1816 // If the dataset is dense (no NaNs)
1817 if (cloud->is_dense)
1818 {
1819 for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
1820 std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1821 }
1822 else
1823 {
1824 lookup.resize (nr_points);
1825 vtkIdType j = 0; // true point index
1826 for (vtkIdType i = 0; i < nr_points; ++i)
1827 {
1828 // Check if the point is invalid
1829 if (!isFinite ((*cloud)[i]))
1830 continue;
1831
1832 lookup [i] = static_cast<int> (j);
1833 std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1834 j++;
1835 ptr += 3;
1836 }
1837 nr_points = j;
1838 points->SetNumberOfPoints (nr_points);
1839 }
1840
1841 // Update colors
1842 vtkUnsignedCharArray* colors = vtkUnsignedCharArray::SafeDownCast (polydata->GetPointData ()->GetScalars ());
1843 if (!colors)
1844 return (false);
1845 int rgb_idx = -1;
1846 std::vector<pcl::PCLPointField> fields;
1847 rgb_idx = pcl::getFieldIndex<PointT> ("rgb", fields);
1848 if (rgb_idx == -1)
1849 rgb_idx = pcl::getFieldIndex<PointT> ("rgba", fields);
1850 if (rgb_idx != -1 && colors)
1851 {
1852 int j = 0;
1853 std::uint32_t offset = fields[rgb_idx].offset;
1854 for (std::size_t i = 0; i < cloud->size (); ++i)
1855 {
1856 if (!isFinite ((*cloud)[i]))
1857 continue;
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);
1864 }
1865 }
1866
1867 // Get the maximum size of a polygon
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 ());
1872
1873 // Update the cells
1875
1876 const auto idx = details::fillCells(lookup, verts, cells, max_size_of_polygon);
1877
1878 cells->GetData ()->SetNumberOfValues (idx);
1879 cells->Squeeze ();
1880 // Set the the vertices
1881 polydata->SetPolys (cells);
1882
1883 return (true);
1884}
1885
1886#ifdef vtkGenericDataArray_h
1887#undef SetTupleValue
1888#undef InsertNextTupleValue
1889#undef GetTupleValue
1890#endif
1891
1892#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(FILE *stream, const std::string format, Args &&... args)
Print an error message on stream with colors.
Definition print.h:313
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:56
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
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.