贝塞尔曲线 ( Bézier curve ) ,又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线,它是依据四个位置任意的点坐标绘制出的一条光滑曲线。
Bézier 算法介绍
我们上次课学了 DDA 直线算法
、 Bresenham 直线算法
,虽然算法不同,但其核心思路都是根据直线的参数方程,通过控制点位置,计算直线上的其他点的坐标。确定一条直线只需要两个控制点;确定一条曲线至少需要三个控制点;而确定一条贝塞尔曲线则需要四个控制点。
下面我们将从 线性公式
,到 二次方公式
再到 三次方公式
,然后推导出一般性的 n 次方贝塞尔曲线公式
。
1. Linear Bézier curves
给定点 P0
、P1
,线性贝塞尔曲线只是一条两点之间的直线。这条线由下式给出:
其等同于线性插值。
2. Quadratic Bézier curves
二次方贝塞尔曲线的路径由给定点 P0
、P1
、P2
的函数 B(t)
给出:
当参数 t
变化时,绘制出的曲线如下图所示:
3. Cubic Bézier curves
P0
、P1
、P2
、P3
四个点在平面或在三维空间中定义了三次方贝塞尔曲线。曲线起始于 P0
走向 P1
,并从 P2
的方向来到 P3
。一般不会经过 P1
或 P2
;这两个点只是在那里提供方向资讯。P0
和 P1
之间的间距,决定了曲线在转而趋进 P3
之前,走向 P2
方向的 长度有多长
。
当参数 t
变化时,绘制出的曲线如下图所示:
4. Higher-Order Bézier curves
由以上公式可以推断得到 n阶贝塞尔曲线公式
。
给定 n 个控制点 P0
、P1
、… 、Pn
,曲线轨迹由下述公式给出:
(貌似跟老师PPT上的不一样是不是?没关系,整理一下就好了)
对于 n 个控制点 Pk = (xk, yk, zk)
,曲线上的任意一点 P(u)
坐标:
其中,u
是函数的参数,变化范围为 0 ~ 1
。
当参数 u
变化时,绘制出的曲线如下图所示:
关键代码
//计算n!/(k!(n-k)!),存储到c[k],其中k=0,1,...,n
void BezierCurve::binomiaCoeffs(int n, int *c)
{
int k, i;
for (k = 0; k <= n; k++)
{
//计算n!/(k!(n-k)!)
c[k] = 1;
for (i = n; i >= k + 1; i--)
c[k] *= i;
for (i = n - k; i >= 2; i--)
c[k] /= i;
}
}
//Bezier曲线中,起点为B(0),终点为B(1),该函数计算点B(u)的坐标,其中0<=u<=1;
//bezPt 指向B(u)的指针,
//nCtrlPts 控制点个数
//ctrlPts 控制点内存起始地址
void BezierCurve::computeBezPt(float u, wcPt3D *bezPt, int nCtrlPts, wcPt3D *ctrlPts, int *C)
{
//powf(x,k) x的k次方
int k, n = nCtrlPts - 1;
float bezBlendFcn;
bezPt->x = bezPt->y = bezPt->z = 0.0;
for (k = 0; k < nCtrlPts; k++)
{
bezBlendFcn = C[k] * pow(u, k)*pow(1 - u, n - k);
bezPt->x += ctrlPts[k].x*bezBlendFcn;
bezPt->y += ctrlPts[k].y*bezBlendFcn;
bezPt->z += ctrlPts[k].z*bezBlendFcn;
}
}
//计算bezier曲线
//ctrlPts 控制点数组内存起始地址
//nCtrlPts 控制点个数
//bezCurvePts 曲线点数组内存起始地址
//nBezCurvePts 曲线点个数
void BezierCurve::bezier(wcPt3D *ctrlPt3D, int nCtrlPts, int nBezCurvePts)
{
wcPt3D BezCurvePt;
float u; int *C, k;
C = new int[nCtrlPts];
binomiaCoeffs(nCtrlPts - 1, C);
for (k = 0; k < nBezCurvePts; k++)
{
u = float(k) / float(nBezCurvePts);
computeBezPt(u, &BezCurvePt, nCtrlPts, ctrlPt3D, C);
plotPoint(BezCurvePt);
}
delete[]C;
}
运行结果示例
参考文献
【1】https://baike.baidu.com/item/%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF/1091769?fr=aladdin
本文由 机灵鹤 SmartCrane 创作
本站文章所有原创文章, 转载前请务必署名
最后编辑时间为: 2018-09-27 23:10