2D动态绘图软体之设计与研究.docx
- 文档编号:6469747
- 上传时间:2023-01-06
- 格式:DOCX
- 页数:37
- 大小:79.37KB
2D动态绘图软体之设计与研究.docx
《2D动态绘图软体之设计与研究.docx》由会员分享,可在线阅读,更多相关《2D动态绘图软体之设计与研究.docx(37页珍藏版)》请在冰豆网上搜索。
2D动态绘图软体之设计与研究
2D動態繪圖軟體之設計與研究
研究學生:
陳可嘉熊家媛
指導老師:
陳怡芬老師
1、研究動機:
在尋找研究題目前,我們曾接觸過一個名為GSP的動態幾何數學遠距教學軟體。
該軟體有兩個地方非常吸引我們,一為其操控方便的視窗界面,具備了特殊的工具按鈕,能使使用者在操作上獲得簡潔而有系統的便利感;二為在圖形操控上,能精準且動態地呈現圖形的變化。
由此中我們對於這樣控制圖形的方式感到好奇,要如何使圖形與各操縱項間(如:
數據輸入、滑鼠控制等方式。
)取得密切而流暢的聯繫?
這是我們想要瞭解的。
以此為目的出發,我們尋找了同樣具有幾何關係性質的物理光學領域,其中考慮初期研究的能力與圖形元件的單純性,我們選擇以幾何光學中透鏡及面鏡成像的實驗呈現為研究的方式。
再說到目前在幾何光學這部份的教學具體呈現上,往往因為教學硬體設備的種種限制而不能達到適當、良好的效果:
學校老師們在黑板上解釋面鏡透鏡成像時通常只能粗略地畫出光線的路徑,若要解釋透鏡、面鏡的曲率與光線行進路線的關係,就更顯麻煩、困難了:
一來是由於在黑板上精確而快速的作圖實在不易,二來無法呈現光線、鏡面在變化期間的完整過程,失去了對照的效果與切實的具體感。
利用實物實驗或許可解決這方面的困擾,但畢竟實驗器材的準備在現今所有校園中未必可普及,要有精確而多量的儀器亦須耗費不小,只由教師操作的示範實驗更難以達到讓學生清楚觀察並親身體驗的功效。
在這樣的情況下,若能有一個如前述的幾何光學教學軟體,不但能做到精準且簡單明瞭的具體呈現,使學習者一目了然,更能讓使用者在自學時便利地針對自己所需要了解的地方加強學習印象。
綜合以上所述,我們在研究時,主要著重於圖形操縱的流暢度及使用介面的自主性、便利性。
2、研究目的:
討論以數據控制圖形變化的方法,研究物件(如圖形)間的關係。
並與使用者建立互動良好界面。
3、研究設備與器材:
硬體方面:
個人電腦
軟體方面(程式語言):
TurboC2.0版
VisualC++5.0版
我們最後呈現的視窗軟體,是用MicrosoftVisualC++5.0製作出來的。
由於視窗軟體的複雜及具備多元的視窗資源(如圖示、選單、工具按鈕、對話盒等),我們需要像VC++這樣的整合程式開發環境,即所謂IDE(IntegratedDevelopmentEnvironment)。
它包含了程式編輯器、編譯器、連結器,以及強大的函式庫,利於編寫視窗程式;此外,VisualC++具備不少提供繪圖功能的函式與資源檔,是用來製作「小畫家」軟體的語言,也與我們要進行有關動態繪圖方面研究的需求相符合。
雖然VisualC++有功能強大的精靈工具,包括AppWizard與ClassWizard,可以產生基本程式架構的許多程式碼。
不過由於我們在視窗程式設計方面還是新手,為了透徹這種陌生的程式語言架構,我們除了在比較必要的部份,如對話盒的產生之外,幾乎沒有使用此項工具,而是以堆砌的方式建構起整個視窗程式。
也許留待以後進一步改良這軟體或開發新軟體時再來嘗試吧。
也因為對VC++較感陌生,而且為使編輯程式後的除錯方便,儘可能免除繪圖部份邏輯錯誤的產生,我們也利用從事專題研究之前以接觸過、較為熟習的TurboC語言先行撰寫一些基本的圖形,如薄球面或拋物面透鏡、面鏡的形狀、光線的路徑等。
雖然TC與VC++兩者在使用者操控、輸入及輸出到裝置的模式,以及整體程式的架構上,都有著很大的不同,不過就一些基本的繪圖函數上,它們之間有不少是十分相似的。
加上C與C++在語法、觀念上本就有許多相關的親緣關係,於是我們也利用TC作為研究繪圖方面的輔助工具。
4、研究內容:
1.相關知識學習︰
A.物件導向之程式設計概念:
Windows程式設計十分繁雜,它要能在任何時間內處理任何形態的輸入,而且它不能直接存取硬體資源,只能經由Windows的功能來存取輸入、輸出設備,在這樣的情況下,物件導向的方法是必要的,它提供了重要的「類別繼承」觀念、方法,算是對類似模式的「刺激」,做出相同形態的「反應」的一種有效率的發法,而完全由「刺激」來考慮「反應」的思路及程式結構,則是物件導向的重要精神。
B.相關物理知識:
面鏡部份,知凹面鏡聚光、凸面鏡散光,若是拋物面鏡則在凹面處有一焦點,聚光能力強,但製造不易;若為球面鏡則有像差,但若鏡面口徑小,則球面鏡與拋物面鏡幾乎無異。
(我們在寫程式時,雖也有描繪過拋物面鏡的形狀,不過最終考慮程式簡潔與符合日常情況,仍以口徑小的球面鏡作為模型。
)
成像主要公式:
r﹦2f
(r為球面鏡之半徑;f為其焦距)
透鏡折射部份,有許多與面鏡相似,惟要考慮透鏡折射問題,將折射率納入公式後:
r﹦2f﹡(n-1)
(n為透鏡相對於折射率為一的空氣折射率)
2.問題探討︰
如在目的及研究動機裡所說的,我們希望能建立一個能動態控制圖形,各物件間也具有互動關連的視窗軟體,並使之同時擁有與使用者溝通良好的操作系統。
A.如何設計介面?
a.在功能表列部分:
大致上我們的軟體介面在系統操控部分,與一般的應用軟體相同,但加入了一些特殊的原件,在這裡只列舉其中與其他軟體不同的部分。
i.在Display選單中,有:
Line設定線條樣式
Color設定顏色
Text設定字形樣式
ShowLable顯示標籤
Relable訂正標籤
●「標籤」是讓使用者自己為畫面上各個物件命名,方便下指令以及辨認的工具
Trace顯示光線行進軌跡:
可選擇顯示少數代表性的光線軌跡,或是大量顯示光線軌跡,以達真實感。
Preferences屬性:
更改其他物件屬性
ii.在Construct選單中,有:
透鏡可選擇凸透鏡、凹透鏡
面鏡可選擇凸面鏡、凹面鏡、或是平面鏡
光源可選擇點光源或是平行光源
iii.在Transform選單中,有:
Translate平移:
出現對話盒,設定選取物件之平移狀態
Dilate縮放:
出現對話盒,設定選取物件之縮放狀態
DefineTransform定義變換:
結合兩種以上之變換
iv.而點選Set選單,則代表動態動作開始執行。
b.在工具列部分,依需求設計了:
透鏡、面鏡、平行光源、點光源、說明、標籤之工具按鈕。
點選後,前四者均直接出現預設之形狀原件,後二者則顯示對話盒。
譬如,在點選透鏡工具按鈕後,就出現預設的凸透鏡,並連帶的出現水平軸,之後相關的其他原件被選取時,就依著這水平軸出現在畫面上;如圖:
當然也可以先選擇光源,則此時出現預設的平行光源,縱貫整個畫面,同時也出現水平軸,待透鏡或面鏡被點選後,也就隨其改變樣貌了。
B.如何匯出圖形?
在我們參考的許多書中,對於應用程式的圖形處理流程大致是這樣的結構:
建立shape類別為形狀類別的基礎類別
{定義形狀物件的起點和終點
建構子設定初始值
運算子設定起點和終點
複製建構子
過載=運算子
宣告虛擬函數shape:
:
draw
GetShapenum()取得形狀代號
SetPoint()設定形狀的起點和終點
}
類別繼承
建立繪圖類別
{預設建構子,設定形狀代號
建構子設定起點和終點
複製建構子
過載=運算子
宣告虛擬函數draw
{建立畫筆物件\設定DC物件使用pen物件﹒﹒﹒
dc.繪出圖形函式,繪出圖形
還原畫筆物件
}
afx_msgvoid回應按鈕產生形狀物件
afx_msgvoid回應視窗重繪函數
{
取得目前Document物件
取得Document中形狀物件的個數
呼叫Cview中的OnDraw成員函數
判別從Document物件中取得哪種形狀物件
建立適當形狀物件
建立形狀物件的起點和終點
}
MyView:
:
形狀物件被選擇(工具按鈕資源被按下)的回應函數
{產生形狀物件}
當滑鼠按下:
取得滑鼠訊息接收權
判斷是否在執行的視窗中
若是,則設定形狀物件的起點、終點
當滑鼠被放開:
判斷是否在執行的視窗中若是則:
建立畫布、
設定終點、
畫出形狀物件
儲存繪出的形狀物件
釋放滑鼠訊息接收權
當滑鼠移動:
判斷是否在執行視窗中
若是則:
建立畫布、
畫出形狀物件、
設定終點、
再畫出形狀物件
這也是VC++作為視窗繪圖軟體最常見的結構(如小畫家)
不過我們的軟體需求與這樣的架構並不盡相同,其相異處如下:
(1)我們在選擇了形狀物件的同時就需要它顯示出圖形(如凸透鏡、凹面鏡等)。
(2)在我們的繪圖函式中並不使用如上程式中的矩形繪圖機制,所以不需要設定起始點和終點,而只需要一個引數,也就是滑鼠所在的那點。
(3)在這個程式中最重要的就是圖形的動態功能,就一方面來說也就是圖形要能不斷接受滑鼠的訊息而改變。
所以只要滑鼠在圖形的偵測範圍,我們就必須給予滑鼠訊息接收權,而不同於上述程式中,一旦形狀物件繪出完成後就釋放接收權。
因應以上的理由,我們嘗試自己以一般軟體的通用繪圖模式為基礎,建構符合我們需求的繪圖模式。
結構如下:
法一:
建立shape類別為形狀類別的基礎類別
<使Shape類別繼承自含繪圖成員函式的CDC
類別>
{定義形狀物件的起點和終點
<加入新的建構子成員(因為繪製透鏡的類
別較繪製一般幾何圖形的所需引入的參數為
多)>
<加入建構子的預設值>
建構子設定初始值
運算子設定起點和終點
複製建構子
過載=運算子
宣告虛擬函數shape:
:
draw
GetShapenum()取得形狀代號
SetPoint()設定形狀(起點和終點)<<參考點>>
}
類別繼承
建立繪圖類別
{預設建構子,設定形狀代號
建構子設定起點和終點
<依形狀物件不同個別加入建構子成員>
複製建構子
過載=運算子
宣告虛擬函數draw
{建立畫筆物件\設定DC物件使用pen物件﹒﹒﹒
dc.繪出圖形函式,繪圖形
<<在這裡利用OnDraw函數,及MoveTo()、
Line組合繪出初始形;)…組合繪出初始圖形>>
【NOTE1】
還原畫筆物件
}
afx_msgvoid回應按鈕產生形狀物件{}
afx_msgvoid回應視窗重繪函數
{
取得目前Document物件
取得Document中形狀物件的個數
呼叫Cview中的OnDraw成員函數
判別從Document物件中取得哪種形狀物件
建立適當狀物件
建立形狀物件(起點和終點)<<參考點>>
}
MyView:
:
形狀物件被選擇(工具按鈕資源被按下)的回應函數
{產生形狀物件}
當滑鼠按下:
取得滑鼠訊息接收權
(判斷是否在執行的視窗中)<<判斷是否在執行的範圍內>>【Note2】
若是,則設定形狀物件的(起點、終點)參考點
當滑鼠移動:
判斷是否在(執行視窗)中<<執行範圍內>>
若是則:
建立畫布、
畫出形狀物件、
設定終點(即參考點)、
再畫出形狀物件
當滑鼠被放開:
判斷是否在(執行的視窗)中<<執行範圍內>>若是則:
建立畫布、
設定終點(參考點)、
畫出形狀物件
儲存繪出的形狀物件
釋放滑鼠訊息接收權
【Note1】︰
這是我們研究的主要部份之一,由於VC++的繪圖函數中所需引入的參數,其數學幾何意義並不強,它們多是利用虛擬外界矩形的內界圖形模式繪出基礎形狀物件,而非如C語言的引入具體的圓心座標、半徑長度,以一般直觀的方式繪出圖形,所以在我們這樣需要許多數學幾何方面計算、繪圖的程式中,這是一個蠻麻煩的困難之處,因為在利用其繪圖函數之前都得先行將在座標平面計算的結果轉換運算出在VC++繪圖函式中的引數,以將它繪出。
【Note2】︰
判斷範圍改為一個虛擬的矩形方框,圍繞在初始產生的形狀物件周圍,當滑鼠指到這個範圍內,便給予滑鼠訊息接收權,待滑鼠按下後,接收滑鼠訊息,載入,繪圖。
以上的方法在第一次顯示圖形時,是依據Shape類別中的建構子預設值來產生的。
但我們實際上在撰寫程式碼時,系統並不接受非數據型態的預設值入。
所以沒有辦法在這樣的方式下執行程式。
因此我們在初次顯示圖形的方面採取了另一種方式:
法二:
先設定限制圖形輸出的許可範圍,即讓使用者只能在一定的範圍內任意初始圖形,再搭配「復原」圖形輸出的許可範圍,即讓使用者只能在一定的範圍內任意初始圖形,再搭配「復原」的功能讓使用者將所要的圖形修改至滿意。
當形狀物件被選擇時,傳入形狀物件代號給Shape類別。
因為在這個繪圖機制中,我們並非讓使用者在選擇了形狀物件時就產生圖形,而是要在選擇形狀物件後,再以拖曳的方式匯出圖形,所以在Shape類別及各個形狀物件的類別中都不給定預設值,而以使用者滑鼠點下的那一點作為StartPnt,滑鼠拖曳停止放開的點作為EndPnt,以此二點決定的矩形,就是我們要繪出的物件(如凸透鏡)的虛擬外界矩形,從這個外界矩形可推知所要繪出圖形需要引入的參數,將圖形畫出。
由外界矩形推算我們要畫的透鏡線條是有點麻煩的,因為VC++在畫圓弧線時用的函數為BOOLArc(intx1,inty1,intx2,inty2,intx3,inty3,intx4,inty4),這八個數一對對構成了四個座標,依序是決定圓弧外界矩形的兩個座標,以及決定圓弧起點、終點的兩個座標,大大地不同於Tc中用來繪製圓弧的函示只需引入圓弧曲率半徑以及曲率中心的模式。
後者的數學性質較強,也較容易做推算的工作,但在VC++的模式下,由外界矩形來推得圓弧的座標計算式十分冗長,而且還會牽涉到數值型態轉換的問題。
不過這些都是可以克服的。
這個方法在偵測語法錯誤方面都沒有問題,但在執行繪圖動作時卻會造成程式異常終止,應是邏輯方面的錯誤,較有可能是在繁雜的指標系統中出了問題。
法三:
我們也試過用比較直接的方式撰寫程式。
從比較基礎的觀點說來,VC++繪圖機制中的OnDraw()函數,也就是之前所述流程中用來執行視窗重繪的函數,可以用來呼叫其他繪圖的基本函數們,直接地輸出基本圖形,如點、線、橢圓、弧線等到使用者的工作區。
大致的想法是先讓形狀物件類別的母類別:
Shape繼承自CDC類別(VC++的圖形裝置介面類別)使其具有繪圖的能力,然後在Shape的建構子中給定所需引入參數的預設值,再在Shape類別中放入OnDraw()函數,在OnDraw()中撰寫所需的形狀線條的程式碼即可。
但問題就在對於整個應用程式架構而言,OnDraw擔負著重要的視窗重繪工作,也就是我們所希望寫出的軟體中十分重要的「動態」部分,在龐大的軟體架構中,OnDraw()並無法如此身兼二職,而且想在OnDraw()中利用那些繪圖函式,必須引入許多的預設值,在VC++中預設值的引入非得寫類別建構子的地方不可,但我們又無法在這麼繁複的結構中為這些預設值找到安身立命之所,因為難以建立OnDraw函式與適於安置這些預設值的類別的直接關係的緣故。
於是此法就被放棄了。
C.操作程序
使用者在初始好一個完整的畫面(包括透鏡或面鏡、以及光源的基本原件)後,就可以開始進行調整的動作,這些調整的動作有兩種方式可以來進行:
利用滑鼠:
使用者用滑鼠移到原件(如一個凸透鏡)上時,則凸透鏡周圍出現一個外框,提示使用者拖曳;在拖曳的過程中,透鏡的曲率隨之改變,通過此透鏡的光線行進路徑也跟著改變。
至使用者將滑鼠放開為止。
對於點光源,使用者也可以以拖曳的方式讓他在水平軸上移動,並觀察光線折射、反射的結果。
利用數據控制:
在原件上用滑鼠點兩下,則出現此原件之屬性控制對話盒,譬如在一個凹透鏡上點兩下,就可以輸入數據,設定其曲率、折射率等的屬性,對於其他原件亦然。
5、結果︰
下圖為軟體界面︰
多文件視窗樣式︰
自訂的資源檔︰(工具按鈕)
6、結論:
在為期一整學年的學習與摸索探討結束後,獲得的收穫不只是以上所呈現的。
在程式設計上我們失敗了,並沒有達到我們所冀望的目的,甚而是在很初期的圖形匯出部分就未能突破程式的限制,以致於無法繼續我們的研究,而我們花了很多心血和腦力所設計規劃的軟體架構,包括介面、對話框與控制項的配合運用等,都未能將之透過這樣的程式加以呈現。
但在這樣思考程式和軟體架構的過程中我們藉以學習到了「物件導向」的觀念,以及在VisualC++的視窗產生機制中,物件的觀念是如何被複雜而且靈活的運用,各類別與物件它們之間的獨立又互相牽連的關係,這些是在其他程式語言中所未有接觸過的,是我們此次最大的收穫。
另一方面也由不斷嘗試錯誤中,了解到VisualC++也許並不適合用來製作運用圖形方面的視窗軟體。
它所具備的繪圖原件非常少,而且在繪圖函數中更是以運用外界矩形的方法來繪出所有基礎形狀物件的,對於我們要做的如此充滿數學計算性質的軟體並不適合。
我們的失敗也許是由於沒找到適合的程式語言,以及因此而缺乏詢問的對象(VisualC++在一般的運用和使用情形並不廣泛),畢竟研究本來就是需要通的人曉指導。
這樣的經驗我們將它記錄下來,作為以後要研究相關領域的學妹參考。
7、參考資料及其他:
參考資料:
精通視窗程式設計作者:
郭尚均
出版社:
文魁資訊股份有限公司
出版日期:
BeginningVisualC++6(中譯:
VisualC++6教學手冊)
作者:
IvorHorton譯者:
蔡明志
出版社:
碁峰出版社
出版日期:
MasteringC++6(中譯:
精通VisualC++6──GUI設計基礎篇)
作者:
MichaelJ.Young譯者:
張苑蓉出版社:
儒林圖書有限公司出版日期:
1999年7月
VisualC++入門進階(物件導向到視窗程式設計)
編著:
位元文化
出版社:
文魁資訊股份有限公司
出版日期:
1999年3月
幾何光學作者:
吳文政
出版社:
建宏出版社
出版日期:
1998年7月
8、感謝:
感謝陳怡芬老師在我們研究的過程給予技術和想法上的支援;另外感謝家長在漫長的過程中給予的支持。
特別謝謝北一女特教組的老師對我們的愚蠢的容忍及寬容。
9、附錄:
程式碼
*以下程式碼是根據討論二:
如何匯出圖形之法一而寫成
#include
#include"resource.h"
#include
#include
classGraphicObject:
publicCObject
{//儲存形狀物件的類別,衍生自CObject類別以便具備儲存(Serialize)功能
public:
intshapenum;//形狀代號
BOOLfill;//是否填滿
COLORREFFillColor,LineColor;//填滿顏色與外框顏色
intwidth;//外框寬度
CPointStartPnt,EndPnt;//形狀的起點與終點
GraphicObject(){}//預設建構子
//一般建構子
GraphicObject(intshapenum,BOOLfill,COLORREFFillColor,
COLORREFLineColor,intwidth,CPointStartPnt,CPointEndPnt)
:
shapenum(shapenum),fill(fill),FillColor(FillColor)
LineColor(LineColor),width(width),StartPnt(StartPnt),
EndPnt(EndPnt){}
GraphicObject(GraphicObject&g)//複製建構子
:
shapenum(g.shapenum),fill(g.fill),FillColor(g.FillColor),
LineColor(g.LineColor),width(g.width),StartPnt(g.StartPnt),
EndPnt(g.EndPnt){}
//過載=運算子
GraphicObject&operator=(GraphicObject&g){
shapenum=g.shapenum;
fill=g.fill;
FillColor=g.FillColor;
LineColor=g.LineColor;
width=g.width;
StartPnt=g.StartPnt;
EndPnt=g.EndPnt;
return*this;
}
//GraphicObejct:
:
Serialize
voidSerialize(CArchive&ar)
{
CObject:
:
Serialize(ar);
if(ar.IsStoring())//判斷是否為存檔
{//輸出至檔案
ar< < } else {//從檔案輸入 ar>>shapenum>>fill>>FillColor>>LineColor >>width>>StartPnt>>EndPnt; } } DECLARE_SERIAL(GraphicObject)//宣告為可Serialize的類別 }; //宣告GraphicObject為可Serialize的類別 IMPLEMENT_SERIAL(GraphicObject,CObject,1) classShape: publicCDC//形狀類別的基礎類別 { protected: CPointStartPnt,EndPnt;//定義形狀的終點與起點 intshapenum;//形狀代號 friendclassMyView;//將MyView設為friend類別,方便資料存取 public: //建構子 Shape(CPointStartPnt,CPointEndPnt,intshapenum) : StartPnt(StartPnt),EndPnt(EndPnt),shapenum(shapenum){} //複製建構子 Shape(Shape&s) : StartPnt(s.StartPnt),EndPnt(s.EndPnt),shapenum(s.shapenum){} Shape(){} //過載=運算子 Shape&operator=(Shape&s) { StartPnt=s.StartPnt;//設定起點 EndPnt=s.EndPnt;//設定終點
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 动态 绘图 软体 设计 研究