关于Bezier曲线的相关推导
有关的基础知识和背景介绍,大家可以参考
贝塞尔曲线简单介绍_xiaozhangcsdn的博客-CSDN博客blog.csdn.net这篇文章,这里不多做介绍了,本文只是完成对于相关公式的推导和证明,以及具体的代码实现。
首先回忆一次Bezier曲线公式:
设
是平面的任意两点,则
两点连线的参数方程可表示为:
其中,
为参数,
二次Bezier曲线公式:
二次Bezier曲线有三个控制点,假设分别为
假设
分别是线段
和线段
上的两个动点,
坐标的参数表 示分别为:
那么根据
,二次Bezier曲线表达式为:
更高阶的Bezier曲线公式:
假设
表示
阶Bezier曲线的第
个控制点的系数。
将
中的
换成
,
换成
所以在
中,新的
因此有下面的递推公式[1]:
下面证明:
证明: 采用数学归纳法,当
时,上式都成立,
假设当
的时,有
,
当
时,利用递推公式
有:
所以当
时,归纳假设也成立
证毕。
所以我们可以表示任意
阶Bezier曲线的表达式
附:python 代码实现Bezier曲线
import numpy as np
import matplotlib.pyplot as plt
def B_nx(n, i, x):
if i > n:
return 0
elif i == 0:
return (1-x)**n
elif i == 1:
return n*x*((1-x)**(n-1))
return B_nx(n-1, i, x)*(1-x)+B_nx(n-1, i-1, x)*x
def get_value(p, canshu):
sumx = 0.
sumy = 0.
length = len(p)-1
for i in range(0, len(p)):
sumx += (B_nx(length, i, canshu) * p[i][0])
sumy += (B_nx(length, i, canshu) * p[i][1])
return sumx, sumy
def get_newxy(p,x):
xx = [0] * len(x)
yy = [0] * len(x)
for i in range(0, len(x)):
print('x[i]=', x[i])
a, b = get_value(p, x[i])
xx[i] = a
yy[i] = b
print('xx[i]=', xx[i])
return xx, yy
p = np.array([ #控制点,控制贝塞尔曲线的阶数n
[2, -4],
[3, 8],
[5, 1],
[7, 6],
[9, 4],
[7, 1],
])
x = np.linspace(0, 1, 101)
xx, yy = get_newxy(p, x)
plt.plot(xx, yy, 'r', linewidth=1) # 最终拟合的贝塞尔曲线
plt.scatter(xx[:], yy[:], 1, "blue") #散点图,表示采样点
plt.show()
n=3,二阶
n=4, 三阶
n=5,四阶
n=6,五阶
未完待续!欢迎各位多多补充,不吝赐教!
以下是最近的一些补充知识:
定义一种不含参数的势函数:
其具有以下性质:
(1)端点性:
(2) 导数性:对
有
(3) 中点性:
(4) 对称性:
(5) 单调性:对于固定的自然数k,
关于变量t(
)上单调递减;对于固定变量t,当
时候,
关于参数t单调递增,当
时,
关于参数t单调递减。
前四个结论都是显然的,这里证明结论(5)
所以
,即:
时候,
关于参数t单调递增,
时候,
关于参数t单调递减。
此处用到了升阶公式:
证明如下:
同时,我们注意到:
所以,有:
从而
。
这样就完成了定理5的证明。
当然还有一些含参数的势函数,不在继续展开。有了势函数,就可以利用它构造过渡曲线。
参考
- ^这里有一篇文章,他的递推公式有点错误,可能是他笔误吧 https://www.jianshu.com/p/8f82db9556d2