貪婪三角形投影算法
在pcl-1.8測試
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/vtk_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <fstream>
#include <iostream>
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv)
{
// 點雲模型讀入,此處讀入為PCD格式點雲文件.數據類型為PointXYZ.
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[1], *cloud) == -1)
{
PCL_ERROR("Couldn't read file mypointcloud.pcd\n"); //若讀取失敗將提示
return -1;
}
std::cerr << "點雲讀入 完成" << std::endl;
//sensor_msgs::PointCloud2 cloud_blob;
//pcl::io::loadPCDFile ("bun0.pcd", cloud_blob);
//pcl::fromROSMsg (cloud_blob, *cloud);
//* the data should be available in cloud
// Normal estimation(法向量估計)
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;//創建法向估計對象
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);//創建法向數據指針
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);//創建kdtree用於法向計算時近鄰搜索
tree->setInputCloud(cloud);//為kdtree輸入點雲
n.setInputCloud(cloud);//為法向估計對象輸入點雲
n.setSearchMethod(tree);//設置法向估計時采用的搜索方式為kdtree
n.setKSearch(20);//設置法向估計時,k近鄰搜索的點數
n.compute(*normals); //進行法向估計
std::cerr << "法線計算 完成" << std::endl;
// 創建同時包含點和法向的數據結構的指針
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);
//將已獲得的點數據和法向數據拼接
pcl::concatenateFields(*cloud, *normals, *cloud_with_normals);
// 創建另一個kdtree用於重建
pcl::search::KdTree<pcl::PointNormal>::Ptr tree2(new pcl::search::KdTree<pcl::PointNormal>);
//為kdtree輸入點雲數據,該點雲數據類型為點和法向
tree2->setInputCloud(cloud_with_normals);
// 創建貪婪三角形投影重建對象
pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;
//創建多邊形網格對象,用來存儲重建結果
pcl::PolygonMesh triangles;
//設置參數
gp3.setSearchRadius(25); // 設置連接點之間的最大距離(最大邊長)用於確定k近鄰的球半徑(默認為0)
gp3.setMu(2.5); // 設置最近鄰距離的乘子,已得到每個點的最終搜索半徑(默認為0)
gp3.setMaximumNearestNeighbors(100); //設置搜索的最近鄰點的最大數量
gp3.setMaximumSurfaceAngle(M_PI / 2); // 45 degrees 最大平面角
gp3.setMinimumAngle(M_PI / 18); // 10 degrees 每個三角的最大角度
gp3.setMaximumAngle(2 * M_PI / 3); // 120 degrees
gp3.setNormalConsistency(false); //若法向量一致,設為true
// 設置點雲數據和搜索方式
gp3.setInputCloud(cloud_with_normals);
gp3.setSearchMethod(tree2);
//開始重建
gp3.reconstruct(triangles);
std::cerr << "重建 完成" << std::endl;
//將重建結果保存到硬盤文件中,重建結果以VTK格式存儲
pcl::io::saveVTKFile("mymesh.vtk", triangles);
// Additional vertex information
std::vector<int> parts = gp3.getPartIDs();
std::vector<int> states = gp3.getPointStates();
fstream fs;
fs.open("partsID.txt", ios::out);
if (!fs)
{
return -2;
}
fs << "點雲數量為:" << parts.size() << "\n";
for (int i = 0; i < parts.size(); i++)
{
if (parts[i] != 0)
{
fs << parts[i] << "\n"; //這的fs對嗎?
}
}
std::cerr << "開始顯示 ........" << std::endl;
//圖形顯示模塊
//創建顯示對象指針
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
viewer->setBackgroundColor(0, 0, 0.6); //設置窗口顏色
viewer->addPolygonMesh(triangles, "my"); //設置所要顯示的網格對象
viewer->addCoordinateSystem(0.1); //設置坐標系,參數為坐標顯示尺寸
viewer->initCameraParameters();
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
// Finish
return 0;
}