我正在尝试编写一种以曲率作为优化参数之一的遗传算法。我想根据贝塞尔曲线的控制点计算曲率。我有一个想要优化的最小曲率半径。我一直在引用这篇论文: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);
}
Run Code Online (Sandbox Code Playgroud)
这个函数的结果似乎不正确。我对路径中的每个点运行此函数,保存最后两个点,然后获取所有点的最小半径。当我绘制路径时,该函数的计算结果与我直观看到的结果之间似乎存在重大差异。执行此操作的正确方法是什么?
编辑:我正在计算三个控制点之间的曲率半径,而不是曲线中给定点的曲率半径,如果不清楚,我很抱歉。
曲率半径 R(t) 等于 1/\xce\xba(t),其中 \xce\xba(t) 是曲线在 t 点的曲率,对于参数化平面曲线为:
\n\n x\'y" - y\'x"\n\xce\xba(t) = --------------------\n (x\'\xc2\xb2 + y\'\xc2\xb2)^(3/2)\nRun Code Online (Sandbox Code Playgroud)\n\n(其中^(3/2)确实是3/2,但您不能在代码块中使用 html 进行上标格式设置,并且 (t) 部分已从 x 和 y 的函数中删除,因为这会使内容变得不必要地难以阅读)
因此,对于具有控件 P\xe2\x82\x81、P\xe2\x82\x82 和 P\xe2\x82\x83 的二次贝塞尔曲线,一阶和二阶导数使用以下控制点:
\n\nB(t)\': P\xe2\x82\x81\' = 2(P\xe2\x82\x82 - P\xe2\x82\x81), and P\xe2\x82\x82\' = 2(P\xe2\x82\x83 - P\xe2\x82\x82)\nB(t)": P\xe2\x82\x81" = (P\'\xe2\x82\x82 - P\'\xe2\x82\x81)\nRun Code Online (Sandbox Code Playgroud)\n\n评估 x 和 y 的值实际上只是“使用 x 或 y 坐标”,因此:
\n\nx\' = Px\xe2\x82\x81\'(t-1) + Px\xe2\x82\x82\'(t)\ny\' = Py\xe2\x82\x81\'(t-1) + Py\xe2\x82\x82\'(t)\nx" = Px\xe2\x82\x81"\ny" = Py\xe2\x82\x81"\nRun Code Online (Sandbox Code Playgroud)\n\n注意 x" 和 y" 只是常数。我们将这些值代入 \xce\xba(t) 的函数中,当然前提是分母不为零(表示一条线段,没有曲率半径),然后我们就知道 R(t ) 是因为这只是倒数。
\n\n但我们实际上不需要做任何事情,因为我们可以做一个简单的观察:将圆也视为参数曲线,我们可以根据以下事实立即找到它的半径:曲线的导数与圆在同一点的导数相等。此外,我们知道圆上任何位置导数的长度都相同(因为它是一个圆,根据定义,它关于原点径向对称)。因此,我们可以解决以下问题:
\n\nB(t) = P1(1-t)^2 + 2*P2(1-t)t + P3t^2\nB(t)\' = 2*(P2-P1)(1-t) + 2*(P3-P2)t\n\nC(s) = { r*sin(s), r*cos(s) }independent of \'t\')\nC(s)\' = { r*cos(s), -r*sin(s) }\n\nd = |B(t)\'| = |C(s = any value, so let\'s pick 0)\'|\nd = C(0)\' = | (r,0) | = r\nRun Code Online (Sandbox Code Playgroud)\n\n我们就完成了。B(t)点的曲率半径等于B(t)'的向量长度,这样实现起来更容易,运行起来也更快。
\n\n最后,如果您真正想要的只是用圆弧近似曲线部分,那么https://pomax.github.io/bezierinfo/#arcapproximation 应该涵盖该特定用例的“如何做”。
\n| 归档时间: |
|
| 查看次数: |
7917 次 |
| 最近记录: |