赞
踩
生成过程如下图所示:
- 在二维平面内选三个不同的点(起点A,中间点B,终点C)并依次用线段连接
- 在线段AB和BC上按比例分割找到新的起点和中间点:D、E两点,使得AD/AB=BE/BC
- 连接DE,并在DE上找到新的起点F点,EC上找到新的中间点G点,使其满足DF/DE=EG/EC
- 重复步骤1、2、3,找出符合上述条件的所有点,直到新的起点和终点C重合或者中间点和终点C重合(完全重合或者距离小于某个设定阈值)时结束递归
- 连接上述所有符合条件的点A、D、F、H、J...C,所形成的曲线就是贝塞尔曲线。
上述示意图为二阶贝塞尔曲线形成过程,高阶贝塞尔曲线过程类似,可以使用递归实现。
贝塞尔曲线生成代码如下:
- class Bezier:
- def __init__(self,points,baseRatio=1e-5):
- self.curve = []
- self.ratio = baseRatio
- self.Points = points
- def findP(self): # start,end:矩阵:1*2,1*2。更新p0,p1。ratio:比例:[0,1]
- self.curve.append(self.Points[0])
- self.ratio=self.ratio+1e-2#使raito非固定值,否则递归深度过深,容易栈溢出
- # 寻找pNew
- for ii in range(1, len(self.Points)):
- '''
- * a(x0,y0)
- .* b(x,y)
- ...
- ....
- ....* c(x1,y1)
- (x-x0)/(x1-x0)=0.4-->x=(x1-x0)*0.4+x0
- (y-y0)/(y1-y0)=0.4-->y=(y1-y0)*0.4+y0
- '''
- pNew = [(self.Points[ii][0] - self.Points[ii - 1][0]) * self.ratio + self.Points[ii - 1][0],
- (self.Points[ii][1] - self.Points[ii - 1][1]) * self.ratio + self.Points[ii - 1][1]]
- # 更新
- self.Points[ii - 1] = pNew
- if np.sqrt(sum(np.power((self.Points[-1][0] - self.Points[0][0],self.Points[-1][1] - self.Points[0][1]), 2)))>1e-5:#新的起点和终点重合时,结束递归
- self.findP()
- def run(self):
- self.findP()
- self.curve.append(self.Points[-1])
- if __name__=='__main__':
- Points = [[1, 1], [2, 1], [2, 2], [1, 2]]
- xx = Bezier(p)
- xx.run()
- xx.curve = np.array(xx.curve)
- plt.figure(1)
- plt.plot(xx.curve[:,0],xx.curve[:,1])
- plt.show()
简单的贝塞尔曲线拟合效果如下
如下图所示,点A、点C分别为起点和终点,"中间"点B称为控制点。
通过调整控制点B的位置,可以调整曲线的曲率以及方向(凸或者凹),如下图所示,其中红点为控制点
用贝塞尔曲线拟合,需要注意控制点的选择,还要做平滑优化曲线处理(待完成),如下图所示
待完成
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。