OSG中的DelaunayTriangulator三角化方法和结果转化为PCL的mesh形式

本文的目的是了解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进行读写;


版权声明:本文为zhaoxr233原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。