VC、OpenGL、ArcGIS Engine开发的二维三维结合的GIS系统

 1、前言git

  众所周知,二维GIS技术发展了近四十年,伴随着计算机软硬件以及关系型数据库的飞速发展,二维GIS技术已日臻完善。在对地理信息的分析功能上有着无可比拟的优点。一些宏观的地理信息,一维的地理信息,如河流、公路等,以及二维的地理信息,如植被、湖泊、人口数量等,在对这些地理信息的分析和处理上,比较适合采用二维GIS系统。二维GIS始于20世纪60年代的机助制图,今天它已经深刻社会的各行各业,如土地管理、电力、电信、水利、消防、交通、规划等,但二维GIS有其自身难以克服的缺陷,它本质上是基于抽象符号的系统,不能真实的再现三维客观世界。随着信息技术的快速发展特别是数字地球(Digital Earth)的提出与实施,以及GIS应用深度和广度的不断扩大,二维GIS已经没法知足用户的需求,用户对三维GIS的需求愈发迫切。伴随着计算机显示设备以及存储设备的进步,三维GIS也获得了必定的发展,GIS正在经历一个由二维向三维发展的过程。算法

  三维GIS最大优势是能够真实的再现现实环境中的地理信息,如地形、地貌等。利用三维GIS技术和DEM、纹理数据能够实现真实感地形地貌的生成功能,以及实时漫游功能等,对于一些只有三维GIS技术才能实现的功能,也必须由三维GIS技术实现,如为了更加直观地理解空间查询和分析的结果、提升空间分析的水平,有必要恢复三维空间关系,并进行透视显示。可是三维GIS才起步不久,并无成熟的空间数据模型给予其强有力的支撑,空间数据库也并不能彻底表达空间实体的复杂关系。三维GIS的核心便是地形三维可视化及其查询分析,地形三维可视化技术自20世纪90年代以来一直是地理信息系统领域开发和应用的热点方向之一,地形三维可视化是一门利用数字化高程模型(DEM)显示仿真内容的学科,是图形学研究方向的热门课题,而DEM数据的三维显示是地形三维可视化的基础。近年来,地形三维可视化技术愈来愈普遍地运用于地理信息系统、防洪决策系统、虚拟环境仿真、国土资源管理等领域。随着科学技术的发展,地形三维可视化逐渐成为当前对河道、湖泊和港口等进行防洪预测、河床演变分析研究的前沿及主要手段,同时也是快速、及时再现地形三维信息及分析的有效手段。现有的三维GIS系统中,系统功能在三维场景可视化、实时漫游等方面取得了较好的成果,但查询分析功能比较弱。然而查询分析功能在三维GIS的实现和应用中具备十分重要的地位,它使三维GIS具备辅助决策支持能力。数据库

  综合考虑上述状况及因素,做者认为目前应以开发二维为主、三维为辅的混合型GIS为主要目标,不宜单纯开发三维GIS。在当前GIS产业界,二维GIS已经可以知足大部分实际需求,对三维GIS的需求仍然只占少部分。当前三维GIS在三维数据获取、大数据量处理与存储、三维可视化、三维空间分析方面还不能以较好的性价比知足大规模商业应用的须要。若是彻底采用三维GIS,势必将花费高昂的系统建设费用,在二维GIS可以知足须要的状况下,用户没有必要去一味追求高性能。固然,这里并不排除部分单位研制彻底的三维GIS以知足一些行业的特定须要,如军事、采矿、石油勘探、地质结构研究等工做。因此发挥二维GIS与三维GIS的优点,进行矢量数据与地形三维可视化的结合性研究有很大的实用价值。若是采用三维可视化的方法集成矢量数据,并实现其相关属性的查询分析,将二维GIS的优点用在地形三维可视化中,使二维GIS与三维GIS获得良好的结合,对军事、民航、气象等行业有很是重要的现实意义。安全

  目前不一样的应用目的每每须要二维GIS与三维GIS两种方式交替运做,而不是单一的某一种。所以,结合二维GIS与三维GIS于一体,充分发挥二者的优点,是一个即经济又实用的思想,这也正是本研究的宗旨所在。因此研发一个使矢量数据与地形三维可视化集成的系统,具备重要的现实意义,本研究系统将分为二维和三维两个部分,二维部分采用MFC与ArcGIS Engine实现,三维部分则采用ATL与OpenGL设计成ActiveX控件,ActiveX控件的集成性很是好,能够发布到任何联网的用户终端使用。所以,本论文将三维部分集成到二维部分中,使二维视图与三维视图造成一体化系统,采用的方式是动态加载ActiveX控件,该方式很是灵活,当ActiveX控件版本变化时,没必要手动的更新。固然,不能简单的堆砌为一个集二维GIS与三维GIS于一身的显示系统,更重要的是使二维与三维两个部分得以互动,因此,本论文将二维与三维有机的结合,实现了二维与三维的互动。下图说明了本系统的整体设计思路。函数

  本系统是由二维与三维两个部分共同构建的,以下图所示的系统主界面。系统分为左右两个视图,左视图是二维部分,右视图是三维部分,下面将详细阐述二维部分、三维部分以及二维与三维互动的设计与实现,并用某地数据进行了测试。工具

  2、技术路线和功能简介性能

  一、二维部分测试

  本系统二维部分使用VC提供的MFC与ArcGIS Engine组件实现。在MFC中使用ArcGIS Engine的控件、接口和方法必须遵循必定的步骤,并不像VB、DoNet中那样方便,下面详细介绍在MFC中应用ArcGIS Engine的步骤。大数据

  一、引入ArcGIS Engine控件库文件(*.ocx)和组件库文件(*.olb)。控件库中定义了与控件相关的接口,组件库中定义了与控件无关的接口。引用语句以下,其中除库文件名(如:esriGeometry.olb)外其他各参数均采用默认便可;ui

  #import <esriGeometry.olb>_       //库文件名

  raw_interfaces_only_

  raw_native_types_

  no_namespace_

  named_guids_

  exclude("OLE_COLOR", "OLE_HANDLE")

  二、加载ArcGIS Engine控件。VC控件工具箱中有一些默认加载的控件,这些控件能够在对话框中进行所见即所得的绘制,但ArcGIS Engine控件并无加载进去,所以须要手动加载,使得能够在对话框中绘制Map、Scene、Toorbal等控件,VC中提供了两种加载控件的方法;

  第一种本论文称之为COM方式,该方式加载的控件图标并不出如今工具箱中。首先右击对话框,选择“插入ActiveX控件”;而后选择“插入ActiveX控件”对话框中要加载的控件,如:ESRI MapControl,这样MapControl即出如今对话框中。

  第二种本论文称之为C++方式,该方式加载的控件图标出如今工具箱中,而且向VC工程中添加该控件的VC源文件(*.cpp)和头文件(*.h)。首先,选择工程->增长到工程->Components and Controls菜单,打开“Components and Controls”对话框,选择Registered ActiveX Controls中要插入到工程的控件,如:ESRI MapControl,这样MapControl即出如今VC工具箱中,即可以像默认控件那样,在对话框中绘制MapControl。

  三、定义ArcGIS Engine的类对象。ArcGIS Engine包含三种类[62]:抽象类(abstract class)、可实例化类(class)和组件类(cocalss)。抽象类不能用以建立新对象,但能够指定子类;可实例化类不可以直接建立新对象,由于它的构造函数是私有的,但能够经过其余类对象的属性或其余类的方法实例化;组件类指的是可以直接使用经过开发环境中的对象定义语法来建立对象的类,组件类能够直接被建立或者实例化。

  VC中均采用智能指针来声明ArcGIS Engine接口,能够被实例化的类在VC中具备三种实例化方式:

  第一种本论文称之为类标识方式。在类对象声明时,直接使用类惟一标识(CLSID)进行构造,如:IFieldsPtr pFlds(CLSID_Fields);

  第二种本论文称之为ATL方式。在类对象声明时,使用CocreateInstance方法进行构造,如:CComPtr<IFields> pFlds;pFlds.CoCreateInstance(CLSID_Fields);

  第三种本论文称之为COM方式。在类对象声明时,使用CreateInstance方法进行构造,如:IFeatureLayerPtr pFlds;HRESULT hr = pFlds.CreateInstance(CLSID_Fields)。

  通过以上步骤,便可以应用ArcGIS Engine提供的接口、方法进行本系统二维部分的程序设计。二维的功能以下图所示,其中数据转换部分实现了由Shapefile向TIN及Raster的转换和由TIN或Raster生成等高线。二维AE部分实现了DEM及SHP文件的显示,以及对DEM分层设色、生成坡度、通视分析、TIN的三维显示、夸张系数设置等功能。 

  下面是二维的一些贴图。

  二、三维部分

  本系统三维部分使用VC提供的ATL与OpenGL实现。ATL是活动模板库(Active Template Library)的简称,是VC中为了支持COM而提供的轻便类库,用ATL能够容易的定制COM组件,并不须要本身写模块定义文件(*.def)。在ATL中使用OpenGL的步骤以下。

 一、引入OpenGL函数库。首先,选择工具->选项菜单,分别选择目录->Include files和目录->Library files,将相应目录添加进去;而后,在stdafx.h文件中加入以下语句,引入OpenGL头文件和库文件(*.lib)。

  #pragma comment(lib, "opengl32.lib")

  #pragma comment(lib, "glu32.lib")

  #pragma comment(lib, "glaux.lib")

  #include <gl"gl.h>

  #include <gl"glu.h>

  #include <gl"glaux.h>

  二、在具体的实现过程当中,因为OpenGL函数经过“绘制场景”(Rendring ContextRC)完成三维图形的绘制。Windows下的窗口和设备场景支持位图格式属性,该属性与RC存在位图结构上的一致。只要在建立RC时将它与一个DC(Device Context)相关联(RC只能由一个已经创建了位图格式的DC来建立),OpenGL的函数就能够经过RC对应的DC绘制到相应的显示设备上,相应的步骤以下:

  1)设置显示设备DC的位图格式属性。经过填写一个PIXELFORMATDESCRIPTOR的结构来完成,该结构决定了OpenGL绘图的物理设备属性,另外,DC有可能只支持部分位图格式,所以首先使用函数ChoosePixelFormat选择与DC支持的指定位图格式最接近的位图格式,而后使用函数SetPixelFormt设置DC的位图格式。

  2)建立绘制环境RC与DC的联系,利用DC建立绘制场景RC(wglCreateContext),以便在DC与RC之间建立关联,此时须要使用函数wglMakeContexte。

  3)调用OpenGL函数进行绘制。

  4)释放相关内存。绘图完备后,须要调用函数wglMakeContext设置当前线程的RC为NULL,从而断开当前线程和该RC的关联,并由此断开与DC的关联。

  通常地,在使用单个RC的应用程序中,相应的WM_CREATE消息时建立RC,当WM_CLOSE或WM_DESTROY到来时再删除它。在使用OpenGL命令往窗口中绘制图形以前,必须先创建一个RC,并使之成为现行RC。OpenGL命令无需提供RC,OpenGL将简单地忽略全部的绘图命令。

  通过以上步骤,便可以应用ATL及OpenGL从底层实现本系统三维部分的程序设计。三维OpenGL部分的功能以下图所示,三维部分采用Roam算法实现DEM的三维可视化以及纹理的叠加,并实现了在三维场景中的实时漫游和Shapefile叠加到纹理表面,能够清晰的看到Shapefile叠加到纹理表面后的是有起伏的,这是由于Shapefile是绘制在纹理图像上的,避免了低于地形或高于地形的状况,为有关部门的规划管理提供了支持。

  下面是一些三维贴图。

  一、叠加shapefile的效果图

  二、漫游浏览的效果图(不知为什么变成黑白色了,晕)

  三、Roam算法生成的Dem格网图

  3、二维与三维集成及互动1三维ActiveX控件集成到二维部分

  欲将ActiveX控件集成到二维部分,首先必须将二维部分分割成左右两个视图,而后将ActiveX控件插入到其中一个视图中,详细实现以下。

  一、分割MFC视图(View)。首先创建一个继承自CFormView的视图COpenGL,该视图便是三维ActiveX控件的载体;而后创建一个继承自CSplitterWnd的类CMySplitter,该类用来建立左右两个视图;最后重载CMainFrame的OnCreateClient函数,在该函数中调用CSplitterWnd的CreateStatic函数建立两个视图,并用RUNTIME_CLASS将COpenGL做为其中一个视图显示。

  二、动态加载ActiveX控件。首先如上节的方法插入三维ActiveX控件;而后在COpenGL类的OnCreate函数中使用CWnd类的CreateControl动态的加载ActiveX控件。

  2 二维与三维互通讯

  二维视图与三维视图的互通讯是实现二维与三维的互动的基础,二维与三维互通讯分为如下两步。

  一、视图间互通讯。它不是简单的函数调用问题,由于MFC的默认视图类(CView)并不能安全的与除文档类(CDocument)之外的其他视图类进行通讯,因此,必须使得全部视图类均先与文档类进行通讯,这就须要重载CDocument::OnOpenDocument函数,将COpenGL类的指针加入其中便可以实现视图间的通讯。

  二、MFC视图与ActiveX控件通讯。ActiveX控件所提供的方法均没有返回值,而实现MFC视图与ActiveX控件的通讯又必须获得方法的返回值,解决这个矛盾有三种方法:

一是将方法的参数设置为指针类型;

二是提供相应方法的属性,在属性内部调用ActiveX的类函数;

三是将方法声明成事件,并能够与默认的ActiveX事件挂钩。

这三种方法各有千秋,须要结合应用,如:坡度坡向计算时,须要获得该点的坡度坡向两个数值,便可将该方法的参数声明为指针类型;距离量算时,只需获得距离一个参数值,便可将其声明为属性;坐标查询时,须要在MFC视图中截获鼠标单击的消息,所以要将该方法声明为响应鼠标单击的事件。

添加ActiveX事件是一项很是困难的工做,须要用接口定义语言—IDL(Interface Definition Language)手动编写接口定义文件(*.idl)。下面以添加鼠标单击事件Click为例说明添加事件的步骤。首先,应用guidgen.exe得到一个惟一标识码做为Click事件的接口_IEvent的ID,而后将_IEvent声明为[default, source]dispinterface,编译idl文件,并添加该_IEvent的Click事件的链接点(Connection Point),系统会自动产生一个继承自IConnectionPointImpl接口的CProxy_IEvents类,并在该类中加入Fire_Click方法,该方法即为Click事件。这样只是添加了Click事件,还必须将其与ActiveX默认的鼠标单击事件OnLButtonDown挂接,才能响应鼠标单击的消息,所以必须在OnLButtonDown中调用Fire_Click方法,一切处理均在OnLButtonDown中实现,然后传入Fire_Click中。

  

3 设计思路

本研究的核心思想便是有机的结合二维GIS与三维GIS,并将二者统一应用到一个系统中,使在三维中难以实现或算法复杂的功能应用二维GIS实现,而在二维中不能实现或不够精确的功能应用三维GIS实现,使二维GIS与三维GIS优点互补。

本文即应用该思想设计一个二维与三维结合的系统,在本系统中,要达到矢量数据和三维场景之间的一一映射,必须创建二者之间坐标系的惟一对应或对应地理目标名称[63](惟一的ID)的一一对应,一旦得到对象的惟一标识,就能够得到对象实体的所有信息。本论文选择坐标对应方式,得到三场景中任意一点对应的地面点坐标是进行有关空间信息的查询操做和地形分析的前提,所以在三维部分中最为重要的就是如何得到三维坐标,对点的空间位置查询是其他地形空间信息查询的基础,本论文改进了现有的三维坐标查询算法(见3.3.4节),使查询三维坐标更加方便准确。经过创建二维与三维两部分坐标的对应和消息响应机制能够实现矢量数据与三维场景的互动。如:

一、用户在三维场景中漫游时,在二维场景中显示出相应的位置和视野(FOV);

二、在二维场景中改变观察者位置的时候,相应地在三维场景中跳到对应的位置。在三维场景中改变观察者的位置,在二维场景中视点也跳到对应的位置;

三、二维中进行目标属性信息查询的时候,三维场景的对应目标高亮度显示;

四、三维中进行目标属性信息查询的时候,二维场景的对应目标高亮度显示;

五、因为二维GIS宏观性、总体性、简洁性的特色,在二维中实现剖面图绘制、通视分析、坡度图绘制等宏观的功能;

六、因为三维GIS局部性、现实性、直观性的特色,在三维中实现地形的真实再现、面积量算、距离量算、单点坡度坡向计算等微观功能;

二维GIS与三维GIS结合应用,即克服了二维GIS的抽象多义性,又避免了三维场景漫游的方向迷失感。本研究充分发挥了二者的优点,经过二维GIS与三维GIS的互动实现GIS功能,而不局限于用单一的方式来实现,这样即加强了系统的灵活性,又使问题简单化。

 

4 功能介绍

通过以上两步,二维与三维互动的准备工做已经完成,二维与三维互动的根本思想便是经过二维与三维的互通讯,使得二维与三维互相关联,造成一个有机的总体。实现了二维与三维的互动的功能。其中坐标查询是最为关键的功能,是实现其余功能的基础与前提。下面详细说明这些功能实现的主要思想。

4.一、坐标查询。二维中只具备 坐标,三维中具备 坐标,所以欲获得二维中鼠标点击位置的三维坐标,必须将二维中的 传入三维中,通过改进算法的计算便可;而三维中坐标与二维中对应只需将三维中的 坐标传入二维中。这样就实现了二维与三维互动的坐标查询功能,以下图所示,经验证得到的坐标正确,且实现了二维与三维的坐标对应。

 

4.二、场景定位。在二维中想了解某个位置的详细状况时,能够直接将二维坐标传入三维中,计算出三维坐标后,在进行局部放大到相应位置的三维视图。若是想得到二维中某条线路或某个区域的具体信息,能够将该线路或区域传入三维中绘制在地形纹理上进行仔细观察,其中区域绘制有透明和非透明两种,透明采用遍历活性边表的扫描线算法进行填充,非透明采用GDI的FillRgn函数进行填充;而三维中漫游时,若是迷失方向,则能够将三维坐标传入二维中进行定位标识,以下图所示,二维中的任意位置、线路及区域都可在三维中做相应的绘制,均具有有地形相符的起伏;而三维中漫游时亦可随时定位到二维中。

 

4.三、距离量算。若是在三维GIS中测量曲面距离,必须与网格线进行屡次求交,获得相应的交点再计算,这样势必大大增长系统负担,而二维GIS中刚好能够应用IPointCollection接口直接得到与网格线的交点集合,但二维GIS中的距离是投影距离,而曲面距离中每一段距离是空间距离,因此,若是是三维中两点的曲面距离,首先需将起终点传入二维GIS中,得到与网格线的交点集合再传回三维GIS中进行计算便可;而若是是二维中两点间的曲面距离,便可首先获得交点(x,y)坐标集合,而后传入三维中,得到网格点集合的(x,y,z)坐标,再进行计算便可。下图即为按照该方法获得的投影、直线、曲面三种距离。

 

 

还有体积、剖面图、三维二维加载shapefile等功能,此处就再也不一一赘述。完结啦,^_^

相关文章
相关标签/搜索