版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
內(nèi)蒙古科技大學(xué)畢業(yè)設(shè)計說明書(畢業(yè)論文)PAGEPAGE57基于VC++的電子導(dǎo)航系統(tǒng)摘要地理信息系統(tǒng)(GIS)自二十世紀(jì)六十年代開始發(fā)展至今,已經(jīng)逐漸成為一門成熟的技術(shù),其在交通、旅游、環(huán)境等諸多領(lǐng)域的應(yīng)用使地理信息系統(tǒng)被越來越多的用戶所接受,成為人們工作、生活中一個強(qiáng)有力的工具。本設(shè)計以VC++為開發(fā)平臺,以MapX控件為圖形平臺,以MSComm控件為通信平臺,設(shè)計具有電子導(dǎo)航的基本功能(如地圖的放大縮小、全圖、漫游等)、自定義工具測量折線距離、圖層控制、最優(yōu)路徑分析、GPS導(dǎo)航等功能的GIS應(yīng)用軟件。本文介紹了電子導(dǎo)航系統(tǒng)設(shè)計的背景及設(shè)計中需要用到的MapX控件、VC++、MSComm控件,分析了GIS開發(fā)三種實(shí)現(xiàn)方式,提出系統(tǒng)設(shè)計方案:集成二次開發(fā)。在集成二次開發(fā)的基礎(chǔ)上,首先實(shí)現(xiàn)了地圖的導(dǎo)入、地圖放大縮小及圖層控制等電子導(dǎo)航的基本功能,其次以測量折線距離為例實(shí)現(xiàn)了自定義工具的功能,再次介紹了最優(yōu)路徑分析,最后實(shí)現(xiàn)GPS導(dǎo)航功能。關(guān)鍵詞:電子導(dǎo)航;GIS開發(fā);VC++;MapX控件;最優(yōu)路徑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 設(shè)計背景 11.2 系統(tǒng)設(shè)計方案 41.2.1 應(yīng)用型GIS開發(fā)的三種實(shí)現(xiàn)方式 41.2.2 三種實(shí)現(xiàn)方式的分析 5第二章電子導(dǎo)航基本功能在VC++中的實(shí)現(xiàn) 72.1 利用MapX實(shí)現(xiàn)GIS基本功能 72.1.1 將MapX支持類庫加入工程 72.1.2 地圖的顯示 72.2 使用地圖標(biāo)準(zhǔn)工具 92.3 圖層控制工具 11第三章自定義工具測量折線距離 133.1 創(chuàng)建用戶自定義工具 133.2 編程實(shí)現(xiàn)自定義工具的行為 143.3 調(diào)用自定義工具 16第四章最優(yōu)路徑分析 184.1 實(shí)現(xiàn)過程及其算法分析 184.2 查詢最短路徑 25第五章GPS導(dǎo)航功能 305.1 定位信息的接收 325.2 提取定位數(shù)據(jù) 34總結(jié) 39參考文獻(xiàn) 40附錄:源程序 42CVCDZDHView類源程序 42致謝 52引言設(shè)計背景學(xué)科發(fā)展走向綜合是一個普遍的趨勢,比如全球定位系統(tǒng)(GPS)與地理信息系統(tǒng)(GIS)的集成應(yīng)用。目前用于GIS應(yīng)用軟件開發(fā)的模式有很多,其中組件式GIS軟件開發(fā)是目前較為流行、高效、快速的開發(fā)模式。隨著計算機(jī)技術(shù)的飛速發(fā)展,GIS得到了廣泛的重視和應(yīng)用,GPS技術(shù)也已深入到各行各業(yè),GPS與GIS的集成具有廣泛的應(yīng)用需求,它可以實(shí)現(xiàn)GPS導(dǎo)航信息在地圖上的可視化、一體化和集成化,能夠在地圖上實(shí)時動態(tài)地跟蹤目標(biāo)和顯示地理方位。VC++是目前較流行的可視化開發(fā)編程工具之一,支持面向?qū)ο蠛褪录?qū)動機(jī)制的程序開發(fā),利用其強(qiáng)大的集成開發(fā)環(huán)境,程序員僅需要較少代碼即可生成標(biāo)準(zhǔn)的“Windows”界面,并且能在VC開發(fā)平臺下可以較為方便的集成組件。本文主要介紹利用MapX控件,采用VC++編程語言進(jìn)行組件式GIS應(yīng)用軟件開發(fā)的主要過程和基本模式,來實(shí)現(xiàn)電子導(dǎo)航的目的。MapX是MapInfo公司向用戶提供的具有強(qiáng)大地圖分析功能的ActiveX控件產(chǎn)品。由于它是一種基于Windows操作系統(tǒng)的標(biāo)準(zhǔn)控件,因而能支持絕大多數(shù)標(biāo)準(zhǔn)的可視化開發(fā)環(huán)境如VisualC++、VisualBasic、Delphi、PowerBuilder等。編程人員在開發(fā)過程中可以選用自己最熟悉的開發(fā)語言,輕松地將地圖功能嵌入到應(yīng)用中,并且可以脫離MapInfo的軟件平臺運(yùn)行。利用MapX,能夠簡單快速地在企業(yè)應(yīng)用中嵌入地圖化功能,增強(qiáng)企業(yè)應(yīng)用的空間分析能力,實(shí)現(xiàn)企業(yè)應(yīng)用的增值。MapX采用基于MapInfoProfessional的相同的地圖化技術(shù),可以實(shí)現(xiàn)MapInfoProfessional具有的絕大部分地圖編輯和空間分析功能。而且,MapX提供了各種工具、屬性和方法,實(shí)現(xiàn)這些功能是非常容易的[1]。MapX為開發(fā)人員提供了一個快速、易用、功能強(qiáng)大的地圖化組件。在VB,Delphi,PowerBuilder,VC等可視化開發(fā)環(huán)境中,只需在設(shè)計階段將MapX控件放入窗體中,并對其進(jìn)行編程,設(shè)置屬性或調(diào)用方法或相應(yīng)事件,即可實(shí)現(xiàn)數(shù)據(jù)可視化,專題分析,地理查詢,地理編碼等豐富的地圖信息系統(tǒng)功能。MapX定義了一個類體系,以有效的組織圖形元素,圖層,屬性數(shù)據(jù)等對象。MapX的主要功能包括:顯示MapInfo格式的地圖;對地圖進(jìn)行放大、縮小、漫游、選擇等操作;專題地圖;圖層控制;數(shù)據(jù)綁定;動態(tài)圖層和用戶繪圖圖層;生成和編輯地圖對象;簡單地理查詢:邊界查詢,地址查詢。VC++是微軟公司開發(fā)的一個IDE(集成開發(fā)環(huán)境),換句話說,就是使用C++的一個開發(fā)平臺。有些軟件就是這個編出來的,另外還有VB、VF,只是使用不同語言。但是,VC++是Windows平臺上的C++編程環(huán)境,學(xué)習(xí)VC要了解很多Windows平臺的特性并且還要掌握MFC、ALT、COM等的知識。Windows下編程需要了解Windows的消息機(jī)制以及回調(diào)(callback)函數(shù)的原理;MFC是Win32API的包裝類,需要理解文檔視圖類的結(jié)構(gòu),窗口類的結(jié)構(gòu),消息流向等等;COM是代碼共享的二進(jìn)制標(biāo)準(zhǔn),需要掌握其基本原理等等。VC++應(yīng)用程序的開發(fā)主要有兩種模式,一種是WINAPI方式,另一種則是MFC方式,傳統(tǒng)的WINAPI開發(fā)方式比較繁瑣,而MFC則是對WINAPI再次封裝,所以MFC相對于WINAPI開發(fā)更具備效率優(yōu)勢。VC基于C,C++語言,主要由是MFC組成,是與系統(tǒng)聯(lián)系非常緊密的編程工具,它兼有高級,和低級語言的雙重性,功能強(qiáng)大,靈活,執(zhí)行效率高,幾乎可說VC在Windows平臺無所不能。MSComm作為一個串行通訊控件為程序員串口通訊編程節(jié)省了很多時間。在基于對話框的應(yīng)用中加入一個MSComm控件非常簡單。只需進(jìn)行以下操作即可:打開“Project->AddToProject->ComponentsandControls->RegisteredActivexControls”,然后選擇控件:MicrosoftCommunicationControl,version6.0插入到當(dāng)前的工程中。這樣就將類CMSComm的相關(guān)文件mscomm.cpp和mscomm.h一并加入到了工程中。編程時只需將控件對話中的MSComm控件拖至你的應(yīng)用對話框中就OK了。MSComm控件提供了兩種處理通信的方法:1.事件驅(qū)動通信,是一種功能很強(qiáng)的處理串口活動的方法。例如,當(dāng)在CD(CarrierDetect)線或RTS(RequestToSend)線上有字符到達(dá)或發(fā)生了改變,在這種情況下,可以使用MSComm控件的OnComm事件捕獲和處理這些通信事件。OnComm也可以捕獲和處理通信中的錯誤。2.可以在每個重要的程序功能之后檢查CommEvent屬性的值來檢測事件和通信錯誤。使用的每個MSComm控件都與一個串口對應(yīng)。如果在應(yīng)用程序中需要訪問多個串口,必須使用多個MSComm控件,可以在Windows控制面板中修改串口地址的中斷地址。MSComm控件有很多重要的屬性,如:CommPort屬性:設(shè)置并返回通訊端口號。RThreshold屬性:在MSComm控件設(shè)置CommEvent屬性為comEReceive并產(chǎn)生OnComm之前,設(shè)置并返回的要接收的字符數(shù)。CTSHolding屬性:確定是否可通過查詢ClearToSend(CTS)線的狀態(tài)發(fā)送數(shù)據(jù)。ClearToSend是調(diào)制解調(diào)器發(fā)送到相聯(lián)計算機(jī)的信號,指示傳輸可以進(jìn)行。該屬性在設(shè)計時無效,在運(yùn)行時為只讀。SThreshold屬性:在MSComm控件設(shè)置CommEvent屬性為comEvSend并產(chǎn)生OnComm事件之前,設(shè)置并返回傳輸緩沖區(qū)中允許的最小字符數(shù)。CDHolding屬性:通過查詢CarrierDetect(CD)線的狀態(tài)確定當(dāng)前是否有傳輸。CarrierDetect是從調(diào)制解調(diào)器發(fā)送到相聯(lián)計算機(jī)的一個信號,指示調(diào)制解調(diào)器正在聯(lián)機(jī)。該屬性在設(shè)計時無效,在運(yùn)行時為只讀。DSRHolding屬性:確定DataSetReady(DSR)線的狀態(tài)。DataSetReady信號由調(diào)制解調(diào)器發(fā)送到相連計算機(jī),指示作好操作準(zhǔn)備。該屬性在設(shè)計時無效,在運(yùn)行時為只讀。Settings屬性:設(shè)置并返回波特率、奇偶校驗(yàn)、數(shù)據(jù)位、停止位參數(shù)。InputLen屬性:設(shè)置并返回Input屬性從接收緩沖區(qū)讀取的字符數(shù)。系統(tǒng)設(shè)計方案應(yīng)用型GIS開發(fā)的三種實(shí)現(xiàn)方式(1)獨(dú)立開發(fā)不依賴于任何GIS工具軟件,從空間數(shù)據(jù)的采集、編輯到數(shù)據(jù)的處理分析及結(jié)果輸出,所有的算法都由開發(fā)者獨(dú)立設(shè)計,然后選用某種程序設(shè)計語言,如VisualC++、Delphi等,在一定的操作系統(tǒng)平臺上編程實(shí)現(xiàn)。這種方式的好處在于無須依賴任何商業(yè)GIS工具軟件,減少了開發(fā)成本,但一方面對于大多數(shù)開發(fā)者來說,能力、時間、財力方面的限制使其開發(fā)出來的產(chǎn)品很難在功能上與商業(yè)化GIS工具軟件相比,而且在購買GIS工具軟件上省下的錢可能還抵不上開發(fā)者在開發(fā)過程中絞盡腦汁所花的代價。(2)單純二次開發(fā)完全借助于GIS工具軟件提供的開發(fā)語言進(jìn)行應(yīng)用系統(tǒng)開發(fā)。GIS工具軟件大多提供了可供用戶進(jìn)行二次開發(fā)的宏語言,如ESRI的ArcView提供了Avenue語言,MapInfo公司研制的MapInfoProfessional提供了MapBasic語言等等。用戶可以利用這些宏語言,以原GIS工具軟件為開發(fā)平臺,開發(fā)出自己的針對不同應(yīng)用對象的應(yīng)用程序。這種方式省時省心,但進(jìn)行二次開發(fā)的宏語言,作為編程語言只能算是二流,功能極弱,用它們來開發(fā)應(yīng)用程序仍然不盡如人意。(3)集成二次開發(fā)集成二次開發(fā)是指利用專業(yè)的GIS工具軟件,如MapInfo、ArcView等,實(shí)現(xiàn)GIS的基本功能,以通用軟件開發(fā)工具尤其是可視化開發(fā)工具,如VisualC++、Delphi、VisualBasic、PowerBuilder等為開發(fā)平臺,進(jìn)行二者的集成開發(fā)。集成二次開發(fā)目前主要有兩種方式:1)OLE/DDE采用OLEAutomation技術(shù)或利用DDE技術(shù),用軟件開發(fā)工具開發(fā)前臺可執(zhí)行應(yīng)用程序,以O(shè)LE自動化方式或DDE方式啟動GIS工具軟件在后臺執(zhí)行,利用回調(diào)技術(shù)動態(tài)獲取其返回信息,實(shí)現(xiàn)應(yīng)用程序中的地理信息處理功能。2)GIS控件利用GIS工具軟件生產(chǎn)廠家提供的建立在OCX技術(shù)基礎(chǔ)上的GIS功能控件,如ESRI的MapObjects、MapInfo公司的MapX等,在VC++等編程工具編制的應(yīng)用程序中,直接將GIS功能嵌入其中,實(shí)現(xiàn)地理信息系統(tǒng)的各種功能。三種實(shí)現(xiàn)方式的分析由于獨(dú)立開發(fā)難度太大,單純二次開發(fā)受GIS工具提供的編程語言的限制差強(qiáng)人意,因此結(jié)合GIS工具軟件與當(dāng)今可視化開發(fā)語言的集成二次開發(fā)方式就成為GIS應(yīng)用開發(fā)的主流。它的優(yōu)點(diǎn)是既可以充分利用GIS工具軟件對空間數(shù)據(jù)庫的管理、分析功能,又可以利用其它可視化開發(fā)語言具有的高效、方便等編程優(yōu)點(diǎn),集二者之所長,不僅能大大提高應(yīng)用系統(tǒng)的開發(fā)效率,而且使用可視化軟件開發(fā)工具開發(fā)出來的應(yīng)用程序具有更好的外觀效果,更強(qiáng)大的數(shù)據(jù)庫功能,而且可靠性好、易于移植、便于維護(hù),尤其是使用OCX技術(shù)利用GIS功能組件進(jìn)行集成開發(fā),更能表現(xiàn)出這些優(yōu)勢。由于上述優(yōu)點(diǎn),集成二次開發(fā)正成為應(yīng)用GIS開發(fā)的主流方向。這種方法唯一的缺點(diǎn)是前期投入比較大,需要同時購買GIS工具軟件和可視化編程軟件,但“工欲善其事,必先利其器”,這種投資值得。目前許多軟件公司都開發(fā)了很多ActiveX控件,合理選擇和運(yùn)用現(xiàn)成的控件,減少了開發(fā)者的編程工作量,使開發(fā)者避開某些應(yīng)用的具體編程,直接調(diào)用控件,實(shí)現(xiàn)這些具體應(yīng)用,不僅可以縮短程序開發(fā)周期,使編程過程更簡潔,用戶界面更友好,可以使程序更加靈活、簡便。與利用OLEAutomation技術(shù)作為服務(wù)器的MapInfo相比,利用控件開發(fā)速度快,占用資源少,而且易實(shí)現(xiàn)許多底層的編程和開發(fā)功能[4]。電子導(dǎo)航基本功能在VC++中的實(shí)現(xiàn)利用MapX實(shí)現(xiàn)GIS基本功能在進(jìn)行MapX開發(fā)之前,首先要在計算機(jī)中正確的安裝了MapX控件和VC++應(yīng)用程序。下面就用一個具體的實(shí)例,介紹在VC++中集成MapX的方法。將MapX支持類庫加入工程利用VC++環(huán)境下的應(yīng)用程序生成向?qū)?chuàng)建一單文檔界面應(yīng)用程序VCDZDH。先將位于MapX的安裝路徑下的子目錄Samples40\C++\Cpp中的MapX.h和MapX.cpp文件拷貝到當(dāng)前應(yīng)用程序所在的VCDZDH文件夾下,然后從Project菜單中選擇AddtoProject>Files命令,此時打開了InsertFilesintoProject對話框,選擇VCDZDH文件夾下的MapX.cpp和MapX.h文件加入到工程中。地圖的顯示在VCDZDH文件夾下新建文件夾map,map中復(fù)制MapInfo格式的地圖文件及Geoset(.GST)文件MY.GST。用戶只需要打開Geoset文件,就可以按預(yù)先定制的方式顯示各層地圖。通過以下步驟,就可以實(shí)現(xiàn)地圖的顯示[5]。1)在VCDZDHView.h文件中,加入MapX.h對象的頭文件,并聲明CMapX類型的變量m_ctrlMapX。方法如下:#include“MAPX.H”ClassCVCDZDHView::publicCView{protected:CMapXm_ctrlMapX;//聲明CMapX類型的變量m_ctrlMapX}2)為MapX創(chuàng)建一個資源ID。選擇ViewResourceSymbols,并點(diǎn)擊New按鈕,輸入名稱IDC_MAP,值取默認(rèn)數(shù)值。3)在VCDZDHView.h文件中聲明int類型的全局變量m_created和CString類型的全局變量m_tempclientpath。通過類向?qū)?chuàng)建消息映射函數(shù)WM_CREATE。選擇“建立類向?qū)А被蚴褂每旖萱ICTRL+W,可以打開類向?qū)А念惷羞x擇CVCDZDHView類,在消息框中選擇WM_CREATE消息,然后添加函數(shù),編輯代碼創(chuàng)建MapX對象。代碼如下:intCVCDZDHView::OnCreate(LPCREATESTRUCTlpCreateStruct){if(!m_ctrlMapX.Create(NULL,WS_VISIBLE,CRect(0,0,100,100),this,IDC_MAP))return-1;}4)采用同樣的方法創(chuàng)建WM_SIZE消息映射函數(shù)。該函數(shù)用來調(diào)整地圖大小使其充滿客戶區(qū)。具體代碼如下:voidCVCDZDHView::OnSize(UINTnType,intcx,intcy){CView::OnSize(nType,cx,cy);m_ctrlMapX.MoveWindow(0,0,cx,cy);//調(diào)整地圖大小}5)采用同樣的方法創(chuàng)建WM_SETFOCUS消息映射函數(shù)。修改函數(shù)使得當(dāng)窗口獲得焦點(diǎn)時,地圖控件獲得焦點(diǎn)。具體代碼如下。voidCVCDZDHView::OnSetFocus(CWnd*pOldWnd){CView::OnSetFocus(pOldWnd);m_ctrlMapX.SetFocus();//當(dāng)窗口獲得焦點(diǎn)時,地圖控件獲得焦點(diǎn)}通過以上步驟,將應(yīng)用程序編譯運(yùn)行就可顯示地圖。如圖2.1所示:圖2.1地圖的顯示使用地圖標(biāo)準(zhǔn)工具在地圖顯示出來后,用戶通常要以各種比例查看地圖的全局、局部或細(xì)部,必須提供諸如放大、縮小和漫游等功能。采用MapX通用工具,可以非常方便地實(shí)現(xiàn)上述功能。設(shè)定MapX使用標(biāo)準(zhǔn)工具的方法很簡單,只需設(shè)定地圖對象的CulrentTool屬性。下面的例子是用標(biāo)準(zhǔn)放大工具實(shí)現(xiàn)放大功能。添加新菜單項(xiàng)資源,輸入標(biāo)題“工具”,在“工具”下添加子菜單,輸入標(biāo)題“放大”及ID為ID_ZOOM_IN。打開類向?qū)Вx擇視圖類CVCDZDHView,為菜單項(xiàng)ID_ZOOM_IN添加COMMAND消息映射函數(shù)OnZoomIn(),并編輯代碼如下。voidCVCDZDHView::OnZoomIn(){m_ctrlMapX.SetCurrentTool(miZoomInToo1);//miZoomInTool為放大工具的常量}編譯運(yùn)行程序,選擇“工具>放大”,就會看到此時光標(biāo)變?yōu)榉糯箸R,單擊鼠標(biāo)就會實(shí)現(xiàn)放大功能。如圖2.2所示:圖2.2放大功能演示可用相同方法實(shí)現(xiàn)縮小、漫游、全圖等標(biāo)準(zhǔn)工具的功能。其它的功能跟上面的方法類似,只是需要修改指示常量。表2.1中列出了部分MapX工具的指示常量[9]。表2.1部分MapX工具的指示常量圖層控制工具為了使用戶方便查詢各個圖層,通常要在電子導(dǎo)航系統(tǒng)中設(shè)計圖層控制工具。在菜單中建立圖層控制菜單,設(shè)置圖層控制ID為ID_VIEW_LAYERCONTROL,然后建立類向?qū)Вx擇CVCDZDHView類,添加如下函數(shù):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();}}這樣,就添加上了圖層控制工具,運(yùn)行程序,該功能如圖2.3所示:圖2.3圖層控制工具自定義工具測量折線距離MapX提供的地圖標(biāo)準(zhǔn)工具能滿足一般需要,但在一些特殊地方,用戶可能需要某種特殊工具來完成某些特定的地圖操作功能。因此,MapX提供了用戶自定義工具的方法,這樣可以大大擴(kuò)展MapX的應(yīng)用范圍??墒褂玫貓D對象的CreateCustomTool方法創(chuàng)建自定義工具。下面是用自定義工具實(shí)現(xiàn)折線距離的計算。創(chuàng)建用戶自定義工具為了滿足用戶需要,使用戶方便查詢兩地之間的距離,我們利用自定義工具在電子導(dǎo)航系統(tǒng)中設(shè)計了折線距離計算功能。方法如下:首先,在VCDZDH.h文件中定義常量。#defineMYTOOL_DISTANCE1然后,在VCDZDH.cpp文件中的OnCreate()函數(shù)中加入如下代碼,從而創(chuàng)建一個用戶自定義工具。intCVCDZDHView::OnCreate(LPCREATESTRUCTlpCreateStruct){if(CView::OnCreate(1pCreateStruct)==-1)return-1;……m_ctrlMapX.CreateCustomTool(MYTOOL_DISTANCE,miToolTypePoly,miCrossCursor);//MYTOOL_DISTANCE代表自定義工具的常量,miToolTypePoly描述了該工具的行為是畫折線,miCrossCursor表示指定光標(biāo)的形式return0;}編程實(shí)現(xiàn)自定義工具的行為在創(chuàng)建了用戶自定義工具后,需在ToolUsed事件中實(shí)現(xiàn)該工具是如何工作的。要處理MapX事件,首先需要為要處理的事件創(chuàng)建一事件槽,其方法如下。在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是事件響應(yīng)函數(shù)的名稱。END_EVENTSINK_MAP()BEGIN_EVENTSINK_MAP(CVCDZDHView,CView)和END_EVENTSINK_MAP()兩行代碼之間加入的,就是要處理的事件。切換到VCDZDHView.h文件中,聲明事件響應(yīng)函數(shù),代碼如下。voidOnPolyToolUsedMap(shortToolNum,longFlags,LPDISPATCHPoints,BOOLbShift,BOOLbCtrl,BOOLFAR*EnableDefauh)然后在VCDZDHView.cpp中加入函數(shù)的實(shí)現(xiàn)代碼。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);//在狀態(tài)欄中顯示折線距離}catch(COleDispatchException*e){e->ReportError();e->Delete();}catch(COleException*e){e->ReportError();e->Delete();}}}為了在狀態(tài)欄中顯示折線距離,還必須在VCDZDH.cpp文件中添加CMainFrame類的頭文件。#include“MainFrm.h”并且將CMainFrame類中的mwndStatusBar由受保護(hù)的變量改為全局變量。調(diào)用自定義工具在“工具”下拉菜單中添加“折線距離”子菜單項(xiàng),ID為ID_DISTANCE_TOOL。打開類向?qū)Вx擇視圖類CVCDZDHView,為菜單項(xiàng)ID_DISTANCE_TOOL添加COMMAND消息映射函數(shù)OnPolydistancetool(),添加代碼如下。voidCVCDZDHView::OnDistanceTool(){ //TODO:Addyourcommandhandlercodehere m_ctrlMapX.SetCurrentTool(MYTOOL_DISTANCE);//調(diào)用自定義工具}編譯并運(yùn)行程序,如圖3.1所示為使用“折線距離”工具的應(yīng)用程序界面。圖3.1折線距離演示最優(yōu)路徑分析對城市道路網(wǎng)進(jìn)行最短路徑分析,需要把城市道路網(wǎng)絡(luò)實(shí)體抽象化為網(wǎng)絡(luò)圖論理論中的網(wǎng)絡(luò)圖,然后通過圖論中的網(wǎng)絡(luò)分析理論來實(shí)現(xiàn)道路網(wǎng)絡(luò)的最短路徑分析。在實(shí)際應(yīng)用中,道路網(wǎng)的表現(xiàn)形式一般為數(shù)字化的矢量地圖,其網(wǎng)絡(luò)空間特征中的交叉路口坐標(biāo)和道路位置坐標(biāo)是在地圖上借助圖形來識別和解釋的;而為了能夠高效率地進(jìn)行最短路徑分析,必須首先將其按結(jié)點(diǎn)和弧的關(guān)系抽象為圖的結(jié)構(gòu)。這就需要先對原始道路圖進(jìn)行預(yù)處理,構(gòu)建其相應(yīng)的網(wǎng)絡(luò)拓?fù)潢P(guān)系,然后才能進(jìn)行最短路徑分析等各種操作。下面介紹一種Dijkstra算法。實(shí)現(xiàn)過程及其算法分析Dijkstra(迪杰斯特拉)算法是典型的最短路徑路由算法,用于計算一個節(jié)點(diǎn)到其他所有節(jié)點(diǎn)的最短路徑。主要特點(diǎn)是以起始點(diǎn)為中心向外層層擴(kuò)展,直到擴(kuò)展到終點(diǎn)為止。Dijkstra算法能得出最短路徑的最優(yōu)解,但由于它遍歷計算的節(jié)點(diǎn)很多,所以效率低。Dijkstra算法一般的表述通常有兩種方式,一種用永久和臨時標(biāo)號方式,一種是用OPEN,CLOSE表方式。其采用的是貪心法的算法策略,大概過程:創(chuàng)建兩個表,OPEN,CLOSE。OPEN表保存所有已生成而未考察的節(jié)點(diǎn),CLOSED表中記錄已訪問過的節(jié)點(diǎn)。1.訪問路網(wǎng)中距離起始點(diǎn)最近且沒有被檢查過的點(diǎn),把這個點(diǎn)放入OPEN組中等待檢查。2.從OPEN表中找出距起始點(diǎn)最近的點(diǎn),找出這個點(diǎn)的所有子節(jié)點(diǎn),把這個點(diǎn)放到CLOSE表中。3.遍歷考察這個點(diǎn)的子節(jié)點(diǎn)。求出這些子節(jié)點(diǎn)距起始點(diǎn)的距離值,放子節(jié)點(diǎn)到OPEN表中。4.重復(fù)第2和第3步,直到OPEN表為空,或找到目標(biāo)點(diǎn)。Dijkstra算法的基本思路是:假設(shè)每個點(diǎn)都有一對標(biāo)號(dj,pj),其中dj是從起源點(diǎn)s到點(diǎn)j的最短路徑的長度(從頂點(diǎn)到其本身的最短路徑是零路(沒有弧的路),其長度等于零);pj則是從s到j(luò)的最短路徑中j點(diǎn)的前一點(diǎn)。求解從起源點(diǎn)s到點(diǎn)j的最短路徑算法的基本過程如下:圖4.1算法流程圖1)初始化。起源點(diǎn)設(shè)置為:①ds=0,ps為空;②所有其他點(diǎn):di=∞,pi=?;③標(biāo)記起源點(diǎn)s,記k=s,其他所有點(diǎn)設(shè)為未標(biāo)記的。2)檢驗(yàn)從所有已標(biāo)記的點(diǎn)k到其直接連接的未標(biāo)記的點(diǎn)j的距離,并設(shè)置:dj=min[dj,dk+lkj],式中,lkj是從點(diǎn)k到j(luò)的直接連接距離。3)選取下一個點(diǎn)。從所有未標(biāo)記的結(jié)點(diǎn)中,選取dj中最小的一個i:di=min[dj,所有未標(biāo)記的點(diǎn)j],點(diǎn)i就被選為最短路徑中的一點(diǎn),并設(shè)為已標(biāo)記的。4)找到點(diǎn)i的前一點(diǎn)。從已標(biāo)記的點(diǎn)中找到直接連接到點(diǎn)i的點(diǎn)j*,作為前一點(diǎn),設(shè)置:i=j*。5)標(biāo)記點(diǎn)i。如果所有點(diǎn)已標(biāo)記,則算法完全推出,否則,記k=i,轉(zhuǎn)到2)再繼續(xù)。為了實(shí)現(xiàn)Dijkstra算法,在程序中首先引入三個類:classVERTEX//頂點(diǎn)類{publicintid;publicintSearched;//0表示從來沒有搜索過,表示搜索過,但沒有完成,表示搜索完成,該點(diǎn)的最短路徑已經(jīng)找到publicIPointpPoint;publicVERTEXPrev;publicVERTEXNext;publicLinkNeighbor;//一個鏈接關(guān)系,相當(dāng)于線節(jié)點(diǎn)publicdoubleWeight;//權(quán)重,初始時置為無窮大,搜尋最短路徑時置為該點(diǎn)當(dāng)前最短路徑長度publicVERTEXShortPathPre;//在最短路徑上的前一個點(diǎn)publicintLineID;//最短路徑中與前一個點(diǎn)之間的線的IDpublicSearchLinkSLink;//Open或Close表中的鏈接}classLink//點(diǎn)的鄰接關(guān)系{publicVERTEXv1;//每個Link對象的v1都應(yīng)該指向它所附屬的點(diǎn)節(jié)點(diǎn)publicVERTEXv2;//每個Link對象的v2都應(yīng)該指向與它所附屬的點(diǎn)相鄰的那個點(diǎn)節(jié)點(diǎn)publicdoubleweight;//線的權(quán)重publicLinkv1Next;publicLinkv2Next;publicintLineID;}classSearchLink//搜尋路徑時的鄰接關(guān)系,用來放入Open或Close表中{publicVERTEXv;publicSearchLinkPrev;publicSearchLinkNext;}VERTEX類用來存儲點(diǎn)節(jié)點(diǎn),Link類用來存儲鄰接關(guān)系,SearchLink是一個臨時的中間鄰接關(guān)系,在尋徑時替代VERTEX實(shí)例進(jìn)行運(yùn)算,用來維持鄰接多重表。系統(tǒng)的主要功能函數(shù)為:privateVERTEXBuildTopo(IFeatureLayerpFeatLayerP,IFeatureLayerpFeatLayerL,IPointpStartV,IPointpEndV,refintPointCount,refintEdgeCount),主要用來建立拓?fù)潢P(guān)系privatevoidshortpath(),查詢最短路徑的主函數(shù)privatevoidInsertOrder(SearchLinkvIN,refSearchLinkvTO)按權(quán)重的升序插入privatevoidInsert(SearchLinkvIN,refSearchLinkvTO)插入privatevoidDelete(refSearchLinkvOUT,refSearchLinkvFROM)從鏈表中刪除建立拓?fù)潢P(guān)系: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數(shù)組,用來存放點(diǎn)節(jié)點(diǎn),在遍歷點(diǎn)層元素的過程中,根據(jù)點(diǎn)的ID號找到數(shù)組索引號,生成點(diǎn)節(jié)點(diǎn)的實(shí)例(即VERTEX實(shí)例)。建立這一過程的時間消耗與點(diǎn)的數(shù)量n成正比,即時間復(fù)雜度為O(n)。pFeatCsrL=pFeatClsL.Search(null,false);intindexP1=0,indexP2=0;pFeatureL=pFeatCsrL.NextFeature();while(null!=pFeatureL)//遍歷線對象,根據(jù)線的首尾節(jié)點(diǎn)ID,即點(diǎn)的索引,找到點(diǎn),建立鏈接關(guān)系{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值之后,直接可以得到點(diǎn)節(jié)點(diǎn)在數(shù)組中的位置vLink1.v2=RoadNode[indexP2];vLink1.v2Next=RoadNode[indexP2].Neighbor;RoadNode[indexP2].Neighbor=vLink1;pFeatureL=pFeatCsrL.NextFeature();}點(diǎn)的數(shù)組建立完成之后,可以開始遍歷線層元素,每取得一個線元素,則可以得到首尾節(jié)點(diǎn)的ID,根據(jù)首尾節(jié)點(diǎn)ID(即首尾節(jié)點(diǎn)在數(shù)組中的索引)得到首尾節(jié)點(diǎn),分別為首尾節(jié)點(diǎn)建立鄰接關(guān)系vLink1和vLink2,從線元素獲得首尾節(jié)點(diǎn)的過程的時間復(fù)雜度為O(1),而外層while循環(huán)是遍歷線層元素,時間復(fù)雜度為O(n),經(jīng)過這一過程,拓?fù)潢P(guān)系基本建立完成,由于采用數(shù)組存儲VERTEX元素的目的是建立索引,減少建立拓?fù)潢P(guān)系時點(diǎn)的搜索時間,因此,拓?fù)潢P(guān)系建立完成后,為了方便運(yùn)算,也為了盡量減少數(shù)組元素所占用的大塊內(nèi)存區(qū)域,把VERTEX元素從數(shù)組中摘下并建立環(huán)狀鏈表: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;通過這一步操作,環(huán)狀的鄰接多重表建立完成。以上三次遍歷并沒有嵌套關(guān)系,因此整個建立鄰接多重表的時間復(fù)雜度為O(n)。查詢最短路徑查詢最短路徑:intflag=0;intc=0;vWork=vHead.Next;while(c<PointCnt){//根據(jù)點(diǎn)節(jié)點(diǎn)的數(shù)量,循環(huán)設(shè)定點(diǎn)節(jié)點(diǎn)中各字段的初始值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++;}由于鄰接多重表可以重復(fù)使用,因此在一次尋徑后,鏈表中的節(jié)點(diǎn)的一些屬性值可能被改變,因此需要重新初始化節(jié)點(diǎn)的屬性值,如查詢狀態(tài)Searched、最短路徑前導(dǎo)節(jié)點(diǎn)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函數(shù)按升序?qū)⒐?jié)點(diǎn)sTemp插入鏈表sOpen中while(sOpen.Next!=null&&vTail.Next.Searched!=2)//一旦鏈表sOpen變?yōu)榭眨蚪K點(diǎn)的最短路徑已經(jīng)找到,則查詢結(jié)束{sTemp=sOpen.Next;vWork=sTemp.v;vLink=vWork.Neighbor;vWork.Searched=2;Delete(refsTemp,refsOpen);//在sOpen鏈表中找到權(quán)值最小節(jié)點(diǎn)之后,將該節(jié)點(diǎn)從鏈表sOpen中移除,并插入鏈表sClose中,表示該節(jié)點(diǎn)的最短路徑已經(jīng)找到Insert(sTemp,refsClose);while(vLink!=null)//遍歷節(jié)點(diǎn)的各個鄰接點(diǎn){if(vLink.v2.Searched==0)//Searched字段表名該鄰接點(diǎn)的搜索狀態(tài),如果是0,則表示該鄰接點(diǎn)從未被搜索過{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,則表示該鄰接點(diǎn)已經(jīng)搜索過,但還沒有找到最短路徑{if(vLink.v2.Weight>vWork.Weight+vLink.weight)//如果權(quán)值不是最小,則需要重新計算權(quán)值{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用來放置已經(jīng)找到最短路徑的節(jié)點(diǎn),sOpen用來放置已經(jīng)搜索但還沒有找到最短路徑、等待繼續(xù)搜索的節(jié)點(diǎn)。其次需要初始化鄰接多重表,將每一個節(jié)點(diǎn)的Searched字段置為0,表明該節(jié)點(diǎn)還沒有被搜索過,并把節(jié)點(diǎn)權(quán)重置為無窮大(最大值)。這一過程為單循環(huán),時間復(fù)雜度為O(n)。以上是最短路徑算法的主體部分,首先將源節(jié)點(diǎn)的Searched字段置為1,權(quán)重置為0,并插入鏈表sOpen中,而后進(jìn)入循環(huán)搜索最短路徑的過程。外循環(huán)用來遍歷鏈表sClose,直到鏈表sClose變?yōu)榭?,或者最短路徑的終點(diǎn)vTail的最短路徑被找到(Searched字段變?yōu)?)。而內(nèi)循環(huán)則遍歷sOpen中節(jié)點(diǎn)的鄰接關(guān)系,本算法實(shí)現(xiàn)過程中這一循環(huán)與節(jié)點(diǎn)數(shù)或線數(shù)并沒有數(shù)學(xué)關(guān)系,它的循環(huán)次數(shù)通常為2~5之間。在每次循環(huán)中,首先將節(jié)點(diǎn)置于鏈表sClose中,并把Searched值置為2,表明該節(jié)點(diǎn)已經(jīng)找到最短路徑,然后遍歷該節(jié)點(diǎn)的每一個鄰接點(diǎn),首先判斷該鄰接點(diǎn)的搜索情況(Searched字段值),然后進(jìn)行插入或重新插入集合sOpen的操作(InsertOrder),程序中設(shè)置了兩個插入函數(shù)InsertOrder和Insert,InsertOrder函數(shù)專用來向sOpen中插入節(jié)點(diǎn),這一過程需要進(jìn)行排序,因此隨著sOpen鏈表的規(guī)模增大,相應(yīng)的時間消耗也會增大,插入排序過程的時間復(fù)雜度為O((n+1)/2)。為了使計算最短路徑時搜索的節(jié)點(diǎn)范圍盡量縮小,程序中對每次更改Searched字段值之后的節(jié)點(diǎn)都要移出原集合(鏈表),這一方式使單次搜索最短路徑的效率得到很大的提高。但是隨之而來的問題是,單次搜索之后,原來的鄰接多重表被破壞了,在下一次搜索前不得不重新建立鄰接多重表,由于建立鄰接多重表時如果數(shù)據(jù)量比較大,則程序需要頻繁訪問外存儲器,造成了大量的時間開銷。而SearchLink類的引入,使得鄰接多重表可以“一次建立,多次使用”,真正提高算法的效率和實(shí)用性。SearchLink是純指針類,實(shí)例化的時候只占用很少的內(nèi)存開銷,因此這種以空間換時間的方法能夠有效的提高算法執(zhí)行的效率。GPS導(dǎo)航功能衛(wèi)星導(dǎo)航技術(shù)的飛速發(fā)展已逐漸取代了無線電導(dǎo)航、天文導(dǎo)航等傳統(tǒng)導(dǎo)航技術(shù),而成為一種普遍采用的導(dǎo)航定位技術(shù),并在精度、實(shí)時性、全天候等方面取得了長足進(jìn)步?,F(xiàn)不僅應(yīng)用于物理勘探、電離層測量和航天器導(dǎo)航等諸多民用領(lǐng)域,在軍事領(lǐng)域更是取得了廣泛的應(yīng)用——在彈道導(dǎo)彈、野戰(zhàn)指揮系統(tǒng)、精確彈道測量以及軍用地圖快速測繪等領(lǐng)域均大量采用了衛(wèi)星導(dǎo)航定位技術(shù)。有鑒于衛(wèi)星導(dǎo)航技術(shù)在民用和軍事領(lǐng)域的重要意義,使其得到了許多國家的關(guān)注。我國也于2000年10月31日和12月21日成功發(fā)射了第一顆和第二顆導(dǎo)航定位試驗(yàn)衛(wèi)星并建立了我國第一代衛(wèi)星導(dǎo)航定位系統(tǒng)"北斗導(dǎo)航系統(tǒng)",但由于起步晚也沒有得到廣泛應(yīng)用。目前在我國應(yīng)用最多的還是美國的GPS系統(tǒng)。GPS接收機(jī)可接收到準(zhǔn)確至納秒級的時間信息;用于預(yù)報未來幾個月內(nèi)衛(wèi)星所處概略位置的預(yù)報星歷;用于計算定位時所需衛(wèi)星坐標(biāo)的廣播星歷,精度為幾米至幾十米(各個衛(wèi)星不同,隨時變化);以及GPS系統(tǒng)信息,如衛(wèi)星狀況等。GPS接收機(jī)對碼的量測就可得到衛(wèi)星到接收機(jī)的距離,由于含有接收機(jī)衛(wèi)星鐘的誤差及大氣傳播誤差,故稱為偽距。對0A碼測得的偽距稱為UA碼偽距,精度約為20米左右,對P碼測得的偽距稱為P碼偽距,精度約為2米左右。GPS接收機(jī)對收到的衛(wèi)星信號,進(jìn)行解碼或采用其它技術(shù),將調(diào)制在載波上的信息去掉后,就可以恢復(fù)載波。嚴(yán)格而言,載波相位應(yīng)被稱為載波拍頻相位,它是收到的受多普勒頻移影響的衛(wèi)星信號載波相位與接收機(jī)本機(jī)振蕩產(chǎn)生信號相位之差。一般在接收機(jī)鐘確定的歷元時刻量測,保持對衛(wèi)星信號的跟蹤,就可記錄下相位的變化值,但開始觀測時的接收機(jī)和衛(wèi)星振蕩器的相位初值是不知道的,起始?xì)v元的相位整數(shù)也是不知道的,即整周模糊度,只能在數(shù)據(jù)處理中作為參數(shù)解算。相位觀測值的精度高至毫米,但前提是解出整周模糊度,因此只有在相對定位、并有一段連續(xù)觀測值時才能使用相位觀測值,而要達(dá)到優(yōu)于米級的定位精度也只能采用相位觀測值。按定位方式,GPS定位分為單點(diǎn)定位和相對定位(差分定位)。單點(diǎn)定位就是根據(jù)一臺接收機(jī)的觀測數(shù)據(jù)來確定接收機(jī)位置的方式,它只能采用偽距觀測量,可用于車船等的概略導(dǎo)航定位。相對定位(差分定位)是根據(jù)兩臺以上接收機(jī)的觀測數(shù)據(jù)來確定觀測點(diǎn)之間的相對位置的方法,它既可采用偽距觀測量也可采用相位觀測量,大地測量或工程測量均應(yīng)采用相位觀測值進(jìn)行相對定位。在GPS觀測量中包含了衛(wèi)星和接收機(jī)的鐘差、大氣傳播延遲、多路徑效應(yīng)等誤差,在定位計算時還要受到衛(wèi)星廣播星歷誤差的影響,在進(jìn)行相對定位時大部分公共誤差被抵消或削弱,因此定位精度將大大提高,雙頻接收機(jī)可以根據(jù)兩個頻率的觀測量抵消大氣中電離層誤差的主要部分,在精度要求高,接收機(jī)間距離較遠(yuǎn)時(大氣有明顯差別),應(yīng)選用雙頻接收機(jī)。在定位觀測時,若接收機(jī)相對于地球表面運(yùn)動,則稱為動態(tài)定位,如用于車船等概略導(dǎo)航定位的精度為30——100米的偽距單點(diǎn)定位,或用于城市車輛導(dǎo)航定位的米級精度的偽距差分定位,或用于測量放樣等的厘米級的相位差分定位(RTK),實(shí)時差分定位需要數(shù)據(jù)鏈將兩個或多個站的觀測數(shù)據(jù)實(shí)時傳輸?shù)揭黄鹩嬎恪T诙ㄎ挥^測時,若接收機(jī)相對于地球表面靜止,則稱為靜態(tài)定位,在進(jìn)行控制網(wǎng)觀測時,一般均采用這種方式由幾臺接收機(jī)同時觀測,它能最太限度地發(fā)揮GPS的定位精度,專用于這種目的的接收機(jī)被稱為大地型接收機(jī),是接收機(jī)中性能最好的一類。目前,GPS已經(jīng)能夠達(dá)到地殼形變觀測的精度要求,IGS的常年觀測臺站已經(jīng)能構(gòu)成毫米級的全球坐標(biāo)框架。下面就針對當(dāng)前比較普及的GPS系統(tǒng),對其衛(wèi)星定位信息的接收及其定位參數(shù)提取的實(shí)現(xiàn)方法予以介紹。定位信息的接收通常GPS定位信息接收系統(tǒng)主要由GPS接收天線、變頻器、信號通道、微處理器、存儲器以及電源等部分組成。由于GPS定位信息內(nèi)容較少,因此多用RS-232串口將定位信息(NEMA0183語句)從GPS接收機(jī)傳送到計算機(jī)中進(jìn)行信息提取處理。初始化并打開串口:對串口初始化通常要完成以下幾個設(shè)置:設(shè)定通信端口號,即CommPort屬性;設(shè)定通信協(xié)議,即HandShaking屬性;設(shè)定傳輸速率等參數(shù),即Settings屬性;打開通信端口,即將PortOpen屬性設(shè)為True。if(m_Comm.GetPortOpen())m_Comm.SetPortOpen(FALSE);m_Comm.SetCommPort(1);//選擇COM1m_Comm.SetInBufferSize(1024);//設(shè)置輸入緩沖區(qū)的大小if(!m_Comm.GetPortOpen())m_Comm.SetPortOpen(TRUE);//打開串口elseAfxMessageBox("cannotopenserialport");m_Comm.SetSettings("9600,n,8,1");//波特率9600,無校驗(yàn),8個數(shù)據(jù)位,1停止位m_Comm.SetInputMode(1);//1:表示以二進(jìn)制方式檢取數(shù)據(jù)m_Comm.SetRThreshold(1);//1:表示有一個字符引發(fā)一個事件從串口讀取數(shù)據(jù)有多種方法,在此直接使用Win32API函數(shù)對其進(jìn)行編程處理。在Windows下不允許直接對硬件端口進(jìn)行控制操作,所有的端口均被視為“文件”,因此在對串口進(jìn)行偵聽之前需要通過打開文件來打開串口,并對其進(jìn)行相關(guān)參數(shù)配置: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/*寫緩沖*/);//初始化通訊設(shè)備參數(shù)//清除緩沖信息PurgeComm(m_hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);//對異步I/O進(jìn)行設(shè)置CommTimeOuts.ReadIntervalTimeout=MAXDWORD;//接收兩連續(xù)字節(jié)的最大時間間隔CommTimeOuts.ReadTotalTimeoutMultiplier=0;//接收每字節(jié)的平均允許時間CommTimeOuts.ReadTotalTimeoutConstant=0;//接收時間常數(shù)SetCommTimeouts(m_hCom,&CommTimeOuts);//獲取并設(shè)置串口GetCommState(m_hCom,&dcb);dcb.BaudRate=CBR_4800;dcb.ByteSize=8;dcb.Parity=ODDPARITY;dcb.StopBits=ONESTOPBIT;SetCommState(m_hCom,&dcb);在成功打開并設(shè)置通訊口后,可采取輪詢串口和事件觸發(fā)兩種方式對數(shù)據(jù)進(jìn)行接收處理,本文在此采取效率比較高的事件觸發(fā)方式進(jìn)行接收處理,通過等待EV_RXCHAR事件的發(fā)生來啟動ReadFile函數(shù)完成對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);}提取定位數(shù)據(jù)GPS接收機(jī)只要處于工作狀態(tài)就會源源不斷地把接收并計算出的GPS導(dǎo)航定位信息通過串口傳送到計算機(jī)中。前面的代碼只負(fù)責(zé)從串口接收數(shù)據(jù)并將其放置于緩存,在沒有進(jìn)一步處理之前緩存中是一長串字節(jié)流,這些信息在沒有經(jīng)過分類提取之前是無法加以利用的。因此,必須通過程序?qū)⒏鱾€字段的信息從緩存字節(jié)流中提取出來,將其轉(zhuǎn)化成有實(shí)際意義的,可供高層決策使用的定位信息數(shù)據(jù)。同其他通訊協(xié)議類似,對GPS進(jìn)行信息提取必須首先明確其幀結(jié)構(gòu),然后才能根據(jù)其結(jié)構(gòu)完成對各定位信息的提取。對于本文所使用的GARMINGPS天線板,其發(fā)送到計算機(jī)的數(shù)據(jù)主要由幀頭、幀尾和幀內(nèi)數(shù)據(jù)組成,根據(jù)數(shù)據(jù)幀的不同,幀頭也不相同,主要有"$GPGGA"、"$GPGSA"、"$GPGSV"以及"$GPRMC"等。這些幀頭標(biāo)識了后續(xù)幀內(nèi)數(shù)據(jù)的組成結(jié)構(gòu),各幀均以回車符和換行符作為幀尾標(biāo)識一幀的結(jié)束。對于通常的情況,我們所關(guān)心的定位數(shù)據(jù)如經(jīng)緯度、速度、時間等均可以從"$GPRMC"幀中獲取得到,該幀的結(jié)構(gòu)及各字段釋義如下:$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>*hh<1>當(dāng)前位置的格林尼治時間,格式為hhmmss<2>狀態(tài),A為有效位置,V為非有效接收警告,即當(dāng)前天線視野上方的衛(wèi)星個數(shù)少于3顆。<3>緯度,格式為ddmm.mmmm<4>標(biāo)明南北半球,N為北半球、S為南半球<5>徑度,格式為dddmm.mmmm<6>標(biāo)明東西半球,E為東半球、W為西半球<7>地面上的速度,范圍為0.0到999.9<8>方位角,范圍為000.0到359.9度<9>日期,格式為ddmmyy<10>地磁變化,從000.0到180.0度<11>地磁變化方向,為E或W至于其他幾種幀格式,除了特殊用途外,平時并不常用,雖然接收機(jī)也在源源不斷地向主機(jī)發(fā)送各種數(shù)據(jù)幀,但在處理時一般先通過對幀頭的判斷而只對"$GPRMC"幀進(jìn)行數(shù)據(jù)的提取處理。如果情況特殊,需要從其他幀獲取數(shù)據(jù),處理方法與之也是完全類似的。由于幀內(nèi)各數(shù)據(jù)段由逗號分割,因此在處理緩存數(shù)據(jù)時一般是通過搜尋ASCII碼"$"來判斷是否是幀頭,在對幀頭的類別進(jìn)行識別后再通過對所經(jīng)歷逗號個數(shù)的計數(shù)來判斷出當(dāng)前正在處理的是哪一種定位導(dǎo)航參數(shù),并作出相應(yīng)的處理。下面就是對緩存Data中的數(shù)據(jù)進(jìn)行解幀處理的主要代碼,本文在此只關(guān)心時間(日期和時間)和地理坐標(biāo)(經(jīng)、緯度):for(inti=0;i<DATALENGTH;i++){if(Data[i]=='$')//幀頭,SectionID為逗號計數(shù)器SectionID=0;if(Data[i]==10){//幀尾}if(Data[i]==',')file://逗號計數(shù)SectionID++;else{switch(SectionID){case1://提取出時間m_sTime+=Data[i];break;case2://判斷數(shù)據(jù)是否可信(當(dāng)GPS天線能接收到有3顆GPS衛(wèi)星時為A,可信)if(Data[i]=='A')GPSParam[m_nNumber].m_bValid=true;break;case3:file://提取出緯度m_sPositionY+=Data[i];break;case5:file://提取出經(jīng)度m_sPositionX+=Data[i];break;case9:file://提取出日期m_sDate+=Data[i];break;default:break;}}}現(xiàn)在已將所需信息提取到內(nèi)存,即時間、日期以及經(jīng)緯度分別保存在CString型變量m_sTime、m_Data、m_sPositionY和m_sPositionX中。在實(shí)際應(yīng)用中往往要根據(jù)需要對其做進(jìn)一步的運(yùn)算處理,比如從GPS接收機(jī)中獲得的時間信息為格林尼治時間,因此需要在獲取時間上加8小時才為我國標(biāo)準(zhǔn)時間。而且GPS使用的WGS-84坐標(biāo)系也與我國采用的坐標(biāo)系不同,有時也要對此加以變換。而這些變換運(yùn)算必須通過數(shù)值運(yùn)算完成,因此需要將前面獲取的字符型變量轉(zhuǎn)化為數(shù)值型變量,這部分工作可放在檢測到幀尾完成:::strcpy(buf,m_sTime);str.Format("%c%c",buf[0],buf[1]);GPSParam[m_nNumber].m_nHour=(atoi(str)+8)%24;//提取出小時并轉(zhuǎn)化為24小時制北京時間file://buf第2、3字節(jié)為分鐘,4、5字節(jié)為秒,提取方法同上……::strcpy(buf,m_sDate);str.Format("%c%c",buf[0],buf[1]);//提取出月份//buf第2、3字節(jié)為天,4、5字節(jié)為年,提取方法同上……::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)//經(jīng)度超過90度(如東經(jīng)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);//提取出經(jīng)度(單位為分)}if(m_sPositionX.GetLength()==9)//經(jīng)度未超過90度(如東經(jīng)89度){//處理方法同上,只是buf的第0、1字節(jié)為度數(shù),2~9為分?jǐn)?shù)。}通過上面的設(shè)計方法可以將GPS定位導(dǎo)航信息從GPS接收機(jī)完整接收??偨Y(jié)可以看出,MapX開發(fā)平臺可以提供地理信息應(yīng)用系統(tǒng)所需要的各主要方面功能,并具有開發(fā)方式靈活,接口簡便的特點(diǎn),不失為開發(fā)地理信息應(yīng)用系統(tǒng)的理想平臺。建立一個GIS應(yīng)用系統(tǒng)是比較復(fù)雜的,并且必須根據(jù)特定的要求來實(shí)現(xiàn)不同的功能。由于筆者能力有限,本文采用面向?qū)ο蟪绦蛟O(shè)計語言VC++,集成MapX、MSComm控件,實(shí)現(xiàn)了一個小型的GPS導(dǎo)航信息系統(tǒng)應(yīng)用軟件,旨在為用戶提供開發(fā)具有典型GIS功能的應(yīng)用軟件接口程序的基本方法。在實(shí)際應(yīng)用中,可以在此基礎(chǔ)上進(jìn)行完善和擴(kuò)充,來滿足不同的需求。參考文獻(xiàn)1.賈國憲,劉新江.VC環(huán)境下基于GIS的GPS導(dǎo)航系統(tǒng)的開發(fā)[J],北京測繪,2003年,第二期:41,51,61,712.顏輝武,吳小芳,祝國瑞.VC++環(huán)境下基于MapX控件的GIS應(yīng)用軟件的開發(fā)[J],昆明理工大學(xué)學(xué)報,2001年12月,第26卷第6期:12-173.岳新利,張永進(jìn),孫毅.基于MapX平臺的地理信息系統(tǒng)開發(fā)技術(shù)的研究[J],現(xiàn)代電子技術(shù),2003年,第8期:75-774.車建仁.VC++環(huán)境下基于MapX開發(fā)的旅游信息系統(tǒng)[J],水利科技與經(jīng)濟(jì),2004年12月,第10卷第6期:382-3845.馮永玉,王寶山,路天偉.VC++環(huán)境下基于MapX控件的GIS應(yīng)用軟件基本功能的開發(fā)[J],焦作工學(xué)院學(xué)報,2004年11月,第23卷第6期:451-4556.侯江麗.VC環(huán)境下基于MapX控件的地理信息系統(tǒng)的開[J]發(fā),邢臺職業(yè)技術(shù)學(xué)院學(xué)報,2005年10月,第22卷第5期:63-657.韓平陽,羅五明.基于MapX的地理信息系統(tǒng)的VC開發(fā)[J],交通與計算機(jī),2004年,第22卷第5期:71-748.王德文,趙文清.基于MapX的地理信息系統(tǒng)的設(shè)計與實(shí)現(xiàn)[J],微機(jī)發(fā)展,2003年5月,第13卷第5期:59-619.王世東,陳魁奎.基于MapX的地理信息系統(tǒng)應(yīng)用軟件的開發(fā)[J],電腦學(xué)習(xí),2006年8月,第4期:2-310.王豐,高光金.VisualC++6.0程序設(shè)計教程與實(shí)訓(xùn)[M],北京:北京大學(xué)出版社,2005年9月11.姜曉銘.VisualC++6.0程序設(shè)計應(yīng)用短期培訓(xùn)教程[M],北京:北京工業(yè)大學(xué)出版社,2000年5月12.吳信才.地理信息系統(tǒng)原理與方法[M],北京:電子工業(yè)出版社,2002年,P218-22313.龔健雅.地
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度高性能耐磨混凝土地面施工合同
- 2025年度外企在華工作許可及聘用合同
- 二零二五年度電影特效化妝與拍攝合同
- 2025年度鏟車租賃安全培訓(xùn)及事故處理合同
- 護(hù)士護(hù)理壓瘡理論考試試題
- 安全生產(chǎn)管理預(yù)案
- 安全應(yīng)知應(yīng)會知識培訓(xùn)
- 干部選拔任用培訓(xùn)
- 2025有關(guān)宅基地的買賣合同
- 2025道路旅游運(yùn)輸合同范本
- 人教版2024-2025學(xué)年七年級數(shù)學(xué)上冊計算題專項(xiàng)訓(xùn)專題09運(yùn)用運(yùn)算律簡便運(yùn)算(計算題專項(xiàng)訓(xùn)練)(學(xué)生版+解析)
- GB 26134-2024乘用車頂部抗壓強(qiáng)度
- 2024年高中生物新教材同步必修第二冊學(xué)習(xí)筆記第3章 本章知識網(wǎng)絡(luò)
- (正式版)YS∕T 5040-2024 有色金屬礦山工程項(xiàng)目可行性研究報告編制標(biāo)準(zhǔn)
- 2024版軟包合同模板
- GB/T 36548-2024電化學(xué)儲能電站接入電網(wǎng)測試規(guī)程
- NB-T+31010-2019陸上風(fēng)電場工程概算定額
- JT-T-617.7-2018危險貨物道路運(yùn)輸規(guī)則第7部分:運(yùn)輸條件及作業(yè)要求
- 2024土方運(yùn)輸居間合同范本
- 2023-2024學(xué)年成都市錦江區(qū)中考英語二診試題(含答案)
- 市場監(jiān)管知識問答
評論
0/150
提交評論