【问题标题】:Computing the Radius of Curvature of a Bezier Curve Given Control Points给定控制点计算贝塞尔曲线的曲率半径
【发布时间】:2017-10-16 04:29:58
【问题描述】:

我正在尝试编写一个以曲率作为优化参数之一的遗传算法。我想根据贝塞尔曲线的控制点计算曲率。我有一个想要优化的最小曲率半径。我一直在参考这篇论文: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);

}

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

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

【问题讨论】:

  • 您实现的函数似乎与参数平面曲线曲率半径的实际函数不匹配。
  • @Mike'Pomax'Kamermans 是的,这就是我的想法,我正在研究的论文使用了这个功能。

标签: bezier


【解决方案1】:

曲率半径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₁、P₂ 和 P₃ 的二次贝塞尔曲线,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 应该涵盖该特定用例的“操作方法”。

【讨论】:

  • 我有点不清楚我在这个问题中要寻找什么,我深表歉意。我正在寻找一种方法来获得曲线中给定 3 个点的曲率半径,而不是评估曲线上给定点的曲率。
  • 你不能,你只能在“一点”计算贝塞尔曲线的圆弧半径,而不是“在一个区间内”,所以这听起来像你实际上 want 是一种将曲线部分近似为圆弧的方法。在这种情况下,pomax.github.io/bezierinfo/#arcapproximation 涵盖了这一点。
  • 我不明白您所说的“为 x 和 y 评估这些实际上只是“使用 x 或 y 坐标””以及这与事实之间的关系,例如x' = Px₁'(t-1) + Px₂'(t)x' 的这个定义从何而来(相对于B(t)' 的定义,它是根据两点的导数来定义的,甚至不清楚这意味着什么)?
  • 请参阅pomax.github.io/bezierinfo/#derivatives(在第二个代码块之前的帖子中明确链接),它详细解释了为什么衍生品就是我声称的那样。贝塞尔导数非常容易写出,因为每个导数都少一个坐标,并且导数坐标是原始集合的非常简单且干净的插值。为了形成 x'、y'、x'' 和 y'' 项,我们从二次 x 和 y 公式开始,并根据 Bezier 推导规则对它们进行简化。因为我们知道t,所以它们都计算为常量。
  • @Mike'Pomax'Kamermans 为了形成 x'、y'、x'' 和 y'' 项,我们从 x 和 y 的二次公式开始,然后减少它们根据贝塞尔推导规则,您所说的“贝塞尔推导规则”是什么意思?顺便说一句,我对贝塞尔并不熟悉。我试图理解您的推导,以便将其应用于 Catmull-Rom 样条的情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-26
  • 2018-03-10
  • 2011-08-03
  • 2014-11-01
  • 2011-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多