基于VC++的电子导航系统-毕业论文_第1页
基于VC++的电子导航系统-毕业论文_第2页
基于VC++的电子导航系统-毕业论文_第3页
基于VC++的电子导航系统-毕业论文_第4页
基于VC++的电子导航系统-毕业论文_第5页
已阅读5页,还剩56页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

内蒙古科技大学毕业设计说明书(毕业论文)PAGEPAGE57基于VC++的电子导航系统摘要地理信息系统(GIS)自二十世纪六十年代开始发展至今,已经逐渐成为一门成熟的技术,其在交通、旅游、环境等诸多领域的应用使地理信息系统被越来越多的用户所接受,成为人们工作、生活中一个强有力的工具。本设计以VC++为开发平台,以MapX控件为图形平台,以MSComm控件为通信平台,设计具有电子导航的基本功能(如地图的放大缩小、全图、漫游等)、自定义工具测量折线距离、图层控制、最优路径分析、GPS导航等功能的GIS应用软件。本文介绍了电子导航系统设计的背景及设计中需要用到的MapX控件、VC++、MSComm控件,分析了GIS开发三种实现方式,提出系统设计方案:集成二次开发。在集成二次开发的基础上,首先实现了地图的导入、地图放大缩小及图层控制等电子导航的基本功能,其次以测量折线距离为例实现了自定义工具的功能,再次介绍了最优路径分析,最后实现GPS导航功能。关键词:电子导航;GIS开发;VC++;MapX控件;最优路径ElectronicNavigationSystemsBasedOnVC++AbstractSincethebeginningof1960s,GeographicInformationSystem(GIS)hasgraduallybecomeamaturetechnology.Intransportation,tourism,environmentandmanyotherfieldsofapplicationGIShasbeenacceptedbyanincreasingnumberofusersforthepeopleworkingandlivingasapowerfultool.ThedesignusedVC++asadevelopmentplatform,MapXcontrolasagraphicsplatform,MSCommcontrolasacommunicationsplatform.IthasdevisedtheGISapplicationssuchaselectronicnavigationBasicfunctions(zoomcontrol,thewholemap,Roaming,forexample),Calculatingthedistance,LayerControl,AnalysisoftheoptimalpathandGPSNavigationFeatures.Thisarticlehasdescribedthedesignofelectronicnavigationsystemsbackground,MapXcontrol,VC++andMSCommcontrol.IthasanalyzedGISdevelopmentinthreewaysandproposedsystemdesign:Secondarydevelopmentofintegrated.Firstofall,IthasrealizedthebasicfunctionsofGISsuchastheinsertmap,LayerControl,Zoomcontrolintheintegrateddevelopmentofthebasisofsecondary.Second,ithasusedacustomtoolasanexampletomeasurethedistance,andthenithasintroducedtheanalysisoftheoptimalpath.Finally,ithasrealizedGPSnavigation.Keywords:Electronicnavigation;GISDevelopment;VC++;MapXcontrol;Optimalpath目录摘要 IAbstract II第一章引言 11.1 设计背景 11.2 系统设计方案 41.2.1 应用型GIS开发的三种实现方式 41.2.2 三种实现方式的分析 5第二章电子导航基本功能在VC++中的实现 72.1 利用MapX实现GIS基本功能 72.1.1 将MapX支持类库加入工程 72.1.2 地图的显示 72.2 使用地图标准工具 92.3 图层控制工具 11第三章自定义工具测量折线距离 133.1 创建用户自定义工具 133.2 编程实现自定义工具的行为 143.3 调用自定义工具 16第四章最优路径分析 184.1 实现过程及其算法分析 184.2 查询最短路径 25第五章GPS导航功能 305.1 定位信息的接收 325.2 提取定位数据 34总结 39参考文献 40附录:源程序 42CVCDZDHView类源程序 42致谢 52引言设计背景学科发展走向综合是一个普遍的趋势,比如全球定位系统(GPS)与地理信息系统(GIS)的集成应用。目前用于GIS应用软件开发的模式有很多,其中组件式GIS软件开发是目前较为流行、高效、快速的开发模式。随着计算机技术的飞速发展,GIS得到了广泛的重视和应用,GPS技术也已深入到各行各业,GPS与GIS的集成具有广泛的应用需求,它可以实现GPS导航信息在地图上的可视化、一体化和集成化,能够在地图上实时动态地跟踪目标和显示地理方位。VC++是目前较流行的可视化开发编程工具之一,支持面向对象和事件驱动机制的程序开发,利用其强大的集成开发环境,程序员仅需要较少代码即可生成标准的“Windows”界面,并且能在VC开发平台下可以较为方便的集成组件。本文主要介绍利用MapX控件,采用VC++编程语言进行组件式GIS应用软件开发的主要过程和基本模式,来实现电子导航的目的。MapX是MapInfo公司向用户提供的具有强大地图分析功能的ActiveX控件产品。由于它是一种基于Windows操作系统的标准控件,因而能支持绝大多数标准的可视化开发环境如VisualC++、VisualBasic、Delphi、PowerBuilder等。编程人员在开发过程中可以选用自己最熟悉的开发语言,轻松地将地图功能嵌入到应用中,并且可以脱离MapInfo的软件平台运行。利用MapX,能够简单快速地在企业应用中嵌入地图化功能,增强企业应用的空间分析能力,实现企业应用的增值。MapX采用基于MapInfoProfessional的相同的地图化技术,可以实现MapInfoProfessional具有的绝大部分地图编辑和空间分析功能。而且,MapX提供了各种工具、属性和方法,实现这些功能是非常容易的[1]。MapX为开发人员提供了一个快速、易用、功能强大的地图化组件。在VB,Delphi,PowerBuilder,VC等可视化开发环境中,只需在设计阶段将MapX控件放入窗体中,并对其进行编程,设置属性或调用方法或相应事件,即可实现数据可视化,专题分析,地理查询,地理编码等丰富的地图信息系统功能。MapX定义了一个类体系,以有效的组织图形元素,图层,属性数据等对象。MapX的主要功能包括:显示MapInfo格式的地图;对地图进行放大、缩小、漫游、选择等操作;专题地图;图层控制;数据绑定;动态图层和用户绘图图层;生成和编辑地图对象;简单地理查询:边界查询,地址查询。VC++是微软公司开发的一个IDE(集成开发环境),换句话说,就是使用C++的一个开发平台。有些软件就是这个编出来的,另外还有VB、VF,只是使用不同语言。但是,VC++是Windows平台上的C++编程环境,学习VC要了解很多Windows平台的特性并且还要掌握MFC、ALT、COM等的知识。Windows下编程需要了解Windows的消息机制以及回调(callback)函数的原理;MFC是Win32API的包装类,需要理解文档视图类的结构,窗口类的结构,消息流向等等;COM是代码共享的二进制标准,需要掌握其基本原理等等。VC++应用程序的开发主要有两种模式,一种是WINAPI方式,另一种则是MFC方式,传统的WINAPI开发方式比较繁琐,而MFC则是对WINAPI再次封装,所以MFC相对于WINAPI开发更具备效率优势。VC基于C,C++语言,主要由是MFC组成,是与系统联系非常紧密的编程工具,它兼有高级,和低级语言的双重性,功能强大,灵活,执行效率高,几乎可说VC在Windows平台无所不能。MSComm作为一个串行通讯控件为程序员串口通讯编程节省了很多时间。在基于对话框的应用中加入一个MSComm控件非常简单。只需进行以下操作即可:打开“Project->AddToProject->ComponentsandControls->RegisteredActivexControls”,然后选择控件:MicrosoftCommunicationControl,version6.0插入到当前的工程中。这样就将类CMSComm的相关文件mscomm.cpp和mscomm.h一并加入到了工程中。编程时只需将控件对话中的MSComm控件拖至你的应用对话框中就OK了。MSComm控件提供了两种处理通信的方法:1.事件驱动通信,是一种功能很强的处理串口活动的方法。例如,当在CD(CarrierDetect)线或RTS(RequestToSend)线上有字符到达或发生了改变,在这种情况下,可以使用MSComm控件的OnComm事件捕获和处理这些通信事件。OnComm也可以捕获和处理通信中的错误。2.可以在每个重要的程序功能之后检查CommEvent属性的值来检测事件和通信错误。使用的每个MSComm控件都与一个串口对应。如果在应用程序中需要访问多个串口,必须使用多个MSComm控件,可以在Windows控制面板中修改串口地址的中断地址。MSComm控件有很多重要的属性,如:CommPort属性:设置并返回通讯端口号。RThreshold属性:在MSComm控件设置CommEvent属性为comEReceive并产生OnComm之前,设置并返回的要接收的字符数。CTSHolding属性:确定是否可通过查询ClearToSend(CTS)线的状态发送数据。ClearToSend是调制解调器发送到相联计算机的信号,指示传输可以进行。该属性在设计时无效,在运行时为只读。SThreshold属性:在MSComm控件设置CommEvent属性为comEvSend并产生OnComm事件之前,设置并返回传输缓冲区中允许的最小字符数。CDHolding属性:通过查询CarrierDetect(CD)线的状态确定当前是否有传输。CarrierDetect是从调制解调器发送到相联计算机的一个信号,指示调制解调器正在联机。该属性在设计时无效,在运行时为只读。DSRHolding属性:确定DataSetReady(DSR)线的状态。DataSetReady信号由调制解调器发送到相连计算机,指示作好操作准备。该属性在设计时无效,在运行时为只读。Settings属性:设置并返回波特率、奇偶校验、数据位、停止位参数。InputLen属性:设置并返回Input属性从接收缓冲区读取的字符数。系统设计方案应用型GIS开发的三种实现方式(1)独立开发不依赖于任何GIS工具软件,从空间数据的采集、编辑到数据的处理分析及结果输出,所有的算法都由开发者独立设计,然后选用某种程序设计语言,如VisualC++、Delphi等,在一定的操作系统平台上编程实现。这种方式的好处在于无须依赖任何商业GIS工具软件,减少了开发成本,但一方面对于大多数开发者来说,能力、时间、财力方面的限制使其开发出来的产品很难在功能上与商业化GIS工具软件相比,而且在购买GIS工具软件上省下的钱可能还抵不上开发者在开发过程中绞尽脑汁所花的代价。(2)单纯二次开发完全借助于GIS工具软件提供的开发语言进行应用系统开发。GIS工具软件大多提供了可供用户进行二次开发的宏语言,如ESRI的ArcView提供了Avenue语言,MapInfo公司研制的MapInfoProfessional提供了MapBasic语言等等。用户可以利用这些宏语言,以原GIS工具软件为开发平台,开发出自己的针对不同应用对象的应用程序。这种方式省时省心,但进行二次开发的宏语言,作为编程语言只能算是二流,功能极弱,用它们来开发应用程序仍然不尽如人意。(3)集成二次开发集成二次开发是指利用专业的GIS工具软件,如MapInfo、ArcView等,实现GIS的基本功能,以通用软件开发工具尤其是可视化开发工具,如VisualC++、Delphi、VisualBasic、PowerBuilder等为开发平台,进行二者的集成开发。集成二次开发目前主要有两种方式:1)OLE/DDE采用OLEAutomation技术或利用DDE技术,用软件开发工具开发前台可执行应用程序,以OLE自动化方式或DDE方式启动GIS工具软件在后台执行,利用回调技术动态获取其返回信息,实现应用程序中的地理信息处理功能。2)GIS控件利用GIS工具软件生产厂家提供的建立在OCX技术基础上的GIS功能控件,如ESRI的MapObjects、MapInfo公司的MapX等,在VC++等编程工具编制的应用程序中,直接将GIS功能嵌入其中,实现地理信息系统的各种功能。三种实现方式的分析由于独立开发难度太大,单纯二次开发受GIS工具提供的编程语言的限制差强人意,因此结合GIS工具软件与当今可视化开发语言的集成二次开发方式就成为GIS应用开发的主流。它的优点是既可以充分利用GIS工具软件对空间数据库的管理、分析功能,又可以利用其它可视化开发语言具有的高效、方便等编程优点,集二者之所长,不仅能大大提高应用系统的开发效率,而且使用可视化软件开发工具开发出来的应用程序具有更好的外观效果,更强大的数据库功能,而且可靠性好、易于移植、便于维护,尤其是使用OCX技术利用GIS功能组件进行集成开发,更能表现出这些优势。由于上述优点,集成二次开发正成为应用GIS开发的主流方向。这种方法唯一的缺点是前期投入比较大,需要同时购买GIS工具软件和可视化编程软件,但“工欲善其事,必先利其器”,这种投资值得。目前许多软件公司都开发了很多ActiveX控件,合理选择和运用现成的控件,减少了开发者的编程工作量,使开发者避开某些应用的具体编程,直接调用控件,实现这些具体应用,不仅可以缩短程序开发周期,使编程过程更简洁,用户界面更友好,可以使程序更加灵活、简便。与利用OLEAutomation技术作为服务器的MapInfo相比,利用控件开发速度快,占用资源少,而且易实现许多底层的编程和开发功能[4]。电子导航基本功能在VC++中的实现利用MapX实现GIS基本功能在进行MapX开发之前,首先要在计算机中正确的安装了MapX控件和VC++应用程序。下面就用一个具体的实例,介绍在VC++中集成MapX的方法。将MapX支持类库加入工程利用VC++环境下的应用程序生成向导创建一单文档界面应用程序VCDZDH。先将位于MapX的安装路径下的子目录Samples40\C++\Cpp中的MapX.h和MapX.cpp文件拷贝到当前应用程序所在的VCDZDH文件夹下,然后从Project菜单中选择AddtoProject>Files命令,此时打开了InsertFilesintoProject对话框,选择VCDZDH文件夹下的MapX.cpp和MapX.h文件加入到工程中。地图的显示在VCDZDH文件夹下新建文件夹map,map中复制MapInfo格式的地图文件及Geoset(.GST)文件MY.GST。用户只需要打开Geoset文件,就可以按预先定制的方式显示各层地图。通过以下步骤,就可以实现地图的显示[5]。1)在VCDZDHView.h文件中,加入MapX.h对象的头文件,并声明CMapX类型的变量m_ctrlMapX。方法如下:#include“MAPX.H”ClassCVCDZDHView::publicCView{protected:CMapXm_ctrlMapX;//声明CMapX类型的变量m_ctrlMapX}2)为MapX创建一个资源ID。选择ViewResourceSymbols,并点击New按钮,输入名称IDC_MAP,值取默认数值。3)在VCDZDHView.h文件中声明int类型的全局变量m_created和CString类型的全局变量m_tempclientpath。通过类向导创建消息映射函数WM_CREATE。选择“建立类向导”或使用快捷键CTRL+W,可以打开类向导。从类名中选择CVCDZDHView类,在消息框中选择WM_CREATE消息,然后添加函数,编辑代码创建MapX对象。代码如下:intCVCDZDHView::OnCreate(LPCREATESTRUCTlpCreateStruct){if(!m_ctrlMapX.Create(NULL,WS_VISIBLE,CRect(0,0,100,100),this,IDC_MAP))return-1;}4)采用同样的方法创建WM_SIZE消息映射函数。该函数用来调整地图大小使其充满客户区。具体代码如下:voidCVCDZDHView::OnSize(UINTnType,intcx,intcy){CView::OnSize(nType,cx,cy);m_ctrlMapX.MoveWindow(0,0,cx,cy);//调整地图大小}5)采用同样的方法创建WM_SETFOCUS消息映射函数。修改函数使得当窗口获得焦点时,地图控件获得焦点。具体代码如下。voidCVCDZDHView::OnSetFocus(CWnd*pOldWnd){CView::OnSetFocus(pOldWnd);m_ctrlMapX.SetFocus();//当窗口获得焦点时,地图控件获得焦点}通过以上步骤,将应用程序编译运行就可显示地图。如图2.1所示:图2.1地图的显示使用地图标准工具在地图显示出来后,用户通常要以各种比例查看地图的全局、局部或细部,必须提供诸如放大、缩小和漫游等功能。采用MapX通用工具,可以非常方便地实现上述功能。设定MapX使用标准工具的方法很简单,只需设定地图对象的CulrentTool属性。下面的例子是用标准放大工具实现放大功能。添加新菜单项资源,输入标题“工具”,在“工具”下添加子菜单,输入标题“放大”及ID为ID_ZOOM_IN。打开类向导,选择视图类CVCDZDHView,为菜单项ID_ZOOM_IN添加COMMAND消息映射函数OnZoomIn(),并编辑代码如下。voidCVCDZDHView::OnZoomIn(){m_ctrlMapX.SetCurrentTool(miZoomInToo1);//miZoomInTool为放大工具的常量}编译运行程序,选择“工具>放大”,就会看到此时光标变为放大镜,单击鼠标就会实现放大功能。如图2.2所示:图2.2放大功能演示可用相同方法实现缩小、漫游、全图等标准工具的功能。其它的功能跟上面的方法类似,只是需要修改指示常量。表2.1中列出了部分MapX工具的指示常量[9]。表2.1部分MapX工具的指示常量图层控制工具为了使用户方便查询各个图层,通常要在电子导航系统中设计图层控制工具。在菜单中建立图层控制菜单,设置图层控制ID为ID_VIEW_LAYERCONTROL,然后建立类向导,选择CVCDZDHView类,添加如下函数:voidCVCDZDHView::OnViewLayercontrol(){ try{ VARIANTvHelpFile,vHelpID; vHelpFile.vt=VT_ERROR; vHelpFile.scode=DISP_E_PARAMNOTFOUND; vHelpID.vt=VT_ERROR; vHelpID.scode=DISP_E_PARAMNOTFOUND; CMapXLayerslayers=m_ctrlMapX.GetLayers(); layers.LayersDlg(vHelpFile,vHelpID);} catch(COleDispatchException*e){ e->ReportError(); e->Delete();} catch(COleException*e){ e->ReportError(); e->Delete();}}这样,就添加上了图层控制工具,运行程序,该功能如图2.3所示:图2.3图层控制工具自定义工具测量折线距离MapX提供的地图标准工具能满足一般需要,但在一些特殊地方,用户可能需要某种特殊工具来完成某些特定的地图操作功能。因此,MapX提供了用户自定义工具的方法,这样可以大大扩展MapX的应用范围。可使用地图对象的CreateCustomTool方法创建自定义工具。下面是用自定义工具实现折线距离的计算。创建用户自定义工具为了满足用户需要,使用户方便查询两地之间的距离,我们利用自定义工具在电子导航系统中设计了折线距离计算功能。方法如下:首先,在VCDZDH.h文件中定义常量。#defineMYTOOL_DISTANCE1然后,在VCDZDH.cpp文件中的OnCreate()函数中加入如下代码,从而创建一个用户自定义工具。intCVCDZDHView::OnCreate(LPCREATESTRUCTlpCreateStruct){if(CView::OnCreate(1pCreateStruct)==-1)return-1;……m_ctrlMapX.CreateCustomTool(MYTOOL_DISTANCE,miToolTypePoly,miCrossCursor);//MYTOOL_DISTANCE代表自定义工具的常量,miToolTypePoly描述了该工具的行为是画折线,miCrossCursor表示指定光标的形式return0;}编程实现自定义工具的行为在创建了用户自定义工具后,需在ToolUsed事件中实现该工具是如何工作的。要处理MapX事件,首先需要为要处理的事件创建一事件槽,其方法如下。在VCDZDHView.h文件中,在DECLARE_MESSAGE_MAP()行下面加入如下一行代码。DECLARE_EVENTSINK_MAP()然后在VCDZDHView.cpp文件中,加入如下代码。BEGIN_EVENTSINK_MAP(CVCDZDHView,CView)ON_EVENT(CVCDZDHView,IDC_MAP,11,OnPolyTooIUsedMap,VTS_I2VTS_I4VTS_DISPATCHVTS_BOOLVTS_BOOLVTS_PBOOL)//11代表PolyToolused,OnPolyToolUsedMap是事件响应函数的名称。END_EVENTSINK_MAP()BEGIN_EVENTSINK_MAP(CVCDZDHView,CView)和END_EVENTSINK_MAP()两行代码之间加入的,就是要处理的事件。切换到VCDZDHView.h文件中,声明事件响应函数,代码如下。voidOnPolyToolUsedMap(shortToolNum,longFlags,LPDISPATCHPoints,BOOLbShift,BOOLbCtrl,BOOLFAR*EnableDefauh)然后在VCDZDHView.cpp中加入函数的实现代码。voidCVCDZDHView::OnPolyToolUsedMap(shortToolNum,longags,LPDISPATCHPoints,BOOLbShift,BOOLbCtrl,BOOLFAR*EnableDefault){if(ToolNum==MYTOOL_DISTANCE);{CMapXPointspts;longn;longi;try{pts.AttachDispatch(Points,FALSE);doubledDistanceTot=0.0;n=pts.GetCount();for(i=1;i<n;i++) {CMapXPointpt1=pts.Item(i);CMapXPointpt2=pts.Item(i+1);Doubled=m_ctrlMapX.Distance(pt1.GetX(),pt1.GetY(),pt2.GetX(),pt2.GetY());dDistanceTot+=d;}CStringstr;str.Format("总距离为:%f公里",dDistanceTot);((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetPaneText(0,str);//在状态栏中显示折线距离}catch(COleDispatchException*e){e->ReportError();e->Delete();}catch(COleException*e){e->ReportError();e->Delete();}}}为了在状态栏中显示折线距离,还必须在VCDZDH.cpp文件中添加CMainFrame类的头文件。#include“MainFrm.h”并且将CMainFrame类中的mwndStatusBar由受保护的变量改为全局变量。调用自定义工具在“工具”下拉菜单中添加“折线距离”子菜单项,ID为ID_DISTANCE_TOOL。打开类向导,选择视图类CVCDZDHView,为菜单项ID_DISTANCE_TOOL添加COMMAND消息映射函数OnPolydistancetool(),添加代码如下。voidCVCDZDHView::OnDistanceTool(){ //TODO:Addyourcommandhandlercodehere m_ctrlMapX.SetCurrentTool(MYTOOL_DISTANCE);//调用自定义工具}编译并运行程序,如图3.1所示为使用“折线距离”工具的应用程序界面。图3.1折线距离演示最优路径分析对城市道路网进行最短路径分析,需要把城市道路网络实体抽象化为网络图论理论中的网络图,然后通过图论中的网络分析理论来实现道路网络的最短路径分析。在实际应用中,道路网的表现形式一般为数字化的矢量地图,其网络空间特征中的交叉路口坐标和道路位置坐标是在地图上借助图形来识别和解释的;而为了能够高效率地进行最短路径分析,必须首先将其按结点和弧的关系抽象为图的结构。这就需要先对原始道路图进行预处理,构建其相应的网络拓扑关系,然后才能进行最短路径分析等各种操作。下面介绍一种Dijkstra算法。实现过程及其算法分析Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。Dijkstra算法一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN,CLOSE表方式。其采用的是贪心法的算法策略,大概过程:创建两个表,OPEN,CLOSE。OPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。1.访问路网中距离起始点最近且没有被检查过的点,把这个点放入OPEN组中等待检查。2.从OPEN表中找出距起始点最近的点,找出这个点的所有子节点,把这个点放到CLOSE表中。3.遍历考察这个点的子节点。求出这些子节点距起始点的距离值,放子节点到OPEN表中。4.重复第2和第3步,直到OPEN表为空,或找到目标点。Dijkstra算法的基本思路是:假设每个点都有一对标号(dj,pj),其中dj是从起源点s到点j的最短路径的长度(从顶点到其本身的最短路径是零路(没有弧的路),其长度等于零);pj则是从s到j的最短路径中j点的前一点。求解从起源点s到点j的最短路径算法的基本过程如下:图4.1算法流程图1)初始化。起源点设置为:①ds=0,ps为空;②所有其他点:di=∞,pi=?;③标记起源点s,记k=s,其他所有点设为未标记的。2)检验从所有已标记的点k到其直接连接的未标记的点j的距离,并设置:dj=min[dj,dk+lkj],式中,lkj是从点k到j的直接连接距离。3)选取下一个点。从所有未标记的结点中,选取dj中最小的一个i:di=min[dj,所有未标记的点j],点i就被选为最短路径中的一点,并设为已标记的。4)找到点i的前一点。从已标记的点中找到直接连接到点i的点j*,作为前一点,设置:i=j*。5)标记点i。如果所有点已标记,则算法完全推出,否则,记k=i,转到2)再继续。为了实现Dijkstra算法,在程序中首先引入三个类:classVERTEX//顶点类{publicintid;publicintSearched;//0表示从来没有搜索过,表示搜索过,但没有完成,表示搜索完成,该点的最短路径已经找到publicIPointpPoint;publicVERTEXPrev;publicVERTEXNext;publicLinkNeighbor;//一个链接关系,相当于线节点publicdoubleWeight;//权重,初始时置为无穷大,搜寻最短路径时置为该点当前最短路径长度publicVERTEXShortPathPre;//在最短路径上的前一个点publicintLineID;//最短路径中与前一个点之间的线的IDpublicSearchLinkSLink;//Open或Close表中的链接}classLink//点的邻接关系{publicVERTEXv1;//每个Link对象的v1都应该指向它所附属的点节点publicVERTEXv2;//每个Link对象的v2都应该指向与它所附属的点相邻的那个点节点publicdoubleweight;//线的权重publicLinkv1Next;publicLinkv2Next;publicintLineID;}classSearchLink//搜寻路径时的邻接关系,用来放入Open或Close表中{publicVERTEXv;publicSearchLinkPrev;publicSearchLinkNext;}VERTEX类用来存储点节点,Link类用来存储邻接关系,SearchLink是一个临时的中间邻接关系,在寻径时替代VERTEX实例进行运算,用来维持邻接多重表。系统的主要功能函数为:privateVERTEXBuildTopo(IFeatureLayerpFeatLayerP,IFeatureLayerpFeatLayerL,IPointpStartV,IPointpEndV,refintPointCount,refintEdgeCount),主要用来建立拓扑关系privatevoidshortpath(),查询最短路径的主函数privatevoidInsertOrder(SearchLinkvIN,refSearchLinkvTO)按权重的升序插入privatevoidInsert(SearchLinkvIN,refSearchLinkvTO)插入privatevoidDelete(refSearchLinkvOUT,refSearchLinkvFROM)从链表中删除建立拓扑关系:VERTEX[]RoadNode=newVERTEX[NodeCount];indexP=0;pFeatureP=pFeatCsrP.NextFeature();while(null!=pFeatureP){indexP=(int)pFeatureP.get_Value(pFeatureP.Fields.FindField("ID"));if(indexP<0){pFeatureP=pFeatCsrP.NextFeature();continue;}RoadNode[indexP]=newVERTEX();RoadNode[indexP].Neighbor=null;RoadNode[indexP].pPoint=(IPoint)pFeatureP.Shape;RoadNode[indexP].Searched=0;RoadNode[indexP].ShortPathPre=null;RoadNode[indexP].Weight=double.MaxValue;pFeatureP=pFeatCsrP.NextFeature();}首先建立VERTEX数组,用来存放点节点,在遍历点层元素的过程中,根据点的ID号找到数组索引号,生成点节点的实例(即VERTEX实例)。建立这一过程的时间消耗与点的数量n成正比,即时间复杂度为O(n)。pFeatCsrL=pFeatClsL.Search(null,false);intindexP1=0,indexP2=0;pFeatureL=pFeatCsrL.NextFeature();while(null!=pFeatureL)//遍历线对象,根据线的首尾节点ID,即点的索引,找到点,建立链接关系{cnt1++;cntEdge++;vLink1=vLink2=null;pPointCol=(IPointCollection)pFeatureL.Shape;p1=pPointCol.get_Point(0);p2=pPointCol.get_Point(pPointCol.PointCount-1);vWork=vHead.Next;flag1=flag2=0;indexP1=(int)pFeatureL.get_Value(pFeatureL.Fields.FindField("STNODEID"));indexP2=(int)pFeatureL.get_Value(pFeatureL.Fields.FindField("EDNODEID"));indexP=(int)pFeatureL.get_Value(pFeatureL.Fields.FindField("FID"));//依次获得线元素的STNODEID、EDNODEID、FID三个字段的值vLink1=newLink();vLink1.LineID=indexP;vLink1.weight=(double)(int)pFeatureL.get_Value(pFeatureL.Fields.FindField("Weight"));vLink1.v1=RoadNode[indexP1];vLink1.v1Next=RoadNode[indexP1].Neighbor;RoadNode[indexP1].Neighbor=vLink1;//获得线元素的STNODEID值之后,直接可以得到点节点在数组中的位置vLink1.v2=RoadNode[indexP2];vLink1.v2Next=RoadNode[indexP2].Neighbor;RoadNode[indexP2].Neighbor=vLink1;pFeatureL=pFeatCsrL.NextFeature();}点的数组建立完成之后,可以开始遍历线层元素,每取得一个线元素,则可以得到首尾节点的ID,根据首尾节点ID(即首尾节点在数组中的索引)得到首尾节点,分别为首尾节点建立邻接关系vLink1和vLink2,从线元素获得首尾节点的过程的时间复杂度为O(1),而外层while循环是遍历线层元素,时间复杂度为O(n),经过这一过程,拓扑关系基本建立完成,由于采用数组存储VERTEX元素的目的是建立索引,减少建立拓扑关系时点的搜索时间,因此,拓扑关系建立完成后,为了方便运算,也为了尽量减少数组元素所占用的大块内存区域,把VERTEX元素从数组中摘下并建立环状链表:vWork=vHead;for(indexP=1;indexP<NodeCount;indexP++){if(RoadNode[indexP]!=null){RoadNode[indexP].Prev=vWork;RoadNode[indexP].Next=vWork.Next;vWork.Next.Prev=RoadNode[indexP];vWork.Next=RoadNode[indexP];vWork=RoadNode[indexP];}}vWork.Next=vHead;vHead.Prev=vWork;通过这一步操作,环状的邻接多重表建立完成。以上三次遍历并没有嵌套关系,因此整个建立邻接多重表的时间复杂度为O(n)。查询最短路径查询最短路径:intflag=0;intc=0;vWork=vHead.Next;while(c<PointCnt){//根据点节点的数量,循环设定点节点中各字段的初始值if(vWork.id==pStartID){flag++;vHead.Next=vWork;}if(vWork.id==pEndID){flag++;vTail.Next=vWork;}vWork.Searched=0;vWork.ShortPathPre=null;vWork.Weight=double.MaxValue;vWork=vWork.Next;c++;}由于邻接多重表可以重复使用,因此在一次寻径后,链表中的节点的一些属性值可能被改变,因此需要重新初始化节点的属性值,如查询状态Searched、最短路径前导节点ShortPathPre,最短路径值Weight等。sOpen=newSearchLink();sClose=newSearchLink();sOpen.Next=sOpen.Prev=null;sOpen.v=null;sClose.Next=sClose.Prev=null;sClose.v=null;sTemp=newSearchLink();sTemp.v=vHead.Next;sTemp.v.Searched=1;sTemp.v.Weight=0;sTemp.v.SLink=sTemp;sTemp.Prev=sTemp.Next=null;Insert(sTemp,refsOpen);//Insert函数按升序将节点sTemp插入链表sOpen中while(sOpen.Next!=null&&vTail.Next.Searched!=2)//一旦链表sOpen变为空,或终点的最短路径已经找到,则查询结束{sTemp=sOpen.Next;vWork=sTemp.v;vLink=vWork.Neighbor;vWork.Searched=2;Delete(refsTemp,refsOpen);//在sOpen链表中找到权值最小节点之后,将该节点从链表sOpen中移除,并插入链表sClose中,表示该节点的最短路径已经找到Insert(sTemp,refsClose);while(vLink!=null)//遍历节点的各个邻接点{if(vLink.v2.Searched==0)//Searched字段表名该邻接点的搜索状态,如果是0,则表示该邻接点从未被搜索过{vLink.v2.Weight=vWork.Weight+vLink.weight;vLink.v2.LineID=vLink.LineID;vLink.v2.Searched=1;vLink.v2.ShortPathPre=vWork;sTemp1=newSearchLink();sTemp1.v=vLink.v2;sTemp1.v.SLink=sTemp1;InsertOrder(sTemp1,refsOpen);}elseif(vLink.v2.Searched==1)//Searched如果为1,则表示该邻接点已经搜索过,但还没有找到最短路径{if(vLink.v2.Weight>vWork.Weight+vLink.weight)//如果权值不是最小,则需要重新计算权值{Delete(refvLink.v2.SLink,refsOpen);vLink.v2.Weight=vWork.Weight+vLink.weight;vLink.v2.LineID=vLink.LineID;vLink.v2.ShortPathPre=vWork;InsertOrder(vLink.v2.SLink,refsOpen);}}vLink=vLink.Next;}}在开始最短路径查询之前,首先定义两个链表sOpen和sClose,sClose用来放置已经找到最短路径的节点,sOpen用来放置已经搜索但还没有找到最短路径、等待继续搜索的节点。其次需要初始化邻接多重表,将每一个节点的Searched字段置为0,表明该节点还没有被搜索过,并把节点权重置为无穷大(最大值)。这一过程为单循环,时间复杂度为O(n)。以上是最短路径算法的主体部分,首先将源节点的Searched字段置为1,权重置为0,并插入链表sOpen中,而后进入循环搜索最短路径的过程。外循环用来遍历链表sClose,直到链表sClose变为空,或者最短路径的终点vTail的最短路径被找到(Searched字段变为2)。而内循环则遍历sOpen中节点的邻接关系,本算法实现过程中这一循环与节点数或线数并没有数学关系,它的循环次数通常为2~5之间。在每次循环中,首先将节点置于链表sClose中,并把Searched值置为2,表明该节点已经找到最短路径,然后遍历该节点的每一个邻接点,首先判断该邻接点的搜索情况(Searched字段值),然后进行插入或重新插入集合sOpen的操作(InsertOrder),程序中设置了两个插入函数InsertOrder和Insert,InsertOrder函数专用来向sOpen中插入节点,这一过程需要进行排序,因此随着sOpen链表的规模增大,相应的时间消耗也会增大,插入排序过程的时间复杂度为O((n+1)/2)。为了使计算最短路径时搜索的节点范围尽量缩小,程序中对每次更改Searched字段值之后的节点都要移出原集合(链表),这一方式使单次搜索最短路径的效率得到很大的提高。但是随之而来的问题是,单次搜索之后,原来的邻接多重表被破坏了,在下一次搜索前不得不重新建立邻接多重表,由于建立邻接多重表时如果数据量比较大,则程序需要频繁访问外存储器,造成了大量的时间开销。而SearchLink类的引入,使得邻接多重表可以“一次建立,多次使用”,真正提高算法的效率和实用性。SearchLink是纯指针类,实例化的时候只占用很少的内存开销,因此这种以空间换时间的方法能够有效的提高算法执行的效率。GPS导航功能卫星导航技术的飞速发展已逐渐取代了无线电导航、天文导航等传统导航技术,而成为一种普遍采用的导航定位技术,并在精度、实时性、全天候等方面取得了长足进步。现不仅应用于物理勘探、电离层测量和航天器导航等诸多民用领域,在军事领域更是取得了广泛的应用——在弹道导弹、野战指挥系统、精确弹道测量以及军用地图快速测绘等领域均大量采用了卫星导航定位技术。有鉴于卫星导航技术在民用和军事领域的重要意义,使其得到了许多国家的关注。我国也于2000年10月31日和12月21日成功发射了第一颗和第二颗导航定位试验卫星并建立了我国第一代卫星导航定位系统"北斗导航系统",但由于起步晚也没有得到广泛应用。目前在我国应用最多的还是美国的GPS系统。GPS接收机可接收到准确至纳秒级的时间信息;用于预报未来几个月内卫星所处概略位置的预报星历;用于计算定位时所需卫星坐标的广播星历,精度为几米至几十米(各个卫星不同,随时变化);以及GPS系统信息,如卫星状况等。GPS接收机对码的量测就可得到卫星到接收机的距离,由于含有接收机卫星钟的误差及大气传播误差,故称为伪距。对0A码测得的伪距称为UA码伪距,精度约为20米左右,对P码测得的伪距称为P码伪距,精度约为2米左右。GPS接收机对收到的卫星信号,进行解码或采用其它技术,将调制在载波上的信息去掉后,就可以恢复载波。严格而言,载波相位应被称为载波拍频相位,它是收到的受多普勒频移影响的卫星信号载波相位与接收机本机振荡产生信号相位之差。一般在接收机钟确定的历元时刻量测,保持对卫星信号的跟踪,就可记录下相位的变化值,但开始观测时的接收机和卫星振荡器的相位初值是不知道的,起始历元的相位整数也是不知道的,即整周模糊度,只能在数据处理中作为参数解算。相位观测值的精度高至毫米,但前提是解出整周模糊度,因此只有在相对定位、并有一段连续观测值时才能使用相位观测值,而要达到优于米级的定位精度也只能采用相位观测值。按定位方式,GPS定位分为单点定位和相对定位(差分定位)。单点定位就是根据一台接收机的观测数据来确定接收机位置的方式,它只能采用伪距观测量,可用于车船等的概略导航定位。相对定位(差分定位)是根据两台以上接收机的观测数据来确定观测点之间的相对位置的方法,它既可采用伪距观测量也可采用相位观测量,大地测量或工程测量均应采用相位观测值进行相对定位。在GPS观测量中包含了卫星和接收机的钟差、大气传播延迟、多路径效应等误差,在定位计算时还要受到卫星广播星历误差的影响,在进行相对定位时大部分公共误差被抵消或削弱,因此定位精度将大大提高,双频接收机可以根据两个频率的观测量抵消大气中电离层误差的主要部分,在精度要求高,接收机间距离较远时(大气有明显差别),应选用双频接收机。在定位观测时,若接收机相对于地球表面运动,则称为动态定位,如用于车船等概略导航定位的精度为30——100米的伪距单点定位,或用于城市车辆导航定位的米级精度的伪距差分定位,或用于测量放样等的厘米级的相位差分定位(RTK),实时差分定位需要数据链将两个或多个站的观测数据实时传输到一起计算。在定位观测时,若接收机相对于地球表面静止,则称为静态定位,在进行控制网观测时,一般均采用这种方式由几台接收机同时观测,它能最太限度地发挥GPS的定位精度,专用于这种目的的接收机被称为大地型接收机,是接收机中性能最好的一类。目前,GPS已经能够达到地壳形变观测的精度要求,IGS的常年观测台站已经能构成毫米级的全球坐标框架。下面就针对当前比较普及的GPS系统,对其卫星定位信息的接收及其定位参数提取的实现方法予以介绍。定位信息的接收通常GPS定位信息接收系统主要由GPS接收天线、变频器、信号通道、微处理器、存储器以及电源等部分组成。由于GPS定位信息内容较少,因此多用RS-232串口将定位信息(NEMA0183语句)从GPS接收机传送到计算机中进行信息提取处理。初始化并打开串口:对串口初始化通常要完成以下几个设置:设定通信端口号,即CommPort属性;设定通信协议,即HandShaking属性;设定传输速率等参数,即Settings属性;打开通信端口,即将PortOpen属性设为True。if(m_Comm.GetPortOpen())m_Comm.SetPortOpen(FALSE);m_Comm.SetCommPort(1);//选择COM1m_Comm.SetInBufferSize(1024);//设置输入缓冲区的大小if(!m_Comm.GetPortOpen())m_Comm.SetPortOpen(TRUE);//打开串口elseAfxMessageBox("cannotopenserialport");m_Comm.SetSettings("9600,n,8,1");//波特率9600,无校验,8个数据位,1停止位m_Comm.SetInputMode(1);//1:表示以二进制方式检取数据m_Comm.SetRThreshold(1);//1:表示有一个字符引发一个事件从串口读取数据有多种方法,在此直接使用Win32API函数对其进行编程处理。在Windows下不允许直接对硬件端口进行控制操作,所有的端口均被视为“文件”,因此在对串口进行侦听之前需要通过打开文件来打开串口,并对其进行相关参数配置:m_hCom=CreateFile("COM1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);//以异步方式打开COM1口SetCommMask(m_hCom,EV_RXCHAR);//添加或修改Windows所报告的事件列表SetupComm(m_hCom,READBUFLEN/*读缓冲*/,WRITEBUFLEN/*写缓冲*/);//初始化通讯设备参数//清除缓冲信息PurgeComm(m_hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);//对异步I/O进行设置CommTimeOuts.ReadIntervalTimeout=MAXDWORD;//接收两连续字节的最大时间间隔CommTimeOuts.ReadTotalTimeoutMultiplier=0;//接收每字节的平均允许时间CommTimeOuts.ReadTotalTimeoutConstant=0;//接收时间常数SetCommTimeouts(m_hCom,&CommTimeOuts);//获取并设置串口GetCommState(m_hCom,&dcb);dcb.BaudRate=CBR_4800;dcb.ByteSize=8;dcb.Parity=ODDPARITY;dcb.StopBits=ONESTOPBIT;SetCommState(m_hCom,&dcb);在成功打开并设置通讯口后,可采取轮询串口和事件触发两种方式对数据进行接收处理,本文在此采取效率比较高的事件触发方式进行接收处理,通过等待EV_RXCHAR事件的发生来启动ReadFile函数完成对GPS定位信息的接收:while(true){WaitCommEvent(m_hCom,&dwEvtMask,NULL);if(dwEvtMask&EV_RXCHAR==EV_RXCHAR)if(ComStat.cbInQue>0)ReadFile(m_hCom,m_readbuf,ComStat.cbInQue,&nLength,&olRead);}提取定位数据GPS接收机只要处于工作状态就会源源不断地把接收并计算出的GPS导航定位信息通过串口传送到计算机中。前面的代码只负责从串口接收数据并将其放置于缓存,在没有进一步处理之前缓存中是一长串字节流,这些信息在没有经过分类提取之前是无法加以利用的。因此,必须通过程序将各个字段的信息从缓存字节流中提取出来,将其转化成有实际意义的,可供高层决策使用的定位信息数据。同其他通讯协议类似,对GPS进行信息提取必须首先明确其帧结构,然后才能根据其结构完成对各定位信息的提取。对于本文所使用的GARMINGPS天线板,其发送到计算机的数据主要由帧头、帧尾和帧内数据组成,根据数据帧的不同,帧头也不相同,主要有"$GPGGA"、"$GPGSA"、"$GPGSV"以及"$GPRMC"等。这些帧头标识了后续帧内数据的组成结构,各帧均以回车符和换行符作为帧尾标识一帧的结束。对于通常的情况,我们所关心的定位数据如经纬度、速度、时间等均可以从"$GPRMC"帧中获取得到,该帧的结构及各字段释义如下:$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>*hh<1>当前位置的格林尼治时间,格式为hhmmss<2>状态,A为有效位置,V为非有效接收警告,即当前天线视野上方的卫星个数少于3颗。<3>纬度,格式为ddmm.mmmm<4>标明南北半球,N为北半球、S为南半球<5>径度,格式为dddmm.mmmm<6>标明东西半球,E为东半球、W为西半球<7>地面上的速度,范围为0.0到999.9<8>方位角,范围为000.0到359.9度<9>日期,格式为ddmmyy<10>地磁变化,从000.0到180.0度<11>地磁变化方向,为E或W至于其他几种帧格式,除了特殊用途外,平时并不常用,虽然接收机也在源源不断地向主机发送各种数据帧,但在处理时一般先通过对帧头的判断而只对"$GPRMC"帧进行数据的提取处理。如果情况特殊,需要从其他帧获取数据,处理方法与之也是完全类似的。由于帧内各数据段由逗号分割,因此在处理缓存数据时一般是通过搜寻ASCII码"$"来判断是否是帧头,在对帧头的类别进行识别后再通过对所经历逗号个数的计数来判断出当前正在处理的是哪一种定位导航参数,并作出相应的处理。下面就是对缓存Data中的数据进行解帧处理的主要代码,本文在此只关心时间(日期和时间)和地理坐标(经、纬度):for(inti=0;i<DATALENGTH;i++){if(Data[i]=='$')//帧头,SectionID为逗号计数器SectionID=0;if(Data[i]==10){//帧尾}if(Data[i]==',')file://逗号计数SectionID++;else{switch(SectionID){case1://提取出时间m_sTime+=Data[i];break;case2://判断数据是否可信(当GPS天线能接收到有3颗GPS卫星时为A,可信)if(Data[i]=='A')GPSParam[m_nNumber].m_bValid=true;break;case3:file://提取出纬度m_sPositionY+=Data[i];break;case5:file://提取出经度m_sPositionX+=Data[i];break;case9:file://提取出日期m_sDate+=Data[i];break;default:break;}}}现在已将所需信息提取到内存,即时间、日期以及经纬度分别保存在CString型变量m_sTime、m_Data、m_sPositionY和m_sPositionX中。在实际应用中往往要根据需要对其做进一步的运算处理,比如从GPS接收机中获得的时间信息为格林尼治时间,因此需要在获取时间上加8小时才为我国标准时间。而且GPS使用的WGS-84坐标系也与我国采用的坐标系不同,有时也要对此加以变换。而这些变换运算必须通过数值运算完成,因此需要将前面获取的字符型变量转化为数值型变量,这部分工作可放在检测到帧尾完成:::strcpy(buf,m_sTime);str.Format("%c%c",buf[0],buf[1]);GPSParam[m_nNumber].m_nHour=(atoi(str)+8)%24;//提取出小时并转化为24小时制北京时间file://buf第2、3字节为分钟,4、5字节为秒,提取方法同上……::strcpy(buf,m_sDate);str.Format("%c%c",buf[0],buf[1]);//提取出月份//buf第2、3字节为天,4、5字节为年,提取方法同上……::strcpy(buf,m_sPositionY);str.Format("%c%c",buf[0],buf[1]);PositionValue=atoi(str);str.Format("%c%c%c%c%c%c%c",buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8]);GPSParam[m_nNumber].m_dPositionY=PositionValue*60+atof(str);//提取出纬度……::strcpy(buf,m_sPositionX);if(m_sPositionX.GetLength()==10)//经度超过90度(如东经125度){str.Format("%c%c%c",buf[0],buf[1],buf[2]);PositionValue=atoi(str);str.Format("%c%c%c%c%c%c%c",buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9]);GPSParam[m_nNumber].m_dPositionX=PositionValue*60+atof(str);//提取出经度(单位为分)}if(m_sPositionX.GetLength()==9)//经度未超过90度(如东经89度){//处理方法同上,只是buf的第0、1字节为度数,2~9为分数。}通过上面的设计方法可以将GPS定位导航信息从GPS接收机完整接收。总结可以看出,MapX开发平台可以提供地理信息应用系统所需要的各主要方面功能,并具有开发方式灵活,接口简便的特点,不失为开发地理信息应用系统的理想平台。建立一个GIS应用系统是比较复杂的,并且必须根据特定的要求来实现不同的功能。由于笔者能力有限,本文采用面向对象程序设计语言VC++,集成MapX、MSComm控件,实现了一个小型的GPS导航信息系统应用软件,旨在为用户提供开发具有典型GIS功能的应用软件接口程序的基本方法。在实际应用中,可以在此基础上进行完善和扩充,来满足不同的需求。参考文献1.贾国宪,刘新江.VC环境下基于GIS的GPS导航系统的开发[J],北京测绘,2003年,第二期:41,51,61,712.颜辉武,吴小芳,祝国瑞.VC++环境下基于MapX控件的GIS应用软件的开发[J],昆明理工大学学报,2001年12月,第26卷第6期:12-173.岳新利,张永进,孙毅.基于MapX平台的地理信息系统开发技术的研究[J],现代电子技术,2003年,第8期:75-774.车建仁.VC++环境下基于MapX开发的旅游信息系统[J],水利科技与经济,2004年12月,第10卷第6期:382-3845.冯永玉,王宝山,路天伟.VC++环境下基于MapX控件的GIS应用软件基本功能的开发[J],焦作工学院学报,2004年11月,第23卷第6期:451-4556.侯江丽.VC环境下基于MapX控件的地理信息系统的开[J]发,邢台职业技术学院学报,2005年10月,第22卷第5期:63-657.韩平阳,罗五明.基于MapX的地理信息系统的VC开发[J],交通与计算机,2004年,第22卷第5期:71-748.王德文,赵文清.基于MapX的地理信息系统的设计与实现[J],微机发展,2003年5月,第13卷第5期:59-619.王世东,陈魁奎.基于MapX的地理信息系统应用软件的开发[J],电脑学习,2006年8月,第4期:2-310.王丰,高光金.VisualC++6.0程序设计教程与实训[M],北京:北京大学出版社,2005年9月11.姜晓铭.VisualC++6.0程序设计应用短期培训教程[M],北京:北京工业大学出版社,2000年5月12.吴信才.地理信息系统原理与方法[M],北京:电子工业出版社,2002年,P218-22313.龚健雅.地

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论