當(dāng)前位置: 首頁編程開發(fā)VC(VC++) → 用鼠標(biāo)和貝塞爾曲線交互

用鼠標(biāo)和貝塞爾曲線交互

更多

貝塞爾曲線(The Bézier Curves),是一種在計(jì)算機(jī)圖形學(xué)中相當(dāng)重要的參數(shù)曲線(2D,3D的稱為曲面)。貝塞爾曲線于1962年,由法國工程師皮埃爾·貝塞爾(Pierre Bézier)所發(fā)表,他運(yùn)用貝塞爾曲線來為汽車的主體進(jìn)行設(shè)計(jì)。

線性曲線
給定點(diǎn)P0、P1,線性貝塞爾曲線只是一條兩點(diǎn)之間的直線。這條線由下式給出:

當(dāng)參數(shù)t變化時,其過程如下:

線性貝塞爾曲線函數(shù)中的t會經(jīng)過由P0至P1的B(t)所描述的曲線。例如當(dāng)t=0.25時,B(t)即一條由點(diǎn)P0至P1路徑的四分之一處。就像由0至1的連續(xù)t,B(t)描述一條由P0至P1的直線。
二次曲線
二次方貝塞爾曲線的路徑由給定點(diǎn)P0、P1、P2的函數(shù)B(t)追蹤:

為建構(gòu)二次貝塞爾曲線,可以中介點(diǎn)Q0和Q1作為由0至1的t:
* 由P0至P1的連續(xù)點(diǎn)Q0,描述一條線性貝塞爾曲線。
* 由P1至P2的連續(xù)點(diǎn)Q1,描述一條線性貝塞爾曲線。
* 由Q0至Q1的連續(xù)點(diǎn)B(t),描述一條二次貝塞爾曲線。
二次曲線看起來就是這樣的:

三次曲線
為建構(gòu)高階曲線,便需要相應(yīng)更多的中介點(diǎn)。對于三次曲線,可由線性貝塞爾曲線描述的中介點(diǎn)Q0、Q1、Q2,和由二次曲線描述的點(diǎn)R0、R1所建構(gòu)。
P0、P1、P2、P3四個點(diǎn)在平面或在三維空間中定義了三次方貝塞爾曲線。曲線起始于P0走向P1,并從P2的方向來到P3。一般不會經(jīng)過P1或P2;這兩個點(diǎn)只是在那里提供方向資訊。P0和P1之間的間距,決定了曲線在轉(zhuǎn)而趨進(jìn)P3之前,走向P2方向的“長度有多長”。
曲線的參數(shù)形式為:

看起來就是這樣的:

高階曲線
更高階的貝塞爾曲線,可以用以下公式表示:
表示由點(diǎn)P0、P1、…、Pn所決定的貝塞爾曲線。則有:

更多的關(guān)于貝塞爾曲線的內(nèi)容,你可以去查閱各種數(shù)學(xué)書。加油,求知的騷年。
應(yīng)用
在幾乎所有的高級圖像軟件中,均使用到了三次貝塞爾曲線來實(shí)現(xiàn)“平滑曲線”繪制功能。例如photoshop中的“鋼筆”,CoralDraw中的“貝塞爾工具”,F(xiàn)ireworks中的“畫筆”。

在編程中實(shí)現(xiàn)
計(jì)算機(jī)繪圖
要“畫”出貝塞爾曲線,一般需要進(jìn)行較多的計(jì)算,然后繪制出來,類似這樣:

繪制的代碼可以在各類計(jì)算機(jī)圖形學(xué)書籍中找到。
GDI+
幸運(yùn)的是,GDI+已經(jīng)封裝好了貝塞爾曲線的繪制代碼,如果你想畫出貝塞爾曲線,只用調(diào)用Graphics.DrawBezier方法:

這是一個三次貝塞爾曲線,其中4個點(diǎn)分別為:起點(diǎn),起點(diǎn)控制點(diǎn),終點(diǎn),終點(diǎn)控制點(diǎn)。繪制出來的效果如下:

與鼠標(biāo)的交互
怎么實(shí)現(xiàn)Photoshop里那樣可以調(diào)整的貝塞爾曲線呢?兩種方法:
* 輸入新參數(shù)生成曲線
* 用鼠標(biāo)交互調(diào)整曲線
很顯然第二種看起來會拉風(fēng)很多,那么就來試試看。
你想要獲得是這樣的效果:

這是一條三次貝塞爾曲線,圖中應(yīng)該這樣解讀:

所以需要幾個需要解決的:
* 表示貝塞爾曲線的錨點(diǎn)和控制點(diǎn)
* 繪制曲線和控制點(diǎn)/控制柄
* 鼠標(biāo)交互
看起來不是很難的樣子,那么就來化整為零,各個擊破吧。
錨點(diǎn)
對于三次貝塞爾曲線而言,有兩個錨點(diǎn):起始點(diǎn)和結(jié)束點(diǎn)。每個錨點(diǎn)有兩個坐標(biāo):本身坐標(biāo)和控制點(diǎn)坐標(biāo)。于是,可以用這樣的類來描述:

三次貝塞爾曲線
三次曲線前面已經(jīng)說過原理了,那么它的結(jié)構(gòu)應(yīng)該就是這樣的:

畫出來
為了簡單,就用一個最基本的渲染器來畫,代碼如下:

畫出曲線和控制點(diǎn)及其手柄:


畫出來的效果就是這樣的:

鼠標(biāo)交互
和鼠標(biāo)實(shí)際上是這樣交互的:
* 按下鼠標(biāo),如果落點(diǎn)在某個控制點(diǎn)上,就表示選中了該點(diǎn),否則落空
* 移動鼠標(biāo),如果選中了某個控制點(diǎn),則調(diào)整控制點(diǎn)坐標(biāo)至新坐標(biāo),否則忽略
* 放開鼠標(biāo),取消任何選擇
看起來只需要處理MouseDown,MouseMove和MouseUp這三個事件就夠了,很容易嘛。
先弄一個全局標(biāo)記:

然后處理鼠標(biāo)事件:
MouseDown:

MouseMove:

MouseUp:

為了簡單,刷新就這么弄了:

更高效的刷新應(yīng)該只處理臟區(qū)。
效果
最后看起來就像這樣。

就這么簡單。

擴(kuò)展和優(yōu)化
要實(shí)現(xiàn)Photoshop那種曲線效果,需要多個錨點(diǎn)連接起來。上面的方法在效率上也還有可以提高的地方。

熱門評論
最新評論
發(fā)表評論 查看所有評論(0)
昵稱:
表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
字?jǐn)?shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)