SVG:将弧转换为三次贝塞尔曲线

Vog*_*gel 7 javascript svg bezier approximation

我正在尝试做一些我认为非常简单的事情:用三次贝塞尔曲线替换 SVG 路径中的所有弧。

这个:http : //www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes并没有真正帮助我,因为它并没有真正说明转换。

我知道如何制作简单的弧,但 SVG 弧确实有很多参数。

所以我需要的基本上只是一个算法,它需要:

rx ry x-axis-rotation large-arc-flag sweep-flag x y
Run Code Online (Sandbox Code Playgroud)

(也是圆弧的起点)

并计算:

x1 y1 x2 y2 x y
Run Code Online (Sandbox Code Playgroud)

(当然,起点,x 和 y 保持相同的值...)

有人知道这样的事情吗?

提前致谢!:-)

Mik*_*ans 8

事实证明这是不可能的。我的意思是,至少在数学上。你不能用普通的三次贝塞尔曲线做圆弧,你总是会出错,所以根据圆弧的角度,你可能需要不止一条贝塞尔曲线。

话虽如此,三次贝塞尔曲线对于四分之一圆弧效果很好,所以如果你的弧比那个小,你可以使用一条曲线,如果你有更宽的弧,你可以简单地将它除以一个合理的数字(介于四分之一圆和半圆?使用两条曲线。半夸脱和三夸脱之间?使用三个。完整的圆?四条曲线。很简单)。

那么,这是多少工作呢?事实证明,如果你必须从头开始:相当多的工作,但你可以直接跳到“好吧,我需要的最终公式是什么”,然后它变得相对简单。

如果我们有 angle phi,那么弧的三次曲线近似值,只要我们将弧的起点与 x 轴对齐(这样弧从 y=0 开始,然后从那里逆时针运行),我们有圆弧半径R,为:

start coordinate = {
  x: R,
  y: 0
}

control point 1 = {
  x: R,
  y: R * 4/3 * tan( phi / 4)
}

control point 2 = {
  x: R * ( cos(phi) + 4/3 * tan( phi/4 ) * sin(phi) ),
  y: R * ( sin(phi) - 4/3 * tan( phi/4 ) * cos(phi) ),
}

end coordinate = {
  x: R * cos(phi),
  y: R * sin(phi)
}
Run Code Online (Sandbox Code Playgroud)

数学!但实际上只是“插入角度,获取我们需要的坐标”。简单的!

但是如果我们的弧没有与 x 轴对齐怎么办?我们应用一个愚蠢的“旋转+平移”来对齐我们的弧,然后在完成后反向运行旋转/平移。在这里解释。

  • 对于椭圆映射,您需要找到长/短轴,将椭圆沿短轴缩放为圆形,进行弧近似,然后沿短轴缩小。多一点工作。 (3认同)
  • 更复杂的是,弧不是圆的一部分,而是椭圆。所以它实际上有两个半径 rx 和 ry。尽管如此,假设单个半径为 3,像 (5,7) 这样的东西可以通过 (-2, -7) 转换为 (3, 0) 并且不需要旋转 (?) :( (2认同)

Pau*_*eau 5

大多数 SVG 渲染库都必须这样做,因为 2D 图形库似乎不直接支持相对于 X 轴旋转的弧。

所以你可以在例如 Batik 中查找代码。或者看看arcTo()我的SVG库中的方法(也借用了Batik):

AndroidSVG / SVGAndroidRenderer.java / 第 2889 行

它是 Java,但应该很容易转换为 JS。