前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >贝塞尔曲线

贝塞尔曲线

作者头像
为为为什么
发布2024-09-20 16:37:43
980
发布2024-09-20 16:37:43
举报
文章被收录于专栏:又见苍岚

应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,如 Photoshop 中的钢笔工具,本文记录相关内容。

简介

贝塞尔曲线 (Bézier Curve) 是由法国工程师皮埃尔·贝兹 (Pierre Bézier) 于 1962 年所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计 1。贝塞尔曲线最初由保尔·德·卡斯特里奥 (Paul de Casteljau) 于 1959 年运用德卡斯特里奥算法 (De Casteljau’s Algorithm) 开发,以稳定数值的方法求出贝塞尔曲线。

贝塞尔曲线

线性贝塞尔曲线

,线性贝塞尔曲线定义为:

B \left(t\right) = \left(1 - t\right) P_0 + t P_1, t \in \left[0, 1\right]

不难看出,线性贝塞尔曲线即为点

二阶贝塞尔曲线

,二次贝塞尔曲线定义为:

B \left(t\right) = \left(1 - t\right)^2 P_0 + 2 t \left(1 - t\right) P_1 + t^2 P_2, t \in \left[0, 1\right]

二次贝塞尔曲线生成过程如下图所示:

三阶贝塞尔曲线

,三次贝塞尔曲线定义为:

B \left(t\right) = \left(1 - t\right)^3 P_0 + 3 t \left(1 - t\right)^2 P_1 + 3 t^2 \left(1 - t\right) P_2 + t^3 P_3, t \in \left[0, 1\right]

三次贝塞尔曲线生成过程如下图所示:

测试曲线

  • 三阶贝塞尔曲线

一般化的贝塞尔曲线

, n 阶贝塞尔曲线定义为:

B \left(t\right) = \sum_{i=0}^{n}{\binom{n}{i} \left(1 - t\right)^{n - i} t^{i} P_i}, t \in \left[0, 1\right]

其中

b_{i, n} \left(t\right) = \binom{n}{i} \left(1 - t\right)^{n - i} t^{i}

称之为 n 阶 Bernstein 多项式,点

可以认为贝塞尔曲线就是多个控制点之间连成的线段上,递归实现的线性变化。

贝塞尔曲线的绘制

通过前面的介绍,也就是说我们的贝塞尔曲线可以通过一堆控制点来画出,那么假如我们有如下三个控制点,我们怎么来画出一个贝塞尔曲线呢?

贝塞尔曲线参数形式的表达,是对曲线上各个点坐标的表达,那么我们只需要根据这些控制点依照 t 的变换求出对应的点,即可求出曲线上所有的点,从而形成曲线。

那么问题就变成了我知道控制点和 t 的值,求曲线上对应的点 P(t) 的坐标是多少。这个问题我们可以使用德卡斯特里奥算法(de Casteljau Algorithm)来解决。

我们先把 P_{0}, P_{1}, P_{2} \ldots P_{n} 连线,例子中就三个点,连线如下:

通过线性插值在线段上找到中间点 P_{0,1} ,使得 P_{0} P_{0,1}: P_{0,1} P 1=t: 1-t ,其他线段也如此,我们就可得到下图

然后我们连接 P_{0,1} P_{1,1} ,得到新的线段,然后在该线段上再取一点使得该线段被分为 t 和 1-t,那么就会得到下图:

如果有更多的控制点,我们也可以使用相同的方法来求出曲线上的一点,如下图是四个控制点求曲线上一点的过程:

伯恩斯坦多项式与de Casteljau算法

拿最简单的二阶贝塞尔曲线举例,如下图:

图中蓝色的点为控制点,他们的坐标我们是知道的,那么通过线性插值,我们可以得到求出红色点的坐标:

\begin{array}{l}P_{0}^{1}=(1-t) P_{0}+t P_{1} \ P_{1}^{1}=(1-t) P_{1}+t P_{2}\end{array}

红色点坐标求出后,我们自然可以再求出绿色点的坐标:

P_{0}^{2}=(1-t) P_{0}^{1}+t P_{1}^{1}

把上面两个式子带入到下面的式子,得到:

\begin{array}{l}P_{0}^{2}=(1-t)\left((1-t) P_{0}+t P_{1}\right)+t\left((1-t) P_{1}+t P_{2}\right) \ =(1-t)^{2} P_{0}+2 t(1-t) P_{1}+t^{2} P_{2}\end{array}

我们还可以用这个方法去算三阶的,四阶的,乃至n阶的贝塞尔曲线,得到的结果为曲线上任意一点P(t)是各个顶点的线性组合,即:

P(t)=k_{0} P_{0}+k_{1} P_{1}+k_{2} P_{2}+\ldots+k_{n} P n

对于 n 阶的贝塞尔曲线,曲线上 t 位置上的点 P(t) 的坐标是由 n+1 个顶点和伯恩斯坦多项式的乘积求和:

P(t)=B_{0}^{n}(t) P_{0}+B_{1}^{n}(t) P_{1}+B_{2}^{n}(t) P_{2}+\ldots+B_{n}^{n}(t) P n=\sum_{i=0}^{n} P_{i} B_{i}^{n}(t)

上面式子也就是Forrest在1972年提出的结论。因此我们就可以使用de Casteljau算法来算曲线上任意一点的坐标,该算法是计算伯恩斯坦多项式的一种递归算法,直接方法相比较慢,但它在数值上更为稳定。

前面我们是从线性插值计算,逆推到伯恩斯坦多项式。现在我们来看看怎么直接使用伯恩斯坦多项式得到递归的结果。

伯恩斯坦多项式具有递归性,即可以把 n 阶的伯恩斯坦多项式写成 n-1 阶的多项式组合:

B_{i}^{n}(t)=(1-t) B_{i}^{n-1}(t)+t B_{i-1}^{n-1}(t)

也就是说原本的方程式:

P(t)=B_{0}^{n}(t) P_{0}+B_{1}^{n}(t) P_{1}+B_{2}^{n}(t) P_{2}+\ldots+B_{n}^{n}(t) P n

可以写成:

\begin{array}{l}P(t)=(1-t) B_{0}^{n-1}(t) P_{0}+\left((1-t) B_{1}^{n-1}(t)+t B_{0}^{n-1}(t)\right) P_{1}+ \ \left((1-t) B_{2}^{n-1}(t)+t B_{1}^{n-1}(t)\right) P_{2}+\ldots+t B_{n-1}^{n-1}(t) P n\end{array}

就是线性插值。对于后面的几项也是一样的,上面式子就可以写成:

\begin{array}{l}P(t)=\left((1-t) P_{0}+t P_{1}\right) B_{0}^{n-1}(t)+\left((1-t) P_{1}+t P_{2}\right) B_{1}^{n-1}(t)+((1- \left.t) P_{2}+t P_{3}\right) B_{2}^{n-1}(t)+\ldots+\left((1-t) P_{n-1}+t P_{n}\right) B_{n-1}^{n-1}(t)\end{array}

那么就可以把贝塞尔曲线的方程式写成:

\begin{array}{l}P(t)=\sum_{i=0}^{n} P_{i}\left((1-t) B_{i}^{n-1}(t)+t B_{i-1}{n-1}(t)\right)=\sum_{i=0}{n-1}\left((1-t) P_{i}+\right. \left.t P_{i+1}\right) B_{i}^{n-1}(t)\end{array}

也就是说我们把原本 n 个控制点,通过

参考资料

文章链接:

https://cloud.tencent.com/developer/article/2452284

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-9-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 贝塞尔曲线
    • 线性贝塞尔曲线
      • 二阶贝塞尔曲线
      • 三阶贝塞尔曲线
      • 测试曲线
      • 一般化的贝塞尔曲线
      • 贝塞尔曲线的绘制
      • 伯恩斯坦多项式与de Casteljau算法
      • 参考资料
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档