版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
學科分類號0812本科學生畢業(yè)論文〔設計〕基于VC的根本矢量圖形系統(tǒng)的開發(fā)與實現(xiàn)DevelopmentandImplementationofBasicVectorGraphicsSystemUnderVC學號院〔系〕計算機與通信工程系計算機科學與技術2007級指導教師目錄第一章緒論11.1選題背景及意義11.2國內外研究現(xiàn)狀11.3論文內容及結構安排21.4本章小結3第二章矢量圖形系統(tǒng)的分析與設計42.1開發(fā)思路42.2開發(fā)模式42.3功能分析52.4功能模塊設計62.5本章小結6第三章矢量圖形系統(tǒng)的坐標轉換73.1Windows環(huán)境下的坐標系73.1.1設備坐標73.1.2邏輯坐標73.2設備坐標與邏輯坐標83.2.1設備坐標與邏輯坐標的關系83.2.1設備坐標及邏輯坐標的轉換83.3窗口與視口93.4本章小結9第四章實現(xiàn)矢量圖形系統(tǒng)的文檔和視圖104.1矢量圖形系統(tǒng)的圖形元素類104.1.1圖形元素基類104.1.2直線類104.1.3連續(xù)直線或封閉多邊形類104.1.4圓類104.1.5圓弧類114.1.6標注文本類114.1.7圖形參數(shù)類114.2矢量圖形系統(tǒng)的文檔114.2.1面向對象的文檔管理機制114.2.2創(chuàng)立圖形元素對象指針114.2.3矢量圖形系統(tǒng)的文檔124.2.4實現(xiàn)文檔的管理功能124.3矢量圖形系統(tǒng)的視圖134.3.1建立坐標系134.3.2實現(xiàn)各類圖形元素的繪制功能144.3.3實現(xiàn)視圖的繪制144.4鼠標交互繪圖154.4.1要解決的主要問題154.4.2交互繪制各類圖形元素154.5本章小結17第五章矢量圖形系統(tǒng)的操作功能185.1圖形操作菜單管理185.1.1增加菜單資源185.1.2添加消息處理函數(shù)185.2圖形操作的具體實現(xiàn)195.2.1圖形重畫195.2.2圖形放大和移動205.2.3重畫上屏和重畫首屏225.2.4顯示全圖245.2.5圖形重畫速度的提升255.3圖形的點選與撤銷275.3.1鼠標點選圖形元素275.3.2各種圖形元素的點選判斷函數(shù)285.3.3實現(xiàn)點選圖形元素功能295.3.4選中圖形元素的特殊顯示315.3.5撤銷選中的圖形元素325.4圖形元素的刪除325.5本章小結35第六章總結與展望366.1總結366.2展望36參考文獻37致謝38基于VC的根本矢量圖形系統(tǒng)的開發(fā)與實現(xiàn)摘要矢量圖形系統(tǒng)作為GIS系統(tǒng)組成的一局部,隨著GIS系統(tǒng)用戶的不同,對于矢量圖形系統(tǒng)的要求也不同,現(xiàn)有GIS矢量圖形繪制系統(tǒng)功能全面,但是針對性差,所以有針對性的從底層自主開發(fā)符合自己需要的矢量圖形系統(tǒng)是十分必要的。論文利用面向對象的程序設計和C++類的組織方法,在VC6.0下實現(xiàn)了一個根本的矢量圖形系統(tǒng),能夠實現(xiàn)鼠標繪制直線、圓、圓弧、圓形區(qū)域等功能。通過對矢量圖形系統(tǒng)坐標系的建立及其與Windows坐標系之間的轉換關系的探討,實現(xiàn)了圖形的無級縮放、漫游、全圖顯示等操作功能。通過對點選圖形元素的原理的研究,實現(xiàn)了圖形的選中、圖形刪除、放棄選中等功能。此外,就矢量圖形的顯示速度等問題進行了探討,并提出了加快圖形顯示速度的根本方法:在顯示一個圖形元素前,對這個圖形元素進行判斷,判斷這個圖形元素是否在視圖屏幕中,如果這個圖形元素不在當前的視圖屏幕中,就不用對這個圖形元素進行繪制,以此節(jié)省繪制時間。 系統(tǒng)具有比擬完善的圖形繪制功能,可應用于城市信息管理系統(tǒng)中?!娟P鍵詞】矢量圖形;鼠標繪圖;無極縮放DevelopmentandImplementationofBasicVectorGraphicsSystemUnderVCAbstractVectorgraphicssystemasacomponentpartoftheGISsystem,GISsystemuserswithdifferentrequirementsforthevectorgraphicssystemisdifferent,andtheexistingfull-featuredGISgraphicsrenderingsystem,buttargetedpoor,ittargetedindependentfromtheunderlyingdevelopmentinlinewiththeirvectorgraphicssystemneedsisessential.Byusingobject-orientedprogrammingandC++classmethodoforganization,theorganizationimplementsabasicvectorgraphicssystemthatenablesthemousetodrawastraightline,circle,arc,circleandsoon.VectorgraphicssystemthroughtheestablishmentofthecoordinatesystemanditsWindowscoordinatesystemconversionrelationshipbetweenstudyandrealizethesteplesszoomgraphics,roaming,fullmapdisplayandotheroperationsfunctions.Clickthroughontheprinciplesofgraphicelementstoachievetheselectedgraphic,graphics,remove,abandonselectedfunctions.Inaddition,vectorgraphicsdisplayspeedoftheotherissuesdiscussed,Andproposedtoacceleratethespeedofthebasicmethodofgraphicaldisplay,whichisagraphicalelementinthedisplaybeforethejudgeonthegraphicelementstodeterminewhetherthegraphicelementsintheviewscreen,ifthegraphicelementisnotthecurrentviewofthescreen,theydonotdrawonthegraphicelementsinordertosaverenderingtime.Systemhasarelativelycompletegraphicsrenderingcapabilities,mainlyusedforurbaninformationmanagementsystem.【Keywords】vectorgraphic;Mousedrawing;PromiseZoom第一章緒論1.1選題背景及意義一個根本的GIS系統(tǒng)包括管理空間坐標數(shù)據(jù)的矢量圖形系統(tǒng)和管理屬性信息的數(shù)據(jù)庫管理系統(tǒng),以及實現(xiàn)矢量圖形系統(tǒng)與數(shù)據(jù)庫管理系統(tǒng)雙向連接的連接系統(tǒng)三個局部1]。 矢量圖形系統(tǒng)面向地理對象,是地理實體抽象和完整表達的主要方式,因而是GIS系統(tǒng)中重要的組成局部,也是開發(fā)一個GIS系統(tǒng)的重點所在2]。 一些專業(yè)的商品化GIS軟件都提供了比擬完善的圖形系統(tǒng)的功能,利用這些專業(yè)的工具軟件進行開發(fā),雖然開發(fā)難度不高,簡單易學,但也普遍存在著一些弊端3]:⑴不易擴展。專業(yè)的GIS工具軟件提供的接口復雜,難于修改,不能夠很好的擴展;⑵軟硬件要求高。專業(yè)的GIS軟件開發(fā)工具通常比擬龐大,對系統(tǒng)軟硬件的要求高;⑶軟件不易升級。利用GIS專業(yè)軟件工具所進行的圖形系統(tǒng)的開發(fā),實質上只是在這些專業(yè)軟件根底上做一些簡單的應用開發(fā),開發(fā)完成的產品同樣需要這些專業(yè)軟件工具的支撐,因此,軟件的升級就要受到制約;⑷代價高。商品化的GIS軟件要面向最廣的用戶,所以軟件和系統(tǒng)還是作為一個整體而存在,開發(fā)者必須要購置整個的GIS軟件,代價較高,而且購置的平臺中真正需要的功能可能只是很少的一局部,造成了軟件資源的浪費。 此外,在實際的應用中,我們對系統(tǒng)的需求往往主要集中在某些特定功能上,如本論文結合信息平臺的需求,所需要的功能主要是圖形的繪制、顯示、查詢、縮放等。然而,商品化的GIS軟件致力于提供解決方案,它提供了全面的GIS功能,因此,面向實際應用的針對性必然要差一些。 綜合以上分析,對于有特定需求的用戶來說,有針對性的從底層自主開發(fā)符合自己需要的矢量圖形系統(tǒng)是十分必要的。1.2國內外研究現(xiàn)狀 矢量圖形系統(tǒng)作為GIS系統(tǒng)最重要的組成局部,應用領域也不斷擴大,已進入了普通管理信息系統(tǒng)(MIS)[4],GIS矢量圖形系統(tǒng)與普通管理信息系統(tǒng)相結合,克服了MIS系統(tǒng)的局限性,大大提高了系統(tǒng)的直觀性和可操作性,同時提高了MIS系統(tǒng)所不能解決的如空間信息統(tǒng)計、屬性信息計算等功能。 專業(yè)的GIS軟件大都提供了較為完善的矢量圖形的開發(fā)功能。借助這些專業(yè)的開發(fā)工具軟件,出現(xiàn)了大量GIS系統(tǒng)的研究和開發(fā)成果。 文獻[5]提出了一種小型GIS矢量圖形系統(tǒng)的設計方案,利用GIS、面向對象及數(shù)據(jù)庫等技術,以VC++6.0開發(fā)平臺,底層開發(fā)實現(xiàn)了一個具有圖形編輯功能,且有與第三方GIS軟件數(shù)據(jù)接口功能的GIS矢量圖形系統(tǒng),并已在生產中得到了應用。 文獻[6]提出了一種基于MFC的動態(tài)交互的矢量圖形系統(tǒng)的快速開發(fā)方法,設計實現(xiàn)的矢量圖形系統(tǒng)已成功應用于測繪數(shù)據(jù)處理等專門問題的解決中。 文獻[7]同樣利用VC++6.0,基于面向對象技術的軟件工程思想開發(fā)實現(xiàn)了一個用于煤礦平安分析可視化研究的矢量圖形系統(tǒng)。 綜上所述,從底層開發(fā)實現(xiàn)的GIS矢量圖形系統(tǒng)以其較好的靈活性和可操作性已經在很多領域得到了推廣應用。1.3論文內容及結構安排本文主要研究如何基于VC++從底層開發(fā)實現(xiàn)一個能夠滿足信息平臺需求的矢量圖形系統(tǒng)。主要對圖形元素的組織和存儲、圖形對象的繪制、圖形的操作、圖形與屬性的雙向查詢、圖層管理等方面進行研究,具體包括以下幾個方面的工作:⑴采用面向對象的方法完成矢量圖形數(shù)據(jù)對象類的組織和存儲,實現(xiàn)包括圓形,直線,點,標注文本等圖形元素的繪制;⑵能夠實現(xiàn)鼠標交互繪圖的功能;⑶研究矢量圖形系統(tǒng)坐標系的建立及坐標轉換關系,并在此根底上實現(xiàn)圖形的無級縮放、移動、全圖顯示等操作功能;⑷能夠對圖形進行選中、刪除等功能。論文的結構安排: 第一章是緒論,主要對課題的研究背景、矢量圖形系統(tǒng)開發(fā)研究的現(xiàn)狀進行了探討,并簡要介紹了本文的研究內容; 第二章是對本系統(tǒng)的分析與設計,主要介紹系統(tǒng)的開發(fā)思路、開發(fā)模式的選擇、系統(tǒng)功能模塊設計等內容; 第三章是矢量圖形系統(tǒng)坐標系的設計。介紹和分析了Windows環(huán)境下的邏輯坐標系和設備坐標系,在此根底上建立了系統(tǒng)的實際坐標系以及三種坐標之間的轉換關系; 第四章是實現(xiàn)圖形系統(tǒng)的文檔和視圖,這一章主要是真對在系統(tǒng)實現(xiàn)過程中所用到的一些文檔與視圖的管理; 第五章矢量圖形系統(tǒng)的操作功能,這一章是論文的重點,主要對系統(tǒng)各功能模塊的實現(xiàn)技術、實現(xiàn)過程進行了詳細的研究和闡述; 第六章主要是對全文進行的一個總結。1.4本章小結 本章主要是對GIS系統(tǒng)的研究背景、研究現(xiàn)狀進行了簡單的描述,從而表達出選題的意義及其目的,在確定了系統(tǒng)需要的功能后,對整個系統(tǒng)的功能進行了簡單的描述,并對系統(tǒng)預期實現(xiàn)的功能進行了分析,最后列出了整篇論文的根本構架。第二章矢量圖形系統(tǒng)的分析與設計2.1開發(fā)思路 一個根本的矢量圖形系統(tǒng)包含兩個局部:矢量圖形元素以及對圖形元素的各種操作?;谶@兩個組成局部,本文將從以下兩方面組織確立系統(tǒng)的開發(fā)思路。 開發(fā)工具的選擇:從底層開發(fā)GIS矢量圖形系統(tǒng)的首要問題是要選擇適宜的可視化編程語言9]。適用的有Delphi,VC++等。目前比擬流行的GIS專業(yè)軟件平臺多是用C++開發(fā)完成的。在Windows下VC++是一個很好的底層開發(fā)工具。VC++通過微軟根底類MFC〔MicrosoftFoundationClass〕把WIN32API封裝起來,使得在MFC根底上用C++編寫Windows平臺下面的程序更為方便。此外,VC++的MFC提供了很多與圖形操作有關的類,使得VC++結合GDI對象可以簡單的實現(xiàn)圖形圖像的顯示。因此使用VC++開發(fā)圖形系統(tǒng),具有開發(fā)靈活、功能強等特點。最重要的一點是MFC在簡化編程的同時,并沒有限制對系統(tǒng)的控制,設計出的程序也穩(wěn)定、高效。所以兩者的結合有利于矢量圖形系統(tǒng)的開發(fā)。因此,系統(tǒng)選用MicrosoftVisualC++6.0〔簡稱VC6.0〕作為開發(fā)平臺,VC++作為程序設計語言。2.2開發(fā)模式 當前的軟件開發(fā)模式有面向過程和面向對象兩種。面向過程的方法 面向過程的方法也就是傳統(tǒng)的結構化方法10],包括結構化系統(tǒng)分析、系統(tǒng)設計及程序設計方法,是以系統(tǒng)中的數(shù)據(jù)及對數(shù)據(jù)進行處理的過程為研究中心的。面向過程的方法構建一個系統(tǒng)的流程是:從需求出發(fā),制定方案,編寫代碼,測試代碼,維護系統(tǒng)。面向對象的方法 面向對象的方法〔Object-OrientedParadigm,簡稱O-O方法〕是目前軟件開發(fā)的主流方法11]。面向對象的方法以對象為中心,對象是屬性〔數(shù)據(jù)〕和操作〔處理數(shù)據(jù)的函數(shù)〕的封裝體。面向對象方法有如下三大特性12]:⑴封裝性:封裝性(Encapsulation)是指對象將其屬性的實現(xiàn)細節(jié)隱藏在內部,外界只有通過函數(shù)才能對其訪問和利用。因此保證了面向對象軟件的可構造性和易維護性;⑵繼承性:繼承性(Inheritance)是指下層對象能夠擁有上層對象的特征〔屬性和操作〕的能力。繼承性是面向對象方法中最重要的機制,可以通過繼承機制擴充和完善舊的程序設計以適應新的需求;⑶多態(tài)性:多態(tài)性(Polymorphism)是指發(fā)出同樣的消息被不同類型的對象接收時導致完全不同的行為。這里所說的消息主要是指對對象函數(shù)的調用,而不同的行為是指不同的實現(xiàn)。多態(tài)性表達了對象行為的擴充能力,使程序的動態(tài)鏈接方便易行。面向對象方法的這三大特性是相互關聯(lián)的,封裝性是根底,繼承性是關鍵,多態(tài)性是補充,而多態(tài)性又必須存在于繼承的環(huán)境中。兩種開發(fā)模式的比擬 應用于不同領域的GIS系統(tǒng),對矢量圖形系統(tǒng)功能的要求是有差異的12]。用戶的需求也可能是逐步提出的,如果考慮系統(tǒng)的所有功能,那么在構建時會很困難。而面向過程的方法在做需求分析、制定方案階段都需要用戶的參與,開發(fā)人員對這些需求的理解也會存在差異,這就導致開發(fā)人員將不斷地修改這些面向過程的代碼,陷入代碼的泥潭。面向對象技術很好地解決了這種問題。在需求分析階段,如果用戶對需求不十分清楚,正如在此系統(tǒng)中,那么開發(fā)人員無須考慮將要構建的矢量圖形系統(tǒng)會應用于哪一類實際應用,可以先從一般的需求出發(fā),構造實現(xiàn)這種需求的對象,把系統(tǒng)看做是一組相對獨立的對象的集合,規(guī)定其操作13],由多個對象抽象為類,由類構造派生類,由這些類派生出實例,逐步構造系統(tǒng)。由于對象的數(shù)據(jù)與其操作〔處理數(shù)據(jù)的函數(shù)〕是封裝的,并通過函數(shù)與外部進行聯(lián)系,這是一種自下向上的開發(fā)方法,在對某個對象修改時只涉及該對象、該類的細節(jié),不影響整個系統(tǒng)。這使建立一個根本圖形系統(tǒng)來滿足不同圖形應用系統(tǒng)開發(fā)的需要具有了可行性。將面向對象技術應用于矢量圖形系統(tǒng)的設計當中,可以根據(jù)應用系統(tǒng)本身的需求來實現(xiàn)功能,使軟件易于擴充。面向對象的方法在GIS中的應用,己經成為GIS開展的方向。這是因為空間信息較之傳統(tǒng)數(shù)據(jù)庫處理的一維信息更為復雜、繁瑣,面向對象的方法為描述復雜的空間信息提供了一條直觀、結構清晰、組織有序的方法。 基于以上分析,確定本系統(tǒng)的開發(fā)思路是:在Windows下選用VC6.0作為開發(fā)平臺,VC++作為程序設計語言,采用面向對象的軟件開發(fā)模式,從底層開發(fā)獨立于其他任何專業(yè)GIS開發(fā)平臺的軟件產品。2.3功能分析 一個根本的GIS矢量圖形系統(tǒng),一般應具備如下根本功能10]:⑴比擬完善的圖形元素。具備處理點、線、面等根本圖形元素的能力;⑵比擬完善的圖形繪制功能,能夠繪制圖形系統(tǒng)的各種圖形元素;⑶比擬完善的圖形操作功能。具備圖形的放縮、漫游、全屏等功能;⑷圖層管理功能。根據(jù)圖形元素的屬性不同,分圖層進行管理;⑸具有顏色、線型、線寬、填充色等參數(shù)的設置功能;⑹圖形對象的各種選取功能。根據(jù)需要選定圖形對象,如點選、框選等。 但不同的行業(yè)對GIS矢量圖形系統(tǒng)的需求是有差異的[14]。建立一個城市信息管理系統(tǒng),要求矢量圖形系統(tǒng)具有豐富的圖形元素、豐富的線型、巨大的存儲容量、完整的輸入和輸出、強大的地圖編輯功能等;而建立一個地圖查詢系統(tǒng),那么只需要地圖顯示和操作的根本功能。根據(jù)以上功能分析,本系統(tǒng)將以矢量圖形系統(tǒng)所應具備的根本功能為根底,從城市信息管理系統(tǒng)的需求出發(fā)進行系統(tǒng)功能的設計。2.4功能模塊設計 本系統(tǒng)對功能結構的設計采用的是完全面向對象的模塊化方式,“模塊化的設計方式,使得系統(tǒng)能夠易于維護和擴展。系統(tǒng)主要包含以下能模塊:圖形繪制模塊、圖形操作模塊、查詢模塊、矢量數(shù)據(jù)的輸入及輸出模塊。下面分別對各模塊功能作簡要說明。圖形繪制模塊 該模塊主要實現(xiàn)對根本圖形元素類〔點、線、圓、圓形區(qū)域、標注文本等〕的繪制功能。2.圖形操作模塊 該模塊要實現(xiàn)的主要操作功能有:⑴圖形無級縮放:圖形能夠以任意比例尺放大縮??;⑵漫游:通過調整視圖屏幕來顯示圖形的其他局部進行瀏覽;⑶全圖顯示:在視圖屏幕中顯示所有圖形元素;⑷點選:通過鼠標點擊選取當前視圖屏幕中的圖形元素并查詢其屬性數(shù)據(jù)。2.5本章小結 本章主要對系統(tǒng)開發(fā)的思路進行了簡單的闡述,包括矢量圖形系統(tǒng)的構成、開發(fā)工具的選擇等方面;開發(fā)模式的選擇,包括對兩種開發(fā)模式的簡單介紹,并對兩種開發(fā)模式進行了比擬,選出了適合本系統(tǒng)的開發(fā)模式,即面向對象開發(fā)模式;闡述了組本錢系統(tǒng)的幾個模塊,并對各個模塊的功能進行了分析與介紹。第三章矢量圖形系統(tǒng)的坐標轉換3.1Windows環(huán)境下的坐標系3.1.1設備坐標 設備坐標是指在Windows環(huán)境下的各種輸出設備所使用的坐標4,5]。它所對應的對象是具體的設備,如:鍵盤、顯示器及打印機等。設備坐標是建立在笛卡爾直角坐標系上的,以像素為單位。一個實際物理屏幕就是由像素組成的,如平常所說的分辨率1024*768指的就是顯示器屏幕的實際寬度和高度的像素數(shù)目。由于不同的設備分辨率不同,相同坐標值的物理位置就可能不同。邏輯坐標 邏輯坐標也是建立在笛卡爾坐標系上的,即是指Windows系統(tǒng)各種映射模式下的坐標。Windows系統(tǒng)為了方便程序開發(fā),為我們提供了如表3.1所示的8種映像模式:表3.1Windows映像模式映射模式映射識別碼邏輯單元X和Y軸正向MM_TEXT1Pixel右下MM_LOMETRIC20.1mm右上MM_HIMETRIC30,01mm右上MM_LONGLISH40.1inch右上MM_HIENGLISH50.01inch右上MM_TWIPS61/440inch右上MM_ISOTROPIC7Variable變化的MM_ANISOTROPIC8Variable變化的 其中MM_TEXT方式宇DOS文本方式很相似,MM_Text方式允許應用程序利用設備像素工作,而DOS是在字符狀態(tài)下操作。在此模式下,窗口〔屏幕〕的原點是在坐上角,X的正方向為向右,Y的正方向為向下。 而MM_LOMETRIC、MM_LONGLISH、MM_HIENGLISH、MM_HIMETRIC四種映像方式默認的原點即是窗口的左上角,X的正方向為向右,Y的正方向為向上。坐標用英尺(inch)或毫米(mm)表示,對于繪圖程序來說很方便,不用進行坐標轉換。MM_ISOTROPIC與MM_ANISOTROPIC映像方式都是用笛卡爾坐標,且提供可變的邏輯單位和可變的原點。在MM_ISOTROPIC方式下,X軸和Y軸坐標的刻度是相同的,而MM_ANISOTROPIC方式下X軸和Y軸坐標的刻度是可以設置為不同的。 MM_TWRIPS方式下,TWIPS是對“一個點的1/20”3.2設備坐標與邏輯坐標設備坐標與邏輯坐標的關系邏輯坐標不同于設備坐標,它不需要考慮具體的設備類型,其中面向的對象是設備環(huán)境,在內存中建立的一種虛擬坐標系。雖然邏輯坐標的取值同設備坐標一樣都是整數(shù),但是采用的坐標單位是不同的,而且坐標軸的方向也是隨著映射模式的改變而不同。在矢量圖形系統(tǒng)中,應根據(jù)實際需要使用特定的邏輯坐標系。 邏輯坐標和設備坐標一起為Windows提供了設備無關性,設備無關性指的是只要設定了映射模式,不管是在何種輸出設備上,一個圖形顯示出同樣的效果。但對于MM_TEXT映射模式來說,因為其坐標單位是像素,而一個像素所占的實際長度隨著設備的不同而不同,長度是不固定的,所以在不同的輸出設備上不能保證所顯示圖形的大小相同。 設備坐標系和邏輯坐標系均是由Windows系統(tǒng)定義的,因此統(tǒng)稱為Windows坐標系3]。Windows下列圖形的繪制是在邏輯坐標系中進行的,用戶在各種繪圖設備上的繪制操作使用的是邏輯坐標值,然后Windows再根據(jù)所設定的映射模式,將邏輯坐標值轉換成設備坐標值,最后將圖形輸出到實際的顯示設備或打印設備上。設備坐標及邏輯坐標的轉換Windows下的繪圖是在邏輯坐標系中進行的,而任何圖形的顯示和輸出都必須在一定的設備上實現(xiàn),因此,在圖形系統(tǒng)的開發(fā)中,邏輯坐標到設備坐標的轉換常被大量用到。另外,當系統(tǒng)和用戶之間進行交互時,系統(tǒng)需要知道用戶輸入焦點的位置坐標,而這個坐標是設備坐標,必須將其轉換為邏輯坐標后才能進行識別和操作。 邏輯坐標與設備坐標轉換之前,首先要對映射模式進行設置,也就是要確立系統(tǒng)開發(fā)所采用的邏輯坐標系。在MFC中,不同的映射模式其對應的邏輯坐標單位是不同的,設定了映射模式,就規(guī)定了邏輯單位的大小和增量的方式。所以實現(xiàn)邏輯坐標與設備坐標轉換的第一步就是確定系統(tǒng)所使用的映射模式14]。 在MFC應用程序中可以通過調用CDC類的函數(shù)SetMapMode(intnMapMode)來設置,其中參數(shù)nMapMode代表的即是表1中的映射模式識別碼,用來指定新的映射模式,可以取Windows八種映射模式中的任意一種。 本系統(tǒng)在視圖類CMapView的OnDraw函數(shù)中設置映射模式如下:pDC->SetMapMode(MM_TEXT); 為了完成Windows各種映射模式下從邏輯坐標到設備坐標的轉換,VC++提供了兩個轉換功能函數(shù):DPtoLP(LPPOINTlpPoints)//從設備坐標到邏輯坐標的轉換LPtoDP(LPPOINTlpPoints)//從邏輯坐標到設備坐標的轉換3.3窗口與視口 窗口是虛擬存在的一個屏幕視口〔也稱視圖〕是設備坐標系〔通常屏幕〕中定義的一個矩形區(qū)域,就是在屏幕上看到的視圖客戶區(qū),即繪圖的區(qū)域,用來確定顯示內容,窗口是圖形的可見局部。窗口的坐標是邏輯坐標,與設備無關5]。視口是與設備相關的一個矩形區(qū)域,坐標單位是與設備相關的。視口決定了窗口中的圖形顯示在屏幕上的位置和大小。窗口坐標的原點與視口坐標的原點始終對應于同一點。 窗口和視口的劃分與Windows下列圖形繪制的機制有關。Windows下的繪圖并不是把圖形直接繪制到設備屏幕上,而是先在Windows預先定義好的坐標系統(tǒng)〔映射模式〕中選擇一個作為繪圖參考系,在此映射模式下將圖形繪制到虛擬的內存窗口中去。然后再將窗口中的圖形映射到視口中。如果映射到屏幕上就實現(xiàn)了圖形的顯示;如果映射到打印機等輸出設備上就實現(xiàn)了圖形的打印輸出。 窗口原點和視口原點指的是同一點分別在窗口坐標系和視口坐標系中的坐標值,它們決定了圖形由窗口映射到視口時的相對位置。3.4本章小結要實現(xiàn)矢量圖形的繪制、顯示及無級縮放等功能,首先要確立和實現(xiàn)矢量圖形系統(tǒng)所采用的坐標系,坐標系是整個圖形系統(tǒng)開發(fā)的根底。本系統(tǒng)建立了自己的圖形坐標系,稱之為實際坐標系,來維護矢量數(shù)據(jù)的地理坐標,并實現(xiàn)了實際坐標與Windows坐標——邏輯坐標和設備坐標的相互轉換。因此本章對矢量圖形系統(tǒng)坐標系的建立過程及其與Windows坐標系的相互關系進行了介紹,并對設備坐標與實際坐標的轉換方法進行了闡述,最后還簡單的介紹了窗口與視口及其他們之間的關系。第四章實現(xiàn)矢量圖形系統(tǒng)的文檔和視圖4.1矢量圖形系統(tǒng)的圖形元素類 面向對象的程序設計,是目前程序設計的主流方法,在本設計中,將利用面向對象的程序設計和C++類的組織方法,組織建立一個根本矢量圖形的圖形元素類。組織實現(xiàn)的矢量圖形系統(tǒng),能夠處理點類、線類、面類等類別的圖形元素,其中點類圖形元素有包括直線,圓,圓弧,標注文本等圖形元素,針對每類圖形元素組織建立起對其進行管理的C++類,并把每個圖形元素作為一個獨立的對象來管理。圖形元素基類對各類圖形元素進行分析,可以發(fā)現(xiàn)各類圖形元素具有一些相同的屬性和操作功能,如圖形元素的顏色、線型線寬所在層等屬性和得到一個圖形元素是否做了刪除標志等操作。把這些圖形元素中共性的東西〔屬性和操作〕,組織存放在一個圖形元素基類(CDraw)中,具體的圖形元素由這個基類來派生。直線類直線類Cline是從CDraw派生而來,在直線類的構造函數(shù)中,共有包括11個參數(shù),并利用前7個參數(shù)從CDraw派生而來,并在構造函數(shù)中對其余的四個參數(shù)〔直線的起點與終點〕進行了初始化。用來標識直線類的特殊屬性,也在類中進行了定義。連續(xù)直線或封閉多邊形類連續(xù)直線除了具有圖形元素基類所具有的屬性外,從圖形的幾何特征上,連續(xù)直線是由很多頂點組成的,而且頂點數(shù)目是不確定的。一條連續(xù)直線可能只有兩個頂點,也可能有幾千個頂點。所以,需要定義一個結構來存儲連續(xù)直線的一個頂點坐標。定義一個成員變量m_Numble用來記錄點的個數(shù),定義一個b_Fill來標識是連續(xù)直線還是封閉多邊形。圓類 對圓類CCircle的創(chuàng)立方法與直線類CLine類似,圓除了具有圖形元素的根本特征外,還有自身的幾何特性。在CCircle類中定義了m_CircleX,m_CircleY,m_CircleR用來記錄圓心與圓的半徑,并定義了b_Fill用來標識此圖形元素是圓還是圓形區(qū)域。圓弧類圓是圓弧的一個特例,當圓弧的弧度等于2時就是圓。所以可以從一個圓類派生得到一個圓弧類。在圓弧類中定義了m_Angle1,m_Angle2用來表示圓弧的起始弧度與終點的弧度。標注文本類矢量圖形中可以有大量的標注文本,標注文本除了具有圖形元素的根本特性外,還具有位置、字體及標注內容等自身的信息。CText類也有兩個構造函數(shù),第二個構造參數(shù)有多個參數(shù),并利用多個參數(shù)對類的成員變量進行初始化。在構造函數(shù)中,調用了基類CDraw的構造函數(shù)對基類CDraw的成員變量進行初始化。圖形參數(shù)類在矢量圖形系統(tǒng)中,圖形參數(shù)是集中存儲的。在圖形元素基類中成員變量m_ColorPen,m_ColorBrush分別用來存儲畫筆的顏色與畫刷的顏色序號,m_Layer中存儲的是在圖層列表中的序列號。用m_ColorList,m_LayerList兩個數(shù)組來分別存儲顏色和涂層,并在構造函數(shù)中進行初始化。4.2矢量圖形系統(tǒng)的文檔面向對象的文檔管理機制管理矢量圖形系統(tǒng)圖形數(shù)據(jù)的方法即文檔管理機制。在本設計的開發(fā)中,采用一套完全面向對象的文檔組織機制。這種機制就是通過圖形元素類創(chuàng)立很多圖形元素對象,每個圖形元素對象作為一個整體來組織存儲空間的分配、存取等各種管理功能。然后通過建立一種存儲機制,來管理指向所有圖形元素對象的指針,到達管理所有圖形元素對象的目的。這種文檔管理機制具有組織簡單結構化和移植性好,以及比擬容易利用VC++程序設計語言的開發(fā)功能等優(yōu)點。缺點是需要較大的內存空間。創(chuàng)立圖形元素對象指針管理一個矢量圖形系統(tǒng)文檔的思路是:每個圖形元素是圖形元素類創(chuàng)立的一個對象,在創(chuàng)立這個對象時得到指向這個對象的指針,建立一個對象指針數(shù)組來管理這些指針,以到達管理所有圖形元素對象的目的。 在VC++下可以較容易地實現(xiàn)對指向圖形元素對象的指針的組織和管理。在MFC中有一個類模板CTypedPtrArray,可以用它來創(chuàng)立一個管理類指針的對象。例如,可以定義一個管理CLine類指針的對象如下:CTypedPtrArray<CObArray,Cline*>m_LineArray;矢量圖形系統(tǒng)的文檔在應用程序Draw中,可以派生幾個CObArray對象來分別管理基類圖形元素。在文檔類CDrawDoc中創(chuàng)立用來管理各類圖形元素的對象指針,創(chuàng)立的CObArray對象如下: private: CTypedPtrArray<CObArray,CLine*>m_LineArray; //管理直線對象指針的對象 CTypedPtrArray<CObArray,CPline*>m_PLineArray;//管理連續(xù)直線對象指針對象 CTypedPtrArray<CObArray,CCircle*>m_CircleArray;//管理圓對象指針的對象 CTypedPtrArray<CObArray,CArc*>m_ArcArray; //管理圓弧對象指針的對象 CTypedPtrArray<CObArray,CText*>m_TextArray; //管理文字對象指針的對象實現(xiàn)文檔的管理功能⑴增加圖形元素。在應用程序Draw中增加一個圖形元素對象〔如一條直線〕時,需要進行以下兩個步驟的操作:首先需要創(chuàng)立一個圖形元素對象,并用圖形元素的實際數(shù)據(jù)初始化這個圖形元素對象。如增加一條直線時,需要創(chuàng)立一個CLine對象,并用這條直線的實際數(shù)據(jù)〔起終點、所在圖層、顏色等〕初始化這個CLine對象的成員變量。然后需要把指向新創(chuàng)立的圖形元素對象的指針,增加到文檔類中管理圖形元素對象指針的對象中。如增加一條CLine對象后,需要把指向這個CLine對象的指針增加到文檔類的m_LineArray對象中。 為了實現(xiàn)增加各類圖形元素的功能,在文檔類CDrawDoc中定義幾個函數(shù),分別來完成增加各類圖形元素的操作功能 CLine*AddLine(shortColorPen,shortColorBrush,floatLineWide,shortLineType,shortLayer,intid_only,floatX1,floatY1,floatX2,floatY2); CCircle*AddCircle(shortColorPen,shortColorBrush,floatLineWide,shortLineType,shortLayer,intid_only,floatCircleX,floatCircleY,floatCircleR,BOOLbFill); CArc*AddArc(shortColorPen,shortColorBrush,floatLineWide,shortLineType,shortLayer,intid_only,floatCircleX,floatCircleY,floatCircleR,floatAngle1,floatAngle2); CText*AddText(shortColorPen,shortColorBrush,floatLineWide,shortLineType,shortLayer,intid_only,floatStartX,floatStartY,floatAngle1,floatAngle2,floatTextHeight,floatTextWide,floatOffWide,unsignedcharTextFont,intTextLong,CStringText); CTag*AddTag(shortColorPen,intLayer,floatxInsert,floatyInsert,floatxScale,floatyScale,floatangle,intonly_id,intidBlock); CPline*AddPLine(shortColorPen,shortColorBrush,floatLineWide,shortLineType,shortLayer,intid_only,intNumble,PointStruct*PointList); 這6個函數(shù)分別用來實現(xiàn)增加一條直線、一個圓、一個圓弧、一個標注文本、一條連續(xù)直線或一個多邊形區(qū)域的功能。函數(shù)返回指向新增圖形元素對象的指針。⑵實現(xiàn)對圖形元素的操作。為了實現(xiàn)對圖形元素的操作,為此,在文檔類CDrawDoc中定義一些Public成員函數(shù),并在實現(xiàn)文件drawdoc.cpp中,參加函數(shù)的具體實現(xiàn)代碼。函數(shù)具體定義如下:CDraw*GetGraph(shortLb,intindex);//得到指向圖形元素對象的指針VoidDeleteGraph(shortLb,intindex);//刪除圖形元素對象IntGetGraphNumb(shortLb);//各類圖形元素的數(shù)目IntGetGraphUpperBound(shortLb);//存儲各類圖形元素CObArray對象數(shù)組的最大下標IntGetGraphIndex(shortLb,intID);//某個識別號的圖形元素對象指針在CObArray數(shù)組中的存放位置4.3矢量圖形系統(tǒng)的視圖建立坐標系⑴建立坐標系 該坐標系取屏幕的左下角點作為圖形屏幕的基點。客戶區(qū)的左下角的坐標定義為(m_xStart,m_yStart),并確定一個變量blc作為邏輯坐標和實際坐標的比例關系。⑵實際坐標與邏輯坐標的轉換 為了實現(xiàn)實際坐標與邏輯坐標的轉換,在視圖類CDrawDoc中定義如下的四個轉換函數(shù): Public: VoidDPtoVP(floatx,floaty,int*X,int*Y); VoidVPtoDP(intx,inty,float*X,float*Y); IntDLtoVL(floatl); FloatVLtoDL(intl); 函數(shù)VPtoDP用來將邏輯坐標轉換成實際坐標,參數(shù)(x,y)是一個點的邏輯坐標,參數(shù)(*X,*Y)返回轉換后的實際坐標值。 函數(shù)DLtoVL用來將實際坐標長度轉換成邏輯坐標長度,參數(shù)l是一個實際坐標長度,函數(shù)返回邏輯坐標表示的長度值。 四個轉換函數(shù)中用到的成員變量,在視圖類CDrawView中定義: Privated: Floatm_xStart,m_yStart,blc; Intm_wScreen,m_hScreen; 為了在應用程序Draw的其他類中能夠使用四個坐標轉換函數(shù),可以將四個轉換函數(shù)定義成四個全局函數(shù)來實現(xiàn)轉換操作功能,在實現(xiàn)文件drawview.cpp中,定義四個全局函數(shù)。且四個全局函數(shù)利用視圖類指針p_View調用視圖類的四個坐標轉換函數(shù),來完成坐標和長度的轉換功能,p_View指向當前激活的視圖對象。如果在某個實現(xiàn)文件中使用這四個全局轉換函數(shù),只需在這個實現(xiàn)文件中的開始處參加全局函數(shù)的外部引用。實現(xiàn)各類圖形元素的繪制功能利用虛函數(shù)實現(xiàn)各種圖形元素的繪制功能。在圖形元素基類CDraw中,抽象定義一個進行繪制操作的虛函數(shù)。因為在應用程序Draw中,不用CDraw類直接來創(chuàng)立對象,所以可以將虛函數(shù)定義成純虛函數(shù): VirtualvoidDraw(CDC*pDC,intm_DrawMode,intm_DrawModel,shortBackColor)=0;在各種圖形元素類CLineCCircleCArcCTextCTagCPlineCPlineRgnCLinkNet中,重載虛函數(shù)Draw:virtualvoidDraw(CDC*pDC,intm_DrawMode,intm_DrawModel,shortBackColor);實現(xiàn)視圖的繪制 為了實現(xiàn)應用程序Draw的圖形繪制工作,在文檔類CDrawDoc中定義Draw函數(shù)如下: voidDraw(CDC*pDC,intm_DrawMode,intm_DrawModel,shortBackColor);4.4鼠標交互繪圖要解決的主要問題⑴捕獲鼠標操作消息 VC++提供了足夠的窗口消息和已經保護的消息處理函數(shù)解決這個問題.在應用程序Draw中實現(xiàn)鼠標交互繪制圖形元素時,將主要用到以下三個鼠標操作: OnMouseMove(UINTnFlags,CPointpoint)WM_MOUSEMOVE//鼠標移動 OnRButtonDown(UINTnFlags.CPointpoint)WM_RBUTTONDOWN//按下右鍵 OnLButtonDown(UINTnFlags.CPointpoint)WM_LBUTTONDOWN//按下左鍵⑵捕捉所有的鼠標輸入 在用鼠標交互繪制一個圖形元素時,在已經開始繪圖的情況下,不希望還能進行別的操作,以防止造成系統(tǒng)流程和變量初始化等方面的錯誤.VC++提供了兩個成員函數(shù)來滿足以上的功能需求: CWnd::SetCapture(); CWnd::ReleaseCapture();⑶在屏幕上拖動圖形 在用鼠標交互繪制圖形元素時,為了直觀的看到所繪制的圖形,一般采用拖動圖形的方法;⑷保存圖形數(shù)據(jù)到文檔 用鼠標在屏幕上交互繪制的圖形元素,要創(chuàng)立一個圖形元素對象并將指向這個圖形元素對象的指針保存起來;⑸將圖形以實際的形態(tài)重畫 用鼠標交互繪制一個圖形元素后,要在屏幕上馬上顯示出這個圖形元素的實際形態(tài),必須將圖形元素以實際的形態(tài)重畫。在矢量圖形系統(tǒng)設計中,一般采用CClientDC對象,在交互繪制圖形元素操作完成后,即時在視圖中重畫這個新增的圖形元素。交互繪制各類圖形元素本設計主要實現(xiàn)交互繪制直線、圓、填充圓、圓弧、標注文本、連續(xù)直線、多邊形區(qū)域的實現(xiàn)過程.⑴增加菜單資源. 在應用程序Draw的菜單資源中,增加一個菜單〞鼠標繪圖〞,.在這個菜單中包含直線、圓、填充圓、圓弧、標注文本、連續(xù)直線及多邊形區(qū)域菜單項。參加的菜單如圖4-1所示:圖4-1鼠標繪圖菜單⑵為每個操作添加消息處理函數(shù) 選中其中的一個菜單項,單擊鼠標右鍵,選擇“建立類向導……〞,在Classname中選擇CDrawView,在Messages中選擇COMMAND,點擊AddFunction,即可為菜單先增加一個響應函數(shù)。點擊Edit即可在實現(xiàn)文件drawview.cpp中增加消息處理函數(shù)的實現(xiàn)代碼.操作界面如圖4-2所示:圖4-2MFCClassWisard獲得圖形元素的唯一識別號: 在一個矢量圖形系統(tǒng)中,對于任何一個圖形元素,必須有一個能夠與其他圖形元素區(qū)分開來的屬性,因此,在此系統(tǒng)中,在Draw類中為每類圖形元素創(chuàng)立一個惟一識別號變量m_id_only.為了得到每類圖形元素的識別號,在CDrawDoc中定義一個成員函數(shù)GetGraphID來實現(xiàn)。具體函數(shù)定義如下: intGetGraphID(shortLb).其中參數(shù)Lb用來表示圖形類別,具體的實現(xiàn)代碼在drawdoc.cpp文件中。當單擊標注文本時出現(xiàn)文本對話框如圖4-3:圖4-3標注信息窗口當單擊字體參數(shù)時出現(xiàn)的對話框如圖4-4:圖4-4標注字體參數(shù)4.5本章小結本章主要是對直線、連續(xù)直線及封閉多邊形區(qū)域、圓、圓弧、標注文本等根本的圖形元素的數(shù)據(jù)組織和繪制方法做了簡單的介紹,并對具體的實現(xiàn)過程也做了簡要的概述。對于鼠標繪圖操作的完成提供了有效的方法。第五章矢量圖形系統(tǒng)的操作功能5.1圖形操作菜單管理增加菜單資源 在應用程序Draw的菜單資源中,增加“圖形操作〞及“圖形選中〞兩個菜單,.并分別在兩個菜單下參加菜單項如圖5-1與圖5-2所示:圖5-1圖形操作菜單圖5-2圖形選中菜單添加消息處理函數(shù)按照4.3節(jié)中介紹的方法為兩個菜單下的所有菜單項添加消息處理函數(shù)。添加后,可以在視圖類CDrawView中找到如下定義:afx_msgvoidOnGraphRedraw();afx_msgvoidOnGraphZoom(); afx_msgvoidOnGraphSmall();afx_msgvoidOnGraphPan();afx_msgvoidOnGraphUp();afx_msgvoidOnGraphFirst();afx_msgvoidOnGraphAll();可以在視圖類drawView.cpp中找到如下定義: ON_COMMAND(ID_GRAPH_REDRAW,OnGraphRedraw) //圖形重畫 ON_COMMAND(ID_GRAPH_ZOOM,OnGraphZoom) //圖形放大 ON_COMMAND(ID_GRAPH_SMALL,OnGraphSmall)//圖形縮小 ON_COMMAND(ID_GRAPH_PAN,OnGraphPan) //圖形搖動 ON_COMMAND(ID_GRAPH_UP,OnGraphUp) //重畫上屏 ON_COMMAND(ID_GRAPH_FIRST,OnGraphFirst) //重畫首屏 ON_COMMAND(ID_GRAPH_ALL,OnGraphAll) //重畫全屏 ON_COMMAND(ID_SELECT_MOUSE,OnSelectMouse)//圖形選中 ON_COMMAND(ID_SELECT_CLEAR,OnSelectClear) //放棄選中 ON_COMMAND(ID_SELECT_DELETE,OnSelectDelete)//刪除選中圖形5.2圖形操作的具體實現(xiàn)圖形重畫所謂圖形重畫,就是把當前視圖屏幕重新繪制一次,實際上也就是讓視圖類的函數(shù)OnDraw(CDC*pDC)重新執(zhí)行一次。根據(jù)需要重畫區(qū)域的不同,圖形重畫可以分為全屏重畫和局部重畫。⑴全屏重畫 在有些情況下,需要將當前視圖屏幕全屏重畫。全屏重畫有兩種方法,一種是使用函數(shù)UpdateAllViews,使屬于當前文檔對象的所有視圖重畫。另外一種方法即是用函數(shù)Invalidate,使當前視圖屏幕的客戶區(qū)失效,從而激活圖形重畫。兩種方法的不同點為:Invalidate函數(shù)它只能使當前視圖重畫,而與其同文檔的其他視圖并不重畫。對視圖類CDrawView的OnGraphRedraw函數(shù)進行修改。具體代碼如下:VoidCDrawView::OnGraphRedraw() { CDrawDoc*pDoc=GetDocument(); pDoc->UpdateAllViews(this); Invalidate(); } OnGraphRedraw函數(shù)首先得到指向當前文檔對象的指針,然后調用UpdateAllViews函數(shù)重畫此文檔對象所有的視圖,參數(shù)this是指向當前視圖對象的指針。⑵局部重畫 如果只希望將當前視圖屏幕的一局部區(qū)域重畫,即進行局部重畫。在VC++中,Invalidate與RectInvalidateRgn兩個函數(shù)可以完成此功能。兩個函數(shù)的定義如下:VoidInvalidateRect(LPCRECTlpRect,BOOLbErase=TRUE); //lpRect中存儲著視圖中需要重畫的區(qū)域,參數(shù)bErase用于指定當區(qū)域重畫時,背景是否擦除voidInvalidateRgn(CRgn*pRgn,BOOLbErase=TRUE);圖形放大和移動1.圖形放大 圖形放大指的是通過調整視圖屏幕,使當前視圖屏幕中的一局部區(qū)域放大顯示到整個視圖屏幕中15]。矢量圖形系統(tǒng)應具有無級放縮的功能。所謂“無級〞,指的是圖形能以任何的比例進行顯示。在應用程序Draw已經建立的坐標系根底上,可以很容易實現(xiàn)圖形的無級放大。實現(xiàn)圖形放大的操作方法很多:如可以進行固定比例的圖形放大;再如可以通過窗口放大。本設計將涉及到用窗口放大圖形的操作方法和具體實現(xiàn)步驟。在此根底上,可以輕而易舉的實現(xiàn)其他方法的圖形放大操作功能。實現(xiàn)圖形放大、移動后的效果圖分別如圖5-3、圖5-4所示:圖5-3圖形繪制〔放大前〕圖5-4圖形繪制〔放大后〕2.圖形移動 圖形移動指的是將圖形元素在橫向和縱向上移動一定的偏移量,得到移動后圖形元素的坐標。圖形移動操作功能的機理非常簡單,只需將各類圖形元素的特征點做相應的坐標移動即可。⑴各類圖形元素的移動操作 為了實現(xiàn)圖形元素的移動功能,同樣需要在圖形元素基類CDraw中定義一個純虛函數(shù):virtualvoidMove(floatx_Move,floaty_Move)=0; 在各個圖形元素類中增加這個虛函數(shù)的重載定義,在各個圖形元素類的實現(xiàn)文件中,參加這個重載函數(shù)的實現(xiàn)代碼。⑵實現(xiàn)圖形移動操作功能 圖形移動功能的操作步驟如下:首先用“鼠標點中〞操作選中要移動的圖形元素,按下鼠標左鍵點中移動操作的基點,再按下鼠標左鍵點中移動操作的目標點,各個圖形元素將以這兩個點為根底進行相對移動。在OnEditMove函數(shù)中,對圖形移動操作進行了標識,為了實現(xiàn)具體的移動操作,需要對各個鼠標消息處理函數(shù)進行修改。在實現(xiàn)文件drawview.cpp的消息處理函數(shù)OnLButtonDow、OnMouseMoven、OnRButtonDown中參加相應的實現(xiàn)代碼。圖形移動的效果圖如圖5-5、圖5-6所示:圖5-5圖形繪制〔移動前〕圖5-6圖形繪制〔移動后〕重畫上屏和重畫首屏圖形經過放大、移動操作后,還要有把圖形屏幕再恢復到前一屏幕〔重畫上屏〕或者直接使圖形回到第一屏〔重畫首屏〕的功能。要實現(xiàn)重畫上屏和重畫首屏的功能,就需要記錄下每一屏幕的狀態(tài),并時刻跟蹤著當前的狀態(tài)。記錄屏幕狀態(tài): 一個圖形屏幕是由三個參數(shù)來確定的:屏幕左下角原點的坐標m_xStart、m_yStart和顯示比例blc,在文檔類CDrawDoc中定義一個結構數(shù)組來存儲歷史圖形屏幕。在CDrawDoc類中定義以下幾個變量:Public: intm_CurrentScreen;//當前屏幕的序號 intm_MaxScreen;//最多能存儲的屏幕數(shù) ScreenStruct*m_Screen;//記錄屏幕參數(shù)的結構數(shù)組結構ScreenStruct在頭文件drawdoc.h中CDrawDoc類定義前定義:Typedefstruct {Floatblc;//顯示比例Floatsx;//屏幕左下角橫坐標Floatsy;//屏幕左下角縱坐標 }ScreenStruct;在文檔類CDrawDoc中定義一個函數(shù),來完成存儲一個圖形屏幕狀態(tài)的操作功能:Public:VoidAddScreen(floatStartX,floatStartY,floatblc); 在實現(xiàn)文件drawdoc.cpp中,參加函數(shù)的實現(xiàn)代碼。⑴重畫上屏 要實現(xiàn)重畫上屏操作功能,只需把m_CurrentScreen的值減去1,從結構數(shù)組m_Screen中取出屏幕參數(shù)重畫圖形即可。在實現(xiàn)文件drawview.cpp中,將“重畫上屏〞菜單項的消息處理函數(shù)OnGraphUp的實現(xiàn)代碼修改如下:voidCDrawView::OnGraphUp(){CDrawDoc*pDoc=(CDrawDoc*)GetDocument();if(pDoc->m_CurrentScreen>0)//如果當前不是首屏,當前圖形屏幕序號減1pDoc->m_CurrentScreen--;//得到上一屏幕的圖形參數(shù)并重畫圖形m_xStart=p_Screen[pDoc->m_CurrentScreen].sx;m_yStart=p_Screen[pDoc->m_CurrentScreen].sy;blc=p_Screen[pDoc->m_CurrentScreen].blc;Invalidate();//重畫圖形}p_Screen是CDrawView類中定義的指向文檔對象中的結構數(shù)組m_Screen的指針,它在 視圖類CDrawView中定義ScreenStruct*p_Screen; 在實現(xiàn)文件drawview.cpp中,在重載的虛函數(shù)OnActiveView中對p_Screen進行初始化,將它指向當前文檔對象中的結構數(shù)組m_Screen:voidCDrawView::OnActivateView(BOOLbActivate,CView*pActivateView,CView*pDeactiveView){p_View=this;CDrawDoc*pDoc=(CDrawDoc*)GetDocument();p_Screen=pDoc->m_Screen;CView::OnActivateView(bActivate,pActivateView,pDeactiveView);}⑵重畫首屏 對于重畫首屏功能來說,只要取出存儲在結構數(shù)組m_Screen中的首屏參數(shù),并對視圖重畫即可。修改實現(xiàn)文件drawview.cpp中的消息處理函數(shù)OnGraphFirst,得到實現(xiàn)代碼如下:voidCDrawView::OnGraphFirst()//重畫首屏{//TODO:AddyourcommandhandlercodehereCDrawDoc*pDoc=GetDocument();if(pDoc->m_CurrentScreen==0)return;m_xStart=p_Screen[0].sx;m_yStart=p_Screen[0].sy;blc=p_Screen[0].blc;pDoc->AddScreen(m_xStart,m_yStart,blc);Invalidate();}顯示全圖在矢量圖形系統(tǒng)中,隨著一些圖形元素通過外部接口或者系統(tǒng)本身的繪制功能的參加,圖形首屏可能包含不了所有的圖形元素;還有一種情況是,圖形中所有的圖形元素都在視圖屏幕的一個角上,只占圖幅的一小局部。這是就需要一個操作功能,調整視圖屏幕左下角原點的實際坐標(m_xStart,m_yStart)和顯示比例blc,使所有的圖形元素正好能夠繪制到視圖屏幕中〔在屏幕上留有一局部邊界區(qū)域〕,顯示全圖功能就是為完成此功能而設置的。實現(xiàn)顯示全圖功能的思路是,通過得到每一類圖形元素〔如直線、連續(xù)直線〕的邊界矩形,然后根據(jù)視圖屏幕的大小〔邏輯坐標〕進行計算,得到屏幕的參數(shù)m_xStart,m_yStart,blc.所以,解決問題的關鍵在于得到各類圖形元素的邊界矩形。各類圖形元素的邊界矩形計算: 在圖形元素基類CDraw中定義一個純虛函數(shù):VirtualvoidGetRect(float*minx,float*minY,float*maxX,float*maxY)=0; 函數(shù)GetRect用來計算圖形元素的邊界矩形,〔*minX,*minY〕和〔*maxX,*maxY〕這四個指針參數(shù)用來返回邊界矩形的最小和最大坐標。 在由CDraw類派生的各個圖形元素類中重載虛函數(shù)GetRect,即在各個類中參加以下定義代碼:VirtualvoidGetRect(float*minx,float*minY,float*maxX,float*maxY);并在各個圖形元素類中實現(xiàn)代碼,以完成計算各類圖形元素邊界矩形的功能。實現(xiàn)顯示全圖功能:⑴得到所有圖形元素的邊界矩形 把所有圖形元素的邊界矩形坐標進行比擬,就可以得到所有圖形元素的邊界矩形。為了實現(xiàn)這個功能,在文檔類CDrawDoc中定義一個Public函數(shù):BOOLGetRect(float*m_Xmin,float*m_Ymin,float*m_Xmax,float*m_Ymax); 指針參數(shù)用來返回邊界矩形的最小和最大坐標,當能計算得到邊界矩形時,函數(shù)返回TRUE,否那么,函數(shù)返回FALSE.在實現(xiàn)文件drawdoc.cpp中,參加這個函數(shù)的實現(xiàn)代碼在函數(shù)GetRect中,首先對記錄最小值和最大值的變量初始化,然后對所有的直線連續(xù)直線圓圓弧標注文本多邊形區(qū)域網絡點等類圖形元素進行循環(huán),得到每個圖形元素的邊界矩形,并比擬運算得到所有圖形元素的邊界矩形。當至少有一個圖形元素時,函數(shù)返回TRUE,沒有任何圖形元素時,函數(shù)返回FALSE.⑵實現(xiàn)顯示全圖功能 在得到所有圖形元素的邊界矩形后,就可以調整視圖屏幕的基點和比例,使當前視圖正好能夠繪制下所有的圖形元素。在實現(xiàn)文件drawview.cpp中,對菜單項“重畫全屏〞的消息處理函數(shù)OnGraphAll進行修改:voidCDrawView::OnGraphAll(){//TODO:Addyourcommandhandlercodeherefloatminx,miny,maxx,maxy,bl1;CDrawDoc*pDoc=GetDocument();SetCapture();SetCursor(LoadCursor(NULL,IDC_WAIT));BOOLpb=pDoc->GetRect(&minx,&miny,&maxx,&maxy);SetCursor(LoadCursor(NULL,IDC_ARROW));ReleaseCapture();if(!pb)return;bl1=(maxx-minx)/(m_wScreen-20);blc=(maxy-miny)/(m_hScreen-20);if(bl1>blc)blc=bl1;m_xStart=minx-10*blc;m_yStart=miny-10*blc;p_Screen[0].sx=m_xStart;p_Screen[0].sy=m_yStart;p_Screen[0].blc=blc;pDoc->m_CurrentScreen=0;Invalidate();}圖形重畫速度的提升⑴提高圖形重畫速度的方法 一個根本的方法就是在顯示一個圖形元素前,對這個圖形元素進行判斷,判斷這個圖形元素是否在視圖屏幕中,如果這個圖形元素不在當前的視圖屏幕中,就不用對這個圖形元素進行繪制,以此節(jié)省繪制時間。 我們采用的計算方法應該是計算簡單且允許不太嚴密。這里所謂的不太嚴密,指的是用這種方法判斷是在視圖屏幕中的圖形元素,實際也可能不在視圖屏幕中,而經過判斷不在視圖屏幕中的圖形元素一定不在視圖屏幕中。這種判斷一般采用這個圖形元素的邊界矩形和屏幕邊界矩形是否相交的方法。 在提高圖形重畫速度時,首先要得到視圖屏幕即客戶區(qū)的大小。在應用程序Draw中,在視圖類CDrawView中有兩個變量m_hScreen和m_wScreen分別用來存儲當前視圖的高度和寬度〔邏輯坐標〕。在進行圖形繪制前,把視圖屏幕矩形有邏輯坐標轉換成實際坐標。定義以下四個全局變量,用來傳遞要繪制視圖的左下角和右上角的實際坐標。在實現(xiàn)文件drawdoc.cpp中,增加全局變量的定義:FloatxMinScreen,yMinScreen,xMaxScreen,yMaxScreen;為了在實現(xiàn)文件drawview.cpp中使用這些變量,在實現(xiàn)文件drawview.cpp中增加對這些全局變量的引用:ExternfloatxMinScreen,yMinScreen,xMaxScreen,yMaxScreen這四個全局變量在每次調用OnDraw函數(shù)實現(xiàn)視圖的繪制功能前被初始化。在實現(xiàn)文件drawview.cpp中的繪制函數(shù)CDrawView::OnDraw(CDC*pDC)中參加代碼,實現(xiàn)在每次繪制前得到視圖屏幕邊界的實際坐標:voidCDrawView::OnDraw(CDC*pDC){CDrawDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);//TODO:adddrawcodefornativedataherexMinScreen=m_xStart;yMinScreen=m_yStart;xMaxScreen=xMinScreen+blc*m_wScreen;yMaxScreen=yMinScreen+blc*m_hScreen;DrawBack(pDC);pDoc->Draw(pDC,0,0,m_bColor);m_MapMode=pDC->SetMapMode(1);}這樣在以當前的屏幕參數(shù)〔m_xStart,m_yStart,blc〕繪制圖形前,把視圖屏幕的左下角和右上角的實際坐標計算出來。 為判斷一個矩形區(qū)域與視圖屏幕矩形是否相交,在drawdoc.cpp中定義一個全局函數(shù):BOOLIsRectCross(floatminx,floatminy,floatmaxx,floatmaxy);函數(shù)的實現(xiàn)代碼如下:BOOLIsRectCross(floatminx,floatminy,floatmaxx,floatmaxy){if(minx>xMaxScreen||maxx<xMinScreen||miny>yMaxScreen||maxy<yMinScreen) returnFALSE;//如兩個矩形不相交else returnTRUE;}IsRectCross函數(shù)在一個矩形區(qū)域與視圖屏幕區(qū)域相交時返回TRUE,否那么返回FALSE.⑵提高圖形元素的繪制速度 對各類圖形元素的繪制函數(shù)Draw進行修改,使其能夠先判斷圖形元素的邊界矩形是否與圖形屏幕區(qū)域相交,來決定是否需要對圖形元素進行繪制。在直線類CLine的繪制函數(shù)Draw中,參加完整實現(xiàn)代碼,對于CCircle、CArc、CText、CPline、CPlineRgn、CTag、CLinkNet等圖形元素類,同樣也需要在其繪制函數(shù)Draw中參加相同的代碼。5.3圖形的點選與撤銷鼠標點選圖形元素為了實現(xiàn)圖形的刪除和恢復等操作功能,首先應該在矢量圖形系統(tǒng)中實現(xiàn)圖形的選中操作。對于一個矢量圖形系統(tǒng)來說,不但要能夠實現(xiàn)交互圖形繪制、放縮操作等,還應有一項根本的功能,就是能夠選中圖形元素。選中圖形元素是對圖形進行修改刪除直接從圖形上得到信息〔在GIS中〕,以及在GIS中實現(xiàn)空間統(tǒng)計和分析功能等操作的根底。各種圖形元素的選中區(qū)域:⑴直線和連續(xù)直線 因為直線是沒有寬度的,所以,這種選中判斷實際上是要判斷一個點與一條直線的距離是否在一定的距離范圍之內。問題的實質就是,如何確定這個判斷選中的距離范圍和怎樣計算一個點與一條直線的距離。點與直線距離的計算方法 為了完成計算點到直線距離的功能,需要定義一個函數(shù),為了在直線和連續(xù)直線類中都能夠使用這個函數(shù),在圖形元素基類CDraw中定義一個Public函數(shù):floatPointLine(floatxx,floatyy,floatx1,floaty1,floatx2,floaty2);函數(shù)的參數(shù)分別是選中點與直線兩個頂點的實際坐標,函數(shù)返回計算得到的距離值。在實現(xiàn)文件draw.cpp中,參加函數(shù)實現(xiàn)代碼。在上述函數(shù)中,調用了一個在CDraw類中定義的計算兩點距離的函數(shù)CalDisp,:FloatCalDisp(floatx1,floaty1,floatx2,floaty2);⑵圓和填充圓 圓的選中區(qū)域非常簡單,如果有效距離為j1,計算得到的鼠標按中點到圓心的距離為jl1;選中區(qū)域就是: |jl1-circle.r|<jl;即按中點到圓的距離小于jl.對于填充圓,選中區(qū)域那么是:Jl1<=jl;⑶圓弧 圓弧的選中區(qū)域同圓類似,首先要確定按中點是否在圓弧所在的圓上。即按中點到圓心的距離jl1符合: |jl1-circle.r|<jl;因為圓弧不是封閉的,還要確定按中點相對于圓心的弧度是否在圓弧的弧度范圍內,可以通過CArc類中的成員函數(shù)IsInArc函數(shù)來確定。⑷多邊形區(qū)域 圖形元素多邊形區(qū)域和標注文本〔四邊形〕都屬于這種情況。最簡單的多邊形區(qū)域就是沒有旋轉的矩形〔如水平標注的文本就是這種情況〕,判斷一個點是否在這種矩形中的算法非常簡單。VC++的CRgn類提供了一個成員函數(shù)來實現(xiàn)這個操作功能。CRgn類封裝了一些進行區(qū)域操作的函數(shù),可以直接解決按中點是否在多邊形區(qū)域中的問題。以下是操作步驟:首先定義一個CRgn對象;把CRgn初始化成一個具有n個頂點的多邊形區(qū)域;建立一個多邊形區(qū)域后,調用PtInRegion函數(shù)來判斷一個點是否在區(qū)域內。函數(shù)PtInRegion是CRgn類的成員函數(shù),它可以判斷點是否在初始化區(qū)域內。在CDraw類中建立一個函數(shù)完成這個操作:Public: BOOLPointRgn(floatx,floaty,intNumble,PointStruct*PointList,floatblc); //判斷點是否在初的區(qū)域內在實現(xiàn)文件draw.cpp中,參加函數(shù)的實現(xiàn)代碼各種圖形元素的點選判斷函數(shù)首先,在圖形基類CDraw中定義一個純虛函數(shù):Public:VirtualBOOLIsPoint(floatx,floaty,floatjl,floatblc)=0; 在各個圖形元素類CLineCCircleCArcCTextCPlineCPlineRgnCLinkNet中重載虛函數(shù)IsPoint,即在這些類中參加這個函數(shù)的重載定義:Pubic:VirtualBOOLIsPoint(floatx,floaty,floatjl,floatblc);然后實現(xiàn)各個圖形元素類重載的IsPoint函數(shù)的實現(xiàn)代碼,實現(xiàn)各個圖形元素類的點選判斷功能。實現(xiàn)點選圖形元素功能⑴增加一個菜單及消息處理函數(shù)⑵保存選中的圖形元素 要實現(xiàn)數(shù)據(jù)保存,就需要建立數(shù)據(jù)結構來存儲選中的圖形元素。在文檔類CDrawDoc中,定義一個結構數(shù)組和一個變量:Protected: GraphSelectStruct*GraphSelect;//存儲選中的圖形元素Intn_GraphSelect;//選中圖形元素的數(shù)目結構GraphSelectStruct在頭文件drawdoc.h中〔CDrawDoc類前〕定義為:Typedefstruct{ShortintLb;IntIndex;Intid_only;}GraphSelectStruct; 將選中的圖形元素存儲在結構數(shù)組GraphSelect中,成員變量Lb存儲選中圖形元素的類別;成員變量Index存儲圖形元素的序列號,即圖形元素在指針數(shù)組中的下標;成員變量id_only存儲這個圖形元素惟一的識別號,即圖形元素中的成員變量m_id_only。在實現(xiàn)文件drawdoc.cpp中,在CDrawDoc文檔類的構造函數(shù)內動態(tài)分配結構數(shù)組GraphSelect: CDrawDoc::CDrawDoc() { GraphSelect=newGraphSelectStruct[10000]; }在CDrawDo類的析構函數(shù)中,刪除動態(tài)分配的結構數(shù)組: CDrawDoc::~CDrawDoc() {DeleteGraphSelect; } 為了將一個選中的圖形元素存儲到結構數(shù)組GraphSelect中,在文檔類CDrawDoc中定義一個函數(shù):Public: BOOLAddSelectList(intLb,intindex,intid_only); 函數(shù)AddSelectList實現(xiàn)在結構數(shù)組GraphSelect中增加一個選中的圖形元素,增加成功是返回TRUE,否那么函數(shù)返回FALSE.函數(shù)的實現(xiàn)代碼如下:BOOLCDrawDoc::AddSelectList(intLb,intindex,intid_only){for(inti=0;i<n_G
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度建筑起重機械安全標準制定與實施合同3篇
- 二零二五年度加氣站設備維修與技術培訓服務合同3篇
- 二零二五年度房屋買賣居間合同中介機構責任與義務規(guī)范
- 二零二五年度小學生閱讀理解家教合同3篇
- 2025年度智能家電全面維修服務合同模板2篇
- 二零二五年度教務主任任期目標責任聘用合同3篇
- 二零二五年度建筑公司勞動合同范本:勞動合同續(xù)簽條件及程序3篇
- 二零二五年度海外工程勞務輸出合同3篇
- 二零二五年度辦公室改造與企業(yè)文化塑造合同3篇
- 二零二五年度城市排水系統(tǒng)PPP項目合作合同協(xié)議
- 封條模板A4直接打印版
- 常見化療藥物的不良反應及預防 課件
- 電解銅箔制造工藝簡介
- 電工維修培訓資料 維修電工技術學習 維修電工常識 電工培訓ppt課件
- 撲克牌24點練習題大全
- 螺絲英文簡稱
- 15MW風力發(fā)電機
- 正面管教 讀書分享(課堂PPT)
- 教練技術CP理論PPT課件
- 產品生命周期曲線(高清)
- 機械工程學報標準格式
評論
0/150
提交評論