C#交互繪圖技術(shù)_第1頁(yè)
C#交互繪圖技術(shù)_第2頁(yè)
C#交互繪圖技術(shù)_第3頁(yè)
C#交互繪圖技術(shù)_第4頁(yè)
C#交互繪圖技術(shù)_第5頁(yè)
已閱讀5頁(yè),還剩31頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第5章交互繪圖技術(shù)5.1窗口系統(tǒng)和事件驅(qū)動(dòng)模式5.2交互式的顯示控制技術(shù)5.3交互式的圖形生成技術(shù)5.4交互式的圖形編輯技術(shù)5.5OpenGL對(duì)圖形交互的支持5.1窗口系統(tǒng)和事件驅(qū)動(dòng)模式Windows操作系統(tǒng)是一個(gè)窗口式的多任務(wù)操作系統(tǒng),在Windows環(huán)境下編寫應(yīng)用程序,采用事件驅(qū)動(dòng)機(jī)制。傳統(tǒng)的MS-DOS程序主要采用順序的、關(guān)聯(lián)的、過(guò)程驅(qū)動(dòng)的程序設(shè)計(jì)方法。一個(gè)程序是一系列預(yù)先定義好的操作序列的組合,它具有一定的開(kāi)頭、中間過(guò)程和結(jié)束。程序直接控制事件和過(guò)程的順序。這樣的程序設(shè)計(jì)方法是面向程序而不是面向用戶的,交互性差,用戶界面不夠友好,因?yàn)樗鼜?qiáng)迫用戶按照某種不可更改的模式進(jìn)行工作。它的基本模型如圖所示。DOS環(huán)境下編程模式

事件驅(qū)動(dòng)程序設(shè)計(jì)模式對(duì)于需要用戶交互的應(yīng)用程序來(lái)說(shuō),事件驅(qū)動(dòng)的程序設(shè)計(jì)有著過(guò)程驅(qū)動(dòng)方法無(wú)法替代的優(yōu)點(diǎn)。它是一種面向用戶的程序設(shè)計(jì)方法,它在程序設(shè)計(jì)過(guò)程中除了完成所需功能之外,更多的考慮了用戶可能的各種輸入,并針對(duì)性的設(shè)計(jì)相應(yīng)的處理程序。它是一種“被動(dòng)”式程序設(shè)計(jì)方法,程序開(kāi)始運(yùn)行時(shí),處于等待用戶輸入事件狀態(tài),然后取得事件并作出相應(yīng)反應(yīng),處理完畢又返回并處于等待事件狀態(tài)。它的基本模型如圖所示。事件驅(qū)動(dòng)程序設(shè)計(jì)模式Windows下基于消息的事件驅(qū)動(dòng)編程消息MSG結(jié)構(gòu)是Windows的一種數(shù)據(jù)結(jié)構(gòu),包含消息的窗口來(lái)源、消息種類、與此消息相關(guān)的附加信息、消息發(fā)生時(shí)鼠標(biāo)的位置等。接收和處理消息的是窗口,每個(gè)窗口都有一個(gè)專門負(fù)責(zé)處理消息的“窗口函數(shù)”。MFC中的事件驅(qū)動(dòng)編程

微軟基礎(chǔ)類庫(kù)(MFC:MicrosoftFoundationClass)是微軟為Windows程序員提供的一個(gè)面向?qū)ο蟮腤indows編程接口,它大大簡(jiǎn)化了Windows編程工作。MFC通過(guò)定義一個(gè)消息與處理函數(shù)的對(duì)照表,實(shí)現(xiàn)了消息處理的分離編程。每當(dāng)產(chǎn)生一個(gè)事件,便可以通過(guò)這個(gè)對(duì)照表找到相應(yīng)的消息處理函數(shù),執(zhí)行這個(gè)函數(shù)便完成了相應(yīng)的功能;這樣,程序員不再需要編寫龐大的窗口函數(shù)。因此需要一類特殊的對(duì)象,每個(gè)對(duì)象負(fù)責(zé)在不同狀態(tài)之下根據(jù)自己的任務(wù)完成工作,稱這些類為功能類,具有以下共同特點(diǎn):都具有接收鍵盤,鼠標(biāo)消息的外部接口都應(yīng)提供一個(gè)初始化工作的外部接口Initalize都應(yīng)提供一個(gè)做掃尾工作的外部接口Suspend都應(yīng)提供接收自己將被刪除的消息的外部接口Kill提供恢復(fù)臨時(shí)的場(chǎng)景的外部接口Draw提供外部接口以完成被重新喚醒之后需要進(jìn)行的操作WakeUp每個(gè)功能類有相同的祖先,設(shè)計(jì)為虛接口VirtualFunction這種機(jī)制可是實(shí)現(xiàn)模塊分解和分工寫作,實(shí)現(xiàn)思想:從BaseFunction派生出一個(gè)新類,重載其中某些接口就可以完成具體的功能每個(gè)從BaseFunction派生出的新類只需負(fù)責(zé)自己的工作每個(gè)不同的功能類可以由不同的的單獨(dú)開(kāi)發(fā)而不影響系統(tǒng)的集成文檔類(MFC體系)中設(shè)置功能類對(duì)象的隊(duì)列,包含當(dāng)前正在運(yùn)轉(zhuǎn)的功能類對(duì)象和之前運(yùn)轉(zhuǎn)過(guò)的對(duì)象從一種狀態(tài)A轉(zhuǎn)換到另一種狀態(tài)B需要傳劍一個(gè)新的功能類的對(duì)象b(B類對(duì)象),然后將b作為參數(shù)調(diào)用文檔的一個(gè)外部接口SetCurrentFunction,完成狀態(tài)轉(zhuǎn)換SetCurrentFunction:調(diào)用被掛起對(duì)象的Kill外部接口;調(diào)用隊(duì)列中當(dāng)前功能類對(duì)象的Suspend外部接口;最后調(diào)用b的外部接口Initalize,將b壓進(jìn)隊(duì)列,成為當(dāng)前功能類對(duì)象當(dāng)視圖接受到鼠標(biāo)鍵盤消息,將此消息分發(fā)給文檔類中維護(hù)的當(dāng)前功能類對(duì)象。5.2交互式的顯示控制技術(shù)全景顯示旋轉(zhuǎn)平移縮放

本節(jié)內(nèi)容為交互繪圖平臺(tái)與顯示相關(guān)的控制技術(shù),以上機(jī)實(shí)現(xiàn)為主。場(chǎng)景充滿窗口的控制方法//得到場(chǎng)景分布區(qū)域的寬度ExtendPoint3DMax,Min;PSceneData->GetBox(Max,Min);//設(shè)置視距viewDisatance=Max.Distance(&Min)*15;//求出場(chǎng)景中心點(diǎn)middlePoint,作為顯示中心點(diǎn),保證場(chǎng)景能夠顯示在屏幕中心middlePoint=(Max+Min)/2;//求出場(chǎng)景分布區(qū)域x方向的長(zhǎng)度dX_Extend和y方向的長(zhǎng)度dY_ExtendPSceneData->GetBox(Max,Min);doubleExtend=Max.Distance(&Min);doubledX_Extend=Extend;doubledY_Extend=Extend;//再根據(jù)窗口的寬高比及Y方向的長(zhǎng)度,得到X方向的適合窗口寬高比的長(zhǎng)度dTmpX_ExtendDoubledTmpX_Extend=dY_Extend*m_dAspectRatio;//設(shè)置near平面和far平面nearestPlaneDistance=viewDistance-Extend/2;farestPlaneDistance=viewDistance+Extend/2;//設(shè)置視寬為X方向長(zhǎng)度及Y方向的適合窗口寬高比的長(zhǎng)度中小者//保證場(chǎng)景在X方向及Y方向都不會(huì)超出視景體viewWidth=max(dX_Extend,dTmpX_Extend)/1.1;//刷新窗口Invalidate();OnLButtonDown(msg){ m_LeftButtonDown=TRUE; m_LeftDownPos=GetMouseLocation(); m_CenterPoint=GetCenterPont(); m_ViewPoint=GetViewPoint();}OnLButtonUp(msg){ m_LeftButtonDown=FALSE;}OnMouseMove(msg){ intdx,dy; dx=m_LeftDownPos.x-GetMouseLocation().x; dy=m_LeftDownPos.y-GetMouseLocation().y; m_LeftDownPos=GetMouseLocation(); VP=m_ViewPoint-m_CenterPoint; doublealfa=3.14*dx/GetClientRect().right; SetViewDirection()VP; m_ViewPoint=GetViewPoint();

Invalidate();}m_LeftButtonDown用來(lái)標(biāo)志鼠標(biāo)左鍵是否已被按下。m_LeftDownPos記錄上次鼠標(biāo)移動(dòng)事件中鼠標(biāo)的位置,用來(lái)計(jì)算兩次鼠標(biāo)移動(dòng)的距離。m_CenterPoint,Point3D類型,顯示中心點(diǎn)的坐標(biāo)m_ViewPoint,Point3D類型,視點(diǎn)的位置當(dāng)按下鼠標(biāo)左鍵,旋轉(zhuǎn)操作開(kāi)始:設(shè)標(biāo)志m_LeftButtonDown為真,表示已經(jīng)處于旋轉(zhuǎn)狀態(tài);記下此時(shí)鼠標(biāo)指針的位置,放在m_LeftDownPos中,用來(lái)在鼠標(biāo)移動(dòng)事件中計(jì)算兩次鼠標(biāo)位置的移動(dòng)距離,從而計(jì)算出場(chǎng)景旋轉(zhuǎn)的尺度;將此時(shí)場(chǎng)景的顯示中心點(diǎn)記入m_CenterPoint中,將視點(diǎn)位置記入m_ViewPoint中。當(dāng)鼠標(biāo)移動(dòng)時(shí),旋轉(zhuǎn)功能類首先判斷鼠標(biāo)左鍵是否已按下,這可以根據(jù)m_LeftButtonDown的值來(lái)確定。若鼠標(biāo)左鍵未按下,則不做任何處理,否則,做如下工作:分別計(jì)算上次鼠標(biāo)位置與現(xiàn)在鼠標(biāo)位置在x,y方向的距離,根據(jù)這兩個(gè)距離計(jì)算場(chǎng)景應(yīng)旋轉(zhuǎn)的尺度,然后按照這個(gè)尺度將視圖原來(lái)的實(shí)現(xiàn)方向(視點(diǎn)減去參考點(diǎn)所得向量)進(jìn)行旋轉(zhuǎn),得到新的視線方向VP,并將視圖的視線方向修改為新的值。然后刷新視圖。當(dāng)視圖刷新時(shí),會(huì)根據(jù)視點(diǎn)、顯示中心點(diǎn)、視線方向等參數(shù)自動(dòng)調(diào)整場(chǎng)景的外觀。當(dāng)鼠標(biāo)左鍵抬起時(shí),表示旋轉(zhuǎn)動(dòng)作結(jié)束。旋轉(zhuǎn)功能類將標(biāo)志m_LeftButtonDown的值設(shè)置FALSE平移操作:OnLButtonDown(msg){ m_LeftButtonDown=TRUE; //確認(rèn)鼠標(biāo)左鍵是否已被按下。

oldCenterPoint=GetCenterPont();//中心點(diǎn)的位置

m_LeftDownPos=GetMouseLocation();//上次鼠標(biāo)移動(dòng)事件中鼠標(biāo)的位置}OnLButtonUp(msg){ m_LeftButtonDown=FALSE;}OnMouseMove(msg){ if(m_LeftButtonDown) {MouseLocation=GetMouseLocation(); oldPoint=GetWorldCrdByScreenCrd(m_LeftDownPos); newPoint=oldCenterPoint+(GetWorldCrdByScreenCrd(MouseLocation))-oldPoint; Invalidate(); }}設(shè)標(biāo)志m_LeftButtonDown為真,表示已經(jīng)處于旋轉(zhuǎn)狀態(tài);記下此時(shí)鼠標(biāo)指針的位置,放在m_LeftDownPos中,用來(lái)在鼠標(biāo)移動(dòng)事件中計(jì)算兩次鼠標(biāo)位置的移動(dòng)距離,從而計(jì)算出視圖平移的尺度;將此時(shí)場(chǎng)景的顯示中心點(diǎn)記入oldCenterPoint中當(dāng)鼠標(biāo)移動(dòng)時(shí),視圖平移功能類首先判斷鼠標(biāo)左鍵是否已按下,這可以根據(jù)m_LeftButtonDown的值來(lái)確定。若鼠標(biāo)左鍵按下,計(jì)算上次鼠標(biāo)位置對(duì)應(yīng)的世界坐標(biāo),計(jì)算本次鼠標(biāo)位置對(duì)應(yīng)的世界坐標(biāo),求得兩次鼠標(biāo)位置在世界坐標(biāo)系中的距離向量,將此向量加到場(chǎng)景的顯示中心點(diǎn)上,得到場(chǎng)景新的顯示中心點(diǎn)。最后刷新場(chǎng)景??s放操作OnLButtonDown(msg){ m_LeftButtonDown=TRUE; //確認(rèn)鼠標(biāo)左鍵是否已被按下。

m_LeftDownPos=GetMouseLocation();//上次鼠標(biāo)移動(dòng)事件中鼠標(biāo)的位置

oldWidth=GetCenterWidth();//縮放之前視口的寬度}OnLButtonUp(msg){ m_LeftButtonDown=FALSE;}OnMouseMove(msg){ if(m_LeftButtonDown) { dy=m_LeftDownPos.y-GetMouseLocation().y; ScalingFactor=dy/msg.GetView()->GetClientRect().bottom; newWidth=oldWidth*(1+ScalingFactor); SetViewWidth(newwidth); InvalidateRect(NULL,FALSE); }}5.3交互式的圖形生成技術(shù)

坐標(biāo)的輸入技術(shù)將二維計(jì)算機(jī)屏幕的鼠標(biāo)位置轉(zhuǎn)換為三維世界坐標(biāo)。

橡皮筋技術(shù)實(shí)現(xiàn)橡皮筋技術(shù)主要有兩種方法:基于異或操作的橡皮筋技術(shù);基于緩沖區(qū)的橡皮筋技術(shù);5.4交互式的圖形編輯技術(shù)利用鼠標(biāo)動(dòng)作來(lái)改變圖形選中圖形的方法5.4交互式的圖形編輯技術(shù)5.4交互式的圖形編輯技術(shù)圖形元素拾取辦法:靜態(tài)選擇功能類動(dòng)態(tài)選擇功能類5.4交互式的圖形編輯技術(shù)靜態(tài)選擇功能類偽代碼實(shí)現(xiàn):(1)構(gòu)造函數(shù)m_pElementSet=pElementSet;//接收外部提供的待選擇圖元集合m_pElement=pElement;//接受外部提供的預(yù)選取對(duì)象If(m_pElement!=NULL)SetSelectedElement(m_pElement)//將用戶指定的默認(rèn)選中元素賦給成員變量,并高亮顯示默認(rèn)被選中元素5.4交互式的圖形編輯技術(shù)(2)數(shù)據(jù)成員ElementSet*m_pElementSet;//圖形元素集合,將從這些圖元中挑出被選中者,放到m_pElement中Element*m_pElement;//將被選中的圖元放在這個(gè)成員變量中(3)鼠標(biāo)左鍵處理//利用某種機(jī)制從待選擇元素集合中選擇出鼠標(biāo)指向的圖形元素Element*pEI=GetElementFromSelection(m_pElementSet,GetMouseLocation());If(pEI==m_pSelectedElement)return;//恢復(fù)屏幕背景,然后高亮顯示被選中的元素。If(pEI!=NULL)SetSelectedElement(pEI);5.4交互式的圖形編輯技術(shù)動(dòng)態(tài)選擇功能類(1)數(shù)據(jù)成員ElementSet*m_pElementSet;//圖形元素集合,將從這些圖元中挑出被選中者,放到m_pElement中Element*m_pElement;//將被選中的圖元放在這個(gè)成員變量中(2)鼠標(biāo)移動(dòng)處理//利用某種機(jī)制從待選擇元素集合中選擇出鼠標(biāo)指向的圖形元素Element*pEI=GetElementFromSelection(m_pElementSet,GetMouseLocation());If(pEI==m_pSelectedElement)return;If(pEI!=NULL)SetSelectedElement(pEI);5.4交互式的圖形編輯技術(shù)5.5OpenGL對(duì)圖形交互的支持三維坐標(biāo)輸入--OpenGL提供反向坐標(biāo)變換(gluUnProject)實(shí)現(xiàn)橡皮筋技術(shù)--OpenGL的雙緩存機(jī)制三維圖形的編輯及三維目標(biāo)實(shí)體的拾?。璒penGL提供了一種簡(jiǎn)單直觀的選擇機(jī)制,能夠很容易的實(shí)現(xiàn)三維場(chǎng)景中任一圖形元素的選取。

5.5OpenGL對(duì)圖形交互的支持

用OpenGL的反向坐標(biāo)變換實(shí)現(xiàn)三維坐標(biāo)輸入

函數(shù)gluUnProject能夠?qū)indows屏幕坐標(biāo)轉(zhuǎn)換為場(chǎng)景中的三維世界坐標(biāo)。該函數(shù)需要指定如下參數(shù):視口的原點(diǎn)(X,Y坐標(biāo))及視口寬度(width)與高度(height)當(dāng)前顯示三維場(chǎng)景所使用的模型視圖變換矩陣(TheModelviewMatrix)當(dāng)前顯示三維場(chǎng)景所使用的投影變換矩陣(TheProjectionMatrix)Windows窗口坐標(biāo)存儲(chǔ)三維坐標(biāo)的變量(posX,posY,posZ)5.5OpenGL對(duì)圖形交互的支持視口信息:獲得視口左上角坐標(biāo)(x,y)和視口寬度

width及高度height Glintviewport[4];//存儲(chǔ)視口相關(guān)信息glGetIntegerv(GL_VIEWPORT,viewport);//檢索(x,y,width,height)調(diào)用成功后viewport數(shù)組四個(gè)元素將分別為x,y,width,height模型視圖變換矩陣:OpenGL圖元頂點(diǎn)的世界坐標(biāo)如何變換到視坐標(biāo)。

GLdoublemodelview[16];//存儲(chǔ)模型視圖變換矩陣的16個(gè)值

glGetDouble(GL_MODELVIEW_MATRIX,modelview) //檢索模型視圖矩陣5.5OpenGL對(duì)圖形交互的支持投影矩陣:將頂點(diǎn)的視坐標(biāo)變換為剪裁坐標(biāo)

GLdoubleprojection[16];//存儲(chǔ)投影矩陣的16個(gè)值

glGetDouble(GL_PROJECTION_MATRIX,projection) //檢索模型視圖矩陣

5.5OpenGL對(duì)圖形交互的支持Windows屏幕坐標(biāo):為要變換撐三維坐標(biāo)的數(shù)據(jù)來(lái)源,了解當(dāng)前鼠標(biāo)的位置CPointmouse;::GetCursorPos(&mouse);ScreenToClient(hWnd,&mouse);GLfloatwinX,winY,winZ;winX=(float)mouse.x;winY=(float)mouse.y;因?yàn)閃indows窗口(0,0)從左上角開(kāi)始,而OpenGL從左下角開(kāi)始,所以winY=(float)viewport[3]-winY;winZ:通過(guò)glReadPixel(winX,winY,1,1,GL_DEPTH_COMPONENT,GL_GLOAT,&winZ)得到5.5OpenGL對(duì)圖形交互的支持存儲(chǔ)三維坐標(biāo)的變量進(jìn)行方向坐標(biāo)變換實(shí)現(xiàn)三維坐標(biāo)輸入的完整子程序:Point3DGetOGLPos(intx

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論