我一直在寻找,但显然没有找到一种算法,该算法将允许我插入已知沿曲线的 x、y 坐标列表,以便获得三次贝塞尔曲线吐出的 4 个控制点出去。
更准确地说,我正在寻找一种算法,该算法将为我提供塑造曲线所需的两个控制点,同时输入一系列离散点,包括确定曲线起点和终点的两个控制点。
谢谢!
编辑:好的,由于数学,一个老对手,我需要询问最适合多项式函数的贝塞尔曲线。
所以我假设端点是固定的,然后你有许多 (x,y) 样本点,你想用三次贝塞尔曲线拟合。
您拥有的样本点数将决定采用哪种方法。我们来看几个案例:
2 分
2个样本点是最简单的情况。如果您计算终点,那么总共会给您 4 分。这是三次贝塞尔曲线中 CV 的数量。为了解决这个问题,您需要两个样本点的参数 (t) 值。然后你有一个需要求解的 2 个方程和 2 个点的系统,其中方程是贝塞尔曲线在你选择的 t 值处的参数方程。
t 值可以是您喜欢的任何值,但根据您的数据,使用 1/3 和 2/3,或查看相对距离或沿基线的相对距离,您将获得更好的结果。
1分
这类似于 2 点,只是您没有足够的信息来唯一确定您的所有自由度。我的建议是拟合二次贝塞尔曲线,然后提升度数。我在这个问题中写了一个二次拟合的详细例子。
超过2分
在这种情况下,没有唯一的解决方案。我使用了最小二乘近似,结果很好。步骤是:
这本免费的 cagd 教科书第 11 章对这些步骤进行了很好的描述。它谈到了拟合 b 样条,但三次贝塞尔曲线是 b 样条的一种(结向量是 0,0,0,1,1, 1 分,得 4 分)。
假设你有一条曲线 y = f(x)
要定义贝塞尔曲线,您需要 4 个点,例如:P1x、P1y、P2x、P2y、P3x、P3y 和 P4x 和 P4y
P1 和 P4 你是曲线的起点/终点。P2 和 P3 是控制点。您已经知道曲线的起点和终点在哪里。您必须计算 P2 和 P3。x 坐标 P2x 和 P3x 很简单,因为您只需通过选择曲线t
来选择它们,例如 1/3 和 2/3。所以你有 P2x 和 P3x 然后,你会得到一个由两个方程和两个未知数(P2y 和 P3y)组成的系统。在计算了一些数学之后,你最终会得到这样的结果:
(我的 f(x) 是一个三次多项式,这也保证了我能够准确地拟合一条三次贝塞尔曲线。)
/**
@params {Object} firstPoint = {x:...,y...}
@params {Object} lastPoint = {x:...,y...}
@params {Object} cubicPoly Definition of a cubic polynomial in the form y=ax^3+bx^2+c.
Has a method EvaluateAt, which calculates y for a particular x
*/
var CalcBezierControlPoints = function(firstPoint, lastPoint, cubicPoly) {
var xDiff = lastPoint.X - firstPoint.X;
var x1 = firstPoint.X + xDiff / 3.0;
var x2 = firstPoint.X + 2.0 * xDiff / 3.0;
var y1 = cubicPoly.EvaluateAt(x1);
var y2 = cubicPoly.EvaluateAt(x2);
var f1 = 0.296296296296296296296; // (1-1/3)^3
var f2 = 0.037037037037037037037; // (1-2/3)^3
var f3 = 0.296296296296296296296; // (2/3)^3
var b1 = y1 - firstPoint.Y * f1 - lastPoint.Y / 27.0;
var b2 = y2 - firstPoint.Y * f2 - f3 * lastPoint.Y;
var c1 = (-2 * b1 + b2) / -0.666666666666666666;
var c2 = (b2 - 0.2222222222222 * c1) / 0.44444444444444444;
var p2 = {};
var p3 = {};
p2.X = x1;
p2.Y = c1;
p3.X = x2;
p3.Y = c2;
return ([p2, p3]);
}