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

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

【Aegisub】判斷點(diǎn)是否包含在任意(含曲線命令的)繪圖內(nèi)

2021-08-28 14:40 作者:多華宮與火火里  | 我要投稿

????????(提醒:對(duì)于知道A3shape的人,可能知道A3有提供判斷點(diǎn)包含的函數(shù),但是那個(gè)函數(shù)實(shí)際上是有一點(diǎn)錯(cuò)誤的,也就是并不能正確的判斷點(diǎn)包含,文章后面會(huì)講它為何錯(cuò)。當(dāng)然知不知道A3shape都不影響你看這篇文章,因?yàn)檫@篇文章就是講怎么判斷點(diǎn)包含的)

????????之前的視頻講了assdraw的填充方式 ( 和svg的non-zero規(guī)則一樣 ),也講了如何判斷點(diǎn)是否包含于任意直線繪圖內(nèi),那么,如果繪圖里有貝塞爾曲線呢,又怎樣快速地進(jìn)行點(diǎn)包含的判斷呢?

????????相信如果你理解了填充規(guī)則,就知道,在有曲線時(shí)一樣可以用可愛(ài)的掃描線來(lái)判斷繪圖的填充情況,那么重點(diǎn)就是掃描線與繪圖交點(diǎn)的計(jì)算了。當(dāng)繪圖有曲線命令的時(shí)候,就需要計(jì)算掃描線和曲線的交點(diǎn),所以實(shí)際上就是要解三次方程。解三次方程有很多種方法,比如用二分法或牛頓迭代,當(dāng)然如果用二分法的話,迭代次數(shù)會(huì)比用牛頓法的要多。那么你猜咱們這里用什么方法呢,二分法牛頓法弦截法?很好,那么現(xiàn)在用公式法解三次方程

????????然后下一個(gè)問(wèn)題,或者說(shuō)下一個(gè)注意事項(xiàng),我們求得了曲線和繪圖的交點(diǎn)以后,是每一個(gè)求得的交點(diǎn)都要參與計(jì)數(shù)嗎?大家回想一下以前講的判斷點(diǎn)是否包含于全直線繪圖中,當(dāng)我們實(shí)際計(jì)數(shù)的時(shí)候,比如線段AB和水平線有交點(diǎn)C,只有當(dāng)交點(diǎn)C的縱坐標(biāo)不等于線段AB的bottom(也就是A、B兩點(diǎn)的縱坐標(biāo)最大值)的時(shí)候,才會(huì)計(jì)數(shù),而如果交點(diǎn)的縱坐標(biāo)y等于該線段的"最大y"的話,實(shí)際上是不需要更改cnt的。所以同理,在對(duì)水平線和曲線的交點(diǎn)計(jì)數(shù)的時(shí)候,需要滿足這個(gè)原則,就叫端點(diǎn)計(jì)數(shù)原則吧,或者叫不添腳原則?(不是叫不舔腳原則),等一下,要不然叫Lua真是一門(mén)惡心語(yǔ)言原則?想不到好的叫法了,就叫端點(diǎn)計(jì)數(shù)原則吧...

????????接下來(lái),主要用例子來(lái)解析說(shuō)明端點(diǎn)計(jì)數(shù)原則的用法。端點(diǎn)計(jì)數(shù)原則當(dāng)然指的就是,如果水平線和某段路徑的交點(diǎn)的y坐標(biāo)小于該段路徑的最大y坐標(biāo),則計(jì)數(shù)、cnt更新,否則,不計(jì)數(shù)、cnt不變化。先從全直線的情況說(shuō)吧...比如圖1.01

圖1.01

假設(shè)我們要判斷點(diǎn)A是否包含在圖1.01所指定的繪圖中,那么就過(guò)A點(diǎn)作水平線,和繪圖取交點(diǎn),如圖1.02

圖1.02

現(xiàn)在直接看圖的話水平線和繪圖有3個(gè)交點(diǎn),但是實(shí)際計(jì)數(shù)的點(diǎn)只有N、M,因?yàn)锳這個(gè)交點(diǎn)的縱坐標(biāo)是線段AB的bottom(也就是AB的y最大),所以AB段和水平線的交點(diǎn)是不會(huì)參與計(jì)數(shù)的。同樣,線段AC和水平線的交點(diǎn)A的縱坐標(biāo)是線段AC的bottom(即AC段的最大y),所以AC段和水平線的交點(diǎn)也是不參與計(jì)數(shù)的。那么,此時(shí)的計(jì)數(shù)情況就是,在N處,該段路徑向上,所以cnt增加1就等于1,所以N點(diǎn)到下一個(gè)交點(diǎn)M這一部分是填充的,然后在M處,該段路徑向下,所以cnt=cnt-1就等于0,所以M右邊的部分都不填充。

????????再比如圖1.03,m 0 0 l 0 19 l 0 29 l 42 29 l 42 0 m 9 5 l 32 5 l 32 26 l 9 26?

圖1.03

現(xiàn)在假設(shè)要判斷點(diǎn)A是否在繪圖內(nèi),那么過(guò)A點(diǎn)作水平線,得到圖1.04

圖1.04

????????為了突出端點(diǎn)計(jì)數(shù)原則,現(xiàn)在我們首先不用端點(diǎn)計(jì)數(shù)原則來(lái)判斷點(diǎn)包含,然后再用端點(diǎn)計(jì)數(shù)原則來(lái)判斷點(diǎn)包含。

????????假設(shè)不用端點(diǎn)計(jì)數(shù)原則,水平線與BP1段相交得到P1,由于BP1向下,那么cnt=cnt-1=-1,然后水平線與P1C也相交于點(diǎn)P1,又計(jì)數(shù),cnt = cnt - 1 = -2,然后到下一個(gè)交點(diǎn)P2,此時(shí)該段路徑向上,cnt=cnt+1=-1,我們發(fā)現(xiàn),此時(shí)的cnt不等于0,那么按照cnt的情況,P2到P3之間的部分應(yīng)該填充,所以點(diǎn)A應(yīng)該是包含在繪圖內(nèi)的,可是顯然,這是不對(duì)的,A點(diǎn)并不包含在繪圖內(nèi)!

????????而我們這一次再來(lái)用端點(diǎn)計(jì)數(shù)原則看看,水平線與BP1段相交得到P1,而此時(shí)點(diǎn)P1的縱坐標(biāo)等于BP1段的底bottom(即BP1段的最大y),所以這個(gè)P1不參與此次計(jì)數(shù),cnt=0依舊,然后水平線與P1C也相交于點(diǎn)P1,此時(shí)點(diǎn)P1的縱坐標(biāo)不等于P1C段的底bottom(即P1C段的最大y),所以這個(gè)P1就要計(jì)數(shù),cnt?=?cnt?-?1?=?-1,然后到下一個(gè)交點(diǎn)P2,此時(shí)該段路徑向上,cnt=cnt+1=0,所以,現(xiàn)在cnt就等于0,按照此情況,P2到P3之間的部分就是不填充的,所以點(diǎn)A就不包含在繪圖內(nèi),這便是正確的結(jié)果。

????????那么現(xiàn)在來(lái)看看有繪圖中含有曲線命令的例子,如圖1.05,m 2 9 b 5 -26 18 -20 23 0 b 28 12 44 17 48 -19 l 50 20 l 2 20?

圖1.05

假設(shè)我們要判斷點(diǎn)A是否在圖1.05指定的繪圖內(nèi)部,那么過(guò)點(diǎn)A作水平線和繪圖取交點(diǎn),得到圖1.06

圖1.06

????????那么現(xiàn)在又和剛才一樣的,為了突出端點(diǎn)計(jì)數(shù)原則,現(xiàn)在我們首先不用端點(diǎn)計(jì)數(shù)原則來(lái)判斷點(diǎn)包含,然后再用端點(diǎn)計(jì)數(shù)原則來(lái)判斷點(diǎn)包含。
????????假設(shè)不用端點(diǎn)計(jì)數(shù)原則,水平線與第一條貝塞爾有第一個(gè)交點(diǎn)P1,根據(jù)點(diǎn)P1處的時(shí)間參數(shù) t 和此時(shí)的一階導(dǎo)數(shù),得到此時(shí)P1處的方向信息,當(dāng)然“向上”了,所以cnt = cnt+1 = 1,然后水平線與第一條貝塞爾還有第二個(gè)交點(diǎn)P2,同樣求出P2點(diǎn)的切線方向,方向向下,所以cnt=cnt-1=0,再然后水平線和第二條貝塞爾有第一個(gè)交點(diǎn)P2,求出該點(diǎn)方向,方向向下,所以cnt=cnt-1=-1,然后水平線和第二條貝塞爾還有第二個(gè)交點(diǎn)P3,求出該點(diǎn)方向,方向向上,所以cnt=cnt+1=0,所以,根據(jù)現(xiàn)在cnt的情況,我們發(fā)現(xiàn),在P2到P3之間,cnt=-1,所以P2到P3這一部分應(yīng)該填充,然后,P3到P4,cnt等于0,所以P3到P4這一部分應(yīng)該不填充,? 很顯然,這是錯(cuò)誤的,因?yàn)锳明明是不在繪圖內(nèi)部的!

?????????而我們又一次來(lái)用端點(diǎn)計(jì)數(shù)原則看看,水平線與第一條貝塞爾有第一個(gè)交點(diǎn)P1,而P1不是該條貝塞爾曲線的端點(diǎn),所以放心地計(jì)數(shù),cnt=cnt+1=1,然后水平線與第一條貝塞爾還有第二個(gè)交點(diǎn)P2,此時(shí)P2該條貝塞爾曲線的端點(diǎn),所以需要判斷一下了,不過(guò)這時(shí)當(dāng)然不是用這一整條貝塞爾的最大y和P2的y比較,而是這樣,現(xiàn)在P2是該貝塞爾的終點(diǎn),所以咱們用上一個(gè)點(diǎn)(即該貝塞爾的第二個(gè)控制點(diǎn))和終點(diǎn)的y比較,判斷終點(diǎn)的y坐標(biāo)是否更大,更大就說(shuō)明P2也是y更大的,即P2的縱坐標(biāo)y等于“該段”路徑的bottom,那么是bottom就像剛剛說(shuō)的,不參與計(jì)數(shù),cnt不變依舊等于1,再然后水平線和第二條貝塞爾有第一個(gè)交點(diǎn)P2,判斷出P2是該條貝塞爾的端點(diǎn),所以需要判斷是否P2的y是bottom,現(xiàn)在P2是該條貝塞爾的起點(diǎn),所以要用到下一個(gè)點(diǎn)(也就是該條貝塞爾的第一個(gè)控制點(diǎn))和起點(diǎn)比較,顯然,現(xiàn)在起點(diǎn)P2的y比第一個(gè)控制點(diǎn)C的y要小,所以P2的縱坐標(biāo)y不是bottom,所以,現(xiàn)在就需要計(jì)數(shù),那么cnt = cnt - 1 = 0,然后水平線和第二條貝塞爾還有第二個(gè)交點(diǎn)P3,P3并不是該條貝塞爾曲線的端點(diǎn),所以肯定不是bottom,直接計(jì)數(shù),cnt=cnt+1=1,所以根據(jù)此時(shí)的情況,我們就知道,在P2到P3之間cnt等于0,所以P2到P3這一部分不填充,而P3到P4的cnt等于1,所有P3到P4這一部分是要填充的,所以當(dāng)然也可知A點(diǎn)是不在繪圖內(nèi)部的。

????????繼續(xù)舉例,解釋在繪圖有貝塞爾曲線命令時(shí),端點(diǎn)計(jì)數(shù)原則該怎么使用,如圖1.07和圖1.08,m 0 0 b -3 -13 9 -18 19 -18 b 22 -9 32 -5 34 3?

圖1.07

假設(shè)現(xiàn)在想判斷A這個(gè)點(diǎn),是否在繪圖內(nèi)部

圖1.08

????????過(guò)A點(diǎn)作水平線,得到圖1.09

圖1.09

????????現(xiàn)在直接用端點(diǎn)計(jì)數(shù)原則來(lái)判斷點(diǎn)包含,水平線與第一條貝塞爾有交點(diǎn)P,發(fā)現(xiàn)P是該條貝塞爾的端點(diǎn),且P是該條曲線的終點(diǎn),那么就像剛剛說(shuō)的,應(yīng)該配合上一個(gè)點(diǎn)來(lái)判斷P是否是bottom,可是問(wèn)題來(lái)了,現(xiàn)在點(diǎn)C和點(diǎn)P的y是一樣的,那如果你把P當(dāng)成bottom的話,就不會(huì)改變計(jì)數(shù),而在下一條曲線的時(shí)候,P是端點(diǎn)但是不是bottom,所以會(huì)計(jì)數(shù),那么,那樣的話,cnt最后會(huì)等于-1,不等于0,那么A就會(huì)被判斷為在繪圖內(nèi)部,而這是不對(duì)的,所以,現(xiàn)在當(dāng)C和終點(diǎn)P的縱坐標(biāo)y一樣的時(shí)候,需要再往前看,也就是C的前一個(gè)點(diǎn)B,看B的y是否大于P的y,發(fā)現(xiàn),P的縱坐標(biāo)比B的縱坐標(biāo)小,所以P不是bottom而是top,所以此時(shí)實(shí)際上是需要計(jì)數(shù)的,而方向就是向上(因?yàn)镻是終點(diǎn)且P不是bottom),所以cnt=cnt+1=1,然后再來(lái),水平線和第二條貝塞爾曲線有交點(diǎn)P,判斷出P是該條貝塞爾曲線的起點(diǎn),則找出下一點(diǎn)D,判斷P和D的縱坐標(biāo)誰(shuí)大,發(fā)現(xiàn),P的y更小,所以P不是bottom,所以需要計(jì)數(shù),此時(shí)方向一定向下(因?yàn)镻是曲線起點(diǎn)且P不是bottom),所以cnt=cnt-1=0,所以,在該條水平線上,當(dāng)橫坐標(biāo)x大于P的時(shí)候,均不填充,那么由于A的橫坐標(biāo)x大于P的,所以A處不填充,即A不在繪圖內(nèi)部!

????????所以總結(jié)一下,當(dāng)水平線和貝塞爾曲線有交點(diǎn)P時(shí),如果P不是該條貝塞爾曲線的端點(diǎn),那么必然計(jì)數(shù)而如果P是端點(diǎn),那么①若P是曲線起點(diǎn)(即時(shí)間參數(shù)t=0),則逐一查看后面的點(diǎn)(即曲線的第一個(gè)控制點(diǎn)到曲線終點(diǎn))直到檢測(cè)出P是否是bottom為止,若P為bottom則交點(diǎn)P并不參與計(jì)數(shù),若P不是bottom則cnt必然減1,即cnt=cnt-1。②若P是曲線終點(diǎn)(即時(shí)間參數(shù)t=1),則逐一查看前面的點(diǎn)(即曲線的第二個(gè)控制點(diǎn)到曲線起點(diǎn)),直到檢測(cè)出P是否是bottom為止,若P為bottom則交點(diǎn)P并不參與計(jì)數(shù),若P不是bottom則cnt必然加1,即cnt = cnt + 1。

????????所以端點(diǎn)計(jì)數(shù)原則就是和端點(diǎn)有關(guān)系的,不管是直線還是曲線,只要你交點(diǎn)不是端點(diǎn),則必然計(jì)數(shù),如果交點(diǎn)是端點(diǎn)且該點(diǎn)不是bottom,同樣也是必然計(jì)數(shù),如果交點(diǎn)是端點(diǎn)且該點(diǎn)是bottom,那么該交點(diǎn)才不會(huì)參與計(jì)數(shù)、才不會(huì)改變cnt。

????????具體地說(shuō)完端點(diǎn)計(jì)數(shù)原則以后,就回頭聊一聊水平線和繪圖求交點(diǎn)吧。水平線和直線求交點(diǎn)當(dāng)然沒(méi)啥問(wèn)題,那么主要就是水平線和貝塞爾曲線求交點(diǎn)了。

????????水平線和貝塞爾曲線求交點(diǎn)有點(diǎn)需要注意的,就是“精度”問(wèn)題。比如判別式Δ>0時(shí),三次方程除了有一個(gè)實(shí)根外,還有一對(duì)共軛復(fù)根,但是有的時(shí)候求出來(lái)的共軛復(fù)根的虛部非常非常小,比如3.994250345898757e-7i就很小很小,然后結(jié)合原方程就有肉眼可見(jiàn)的問(wèn)題,本來(lái)應(yīng)該得到兩個(gè)實(shí)根,卻得到了一個(gè)實(shí)根兩個(gè)復(fù)根,所以比方說(shuō)你可以計(jì)算當(dāng)求得的復(fù)根的虛部很小的時(shí)候,將其取舍掉,但是這樣計(jì)算量會(huì)增大,因?yàn)橐嗨悴恍枰?jì)算的復(fù)根,所以這里需要的是對(duì)判別式做判斷,如果判別式特別接近于0,那么就認(rèn)為判別式等于0,這樣就能直接按Δ=0來(lái)計(jì)算方程的根,就不用求不必要的復(fù)根了。

解三次方程

? ? ? ? 實(shí)際上,Lua計(jì)算浮點(diǎn)數(shù)的時(shí)候有精度問(wèn)題,所以計(jì)算的判別式Δ特別接近0的時(shí)候,不易知道它具體數(shù)值是多少。甚至不同版本的Lua計(jì)算結(jié)果會(huì)不一樣,比如

用在線的Lua工具得到的判別式D約等于0

而如果用同樣的代碼,直接在aeg里面試試,會(huì)得到這樣的結(jié)果

顯然接近于0的判別式的計(jì)算結(jié)果出現(xiàn)了不同

得到的這兩個(gè)結(jié)果差距是很大的,雖然它們都接近0。

所以為了確保曲線和水平線的交點(diǎn)是曲線的端點(diǎn)時(shí),能求出理想的解,可以讓?duì)そ咏?時(shí)就當(dāng)作0、然后為了確保不會(huì)有多余解和遺漏的解,在Δ>0時(shí)需要判斷0和1是否是方程的解(因?yàn)棣?gt;0也可能很接近0)、在Δ<0時(shí)需要判斷3個(gè)根里有沒(méi)有重復(fù)的,如果有就去除掉重復(fù)的(因?yàn)棣?lt;0也可能很接近0,有可能本身應(yīng)該是當(dāng)作Δ=0算但實(shí)際卻當(dāng)作了Δ<0算,那么3個(gè)實(shí)根中就會(huì)有兩個(gè)是幾乎一樣的數(shù)值)

還有就是如果用太多的除法運(yùn)算,也會(huì)導(dǎo)致計(jì)算結(jié)果不穩(wěn)定,所以可以盡量減少代碼里的除法運(yùn)算。

????????

????????然后除開(kāi)解方程以外,剩下其他判斷點(diǎn)包含的代碼在視頻里講


????????那么說(shuō)起求交點(diǎn),其實(shí)光是求交點(diǎn)的話你也可以用其他方法。比如求兩條貝塞爾曲線的交點(diǎn),假設(shè)這兩條曲線是A1和B1,那么你可以求出A1的邊界框bbox1和B1的邊界框bbox2然后如果兩條曲線的邊界框沒(méi)有重合部分,那么說(shuō)明曲線A1和曲線B1沒(méi)有交點(diǎn),而如果兩個(gè)邊界框有重合部分,那么就拆分兩條曲線,將A1拆為A2和A3、B1拆為B2和B3,然后再求拆出來(lái)的這4條曲線的邊界框,然后看哪兩個(gè)邊界框是有重合的,然后一直這么重復(fù)算下去,直到計(jì)算到最后求出的邊界框是足夠小的就可以了。所以此時(shí)你就可以設(shè)定一個(gè)精度了。那么同樣的,曲線和直線求交點(diǎn)也可以類似的計(jì)算。

????????之前的視頻里說(shuō)過(guò),我看了一下qt庫(kù)的c++源碼(就是很多年前就有的一個(gè)由外國(guó)人寫(xiě)的庫(kù)),其判斷點(diǎn)包含的時(shí)候就有一點(diǎn)錯(cuò)誤。qt庫(kù)中使用的方法就是拆分貝塞爾曲線,并且還限制了拆分的次數(shù),當(dāng)然本來(lái)也不可能無(wú)限的拆分下去。那我大概寫(xiě)了一個(gè)Lua版本的掃描線與貝塞爾曲線的交點(diǎn)計(jì)數(shù)函數(shù):

????local?function?bezier_isect_cnt(x1,y1,x2,y2,x3,y3,x4,y4,y,n)

????????local?top,bottom=math.min(y1,y2,y3,y4),math.max(y1,y2,y3,y4)

????????local?left,right=math.min(x1,x2,x3,x4),math.max(x1,x2,x3,x4)

????????local?n=n?and?n+1?or?0

????????if?y>=top?and?y<bottom?then

????????????local?w,h=right-left,bottom-top

????????????if?n>=32?or?(w<0.001?and?h<0.001)?then

????????????????if?x1<=pt_x?then

????????????????????cnt=cnt+Xshape.sgn(y4-y1)

????????????????end

????????????else

????????????????local?f_x2,f_y2,f_x3,f_y3,tx,ty,s_x2,s_y2,s_x3,s_y3=Xshape.split_bezier_into_two(x1,y1,x2,y2,x3,y3,x4,y4)

????????????????bezier_isect_cnt(x1,y1,f_x2,f_y2,f_x3,f_y3,tx,ty,y,n)

????????????????bezier_isect_cnt(tx,ty,s_x2,s_y2,s_x3,s_y3,x4,y4,y,n)

????????????end

????????end

????end
顯然參數(shù)的n就是為了限制遞歸的次數(shù)的

那么為什么說(shuō)qt庫(kù)的判斷點(diǎn)包含有錯(cuò)誤呢?咱們先來(lái)看看錯(cuò)誤在哪。比如下圖1.10

圖1.10

圖1.10的繪圖代碼是m 36 5 l 36 34 b 37 38 33 39 25 37 b 24 36 24 36 24 34 b 25 33 25 33 27 34 b 31 35 33 35 33 34 l 33 6 b 33 5 33 4 34 4 b 36 4 36 5 36 5 l 36 5 m 25 8 b 25 7 25 6 26 6 b 27 6 28 7 28 8 l 28 28 b 28 29 27 30 26 30 b 25 30 25 29 25 28 l 25 8 m 15 20 l 21 20 b 22 20 23 20 23 21 b 23 23 22 23 21 23 l 15 23 l 15 34 b 15 38 13 39 8 37 b 7 37 6 36 6 35 b 7 34 7 34 9 34 b 11 35 12 35 11 33 l 11 23 l 4 23 b 2 23 2 23 2 21 b 2 20 2 20 4 20 l 11 20 l 11 16 b 11 15 12 14 13 14 b 14 14 15 15 15 16 l 15 20 m 6 5 b 9 6 11 7 14 9 b 15 7 17 6 18 5 b 19 4 19 4 20 4 b 21 5 21 6 20 7 b 19 8 18 9 17 11 b 18 11 19 12 21 14 b 21 14 22 14 22 14 b 23 15 23 16 23 17 b 22 18 21 18 20 17 b 18 16 16 15 14 13 b 11 15 8 16 5 17 b 3 17 2 17 2 16 b 2 15 2 14 3 14 b 6 13 8 12 11 11 b 10 11 8 10 5 8 b 4 8 4 7 4 6 b 4 5 5 5 6 5 l 6 5 m 10 26 b 8 30 7 33 5 34 b 4 35 3 35 2 35 b 2 34 2 33 3 32 b 4 31 5 28 6 25 b 7 24 7 23 9 24 b 9 24 10 25 10 26 l 10 26 m 19 24 b 21 27 22 29 23 31 b 24 33 23 34 23 34 b 22 35 21 34 20 33 b 18 30 17 28 16 26 b 15 25 15 24 16 24 b 17 23 18 23 19 24 l 19 24

那么從圖上可以清楚地看到,點(diǎn)(19,38)一定是不在圖形內(nèi)的、而且是“一點(diǎn)關(guān)系”都不挨著的。但是如果用利用qt庫(kù)的A3shape來(lái)判斷點(diǎn)包含的話,就會(huì)得到點(diǎn)是包含的這個(gè)結(jié)論,如圖1.11和圖1.12

圖1.11
圖1.12

????????而實(shí)際上,不僅僅是(19,38)會(huì)被判斷為在圖形內(nèi),甚至有“一排”點(diǎn)都會(huì)被判斷為在圖形內(nèi)部,如圖1.13

圖1.13

????????那你肯定會(huì)想到底是為啥。其實(shí)很簡(jiǎn)單,因?yàn)閳D形中有貝塞爾曲線剛好和掃描線是相切的?。?/strong>啊,怎么會(huì)這樣啊,哦不,你瞧瞧,哇,你身上有只飛碟耶!那就來(lái)碗飛碟泡飯吧!不好意思,剛才鍵盤(pán)上太多灰了。對(duì),飛碟指的就是UFO。好吧,那么水平線和曲線相切只有一個(gè)交點(diǎn)的話,那就是此時(shí)這個(gè)曲線的方向是沿著水平方向的,所以我們的計(jì)數(shù)變量cnt應(yīng)該加0、也就是cnt應(yīng)該不變,而qt庫(kù)中,卻沒(méi)有這么貼心的考慮,因?yàn)椴鸱重惾麪柷€不可能一直拆分下去, 那么當(dāng)曲線和水平線相切的時(shí)候,怎么也不可能把曲線拆分到一個(gè)點(diǎn),那根據(jù)其代碼,計(jì)數(shù)不是1就會(huì)是-1,那就完全忽略了0的情況。

源碼是c++的,看Lua的話,可以看上文中我寫(xiě)的Lua版

????????所以不知道為什么qt庫(kù)沒(méi)有考慮到曲線有可能和水平線相切的情況,導(dǎo)致交點(diǎn)計(jì)數(shù)錯(cuò)誤。那么這樣帶來(lái)的結(jié)果是什么呢,比如說(shuō),如果咱們用qt庫(kù)的判斷點(diǎn)包含函數(shù)來(lái)將圖形轉(zhuǎn)像素,就會(huì)得到圖1.14、圖1.15這樣的結(jié)果

圖1.14

????????可以看到,由于點(diǎn)包含判斷錯(cuò)誤了,所以求出的像素點(diǎn)就不對(duì)了。

圖1.15

????????在看了利用qt庫(kù)的A3shape的bug以后,咱們知道現(xiàn)在既然能判斷一個(gè)點(diǎn)是否包含在一個(gè)帶有曲線路徑的繪圖內(nèi),那就可以利用這個(gè)方式,來(lái)快速的將圖形轉(zhuǎn)像素了,單獨(dú)寫(xiě)一個(gè)轉(zhuǎn)像素的函數(shù)(當(dāng)然不是用判斷點(diǎn)包含的函數(shù)來(lái)寫(xiě),而是用判斷點(diǎn)包含的思路來(lái)寫(xiě)),這樣寫(xiě)出的函數(shù)就比Yutils的轉(zhuǎn)像素更快(曲線越多,快的就越多)。那么直接將曲線繪圖轉(zhuǎn)像素的函數(shù)就在后面的視頻中講。

????????另外,文章中一些名字完全是我瞎取的,因?yàn)閹в星€的交點(diǎn)計(jì)數(shù)算法是我自己瞎想的,所以為了方便稱呼就取名為端點(diǎn)計(jì)數(shù)原則了,然后比如此時(shí)bottom這名字也是我瞎取的,但是我覺(jué)得這名字還是比較貼切的,應(yīng)該比較好理解。


本文寫(xiě)于2021年1月22日(測(cè)試一下我多久會(huì)發(fā)布這篇專欄,絕大部分專欄都會(huì)等上半年多才發(fā)布)

【Aegisub】判斷點(diǎn)是否包含在任意(含曲線命令的)繪圖內(nèi)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
马关县| 县级市| 芒康县| 唐海县| 临夏县| 石门县| 乐至县| 临沂市| 明水县| 东乌珠穆沁旗| 永平县| 海原县| 鹿泉市| 枞阳县| 博客| 年辖:市辖区| 永嘉县| 黄大仙区| 綦江县| 渝北区| 崇信县| 高邑县| 行唐县| 台江县| 贵南县| 南汇区| 巴中市| 襄樊市| 惠来县| 长武县| 乌拉特前旗| 邛崃市| 清涧县| 雷波县| 东丰县| 桃江县| 阜宁县| 彭山县| 客服| 新田县| 中方县|