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