123

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

如何使用贝塞尔曲线创建圆?

4

10 回答 10

176

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

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

n 段的公式

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

4点案例

于 2015-01-09T14:49:33.333 回答
38

这个问题的答案非常好,所以没有什么可补充的。受此启发,我开始进行实验以直观地确认解决方案,从四条贝塞尔曲线开始,将曲线数量减少到一条。令人惊讶的是,我发现三个贝塞尔曲线的圆对我来说已经足够好了,但构造有点棘手。实际上,我使用 Inkscape 将黑色 1 像素宽的 Bézier 近似值放置在红色 3 像素宽的圆圈上(由 Inkscape 制作)。为了清楚起见,我添加了显示贝塞尔曲线边界框的蓝线和曲面。

为了看到你自己,我将展示我的结果:

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

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

3曲线图:在此处输入图像描述

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

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

于 2017-05-03T12:17:20.020 回答
36

涵盖在 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 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 引擎可能使用不同的绘图方法。

其他平台

无论您尝试使用哪种平台,都值得检查一下弧线绘制是如何完成的,这样您就可以预测这样的视觉错误并进行调整。

于 2012-11-12T04:16:40.947 回答
13

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

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创建 2 个半圆。

使用 SVG 的圆弧路径绘制圆

于 2019-07-12T12:52:58.207 回答
12

已经有很多答案了,但我发现了一篇关于圆的三次贝塞尔曲线非常好的小型在线文章。就单位圆而言,c = 0.55191502449 其中 c 是沿切线的轴截点到控制点的距离。

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

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

这篇文章可以在这里找到用三次贝塞尔曲线近似一个圆

于 2016-05-01T19:33:44.850 回答
9

这不可能。贝塞尔曲线是立方体(至少......最常用的是)。圆不能用三次方精确表示,因为圆在其方程中包含平方根。因此,您必须进行近似。

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

于 2009-11-14T17:06:16.877 回答
7

其他答案已经涵盖了一个真正的圆圈是不可能的事实。这个 SVG 文件是使用二次贝塞尔曲线的近似值,是您可以获得的最接近的东西:http://en.wikipedia.org/wiki/File: Circle_and_quadratic_bezier.svg

这是一个三次贝塞尔曲线:http ://en.wikipedia.org/wiki/File:Circle_and_cubic_bezier.svg

于 2013-02-06T12:22:22.920 回答
1

我不确定我是否应该提出新问题,因为这是关于近似的,但我对获得任何程度的贝塞尔控制点的通用公式很感兴趣,我相信它适合这个问题。我在网上找到的所有解决方案都只适用于三次曲线,或者是付费的,或者我什至不明白(我数学不太好)。所以我决定尝试自己解决这个问题。我正在研究控制点到圆心的距离取决于给定的角度,到目前为止我发现:

在此处输入图像描述

其中N是单曲线的控制点数,α是圆弧角。

对于二次曲线,它可以简化为l ≈ r + r * PI*0.1 * pow(α/90, 2) The PI*0.1is rather a guess - 我没有计算出完美的值,但它非常接近。这对于具有 1-2 个控制点的曲线相当有效,三次曲线的半径误差约为 0.2%。对于更高阶的曲线,精度损失是显着的。3个控制点曲线看起来类似于二次曲线,所以很明显我错过了一些东西,但我无法弄清楚,这种方法现在通常适合我的需要。这是演示

于 2015-07-15T18:45:25.763 回答
0

很抱歉让这个人起死回生,但我发现这篇文章与这个页面一起非常有助于提出一个可扩展的公式。

基本上,您可以使用一个非常简单的公式创建一个近圆,该公式允许您使用超过 4 的任意数量的贝塞尔曲线:Distance = radius * stepAngle / 3

其中Distance是贝塞尔控制点与圆弧最近端之间的距离,半径是radius圆的半径,stepAngle是圆弧两端之间的角度,用 2π /(曲线数)表示。

所以要一口气击中它:Distance = radius * 2π / (the number of curves) / 3

于 2014-06-06T02:30:05.627 回答
-2

这是一个沉重的近似值,根据分辨率和精度,它看起来合理或可怕,但我使用sqrt(2)/2 x 半径作为我的控制点。我读了一篇相当长的文字,这个数字是如何得出的,值得一读,但上面的公式既快又脏。

于 2013-10-12T18:00:35.077 回答