一、简介
贝塞尔曲线(英语:Bézier curve)是计算机图形学中相当重要的参数曲线。更高维度的广泛化贝塞尔曲线就称作贝塞尔曲面,其中贝塞尔三角是一种特殊的实例。
贝塞尔曲线于1962年,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由保尔·德·卡斯特里奥于1959年运用德卡斯特里奥算法开发,以稳定数值的方法求出贝塞尔曲线。
二、数学推导
线性贝塞尔曲线
给定点P0、P1,线性贝塞尔曲线只是一条两点之间的直线。这条线由下式给出:
二阶贝塞尔曲线
二次方贝塞尔曲线的路径由给定点
P
0
、
P
1
、
P
2
P_0、P_1、P_2
P0、P1、P2 的函数
B
(
t
)
B(t)
B(t) 追踪:
三阶贝塞尔曲线
P
0
、
P
1
、
P
2
、
P
3
P_0、P_1、P_2、P_3
P0、P1、P2、P3 四个点在平面或在三维空间中定义了三次方贝塞尔曲线。曲线起始于
P
0
P_0
P0 走向
P
1
P_1
P1,并从
P
2
P_2
P2 的方向来到
P
3
P_3
P3。一般不会经过
P
1
P_1
P1 或
P
2
P_2
P2;这两个点只是在那里提供方向信息。
P
0
P_0
P0 和
P
1
P_1
P1之间的间距,决定了曲线在转而趋进
P
2
P_2
P2 之前,走向
P
1
P_1
P1 方向的“长度有多长”。
曲线的参数形式为:
n n n 阶贝塞尔曲线
n n n 阶贝塞尔曲线可如下推断,给定点 P 0 、 P 1 、 … 、 P n P_0、P_1、…、P_n P0、P1、…、Pn,其贝塞尔曲线即
例如
n
=
5
n = 5
n=5:
如上公式可如下递归表达: 用表示由点
P
0
、
P
1
、
…
、
P
n
P_0、P_1、…、P_n
P0、P1、…、Pn 所决定的贝塞尔曲线。则
用平常话来说, n n n 阶的贝塞尔曲线,等价于两个 n − 1 n - 1 n−1 阶贝塞尔曲线之间的插值。
三、代码实现
cv::Point2f recursive_bezier(const std::vector<cv::Point2f> &control_points, int startIndex, int endIndex, float t)
{
int pointNum = endIndex - startIndex + 1;
if (1 == pointNum)
{
return control_points[startIndex];
}
if (pointNum == 2)
{
return (1 - t) * control_points[startIndex] + t * control_points[endIndex];
}
else
{
return (1 - t) * recursive_bezier(control_points, startIndex, endIndex - 1, t)
+ t * recursive_bezier(control_points, startIndex + 1, endIndex, t);
}
}
void bezier(const std::vector<cv::Point2f> &control_points, cv::Mat &window)
{
for (double t = 0.0; t <= 1.0; t += 0.001)
{
auto point = recursive_bezier(control_points, 0, control_points.size() - 1, t);
window.at<cv::Vec3b>(point.y, point.x)[1] = 255;
}
}
参考链接
[1] Bézier curve:https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Constructing_B.C3.A9zier_curves
[2] 贝塞尔曲线演示:https://www.jasondavies.com/animated-bezier/