如何用Bézier曲线创建圆?

Rel*_*lla 85 geometry bezier

我们有一个起点(x,y)和一个圆半径.还存在可以从贝塞尔曲线点创建路径的引擎.

如何使用Bézier曲线创建圆?

Kpy*_*pym 124

如前所述:使用贝塞尔曲线没有精确的圆圈表示.

要完成其他答案:对于具有n分段的贝塞尔曲线,与控制点的最佳距离,在曲线的中间位于圆本身的意义上,是(4/3)*tan(pi/(2n)).

n段的公式

所以4分是这样的(4/3)*tan(pi/8) = 4*(sqrt(2)-1)/3 = 0.552284749831.

4点案例

  • 通过最佳距离,您优化了哪些指标?如 [用三次贝塞尔曲线近似圆](http://spencermortensen.com/articles/bezier-circle/) 中所示,通过不同的值实现尽可能低的最大漂移。您能否提供一些链接来定义“最佳”在您的情况下的含义,或者公式是如何得出的? (3认同)
  • 好的。我将尝试改写:“到控制点的距离,使得曲线的中间位于圆本身上”。我认为这是一个有效的决定(足够好且易于计算),但我不会称其为最佳(至少在没有写下它是最佳的情况下不会)。 (3认同)
  • @ legends2k我使用LaTeX和TikZ生成一个我转换为PNG的PDF. (2认同)
  • 也许对我编写脚本创建 SVG 之类的路径命令来用贝塞尔曲线绘制圆的人有用:http://codereview.stackexchange.com/questions/141491/how-can-i-do-this-small-haskell-script-better- calculate-a-circle-with-bezier 我基于这个答案。 (2认同)

oco*_*odo 31

包含在comp.graphics.faq中

摘抄:

主题4.04:如何将Bezier曲线拟合到圆上?

有趣的是,贝塞尔曲线可以近似圆形但不完全适合圆形.一个常见的近似是使用四个beziers来模拟一个圆,每个控制点的距离为d = r*4*(sqrt(2)-1)/ 3,距端点(其中r是圆半径),并且与端点处的圆相切的方向.这将确保贝塞尔的中点位于圆上,并且一阶导数是连续的.
该近似值中的径向误差约为圆半径的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/上的非付费应用文章

浏览器和画布元素.

请注意,有些浏览器使用贝塞尔曲线绘制画布绘制弧线,Chrome使用(目前)4扇区方法,Safari使用8扇区方法,差异仅在高分辨率时才会显着,因为0.0273%,并且只有在平行和异相绘制弧线时才真正可见,你会注意到弧线从一个真正的圆圈中振荡.当曲线围绕它的径向中心动画时,效果也更明显,600px半径通常是它会产生差异的大小.

某些绘图API没有真正的圆弧渲染,因此它们也使用贝塞尔曲线,例如Flash平台没有圆弧绘制API,因此任何提供圆弧的框架通常都使用相同的贝塞尔曲线方法.

请注意,浏览器中的SVG引擎可能使用不同的绘图方法.

其他平台

无论您尝试使用什么平台,都值得检查弧形绘制是如何完成的,因此您可以预测这样的视觉错误并进行调整.


U. *_*ndl 25

这个问题的答案非常好,所以几乎无法补充.受此启发,我开始进行实验以直观地确认解决方案,从四条Bézier曲线开始,将曲线数量减少到一条.令人惊讶的是,我发现有三条Bézier曲线,圆圈看起来对我来说足够好,但结构有点棘手.实际上我使用Inkscape将黑色1像素宽Bézier逼近放置在红色3像素宽的圆上(由Inkscape生成).为了澄清,我添加了蓝线和表面,显示了Bézier曲线的边界框.

为了看到自己,我正在展示我的结果:

1曲线图(看起来像一个角落挤在一个角落,只是为了完整性):在此输入图像描述

2曲线图:在此输入图像描述

三曲线图:在此输入图像描述

4曲线图: 在此输入图像描述

(我想在这里放置SVG或PDF,但不支持)


NoO*_*Z24 10

对于那些只是在寻找代码的人:

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)
Run Code Online (Sandbox Code Playgroud)
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
Run Code Online (Sandbox Code Playgroud)

这允许绘制由 4 条贝塞尔曲线组成的圆。用 JS 编写,但可以很容易地翻译成任何其他语言

笔记

如果您需要使用 SVG 路径绘制圆,请不要使用贝塞尔曲线,除非需要这样做。在路径中,您可以Arc用来创建 2 个半圆。

使用 SVG 的圆弧路径绘制圆形


Ste*_*ini 7

这不可能.Bezier是一个立方体(至少......最常用的是).圆不能用三次方精确表示,因为圆在其方程中包含平方根.因此,你必须近似.

要做到这一点,你必须将你的圆圈划分为n-tants(例如,quadrants,octants).对于每个n-tant,您使用第一个和最后一个点作为贝塞尔曲线的第一个和最后一个.贝塞尔多边形需要两个额外的点.为了快速,我将切线用于n-tant的每个极值点的圆,并选择两个点作为两个切线的交点(这样基本上你的Bezier多边形是一个三角形).增加n-tants的数量以适应您的精度.

  • 只要您使用无限数量的贝塞尔曲线,就可以实现零长度.这基本上是无限多个点,或者更确切地说是一条弧形曲线. (3认同)

Jaf*_*fer 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


Bli*_*n67 7

已经有很多答案,但我找到了一篇小型的在线文章,其中有一个很好的立方贝塞尔近似圆.在单位圆c = 0.55191502449方面,其中c是沿着切线到控制点的轴截距点的距离.

作为单位圆的单个象限,两个中间坐标是控制点. (0,1),(c,1),(1,c),(1,0)

径向误差仅为0.019608%,因此我只需将其添加到此答案列表中.

这篇文章可以在这里找到近似圆形的立方Bézier曲线

  • 您是否通过Stackoverflow的[Mike'Pomax'Kamermans](http://stackoverflow.com/users/740553)阅读了关于Bezier曲线的[**优秀论文**](http://pomax.github.io/bezierinfo/) /麦克-pomax-kamermans).这非常值得一读!:-) (3认同)