【Aegisub】吐血奉獻(xiàn)?。「鶕?jù)離散點(diǎn)擬合貝塞爾曲線

? ? ? ? 首先先看兩個(gè)圖,圖1.01在經(jīng)過函數(shù)處理以后就得到圖1.02了:


將折線給重新擬合回了曲線,這應(yīng)該能想到很多種用處吧?比如做碎片字幕時(shí),得到的碎片繪圖會(huì)是一堆全直線繪圖,這就意味著字幕的文本量會(huì)很大,而且全是折線的繪圖可能不太光滑,但是將折線擬合回曲線以后,繪圖不僅變得更加光滑了,而且文本量得到了極大的簡化!比如你看圖1.03這個(gè)原本的碎片繪圖,將其用擬合函數(shù)處理后,就會(huì)得到圖1.04


當(dāng)然這兩個(gè)繪圖代碼里的數(shù)都不是整數(shù),只是放進(jìn)assdraw里就取整了,所以有一些重合的點(diǎn)(就是說其實(shí)本身這兩個(gè)繪圖代碼的結(jié)果都是保留了兩位小數(shù)的),然后碎片在屏幕里是圖1.05這樣的

圖1.05的第一行是經(jīng)過擬合后的碎片繪圖,而第二行是全直線的碎片繪圖
????????除了碎片繪圖能用到擬合函數(shù)以外,在做流暢變形效果時(shí),也可以把一個(gè)有一堆直線的繪圖給重新變?yōu)榍€,如圖1.06擬合后就是圖1.07


比如如果你用直線繪圖變形來做波浪,那么這個(gè)函數(shù)就相當(dāng)有用,圖1.08就可以你擬合得到圖1.09


用一個(gè)完整的字來看會(huì)很清楚,擬合效果很好,文本量節(jié)約很多,如圖1.10變到圖1.11


然后圖1.12是對(duì)比,第一行是全直線繪圖,第二行是擬合后的繪圖

擬合函數(shù)也沒用什么復(fù)雜的東西,你只要明白矩陣、牛頓迭代、最小二乘法即可。代碼在相應(yīng)的視頻里講
????????然后,關(guān)于擬合曲線還要說明一下。比如有一堆數(shù)據(jù),你想根據(jù)這堆數(shù)據(jù)擬合貝塞爾曲線,比如3個(gè)點(diǎn)要你擬合一個(gè)曲線,那么講道理擬合的曲線就差不多是圖1.13這樣

擬合曲線就是得到相應(yīng)的曲線使得原本的數(shù)據(jù)點(diǎn)盡可能的靠近擬合的曲線。也就是說,如果你用線段把各個(gè)點(diǎn)連起來得到一條折線,這條折線的形狀看起來很有可能和擬合出的曲線是有一定區(qū)別的,如圖1.14,這并不意味著擬合曲線是錯(cuò)的,而是擬合曲線的本意本來就不是讓曲線的形狀接近用線段連接數(shù)據(jù)點(diǎn)得到的折線,而是擬合出一條足夠貼近原本數(shù)據(jù)點(diǎn)的光滑曲線

但是做特效的話,就需要擬合出的結(jié)果和繪圖原本的形狀幾乎一樣,那么這樣就要增加代碼,使擬合結(jié)果更理想,所以我寫了兩個(gè)函數(shù),第一個(gè)是專門擬合曲線用的函數(shù),第二個(gè)就是專門用來擬合出形狀幾乎一樣的繪圖的函數(shù)。
????????那么怎么樣讓擬合出的曲線和折線形狀幾乎一樣呢,這很簡單,增加可以判斷的點(diǎn)即可,比如線段的中點(diǎn)和你擬合曲線上相應(yīng)的點(diǎn)的距離是否在允許范圍內(nèi),如圖1.15

如果D和E不夠接近或者F和G不夠接近,那么就拆分?jǐn)?shù)據(jù)點(diǎn)(比如有9個(gè)數(shù)據(jù)點(diǎn),根據(jù)情況拆分后就是一組3個(gè)一組6個(gè)數(shù)據(jù)點(diǎn),當(dāng)然這是舉例子,拆分是根據(jù)情況拆分的,你哪個(gè)點(diǎn)不滿足你設(shè)定的誤差,你就在哪個(gè)點(diǎn)拆開這組數(shù)據(jù)),拆分后再來一組組嘗試擬合(當(dāng)然會(huì)擬合出多條曲線了)。不過有的時(shí)候,就每段增加一個(gè)中點(diǎn)來判斷是不夠的,比如線段很長的時(shí)候,只增加這一個(gè)點(diǎn)判斷曲線和折線形狀是否接近是不夠的,就像圖1.16這樣

圖1.16一共3個(gè)點(diǎn),然后增加了中點(diǎn)D、E,可就算增加了點(diǎn),擬合曲線還是和A、B、C連成的折線有不小的區(qū)別。所以這種就分情況處理即可,當(dāng)線段短一點(diǎn)的時(shí)候,可以不增加點(diǎn)輔助判斷或者就增加中點(diǎn)來輔助判斷,而線段長一點(diǎn)的時(shí)候,就多增加幾個(gè)點(diǎn)來判斷即可,分別取線段上0.25處、0.5處、0.75處的點(diǎn),它們一起來輔助判斷即可。這樣就會(huì)有很好的擬合效果了

如果只是長一點(diǎn)的線段才用增加點(diǎn)來輔助判斷的話,那么在線段較短時(shí),也有可能出現(xiàn)一些問題,如圖1.17,擬合的曲線和這線段的形狀還是不一樣


只是舉個(gè)例子,實(shí)際情況下只是說有可能出現(xiàn)類似的情況。現(xiàn)在這個(gè)曲線就是一個(gè)波浪狀的樣子,和線段的形狀差距很大。(曲線看起來不太看得清楚,可以大概理解為下圖這樣的形狀)

遇到這種情況,只有可能就是線段太短,此時(shí)可以直接判斷你擬合出的曲線相比你的線段來說是不是大過頭了。求出曲線的邊界框的寬w和高h(yuǎn)、求出折線的邊界框的寬w1和高h(yuǎn)1,如果w1不為0且w比w1大好幾倍或者h(yuǎn)1不為0且h比h1大好幾倍,那自然說明這擬合出的曲線是不合格的,于是當(dāng)然就要拆開數(shù)據(jù)點(diǎn)了
(本文寫于2021年8月5日)