跳到主要内容

贝塞尔曲线

· 阅读需 3 分钟

二次贝塞尔曲线

二次贝塞尔曲线的公式为:

B(t)=(1t)2P0+2t(1t)P1+t2P2,t[0,1]B(t) = (1-t)^2P_0 + 2t(1-t)P_1 + t^2P_2, t \in [0, 1]

我们先来回归一下高中数学,二次函数的标准形式为:

y=ax2+bx+cy = ax^2 + bx + c

其中,aa 为二次项系数,bb 为一次项系数,cc 为常数项。

二次函数的图像为抛物线,抛物线的顶点坐标为:

x=b2a,y=b24ac4ax = -\frac{b}{2a}, y = -\frac{b^2-4ac}{4a}

我们可以把二次贝塞尔曲线的公式转换为二次函数的标准形式:

B(t)=(P02P1+P2)t2+2(P1P0)t+P0B(t) = (P_0 - 2P_1 + P_2)t^2 + 2(P_1 - P_0)t + P_0

拿二阶过程描述如下:

  1. 将控制点连接起来,得到两条线段;
  2. 取 t 值,计算出两条线段上的点;
  3. 将两条线段上的点连接起来,得到一条线段;
  4. 取 t 值,计算出线段上的点;
  5. 重复 2、3 步骤,直到 t 值为 1。

高阶的不过是需要多重复几次直到剩一条线段,然后再取 t 值计算出点。

此过程可以用向量表示

B(t)=i=0n(ni)(1t)nitiPiB(t) = \sum_{i=0}^n \binom{n}{i} (1-t)^{n-i}t^iP_i

程序设计

一般化贝塞尔曲线公式

B(t)=i=0n(ni)(1t)nitiPiB(t) = \sum_{i=0}^n \binom{n}{i} (1-t)^{n-i}t^iP_i

这个公式是贝塞尔曲线的定义。它描述了如何根据一组控制点 P_i 和一个参数 t 计算贝塞尔曲线上的点 B(t)。

基于多项式的实现

function bezier(points, t) {
const n = points.length - 1;
let x = 0;
let y = 0;
for (let i = 0; i <= n; i++) {
const b = binomial(n, i);
const a = Math.pow(1 - t, n - i);
const c = Math.pow(t, i);
x += b * a * c * points[i].x;
y += b * a * c * points[i].y;
}
return { x, y };
}

function binomial(n, i) {
return factorial(n) / (factorial(i) * factorial(n - i));
}

function factorial(n) {
let result = 1;
for (let i = 1; i <= n; i++) {
result *= i;
}
return result;
}

binomial 这里查看 二项式定理

基于递归实现

function bezier(points, t) {
const n = points.length - 1;
if (n === 0) {
return points[0];
}
const left = bezier(points.slice(0, n), t);
const right = bezier(points.slice(1, n + 1), t);
return {
x: (1 - t) * left.x + t * right.x,
y: (1 - t) * left.y + t * right.y,
};
}