【发布时间】:2009-11-14 16:33:13
【问题描述】:
我们有一个起点 (x, y) 和一个圆半径。还有一个引擎可以从贝塞尔曲线点创建路径。
如何使用贝塞尔曲线创建圆?
【问题讨论】:
我们有一个起点 (x, y) 和一个圆半径。还有一个引擎可以从贝塞尔曲线点创建路径。
如何使用贝塞尔曲线创建圆?
【问题讨论】:
如前所述:使用贝塞尔曲线无法准确表示圆。
要完成其他答案:对于带有n 的贝塞尔曲线分段,到控制点的 最佳 距离,即曲线的中间位于圆本身上,是 @987654325 @。
所以 4 分是(4/3)*tan(pi/8) = 4*(sqrt(2)-1)/3 = 0.552284749831。
【讨论】:
【讨论】:
包含在 comp.graphics.faq 中
课题 4.04:如何将贝塞尔曲线拟合到圆上?
有趣的是,贝塞尔曲线可以近似于一个圆,但
不完全适合一个圆圈。
一个常见的近似是使用四个贝塞尔曲线来模拟一个圆,每个
控制点距离端点 d=r*4*(sqrt(2)-1)/3
(其中 r 是圆的半径),并且在与
圈在端点。这将确保中点
贝塞尔曲线在圆上,并且一阶导数是连续的。
该近似值的径向误差约为 0.0273%
圆的半径。
Michael Goldapp,“用三次逼近圆弧 多项式”计算机辅助几何设计 (#8 1991 pp.227-238)
Tor Dokken 和 Morten Daehlen,“良好的圆近似 曲率连续贝塞尔曲线"计算机辅助几何 设计(#7 1990 第 33-41 页)。 http://www.sciencedirect.com/science/article/pii/016783969090019N(非免费文章)
另请参阅http://spencermortensen.com/articles/bezier-circle/ 上的非付费文章
请注意,某些浏览器使用贝塞尔曲线绘制画布弧线,Chrome 使用(目前)4 扇区方法,而 Safari 使用 8 扇区方法,差异仅在高分辨率下很明显,因为 0.0273% ,并且只有当弧线平行且异相绘制时才真正可见,您会注意到弧线从真正的圆中振荡。当曲线围绕其径向中心进行动画处理时,效果也更加明显,600px 半径通常是它会产生影响的大小。
某些绘图 API 没有真正的弧线渲染,因此它们也使用贝塞尔曲线,例如 Flash 平台没有弧线绘制 API,因此任何提供弧线的框架通常都使用相同的贝塞尔曲线方法。
请注意,浏览器中的 SVG 引擎可能使用不同的绘图方法。
无论您尝试使用什么平台,都值得检查一下弧线绘制是如何完成的,这样您就可以预测此类视觉错误并进行调整。
【讨论】:
致只是寻找代码的人:
https://jsfiddle.net/nooorz24/2u9forep/12/
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function drawBezierOvalQuarter(centerX, centerY, sizeX, sizeY) {
ctx.beginPath();
ctx.moveTo(
centerX - (sizeX),
centerY - (0)
);
ctx.bezierCurveTo(
centerX - (sizeX),
centerY - (0.552 * sizeY),
centerX - (0.552 * sizeX),
centerY - (sizeY),
centerX - (0),
centerY - (sizeY)
);
ctx.stroke();
}
function drawBezierOval(centerX, centerY, sizeX, sizeY) {
drawBezierOvalQuarter(centerX, centerY, -sizeX, sizeY);
drawBezierOvalQuarter(centerX, centerY, sizeX, sizeY);
drawBezierOvalQuarter(centerX, centerY, sizeX, -sizeY);
drawBezierOvalQuarter(centerX, centerY, -sizeX, -sizeY);
}
function drawBezierCircle(centerX, centerY, size) {
drawBezierOval(centerX, centerY, size, size)
}
drawBezierCircle(200, 200, 64)
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
这允许绘制由 4 条贝塞尔曲线组成的圆。 用 JS 编写,但可以轻松翻译成任何其他语言
如果您需要使用 SVG 路径绘制圆,请不要使用贝塞尔曲线,除非需要这样做。在路径中,您可以使用Arc 创建两个半圆。
【讨论】:
bezierCurveTo() 之后的另一个ctx.lineTo(centerX, centerY); 可以解决这个问题。 `
已经有很多答案了,但我发现了一篇关于圆的三次贝塞尔曲线非常好的小型在线文章。以单位圆表示,c = 0.55191502449 其中 c 是沿切线的轴截点到控制点的距离。
作为单位圆的单象限,两个中间坐标为控制点。 (0,1),(c,1),(1,c),(1,0)
径向误差仅为 0.019608%,因此我只需将其添加到此答案列表中即可。
【讨论】:
这是不可能的。贝塞尔曲线是立方体(至少......最常用的是)。圆不能用三次方精确表示,因为圆在其方程中包含平方根。因此,您必须进行近似。
为此,您必须将您的圆圈划分为 n 个正切(例如,象限、八分圆)。对于每个 n-tant,您使用第一个和最后一个点作为 Bezier 曲线的第一个和最后一个点。贝塞尔多边形需要两个额外的点。为了快速,我会为 n-tant 的每个极值点取圆的切线,并选择这两个点作为两个切线的交点(这样基本上你的贝塞尔多边形是一个三角形)。增加 n-tants 的数量以适应您的精度。
【讨论】:
其他答案已经涵盖了一个真正的圆圈是不可能的事实。这个 SVG 文件是使用二次贝塞尔曲线的近似值,是你能得到的最接近的东西:http://en.wikipedia.org/wiki/File:Circle_and_quadratic_bezier.svg
这是三次贝塞尔曲线:http://en.wikipedia.org/wiki/File:Circle_and_cubic_bezier.svg
【讨论】:
我不确定我是否应该提出新问题,因为这是关于近似的,但我对获得任何程度的贝塞尔控制点的通用公式很感兴趣,我相信它适合这个问题。 我在网上找到的所有解决方案都只适用于三次曲线,或者是付费的,或者我什至不明白(我数学不太好)。 所以我决定尝试自己解决这个问题。我正在研究控制点到圆心的距离取决于给定的角度,到目前为止我发现:
其中N 是单曲线的控制点数,α 是圆弧角。
对于二次曲线可以简化为l ≈ r + r * PI*0.1 * pow(α/90, 2)
PI*0.1 是一个猜测——我没有计算出完美的价值,但它非常接近。
这对于具有 1-2 个控制点的曲线相当有效,三次曲线的半径误差约为 0.2%。对于更高阶的曲线,精度损失是显着的。 3个控制点曲线看起来类似于二次曲线,所以很明显我错过了一些东西,但我无法弄清楚,这种方法现在通常适合我的需要。
这里是demo。
【讨论】:
很抱歉让这个人起死回生,但我发现这篇文章以及 this 页面对提出可扩展公式很有帮助。
基本上,您可以使用一个非常简单的公式创建一个近圆,该公式允许您使用超过 4 的任意数量的贝塞尔曲线:Distance = radius * stepAngle / 3
其中Distance 是贝塞尔控制点与圆弧最近端之间的距离,半径是圆的radius,stepAngle 是圆弧两端之间的角度,由下式表示2π /(曲线数)。
所以一击命中:Distance = radius * 2π / (the number of curves) / 3
【讨论】:
Distance = (4/3)*tan(pi/2n)。对于大量的弧,它几乎相同,因为tan(pi/2)~pi/2n,但例如对于n=4(这是最常用的情况),您的公式给出Distance=0.5235...,但最佳的是Distance=0.5522...(所以你有〜5 % 错误)。
这是一个很重的近似值,取决于分辨率和精度,它看起来合理或糟糕,但我使用 sqrt(2)/2 x radius 作为我的控制点。我读了一篇相当长的文章,这个数字是如何得出的,值得一读,但上面的公式既快又脏。
【讨论】: