最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

【Aegisub】貝塞爾曲線偏移簡(jiǎn)單介紹、繪圖(含曲線)轉(zhuǎn)邊框簡(jiǎn)單介紹

2022-05-02 17:59 作者:多華宮與火火里  | 我要投稿

????????之前講過如何將全直線繪圖轉(zhuǎn)邊框(以及斷裂邊框自定義起點(diǎn)終點(diǎn)的轉(zhuǎn)邊框),后面還講過得到簡(jiǎn)化的全直線邊框(即沒有路徑自交也沒有多余路徑),但是直接將帶有曲線路徑的繪圖轉(zhuǎn)邊框也是有意義的,比如文本量更小、看起來可能更光滑之類的。

????????一般來說,一條三階貝塞爾曲線的等距偏移曲線不會(huì)是一條三階貝塞爾曲線

曲線的"好看"偏移

有的三階貝塞爾曲線是可以直接把它的控制多邊形頂點(diǎn)給等距偏移,然后得到它近似的偏移曲線的,比如圖1.01的曲線得到圖1.02的邊框

圖1.01

圖1.01的繪圖代碼是m 0 0 b 10 -8 32 -10 50 -5?

圖1.02

圖1.02的繪圖代碼是m -4 -5 b 8 -14 33 -16 52 -11 l 48 1 b 31 -4 12 -2 4 5?

放在一起看,得到了圖1.03

圖1.03

其實(shí)基本上來說,此時(shí)就僅僅是把原本曲線的控制多邊形頂點(diǎn)給等距偏移了,然后就得到了相應(yīng)的偏移曲線,如圖1.04

圖1.04

可是,當(dāng)你曲線有曲率很大的點(diǎn)時(shí)就不能這樣做,當(dāng)你設(shè)定的偏移值比你曲線某點(diǎn)的曲率半徑要大的時(shí)候,直接偏移曲線的控制多邊形頂點(diǎn)是得不到比較理想的曲線的,如圖1.05

圖1.05

偏移得到圖1.06,放一起就是圖1.07

圖1.06(顯然有兩條偏移曲線、分別在原本曲線的兩側(cè))
圖1.07

顯然,雖然控制多邊形的頂點(diǎn)是等距偏移的,但是得到的曲線卻不是等距的。這就是因?yàn)樵厩€在比如 t 處的曲率半徑比偏移數(shù)值小了,如圖1.08

圖1.08

眾所周知,曲線在某處看起來越彎曲,那么這點(diǎn)的曲率就越大、曲率半徑就越?。磺€在某處看起來越平,那么這里的曲率就小、曲率半徑就越大(因?yàn)榍拾霃绞乔史种?。顯然,一般的曲線每點(diǎn)的曲率是不一樣的(圓的每一點(diǎn)的曲率都一樣,且曲率半徑就是圓的半徑)。那么你想想看,比如你希望曲線偏移6,但是你曲線上某點(diǎn)的曲率半徑是2,那你直接偏移控制多邊形的頂點(diǎn)很尷尬吧?

????????正如一開始說的,一般的三階貝塞爾曲線的偏移曲線根本不是三階貝塞爾曲線,所以你想用區(qū)區(qū)一條曲線就表示原本曲線的偏移曲線是不可能的。所以什么意思呢,就是說,三階貝塞爾曲線的偏移曲線(經(jīng)常)需要由多條三階貝塞爾曲線構(gòu)成。也就是,將原本的曲線拆分為多條曲線,然后偏移這一條條的曲線即可。

????????關(guān)于三階貝塞爾曲線的偏移,我參考了一個(gè)js寫的bezier庫以及c++寫的qt庫。用js的那個(gè)庫叫啥忘了,但是它用的方法我覺得不算太好,它有求一階導(dǎo)二階導(dǎo),然后甚至從開始一點(diǎn)點(diǎn)的檢查曲線上的點(diǎn)(從0.01到0.99、每次加0.01好像是),用這種方法拆分曲線,計(jì)算量總之不算特別小、而且拆出來的曲線條數(shù)比較多,而qt庫呢它使用的方法就計(jì)算量小不少、且拆出來的曲線條數(shù)一般比較少,我大概根據(jù)qt庫的算法寫了一個(gè)貝塞爾曲線偏移的代碼(不完全一樣)

????????另外,qt庫的轉(zhuǎn)邊框在某些時(shí)候會(huì)有奇怪的錯(cuò)誤,它的端點(diǎn)會(huì)添加錯(cuò)誤,當(dāng)然我自己寫就至少可以避免這種錯(cuò)誤。如圖1.09是原本的曲線,qt庫(A3shape)轉(zhuǎn)邊框得到圖1.10

圖1.09(繪圖代碼是m 0 0 b 4 -17 31 -6 31 -6 )
圖1.10(原曲線和轉(zhuǎn)的邊框一起看的,顯然中間那個(gè)就是原本的曲線)

用我自己寫的轉(zhuǎn)邊框就會(huì)得到圖1.11

圖1.11(原曲線和轉(zhuǎn)的邊框一起看的,顯然中間那個(gè)就是原本的曲線)

????????然后簡(jiǎn)單介紹一下三階貝塞爾曲線偏移的算法,粗略介紹一下,反正我知道這些東西壓根沒幾人會(huì)看并且看完的(有不知道有Yutils教程的,我記得我兩年多以前就出了Yutils的視頻,講了常用的那些函數(shù)怎么用以后,我就開始教的如何自己寫插件自己寫函數(shù)庫,也沒幾人看沒幾人知道),不想學(xué)多簡(jiǎn)單,那我少講點(diǎn)

????????首先,一條曲線設(shè)定最多拆分為16條曲線,用一次次的遞歸來拆分曲線,當(dāng)然并不是所有的情況下都要拆分曲線的,有的不需要拆分。所以對(duì)于一條曲線A,先偏移它的控制多邊形頂點(diǎn),得到新的曲線B,檢查 t 為0.25、0.5、0.75時(shí)的情況,比如檢查在 t 時(shí),A曲線上的這一點(diǎn)和B曲線上的這一點(diǎn)的距離和你設(shè)定的偏移值的相差大不大之類的,如果滿足一定條件,就在相應(yīng)的 t 處將曲線拆分,然后同樣的,拆分出的曲線也要一樣的檢查,比如 t 在0.25、0.5、0.75時(shí)的情況,然后看拆分不拆分之類的,也就是遞歸嘛,這樣下去,但是要設(shè)定原本的曲線最多被拆為16條曲線,就是說遞歸拆分曲線,如果已經(jīng)拆出了16條,那么就不會(huì)繼續(xù)不停地遞歸了。還有就是添加圓弧,就是有的時(shí)候偏移數(shù)值太大,那么偏移曲線就會(huì)加相應(yīng)的圓弧,比如你曲線的邊界框bbox高寬不超過10、但是你希望這個(gè)曲線偏移23333,那你這個(gè)偏移值也太大了吧,此時(shí)就會(huì)做圓弧了,比如圖1.12這樣一條曲線

圖1.12

圖1.12的繪圖代碼為m 0 0 b 2 0 2 -1 1 1?

顯然,這曲線非常小,但是你要忍一下?,F(xiàn)在轉(zhuǎn)邊框、讓偏移值為210,就得到圖1.13

圖1.13

偏移值很大,你要忍一下

顯然,偏移值太大的時(shí)候,就會(huì)做圓弧了,比如可以設(shè)定曲線的bbox的寬高都小于偏移值的0.1時(shí),判斷一下需不需要加圓弧,如果滿足相應(yīng)的條件就加、不滿足就不加

????????然后,一條曲線就可以偏移了,那么轉(zhuǎn)邊框當(dāng)然就是要得到兩條(組)偏移曲線了(原本曲線兩側(cè)各需要一組偏移曲線),比如圖1.14的曲線轉(zhuǎn)邊框得到圖1.15(圖1.15里含有原本曲線,方便觀察)

圖1.14
圖1.15

顯然,原本的曲線就被拆為了幾段,然后這幾段就分別偏移它們的控制多邊形頂點(diǎn),然后就有了相應(yīng)的偏移曲線了,當(dāng)然現(xiàn)在這里轉(zhuǎn)邊框是加了端點(diǎn)的,不加端點(diǎn)就會(huì)得到圖1.16

圖1.16

當(dāng)然不加端點(diǎn)也是正確的偏移,只是作為轉(zhuǎn)邊框來說,至少加上端點(diǎn)會(huì)好看些。那么你也設(shè)定端點(diǎn)樣式是圓的,如圖1.17

圖1.17

????????那么你知道了三階貝塞爾曲線怎么得到偏移曲線后,不就可以寫繪圖轉(zhuǎn)邊框了嗎?之前講過線段怎么偏移的,比如圖1.18的線段AB

圖1.18

假設(shè)A點(diǎn)坐標(biāo)(x1,y1)、B坐標(biāo)(x2,y2),那么線段AB可以求出個(gè)法向量(y2-y1,x1-x2),然后再把這個(gè)法向量變成單位向量,假設(shè)求出的單位向量是(ux,uy)、假設(shè)你要偏移的數(shù)值的d,那么你就可以得到偏移的線段的頂點(diǎn)了,偏移的線段第一個(gè)點(diǎn)x坐標(biāo)就是x1+ux*d、y坐標(biāo)就是y1+uy*d,然后當(dāng)然偏移的線段第二個(gè)點(diǎn)x坐標(biāo)就是x2+ux*d、y坐標(biāo)就是y2+uy*d

????????這樣不管是直的還是彎的,都可以偏移了,轉(zhuǎn)邊框不就可以很簡(jiǎn)單的寫出來了嗎,這樣比如圖1.19就可以轉(zhuǎn)邊框得到圖1.20了

圖1.19
圖1.20

而如果用先把繪圖轉(zhuǎn)直線再轉(zhuǎn)邊框的方法,那文本量就會(huì)比較大了,如圖1.21

圖1.21

那么此時(shí)你可能就會(huì)想,既然先轉(zhuǎn)直線再轉(zhuǎn)邊框會(huì)有這么多文本,那么豈不是全直線轉(zhuǎn)邊框的函數(shù)沒有用處?當(dāng)然不是這樣的,直線繪圖轉(zhuǎn)邊框是有用的、相較于含曲線路徑的轉(zhuǎn)邊框有它的好處,那就是,當(dāng)你希望做變形效果的時(shí)候,比如你得到了邊框繪圖,你對(duì)它做變形效果、改變繪圖的頂點(diǎn),那么當(dāng)然用全直線的邊框就會(huì)好一些,而含曲線路徑的邊框就有一些"多余"的路徑,相當(dāng)于一個(gè)未簡(jiǎn)化的繪圖,變形起來的時(shí)候還會(huì)有多余的點(diǎn)、干擾效果,那自然是不好的。而之前介紹過,如何得到簡(jiǎn)化的全直線邊框,那對(duì)一個(gè)沒有多余路徑的繪圖來變形的話,就會(huì)舒服很多。所以說,直線邊框和有曲線的邊框都有它們的用處,只不過一般來說,不會(huì)做變形效果,所以一般用曲線繪圖轉(zhuǎn)邊框的函數(shù)即可、那樣文本量就會(huì)小一些。

????????另外再提一下轉(zhuǎn)角樣式是什么意思。如圖1.22這樣一個(gè)路徑,比如現(xiàn)在要在一側(cè)得到偏移路徑,那么就會(huì)得到圖1.23吧

圖1.22
圖1.23

那么顯然每個(gè)片段偏移以后,并不算直接連接上的,如圖1.24,所以對(duì)于有很多段路徑片段的一個(gè)繪圖來說,路徑片段與路徑片段偏移后就需要將各自偏移后的片段連接上,而這個(gè)連接的方式就叫做轉(zhuǎn)角樣式

圖1.24

如果直接連接的話,這種樣式可以叫做bevel,如圖1.25就是bevel

圖1.25

如果是用一段圓弧連接的話,這種樣式就叫做round,如圖1.26

圖1.26

如果愿意延長(zhǎng)求交點(diǎn)的話,那么就是miter樣式了,如圖1.27

圖1.27

所以很顯然,這幾種轉(zhuǎn)角樣式里,計(jì)算量最小的是第一種,因?yàn)楦静恍枰?jì)算,直接連接即可。什么意思,連接不就是 l 命令嗎,繪圖代碼里直接用' l '把一段段偏移后的路徑連起來就完了。然后其它比如round就是算一下相應(yīng)的圓弧即可,三階貝塞爾曲線擬合圓弧很簡(jiǎn)單。然后miter模式要算交點(diǎn),但是有的時(shí)候因?yàn)檗D(zhuǎn)角太小,導(dǎo)致直接用交點(diǎn)會(huì)很難看,比如圖1.28

圖1.28

應(yīng)該看得很清楚吧?黑色是原本的路徑,兩個(gè)線段的夾角太小,這樣直接求交點(diǎn)就會(huì)有很長(zhǎng)一段尖尖,所以miter樣式一般不會(huì)直接這么求交點(diǎn),而是,比如你偏移數(shù)值是10,那么就延長(zhǎng)嘛,都延長(zhǎng)10,如果有延長(zhǎng)了這個(gè)10(即路徑的偏移值)后,有交點(diǎn),那么就用,如果沒有交點(diǎn),就直接連接了,如圖1.29,假設(shè)偏移值就是10,然后延長(zhǎng)

圖1.29

發(fā)現(xiàn)延長(zhǎng)后沒有交點(diǎn),好啊,直接連接,得到圖1.30

圖1.30

所以再舉個(gè)例子,如圖1.31,偏移后,然后延長(zhǎng)(偏移值是多少就延長(zhǎng)多少)

圖1.31

發(fā)現(xiàn)有交點(diǎn),就求出來就好了嘛,然后連接就得到了圖1.32

圖1.32

當(dāng)然,轉(zhuǎn)邊框是兩側(cè)都有偏移的,所以比如把圖1.33轉(zhuǎn)邊框、用bevel轉(zhuǎn)角樣式的話,就會(huì)得到圖1.34(即兩側(cè)偏移后都是直接連接)

圖1.33
圖1.34

如果轉(zhuǎn)邊框用的round轉(zhuǎn)角樣式的話,就會(huì)得到圖1.35

圖1.35

這樣就講清楚了幾種轉(zhuǎn)角樣式,當(dāng)然除了這些拐角樣式,還有一開始講的端點(diǎn)樣式,端點(diǎn)樣式顯然需要繪圖的路徑是開放的,如果繪圖是封閉的繪圖,那么就不存在端點(diǎn)了、不用考慮端點(diǎn)樣式了。所以顯然端點(diǎn)樣式其實(shí)就是繪圖路徑最開頭和最末尾的樣式,比如上文的“flat”端點(diǎn)樣式就是圖1.36這樣的

圖1.36

而square端點(diǎn)樣式就是圖1.37這樣的(同樣,延長(zhǎng)的數(shù)值也是等于偏移值)

圖1.37

然后round端點(diǎn)樣式就是加個(gè)半圓,如圖1.38

圖1.38


????????簡(jiǎn)介就這么些了,函數(shù)代碼在視頻里講。

(本文寫于2021年7月20號(hào),因?yàn)橐话銜?huì)隔幾個(gè)月才會(huì)發(fā)布寫好的專欄,所以文章中提前用了"兩年以前"這種說法)

【Aegisub】貝塞爾曲線偏移簡(jiǎn)單介紹、繪圖(含曲線)轉(zhuǎn)邊框簡(jiǎn)單介紹的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
石柱| 铁岭县| 毕节市| 罗源县| 延寿县| 湛江市| 阜宁县| 顺平县| 西乡县| 云浮市| 怀集县| 都昌县| 南皮县| 铜川市| 孟津县| 宝山区| 漾濞| 丰顺县| 墨竹工卡县| 民县| 兴隆县| 桦南县| 安丘市| 福泉市| 江孜县| 乃东县| 银川市| 宿州市| 惠州市| 安图县| 徐汇区| 广河县| 习水县| 揭东县| 杭锦旗| 农安县| 彝良县| 昔阳县| 井冈山市| 浦县| 巴青县|