本文的目的是了解OSG::DelaunayTriangulator方法实现三角化的相关知识
最初的目的是想利用osg中的Delaunay三角化方法进行3维点云的网格重建,但是最终没能达到目的,本文知识记录了我的学习过程、相关的理论方法以及相关的知识,如果有误,希望可以联系我进行改正;
基础:使用该方法必须安装OpenSceneGraph库,可以直接安装或者源码编译安装,后者安装麻烦但是便于查看跟踪代码,由于笔者编译源码没有成功,所以笔者这里是直接安装,然后根据源码中的代码去仔细观察学习他的实现过程,理论知识见Delaunay三角化算法,首先了解一下OSG中的Delaunay三角化方法的过程:
ps:整个方法是基于三维点投影到xy所在二维平面进行三角化的,这也是没能达到最初的目的的原因,也可能还有其他原因,但是目前笔者还没有研究出来;
1、添加约束顶点(需要手动添加约束,否则这一步是不起作用的)
2、按照xy最小值最大值,增加四个扩充顶点,按照xyz的优先顺序将所有的点进行排序
3、由扩充点构成两个超级三角形
4、对于数据集中的每一个数据顶点,建立一个边集合
对于每一个三角形
如果该点x值减去对应外接圆圆心的x大于半径,则该三角形移除,加入discardTri(数据点是排好序的,后面的点不可能存在该三角形对应的外接圆内部);
如果该点在该三角形的外接圆中,则移除该三角形,并将它的边加入到边集合中,对于重复的边进行标记(该边所在的两个三角形的外接圆都包含当前新加入的顶点);
5、如果有需要进行约束三角化,这个阶段有可能会增加新的顶点
6、删除四个扩充的顶点和相关的三角形,并将后面约束三角化中新增的顶点索引向前移动4个位置,输出顶点和三角形信息,然后三角化过程结束;
第二步,关于代码实现,调用该函数,并将三角化后的结果转换为PCL中的mesh类型,由于第一次使用OSG,很多数据结构不清楚,关于类型的转换踩了很多坑,所以记录一下
void swDelaunyTrangulate(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud, pcl::PolygonMesh &mesh){
//void swDelaunyTrangulate(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud, osg::Node* node){
osg::ref_ptr<osg::Vec3Array> vertexArray = new osg::Vec3Array();
for (int i = 0; i < cloud->points.size(); i++){
pcl::PointXYZ p = cloud->points[i];
vertexArray->push_back(osg::Vec3(p.x, p.y, p.z));
}
std::cout << "转换点的数组结束" << std::endl;
time_t time1, time2;
time(&time1);
//pcl::PolygonMesh mesh;
pcl::toPCLPointCloud2(*cloud, mesh.cloud);
osg::ref_ptr<osgUtil::DelaunayTriangulator> dt = new osgUtil::DelaunayTriangulator();
dt->setInputPointArray(vertexArray);
dt->triangulate();
std::cout << "三角化结束" << std::endl;
time(&time2);
std::cout << "OSG Triangulate time : " << time2 - time1 << "s" << std::endl;
转化为osg中的node形式进行写出网格模型
//osg::Geometry* geom = new osg::Geometry();
//geom->setVertexArray(vertexArray);
//geom->addPrimitiveSet(dt->getTriangles());
//osg::Geode* geode = new osg::Geode();
//geode->addDrawable(geom);
//node = (osg::Node*)(geode);
//osgDB::writeNodeFile(*node, "delaunay_chef_view1.obj");
osg::DrawElementsUInt* deu = dt->getTriangles();
osg::VectorGLuint ptVector = deu->asVector();
std::cout << " deu->size() " << deu->size() << "; ptVector.size()/3 "<<ptVector.size()/3<< std::endl;
std::cout << "triangles size : " << ptVector.size()/3 << std::endl;
//将osg中的三角形格式转化为pcl中的mesh类型
for (int i = 0; i < ptVector.size(); i=i+3){
pcl::Vertices tri;
tri.vertices.push_back(ptVector[i]);
tri.vertices.push_back(ptVector[i+1]);
tri.vertices.push_back(ptVector[i+2]);
mesh.polygons.push_back(tri);
}
std::cout << "三角形网格转换结束" << std::endl;
return;
}
由于OSG中的模型读写比较麻烦,所以这里转换为PCL中的mesh进行读写;