【Aegisub】拆分、分割贝塞尔曲线简单介绍

简单地水一下,简单介绍一下贝塞尔曲线怎么分割、把一条n阶贝塞尔曲线拆成两条n阶贝塞尔曲线。如图1.01中,左边是一条6阶贝塞尔曲线、它的控制多边形的顶点是00、01、02、03、04、05、06这几个点,然后假设在 t (t∈[0,1]) 处将其拆分成两条6阶贝塞尔曲线,然后就慢慢地算啊算,最后就得到了右边的两条6阶贝塞尔曲线

细分出来的第一条6阶贝塞尔曲线的控制多边形顶点是00、10、20、30、40、50、60,细分出来的第二条6阶贝塞尔曲线的控制多边形顶点是60、51、42、33、24、15、06
拆分n阶贝塞尔曲线的算法非常简单,直接利用de Casteljau算法即可
如图1.02,刚刚最开始的曲线的控制多边形顶点是下图的第一列,而分割以后,得到的第一条曲线的控制多边形的顶点就是红色的这一边、第二条曲线的控制多边形的顶点就是蓝色的这一边,所以只需要用第一列一点点地加、加出一列列的即可得到最后需要的这两条边

假设要在 t 处将曲线拆分为两条曲线,则根据第一列可得第二列,00乘以(1-t)加上01乘以t就能得到10(即00点的x乘以(1-t)加上01点的x乘以t就得到了10点的x,然后10点的y同理可得),然后01点来乘以(1-t)加上02点来乘以t就能得到11点了。也就是说,为了得到第二列,需要遍历第一列的点(for i=1,n-1 do),这个点来乘以(1-t)加上这一列的下一个点来乘以t,就得到了下一列的相应的点。比如n阶贝塞尔曲线的控制多边形顶点的x坐标数值装在表x里、y坐标装在y里,那么你要得到第二列就可以是这样的:

这样就得到了第二列的点(每个点的x和y都有了,list_x和list_y),然后第二列也就可以以同样的方式加出第三列,比如10乘以(1-t)加上11乘以t就得到了20,当最后得到这些所有列的时候,就有了两边咱们需要的东西了。所以从一列加得下一列需要一个for循环,所以要得到所有的列就要两个for循环,这很简单吧,for里面一个for而已,也就是:
for i=1,n-1 do
for i2=1,n-i do
巴拉巴拉劈里啪啦
end
end
(总共有n列,但是因为第一列已经有了,所以还需要加出n-1列,所以外层循环是for i=1,n-1 )
那么其实要得到最后的两边(即图1.02中的红色边和蓝色边)也很容易嘛,你算出来一列、这一列的第一个点就是红色需要的、这一列的最后一个点就是蓝色需要的。所以如果你不在意原本的曲线的x、y表改变的话,代码就可以像图1.03这么写:

其中f指的是first、s指的second,所以f_x装的是拆分出来的第一条曲线的控制多边形顶点的x,然后当然第二条曲线的控制多边形顶点直接这么用就会是反过来的(曲线的方向反了,因为添加的时候控制多边形的顶点顺序反过来了),比如本来要得到的控制多边形顶点是60、51、42、33、24、15、06,但是现在这么添加的话,second里面就是06、15、24、33、42、51、60了,那么这样的话曲线方向就和60、51、42、33、24、15、06的相反了,所以如果你想两条细分出来的曲线的方向是舒畅的话,就可以把得到的s_x表和s_y表给反转一下即可
当然如果你不想分割的时候改变原来的x表和y表(即记录原本曲线的控制多边形顶点坐标的两个表)的话,也可以比如这么写:

所以知道了n阶贝塞尔曲线可以拆分为两条n阶贝塞尔曲线,那么当然想在t处拆分一条三阶贝塞尔曲线就一样的简单了。还有,既然可以在t处拆分曲线,那么你就可以得到一条曲线的子曲线(subcurve)了不是吗?也就是说,你可以得到比如在 t1 到 t2 这一段的曲线,如图1.04和图1.05


显然这一段就是从 t1到t2 的曲线的子曲线了
其它代码啥的就在视频里讲了