【问题标题】:Bezier curve arc lengths贝塞尔曲线弧长
【发布时间】:2016-07-28 12:03:35
【问题描述】:

我有一些代码可以计算贝塞尔曲线的长度。我正在尝试为它编写单元测试。但除了琐碎的情况(直线贝塞尔曲线)之外,我不知道长度的任何实际正确值。我上网查了一下,没找到。

有人有这个信息吗?我正在寻找一个表的链接,该表有几行包含四个贝塞尔控制点,然后是一个长度,或者可能在计算长度的绘图程序中创建几个贝塞尔曲线(我尝试使用搅拌机和 inkscape 来获得这个信息,它们非常复杂)。

解决方案。here 下载 pomax 的 bezier javascript 代码,然后在网络浏览器中打开此 html:

<html>
<head>
<script src="bezier.js"></script>
</head>
<body>
<script>
curve = new Bezier([4.0, 0.0,  4.0, 
                    4.0, 0.0,  12.0,
                   16.0, 0.0,  12.0,
                   16.0, 0.0,  4.0]);

document.write(curve.length());
</script>
</body>
</html>

【问题讨论】:

标签: math geometry bezier


【解决方案1】:

如果您希望 实际 弧长进行测试,请实施 https://github.com/Pomax/bezierjs/blob/gh-pages/lib/bezier.js#L602-604 - 这将根据 Legendre-Gauss quadrature 评估为您提供任意准确的数字(您不必了解它是如何工作的,虽然视频链接向您展示了它实际上非常简单。因此,实现它真的很容易)。

另一种选择是依赖 wolframalpha.com 或 Mathematica (which is free if you own a Raspberri PI) 之类的东西:设置一条随机曲线,让它们“正确”计算长度,然后在单元测试中使用该结果作为参考值。

【讨论】:

  • 不幸的是,我给我的孩子买了 Arduinos 而不是 Raspberry PI。我在我的问题中包含了一个调用您的 js 代码作为答案的最小示例。不过,我无法让 Wolfram Alpha 给我答案。我尝试了诸如“BezierFunction [{{4,4}, {4,12}, {16,12}, {16,4}}] 的弧长在 0 和 1 之间”之类的东西,使用长度弧长,BezierCurve 方法并尝试整合立方距离的 sqrt - 希望它会做一些聪明的事情(一周前现在细节如此模糊)。我真的应该学习如何更好地使用这些工具。
  • 是的,由于我不知道的原因,没有内置的贝塞尔函数,所以你最终不得不把它们写出来,like so,另外,考虑到 Raspberry Pi 的 35 美元成本,我专门为Mathematica买了一个,家用300美元,否则=P
  • 好吧,我被卖了。下次我孩子的生日到来时,我会得到一个。希望你得到佣金:)
  • 是的,你必须从点手动求解系数。那正确吗?不利的一面是,我必须手动计算系数(我在代码中执行此操作),如果我对如何完成此操作有错误的理解,那么我可能会复制与我的代码手动计算系数相同的错误逻辑.所以我怀疑使用你的 js 库对于这个特定的应用程序更好。也就是说,现在我知道该怎么做了。这很好,因为我现在学到了一些新东西。
【解决方案2】:

您可以尝试以下方法对您的代码进行单元测试:

1) 使用 De Casteljau 算法将贝塞尔曲线拆分为多条贝塞尔曲线
2) 计算每条贝塞尔曲线的弧长,然后计算它们的总和。
3) 计算原始贝塞尔曲线的弧长。
4) 比较第 2 步和第 3 步的结果。如果您的代码正确,它们之间的差异应该只有很小的数字错误。

另一种验证弧长的方法是检查它是否总是在下面计算的两个值之间:

1) 从 Bezier 曲线中采样一些点(比如 100 个)并根据采样点计算多边形的长度。该值将始终小于曲线的实际弧长。
2) 计算控制多边形的长度。这将始终大于曲线的实际弧长。

【讨论】:

  • 您忘记了第 2 组中的 3):将曲线分成许多较小的曲线,如上面的 1),并计算它们的控制多边形长度的总和。是的,非常聪明的方法!
【解决方案3】:

您可以通过摆弄此页面上的 js 小部件来获取一些值 http://pomax.github.io/bezierinfo/#arclengthapprox

【讨论】:

  • JS 绝对不是小程序。它们只是交互式 HTML 画布。而且我不会提供此链接,请按照上面部分中的说明进行实际的弧长计算。
  • JS 不是 .. 但我认为,您在贝塞尔入门网站上的小图是。来自 wiki “小应用程序是执行一项特定任务的任何小型应用程序,该任务在专用小部件引擎或更大程序的范围内运行,通常作为插件”。它们当然不是 Java 小程序。我猜我本可以为他们选择一个不那么重的术语。
  • 小程序,在网络上,真的只是java。这些是交互式图形,背后没有运行任何类型的应用程序引擎:它只是 JS =)
  • 我会将它从小程序更改为小部件以节省更多参数:)
【解决方案4】:

意识到这是一个老问题,但另一个解决方案是使用 SVG 路径元素和 getTotalLength 方法。无需库或复杂的方程式,让浏览器完成繁重的工作。

最简单的形式:

var a = {x: 0, y: 0},  // from
    b = {x: 4, y: 4},  // to
    c1 = {x: 2, y: 0}, // curve 1
    c2 = {x: 2, y: 4}, // curve 2

    // output the curve in SVG bezier syntax
    svgBezier = `M${a.x} ${a.y} C ${c1.x} ${c1.y}, ${c2.x} ${c2.y}, ${b.x} ${b.y}`,

    // create a new <path> element
    path = document.createElementNS("http://www.w3.org/2000/svg", "path");

// add the curve
path.setAttribute('d', svgBezier);

// get the length using browser power
console.log(path.getTotalLength());  // 5.981128692626953

注意:以上在 chrome 和 safari 中返回可靠的结果 .. firefox 开箱即用似乎不太可靠

【讨论】:

    猜你喜欢
    • 2018-12-03
    • 2019-07-27
    • 2014-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    相关资源
    最近更新 更多