从沿该曲线的点导出贝塞尔曲线的控制点的算法?

时间:2013-10-07 05:18:14

标签: algorithm bezier

我一直在寻找,但显然没有找到一种算法,它允许我插入已知沿曲线的x,y坐标列表,以便获得立方体的4个控制点bezier曲线吐出来。

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

谢谢!

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

2 个答案:

答案 0 :(得分:9)

所以我假设端点是固定的,然后你有许多(x,y)采样点,你想要用立方贝塞尔曲线。

您拥有的样本点数量将决定采取何种方法。让我们看看几个案例:

2分

2个样本点是最简单的情况。如果计算终点,那么总共可以得到4分。这是立方贝塞尔曲线中的CV数。要解决此问题,您需要两个采样点的参数(t)值。然后你有一个2个方程和2个点需要求解的系统,其中方程是你选择的t值的贝塞尔曲线的参数方程。

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

1分

这类似于2分,但您没有足够的信息来唯一确定您的所有自由度。我建议的是拟合二次Bezier,然后提升度。我在this question中写了一个二次拟合的详细例子。

超过2分

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

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

在这个free cagd textbook第11章中对这些步骤有了很好的描述。它讨论了拟合b样条,但是一个三次贝塞尔曲线是一种b样条(结矢量是0,0,0) ,1,1,1并且有4分)。

答案 1 :(得分:6)

假设你有一条曲线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]);
}