我想从弧上的两个端点(x1,y1,x2,y2)和中心点(cx,cy)或半径创建二次贝塞尔曲线。
有一次,我认为我可以将两个控制点设置为切线的交点,但这似乎不起作用。
虽然确切的答案会很好,但如果需要,我可以接受合理的近似值。我的数学技能有限但会欣赏简单的伪代码。我已经进行了谷歌搜索,一些建议太复杂,我无法跟进。
问题似乎很简单,但我知道不是。
答案 0 :(得分:1)
对于圆的良好近似,Bezier二次控制点位于
var cp = (r * 4 * (Math.sqrt( 2 ) - 1)) / 3;
其中r
是点(x,y)
处圆的半径。 cp
是沿控制点切线的距离。
ctx.moveTo(x-r,y)
ctx.quadCurve(x - r, y - pc, x + r, y - pc, x + r, y);
将创造一个漂亮的半圈。为底部做同样的事情以获得一个完整的圆圈。
答案 1 :(得分:1)
圆弧和贝塞尔曲线之间没有完美的映射,因为圆具有参数函数:
fx(t) = cos(t)
fy(t) = sin(t)
只能以多项式形式表示为无限序列:
fx(t) = ∑(k=0,inf) x^(2k) * (-1)^k / (2k)!
fy(t) = ∑(k=0,inf) x^(2k+1) * (-1)^k / (2k+1)!
显然,任何有限度贝塞尔曲线总是“关闭”,虽然顺序越高,我们的“关闭”越少。对于一个三次曲线,我们可以非常合理地近似四分之一圆弧,虽然不止于此,它看起来非常明显错误:在{{3}上给出一个角度为弧度的曲线看起来有详细的写法并且值得阅读该部分,然后实现其解释(或“借用”github中的代码,它的公共域代码),以及使用图形来确定一旦你尝试建模更多错误的东西比四分之一圈。
答案 2 :(得分:0)
二次贝塞尔曲线具有等式
B(t) = P0 * (1-t)^2+ 2 * P1 * t * (1-t) + P2 * t^2
对于你的情况
P0 = (x1,y1)
P2 = (x2,y2)
为了用Bezier逼近弧,我们可以声明曲线的中点必须与弧的中点重合。
找到弧的中点:
我们有和弦矢量
V = (x2-x1, y2-y1)
垂直向量(不是y符号变化)
P = (y1-y2, x2-x1)
它的长度
LenP = Sqrt((y1-y2)^2 + (x2-x1)^2)
单位垂直向量
uP = P/LenP = ( (y1-y2) / LenP, (x2-x1) / LenP)
中间圆弧点
M = C + R * uP = (cx + R * (y1-y2) / LenP, cy + R * (x2-x1) / LenP)
Bezier的中点
B(1/2) = P0/4 + P1/2 + P2/4 = (x1/4 + px/2 + x2/4, y1/4 + py/2 + y2/4)
现在我们可以编写方程式
cx + R * (y1-y2) / LenP = x1/4 + px/2 + x2/4
cy + R * (x2-x1) / LenP = y1/4 + py/2 + y2/4
并找到px
和py
- 控制点的坐标。