图1 测试地形等高线图
内插算法的可视化的实现
1、读取文件中离散点数据
离散点数据包括平面位置和高程两种信息,可以直接在野外通过全站仪或者GPS、激光测距仪等进行测量,也可以间接地从航空影像或者遥感图象以及既有地形图上得到。具体采用何种数据源和相应的测量技术,一方面取决于这些源数据的可获得性,另一方面也取决于DEM的分辨率、精度要求、数据量大小和技术要求等。
对于离散点的数据,往往是很大的,我们只有按照一定数据结构存储在*.dem文件中,才能便于管理和修改。在程序中通过读取文件,可以得到任意一个文件中的地形信息。为了测试的需要,依据图1中的等高线我们可以采集到一些特征点的三维信息。例如,我们采集10个点的信息,将其存入文件中,其结构如下所示:
10 0.0 0.0 0.0 10.0 10.0 10.0 10.0 0.0 0.0 3.6 3.0 7.1 3.6 7.1 3.0 2.3 5.5 5.5 1.4 5.7 8.0 1.0 8.0 8.0 0.5 9.0 2.0 1.3 6.0 1.2 1.0 5.0 4.0 1.0 1.0 7.2 2.0 2.0 2.0 0.3
在实例中每个数据按照5个字符来存储。第一个数据为采样离散点的总数,第二到第九个数据分别为所选地形左下、左上、右上、右下点的平面X和Y的坐标,第十和第十一个数据为地形的最小高程值和最大高程值,余下的数据每三个为采样离散点的三维坐标X、Y和Z,共有十个。
在LoadFileData类中,需要先定义如下:
public int DataNum; //离散点的总数 public double[,] DataPoint=new double [50,3]; //离散数据点的三维坐标 int readDemPosition; // 读取位置 string DemFileContent; //DEM文件内容 public struct Point { public double x; public double y; } public struct DEMStruct { public Point LeftBottom; public Point LeftTop; public Point RightTop; public Point RightBottom; public double MinElevation; public double MaxElevation; } public DEMStruct DemDataStruct;//存储*.dem文件中前十一个数据 |
同时在主程序中,还需要调用如下两个读取int型和double型的函数:
private int readInt() { string tmps ; tmps = DemFileContent.Substring(readDemPosition,5); readDemPosition += 5; return ( Convert.ToInt32(tmps)); } private double readDouble() { string tmps; tmps = DemFileContent.Substring(readDemPosition,5); readDemPosition += 5; return (Convert.ToDouble(tmps)); } |
通过读取文件中的数据,我们可以很容易的得到地图的四边、地图中心点坐标和最大与最小高层差,以便在绘制地形时确定屏幕的显示位置和鼠标控制的缩放和移动比例。
2、利用OpenGL实现算法的可视化
Open GL是Open Graphics Library 的缩写,它是SGI公司开发的一套高性能图形处理系统,是图形硬件的软件接口,意为开放的图形库。通过OpenGL程序员可以创建交互式的应用程序,实现具有逼真效果的三维图形图像。由于其开放性和高度的可重用性,目前已成为业界标准。 OpenGL被设计成独立于硬件,独立于窗口系统的,在运行各种操作系统的各种计算机上都可用,并能在网络环境下以客户/服务器模式工作,是专业图形处理、科学计算等高端应用领域的标准图形库。
为了便于我们后期的LOD地形简化,我们一般要将地形绘制成三角格网的形式。在绘制三角形时,由于地形不可能都是规则的长方形或正方形,考虑到一般地形的多样性和复杂性,不能够将点简单的连线。根据三角形的四种形式,每个构成三角形的点都先按照四边形的方式进行划分成四个点(如图2)。
图2 三角形四种情况下点的的划分
在图中,三角形中必有一个点被两个编号所代表,然后按照1-2-4-1-3-4的顺序进行连接,必然能绘制出四种情况中的任何一种三角形。通过上述操作,可以实现程序能运用到所有地形的显示。
程序代码如下:
private void DrawTriangle (Point3D Point1, Point3D Point2, Point3D Point3, Point3D Point4 ) { GL.glBegin(GL.GL_TRIANGLES);//开始绘三角形 GL.glVertex3d(Point1.x, Point1.y, Point1.z);//从1起笔 GL.glVertex3d(Point2.x, Point2.y, Point2.z);//画到2 GL.glVertex3d(Point4.x, Point4.y, Point4.z); //画到4 GL.glVertex3d(Point1.x, Point1.y, Point1.z); //画到1 GL.glVertex3d(Point3.x, Point3.y, Point3.z); //画到3 GL.glVertex3d(Point4.x, Point4.y, Point4.z); //画到4 GL.glEnd();//完成一个三角形的绘制 } |
通过上述操作,可以将图2的点视图转化为三角形格网试图(如图3)。
(a)加权平均内插数学模型
(b)多面函数内插数学模型
(c)最小二乘内插数学模型
图3 利用搜索圆实现地形的三角形格网视图
结论
在现实中,我们需要生成的地形往往是很庞大,很复杂的,因此不能够仅利用某一种算法和某一种搜索方式生成全部的地形。对于大范围的复杂地形,就必须先对地形按起伏程度进行区域分块,对不同的区域选择合适的算法和搜索方式。