00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <pcl/io/vtk_lib_io.h>
00039 #include <pcl/io/impl/vtk_lib_io.hpp>
00040 #include <vtkImageData.h>
00041 #include <vtkImageShiftScale.h>
00042 #include <vtkPNGWriter.h>
00043
00045 int
00046 pcl::io::loadPolygonFile (const std::string &file_name, pcl::PolygonMesh& mesh)
00047 {
00048 if (!boost::filesystem::exists(file_name) || boost::filesystem::is_directory(file_name))
00049 {
00050 PCL_ERROR ("[pcl::io::loadPolygonFile]: No such file or directory.\n");
00051 return (0);
00052 }
00053
00054
00055 std::string extension = boost::filesystem::extension(file_name);
00056 if ( extension == ".pcd" )
00057 {
00058 pcl::io::loadPCDFile (file_name, mesh.cloud);
00059 mesh.polygons.resize (0);
00060 return (static_cast<int> (mesh.cloud.width * mesh.cloud.height));
00061 }
00062 else if (extension == ".vtk")
00063 return (pcl::io::loadPolygonFileVTK (file_name, mesh));
00064 else if (extension == ".ply")
00065 return (pcl::io::loadPolygonFilePLY (file_name, mesh));
00066 else if (extension == ".obj")
00067 return (pcl::io::loadPolygonFileOBJ (file_name, mesh));
00068 else if (extension == ".stl" )
00069 return (pcl::io::loadPolygonFileSTL (file_name, mesh));
00070 else
00071 {
00072 PCL_ERROR ("[pcl::io::loadPolygonFile]: Unsupported file type (%s)\n", extension.c_str ());
00073 return (0);
00074 }
00075 }
00076
00078 int
00079 pcl::io::savePolygonFile (const std::string &file_name, const pcl::PolygonMesh& mesh)
00080 {
00081
00082
00083
00084
00085
00086 std::string extension = boost::filesystem::extension (file_name);
00087 if (extension == ".pcd")
00088 {
00089 int error_code = pcl::io::savePCDFile (file_name, mesh.cloud);
00090 if (error_code != 0)
00091 return (0);
00092 return (static_cast<int> (mesh.cloud.width * mesh.cloud.height));
00093 }
00094 else if (extension == ".vtk")
00095 return (pcl::io::savePolygonFileVTK (file_name, mesh));
00096 else if (extension == ".ply")
00097 return (pcl::io::savePolygonFilePLY (file_name, mesh));
00098 else if (extension == ".stl" )
00099 return (pcl::io::savePolygonFileSTL (file_name, mesh));
00100 else
00101 {
00102 PCL_ERROR ("[pcl::io::savePolygonFile]: Unsupported file type (%s)\n", extension.c_str ());
00103 return (0);
00104 }
00105 }
00106
00108 int
00109 pcl::io::loadPolygonFileVTK (const std::string &file_name, pcl::PolygonMesh& mesh)
00110 {
00111 vtkSmartPointer<vtkPolyData> poly_data = vtkSmartPointer<vtkPolyData>::New ();
00112
00113 vtkSmartPointer<vtkPolyDataReader> ply_reader = vtkSmartPointer<vtkPolyDataReader>::New ();
00114 ply_reader->SetFileName (file_name.c_str ());
00115 ply_reader->Update ();
00116 poly_data = ply_reader->GetOutput ();
00117
00118 return (pcl::io::vtk2mesh (poly_data, mesh));
00119 }
00120
00122 int
00123 pcl::io::loadPolygonFilePLY (const std::string &file_name, pcl::PolygonMesh& mesh)
00124 {
00125 vtkSmartPointer<vtkPolyData> poly_data = vtkSmartPointer<vtkPolyData>::New();
00126
00127 vtkSmartPointer<vtkPLYReader> ply_reader = vtkSmartPointer<vtkPLYReader>::New();
00128 ply_reader->SetFileName (file_name.c_str ());
00129 ply_reader->Update ();
00130 poly_data = ply_reader->GetOutput ();
00131
00132 return (pcl::io::vtk2mesh (poly_data, mesh));
00133 }
00134
00136 int
00137 pcl::io::loadPolygonFileOBJ (const std::string &file_name, pcl::PolygonMesh& mesh)
00138 {
00139 vtkSmartPointer<vtkOBJReader> ply_reader = vtkSmartPointer<vtkOBJReader>::New ();
00140 ply_reader->SetFileName (file_name.c_str ());
00141 ply_reader->Update ();
00142
00143 vtkSmartPointer<vtkPolyData> poly_data = ply_reader->GetOutput ();
00144
00145 return (pcl::io::vtk2mesh (poly_data, mesh));
00146 }
00147
00149 int
00150 pcl::io::loadPolygonFileSTL (const std::string &file_name, pcl::PolygonMesh& mesh)
00151 {
00152 vtkSmartPointer<vtkPolyData> poly_data = vtkSmartPointer<vtkPolyData>::New ();
00153
00154 vtkSmartPointer<vtkSTLReader> ply_reader = vtkSmartPointer<vtkSTLReader>::New ();
00155 ply_reader->SetFileName (file_name.c_str ());
00156 ply_reader->Update ();
00157 poly_data = ply_reader->GetOutput ();
00158
00159 return (pcl::io::vtk2mesh (poly_data, mesh));
00160 }
00161
00163 int
00164 pcl::io::savePolygonFileVTK (const std::string &file_name, const pcl::PolygonMesh& mesh)
00165 {
00166 vtkSmartPointer<vtkPolyData> poly_data = vtkSmartPointer<vtkPolyData>::New ();
00167
00168 pcl::io::mesh2vtk (mesh, poly_data);
00169
00170 vtkSmartPointer<vtkPolyDataWriter> poly_writer = vtkSmartPointer<vtkPolyDataWriter>::New ();
00171 poly_writer->SetInput (poly_data);
00172 poly_writer->SetFileName (file_name.c_str ());
00173 poly_writer->Write ();
00174
00175 return (static_cast<int> (mesh.cloud.width * mesh.cloud.width));
00176 }
00177
00179 int
00180 pcl::io::savePolygonFilePLY (const std::string &file_name, const pcl::PolygonMesh& mesh)
00181 {
00182 vtkSmartPointer<vtkPolyData> poly_data = vtkSmartPointer<vtkPolyData>::New ();
00183
00184 pcl::io::mesh2vtk (mesh, poly_data);
00185
00186 vtkSmartPointer<vtkPLYWriter> poly_writer = vtkSmartPointer<vtkPLYWriter>::New ();
00187 poly_writer->SetInput (poly_data);
00188 poly_writer->SetFileName (file_name.c_str ());
00189 poly_writer->SetArrayName ("Colors");
00190 poly_writer->Write ();
00191
00192 return (static_cast<int> (mesh.cloud.width * mesh.cloud.width));
00193 }
00194
00196 int
00197 pcl::io::savePolygonFileSTL (const std::string &file_name, const pcl::PolygonMesh& mesh)
00198 {
00199 vtkSmartPointer<vtkPolyData> poly_data = vtkSmartPointer<vtkPolyData>::New ();
00200
00201 pcl::io::mesh2vtk (mesh, poly_data);
00202
00203 vtkSmartPointer<vtkSTLWriter> poly_writer = vtkSmartPointer<vtkSTLWriter>::New ();
00204 poly_writer->SetInput (poly_data);
00205 poly_writer->SetFileName (file_name.c_str ());
00206 poly_writer->Write ();
00207
00208 return (static_cast<int> (mesh.cloud.width * mesh.cloud.width));
00209 }
00210
00212 int
00213 pcl::io::vtk2mesh (const vtkSmartPointer<vtkPolyData>& poly_data, pcl::PolygonMesh& mesh)
00214 {
00215 mesh.polygons.resize (0);
00216 mesh.cloud.data.clear ();
00217 mesh.cloud.width = mesh.cloud.height = 0;
00218 mesh.cloud.is_dense = true;
00219
00220 vtkSmartPointer<vtkPoints> mesh_points = poly_data->GetPoints ();
00221 vtkIdType nr_points = mesh_points->GetNumberOfPoints ();
00222 vtkIdType nr_polygons = poly_data->GetNumberOfPolys ();
00223
00224 if (nr_points == 0)
00225 return (0);
00226
00227 vtkUnsignedCharArray* poly_colors = NULL;
00228 if (poly_data->GetPointData() != NULL)
00229 poly_colors = vtkUnsignedCharArray::SafeDownCast (poly_data->GetPointData ()->GetScalars ("Colors"));
00230
00231
00232 if (!poly_colors && poly_data->GetPointData () != NULL)
00233 poly_colors = vtkUnsignedCharArray::SafeDownCast (poly_data->GetPointData ()->GetScalars ("scalars"));
00234
00235 if (!poly_colors && poly_data->GetPointData () != NULL)
00236 poly_colors = vtkUnsignedCharArray::SafeDownCast (poly_data->GetPointData ()->GetScalars ("RGB"));
00237
00238
00239 if (poly_colors && (poly_colors->GetNumberOfComponents () == 3))
00240 {
00241 pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_temp (new pcl::PointCloud<pcl::PointXYZRGB> ());
00242 cloud_temp->points.resize (nr_points);
00243 double point_xyz[3];
00244 unsigned char point_color[3];
00245 for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints (); i++)
00246 {
00247 mesh_points->GetPoint (i, &point_xyz[0]);
00248 cloud_temp->points[i].x = static_cast<float> (point_xyz[0]);
00249 cloud_temp->points[i].y = static_cast<float> (point_xyz[1]);
00250 cloud_temp->points[i].z = static_cast<float> (point_xyz[2]);
00251
00252 poly_colors->GetTupleValue (i, &point_color[0]);
00253 cloud_temp->points[i].r = point_color[0];
00254 cloud_temp->points[i].g = point_color[1];
00255 cloud_temp->points[i].b = point_color[2];
00256 }
00257 cloud_temp->width = static_cast<uint32_t> (cloud_temp->points.size ());
00258 cloud_temp->height = 1;
00259 cloud_temp->is_dense = true;
00260
00261 pcl::toROSMsg (*cloud_temp, mesh.cloud);
00262 }
00263 else
00264 {
00265 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_temp (new pcl::PointCloud<pcl::PointXYZ> ());
00266 cloud_temp->points.resize (nr_points);
00267 double point_xyz[3];
00268 for (vtkIdType i = 0; i < mesh_points->GetNumberOfPoints (); i++)
00269 {
00270 mesh_points->GetPoint (i, &point_xyz[0]);
00271 cloud_temp->points[i].x = static_cast<float> (point_xyz[0]);
00272 cloud_temp->points[i].y = static_cast<float> (point_xyz[1]);
00273 cloud_temp->points[i].z = static_cast<float> (point_xyz[2]);
00274 }
00275 cloud_temp->width = static_cast<uint32_t> (cloud_temp->points.size ());
00276 cloud_temp->height = 1;
00277 cloud_temp->is_dense = true;
00278
00279 pcl::toROSMsg (*cloud_temp, mesh.cloud);
00280 }
00281
00282 mesh.polygons.resize (nr_polygons);
00283 vtkIdType* cell_points;
00284 vtkIdType nr_cell_points;
00285 vtkCellArray * mesh_polygons = poly_data->GetPolys ();
00286 mesh_polygons->InitTraversal ();
00287 int id_poly = 0;
00288 while (mesh_polygons->GetNextCell (nr_cell_points, cell_points))
00289 {
00290 mesh.polygons[id_poly].vertices.resize (nr_cell_points);
00291 for (int i = 0; i < nr_cell_points; ++i)
00292 mesh.polygons[id_poly].vertices[i] = static_cast<int> (cell_points[i]);
00293 ++id_poly;
00294 }
00295
00296 return (static_cast<int> (nr_points));
00297 }
00298
00300 int
00301 pcl::io::mesh2vtk (const pcl::PolygonMesh& mesh, vtkSmartPointer<vtkPolyData>& poly_data)
00302 {
00303 unsigned int nr_points = mesh.cloud.width * mesh.cloud.height;
00304 unsigned int nr_polygons = static_cast<unsigned int> (mesh.polygons.size ());
00305
00306
00307 poly_data = vtkSmartPointer<vtkPolyData>::New ();
00308 vtkSmartPointer<vtkPoints> vtk_mesh_points = vtkSmartPointer<vtkPoints>::New ();
00309 vtkSmartPointer<vtkCellArray> vtk_mesh_polygons = vtkSmartPointer<vtkCellArray>::New ();
00310 poly_data->SetPoints (vtk_mesh_points);
00311
00312
00313 int idx_x = -1, idx_y = -1, idx_z = -1, idx_rgb = -1, idx_rgba = -1, idx_normal_x = -1, idx_normal_y = -1, idx_normal_z = -1;
00314 for (int d = 0; d < static_cast<int> (mesh.cloud.fields.size ()); ++d)
00315 {
00316 if (mesh.cloud.fields[d].name == "x") idx_x = d;
00317 else if (mesh.cloud.fields[d].name == "y") idx_y = d;
00318 else if (mesh.cloud.fields[d].name == "z") idx_z = d;
00319 else if (mesh.cloud.fields[d].name == "rgb") idx_rgb = d;
00320 else if (mesh.cloud.fields[d].name == "rgba") idx_rgba = d;
00321 else if (mesh.cloud.fields[d].name == "normal_x") idx_normal_x = d;
00322 else if (mesh.cloud.fields[d].name == "normal_y") idx_normal_y = d;
00323 else if (mesh.cloud.fields[d].name == "normal_z") idx_normal_z = d;
00324 }
00325 if ( ( idx_x == -1 ) || ( idx_y == -1 ) || ( idx_z == -1 ) )
00326 nr_points = 0;
00327
00328
00329 vtk_mesh_points->SetNumberOfPoints (nr_points);
00330 if (nr_points > 0)
00331 {
00332 Eigen::Vector4f pt = Eigen::Vector4f::Zero ();
00333 Eigen::Array4i xyz_offset (mesh.cloud.fields[idx_x].offset, mesh.cloud.fields[idx_y].offset, mesh.cloud.fields[idx_z].offset, 0);
00334 for (vtkIdType cp = 0; cp < static_cast<vtkIdType> (nr_points); ++cp, xyz_offset += mesh.cloud.point_step)
00335 {
00336 memcpy(&pt[0], &mesh.cloud.data[xyz_offset[0]], sizeof (float));
00337 memcpy(&pt[1], &mesh.cloud.data[xyz_offset[1]], sizeof (float));
00338 memcpy(&pt[2], &mesh.cloud.data[xyz_offset[2]], sizeof (float));
00339 vtk_mesh_points->InsertPoint (cp, pt[0], pt[1], pt[2]);
00340 }
00341 }
00342
00343
00344 if (nr_polygons > 0)
00345 {
00346 for (unsigned int i = 0; i < nr_polygons; i++)
00347 {
00348 unsigned int nr_points_in_polygon = static_cast<unsigned int> (mesh.polygons[i].vertices.size ());
00349 vtk_mesh_polygons->InsertNextCell (nr_points_in_polygon);
00350 for (unsigned int j = 0; j < nr_points_in_polygon; j++)
00351 vtk_mesh_polygons->InsertCellPoint (mesh.polygons[i].vertices[j]);
00352 }
00353 poly_data->SetPolys (vtk_mesh_polygons);
00354 }
00355
00356
00357 if (idx_rgb != -1 || idx_rgba != -1)
00358 {
00359 vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New ();
00360 colors->SetNumberOfComponents (3);
00361 colors->SetName ("Colors");
00362 pcl::RGB rgb;
00363 int offset = (idx_rgb != -1) ? mesh.cloud.fields[idx_rgb].offset : mesh.cloud.fields[idx_rgba].offset;
00364 for (vtkIdType cp = 0; cp < nr_points; ++cp)
00365 {
00366 memcpy (&rgb, &mesh.cloud.data[cp * mesh.cloud.point_step + offset], sizeof (RGB));
00367 const unsigned char color[3] = {rgb.r, rgb.g, rgb.b};
00368 colors->InsertNextTupleValue (color);
00369 }
00370 poly_data->GetPointData ()->SetScalars (colors);
00371 }
00372
00373
00374 if (( idx_normal_x != -1 ) && ( idx_normal_y != -1 ) && ( idx_normal_z != -1 ))
00375 {
00376 vtkSmartPointer<vtkFloatArray> normals = vtkSmartPointer<vtkFloatArray>::New ();
00377 normals->SetNumberOfComponents (3);
00378 float nx = 0.0f, ny = 0.0f, nz = 0.0f;
00379 for (vtkIdType cp = 0; cp < nr_points; ++cp)
00380 {
00381 memcpy (&nx, &mesh.cloud.data[cp*mesh.cloud.point_step+mesh.cloud.fields[idx_normal_x].offset], sizeof (float));
00382 memcpy (&ny, &mesh.cloud.data[cp*mesh.cloud.point_step+mesh.cloud.fields[idx_normal_y].offset], sizeof (float));
00383 memcpy (&nz, &mesh.cloud.data[cp*mesh.cloud.point_step+mesh.cloud.fields[idx_normal_z].offset], sizeof (float));
00384 const float normal[3] = {nx, ny, nz};
00385 normals->InsertNextTupleValue (normal);
00386 }
00387 poly_data->GetPointData()->SetNormals (normals);
00388 }
00389
00390 if (poly_data->GetPoints () == NULL)
00391 return (0);
00392 return (static_cast<int> (poly_data->GetPoints ()->GetNumberOfPoints ()));
00393 }
00394
00396 void
00397 pcl::io::saveRangeImagePlanarFilePNG (
00398 const std::string &file_name, const pcl::RangeImagePlanar& range_image)
00399 {
00400 vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New();
00401 image->SetDimensions(range_image.width, range_image.height, 1);
00402 image->SetNumberOfScalarComponents(1);
00403 image->SetScalarTypeToFloat();
00404 image->AllocateScalars();
00405
00406 int* dims = image->GetDimensions();
00407
00408 for (int y = 0; y < dims[1]; y++)
00409 {
00410 for (int x = 0; x < dims[0]; x++)
00411 {
00412 float* pixel = static_cast<float*>(image->GetScalarPointer(x,y,0));
00413 pixel[0] = range_image(y,x).range;
00414 }
00415 }
00416
00417
00418 float oldRange = static_cast<float> (image->GetScalarRange()[1] - image->GetScalarRange()[0]);
00419 float newRange = 255;
00420
00421 vtkSmartPointer<vtkImageShiftScale> shiftScaleFilter = vtkSmartPointer<vtkImageShiftScale>::New();
00422 shiftScaleFilter->SetOutputScalarTypeToUnsignedChar();
00423 shiftScaleFilter->SetInputConnection(image->GetProducerPort());
00424 shiftScaleFilter->SetShift(-1.0f * image->GetScalarRange()[0]);
00425 shiftScaleFilter->SetScale(newRange/oldRange);
00426 shiftScaleFilter->Update();
00427
00428 vtkSmartPointer<vtkPNGWriter> writer = vtkSmartPointer<vtkPNGWriter>::New();
00429 writer->SetFileName(file_name.c_str());
00430 writer->SetInputConnection(shiftScaleFilter->GetOutputPort());
00431 writer->Write();
00432 }