计算给定控制点的Bezier曲线的曲率半径

时间:2017-10-16 04:29:58

标签: bezier

我正在尝试编写一个带曲率的遗传算法作为优化参数之一。我想根据贝塞尔曲线的控制点计算曲率。我有一个我想要优化的最小曲率半径。我一直在引用这篇论文:https://arxiv.org/pdf/1503.01524.pdf

在论文中,有一个函数采用三角形的边长来得到隐含的曲率半径,这是我实现的。这是我目前的代码:

// Computes the curvature implied by 3 control points of a bezier curve
float curvature(float4 p0, float4 p1, float4 p2) {

    // Get the triangle side lengths
    float a = distance(p0, p1);
    float b = distance(p1, p2);
    float c = distance(p2, p0);

    // Do the curvature calculation
    float num = a * b * c;
    float denom = (a + b + c) * (b + c - a) * (a - b + c) * (a + b - c);

    return num / sqrt(denom);

}

此功能的结果似乎不正确。我为路径中的每个点运行此函数,保存最后两个,然后从所有点中获得最小半径。当我绘制路径图时,此函数的计算与我可以直观地看到的内容之间似乎存在重大差异。什么是正确的方法来做到这一点?

编辑: 我想要计算三个控制点之间的曲率半径,而不是曲线中的给定点,如果不清楚则道歉。

1 个答案:

答案 0 :(得分:2)

曲率半径R(t)等于1 /κ(t),其中κ(t)是点t处曲线的曲率,a parametric planar curve为:

            x'y" - y'x"
κ(t)  = --------------------
         (x'² + y'²)^(3/2)

^(3/2)实际上是 3/2 ,但你不能在代码块中使用html进行上标格式化,并且(t)部分已经不在x和y的函数,因为这会使事情变得不必要地阅读)

因此,对于具有控制P 1,P 2和P 3的二次贝塞尔曲线,the first and second derivatives use the following control points

B(t)': P₁' = 2(P₂ - P₁), and P₂' = 2(P₃ - P₂)
B(t)": P₁" = (P'₂ - P'₁)

为x和y评估这些只是“使用x或y坐标”,所以:

x' = Px₁'(t-1) + Px₂'(t)
y' = Py₁'(t-1) + Py₂'(t)
x" = Px₁"
y" = Py₁"

注意到x“和y”只是常量。我们将这些值插入到κ(t)的函数中,假设分母不为零,当然(表示没有曲率半径的线段)然后我们知道R(t)是什么,因为那是只是反转值。

但我们实际上并不需要做任何这样的事情,因为我们可以做一个简单的观察:将圆圈视为参数曲线,我们可以根据矢量长度的事实立即找到它的半径曲线的导数和相同点处的圆的导数是相等的。另外,我们知道导数的长度在圆上的任何地方都是相同的(因为它是一个圆,根据定义它是关于原点的径向对称)。因此,我们可以解决以下问题:

B(t)  = P1(1-t)^2 + 2*P2(1-t)t + P3t^2
B(t)' = 2*(P2-P1)(1-t) + 2*(P3-P2)t

C(s)  = { r*sin(s), r*cos(s) }independent of 't')
C(s)' = { r*cos(s), -r*sin(s) }

d = |B(t)'| = |C(s = any value, so let's pick 0)'|
d = C(0)' = | (r,0) | = r

我们已经完成了。点B(t)处的曲率半径等于B(t)'的向量长度,这更容易实现,并且运行得更快。

最后,如果您真正想要的只是用圆弧近似曲线的部分,那么https://pomax.github.io/bezierinfo/#arcapproximation应该涵盖该特定用例的“如何”。