|
Point Cloud Library (PCL)
1.5.1
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * Copyright (c) 2010-2011, Willow Garage, Inc. 00006 * 00007 * All rights reserved. 00008 * 00009 * Redistribution and use in source and binary forms, with or without 00010 * modification, are permitted provided that the following conditions 00011 * are met: 00012 * 00013 * * Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * * Redistributions in binary form must reproduce the above 00016 * copyright notice, this list of conditions and the following 00017 * disclaimer in the documentation and/or other materials provided 00018 * with the distribution. 00019 * * Neither the name of Willow Garage, Inc. nor the names of its 00020 * contributors may be used to endorse or promote products derived 00021 * from this software without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00024 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00025 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00026 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00027 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00028 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00029 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00032 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00033 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00034 * POSSIBILITY OF SUCH DAMAGE. 00035 * 00036 * $Id: pcl_visualizer.hpp 4702 2012-02-23 09:39:33Z gedikli $ 00037 * 00038 */ 00039 00040 #ifndef PCL_PCL_VISUALIZER_IMPL_H_ 00041 #define PCL_PCL_VISUALIZER_IMPL_H_ 00042 00043 #include <vtkCellData.h> 00044 #include <vtkSmartPointer.h> 00045 #include <vtkCellArray.h> 00046 #include <vtkProperty2D.h> 00047 #include <vtkMapper2D.h> 00048 #include <vtkLeaderActor2D.h> 00049 #include <pcl/common/time.h> 00050 00052 template <typename PointT> bool 00053 pcl::visualization::PCLVisualizer::addPointCloud ( 00054 const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00055 const std::string &id, int viewport) 00056 { 00057 // Convert the PointCloud to VTK PolyData 00058 PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud); 00059 return (addPointCloud<PointT> (cloud, geometry_handler, id, viewport)); 00060 } 00061 00063 template <typename PointT> bool 00064 pcl::visualization::PCLVisualizer::addPointCloud ( 00065 const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00066 const PointCloudGeometryHandler<PointT> &geometry_handler, 00067 const std::string &id, int viewport) 00068 { 00069 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00070 CloudActorMap::iterator am_it = cloud_actor_map_->find (id); 00071 00072 if (am_it != cloud_actor_map_->end ()) 00073 { 00074 PCL_WARN ("[addPointCloud] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ()); 00075 return (false); 00076 } 00077 00078 //PointCloudColorHandlerRandom<PointT> color_handler (cloud); 00079 PointCloudColorHandlerCustom<PointT> color_handler (cloud, 255, 255, 255); 00080 return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_)); 00081 } 00082 00084 template <typename PointT> bool 00085 pcl::visualization::PCLVisualizer::addPointCloud ( 00086 const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00087 const GeometryHandlerConstPtr &geometry_handler, 00088 const std::string &id, int viewport) 00089 { 00090 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00091 CloudActorMap::iterator am_it = cloud_actor_map_->find (id); 00092 00093 if (am_it != cloud_actor_map_->end ()) 00094 { 00095 // Here we're just pushing the handlers onto the queue. If needed, something fancier could 00096 // be done such as checking if a specific handler already exists, etc. 00097 am_it->second.geometry_handlers.push_back (geometry_handler); 00098 return (true); 00099 } 00100 00101 //PointCloudColorHandlerRandom<PointT> color_handler (cloud); 00102 PointCloudColorHandlerCustom<PointT> color_handler (cloud, 255, 255, 255); 00103 return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_)); 00104 } 00105 00107 template <typename PointT> bool 00108 pcl::visualization::PCLVisualizer::addPointCloud ( 00109 const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00110 const PointCloudColorHandler<PointT> &color_handler, 00111 const std::string &id, int viewport) 00112 { 00113 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00114 CloudActorMap::iterator am_it = cloud_actor_map_->find (id); 00115 00116 if (am_it != cloud_actor_map_->end ()) 00117 { 00118 PCL_WARN ("[addPointCloud] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ()); 00119 00120 // Here we're just pushing the handlers onto the queue. If needed, something fancier could 00121 // be done such as checking if a specific handler already exists, etc. 00122 //cloud_actor_map_[id].color_handlers.push_back (color_handler); 00123 //style_->setCloudActorMap (boost::make_shared<CloudActorMap> (cloud_actor_map_)); 00124 return (false); 00125 } 00126 // Convert the PointCloud to VTK PolyData 00127 PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud); 00128 return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_)); 00129 } 00130 00132 template <typename PointT> bool 00133 pcl::visualization::PCLVisualizer::addPointCloud ( 00134 const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00135 const ColorHandlerConstPtr &color_handler, 00136 const std::string &id, int viewport) 00137 { 00138 // Check to see if this entry already exists (has it been already added to the visualizer?) 00139 CloudActorMap::iterator am_it = cloud_actor_map_->find (id); 00140 if (am_it != cloud_actor_map_->end ()) 00141 { 00142 // Here we're just pushing the handlers onto the queue. If needed, something fancier could 00143 // be done such as checking if a specific handler already exists, etc. 00144 am_it->second.color_handlers.push_back (color_handler); 00145 return (true); 00146 } 00147 00148 PointCloudGeometryHandlerXYZ<PointT> geometry_handler (cloud); 00149 return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_)); 00150 } 00151 00153 template <typename PointT> bool 00154 pcl::visualization::PCLVisualizer::addPointCloud ( 00155 const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00156 const GeometryHandlerConstPtr &geometry_handler, 00157 const ColorHandlerConstPtr &color_handler, 00158 const std::string &id, int viewport) 00159 { 00160 // Check to see if this entry already exists (has it been already added to the visualizer?) 00161 CloudActorMap::iterator am_it = cloud_actor_map_->find (id); 00162 if (am_it != cloud_actor_map_->end ()) 00163 { 00164 // Here we're just pushing the handlers onto the queue. If needed, something fancier could 00165 // be done such as checking if a specific handler already exists, etc. 00166 am_it->second.geometry_handlers.push_back (geometry_handler); 00167 am_it->second.color_handlers.push_back (color_handler); 00168 return (true); 00169 } 00170 return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_)); 00171 } 00172 00174 template <typename PointT> bool 00175 pcl::visualization::PCLVisualizer::addPointCloud ( 00176 const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00177 const PointCloudColorHandler<PointT> &color_handler, 00178 const PointCloudGeometryHandler<PointT> &geometry_handler, 00179 const std::string &id, int viewport) 00180 { 00181 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00182 CloudActorMap::iterator am_it = cloud_actor_map_->find (id); 00183 00184 if (am_it != cloud_actor_map_->end ()) 00185 { 00186 PCL_WARN ("[addPointCloud] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ()); 00187 // Here we're just pushing the handlers onto the queue. If needed, something fancier could 00188 // be done such as checking if a specific handler already exists, etc. 00189 //cloud_actor_map_[id].geometry_handlers.push_back (geometry_handler); 00190 //cloud_actor_map_[id].color_handlers.push_back (color_handler); 00191 //style_->setCloudActorMap (boost::make_shared<CloudActorMap> (cloud_actor_map_)); 00192 return (false); 00193 } 00194 return (fromHandlersToScreen (geometry_handler, color_handler, id, viewport, cloud->sensor_origin_, cloud->sensor_orientation_)); 00195 } 00196 00198 template <typename PointT> void 00199 pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData ( 00200 const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00201 vtkSmartPointer<vtkPolyData> &polydata, 00202 vtkSmartPointer<vtkIdTypeArray> &initcells) 00203 { 00204 vtkSmartPointer<vtkCellArray> vertices; 00205 if (!polydata) 00206 { 00207 allocVtkPolyData (polydata); 00208 vertices = vtkSmartPointer<vtkCellArray>::New (); 00209 polydata->SetVerts (vertices); 00210 } 00211 00212 // Create the supporting structures 00213 vertices = polydata->GetVerts (); 00214 if (!vertices) 00215 vertices = vtkSmartPointer<vtkCellArray>::New (); 00216 00217 vtkIdType nr_points = cloud->points.size (); 00218 // Create the point set 00219 vtkSmartPointer<vtkPoints> points = polydata->GetPoints (); 00220 if (!points) 00221 { 00222 points = vtkSmartPointer<vtkPoints>::New (); 00223 points->SetDataTypeToFloat (); 00224 polydata->SetPoints (points); 00225 } 00226 points->SetNumberOfPoints (nr_points); 00227 00228 // Get a pointer to the beginning of the data array 00229 float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0); 00230 00231 // Set the points 00232 if (cloud->is_dense) 00233 { 00234 for (vtkIdType i = 0; i < nr_points; ++i) 00235 memcpy (&data[i * 3], &cloud->points[i].x, 12); // sizeof (float) * 3 00236 } 00237 else 00238 { 00239 vtkIdType j = 0; // true point index 00240 for (vtkIdType i = 0; i < nr_points; ++i) 00241 { 00242 // Check if the point is invalid 00243 if (!pcl_isfinite (cloud->points[i].x) || 00244 !pcl_isfinite (cloud->points[i].y) || 00245 !pcl_isfinite (cloud->points[i].z)) 00246 continue; 00247 00248 memcpy (&data[j * 3], &cloud->points[i].x, 12); // sizeof (float) * 3 00249 j++; 00250 } 00251 nr_points = j; 00252 points->SetNumberOfPoints (nr_points); 00253 } 00254 00255 vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData (); 00256 updateCells (cells, initcells, nr_points); 00257 00258 // Set the cells and the vertices 00259 vertices->SetCells (nr_points, cells); 00260 } 00261 00263 template <typename PointT> void 00264 pcl::visualization::PCLVisualizer::convertPointCloudToVTKPolyData ( 00265 const pcl::visualization::PointCloudGeometryHandler<PointT> &geometry_handler, 00266 vtkSmartPointer<vtkPolyData> &polydata, 00267 vtkSmartPointer<vtkIdTypeArray> &initcells) 00268 { 00269 vtkSmartPointer<vtkCellArray> vertices; 00270 if (!polydata) 00271 { 00272 allocVtkPolyData (polydata); 00273 vertices = vtkSmartPointer<vtkCellArray>::New (); 00274 polydata->SetVerts (vertices); 00275 } 00276 00277 // Use the handler to obtain the geometry 00278 vtkSmartPointer<vtkPoints> points; 00279 geometry_handler.getGeometry (points); 00280 polydata->SetPoints (points); 00281 00282 vtkIdType nr_points = points->GetNumberOfPoints (); 00283 00284 // Create the supporting structures 00285 vertices = polydata->GetVerts (); 00286 if (!vertices) 00287 vertices = vtkSmartPointer<vtkCellArray>::New (); 00288 00289 vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData (); 00290 updateCells (cells, initcells, nr_points); 00291 // Set the cells and the vertices 00292 vertices->SetCells (nr_points, cells); 00293 } 00294 00296 template <typename PointT> bool 00297 pcl::visualization::PCLVisualizer::addPolygon ( 00298 const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00299 double r, double g, double b, const std::string &id, int viewport) 00300 { 00301 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00302 ShapeActorMap::iterator am_it = shape_actor_map_->find (id); 00303 if (am_it != shape_actor_map_->end ()) 00304 { 00305 PCL_WARN ("[addPolygon] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ()); 00306 return (false); 00307 } 00308 00309 vtkSmartPointer<vtkDataSet> data = createPolygon<PointT> (cloud); 00310 00311 // Create an Actor 00312 vtkSmartPointer<vtkLODActor> actor; 00313 createActorFromVTKDataSet (data, actor); 00314 actor->GetProperty ()->SetRepresentationToWireframe (); 00315 actor->GetProperty ()->SetColor (r, g, b); 00316 actor->GetMapper ()->ScalarVisibilityOff (); 00317 addActorToRenderer (actor, viewport); 00318 00319 // Save the pointer/ID pair to the global actor map 00320 (*shape_actor_map_)[id] = actor; 00321 return (true); 00322 } 00323 00325 template <typename PointT> bool 00326 pcl::visualization::PCLVisualizer::addPolygon ( 00327 const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00328 const std::string &id, int viewport) 00329 { 00330 return (!addPolygon<PointT> (cloud, 0.5, 0.5, 0.5, id, viewport)); 00331 return (false); 00332 } 00333 00335 template <typename P1, typename P2> bool 00336 pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport) 00337 { 00338 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00339 ShapeActorMap::iterator am_it = shape_actor_map_->find (id); 00340 if (am_it != shape_actor_map_->end ()) 00341 { 00342 PCL_WARN ("[addLine] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ()); 00343 return (false); 00344 } 00345 00346 vtkSmartPointer<vtkDataSet> data = createLine (pt1.getVector4fMap (), pt2.getVector4fMap ()); 00347 00348 // Create an Actor 00349 vtkSmartPointer<vtkLODActor> actor; 00350 createActorFromVTKDataSet (data, actor); 00351 actor->GetProperty ()->SetRepresentationToWireframe (); 00352 actor->GetProperty ()->SetColor (r, g, b); 00353 actor->GetMapper ()->ScalarVisibilityOff (); 00354 addActorToRenderer (actor, viewport); 00355 00356 // Save the pointer/ID pair to the global actor map 00357 (*shape_actor_map_)[id] = actor; 00358 return (true); 00359 } 00360 00362 template <typename P1, typename P2> bool 00363 pcl::visualization::PCLVisualizer::addArrow (const P1 &pt1, const P2 &pt2, double r, double g, double b, const std::string &id, int viewport) 00364 { 00365 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00366 ShapeActorMap::iterator am_it = shape_actor_map_->find (id); 00367 if (am_it != shape_actor_map_->end ()) 00368 { 00369 PCL_WARN ("[addArrow] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ()); 00370 return (false); 00371 } 00372 00373 // Create an Actor 00374 vtkSmartPointer<vtkLeaderActor2D> leader = vtkSmartPointer<vtkLeaderActor2D>::New (); 00375 leader->GetPositionCoordinate ()->SetCoordinateSystemToWorld (); 00376 leader->GetPositionCoordinate ()->SetValue (pt1.x, pt1.y, pt1.z); 00377 leader->GetPosition2Coordinate ()->SetCoordinateSystemToWorld (); 00378 leader->GetPosition2Coordinate ()->SetValue (pt2.x, pt2.y, pt2.z); 00379 leader->SetArrowStyleToFilled (); 00380 leader->AutoLabelOn (); 00381 00382 leader->GetProperty ()->SetColor (r, g, b); 00383 addActorToRenderer (leader, viewport); 00384 00385 // Save the pointer/ID pair to the global actor map 00386 (*shape_actor_map_)[id] = leader; 00387 return (true); 00388 } 00389 00391 template <typename P1, typename P2> bool 00392 pcl::visualization::PCLVisualizer::addLine (const P1 &pt1, const P2 &pt2, const std::string &id, int viewport) 00393 { 00394 return (!addLine (pt1, pt2, 0.5, 0.5, 0.5, id, viewport)); 00395 } 00396 00398 /*template <typename P1, typename P2> bool 00399 pcl::visualization::PCLVisualizer::addLineToGroup (const P1 &pt1, const P2 &pt2, const std::string &group_id, int viewport) 00400 { 00401 vtkSmartPointer<vtkDataSet> data = createLine<P1, P2> (pt1, pt2); 00402 00403 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00404 ShapeActorMap::iterator am_it = shape_actor_map_->find (group_id); 00405 if (am_it != shape_actor_map_->end ()) 00406 { 00407 // Get the old data 00408 vtkPolyDataMapper* mapper = static_cast<vtkPolyDataMapper*>(am_it->second->GetMapper ()); 00409 vtkPolyData* olddata = static_cast<vtkPolyData*>(mapper->GetInput ()); 00410 // Add it to the current data 00411 vtkSmartPointer<vtkAppendPolyData> alldata = vtkSmartPointer<vtkAppendPolyData>::New (); 00412 alldata->AddInput (olddata); 00413 00414 // Convert to vtkPolyData 00415 vtkSmartPointer<vtkPolyData> curdata = (vtkPolyData::SafeDownCast (data)); 00416 alldata->AddInput (curdata); 00417 00418 mapper->SetInput (alldata->GetOutput ()); 00419 00420 am_it->second->SetMapper (mapper); 00421 am_it->second->Modified (); 00422 return (true); 00423 } 00424 00425 // Create an Actor 00426 vtkSmartPointer<vtkLODActor> actor; 00427 createActorFromVTKDataSet (data, actor); 00428 actor->GetProperty ()->SetRepresentationToWireframe (); 00429 actor->GetProperty ()->SetColor (1, 0, 0); 00430 addActorToRenderer (actor, viewport); 00431 00432 // Save the pointer/ID pair to the global actor map 00433 (*shape_actor_map_)[group_id] = actor; 00434 00435 //ShapeActorMap::iterator am_it = shape_actor_map_->find (id); 00436 //vtkSmartPointer<vtkLODActor> actor = am_it->second; 00437 //actor->GetProperty ()->SetColor (r, g, b); 00438 //actor->Modified (); 00439 return (true); 00440 }*/ 00441 00443 template <typename PointT> bool 00444 pcl::visualization::PCLVisualizer::addSphere (const PointT ¢er, double radius, double r, double g, double b, const std::string &id, int viewport) 00445 { 00446 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00447 ShapeActorMap::iterator am_it = shape_actor_map_->find (id); 00448 if (am_it != shape_actor_map_->end ()) 00449 { 00450 PCL_WARN ("[addSphere] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ()); 00451 return (false); 00452 } 00453 00454 vtkSmartPointer<vtkDataSet> data = createSphere (center.getVector4fMap (), radius); 00455 00456 // Create an Actor 00457 vtkSmartPointer<vtkLODActor> actor; 00458 createActorFromVTKDataSet (data, actor); 00459 actor->GetProperty ()->SetRepresentationToWireframe (); 00460 actor->GetProperty ()->SetInterpolationToGouraud (); 00461 actor->GetMapper ()->ScalarVisibilityOff (); 00462 actor->GetProperty ()->SetColor (r, g, b); 00463 addActorToRenderer (actor, viewport); 00464 00465 // Save the pointer/ID pair to the global actor map 00466 (*shape_actor_map_)[id] = actor; 00467 return (true); 00468 } 00469 00471 template <typename PointT> bool 00472 pcl::visualization::PCLVisualizer::addSphere (const PointT ¢er, double radius, const std::string &id, int viewport) 00473 { 00474 return (addSphere (center, radius, 0.5, 0.5, 0.5, id, viewport)); 00475 } 00476 00478 template <typename PointT> bool 00479 pcl::visualization::PCLVisualizer::addText3D ( 00480 const std::string &text, 00481 const PointT& position, 00482 double textScale, 00483 double r, 00484 double g, 00485 double b, 00486 const std::string &id, 00487 int viewport) 00488 { 00489 std::string tid; 00490 if (id.empty ()) 00491 tid = text; 00492 else 00493 tid = id; 00494 00495 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00496 ShapeActorMap::iterator am_it = shape_actor_map_->find (tid); 00497 if (am_it != shape_actor_map_->end ()) 00498 { 00499 pcl::console::print_warn ("[addText3d] A text with id <%s> already exists! Please choose a different id and retry.\n", tid.c_str ()); 00500 return (false); 00501 } 00502 00503 vtkSmartPointer<vtkVectorText> textSource = vtkSmartPointer<vtkVectorText>::New (); 00504 textSource->SetText (text.c_str()); 00505 textSource->Update (); 00506 00507 vtkSmartPointer<vtkPolyDataMapper> textMapper = vtkSmartPointer<vtkPolyDataMapper>::New (); 00508 textMapper->SetInputConnection (textSource->GetOutputPort ()); 00509 00510 // Since each follower may follow a different camera, we need different followers 00511 rens_->InitTraversal (); 00512 vtkRenderer* renderer = NULL; 00513 int i = 1; 00514 while ((renderer = rens_->GetNextItem ()) != NULL) 00515 { 00516 // Should we add the actor to all renderers or just to i-nth renderer? 00517 if (viewport == 0 || viewport == i) 00518 { 00519 vtkSmartPointer<vtkFollower> textActor = vtkSmartPointer<vtkFollower>::New (); 00520 textActor->SetMapper (textMapper); 00521 textActor->SetPosition (position.x, position.y, position.z); 00522 textActor->SetScale (textScale); 00523 textActor->GetProperty ()->SetColor (r, g, b); 00524 textActor->SetCamera (renderer->GetActiveCamera ()); 00525 00526 renderer->AddActor (textActor); 00527 renderer->Render (); 00528 00529 // Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers 00530 // for multiple viewport 00531 std::string alternate_tid = tid; 00532 alternate_tid.append(i, '*'); 00533 00534 (*shape_actor_map_)[(viewport == 0) ? tid : alternate_tid] = textActor; 00535 } 00536 00537 ++i; 00538 } 00539 00540 return (true); 00541 } 00542 00544 template <typename PointNT> bool 00545 pcl::visualization::PCLVisualizer::addPointCloudNormals ( 00546 const typename pcl::PointCloud<PointNT>::ConstPtr &cloud, 00547 int level, double scale, const std::string &id, int viewport) 00548 { 00549 return (addPointCloudNormals<PointNT, PointNT>(cloud, cloud, level, scale, id, viewport)); 00550 } 00551 00553 template <typename PointT, typename PointNT> bool 00554 pcl::visualization::PCLVisualizer::addPointCloudNormals ( 00555 const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00556 const typename pcl::PointCloud<PointNT>::ConstPtr &normals, 00557 int level, double scale, 00558 const std::string &id, int viewport) 00559 { 00560 if (normals->points.size () != cloud->points.size ()) 00561 { 00562 PCL_ERROR ("[addPointCloudNormals] The number of points differs from the number of normals!\n"); 00563 return (false); 00564 } 00565 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00566 CloudActorMap::iterator am_it = cloud_actor_map_->find (id); 00567 00568 if (am_it != cloud_actor_map_->end ()) 00569 { 00570 PCL_WARN ("[addPointCloudNormals] A PointCloud with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ()); 00571 return (false); 00572 } 00573 00574 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); 00575 vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New(); 00576 00577 points->SetDataTypeToFloat (); 00578 vtkSmartPointer<vtkFloatArray> data = vtkSmartPointer<vtkFloatArray>::New (); 00579 data->SetNumberOfComponents (3); 00580 00581 vtkIdType nr_normals = (cloud->points.size () - 1) / level + 1 ; 00582 float* pts = new float[2 * nr_normals * 3]; 00583 00584 for (vtkIdType i = 0, j = 0; j < nr_normals; j++, i = j * level) 00585 { 00586 PointT p = cloud->points[i]; 00587 p.x += normals->points[i].normal[0] * scale; 00588 p.y += normals->points[i].normal[1] * scale; 00589 p.z += normals->points[i].normal[2] * scale; 00590 00591 pts[2 * j * 3 + 0] = cloud->points[i].x; 00592 pts[2 * j * 3 + 1] = cloud->points[i].y; 00593 pts[2 * j * 3 + 2] = cloud->points[i].z; 00594 pts[2 * j * 3 + 3] = p.x; 00595 pts[2 * j * 3 + 4] = p.y; 00596 pts[2 * j * 3 + 5] = p.z; 00597 00598 lines->InsertNextCell(2); 00599 lines->InsertCellPoint(2*j); 00600 lines->InsertCellPoint(2*j+1); 00601 } 00602 00603 data->SetArray (&pts[0], 2 * nr_normals * 3, 0); 00604 points->SetData (data); 00605 00606 vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New(); 00607 polyData->SetPoints(points); 00608 polyData->SetLines(lines); 00609 00610 vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New (); 00611 mapper->SetInput (polyData); 00612 mapper->SetColorModeToMapScalars(); 00613 mapper->SetScalarModeToUsePointData(); 00614 00615 // create actor 00616 vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New (); 00617 actor->SetMapper (mapper); 00618 00619 // Add it to all renderers 00620 addActorToRenderer (actor, viewport); 00621 00622 // Save the pointer/ID pair to the global actor map 00623 (*cloud_actor_map_)[id].actor = actor; 00624 return (true); 00625 } 00626 00628 template <typename PointT> bool 00629 pcl::visualization::PCLVisualizer::addCorrespondences ( 00630 const typename pcl::PointCloud<PointT>::ConstPtr &source_points, 00631 const typename pcl::PointCloud<PointT>::ConstPtr &target_points, 00632 const std::vector<int> &correspondences, 00633 const std::string &id, 00634 int viewport) 00635 { 00636 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00637 ShapeActorMap::iterator am_it = shape_actor_map_->find (id); 00638 if (am_it != shape_actor_map_->end ()) 00639 { 00640 PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ()); 00641 return (false); 00642 } 00643 00644 vtkSmartPointer<vtkAppendPolyData> polydata = vtkSmartPointer<vtkAppendPolyData>::New (); 00645 00646 vtkSmartPointer<vtkUnsignedCharArray> line_colors = vtkSmartPointer<vtkUnsignedCharArray>::New (); 00647 line_colors->SetNumberOfComponents (3); 00648 line_colors->SetName ("Colors"); 00649 // Use Red by default (can be changed later) 00650 unsigned char rgb[3]; 00651 rgb[0] = 1 * 255.0; 00652 rgb[1] = 0 * 255.0; 00653 rgb[2] = 0 * 255.0; 00654 00655 // Draw lines between the best corresponding points 00656 for (size_t i = 0; i < source_points->size (); ++i) 00657 { 00658 const PointT &p_src = source_points->points[i]; 00659 const PointT &p_tgt = target_points->points[correspondences[i]]; 00660 00661 // Add the line 00662 vtkSmartPointer<vtkLineSource> line = vtkSmartPointer<vtkLineSource>::New (); 00663 line->SetPoint1 (p_src.x, p_src.y, p_src.z); 00664 line->SetPoint2 (p_tgt.x, p_tgt.y, p_tgt.z); 00665 line->Update (); 00666 polydata->AddInput (line->GetOutput ()); 00667 line_colors->InsertNextTupleValue (rgb); 00668 } 00669 polydata->Update (); 00670 vtkSmartPointer<vtkPolyData> line_data = polydata->GetOutput (); 00671 line_data->GetCellData ()->SetScalars (line_colors); 00672 00673 // Create an Actor 00674 vtkSmartPointer<vtkLODActor> actor; 00675 createActorFromVTKDataSet (line_data, actor); 00676 actor->GetProperty ()->SetRepresentationToWireframe (); 00677 actor->GetProperty ()->SetOpacity (0.5); 00678 addActorToRenderer (actor, viewport); 00679 00680 // Save the pointer/ID pair to the global actor map 00681 (*shape_actor_map_)[id] = actor; 00682 00683 return (true); 00684 } 00685 00687 template <typename PointT> bool 00688 pcl::visualization::PCLVisualizer::addCorrespondences ( 00689 const typename pcl::PointCloud<PointT>::ConstPtr &source_points, 00690 const typename pcl::PointCloud<PointT>::ConstPtr &target_points, 00691 const pcl::Correspondences &correspondences, 00692 const std::string &id, 00693 int viewport) 00694 { 00695 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00696 ShapeActorMap::iterator am_it = shape_actor_map_->find (id); 00697 if (am_it != shape_actor_map_->end ()) 00698 { 00699 PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ()); 00700 return (false); 00701 } 00702 00703 vtkSmartPointer<vtkAppendPolyData> polydata = vtkSmartPointer<vtkAppendPolyData>::New (); 00704 00705 vtkSmartPointer<vtkUnsignedCharArray> line_colors = vtkSmartPointer<vtkUnsignedCharArray>::New (); 00706 line_colors->SetNumberOfComponents (3); 00707 line_colors->SetName ("Colors"); 00708 unsigned char rgb[3]; 00709 // Use Red by default (can be changed later) 00710 rgb[0] = 1 * 255.0; 00711 rgb[1] = 0 * 255.0; 00712 rgb[2] = 0 * 255.0; 00713 00714 // Draw lines between the best corresponding points 00715 for (size_t i = 0; i < correspondences.size (); ++i) 00716 { 00717 const PointT &p_src = source_points->points[correspondences[i].index_query]; 00718 const PointT &p_tgt = target_points->points[correspondences[i].index_match]; 00719 00720 // Add the line 00721 vtkSmartPointer<vtkLineSource> line = vtkSmartPointer<vtkLineSource>::New (); 00722 line->SetPoint1 (p_src.x, p_src.y, p_src.z); 00723 line->SetPoint2 (p_tgt.x, p_tgt.y, p_tgt.z); 00724 line->Update (); 00725 polydata->AddInput (line->GetOutput ()); 00726 line_colors->InsertNextTupleValue (rgb); 00727 } 00728 polydata->Update (); 00729 vtkSmartPointer<vtkPolyData> line_data = polydata->GetOutput (); 00730 line_data->GetCellData ()->SetScalars (line_colors); 00731 00732 // Create an Actor 00733 vtkSmartPointer<vtkLODActor> actor; 00734 createActorFromVTKDataSet (line_data, actor); 00735 actor->GetProperty ()->SetRepresentationToWireframe (); 00736 actor->GetProperty ()->SetOpacity (0.5); 00737 addActorToRenderer (actor, viewport); 00738 00739 // Save the pointer/ID pair to the global actor map 00740 (*shape_actor_map_)[id] = actor; 00741 00742 return (true); 00743 } 00744 00746 template <typename PointT> bool 00747 pcl::visualization::PCLVisualizer::fromHandlersToScreen ( 00748 const PointCloudGeometryHandler<PointT> &geometry_handler, 00749 const PointCloudColorHandler<PointT> &color_handler, 00750 const std::string &id, 00751 int viewport, 00752 const Eigen::Vector4f& sensor_origin, 00753 const Eigen::Quaternion<float>& sensor_orientation) 00754 { 00755 if (!geometry_handler.isCapable ()) 00756 { 00757 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ()); 00758 return (false); 00759 } 00760 00761 if (!color_handler.isCapable ()) 00762 { 00763 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ()); 00764 return (false); 00765 } 00766 00767 vtkSmartPointer<vtkPolyData> polydata; 00768 vtkSmartPointer<vtkIdTypeArray> initcells; 00769 // Convert the PointCloud to VTK PolyData 00770 convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells); 00771 // use the given geometry handler 00772 polydata->Update (); 00773 00774 // Get the colors from the handler 00775 vtkSmartPointer<vtkDataArray> scalars; 00776 color_handler.getColor (scalars); 00777 polydata->GetPointData ()->SetScalars (scalars); 00778 double minmax[2]; 00779 scalars->GetRange (minmax); 00780 00781 // Create an Actor 00782 vtkSmartPointer<vtkLODActor> actor; 00783 createActorFromVTKDataSet (polydata, actor); 00784 actor->GetMapper ()->SetScalarRange (minmax); 00785 00786 // Add it to all renderers 00787 addActorToRenderer (actor, viewport); 00788 00789 // Save the pointer/ID pair to the global actor map 00790 (*cloud_actor_map_)[id].actor = actor; 00791 (*cloud_actor_map_)[id].cells = initcells; 00792 00793 // Save the viewpoint transformation matrix to the global actor map 00794 vtkSmartPointer<vtkMatrix4x4> transformation = vtkSmartPointer<vtkMatrix4x4>::New(); 00795 convertToVtkMatrix (sensor_origin, sensor_orientation, transformation); 00796 (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation; 00797 00798 return (true); 00799 } 00800 00802 template <typename PointT> bool 00803 pcl::visualization::PCLVisualizer::fromHandlersToScreen ( 00804 const PointCloudGeometryHandler<PointT> &geometry_handler, 00805 const ColorHandlerConstPtr &color_handler, 00806 const std::string &id, 00807 int viewport, 00808 const Eigen::Vector4f& sensor_origin, 00809 const Eigen::Quaternion<float>& sensor_orientation) 00810 { 00811 if (!geometry_handler.isCapable ()) 00812 { 00813 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler.getName ().c_str ()); 00814 return (false); 00815 } 00816 00817 if (!color_handler->isCapable ()) 00818 { 00819 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler->getName ().c_str ()); 00820 return (false); 00821 } 00822 00823 vtkSmartPointer<vtkPolyData> polydata; 00824 vtkSmartPointer<vtkIdTypeArray> initcells; 00825 // Convert the PointCloud to VTK PolyData 00826 convertPointCloudToVTKPolyData<PointT> (geometry_handler, polydata, initcells); 00827 // use the given geometry handler 00828 polydata->Update (); 00829 00830 // Get the colors from the handler 00831 vtkSmartPointer<vtkDataArray> scalars; 00832 color_handler->getColor (scalars); 00833 polydata->GetPointData ()->SetScalars (scalars); 00834 double minmax[2]; 00835 scalars->GetRange (minmax); 00836 00837 // Create an Actor 00838 vtkSmartPointer<vtkLODActor> actor; 00839 createActorFromVTKDataSet (polydata, actor); 00840 actor->GetMapper ()->SetScalarRange (minmax); 00841 00842 // Add it to all renderers 00843 addActorToRenderer (actor, viewport); 00844 00845 // Save the pointer/ID pair to the global actor map 00846 (*cloud_actor_map_)[id].actor = actor; 00847 (*cloud_actor_map_)[id].cells = initcells; 00848 (*cloud_actor_map_)[id].color_handlers.push_back (color_handler); 00849 00850 // Save the viewpoint transformation matrix to the global actor map 00851 // Save the viewpoint transformation matrix to the global actor map 00852 vtkSmartPointer<vtkMatrix4x4> transformation = vtkSmartPointer<vtkMatrix4x4>::New(); 00853 convertToVtkMatrix (sensor_origin, sensor_orientation, transformation); 00854 (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation; 00855 00856 return (true); 00857 } 00858 00860 template <typename PointT> bool 00861 pcl::visualization::PCLVisualizer::fromHandlersToScreen ( 00862 const GeometryHandlerConstPtr &geometry_handler, 00863 const PointCloudColorHandler<PointT> &color_handler, 00864 const std::string &id, 00865 int viewport, 00866 const Eigen::Vector4f& sensor_origin, 00867 const Eigen::Quaternion<float>& sensor_orientation) 00868 { 00869 if (!geometry_handler->isCapable ()) 00870 { 00871 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid geometry handler (%s)!\n", id.c_str (), geometry_handler->getName ().c_str ()); 00872 return (false); 00873 } 00874 00875 if (!color_handler.isCapable ()) 00876 { 00877 PCL_WARN ("[fromHandlersToScreen] PointCloud <%s> requested with an invalid color handler (%s)!\n", id.c_str (), color_handler.getName ().c_str ()); 00878 return (false); 00879 } 00880 00881 vtkSmartPointer<vtkPolyData> polydata; 00882 vtkSmartPointer<vtkIdTypeArray> initcells; 00883 // Convert the PointCloud to VTK PolyData 00884 convertPointCloudToVTKPolyData (geometry_handler, polydata, initcells); 00885 // use the given geometry handler 00886 polydata->Update (); 00887 00888 // Get the colors from the handler 00889 vtkSmartPointer<vtkDataArray> scalars; 00890 color_handler.getColor (scalars); 00891 polydata->GetPointData ()->SetScalars (scalars); 00892 double minmax[2]; 00893 scalars->GetRange (minmax); 00894 00895 // Create an Actor 00896 vtkSmartPointer<vtkLODActor> actor; 00897 createActorFromVTKDataSet (polydata, actor); 00898 actor->GetMapper ()->SetScalarRange (minmax); 00899 00900 // Add it to all renderers 00901 addActorToRenderer (actor, viewport); 00902 00903 // Save the pointer/ID pair to the global actor map 00904 (*cloud_actor_map_)[id].actor = actor; 00905 (*cloud_actor_map_)[id].cells = initcells; 00906 (*cloud_actor_map_)[id].geometry_handlers.push_back (geometry_handler); 00907 00908 // Save the viewpoint transformation matrix to the global actor map 00909 vtkSmartPointer<vtkMatrix4x4> transformation = vtkSmartPointer<vtkMatrix4x4>::New(); 00910 convertToVtkMatrix (sensor_origin, sensor_orientation, transformation); 00911 (*cloud_actor_map_)[id].viewpoint_transformation_ = transformation; 00912 00913 return (true); 00914 } 00915 00917 template <typename PointT> bool 00918 pcl::visualization::PCLVisualizer::updatePointCloud (const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00919 const std::string &id) 00920 { 00921 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00922 CloudActorMap::iterator am_it = cloud_actor_map_->find (id); 00923 00924 if (am_it == cloud_actor_map_->end ()) 00925 return (false); 00926 00927 vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput (); 00928 // Convert the PointCloud to VTK PolyData 00929 convertPointCloudToVTKPolyData<PointT> (cloud, polydata, am_it->second.cells); 00930 polydata->Update (); 00931 00932 // Set scalars to blank, since there is no way we can update them here. 00933 vtkSmartPointer<vtkDataArray> scalars; 00934 polydata->GetPointData ()->SetScalars (scalars); 00935 polydata->Update (); 00936 double minmax[2]; 00937 minmax[0] = std::numeric_limits<double>::min (); 00938 minmax[1] = std::numeric_limits<double>::max (); 00939 am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff (); 00940 am_it->second.actor->GetMapper ()->SetScalarRange (minmax); 00941 00942 // Update the mapper 00943 reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata); 00944 return (true); 00945 } 00946 00948 template <typename PointT> bool 00949 pcl::visualization::PCLVisualizer::updatePointCloud (const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00950 const PointCloudGeometryHandler<PointT> &geometry_handler, 00951 const std::string &id) 00952 { 00953 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00954 CloudActorMap::iterator am_it = cloud_actor_map_->find (id); 00955 00956 if (am_it == cloud_actor_map_->end ()) 00957 return (false); 00958 00959 vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput (); 00960 if (!polydata) 00961 return (false); 00962 // Convert the PointCloud to VTK PolyData 00963 convertPointCloudToVTKPolyData (geometry_handler, polydata, am_it->second.cells); 00964 00965 // Set scalars to blank, since there is no way we can update them here. 00966 vtkSmartPointer<vtkDataArray> scalars; 00967 polydata->GetPointData ()->SetScalars (scalars); 00968 polydata->Update (); 00969 double minmax[2]; 00970 minmax[0] = std::numeric_limits<double>::min (); 00971 minmax[1] = std::numeric_limits<double>::max (); 00972 am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff (); 00973 am_it->second.actor->GetMapper ()->SetScalarRange (minmax); 00974 00975 // Update the mapper 00976 reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata); 00977 return (true); 00978 } 00979 00980 00982 template <typename PointT> bool 00983 pcl::visualization::PCLVisualizer::updatePointCloud (const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 00984 const PointCloudColorHandler<PointT> &color_handler, 00985 const std::string &id) 00986 { 00987 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 00988 CloudActorMap::iterator am_it = cloud_actor_map_->find (id); 00989 00990 if (am_it == cloud_actor_map_->end ()) 00991 return (false); 00992 00993 // Get the current poly data 00994 vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput (); 00995 if (!polydata) 00996 return (false); 00997 vtkSmartPointer<vtkCellArray> vertices = polydata->GetVerts (); 00998 vtkSmartPointer<vtkPoints> points = polydata->GetPoints (); 00999 // Copy the new point array in 01000 vtkIdType nr_points = cloud->points.size (); 01001 points->SetNumberOfPoints (nr_points); 01002 01003 // Get a pointer to the beginning of the data array 01004 float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0); 01005 01006 int pts = 0; 01007 // If the dataset is dense (no NaNs) 01008 if (cloud->is_dense) 01009 { 01010 for (vtkIdType i = 0; i < nr_points; ++i, pts += 3) 01011 memcpy (&data[pts], &cloud->points[i].x, 12); // sizeof (float) * 3 01012 } 01013 else 01014 { 01015 vtkIdType j = 0; // true point index 01016 for (vtkIdType i = 0; i < nr_points; ++i) 01017 { 01018 // Check if the point is invalid 01019 if (!isFinite (cloud->points[i])) 01020 continue; 01021 01022 memcpy (&data[pts], &cloud->points[i].x, 12); // sizeof (float) * 3 01023 pts += 3; 01024 j++; 01025 } 01026 nr_points = j; 01027 points->SetNumberOfPoints (nr_points); 01028 } 01029 01030 vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData (); 01031 updateCells (cells, am_it->second.cells, nr_points); 01032 01033 // Set the cells and the vertices 01034 vertices->SetCells (nr_points, cells); 01035 01036 // Get the colors from the handler 01037 vtkSmartPointer<vtkDataArray> scalars; 01038 color_handler.getColor (scalars); 01039 double minmax[2]; 01040 scalars->GetRange (minmax); 01041 // Update the data 01042 polydata->GetPointData ()->SetScalars (scalars); 01043 polydata->Update (); 01044 01045 am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff (); 01046 am_it->second.actor->GetMapper ()->SetScalarRange (minmax); 01047 01048 // Update the mapper 01049 reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata); 01050 return (true); 01051 } 01052 01054 template <typename PointT> bool 01055 pcl::visualization::PCLVisualizer::addPolygonMesh ( 01056 const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 01057 const std::vector<pcl::Vertices> &vertices, 01058 const std::string &id, 01059 int viewport) 01060 { 01061 if (vertices.empty () || cloud->points.empty ()) 01062 return (false); 01063 01064 CloudActorMap::iterator am_it = cloud_actor_map_->find (id); 01065 if (am_it != cloud_actor_map_->end ()) 01066 { 01067 pcl::console::print_warn ( 01068 "[addPolygonMesh] A shape with id <%s> already exists! Please choose a different id and retry.\n", 01069 id.c_str ()); 01070 return (false); 01071 } 01072 01073 // Create points from polyMesh.cloud 01074 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New (); 01075 vtkIdType nr_points = cloud->points.size (); 01076 points->SetNumberOfPoints (nr_points); 01077 vtkSmartPointer<vtkLODActor> actor; 01078 01079 // Get a pointer to the beginning of the data array 01080 float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0); 01081 01082 int ptr = 0; 01083 std::vector<int> lookup; 01084 // If the dataset is dense (no NaNs) 01085 if (cloud->is_dense) 01086 { 01087 for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3) 01088 memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3); 01089 } 01090 else 01091 { 01092 lookup.resize (nr_points); 01093 vtkIdType j = 0; // true point index 01094 for (vtkIdType i = 0; i < nr_points; ++i) 01095 { 01096 // Check if the point is invalid 01097 if (!isFinite (cloud->points[i])) 01098 continue; 01099 01100 lookup[i] = j; 01101 memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3); 01102 j++; 01103 ptr += 3; 01104 } 01105 nr_points = j; 01106 points->SetNumberOfPoints (nr_points); 01107 } 01108 01109 // Get the maximum size of a polygon 01110 int max_size_of_polygon = -1; 01111 for (size_t i = 0; i < vertices.size (); ++i) 01112 if (max_size_of_polygon < (int)vertices[i].vertices.size ()) 01113 max_size_of_polygon = vertices[i].vertices.size (); 01114 01115 if (vertices.size () > 1) 01116 { 01117 // Create polys from polyMesh.polygons 01118 vtkSmartPointer<vtkCellArray> cell_array = vtkSmartPointer<vtkCellArray>::New (); 01119 vtkIdType *cell = cell_array->WritePointer (vertices.size (), vertices.size () * (max_size_of_polygon + 1)); 01120 int idx = 0; 01121 if (lookup.size () > 0) 01122 { 01123 for (size_t i = 0; i < vertices.size (); ++i, ++idx) 01124 { 01125 size_t n_points = vertices[i].vertices.size (); 01126 *cell++ = n_points; 01127 //cell_array->InsertNextCell (n_points); 01128 for (size_t j = 0; j < n_points; j++, ++idx) 01129 *cell++ = lookup[vertices[i].vertices[j]]; 01130 //cell_array->InsertCellPoint (lookup[vertices[i].vertices[j]]); 01131 } 01132 } 01133 else 01134 { 01135 for (size_t i = 0; i < vertices.size (); ++i, ++idx) 01136 { 01137 size_t n_points = vertices[i].vertices.size (); 01138 *cell++ = n_points; 01139 //cell_array->InsertNextCell (n_points); 01140 for (size_t j = 0; j < n_points; j++, ++idx) 01141 *cell++ = vertices[i].vertices[j]; 01142 //cell_array->InsertCellPoint (vertices[i].vertices[j]); 01143 } 01144 } 01145 vtkSmartPointer<vtkPolyData> polydata; 01146 allocVtkPolyData (polydata); 01147 cell_array->GetData ()->SetNumberOfValues (idx); 01148 cell_array->Squeeze (); 01149 polydata->SetStrips (cell_array); 01150 polydata->SetPoints (points); 01151 01152 createActorFromVTKDataSet (polydata, actor, false); 01153 } 01154 else 01155 { 01156 vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New (); 01157 size_t n_points = vertices[0].vertices.size (); 01158 polygon->GetPointIds ()->SetNumberOfIds (n_points - 1); 01159 01160 if (lookup.size () > 0) 01161 { 01162 for (size_t j = 0; j < (n_points - 1); ++j) 01163 polygon->GetPointIds ()->SetId (j, lookup[vertices[0].vertices[j]]); 01164 } 01165 else 01166 { 01167 for (size_t j = 0; j < (n_points - 1); ++j) 01168 polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]); 01169 } 01170 vtkSmartPointer<vtkUnstructuredGrid> poly_grid; 01171 allocVtkUnstructuredGrid (poly_grid); 01172 poly_grid->Allocate (1, 1); 01173 poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ()); 01174 poly_grid->SetPoints (points); 01175 poly_grid->Update (); 01176 01177 createActorFromVTKDataSet (poly_grid, actor, false); 01178 } 01179 actor->GetProperty ()->SetRepresentationToSurface (); 01180 actor->GetProperty ()->BackfaceCullingOn (); 01181 actor->GetProperty ()->EdgeVisibilityOff (); 01182 actor->GetProperty ()->ShadingOff (); 01183 addActorToRenderer (actor, viewport); 01184 01185 // Save the pointer/ID pair to the global actor map 01186 (*cloud_actor_map_)[id].actor = actor; 01187 //if (vertices.size () > 1) 01188 // (*cloud_actor_map_)[id].cells = static_cast<vtkPolyDataMapper*>(actor->GetMapper ())->GetInput ()->GetVerts ()->GetData (); 01189 return (true); 01190 } 01191 01193 template <typename PointT> bool 01194 pcl::visualization::PCLVisualizer::updatePolygonMesh ( 01195 const typename pcl::PointCloud<PointT>::ConstPtr &cloud, 01196 const std::vector<pcl::Vertices> &verts, 01197 const std::string &id) 01198 { 01199 if (verts.empty ()) 01200 { 01201 pcl::console::print_error ("[addPolygonMesh] No vertices given!\n"); 01202 return (false); 01203 } 01204 01205 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 01206 CloudActorMap::iterator am_it = cloud_actor_map_->find (id); 01207 if (am_it == cloud_actor_map_->end ()) 01208 return (false); 01209 01210 // Get the current poly data 01211 vtkSmartPointer<vtkPolyData> polydata = static_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput (); 01212 if (!polydata) 01213 return (false); 01214 vtkSmartPointer<vtkCellArray> cells = polydata->GetStrips (); 01215 if (!cells) 01216 return (false); 01217 vtkSmartPointer<vtkPoints> points = polydata->GetPoints (); 01218 // Copy the new point array in 01219 vtkIdType nr_points = cloud->points.size (); 01220 points->SetNumberOfPoints (nr_points); 01221 01222 // Get a pointer to the beginning of the data array 01223 float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0); 01224 01225 int ptr = 0; 01226 std::vector<int> lookup; 01227 // If the dataset is dense (no NaNs) 01228 if (cloud->is_dense) 01229 { 01230 for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3) 01231 memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3); 01232 } 01233 else 01234 { 01235 lookup.resize (nr_points); 01236 vtkIdType j = 0; // true point index 01237 for (vtkIdType i = 0; i < nr_points; ++i) 01238 { 01239 // Check if the point is invalid 01240 if (!isFinite (cloud->points[i])) 01241 continue; 01242 01243 lookup [i] = j; 01244 memcpy (&data[ptr], &cloud->points[i].x, sizeof (float) * 3); 01245 j++; 01246 ptr += 3; 01247 } 01248 nr_points = j; 01249 points->SetNumberOfPoints (nr_points); 01250 } 01251 01252 // Get the maximum size of a polygon 01253 int max_size_of_polygon = -1; 01254 for (size_t i = 0; i < verts.size (); ++i) 01255 if (max_size_of_polygon < (int)verts[i].vertices.size ()) 01256 max_size_of_polygon = verts[i].vertices.size (); 01257 01258 // Update the cells 01259 cells = vtkSmartPointer<vtkCellArray>::New (); 01260 vtkIdType *cell = cells->WritePointer (verts.size (), verts.size () * (max_size_of_polygon + 1)); 01261 int idx = 0; 01262 if (lookup.size () > 0) 01263 { 01264 for (size_t i = 0; i < verts.size (); ++i, ++idx) 01265 { 01266 size_t n_points = verts[i].vertices.size (); 01267 *cell++ = n_points; 01268 for (size_t j = 0; j < n_points; j++, cell++, ++idx) 01269 *cell = lookup[verts[i].vertices[j]]; 01270 } 01271 } 01272 else 01273 { 01274 for (size_t i = 0; i < verts.size (); ++i, ++idx) 01275 { 01276 size_t n_points = verts[i].vertices.size (); 01277 *cell++ = n_points; 01278 for (size_t j = 0; j < n_points; j++, cell++, ++idx) 01279 *cell = verts[i].vertices[j]; 01280 } 01281 } 01282 cells->GetData ()->SetNumberOfValues (idx); 01283 cells->Squeeze (); 01284 // Set the the vertices 01285 polydata->SetStrips (cells); 01286 polydata->Update (); 01287 01288 /* 01289 vtkSmartPointer<vtkLODActor> actor; 01290 if (vertices.size () > 1) 01291 { 01292 } 01293 else 01294 { 01295 vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New (); 01296 size_t n_points = vertices[0].vertices.size (); 01297 polygon->GetPointIds ()->SetNumberOfIds (n_points - 1); 01298 01299 for (size_t j = 0; j < (n_points - 1); ++j) 01300 polygon->GetPointIds ()->SetId (j, vertices[0].vertices[j]); 01301 01302 vtkSmartPointer<vtkUnstructuredGrid> poly_grid; 01303 allocVtkUnstructuredGrid (poly_grid); 01304 poly_grid->Allocate (1, 1); 01305 poly_grid->InsertNextCell (polygon->GetCellType (), polygon->GetPointIds ()); 01306 poly_grid->SetPoints (points); 01307 poly_grid->Update (); 01308 01309 createActorFromVTKDataSet (poly_grid, actor); 01310 } 01311 */ 01312 01313 // Get the colors from the handler 01314 //vtkSmartPointer<vtkDataArray> scalars; 01315 //color_handler.getColor (scalars); 01316 //polydata->GetPointData ()->SetScalars (scalars); 01317 // polydata->Update (); 01318 01319 am_it->second.actor->GetProperty ()->BackfaceCullingOn (); 01320 // am_it->second.actor->Modified (); 01321 01322 return (true); 01323 } 01324 01325 01327 /* Optimized function: need to do something with the signature as it colides with the general T one 01328 bool 01329 pcl::visualization::PCLVisualizer::updatePointCloud (const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr &cloud, 01330 const PointCloudColorHandlerRGBField<pcl::PointXYZRGB> &color_handler, 01331 const std::string &id) 01332 { 01333 win_->SetAbortRender (1); 01334 // Check to see if this ID entry already exists (has it been already added to the visualizer?) 01335 CloudActorMap::iterator am_it = cloud_actor_map_->find (id); 01336 01337 if (am_it == cloud_actor_map_->end ()) 01338 return (false); 01339 01340 // Get the current poly data 01341 vtkSmartPointer<vtkPolyData> polydata = reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput (); 01342 if (!polydata) 01343 return (false); 01344 vtkSmartPointer<vtkCellArray> vertices = polydata->GetVerts (); 01345 vtkSmartPointer<vtkPoints> points = polydata->GetPoints (); 01346 // vtkUnsignedCharArray* scalars = vtkUnsignedCharArray::SafeDownCast (polydata->GetPointData ()->GetScalars ()); 01347 vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New (); 01348 // Copy the new point array in 01349 vtkIdType nr_points = cloud->points.size (); 01350 points->SetNumberOfPoints (nr_points); 01351 scalars->SetNumberOfComponents (3); 01352 scalars->SetNumberOfTuples (nr_points); 01353 polydata->GetPointData ()->SetScalars (scalars); 01354 unsigned char* colors = scalars->GetPointer (0); 01355 01356 // Get a pointer to the beginning of the data array 01357 float *data = ((vtkFloatArray*)points->GetData ())->GetPointer (0); 01358 01359 // If the dataset is dense (no NaNs) 01360 if (cloud->is_dense) 01361 { 01362 for (vtkIdType i = 0; i < nr_points; ++i) 01363 { 01364 memcpy (&data[i * 3], &cloud->points[i].x, 12); // sizeof (float) * 3 01365 int idx = i * 3; 01366 colors[idx ] = cloud->points[i].r; 01367 colors[idx + 1] = cloud->points[i].g; 01368 colors[idx + 2] = cloud->points[i].b; 01369 } 01370 } 01371 else 01372 { 01373 vtkIdType j = 0; // true point index 01374 for (vtkIdType i = 0; i < nr_points; ++i) 01375 { 01376 // Check if the point is invalid 01377 if (!pcl_isfinite (cloud->points[i].x) || 01378 !pcl_isfinite (cloud->points[i].y) || 01379 !pcl_isfinite (cloud->points[i].z)) 01380 continue; 01381 01382 memcpy (&data[j * 3], &cloud->points[i].x, 12); // sizeof (float) * 3 01383 int idx = j * 3; 01384 colors[idx ] = cloud->points[i].r; 01385 colors[idx + 1] = cloud->points[i].g; 01386 colors[idx + 2] = cloud->points[i].b; 01387 j++; 01388 } 01389 nr_points = j; 01390 points->SetNumberOfPoints (nr_points); 01391 scalars->SetNumberOfTuples (nr_points); 01392 } 01393 01394 vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData (); 01395 updateCells (cells, am_it->second.cells, nr_points); 01396 01397 // Set the cells and the vertices 01398 vertices->SetCells (nr_points, cells); 01399 01400 // Update the mapper 01401 reinterpret_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->SetInput (polydata); 01402 return (true); 01403 }*/ 01404 01405 01406 #endif
1.8.0