OSG之Delaunay 三角网绘制

628 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 31 天

1 Delaunay 三角网绘制

1.1 TIN模型

在数字地形建模中,不规则三角网(TIN)通过从不规则离散分布的数据点生成的连续三角面来逼近地形表面。就表达地形信息的角度而言,TIN 模型的优点是它能以不同层次的分辨率来描述地形表面。与格网数据模型相比,TIN 模型在某一特定分辨率下能用更少的空间和时间更精确地表示更加复杂的表面。

特别是当地形包含有大量特征,如断裂线、构造线时,TIN 模型能更好地顾及这些特征,从而能更精确合理地表达地表形态。

对于TIN模型,其基本要求有以下3点:

(1)TIN是唯一的。

(2)力求最佳三角形几何形状。

(3)保证最邻近的点构成三角形。

在所有可能的三角网中,狄洛尼(Delaunay)三角网在地形拟合方面表现最为出色,常用于TIN的生成。当不相交的断裂线等被作为预先定义的限制条件作用于TIN的生成当中时,就必须考虑带约束条件的狄洛尼三角网。

目前,狄洛尼三角网生成的算法比较多,传统的算法主要包括两种,即Lawson 算法以及Bowyer—Watson 算法。后来经过该传统算法改进的算法就多了,这里不专门对这些算法予以介绍,可参考相关论文。

1.2 osgUtil::DelaunayTriangulator类

上面介绍了狄洛尼(Delaunay)三角网的特性、生成算法及应用,下面来看一下OSG中的狄洛尼三角网。

osgUtil::DelaunayTriangulator 类直接继承自 osg::Referenced类,继承关系图如下图所示。

2.png

创建狄洛尼三角网有如下3个步骤:

(1)创建顶点数组。

(2)创建一个osgUtil::DelaunayTriangulator 对象,并初始化顶点数组,同时生成三角网,程序代码如下:

bool triangulate() //开始生成三角网格

(3)创建一个几何体对象,把osgUtil:DelaunayTriangulator 类对象生成的绘制图元加入到几何体中。在生成狄洛尼三角网时,读者还可以添加一些限制条件,限制条件可以是点、线或多边形,

例如:

void addInputConstraint(DelaunayConstraint* dc)//添加限制条件

通过这么多的讲解,读者应该清楚了狄洛尼三角网的绘制方法了吧。有兴趣的读者可以研究关于狄洛尼三角网的算法。

2 Delaunay 三角网绘制示例

Delaunay 三角网绘制(osgUtil::DelaunayTriangulator)示例的代码如程序清单所示。


#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Geometry>

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <osgGA/StateSetManipulator>

#include <osgUtil/Optimizer>
#include <osgUtil/DelaunayTriangulator>

#include "Tex.h"

#include "utility.h"

int main()
{
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
	//方便查看在多边形之间切换,以查看三角网
	viewer->addEventHandler( new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()) );

	osg::ref_ptr<osg::Group> root = new osg::Group();

	//创建顶点数组
	osg::ref_ptr<osg::Vec3Array> coords = new osg::Vec3Array();

	//计算顶点数组的大小
	unsigned int n = sizeof(vertex)/sizeof(float[3]);

	//添加顶点数据
	for( unsigned int i = 0; i < n; i++ )
	{
		coords->push_back( osg::Vec3(vertex[i][0], vertex[i][1], vertex[i][2] ));
	}

	//创建Delaunay三角网对象
	osg::ref_ptr<osgUtil::DelaunayTriangulator> dt = new osgUtil::DelaunayTriangulator(coords.get());
	//生成三角网
	dt->triangulate();

	//创建几何体
	osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();
	//设置顶点数组
	geometry->setVertexArray(coords.get());

	//加入到绘图基元
	geometry->addPrimitiveSet(dt->getTriangles());

	//添加到叶节点
	osg::ref_ptr<osg::Geode> geode = new osg::Geode();
	geode->addDrawable( geometry.get());

	root->addChild(geode.get()) ;

	//优化场景数据
	osgUtil::Optimizer optimizer;
	optimizer.optimize(root.get());

	setWindowSize(viewer.get(), 700, 400, "DelaunayTriangulator");

	viewer->setSceneData(root.get());

	viewer->realize();

	viewer->run();

	return 0 ;
}

效果图

3.PNG

动态效果图

1.gif

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 31 天