简体   繁体   English

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

[英]SVG: Convert Arcs to Cubic Bezier

I'm trying to do something that i though would be pretty simple: Replacing all Arcs in an SVG path with Cubic Bezier Curves.我正在尝试做一些我认为非常简单的事情:用三次贝塞尔曲线替换 SVG 路径中的所有弧。

This:http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes doesn't really help me as it doesn't really say anything about conversion.这个:http ://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes并没有真正帮助我,因为它并没有真正说明转换。

I know how to make simple Arcs, but the SVG Arcs do have a lot of parameters.我知道如何制作简单的弧,但 SVG 弧确实有很多参数。

So what i need is basically just an algorithm that takes:所以我需要的基本上只是一个算法,它需要:

rx ry x-axis-rotation large-arc-flag sweep-flag x y

(and also the start point of the arc) (也是圆弧的起点)

and calculates:并计算:

x1 y1 x2 y2 x y

(of course, the start point, x and y keep the same values...) (当然,起点,x 和 y 保持相同的值...)

Does anybody know something like this?有人知道这样的事情吗?

Thanks in advance!提前致谢! :-) :-)

Turns out this is impossible.事实证明这是不可能的。 I mean, mathematically, at least.我的意思是,至少在数学上。 You can't do circular arcs with plain cubic Bezier curves, you're always going to have an error, so depending on the arc's angle, you're going to probably need more than one Bezier curve.你不能用普通的三次贝塞尔曲线做圆弧,你总是会出错,所以根据圆弧的角度,你可能需要不止一条贝塞尔曲线。

With that said, cubic Bezier curves work quite well for quarter-circle arcs, so if you have arcs smaller than that, you can use a single curve, and if you have wider arcs, you can simply divide it by a sensible number (between quarter and half circle? Use two curves. Between half and three quarts? Use three. Full circle? Four curves. Pretty simple).话虽如此,三次贝塞尔曲线对于四分之一圆弧来说效果很好,所以如果你的弧比那个小,你可以使用一条曲线,如果你有更宽的弧,你可以简单地将它除以一个合理的数字(介于四分之一圆和半圆?使用两条曲线。半夸脱和三夸脱之间?使用三个。完整的圆?四条曲线。很简单)。

So, how much work is this?那么,这是多少工作呢? Turns out, if you have to do it from scratch: a fair bit of work , but you can just jump to the "okay so what is the final formula I need" and then it becomes relatively simple.事实证明,如果你必须从头开始:相当多的工作,但你可以直接跳到“好吧,我需要的最终公式是什么”,然后它变得相对简单。

If we have angle phi , then the cubic curve approximation of your arc, provided we align the start of our arc with the x-axis (so that the arc starts at y=0, and runs counter clockwise from there), and we have an arc radius R , is:如果我们有角度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)
}

Maths!数学! But really just "plug in angle, get the coordinates we need".但实际上只是“插入角度,获取我们需要的坐标”。 Simple!简单的!

But what if our arc is not aligned to the x-axis?但是如果我们的弧没有与 x 轴对齐怎么办? We apply a dumb "rotate + translate" to put align our arc, and then we run the rotation/translation in reverse when we're done.我们应用一个愚蠢的“旋转+平移”来对齐我们的弧,然后在完成后反向运行旋转/平移。 Explained here .在这里解释。

Most SVG rendering libraries have to do this because 2D graphics libraries don't seem to directly support arcs that are rotated with respect to the X axis.大多数 SVG 渲染库都必须这样做,因为 2D 图形库似乎不直接支持相对于 X 轴旋转的弧。

So you could look up the code in, say, Batik.所以你可以在例如蜡染中查找代码。 Or look at the arcTo() method in my SVG library (which also borrows from Batik):或者查看我的 SVG 库中的arcTo()方法(也借用了 Batik):

AndroidSVG / SVGAndroidRenderer.java / line 2889 AndroidSVG / SVGAndroidRenderer.java / 第 2889 行

It's Java, but should be easily converted to JS.它是 Java,但应该很容易转换为 JS。

You can also look at this function from SnapSVG which might have been used somehow by Adobe Illustrator (it is hosted by a user named "adobe-webplatform"), to convert arc to cubic commands.您还可以从 SnapSVG 中查看此函数,它可能已被 Adob​​e Illustrator 以某种方式使用(它由名为“adobe-webplatform”的用户托管),用于将弧转换为三次命令。 It's also used in SVGO(ptimizer).它也用于 SVGO(ptimizer)。

I'm still trying to decypher it, but the standard is actually pretty helpfull for that.我仍在尝试破解它,但标准实际上对此非常有帮助。

You can check those links:您可以检查这些链接:

Arc to Qubic by Dmitry Baranovskiy And also the same implementation by Jarek Foksa . Arc to Qubic by Dmitry Baranovskiy以及Jarek Foksa的相同实现。

Based onW3.org基于W3.org

Selected answer provides partial solution to circled arcs.所选答案为圆弧提供了部分解决方案。 While researching the topic, found an npm for a function extracted from SVG path , to addres excatly this, and here is a quick codesandbox hope this helps someone在研究这个主题时,发现了一个SVG 路径中提取的函数npm ,以解决这个问题,这里有一个快速代码希望这对某人有所帮助

arcpath.setAttribute("d", "M 0 200 A 100 20 0 1 0 100 200");
const options = {
  px: 0,
  py: 200,
  cx: 100,
  cy: 200,
  rx: 100,
  ry: 20,
  xAxisRotation: 0,
  largeArcFlag: 1,
  sweepFlag: 0
};

弧到三次曲线

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM