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