Answers:
如前所述:没有使用贝塞尔曲线的确切表示。
要完成其他答案:对于曲线n
段为Bezier的曲线,到控制点的最佳距离为,曲线的中心位于圆自身上(4/3)*tan(pi/(2n))
。
所以是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,“曲率连续的贝塞尔曲线的圆的良好近似”,计算机辅助几何设计(1990年第7页,第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没有真正的圆弧渲染,因此它们也使用Bezier曲线,例如Flash平台没有圆弧绘图api,因此任何提供圆弧的框架通常都使用相同的Bezier曲线方法。
请注意,浏览器中的SVG引擎可能使用不同的绘制方法。
无论您尝试使用哪种平台,都值得检查一下圆弧绘制的完成方式,以便您可以预测这样的视觉错误并进行调整。
该问题的答案非常好,因此几乎没有补充。受此启发,我开始进行实验以目视确认解决方案,从4条Bézier曲线开始,将曲线数减少为1。令人惊讶的是,我发现三个Bézier曲线对我来说看起来不错,但是构造有些棘手。实际上,我使用Inkscape将黑色的1像素宽的贝塞尔近似值放置在红色的3像素的圆上(由Inkscape生产)。为了澄清起见,我添加了蓝线和曲面以显示贝塞尔曲线的边界框。
为了展示自己,我正在展示我的结果:
(我想在此处放置SVG或PDF,但不支持)
已经有很多答案,但是我发现了一篇在线文章,其很好的三次方贝塞尔近似于一个圆。以单位圆为单位,c = 0.55191502449,其中c是沿切线从轴截距点到控制点的距离。
作为单位圆的一个象限,其中两个中间坐标为控制点。 (0,1),(c,1),(1,c),(1,0)
径向误差仅为0.019608%,因此我只需要将其添加到此答案列表中即可。
可以在此处找到该文章近似具有三次贝塞尔曲线的圆
这不可能。贝塞尔曲线是立方的(至少...最常用的是)。圆不能精确地用三次方表示,因为圆的方程式中包含平方根。因此,您必须近似。
为此,您必须将圆分成n-tant(四分位数,八分位数)。对于每个正态,将第一个和最后一个点用作Bezier曲线的第一个和最后一个点。贝塞尔曲线多边形需要另外两个点。为了快速起见,我将正切线的每个极点的切线取到圆上,然后选择两个点作为两个切线的交点(这样,您的Bezier多边形基本上就是一个三角形)。增加n-tant的数量以适合您的精度。
其他答案涵盖了一个不可能的事实。该SVG文件是使用二次贝塞尔曲线的近似值,是您可以获得的最接近的东西:http : //en.wikipedia.org/wiki/File : Circle_and_quadratic_bezier.svg
这是具有三次贝塞尔曲线的曲线:http : //en.wikipedia.org/wiki/File : Circle_and_cubic_bezier.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编写,但可以轻松翻译成任何其他语言
我不确定是否应该提出新的问题,因为这是关于近似的问题,但是我对通用公式感兴趣,可以获取贝塞尔的任意程度的控制点,并且我相信它适合这个问题。我在网上找到的所有解决方案仅适用于三次曲线或已付款,或者我什至不了解(我不太擅长数学)。因此,我决定尝试自行解决此问题。我研究了控制点到圆心的距离(取决于给定角度),到目前为止,我发现:
其中N
为单曲线的控制点数量,为α
圆弧角。
对于二次曲线,可以将其简化为。l ≈ r + r * PI*0.1 * pow(α/90, 2)
这PI*0.1
是一个猜测-我没有计算完美值,但是非常接近。这对于具有1-2个控制点的曲线相当有效,三次曲线的半径误差约为0.2%。对于更高程度的曲线,精度的损失是明显的。具有3个控制点的曲线看起来与二次曲线相似,因此很明显我想念一些东西,但是我无法弄清楚,这种方法通常可以满足我现在的需求。这是演示。
对不起,把从死人此一回,但我发现这个职位连同很有帮助此页面中想出一个可扩展的计算公式。
基本上,您可以使用一个非常简单的公式来创建一个近圆,该公式允许您使用超过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%的误差)。