Point Cloud Library (PCL) 1.15.1-dev
Loading...
Searching...
No Matches
pcl_visualizer.hpp
1/*
2 * Software License Agreement (BSD License)
3 *
4 * Point Cloud Library (PCL) - www.pointclouds.org
5 * Copyright (c) 2012, Open Perception, Inc.
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 * * Neither the name of the copyright holder(s) nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 *
36 */
37
38#ifndef PCL_PCL_VISUALIZER_IMPL_H_
39#define PCL_PCL_VISUALIZER_IMPL_H_
40
41#include <vtkVersion.h>
42#include <vtkSmartPointer.h>
43#include <vtkCellArray.h>
44#include <vtkLeaderActor2D.h>
45#include <vtkVectorText.h>
46#include <vtkAlgorithmOutput.h>
47#include <vtkFollower.h>
48#include <vtkLine.h>
49#include <vtkMath.h>
50#include <vtkSphereSource.h>
51#include <vtkProperty2D.h>
52#include <vtkDataSetSurfaceFilter.h>
53#include <vtkPointData.h>
54#include <vtkPolyDataMapper.h>
55#include <vtkProperty.h>
56#include <vtkMapper.h>
57#include <vtkCellData.h>
58#include <vtkDataSetMapper.h>
59#include <vtkRenderer.h>
60#include <vtkRendererCollection.h>
61#include <vtkAppendPolyData.h>
62#include <vtkTextProperty.h>
63#include <vtkLODActor.h>
64#include <vtkLineSource.h>
65
66#include <pcl/common/utils.h> // pcl::utils::ignore
68
69#include <cmath>
70
71// Support for VTK 7.1 upwards
72#ifdef vtkGenericDataArray_h
73#define SetTupleValue SetTypedTuple
74#define InsertNextTupleValue InsertNextTypedTuple
75#define GetTupleValue GetTypedTuple
76#endif
77
78//////////////////////////////////////////////////////////////////////////////////////////////
79template <typename PointT> bool
81 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
82 const std::string &id, int viewport)
83{
84 // Convert the PointCloud to VTK PolyData
85 PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
86 return (addPointCloud<PointT> (cloud, geometry_handler, id, viewport));
87}
88
89//////////////////////////////////////////////////////////////////////////////////////////////
90template <typename PointT> bool
92 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
93 const PointCloudGeometryHandler<PointT> &geometry_handler,
94 const std::string &id, int viewport)
95{
96 if (contains (id))
97 {
98 PCL_WARN ("[addPointCloud] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
99 return (false);
100 }
101
103 {
104 PointCloudColorHandlerRGBField<PointT> color_handler_rgb_field (cloud);
105 return (fromHandlersToScreen (geometry_handler, color_handler_rgb_field, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
106 }
107 PointCloudColorHandlerCustom<PointT> color_handler (cloud, 255, 255, 255);
108 return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
109}
110
111//////////////////////////////////////////////////////////////////////////////////////////////
112template <typename PointT> bool
114 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
115 const GeometryHandlerConstPtr &geometry_handler,
116 const std::string &id, int viewport)
117{
118 if (contains (id))
119 {
120 // Here we're just pushing the handlers onto the queue. If needed, something fancier could
121 // be done such as checking if a specific handler already exists, etc.
122 auto am_it = cloud_actor_map_->find (id);
123 am_it->second.geometry_handlers.push_back (geometry_handler);
124 return (true);
125 }
126
127 //PointCloudColorHandlerRandom<PointT> color_handler (cloud);
128 PointCloudColorHandlerCustom<PointT> color_handler (cloud, 255, 255, 255);
129 return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
130}
131
132//////////////////////////////////////////////////////////////////////////////////////////////
133template <typename PointT> bool
135 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
136 const PointCloudColorHandler<PointT> &color_handler,
137 const std::string &id, int viewport)
138{
139 if (contains (id))
140 {
141 PCL_WARN ("[addPointCloud] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
142
143 // Here we're just pushing the handlers onto the queue. If needed, something fancier could
144 // be done such as checking if a specific handler already exists, etc.
145 //cloud_actor_map_[id].color_handlers.push_back (color_handler);
146 //style_->setCloudActorMap (boost::make_shared<CloudActorMap> (cloud_actor_map_));
147 return (false);
148 }
149 // Convert the PointCloud to VTK PolyData
150 PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
151 return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
152}
153
154//////////////////////////////////////////////////////////////////////////////////////////////
155template <typename PointT> bool
157 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
158 const ColorHandlerConstPtr &color_handler,
159 const std::string &id, int viewport)
160{
161 // Check to see if this entry already exists (has it been already added to the visualizer?)
162 auto am_it = cloud_actor_map_->find (id);
163 if (am_it != cloud_actor_map_->end ())
164 {
165 // Here we're just pushing the handlers onto the queue. If needed, something fancier could
166 // be done such as checking if a specific handler already exists, etc.
167 am_it->second.color_handlers.push_back (color_handler);
168 return (true);
169 }
170
171 PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud);
172 return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
173}
174
175//////////////////////////////////////////////////////////////////////////////////////////////
176template <typename PointT> bool
178 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
179 const GeometryHandlerConstPtr &geometry_handler,
180 const ColorHandlerConstPtr &color_handler,
181 const std::string &id, int viewport)
182{
183 // Check to see if this entry already exists (has it been already added to the visualizer?)
184 auto am_it = cloud_actor_map_->find (id);
185 if (am_it != cloud_actor_map_->end ())
186 {
187 // Here we're just pushing the handlers onto the queue. If needed, something fancier could
188 // be done such as checking if a specific handler already exists, etc.
189 am_it->second.geometry_handlers.push_back (geometry_handler);
190 am_it->second.color_handlers.push_back (color_handler);
191 return (true);
192 }
193 return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
194}
195
196//////////////////////////////////////////////////////////////////////////////////////////////
197template <typename PointT> bool
199 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
200 const PointCloudColorHandler<PointT> &color_handler,
201 const PointCloudGeometryHandler<PointT> &geometry_handler,
202 const std::string &id, int viewport)
203{
204 if (contains (id))
205 {
206 PCL_WARN ("[addPointCloud] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
207 // Here we're just pushing the handlers onto the queue. If needed, something fancier could
208 // be done such as checking if a specific handler already exists, etc.
209 //cloud_actor_map_[id].geometry_handlers.push_back (geometry_handler);
210 //cloud_actor_map_[id].color_handlers.push_back (color_handler);
211 //style_->setCloudActorMap (boost::make_shared<CloudActorMap> (cloud_actor_map_));
212 return (false);
213 }
214 return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_));
215}
216
217//////////////////////////////////////////////////////////////////////////////////////////////
218template <typename PointT> void
219pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData (
220 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
223{
225 if (!polydata)
226 {
227 allocVtkPolyData (polydata);
229 polydata->SetVerts (vertices);
230 }
231
232 // Create the supporting structures
233#ifndef VTK_CELL_ARRAY_V2
234 vertices = polydata->GetVerts (); // Using the return value of GetVerts() in SetVerts() does not guarantee consistent internal data in polydata
235#endif
236 if (!vertices)
238
239 vtkIdType nr_points = cloud->size ();
240 // Create the point set
241 vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
242 if (!points)
243 {
245 points->SetDataTypeToFloat ();
246 polydata->SetPoints (points);
247 }
248 points->SetNumberOfPoints (nr_points);
249
250 // Get a pointer to the beginning of the data array
251 float *data = (dynamic_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
252
253 // Set the points
254 vtkIdType ptr = 0;
255 if (cloud->is_dense)
256 {
257 for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3) {
258 std::copy(&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
259 }
260 }
261 else
262 {
263 vtkIdType j = 0; // true point index
264 for (vtkIdType i = 0; i < nr_points; ++i)
265 {
266 // Check if the point is invalid
267 if (!pcl::isXYZFinite((*cloud)[i]))
268 continue;
269
270 std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
271 j++;
272 ptr += 3;
273 }
274 nr_points = j;
275 points->SetNumberOfPoints (nr_points);
276 }
277
278#ifdef VTK_CELL_ARRAY_V2
279 // TODO: Remove when VTK 6,7,8 is unsupported
280 pcl::utils::ignore(initcells);
281
282 auto numOfCells = vertices->GetNumberOfCells();
283
284 // If we have less cells than points, add new cells.
285 if (numOfCells < nr_points)
286 {
287 for (int i = numOfCells; i < nr_points; i++)
288 {
289 vertices->InsertNextCell(1);
290 vertices->InsertCellPoint(i);
291 }
292 }
293 // if we too many cells than points, set size (doesn't free excessive memory)
294 else if (numOfCells > nr_points)
295 {
296 vertices->ResizeExact(nr_points, nr_points);
297 }
298
299 polydata->SetPoints(points);
300 polydata->SetVerts(vertices);
301
302#else
303 vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
304 updateCells (cells, initcells, nr_points);
305
306 // Set the cells and the vertices
307 vertices->SetCells (nr_points, cells);
308
309 // Set the cell count explicitly as the array doesn't get modified enough so the above method updates accordingly. See #4001 and #3452
310 vertices->SetNumberOfCells(nr_points);
311#endif
312}
313
314//////////////////////////////////////////////////////////////////////////////////////////////
315template <typename PointT> void
316pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData (
320{
322 if (!polydata)
323 {
324 allocVtkPolyData (polydata);
326 polydata->SetVerts (vertices);
327 }
328
329 // Use the handler to obtain the geometry
331 geometry_handler.getGeometry (points);
332 polydata->SetPoints (points);
333
334 vtkIdType nr_points = points->GetNumberOfPoints ();
335
336 // Create the supporting structures
337#ifndef VTK_CELL_ARRAY_V2
338 vertices = polydata->GetVerts (); // Using the return value of GetVerts() in SetVerts() does not guarantee consistent internal data in polydata
339#endif
340 if (!vertices)
342
343#ifdef VTK_CELL_ARRAY_V2
344 // TODO: Remove when VTK 6,7,8 is unsupported
345 pcl::utils::ignore(initcells);
346
347 auto numOfCells = vertices->GetNumberOfCells();
348
349 // If we have less cells than points, add new cells.
350 if (numOfCells < nr_points)
351 {
352 for (int i = numOfCells; i < nr_points; i++)
353 {
354 vertices->InsertNextCell(1);
355 vertices->InsertCellPoint(i);
356 }
357 }
358 // if we too many cells than points, set size (doesn't free excessive memory)
359 else if (numOfCells > nr_points)
360 {
361 vertices->ResizeExact(nr_points, nr_points);
362 }
363
364 polydata->SetPoints(points);
365 polydata->SetVerts(vertices);
366
367#else
368 vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData ();
369 updateCells (cells, initcells, nr_points);
370 // Set the cells and the vertices
371 vertices->SetCells (nr_points, cells);
372#endif
373}
374
375////////////////////////////////////////////////////////////////////////////////////////////
376template <typename PointT> bool
378 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
379 double r, double g, double b, const std::string &id, int viewport)
380{
381 vtkSmartPointer<vtkDataSet> data = createPolygon<PointT> (cloud);
382 if (!data)
383 return (false);
384
385 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
386 auto am_it = shape_actor_map_->find (id);
387 if (am_it != shape_actor_map_->end ())
388 {
390
391 // Add old data
392 all_data->AddInputData (reinterpret_cast<vtkPolyDataMapper*> ((vtkActor::SafeDownCast (am_it->second))->GetMapper ())->GetInput ());
393
394 // Add new data
396 surface_filter->AddInputData (vtkUnstructuredGrid::SafeDownCast (data));
397 vtkSmartPointer<vtkPolyData> poly_data = surface_filter->GetOutput ();
398 all_data->AddInputData (poly_data);
399
400 // Create an Actor
402 createActorFromVTKDataSet (all_data->GetOutput (), actor);
403 actor->GetProperty ()->SetRepresentationToWireframe ();
404 actor->GetProperty ()->SetColor (r, g, b);
405 actor->GetMapper ()->ScalarVisibilityOff ();
406 removeActorFromRenderer (am_it->second, viewport);
407 addActorToRenderer (actor, viewport);
408
409 // Save the pointer/ID pair to the global actor map
410 (*shape_actor_map_)[id] = actor;
411 }
412 else
413 {
414 // Create an Actor
416 createActorFromVTKDataSet (data, actor);
417 actor->GetProperty ()->SetRepresentationToWireframe ();
418 actor->GetProperty ()->SetColor (r, g, b);
419 actor->GetMapper ()->ScalarVisibilityOff ();
420 addActorToRenderer (actor, viewport);
421
422 // Save the pointer/ID pair to the global actor map
423 (*shape_actor_map_)[id] = actor;
424 }
425
426 return (true);
427}
428
429////////////////////////////////////////////////////////////////////////////////////////////
430template <typename PointT> bool
432 const pcl::PlanarPolygon<PointT> &polygon,
433 double r, double g, double b, const std::string &id, int viewport)
434{
435 vtkSmartPointer<vtkDataSet> data = createPolygon<PointT> (polygon);
436 if (!data)
437 return (false);
438
439 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
440 auto am_it = shape_actor_map_->find (id);
441 if (am_it != shape_actor_map_->end ())
442 {
444
445 // Add old data
446 all_data->AddInputData (reinterpret_cast<vtkPolyDataMapper*> ((vtkActor::SafeDownCast (am_it->second))->GetMapper ())->GetInput ());
447
448 // Add new data
450 surface_filter->SetInputData (vtkUnstructuredGrid::SafeDownCast (data));
451 vtkSmartPointer<vtkPolyData> poly_data = surface_filter->GetOutput ();
452 all_data->AddInputData (poly_data);
453
454 // Create an Actor
456 createActorFromVTKDataSet (all_data->GetOutput (), actor);
457 actor->GetProperty ()->SetRepresentationToWireframe ();
458 actor->GetProperty ()->SetColor (r, g, b);
459 actor->GetMapper ()->ScalarVisibilityOn ();
460 actor->GetProperty ()->BackfaceCullingOff ();
461 removeActorFromRenderer (am_it->second, viewport);
462 addActorToRenderer (actor, viewport);
463
464 // Save the pointer/ID pair to the global actor map
465 (*shape_actor_map_)[id] = actor;
466 }
467 else
468 {
469 // Create an Actor
471 createActorFromVTKDataSet (data, actor);
472 actor->GetProperty ()->SetRepresentationToWireframe ();
473 actor->GetProperty ()->SetColor (r, g, b);
474 actor->GetMapper ()->ScalarVisibilityOn ();
475 actor->GetProperty ()->BackfaceCullingOff ();
476 addActorToRenderer (actor, viewport);
477
478 // Save the pointer/ID pair to the global actor map
479 (*shape_actor_map_)[id] = actor;
480 }
481 return (true);
482}
483
484////////////////////////////////////////////////////////////////////////////////////////////
485template <typename PointT> bool
487 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
488 const std::string &id, int viewport)
489{
490 return (addPolygon<PointT> (cloud, 0.5, 0.5, 0.5, id, viewport));
491}
492
493////////////////////////////////////////////////////////////////////////////////////////////
494template <typename P1, typename P2> bool
495pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
496{
497 if (contains (id))
498 {
499 PCL_WARN ("[addLine] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
500 return (false);
501 }
502
503 vtkSmartPointer<vtkDataSet> data = createLine (pt1.getVector4fMap (), pt2.getVector4fMap ());
504
505 // Create an Actor
507 createActorFromVTKDataSet (data, actor);
508 actor->GetProperty ()->SetRepresentationToWireframe ();
509 actor->GetProperty ()->SetColor (r, g, b);
510 actor->GetMapper ()->ScalarVisibilityOff ();
511 addActorToRenderer (actor, viewport);
512
513 // Save the pointer/ID pair to the global actor map
514 (*shape_actor_map_)[id] = actor;
515 return (true);
516}
517
518////////////////////////////////////////////////////////////////////////////////////////////
519template <typename P1, typename P2> bool
520pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport)
521{
522 if (contains (id))
523 {
524 PCL_WARN ("[addArrow] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
525 return (false);
526 }
527
528 // Create an Actor
530 leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
531 leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
532 leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
533 leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
534 leader->SetArrowStyleToFilled ();
535 leader->AutoLabelOn ();
536
537 leader->GetProperty ()->SetColor (r, g, b);
538 addActorToRenderer (leader, viewport);
539
540 // Save the pointer/ID pair to the global actor map
541 (*shape_actor_map_)[id] = leader;
542 return (true);
543}
544
545////////////////////////////////////////////////////////////////////////////////////////////
546template <typename P1, typename P2> bool
547pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2, double r, double g, double b, bool display_length, const std::string &id, int viewport)
548{
549 if (contains (id))
550 {
551 PCL_WARN ("[addArrow] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
552 return (false);
553 }
554
555 // Create an Actor
557 leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
558 leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
559 leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
560 leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
561 leader->SetArrowStyleToFilled ();
562 leader->SetArrowPlacementToPoint1 ();
563 if (display_length)
564 leader->AutoLabelOn ();
565 else
566 leader->AutoLabelOff ();
567
568 leader->GetProperty ()->SetColor (r, g, b);
569 addActorToRenderer (leader, viewport);
570
571 // Save the pointer/ID pair to the global actor map
572 (*shape_actor_map_)[id] = leader;
573 return (true);
574}
575////////////////////////////////////////////////////////////////////////////////////////////
576template <typename P1, typename P2> bool
578 double r_line, double g_line, double b_line,
579 double r_text, double g_text, double b_text,
580 const std::string &id, int viewport)
581{
582 if (contains (id))
583 {
584 PCL_WARN ("[addArrow] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
585 return (false);
586 }
587
588 // Create an Actor
590 leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld ();
591 leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z);
592 leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld ();
593 leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z);
594 leader->SetArrowStyleToFilled ();
595 leader->AutoLabelOn ();
596
597 leader->GetLabelTextProperty()->SetColor(r_text, g_text, b_text);
598
599 leader->GetProperty ()->SetColor (r_line, g_line, b_line);
600 addActorToRenderer (leader, viewport);
601
602 // Save the pointer/ID pair to the global actor map
603 (*shape_actor_map_)[id] = leader;
604 return (true);
605}
606
607////////////////////////////////////////////////////////////////////////////////////////////
608template <typename P1, typename P2> bool
609pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, const std::string &id, int viewport)
610{
611 return (addLine (pt1, pt2, 0.5, 0.5, 0.5, id, viewport));
612}
613
614////////////////////////////////////////////////////////////////////////////////////////////
615template <typename PointT> bool
616pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, double r, double g, double b, const std::string &id, int viewport)
617{
618 if (contains (id))
619 {
620 PCL_WARN ("[addSphere] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
621 return (false);
622 }
623
625 data->SetRadius (radius);
626 data->SetCenter (static_cast<double>(center.x), static_cast<double>(center.y), static_cast<double>(center.z));
627 data->SetPhiResolution (10);
628 data->SetThetaResolution (10);
629 data->LatLongTessellationOff ();
630 data->Update ();
631
632 // Setup actor and mapper
633 vtkSmartPointer <vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New ();
634 mapper->SetInputConnection (data->GetOutputPort ());
635
636 // Create an Actor
638 actor->SetMapper (mapper);
639 //createActorFromVTKDataSet (data, actor);
640 actor->GetProperty ()->SetRepresentationToSurface ();
641 actor->GetProperty ()->SetInterpolationToFlat ();
642 actor->GetProperty ()->SetColor (r, g, b);
643 actor->GetMapper ()->StaticOn ();
644 actor->GetMapper ()->ScalarVisibilityOff ();
645 actor->GetMapper ()->Update ();
646 addActorToRenderer (actor, viewport);
647
648 // Save the pointer/ID pair to the global actor map
649 (*shape_actor_map_)[id] = actor;
650 return (true);
651}
652
653////////////////////////////////////////////////////////////////////////////////////////////
654template <typename PointT> bool
655pcl::visualization::PCLVisualizer::addSphere (const PointT &center, double radius, const std::string &id, int viewport)
656{
657 return (addSphere (center, radius, 0.5, 0.5, 0.5, id, viewport));
658}
659
660////////////////////////////////////////////////////////////////////////////////////////////
661template<typename PointT> bool
662pcl::visualization::PCLVisualizer::updateSphere (const PointT &center, double radius, double r, double g, double b, const std::string &id)
663{
664 if (!contains (id))
665 {
666 return (false);
667 }
668
669 //////////////////////////////////////////////////////////////////////////
670 // Get the actor pointer
671 auto am_it = shape_actor_map_->find (id);
672 vtkLODActor* actor = vtkLODActor::SafeDownCast (am_it->second);
673 if (!actor)
674 return (false);
675 vtkAlgorithm *algo = actor->GetMapper ()->GetInputAlgorithm ();
676 vtkSphereSource *src = vtkSphereSource::SafeDownCast (algo);
677 if (!src)
678 return (false);
679
680 src->SetCenter (double (center.x), double (center.y), double (center.z));
681 src->SetRadius (radius);
682 src->Update ();
683 actor->GetProperty ()->SetColor (r, g, b);
684 actor->Modified ();
685
686 return (true);
687}
688
689//////////////////////////////////////////////////
690template <typename PointT> bool
692 const std::string &text,
693 const PointT& position,
694 double textScale,
695 double r,
696 double g,
697 double b,
698 const std::string &id,
699 int viewport)
700{
701 std::string tid;
702 if (id.empty ())
703 tid = text;
704 else
705 tid = id;
706
707 if (viewport < 0)
708 return false;
709
710 // If there is no custom viewport and the viewport number is not 0, exit
711 if (rens_->GetNumberOfItems () <= viewport)
712 {
713 PCL_ERROR ("[addText3D] The viewport [%d] doesn't exist (id <%s>)! \n",
714 viewport,
715 tid.c_str ());
716 return false;
717 }
718
719 // check all or an individual viewport for a similar id
720 rens_->InitTraversal ();
721 for (std::size_t i = viewport; rens_->GetNextItem (); ++i)
722 {
723 const std::string uid = tid + std::string (i, '*');
724 if (contains (uid))
725 {
726 PCL_ERROR ( "[addText3D] The id <%s> already exists in viewport [%d]! \n"
727 "Please choose a different id and retry.\n",
728 tid.c_str (),
729 i);
730 return false;
731 }
732
733 if (viewport > 0)
734 break;
735 }
736
738 textSource->SetText (text.c_str());
739 textSource->Update ();
740
742 textMapper->SetInputConnection (textSource->GetOutputPort ());
743
744 // Since each follower may follow a different camera, we need different followers
745 rens_->InitTraversal ();
746 vtkRenderer* renderer;
747 int i = 0;
748 while ((renderer = rens_->GetNextItem ()))
749 {
750 // Should we add the actor to all renderers or just to i-nth renderer?
751 if (viewport == 0 || viewport == i)
752 {
754 textActor->SetMapper (textMapper);
755 textActor->SetPosition (position.x, position.y, position.z);
756 textActor->SetScale (textScale);
757 textActor->GetProperty ()->SetColor (r, g, b);
758 textActor->SetCamera (renderer->GetActiveCamera ());
759
760 renderer->AddActor (textActor);
761
762 // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
763 // for multiple viewport
764 const std::string uid = tid + std::string (i, '*');
765 (*shape_actor_map_)[uid] = textActor;
766 }
767
768 ++i;
769 }
770
771 return (true);
772}
773
774//////////////////////////////////////////////////
775template <typename PointT> bool
777 const std::string &text,
778 const PointT& position,
779 double orientation[3],
780 double textScale,
781 double r,
782 double g,
783 double b,
784 const std::string &id,
785 int viewport)
786{
787 std::string tid;
788 if (id.empty ())
789 tid = text;
790 else
791 tid = id;
792
793 if (viewport < 0)
794 return false;
795
796 // If there is no custom viewport and the viewport number is not 0, exit
797 if (rens_->GetNumberOfItems () <= viewport)
798 {
799 PCL_ERROR ("[addText3D] The viewport [%d] doesn't exist (id <%s>)!\n",
800 viewport,
801 tid.c_str ());
802 return false;
803 }
804
805 // check all or an individual viewport for a similar id
806 rens_->InitTraversal ();
807 for (std::size_t i = viewport; rens_->GetNextItem (); ++i)
808 {
809 const std::string uid = tid + std::string (i, '*');
810 if (contains (uid))
811 {
812 PCL_ERROR ( "[addText3D] The id <%s> already exists in viewport [%d]! "
813 "Please choose a different id and retry.\n",
814 tid.c_str (),
815 i);
816 return false;
817 }
818
819 if (viewport > 0)
820 break;
821 }
822
824 textSource->SetText (text.c_str());
825 textSource->Update ();
826
828 textMapper->SetInputConnection (textSource->GetOutputPort ());
829
831 textActor->SetMapper (textMapper);
832 textActor->SetPosition (position.x, position.y, position.z);
833 textActor->SetScale (textScale);
834 textActor->GetProperty ()->SetColor (r, g, b);
835 textActor->SetOrientation (orientation);
836
837 // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
838 rens_->InitTraversal ();
839 int i = 0;
840 for ( vtkRenderer* renderer = rens_->GetNextItem ();
841 renderer;
842 renderer = rens_->GetNextItem (), ++i)
843 {
844 if (viewport == 0 || viewport == i)
845 {
846 renderer->AddActor (textActor);
847 const std::string uid = tid + std::string (i, '*');
848 (*shape_actor_map_)[uid] = textActor;
849 }
850 }
851
852 return (true);
853}
854
855//////////////////////////////////////////////////////////////////////////////////////////////
856template <typename PointNT> bool
858 const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
859 int level, float scale, const std::string &id, int viewport)
860{
861 return (addPointCloudNormals<PointNT, PointNT> (cloud, cloud, level, scale, id, viewport));
862}
863
864//////////////////////////////////////////////////////////////////////////////////////////////
865template <typename PointT, typename PointNT> bool
867 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
868 const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
869 int level, float scale,
870 const std::string &id, int viewport)
871{
872 if (normals->size () != cloud->size ())
873 {
874 PCL_ERROR ("[addPointCloudNormals] The number of points differs from the number of normals!\n");
875 return (false);
876 }
877
878 if (normals->empty ())
879 {
880 PCL_WARN ("[addPointCloudNormals] An empty normal cloud is given! Nothing to display.\n");
881 return (false);
882 }
883
884 if (contains (id))
885 {
886 PCL_WARN ("[addPointCloudNormals] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
887 return (false);
888 }
889
892
893 points->SetDataTypeToFloat ();
895 data->SetNumberOfComponents (3);
896
897
898 vtkIdType nr_normals = 0;
899 float* pts = nullptr;
900
901 // If the cloud is organized, then distribute the normal step in both directions
902 if (cloud->isOrganized () && normals->isOrganized ())
903 {
904 auto point_step = static_cast<vtkIdType> (sqrt (static_cast<double>(level)));
905 nr_normals = (static_cast<vtkIdType> ((cloud->width - 1)/ point_step) + 1) *
906 (static_cast<vtkIdType> ((cloud->height - 1) / point_step) + 1);
907 pts = new float[2 * nr_normals * 3];
908
909 vtkIdType cell_count = 0;
910 for (vtkIdType y = 0; y < normals->height; y += point_step)
911 for (vtkIdType x = 0; x < normals->width; x += point_step)
912 {
913 PointT p = (*cloud)(x, y);
914 if (!pcl::isFinite(p) || !pcl::isNormalFinite((*normals)(x, y)))
915 continue;
916 p.x += (*normals)(x, y).normal[0] * scale;
917 p.y += (*normals)(x, y).normal[1] * scale;
918 p.z += (*normals)(x, y).normal[2] * scale;
919
920 pts[2 * cell_count * 3 + 0] = (*cloud)(x, y).x;
921 pts[2 * cell_count * 3 + 1] = (*cloud)(x, y).y;
922 pts[2 * cell_count * 3 + 2] = (*cloud)(x, y).z;
923 pts[2 * cell_count * 3 + 3] = p.x;
924 pts[2 * cell_count * 3 + 4] = p.y;
925 pts[2 * cell_count * 3 + 5] = p.z;
926
927 lines->InsertNextCell (2);
928 lines->InsertCellPoint (2 * cell_count);
929 lines->InsertCellPoint (2 * cell_count + 1);
930 cell_count ++;
931 }
932 nr_normals = cell_count;
933 }
934 else
935 {
936 nr_normals = (cloud->size () - 1) / level + 1 ;
937 pts = new float[2 * nr_normals * 3];
938
939 vtkIdType j = 0;
940 for (vtkIdType i = 0; (j < nr_normals) && (i < static_cast<vtkIdType>(cloud->size())); i += level)
941 {
942 if (!pcl::isFinite((*cloud)[i]) || !pcl::isNormalFinite((*normals)[i]))
943 continue;
944 PointT p = (*cloud)[i];
945 p.x += (*normals)[i].normal[0] * scale;
946 p.y += (*normals)[i].normal[1] * scale;
947 p.z += (*normals)[i].normal[2] * scale;
948
949 pts[2 * j * 3 + 0] = (*cloud)[i].x;
950 pts[2 * j * 3 + 1] = (*cloud)[i].y;
951 pts[2 * j * 3 + 2] = (*cloud)[i].z;
952 pts[2 * j * 3 + 3] = p.x;
953 pts[2 * j * 3 + 4] = p.y;
954 pts[2 * j * 3 + 5] = p.z;
955
956 lines->InsertNextCell (2);
957 lines->InsertCellPoint (2 * j);
958 lines->InsertCellPoint (2 * j + 1);
959 ++j;
960 }
961 nr_normals = j;
962 }
963
964 data->SetArray (&pts[0], 2 * nr_normals * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
965 points->SetData (data);
966
968 polyData->SetPoints (points);
969 polyData->SetLines (lines);
970
972 mapper->SetInputData (polyData);
973 mapper->SetColorModeToMapScalars();
974 mapper->SetScalarModeToUsePointData();
975
976 // create actor
978 actor->SetMapper (mapper);
979
980 // Use cloud view point info
982 convertToVtkMatrix (cloud->sensor_origin_, cloud->sensor_orientation_, transformation);
983 actor->SetUserMatrix (transformation);
984
985 // Add it to all renderers
986 addActorToRenderer (actor, viewport);
987
988 // Save the pointer/ID pair to the global actor map
989 (*cloud_actor_map_)[id].actor = actor;
990 return (true);
991}
992
993//////////////////////////////////////////////////////////////////////////////////////////////
994template <typename PointNT> bool
996 const typename pcl::PointCloud<PointNT>::ConstPtr &cloud,
998 int level, float scale,
999 const std::string &id, int viewport)
1000{
1001 return (addPointCloudPrincipalCurvatures<PointNT, PointNT> (cloud, cloud, pcs, level, scale, id, viewport));
1002}
1003
1004//////////////////////////////////////////////////////////////////////////////////////////////
1005template <typename PointT, typename PointNT> bool
1007 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1008 const typename pcl::PointCloud<PointNT>::ConstPtr &normals,
1010 int level, float scale,
1011 const std::string &id, int viewport)
1012{
1013 if (pcs->size () != cloud->size () || normals->size () != cloud->size ())
1014 {
1015 pcl::console::print_error ("[addPointCloudPrincipalCurvatures] The number of points differs from the number of principal curvatures/normals!\n");
1016 return (false);
1017 }
1018
1019 if (contains (id))
1020 {
1021 PCL_WARN ("[addPointCloudPrincipalCurvatures] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1022 return (false);
1023 }
1024
1027
1028 // Setup two colors - one for each line
1029 unsigned char green[3] = {0, 255, 0};
1030 unsigned char blue[3] = {0, 0, 255};
1031
1032 // Setup the colors array
1034 line_1_colors->SetNumberOfComponents (3);
1035 line_1_colors->SetName ("Colors");
1037 line_2_colors->SetNumberOfComponents (3);
1038 line_2_colors->SetName ("Colors");
1039
1040 // Create the first sets of lines
1041 for (std::size_t i = 0; i < cloud->size (); i+=level)
1042 {
1043 PointT p = (*cloud)[i];
1044 p.x += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[0]) * scale;
1045 p.y += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[1]) * scale;
1046 p.z += ((*pcs)[i].pc1 * (*pcs)[i].principal_curvature[2]) * scale;
1047
1049 line_1->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1050 line_1->SetPoint2 (p.x, p.y, p.z);
1051 line_1->Update ();
1052 polydata_1->AddInputData (line_1->GetOutput ());
1053 line_1_colors->InsertNextTupleValue (green);
1054 }
1055 polydata_1->Update ();
1056 vtkSmartPointer<vtkPolyData> line_1_data = polydata_1->GetOutput ();
1057 line_1_data->GetCellData ()->SetScalars (line_1_colors);
1058
1059 // Create the second sets of lines
1060 for (std::size_t i = 0; i < cloud->size (); i += level)
1061 {
1062 Eigen::Vector3f pc ((*pcs)[i].principal_curvature[0],
1063 (*pcs)[i].principal_curvature[1],
1064 (*pcs)[i].principal_curvature[2]);
1065 Eigen::Vector3f normal ((*normals)[i].normal[0],
1066 (*normals)[i].normal[1],
1067 (*normals)[i].normal[2]);
1068 Eigen::Vector3f pc_c = pc.cross (normal);
1069
1070 PointT p = (*cloud)[i];
1071 p.x += ((*pcs)[i].pc2 * pc_c[0]) * scale;
1072 p.y += ((*pcs)[i].pc2 * pc_c[1]) * scale;
1073 p.z += ((*pcs)[i].pc2 * pc_c[2]) * scale;
1074
1076 line_2->SetPoint1 ((*cloud)[i].x, (*cloud)[i].y, (*cloud)[i].z);
1077 line_2->SetPoint2 (p.x, p.y, p.z);
1078 line_2->Update ();
1079 polydata_2->AddInputData (line_2->GetOutput ());
1080
1081 line_2_colors->InsertNextTupleValue (blue);
1082 }
1083 polydata_2->Update ();
1084 vtkSmartPointer<vtkPolyData> line_2_data = polydata_2->GetOutput ();
1085 line_2_data->GetCellData ()->SetScalars (line_2_colors);
1086
1087 // Assemble the two sets of lines
1089 alldata->AddInputData (line_1_data);
1090 alldata->AddInputData (line_2_data);
1091 alldata->Update ();
1092
1093 // Create an Actor
1095 createActorFromVTKDataSet (alldata->GetOutput (), actor);
1096 actor->GetMapper ()->SetScalarModeToUseCellData ();
1097
1098 // Add it to all renderers
1099 addActorToRenderer (actor, viewport);
1100
1101 // Save the pointer/ID pair to the global actor map
1102 CloudActor act;
1103 act.actor = actor;
1104 (*cloud_actor_map_)[id] = act;
1105 return (true);
1106}
1107
1108//////////////////////////////////////////////////////////////////////////////////////////////
1109template <typename PointT, typename GradientT> bool
1111 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1112 const typename pcl::PointCloud<GradientT>::ConstPtr &gradients,
1113 int level, double scale,
1114 const std::string &id, int viewport)
1115{
1116 if (gradients->size () != cloud->size ())
1117 {
1118 PCL_ERROR ("[addPointCloudGradients] The number of points differs from the number of gradients!\n");
1119 return (false);
1120 }
1121 if (contains (id))
1122 {
1123 PCL_WARN ("[addPointCloudGradients] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1124 return (false);
1125 }
1126
1129
1130 points->SetDataTypeToFloat ();
1132 data->SetNumberOfComponents (3);
1133
1134 vtkIdType nr_gradients = (cloud->size () - 1) / level + 1 ;
1135 float* pts = new float[2 * nr_gradients * 3];
1136
1137 for (vtkIdType i = 0, j = 0; j < nr_gradients; j++, i = j * level)
1138 {
1139 PointT p = (*cloud)[i];
1140 p.x += (*gradients)[i].gradient[0] * scale;
1141 p.y += (*gradients)[i].gradient[1] * scale;
1142 p.z += (*gradients)[i].gradient[2] * scale;
1143
1144 pts[2 * j * 3 + 0] = (*cloud)[i].x;
1145 pts[2 * j * 3 + 1] = (*cloud)[i].y;
1146 pts[2 * j * 3 + 2] = (*cloud)[i].z;
1147 pts[2 * j * 3 + 3] = p.x;
1148 pts[2 * j * 3 + 4] = p.y;
1149 pts[2 * j * 3 + 5] = p.z;
1150
1151 lines->InsertNextCell(2);
1152 lines->InsertCellPoint(2*j);
1153 lines->InsertCellPoint(2*j+1);
1154 }
1155
1156 data->SetArray (&pts[0], 2 * nr_gradients * 3, 0, vtkFloatArray::VTK_DATA_ARRAY_DELETE);
1157 points->SetData (data);
1158
1160 polyData->SetPoints(points);
1161 polyData->SetLines(lines);
1162
1164 mapper->SetInputData (polyData);
1165 mapper->SetColorModeToMapScalars();
1166 mapper->SetScalarModeToUsePointData();
1167
1168 // create actor
1170 actor->SetMapper (mapper);
1171
1172 // Add it to all renderers
1173 addActorToRenderer (actor, viewport);
1174
1175 // Save the pointer/ID pair to the global actor map
1176 (*cloud_actor_map_)[id].actor = actor;
1177 return (true);
1178}
1179
1180//////////////////////////////////////////////////////////////////////////////////////////////
1181template <typename PointT> bool
1183 const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1184 const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1185 const std::vector<int> &correspondences,
1186 const std::string &id,
1187 int viewport)
1188{
1190 corrs.resize (correspondences.size ());
1191
1192 std::size_t index = 0;
1193 for (auto &corr : corrs)
1194 {
1195 corr.index_query = index;
1196 corr.index_match = correspondences[index];
1197 index++;
1198 }
1199
1200 return (addCorrespondences<PointT> (source_points, target_points, corrs, id, viewport));
1201}
1202
1203//////////////////////////////////////////////////////////////////////////////////////////////
1204template <typename PointT> bool
1206 const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1207 const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1208 const pcl::Correspondences &correspondences,
1209 int nth,
1210 const std::string &id,
1211 int viewport,
1212 bool overwrite)
1213{
1214 if (correspondences.empty ())
1215 {
1216 PCL_DEBUG ("[addCorrespondences] An empty set of correspondences given! Nothing to display.\n");
1217 return (false);
1218 }
1219
1220 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1221 auto am_it = shape_actor_map_->find (id);
1222 if (am_it != shape_actor_map_->end () && !overwrite)
1223 {
1224 PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1225 return (false);
1226 }
1227 if (am_it == shape_actor_map_->end () && overwrite)
1228 {
1229 overwrite = false; // Correspondences doesn't exist, add them instead of updating them
1230 }
1231
1232 Eigen::Affine3f source_transformation;
1233 source_transformation.linear () = source_points->sensor_orientation_.matrix ();
1234 source_transformation.translation () = source_points->sensor_origin_.template head<3> ();
1235 Eigen::Affine3f target_transformation;
1236 target_transformation.linear () = target_points->sensor_orientation_.matrix ();
1237 target_transformation.translation () = target_points->sensor_origin_.template head<3> ();
1238
1239 const int n_corr = static_cast<int>(std::ceil(static_cast<float>(correspondences.size ()) / nth));
1241
1242 // Prepare colors
1244 line_colors->SetNumberOfComponents (3);
1245 line_colors->SetName ("Colors");
1246 line_colors->SetNumberOfTuples (n_corr);
1247
1248 // Prepare coordinates
1251
1252#if VTK_MAJOR_VERSION > 9 || (VTK_MAJOR_VERSION == 9 && VTK_MINOR_VERSION >= 6)
1253 int j = 0;
1254 // Draw lines between the best corresponding points
1255 for (std::size_t i = 0; i < correspondences.size (); i += nth)
1256 {
1257 if (correspondences[i].index_match == UNAVAILABLE)
1258 {
1259 PCL_WARN ("[addCorrespondences] No valid index_match for correspondence %d\n", i);
1260 continue;
1261 }
1262
1263 PointT p_src ((*source_points)[correspondences[i].index_query]);
1264 PointT p_tgt ((*target_points)[correspondences[i].index_match]);
1265
1266 p_src.getVector3fMap () = source_transformation * p_src.getVector3fMap ();
1267 p_tgt.getVector3fMap () = target_transformation * p_tgt.getVector3fMap ();
1268
1269 int id1 = j * 2, id2 = j * 2 + 1;
1270 // Set the points
1271 line_points->InsertNextPoint(p_src.x, p_src.y, p_src.z);
1272 line_points->InsertNextPoint(p_tgt.x, p_tgt.y, p_tgt.z);
1273
1274 vtkNew<vtkLine> line;
1275 line->GetPointIds()->SetId(0, id1);
1276 line->GetPointIds()->SetId(1, id2);
1277 line_cells->InsertNextCell(line);
1278
1279 float rgb[3];
1280 rgb[0] = vtkMath::Random (32, 255); // min / max
1281 rgb[1] = vtkMath::Random (32, 255);
1282 rgb[2] = vtkMath::Random (32, 255);
1283 line_colors->InsertTuple (j, rgb);
1284 ++j;
1285 }
1286 line_colors->SetNumberOfTuples (j);
1287 line_data->SetPoints (line_points);
1288 line_data->SetLines (line_cells);
1289 line_data->GetCellData ()->SetScalars (line_colors);
1290#else
1291 line_points->SetNumberOfPoints (2 * n_corr);
1293 line_cells_id->SetNumberOfComponents (3);
1294 line_cells_id->SetNumberOfTuples (n_corr);
1295 vtkIdType *line_cell_id = line_cells_id->GetPointer (0);
1296
1298 line_tcoords->SetNumberOfComponents (1);
1299 line_tcoords->SetNumberOfTuples (n_corr * 2);
1300 line_tcoords->SetName ("Texture Coordinates");
1301
1302 double tc[3] = {0.0, 0.0, 0.0};
1303
1304 int j = 0;
1305 // Draw lines between the best corresponding points
1306 for (std::size_t i = 0; i < correspondences.size (); i += nth)
1307 {
1308 if (correspondences[i].index_match == UNAVAILABLE)
1309 {
1310 PCL_WARN ("[addCorrespondences] No valid index_match for correspondence %d\n", i);
1311 continue;
1312 }
1313
1314 PointT p_src ((*source_points)[correspondences[i].index_query]);
1315 PointT p_tgt ((*target_points)[correspondences[i].index_match]);
1316
1317 p_src.getVector3fMap () = source_transformation * p_src.getVector3fMap ();
1318 p_tgt.getVector3fMap () = target_transformation * p_tgt.getVector3fMap ();
1319
1320 int id1 = j * 2 + 0, id2 = j * 2 + 1;
1321 // Set the points
1322 line_points->SetPoint (id1, p_src.x, p_src.y, p_src.z);
1323 line_points->SetPoint (id2, p_tgt.x, p_tgt.y, p_tgt.z);
1324 // Set the cell ID
1325 *line_cell_id++ = 2;
1326 *line_cell_id++ = id1;
1327 *line_cell_id++ = id2;
1328 // Set the texture coords
1329 tc[0] = 0.; line_tcoords->SetTuple (id1, tc);
1330 tc[0] = 1.; line_tcoords->SetTuple (id2, tc);
1331
1332 float rgb[3];
1333 rgb[0] = vtkMath::Random (32, 255); // min / max
1334 rgb[1] = vtkMath::Random (32, 255);
1335 rgb[2] = vtkMath::Random (32, 255);
1336 line_colors->InsertTuple (j, rgb);
1337 ++j;
1338 }
1339 line_colors->SetNumberOfTuples (j);
1340 line_cells_id->SetNumberOfTuples (j);
1341 line_cells->SetCells (j, line_cells_id);
1342 line_points->SetNumberOfPoints (j*2);
1343 line_tcoords->SetNumberOfTuples (j*2);
1344
1345 // Fill in the lines
1346 line_data->SetPoints (line_points);
1347 line_data->SetLines (line_cells);
1348 line_data->GetPointData ()->SetTCoords (line_tcoords);
1349 line_data->GetCellData ()->SetScalars (line_colors);
1350#endif
1351
1352 // Create an Actor
1353 if (!overwrite)
1354 {
1356 createActorFromVTKDataSet (line_data, actor);
1357 actor->GetProperty ()->SetRepresentationToWireframe ();
1358 actor->GetProperty ()->SetOpacity (0.5);
1359 addActorToRenderer (actor, viewport);
1360
1361 // Save the pointer/ID pair to the global actor map
1362 (*shape_actor_map_)[id] = actor;
1363 }
1364 else
1365 {
1366 vtkSmartPointer<vtkLODActor> actor = vtkLODActor::SafeDownCast (am_it->second);
1367 if (!actor)
1368 return (false);
1369 // Update the mapper
1370 reinterpret_cast<vtkPolyDataMapper*> (actor->GetMapper ())->SetInputData (line_data);
1371 }
1372
1373 return (true);
1374}
1375
1376//////////////////////////////////////////////////////////////////////////////////////////////
1377template <typename PointT> bool
1379 const typename pcl::PointCloud<PointT>::ConstPtr &source_points,
1380 const typename pcl::PointCloud<PointT>::ConstPtr &target_points,
1381 const pcl::Correspondences &correspondences,
1382 int nth,
1383 const std::string &id,
1384 int viewport)
1385{
1386 return (addCorrespondences<PointT> (source_points, target_points, correspondences, nth, id, viewport, true));
1387}
1388
1389//////////////////////////////////////////////////////////////////////////////////////////////
1390template <typename PointT> bool
1391pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1392 const PointCloudGeometryHandler<PointT> &geometry_handler,
1393 const PointCloudColorHandler<PointT> &color_handler,
1394 const std::string &id,
1395 int viewport,
1396 const Eigen::Vector4f& sensor_origin,
1397 const Eigen::Quaternion<float>& sensor_orientation)
1398{
1399 if (!geometry_handler.isCapable ())
1400 {
1401 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1402 return (false);
1403 }
1404
1405 if (!color_handler.isCapable ())
1406 {
1407 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1408 return (false);
1409 }
1410
1413 // Convert the PointCloud to VTK PolyData
1414 convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1415
1416 // Get the colors from the handler
1417 bool has_colors = false;
1418 double minmax[2];
1419 if (auto scalars = color_handler.getColor ())
1420 {
1421 polydata->GetPointData ()->SetScalars (scalars);
1422 scalars->GetRange (minmax);
1423 has_colors = true;
1424 }
1425
1426 // Create an Actor
1428 createActorFromVTKDataSet (polydata, actor);
1429 if (has_colors)
1430 actor->GetMapper ()->SetScalarRange (minmax);
1431
1432 // Add it to all renderers
1433 addActorToRenderer (actor, viewport);
1434
1435 // Save the pointer/ID pair to the global actor map
1436 CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1437 cloud_actor.actor = actor;
1438 cloud_actor.cells = initcells;
1439
1440 // Save the viewpoint transformation matrix to the global actor map
1442 convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1443 cloud_actor.viewpoint_transformation_ = transformation;
1444 cloud_actor.actor->SetUserMatrix (transformation);
1445 cloud_actor.actor->Modified ();
1446
1447 return (true);
1448}
1449
1450//////////////////////////////////////////////////////////////////////////////////////////////
1451template <typename PointT> bool
1452pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1453 const PointCloudGeometryHandler<PointT> &geometry_handler,
1454 const ColorHandlerConstPtr &color_handler,
1455 const std::string &id,
1456 int viewport,
1457 const Eigen::Vector4f& sensor_origin,
1458 const Eigen::Quaternion<float>& sensor_orientation)
1459{
1460 if (!geometry_handler.isCapable ())
1461 {
1462 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ());
1463 return (false);
1464 }
1465
1466 if (!color_handler->isCapable ())
1467 {
1468 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler->getName ().c_str ());
1469 return (false);
1470 }
1471
1474 // Convert the PointCloud to VTK PolyData
1475 convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells);
1476 // use the given geometry handler
1477
1478 // Get the colors from the handler
1479 bool has_colors = false;
1480 double minmax[2];
1481 if (auto scalars = color_handler->getColor ())
1482 {
1483 polydata->GetPointData ()->SetScalars (scalars);
1484 scalars->GetRange (minmax);
1485 has_colors = true;
1486 }
1487
1488 // Create an Actor
1490 createActorFromVTKDataSet (polydata, actor);
1491 if (has_colors)
1492 actor->GetMapper ()->SetScalarRange (minmax);
1493
1494 // Add it to all renderers
1495 addActorToRenderer (actor, viewport);
1496
1497 // Save the pointer/ID pair to the global actor map
1498 CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1499 cloud_actor.actor = actor;
1500 cloud_actor.cells = initcells;
1501 cloud_actor.color_handlers.push_back (color_handler);
1502
1503 // Save the viewpoint transformation matrix to the global actor map
1505 convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1506 cloud_actor.viewpoint_transformation_ = transformation;
1507 cloud_actor.actor->SetUserMatrix (transformation);
1508 cloud_actor.actor->Modified ();
1509
1510 return (true);
1511}
1512
1513//////////////////////////////////////////////////////////////////////////////////////////////
1514template <typename PointT> bool
1515pcl::visualization::PCLVisualizer::fromHandlersToScreen (
1516 const GeometryHandlerConstPtr &geometry_handler,
1517 const PointCloudColorHandler<PointT> &color_handler,
1518 const std::string &id,
1519 int viewport,
1520 const Eigen::Vector4f& sensor_origin,
1521 const Eigen::Quaternion<float>& sensor_orientation)
1522{
1523 if (!geometry_handler->isCapable ())
1524 {
1525 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler->getName ().c_str ());
1526 return (false);
1527 }
1528
1529 if (!color_handler.isCapable ())
1530 {
1531 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ());
1532 return (false);
1533 }
1534
1537 // Convert the PointCloud to VTK PolyData
1538 convertPointCloudToVTKPolyData (geometry_handler, polydata, initcells);
1539 // use the given geometry handler
1540
1541 // Get the colors from the handler
1542 bool has_colors = false;
1543 double minmax[2];
1544 if (auto scalars = color_handler.getColor ())
1545 {
1546 polydata->GetPointData ()->SetScalars (scalars);
1547 scalars->GetRange (minmax);
1548 has_colors = true;
1549 }
1550
1551 // Create an Actor
1553 createActorFromVTKDataSet (polydata, actor);
1554 if (has_colors)
1555 actor->GetMapper ()->SetScalarRange (minmax);
1556
1557 // Add it to all renderers
1558 addActorToRenderer (actor, viewport);
1559
1560 // Save the pointer/ID pair to the global actor map
1561 CloudActor& cloud_actor = (*cloud_actor_map_)[id];
1562 cloud_actor.actor = actor;
1563 cloud_actor.cells = initcells;
1564 cloud_actor.geometry_handlers.push_back (geometry_handler);
1565
1566 // Save the viewpoint transformation matrix to the global actor map
1568 convertToVtkMatrix (sensor_origin, sensor_orientation, transformation);
1569 cloud_actor.viewpoint_transformation_ = transformation;
1570 cloud_actor.actor->SetUserMatrix (transformation);
1571 cloud_actor.actor->Modified ();
1572
1573 return (true);
1574}
1575
1576//////////////////////////////////////////////////////////////////////////////////////////////
1577template <typename PointT> bool
1579 const std::string &id)
1580{
1581 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1582 auto am_it = cloud_actor_map_->find (id);
1583
1584 if (am_it == cloud_actor_map_->end ())
1585 return (false);
1586
1587 vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1588 if (!polydata)
1589 return false;
1590 // Convert the PointCloud to VTK PolyData
1591 convertPointCloudToVTKPolyData<PointT> (cloud, polydata, am_it->second.cells);
1592
1593 // Set scalars to blank, since there is no way we can update them here.
1595 polydata->GetPointData ()->SetScalars (scalars);
1596 double minmax[2];
1597 minmax[0] = std::numeric_limits<double>::min ();
1598 minmax[1] = std::numeric_limits<double>::max ();
1599 am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1600
1601 // Update the mapper
1602 reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1603 return (true);
1604}
1605
1606/////////////////////////////////////////////////////////////////////////////////////////////
1607template <typename PointT> bool
1609 const PointCloudGeometryHandler<PointT> &geometry_handler,
1610 const std::string &id)
1611{
1612 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1613 auto am_it = cloud_actor_map_->find (id);
1614
1615 if (am_it == cloud_actor_map_->end ())
1616 return (false);
1617
1618 vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1619 if (!polydata)
1620 return (false);
1621 // Convert the PointCloud to VTK PolyData
1622 convertPointCloudToVTKPolyData (geometry_handler, polydata, am_it->second.cells);
1623
1624 // Set scalars to blank, since there is no way we can update them here.
1626 polydata->GetPointData ()->SetScalars (scalars);
1627 double minmax[2];
1628 minmax[0] = std::numeric_limits<double>::min ();
1629 minmax[1] = std::numeric_limits<double>::max ();
1630 am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1631
1632 // Update the mapper
1633 reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1634 return (true);
1635}
1636
1637
1638/////////////////////////////////////////////////////////////////////////////////////////////
1639template <typename PointT> bool
1641 const PointCloudColorHandler<PointT> &color_handler,
1642 const std::string &id)
1643{
1644 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1645 auto am_it = cloud_actor_map_->find (id);
1646
1647 if (am_it == cloud_actor_map_->end ())
1648 return (false);
1649
1650 // Get the current poly data
1651 vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
1652 if (!polydata)
1653 return (false);
1654
1655 convertPointCloudToVTKPolyData<PointT>(cloud, polydata, am_it->second.cells);
1656
1657 // Get the colors from the handler
1658 bool has_colors = false;
1659 double minmax[2];
1660 if (auto scalars = color_handler.getColor ())
1661 {
1662 // Update the data
1663 polydata->GetPointData ()->SetScalars (scalars);
1664 scalars->GetRange (minmax);
1665 has_colors = true;
1666 }
1667
1668 if (has_colors)
1669 am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
1670
1671 // Update the mapper
1672 reinterpret_cast<vtkPolyDataMapper*> (am_it->second.actor->GetMapper ())->SetInputData (polydata);
1673 return (true);
1674}
1675
1676/////////////////////////////////////////////////////////////////////////////////////////////
1677template <typename PointT> bool
1679 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1680 const std::vector<pcl::Vertices> &vertices,
1681 const std::string &id,
1682 int viewport)
1683{
1684 if (vertices.empty () || cloud->points.empty ())
1685 return (false);
1686
1687 if (contains (id))
1688 {
1689 PCL_WARN ("[addPolygonMesh] The id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
1690 return (false);
1691 }
1692
1693 int rgb_idx = -1;
1694 std::vector<pcl::PCLPointField> fields;
1696 rgb_idx = pcl::getFieldIndex<PointT> ("rgb", fields);
1697 if (rgb_idx == -1)
1698 rgb_idx = pcl::getFieldIndex<PointT> ("rgba", fields);
1699 if (rgb_idx != -1)
1700 {
1702 colors->SetNumberOfComponents (3);
1703 colors->SetName ("Colors");
1704 std::uint32_t offset = fields[rgb_idx].offset;
1705 for (std::size_t i = 0; i < cloud->size (); ++i)
1706 {
1707 if (!isFinite ((*cloud)[i]))
1708 continue;
1709 const auto* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
1710 unsigned char color[3];
1711 color[0] = rgb_data->r;
1712 color[1] = rgb_data->g;
1713 color[2] = rgb_data->b;
1714 colors->InsertNextTupleValue (color);
1715 }
1716 }
1717
1718 // Create points from polyMesh.cloud
1720 vtkIdType nr_points = cloud->size ();
1721 points->SetNumberOfPoints (nr_points);
1723
1724 // Get a pointer to the beginning of the data array
1725 float *data = dynamic_cast<vtkFloatArray*> (points->GetData ())->GetPointer (0);
1726
1727 vtkIdType ptr = 0;
1728 std::vector<int> lookup;
1729 // If the dataset is dense (no NaNs)
1730 if (cloud->is_dense)
1731 {
1732 for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3) {
1733 std::copy(&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1734 }
1735 }
1736 else
1737 {
1738 lookup.resize (nr_points);
1739 vtkIdType j = 0; // true point index
1740 for (vtkIdType i = 0; i < nr_points; ++i)
1741 {
1742 // Check if the point is invalid
1743 if (!isFinite ((*cloud)[i]))
1744 continue;
1745
1746 lookup[i] = static_cast<int> (j);
1747 std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1748 j++;
1749 ptr += 3;
1750 }
1751 nr_points = j;
1752 points->SetNumberOfPoints (nr_points);
1753 }
1754
1755 // Get the maximum size of a polygon
1756 int max_size_of_polygon = -1;
1757 for (const auto &vertex : vertices)
1758 if (max_size_of_polygon < static_cast<int> (vertex.vertices.size ()))
1759 max_size_of_polygon = static_cast<int> (vertex.vertices.size ());
1760
1761 if (vertices.size () > 1)
1762 {
1763 // Create polys from polyMesh.polygons
1765
1766 details::fillCells(lookup,vertices,cell_array, max_size_of_polygon);
1767
1769 allocVtkPolyData (polydata);
1770 cell_array->Squeeze ();
1771 polydata->SetPolys (cell_array);
1772 polydata->SetPoints (points);
1773
1774 if (colors)
1775 polydata->GetPointData ()->SetScalars (colors);
1776
1777 createActorFromVTKDataSet (polydata, actor, false);
1778 }
1779 else
1780 {
1782 std::size_t n_points = vertices[0].vertices.size ();
1783 polygon->GetPointIds ()->SetNumberOfIds (n_points - 1);
1784
1785 if (!lookup.empty ())
1786 {
1787 for (std::size_t j = 0; j < (n_points - 1); ++j)
1788 polygon->GetPointIds ()->SetId (j, lookup[vertices[0].vertices[j]]);
1789 }
1790 else
1791 {
1792 for (std::size_t j = 0; j < (n_points - 1); ++j)
1793 polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]);
1794 }
1796 allocVtkUnstructuredGrid (poly_grid);
1797 poly_grid->Allocate (1, 1);
1798 poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ());
1799 poly_grid->SetPoints (points);
1800 if (colors)
1801 poly_grid->GetPointData ()->SetScalars (colors);
1802
1803 createActorFromVTKDataSet (poly_grid, actor, false);
1804 }
1805 addActorToRenderer (actor, viewport);
1806 actor->GetProperty ()->SetRepresentationToSurface ();
1807 // Backface culling renders the visualization slower, but guarantees that we see all triangles
1808 actor->GetProperty ()->BackfaceCullingOff ();
1809 actor->GetProperty ()->SetInterpolationToFlat ();
1810 actor->GetProperty ()->EdgeVisibilityOff ();
1811 actor->GetProperty ()->ShadingOff ();
1812
1813 // Save the pointer/ID pair to the global actor map
1814 (*cloud_actor_map_)[id].actor = actor;
1815
1816 // Save the viewpoint transformation matrix to the global actor map
1818 convertToVtkMatrix (cloud->sensor_origin_, cloud->sensor_orientation_, transformation);
1819 (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation;
1820
1821 return (true);
1822}
1823
1824/////////////////////////////////////////////////////////////////////////////////////////////
1825template <typename PointT> bool
1827 const typename pcl::PointCloud<PointT>::ConstPtr &cloud,
1828 const std::vector<pcl::Vertices> &verts,
1829 const std::string &id)
1830{
1831 if (verts.empty ())
1832 {
1833 pcl::console::print_error ("[addPolygonMesh] No vertices given!\n");
1834 return (false);
1835 }
1836
1837 // Check to see if this ID entry already exists (has it been already added to the visualizer?)
1838 auto am_it = cloud_actor_map_->find (id);
1839 if (am_it == cloud_actor_map_->end ())
1840 return (false);
1841
1842 // Get the current poly data
1843 vtkSmartPointer<vtkPolyData> polydata = dynamic_cast<vtkPolyData*>(am_it->second.actor->GetMapper ()->GetInput ());
1844 if (!polydata)
1845 return (false);
1846 vtkSmartPointer<vtkCellArray> cells = polydata->GetPolys ();
1847 if (!cells)
1848 return (false);
1849 vtkSmartPointer<vtkPoints> points = polydata->GetPoints ();
1850 // Copy the new point array in
1851 vtkIdType nr_points = cloud->size ();
1852 points->SetNumberOfPoints (nr_points);
1853
1854 // Get a pointer to the beginning of the data array
1855 float *data = (dynamic_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
1856
1857 int ptr = 0;
1858 std::vector<int> lookup;
1859 // If the dataset is dense (no NaNs)
1860 if (cloud->is_dense)
1861 {
1862 for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
1863 std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1864 }
1865 else
1866 {
1867 lookup.resize (nr_points);
1868 vtkIdType j = 0; // true point index
1869 for (vtkIdType i = 0; i < nr_points; ++i)
1870 {
1871 // Check if the point is invalid
1872 if (!isFinite ((*cloud)[i]))
1873 continue;
1874
1875 lookup [i] = static_cast<int> (j);
1876 std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
1877 j++;
1878 ptr += 3;
1879 }
1880 nr_points = j;
1881 points->SetNumberOfPoints (nr_points);
1882 }
1883
1884 // Update colors
1885 vtkUnsignedCharArray* colors = vtkUnsignedCharArray::SafeDownCast (polydata->GetPointData ()->GetScalars ());
1886 if (!colors)
1887 return (false);
1888 int rgb_idx = -1;
1889 std::vector<pcl::PCLPointField> fields;
1890 rgb_idx = pcl::getFieldIndex<PointT> ("rgb", fields);
1891 if (rgb_idx == -1)
1892 rgb_idx = pcl::getFieldIndex<PointT> ("rgba", fields);
1893 if (rgb_idx != -1 && colors)
1894 {
1895 int j = 0;
1896 std::uint32_t offset = fields[rgb_idx].offset;
1897 for (std::size_t i = 0; i < cloud->size (); ++i)
1898 {
1899 if (!isFinite ((*cloud)[i]))
1900 continue;
1901 const auto* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
1902 unsigned char color[3];
1903 color[0] = rgb_data->r;
1904 color[1] = rgb_data->g;
1905 color[2] = rgb_data->b;
1906 colors->SetTupleValue (j++, color);
1907 }
1908 }
1909
1910 // Get the maximum size of a polygon
1911 int max_size_of_polygon = -1;
1912 for (const auto &vertex : verts)
1913 if (max_size_of_polygon < static_cast<int> (vertex.vertices.size ()))
1914 max_size_of_polygon = static_cast<int> (vertex.vertices.size ());
1915
1916 // Update the cells
1918
1919 details::fillCells(lookup, verts, cells, max_size_of_polygon);
1920
1921 cells->Squeeze ();
1922 // Set the the vertices
1923 polydata->SetPolys (cells);
1924
1925 return (true);
1926}
1927
1928#ifdef vtkGenericDataArray_h
1929#undef SetTupleValue
1930#undef InsertNextTupleValue
1931#undef GetTupleValue
1932#endif
1933
1934#endif
PlanarPolygon represents a planar (2D) polygon, potentially in a 3D space.
bool empty() const
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields).
Eigen::Quaternionf sensor_orientation_
Sensor acquisition pose (rotation).
std::uint32_t width
The point cloud width (if organized as an image-structure).
bool isOrganized() const
Return whether a dataset is organized (e.g., arranged in a structured grid).
std::uint32_t height
The point cloud height (if organized as an image-structure).
std::size_t size() const
Eigen::Vector4f sensor_origin_
Sensor acquisition pose (origin/translation).
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
shared_ptr< const PointCloud< PointT > > ConstPtr
vtkSmartPointer< vtkLODActor > actor
The actor holding the data to render.
Definition actor_map.h:75
bool addPointCloudIntensityGradients(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, const typename pcl::PointCloud< GradientT >::ConstPtr &gradients, int level=100, double scale=1e-6, const std::string &id="cloud", int viewport=0)
Add the estimated surface intensity gradients of a Point Cloud to screen.
bool addPolygonMesh(const pcl::PolygonMesh &polymesh, const std::string &id="polygon", int viewport=0)
Add a PolygonMesh object to screen.
bool addSphere(const PointT &center, double radius, const std::string &id="sphere", int viewport=0)
Add a sphere shape from a point and a radius.
bool addPointCloud(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, const std::string &id="cloud", int viewport=0)
Add a Point Cloud (templated) to screen.
bool addCorrespondences(const typename pcl::PointCloud< PointT >::ConstPtr &source_points, const typename pcl::PointCloud< PointT >::ConstPtr &target_points, const std::vector< int > &correspondences, const std::string &id="correspondences", int viewport=0)
Add the specified correspondences to the display.
bool addPolygon(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, double r, double g, double b, const std::string &id="polygon", int viewport=0)
Add a polygon (polyline) that represents the input point cloud (connects all points in order)
bool updatePointCloud(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, const std::string &id="cloud")
Updates the XYZ data for an existing cloud object id on screen.
GeometryHandler::ConstPtr GeometryHandlerConstPtr
bool addPointCloudNormals(const typename pcl::PointCloud< PointNT >::ConstPtr &cloud, int level=100, float scale=0.02f, const std::string &id="cloud", int viewport=0)
Add the estimated surface normals of a Point Cloud to screen.
bool addText3D(const std::string &text, const PointT &position, double textScale=1.0, double r=1.0, double g=1.0, double b=1.0, const std::string &id="", int viewport=0)
Add a 3d text to the scene.
bool updateSphere(const PointT &center, double radius, double r, double g, double b, const std::string &id="sphere")
Update an existing sphere shape from a point and a radius.
ColorHandler::ConstPtr ColorHandlerConstPtr
bool addArrow(const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id="arrow", int viewport=0)
Add a line arrow segment between two points, and display the distance between them.
bool addLine(const P1 &pt1, const P2 &pt2, const std::string &id="line", int viewport=0)
Add a line segment from two points.
bool addPointCloudPrincipalCurvatures(const typename pcl::PointCloud< PointNT >::ConstPtr &cloud, const typename pcl::PointCloud< pcl::PrincipalCurvatures >::ConstPtr &pcs, int level=100, float scale=1.0f, const std::string &id="cloud", int viewport=0)
Add the estimated principal curvatures of a Point Cloud to screen.
bool updatePolygonMesh(const typename pcl::PointCloud< PointT >::ConstPtr &cloud, const std::vector< pcl::Vertices > &vertices, const std::string &id="polygon")
Update a PolygonMesh object on screen.
bool updateCorrespondences(const typename pcl::PointCloud< PointT >::ConstPtr &source_points, const typename pcl::PointCloud< PointT >::ConstPtr &target_points, const pcl::Correspondences &correspondences, int nth, const std::string &id="correspondences", int viewport=0)
Update the specified correspondences to the display.
Base Handler class for PointCloud colors.
virtual vtkSmartPointer< vtkDataArray > getColor() const =0
Obtain the actual color for the input dataset as a VTK data array.
bool isCapable() const
Check if this handler is capable of handling the input data or not.
virtual std::string getName() const =0
Abstract getName method.
Base handler class for PointCloud geometry.
virtual std::string getName() const =0
Abstract getName method.
bool isCapable() const
Check if this handler is capable of handling the input data or not.
virtual void getGeometry(vtkSmartPointer< vtkPoints > &points) const =0
Obtain the actual point geometry for the input dataset in VTK format.
PCL_EXPORTS vtkSmartPointer< vtkDataSet > createLine(const Eigen::Vector4f &pt1, const Eigen::Vector4f &pt2)
Create a line shape from two points.
PCL_EXPORTS void print_error(FILE *stream, const std::string format, Args &&... args)
Print an error message on stream with colors.
Definition print.h:313
void ignore(const T &...)
Utility function to eliminate unused variable warnings.
Definition utils.h:62
PCL_EXPORTS vtkIdType fillCells(std::vector< int > &lookup, const std::vector< pcl::Vertices > &vertices, vtkSmartPointer< vtkCellArray > cell_array, int max_size_of_polygon)
PCL_EXPORTS void allocVtkUnstructuredGrid(vtkSmartPointer< vtkUnstructuredGrid > &polydata)
Allocate a new unstructured grid smartpointer.
bool isFinite(const PointT &pt)
Tests if the 3D components of a point are all finite param[in] pt point to be tested return true if f...
Definition point_tests.h:56
static constexpr index_t UNAVAILABLE
Definition pcl_base.h:62
std::vector< pcl::Correspondence, Eigen::aligned_allocator< pcl::Correspondence > > Correspondences
constexpr bool isNormalFinite(const PointT &) noexcept
constexpr bool isXYZFinite(const PointT &) noexcept
Define methods or creating 3D shapes from parametric models.
A point structure representing Euclidean xyz coordinates, and the RGB color.
A structure representing RGB color information.
Metafunction to check if a given point type has either rgb or rgba field.