9

我一直在寻找,但显然没有找到一种算法,该算法将允许我插入已知沿曲线的 x、y 坐标列表,以便获得三次贝塞尔曲线吐出的 4 个控制点出去。

更准确地说,我正在寻找一种算法,该算法将为我提供塑造曲线所需的两个控制点,同时输入一系列离散点,包括确定曲线起点和终点的两个控制点。

谢谢!

编辑:好的,由于数学,一个老对手,我需要询问最适合多项式函数的贝塞尔曲线。

4

2 回答 2

9

所以我假设端点是固定的,然后你有许多 (x,y) 样本点,你想用三次贝塞尔曲线拟合。

您拥有的样本点数将决定采用哪种方法。我们来看几个案例:

2 分

2个样本点是最简单的情况。如果您计算终点,那么总共会给您 4 分。这是三次贝塞尔曲线中 CV 的数量。为了解决这个问题,您需要两个样本点的参数 (t) 值。然后你有一个需要求解的 2 个方程和 2 个点的系统,其中方程是贝塞尔曲线在你选择的 t 值处的参数方程。

t 值可以是您喜欢的任何值,但根据您的数据,使用 1/3 和 2/3,或查看相对距离或沿基线的相对距离,您将获得更好的结果。

1分

这类似于 2 点,只是您没有足够的信息来唯一确定您的所有自由度。我的建议是拟合二次贝塞尔曲线,然后提升度数。我在这个问题中写了一个二次拟合的详细例子。

超过2分

在这种情况下,没有唯一的解决方案。我使用了最小二乘近似,结果很好。步骤是:

  • 为每个样本选择 t 值
  • 将您的方程组构建为矩阵
  • 可选择添加整流罩或其他一些平滑功能
  • 使用最小二乘求解器求解矩阵

这本免费的 cagd 教科书第 11 章对这些步骤进行了很好的描述。它谈到了拟合 b 样条,但三次贝塞尔曲线是 b 样条的一种(结向量是 0,0,0,1,1, 1 分,得 4 分)。

于 2013-10-10T09:11:53.613 回答
7

假设你有一条曲线 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]);
}
于 2015-07-16T11:57:49.107 回答