由于自己需要对点云数据进行分段建模,建模之后所生成的文件是ply格式的,里面包含了
element face这个重要信息。
大部分大佬的教程是先将ply文件转为pcd文件,再将pcd文件合并之后再次转移成为ply文件,但是
利用PCLPointCloud2转变后的ply文件丢失了element face的数量和具体的索引。
所以可以利用PolygonMesh将ply文件读取之后进行合并。(利用 PolygonMesh.concatenate()即可。)
但是利用该函数合并之后的索引信息是有bug的, 他对索引信息值直接会增加全部点云数量的值(假设mesh1和mesh2分别有10个和20个值,那么在合并后的mesh3文件后面的索引信息中,mesh2的索引信息值不是从20开始,反而变成从30开始,导致索引错误,那么拼接之后的模型是显示不成功的)。
下面贴上对应的解决方法,由于时间有点急,写的比较乱,整体思路就是把合并之后的mesh3文件后面的索引信息值进行修改,利用的也就是c++中简单的文件读和写操作。
int contenate_ply()
{
pcl::PolygonMesh mesh1;
pcl::io::loadPLYFile("C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D-1.ply", mesh1);
pcl::PolygonMesh mesh2;
pcl::io::loadPLYFile("C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D-2.ply", mesh2);
pcl::PolygonMesh mesh3;
mesh3.concatenate(mesh1, mesh2, mesh3);
pcl::io::savePLYFile("C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D.ply", mesh3);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPLYFile<pcl::PointXYZ>("C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D-1.ply", *cloud1);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud2(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPLYFile<pcl::PointXYZ>("C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D-2.ply", *cloud2);
int sum = cloud1->points.size();
cout << "point_1_number:" << sum << endl;
rename("C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D-1.ply", "C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D-1.txt");
fstream fin("C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D-1.txt", ios::in);
if (!fin)
{
cerr << "can not open file" << endl;
return -1;
}
char c1;
int lineCnt = 0;
while (fin.get(c1))
{
if (c1 == '\n')
lineCnt++;
}
cout << lineCnt + 1 + cloud2->points.size() << endl;
int total = lineCnt + 1 + cloud2->points.size();
fin.close();
rename("C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D-1.txt", "C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D-1.ply");
rename("C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D.ply", "C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D.txt");
fstream fin1("C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D.txt", ios::in);
if (!fin1)
{
cerr << "can not open file" << endl;
return -1;
}
char cc;
lineCnt = 0;
while (fin1.get(cc))
{
if (cc == '\n')
lineCnt++;
}
cout << lineCnt + 1 << endl;
int txttotal = lineCnt + 1;
fin1.close();
std::queue<int> a;
std::queue<int> b;
std::queue<int> c;
std::queue<int> d;
ifstream f;//读权限变量 f
std::queue<std::string> r;//用于存储
f.open("C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D.txt");//文件text需要存放在当前cpp文件的根目录中
std::string linee, s;
int txtLine = 1;
while (getline(f, linee)) //从文件中读取一行存放在line中
{
int aaa, bbb, ccc, ddd;
r.push(linee);
if (txtLine >= total && txtLine < txttotal)
{
std::istringstream is(linee);
is >> aaa >> bbb >> ccc >> ddd;
cout << aaa << " " << bbb << " " << ccc << "" << ddd << endl;
a.push(aaa);
b.push(bbb);
c.push(ccc);
d.push(ddd);
}
txtLine++;
}
ifstream in;
in.open("C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D.txt");
std::string strFileData = "";
int line = 1;
char tmpLineData[1024] = { 0 };
while (in.getline(tmpLineData, sizeof(tmpLineData)))
{
if (line >= total && line < txttotal)
{
strFileData += std::string("3 " + std::to_string(b.front() - cloud2->points.size()) + " " + std::to_string(c.front() - cloud2->points.size()) + " " + std::to_string(d.front() - cloud2->points.size()));
strFileData += "\n";
b.pop();
c.pop();
d.pop();
}
else
{
strFileData += std::string(tmpLineData);
strFileData += "\n";
}
line++;
}
in.close();
//写入文件
ofstream out;
out.open("C:\\Users\\A\\Desktop\\c\\A10-16008\\mesh3D.txt");
out.flush();
out << strFileData;
out.close();
}
效果如下
这两个要进行拼接的ply文件展示图
欢迎各位做pcl的大牛们指点交流