如何使用贝塞尔曲线最佳逼近几何圆弧?

Mik*_*ron 28 math graphics geometry

当绘制二维弧,用Bezier曲线近似,如何计算给定的,你有一个圆圈,开始和结束的角度和半径的中心点在两个控制点?

Joh*_*lla 17

这在StackOverflow帖子中并不容易解释,特别是因为向您证明它将涉及许多详细步骤.但是,您所描述的是一个常见问题,并且有许多详尽的解释.看到这里这里 ; 我非常喜欢#2并且之前使用过它.

  • #2附近的拼写错误:"x3 = x1"应为"x3 = x0". (12认同)
  • 我在http://pomax.github.io/bezierinfo/#circles_cubic有一个稍微更通用的解释,它涵盖了第二个链接的结论,同时解释了任何弧长而不是角度最大的弧的坐标是什么四分之一圆。 (3认同)

小智 16

这是一个8年的问题,但是我最近一直在努力解决这个问题,所以我想我会分享我想出的东西.我花了很多时间试图利用从溶液(9)这段文字并不能得到任何合理的数字出来,直到我做了一些谷歌搜索,并了解到,显然,有在方程中一些错别字.根据本博文中列出的更正,给定弧的起点和终点(分别为[x1,y1]和[x4,y4])和圆的中心([xc,yc]),可以推导出三次贝塞尔曲线([x2,y2]和[x3,y3])的控制点,如下所示:

ax = x1 – xc
ay = y1 – yc
bx = x4 – xc
by = y4 – yc
q1 = ax * ax + ay * ay
q2 = q1 + ax * bx + ay * by
k2 = 4/3 * (?(2 * q1 * q2) – q2) / (ax * by – ay * bx)


x2 = xc + ax – k2 * ay
y2 = yc + ay + k2 * ax
x3 = xc + bx + k2 * by                                 
y3 = yc + by – k2 * bx
Run Code Online (Sandbox Code Playgroud)

希望这能帮助除我之外的其他人!


Nic*_*Nic 8

一个很好的解释中的“逼近”提供三次Bezier曲线由圆弧

长话短说:使用贝塞尔曲线,您可以实现 1.96×10^-4 的最小误差,这对于大多数应用程序来说是相当不错的。

对于正象限弧,使用以下几点:

p0 = [0, radius]

p1 = [radius * K, radius]  

p2 = [radius, radius * K]

p3 = [radius, 0]
Run Code Online (Sandbox Code Playgroud)

其中K是一个所谓的“幻数”,它是一个无理数。它可以近似如下:

K = 0.5522847498
Run Code Online (Sandbox Code Playgroud)

  • @Tata​​rize为了最小化总平方误差,最佳值为0.5519703814011128603134107。为了最大限度地减少最大误差,最佳值是 Mortensen 的值,其精度更高,为 0.5519150244935105707435627。 (2认同)

Max*_*Art 6

我正在通过一些演示来回答这个老问题(它应该属于数学,所以写公式会很糟糕)。

假设P0P3是弧的起点和终点,P1P2是贝塞尔曲线的控制点,x是角度除以 2 的度量。假设x小于pi /2。

PM为线段的中点P0P3PH弧的中点。为了近似圆弧,我们希望贝塞尔曲线从P0开始,通过PH,在P3结束,并与P0P3 中的圆弧相切。

(单击“运行代码片段”以显示该图。对 imgur 的诅咒仍然不支持 SVG。)

<svg xmlns="http://www.w3.org/2000/svg" viewBox="10 20 80 80">
    <style>text{font-size:40%;font-style:italic;text-anchor:middle}tspan{font-size:50%;font-style:normal}</style>
    <rect x="10" y="20" width="80" height="80" fill="none" stroke="gray"></rect>
    <path stroke="gray" stroke-dasharray="3,2" fill="none" d="M25,30 62.6,31.62 80,65 22.19,95.13 25,30 80,65 M22.19,95.13 62.6,31.62"></path>
    <path stroke="black" fill="none" d="M25,30A65.19 65.19 0 0 1 80,65"></path>
    <circle r="1" fill="red" cx="25" cy="30"></circle>
    <circle r="1" fill="green" cx="80" cy="65"></circle>
    <circle r="1" fill="magenta" cx="22.19" cy="95.13"></circle>
    <circle r="1" fill="darkgreen" cx="52.5" cy="47.5"></circle>
    <circle r="1" fill="yellow" cx="57.19" cy="40.13"></circle>
    <circle r="1" fill="maroon" cx="62.6" cy="31.62"></circle>
    <circle r="1" fill="orange" cx="48.27" cy="31"></circle>
    <circle r="1" fill="teal" cx="69.24" cy="44.35"></circle>
    <text x="25" y="28">P<tspan>0</tspan></text>
    <text x="48.27" y="29">P<tspan>1</tspan></text>
    <text x="71.24" y="42.35">P<tspan>2</tspan></text>
    <text x="83" y="63">P<tspan>3</tspan></text>
    <text x="62.6" y="29.62">P<tspan>E</tspan></text>
    <text x="59.19" y="47.13">P<tspan>H</tspan></text>
    <text x="54.5" y="54.5">P<tspan>M</tspan></text>
</svg>
Run Code Online (Sandbox Code Playgroud)

PEP0P3 中与圆弧相切的线的交点。为了使曲线与圆弧相切,P1必须位于线段P0PE 上P2必须位于P3PE 上。令k为比率P0P1 / P0PE(也等于P3P2 / P3PE):

P1 = (1 - k ) P0 + k PE

P2 = (1 - k ) P3 + k PE

我们还有以下(做一些比例):

PM = ( P0 + P3 ) / 2

PH = PM / cos( x ) = PM sec( x ) = ( P0 + P3 ) 秒( x ) / 2

PE = PH / cos( x ) = PM sec( x )^2 = ( P0 + P3 ) sec( x )^2 / 2

为了简化我们的计算,我认为所有的向量点都是基于中心的,但最终都没有关系。

通用 4 点贝塞尔曲线由以下公式给出

C ( t ) = t ^3 P3 + 3(1 - t ) t ^2 P2 + 3(1 - t )^2 t P1 + (1 - t )^3 P0

我们必须有 C (1/2) = PH,所以

C (1/2) = ( P0 + 3 P1 + 3 P2 + P3 ) / 8

= (( P0 + P3 ) + 3(1 - k ) P0 + 3 k PE + 3(1 - k ) P3 + 3 k PE ) / 8

= (( P0 + P3 ) + 3(1 - k )( P0 + P3 ) + 6 k PE ) / 8

= ( P0 + P3 )(1 + 3(1 - k ) + 3 k秒( x )^2) / 8

所以,这是我们找到k 的等式(乘以 8):

8 C (1/2) = 8 PH

=> ( P0 + P3 )(4 - 3 k + 3 k秒( x )^2) = 4( P0 + P3 ) 秒( x )

让我们摆脱向量( P0 + P3),我们得到:

4 - 3 k + 3 k秒( x )^2 = 4 秒( x )

=> 3 k(秒( x )^2 - 1) = 4(秒( x ) - 1)

=> k = 4 / 3(秒( x ) + 1)

现在您知道在哪里放置控制点。万岁!

如果你有x = pi /4,你会得到k = 0.552...你可能已经看到了这个值。

在处理椭圆弧时,您所要做的就是相应地缩放点的坐标。

如果您必须处理更大的角度,我建议将它们分成更多的曲线。这实际上是一些软件在绘制圆弧时所做的,因为计算贝塞尔曲线有时比使用正弦和余弦更快。


Can*_*der 5

Wolfram MathWorld中有Mathematica代码:Arc的Bézier曲线逼近,应该可以帮助您入门.

也可以看看:

  • 解释同样事情的工作链接是http://pomax.github.io/bezierinfo/#circles_cubic (2认同)