完整版基于VC++的电子导航系统毕业设计.docx
- 文档编号:14983431
- 上传时间:2023-06-29
- 格式:DOCX
- 页数:32
- 大小:461.20KB
完整版基于VC++的电子导航系统毕业设计.docx
《完整版基于VC++的电子导航系统毕业设计.docx》由会员分享,可在线阅读,更多相关《完整版基于VC++的电子导航系统毕业设计.docx(32页珍藏版)》请在冰点文库上搜索。
完整版基于VC++的电子导航系统毕业设计
基于VC++的电子导航系统
摘要
地理信息系统(GIS)自二十世纪六十年代开始发展至今,已经逐渐成为一门成熟的技术,其在交通、旅游、环境等诸多领域的应用使地理信息系统被越来越多的用户所接受,成为人们工作、生活中一个强有力的工具。
本设计以VC++为开发平台,以MapX控件为图形平台,以MSComm控件为通信平台,设计具有电子导航的基本功能(如地图的放大缩小、全图、漫游等)、自定义工具测量折线距离、图层控制、最优路径分析、GPS导航等功能的GIS应用软件。
本文介绍了电子导航系统设计的背景及设计中需要用到的MapX控件、VC++、MSComm控件,分析了GIS开发三种实现方式,提出系统设计方案:
集成二次开发。
在集成二次开发的基础上,首先实现了地图的导入、地图放大缩小及图层控制等电子导航的基本功能,其次以测量折线距离为例实现了自定义工具的功能,再次介绍了最优路径分析,最后实现GPS导航功能。
关键词:
电子导航;GIS开发;VC++;MapX控件;最优路径
ElectronicNavigationSystemsBasedOnVC++
Abstract
Sincethebeginningof1960s,GeographicInformationSystem(GIS)transportation,tourism,environmentandmanyotherfieldsofapplicationGISacceptedbyanincreasingnumberofusersforthepeopleworkingandlivingasapowerfultool.
ThedesignusedVC++asadevelopmentplatform,MapXcontrolasagraphicsplatform,MSCommcontrolasacommunicationsplatform.ItBasicfunctions(zoomcontrol,thewholemap,Roaming,forexample),Calculatingthedistance,LayerControl,AnalysisoftheoptimalpathandGPSNavigationFeatures.
Thisarticleofelectronicnavigationsystemsbackground,MapXcontrol,VC++andMSCommcontrol.Itthreewaysandproposedsystemdesign:
Secondarydevelopmentofintegrated.Firstofall,Ittheintegrateddevelopmentofthebasisofsecondary.Second,itexampletomeasurethedistance,andthenit.
Keywords:
Electronicnavigation;GISDevelopment;VC++;MapXcontrol;Optimalpath
第一章引言
1.1设计背景
学科发展走向综合是一个普遍的趋势,比如全球定位系统(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.-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地图的显示
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工具的指示常量
2.2图层控制工具
为了使用户方便查询各个图层,通常要在电子导航系统中设计图层控制工具。
在菜单中建立图层控制菜单,设置图层控制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方法创建自定义工具。
下面是用自定义工具实现折线距离的计算。
3.1创建用户自定义工具
为了满足用户需要,使用户方便查询两地之间的距离,我们利用自定义工具在电子导航系统中设计了折线距离计算功能。
方法如下:
首先,在VCDZDH.-1;
……
m_ctrlMapX.CreateCustomTool(MYTOOL_DISTANCE,miToolTypePoly,miCrossCursor);MYTOOL_DISTANCE代表自定义工具的常量,miToolTypePoly描述了该工具的行为是画折线,miCrossCursor表示指定光标的形式
return0;
}
3.2编程实现自定义工具的行为
在创建了用户自定义工具后,需在ToolUsed事件中实现该工具是如何工作的。
要处理MapX事件,首先需要为要处理的事件创建一事件槽,其方法如下。
在VCDZDHView.;
longi;
try
{
pts.AttachDispatch(Points,FALSE);
doubledDistanceTot=0.0;
n=pts.GetCount();
for(i=1;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.[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;最短路径中与前一个点之间的线的ID publicSearchLinkSLink;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,IFeatureLayer pFeatLayerL,IPointpStartV,IPointpEndV,refintPointCount,refint EdgeCount),主要用来建立拓扑关系 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 { 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)。 4.1查询最短路径 查询最短路径: intflag=0; intc=0; vWork=vHead.Next; while(c if(vWork.id==pStartID) { flag++;vHead.Next=vWork; } if(vWork.id==pEndID) { flag++; vTail.Next=vWork; } vWork.Searched=0; vWork.ShortPathPre=nul
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 完整版 基于 VC 电子 导航系统 毕业设计
![提示](https://static.bingdoc.com/images/bang_tan.gif)