我们有一个起点(x,y)和一个圆半径。还有一个引擎可以从贝塞尔曲线点创建一条路径。
如何使用Bézier曲线创建圆圈?
答案 0 :(得分:113)
正如已经说过的那样:使用贝塞尔曲线没有精确的圆圈表示。
要完成其他答案:对于贝塞尔曲线,n
分段最佳到控制点的距离,在曲线中间位于圆圈本身的意义上,是(4/3)*tan(pi/(2n))
。
因此对于4分,它是(4/3)*tan(pi/8) = 4*(sqrt(2)-1)/3 = 0.552284749831
。
答案 1 :(得分:30)
包含在comp.graphics.faq
中主题4.04:如何将Bezier曲线拟合到圆圈?
有趣的是,Bezier曲线可以近似圆形但是 不完全适合一个圆圈。 一个常见的近似是使用四个beziers来模拟一个圆圈 控制点与终点距离d = r * 4 *(sqrt(2)-1)/ 3 (其中r是圆半径),并且在与切线相切的方向上 圆点在终点。这将确保中间点 Beziers在圈子里,并且一阶导数是连续的 该近似值中的径向误差约为0.0273% 圆的半径。
Michael Goldapp,“用立方数表示圆弧的近似值 多项式“计算机辅助几何设计(#8 1991 pp.227-238)
Tor Dokken和Morten Daehlen,“圆圈的好近似” 曲率连续Bezier曲线“计算机辅助几何 设计(#7 1990 pp.33-41)。 http://www.sciencedirect.com/science/article/pii/016783969090019N(非免费文章)另请参阅http://spencermortensen.com/articles/bezier-circle/
上的非付费应用文章请注意,有些浏览器使用Bezier曲线绘制画布绘制弧线,Chrome使用(目前)4扇区方法,Safari使用8扇区方法,差异仅在高分辨率时才会显着,因为0.0273% ,并且只有在平行和异相绘制弧线时才真正可见,您会注意到弧线从一个真正的圆形振荡。当曲线围绕它的径向中心动画时,效果也更明显,600px半径通常是它会产生差异的大小。
某些绘图API没有真正的圆弧渲染,因此它们也使用贝塞尔曲线,例如Flash平台没有圆弧绘制API,因此任何提供圆弧的框架通常都使用相同的贝塞尔曲线方法。
请注意,浏览器中的SVG引擎可能使用不同的绘图方法。
无论您尝试使用哪种平台,都值得检查弧形绘制是如何完成的,因此您可以预测这样的视觉错误并进行调整。
答案 2 :(得分:22)
问题的答案非常好,所以几乎没有补充。灵感来自于我开始进行实验以在视觉上确认解决方案,从四条Bézier曲线开始,将曲线数量减少到一条。令人惊讶的是,我发现有三条Bézier曲线,圆圈看起来足够好对我来说,但结构有点棘手。实际上我使用Inkscape将黑色1像素宽Bézier逼近放置在红色3像素宽的圆上(由Inkscape生成)。为了澄清,我添加了蓝线和表面,显示了Bézier曲线的边界框。
为了看到自己,我正在展示我的成果:
(我想在这里放置SVG或PDF,但不支持)
答案 3 :(得分:8)
这是不可能的。 Bezier是一个立方体(至少......最常用的是)。圆不能用三次方精确表示,因为圆在其方程中包含平方根。因此,你必须近似。
要做到这一点,你必须将你的圆圈划分为n-tants(例如,quadrants,octants)。对于每个n-tant,您使用第一个和最后一个点作为贝塞尔曲线的第一个和最后一个。贝塞尔多边形需要两个额外的点。为了快速,我将切线用于n-tant的每个极值点的圆,并选择两个点作为两个切线的交点(这样基本上你的Bezier多边形是一个三角形)。增加n-tants的数量以适应您的精度。
答案 4 :(得分:7)
其他答案涵盖了无法实现真正循环的事实。此SVG文件是使用二次贝塞尔曲线的近似值,是您可以得到的最接近的事物:http://en.wikipedia.org/wiki/File:Circle_and_quadratic_bezier.svg
这是一个Cubic Bezier曲线:http://en.wikipedia.org/wiki/File:Circle_and_cubic_bezier.svg
答案 5 :(得分:7)
已经有很多答案,但我发现了一篇小型的在线文章,其中有一个很好的立方贝塞尔近似圆。在单位圆c = 0.55191502449方面,其中c是沿着切线到控制点的轴截距点的距离。
作为单位圆的单个象限,其中两个中间坐标是控制点。 (0,1),(c,1),(1,c),(1,0)
径向误差仅为0.019608%,因此我只需将其添加到此答案列表中。
答案 6 :(得分:1)
我不确定我是否应该提出新问题,因为这是关于近似的,但我对通用公式感兴趣,以获得任何程度的Bezier控制点,我相信它符合这个问题。 我在网上找到的所有解决方案仅适用于三次曲线或付费,或者我甚至不理解(我不擅长数学)。 所以我决定尝试自己解决这个问题。我根据给定的角度研究了控制点与圆心的距离,到目前为止我发现:
其中N
是单曲线的控制点数,α
是圆弧角。
对于二次曲线,它可以简化为l ≈ r + r * PI*0.1 * pow(α/90, 2)
PI*0.1
是一个猜测 - 我没有计算出完美的价值,但它非常接近。
对于具有1-2个控制点的曲线,这对于三次曲线给出半径误差约0.2%是相当好的。对于更高程度的曲线,精度损失是显而易见的。有3个控制点曲线看起来类似于二次曲线所以很明显我错过了一些东西,但是我无法弄清楚这个方法通常适合我现在的需要。
这是demo。
答案 7 :(得分:0)
很抱歉让这个人从死里复活,但我发现这篇文章非常有用,同时在this页面提出了一个可扩展的公式。
基本上,你可以使用一个非常简单的公式创建一个近圆,这个公式允许你使用任意数量的贝塞尔曲线而不是4:Distance = radius * stepAngle / 3
其中Distance
是贝塞尔控制点与弧的最近端之间的距离,半径是圆的radius
,stepAngle
是两端之间的角度以2π/(曲线数)表示的弧的数量。
所以要一次性击中它:Distance = radius * 2π / (the number of curves) / 3
答案 8 :(得分:0)
致那些只在寻找代码的人:
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编写,但可以轻松翻译成其他任何语言
答案 9 :(得分:-2)
根据分辨率和精度,这是一个看似合理或可怕的重型近似值,但我使用 sqrt(2)/ 2 x radius 作为我的控制点。我读了一个相当长的文本,这个数字是如何得出的,值得一读,但上面的公式是快速而肮脏的。