为缩写/平滑SVG路径的贝塞尔曲线计算控制点

19

链接:官方 SVG 参考文档

大家好,我在使用 SVG 路径时遇到了一些麻烦,具体来说是关于被定义为 SVG 路径的缩写贝塞尔曲线 (由路径数据中的 S 或 s 表示) 的第一个控制点如何计算。

假设我们有一个 curveto 命令,并且已知其控制点为 (X1,Y1)(X2,Y2),端点为 (X3,Y3),起点为 (X0,Y0)

接下来是一个缩写/平滑曲线命令,其第一个控制点为 (X4,Y4),第二个控制点为 (X5,Y5)。 为简单起见,假设所有点坐标都是绝对坐标。

如何根据其他已知点计算出未知的第一个控制点 (X4,Y4)


4个回答

22

你的第一个点是前一条曲线的最后一个点。在这种情况下,它将是(x3,y3)。然后你缩写中的第二个点是该缩写表示的曲线长度的终止点。

如果我们要将你的路径转换为完整长度版本,我们会得到:

M X0, Y0 C X1, Y1 X2, Y2 X3, Y3 
M X3, Y3 C XR, YR X4, Y4 X5, Y5 

XR和YR是上一条曲线的最后一个控制点关于当前曲线的第一个点的反射。

XR和YR只是P2相对于P3的镜像,因此:

XR = 2*X3 - X2 and 
YR = 2*Y3 - Y2

没有误解,我只是把第二条曲线的第一个控制点叫做(X4,Y4),而你却称其为(XR,YR)。 - Adam S

2
您可以将上一个曲线的最后一个控制点和该曲线的结束点(也就是新曲线的第一个点)视为一条直线,镜像的控制点应该位于该直线上,距离与上一个控制点到最后一个结束点的距离相等。

0

我找到了this。我可以从中引用的最短答案是:

我们使用一条线连接围绕起点和终点锚点的锚点(让我们称之为对立线):

opposed-lines

为了使线条平滑,每个控制点的位置都必须相对于其“对立线”而言:
  • 控制点位于与“对立线”平行且切线于当前锚点的直线上。
  • 在这条切线上,从锚点到控制点的距离取决于“对立线”的长度和任意的“平滑”比率。
  • 起始控制点与“对立线”方向相同,而结束控制点则向后。
// When 'current' is the first or last point of the array
// 'previous' or 'next' don't exist.
// Replace with 'current'
const p = previous || current
const n = next || current

我的解释:

  • 为每对“锚点”(实际曲线)点计算2个控制点。
  • 如果正在计算点1(start/end - 1)和点2(start + 1/end):
    • 第一个控制点从点1(start)沿着{从点0(start - 1)到点2(start + 1)的直线}平行。
    • 第二个控制点从点2(end)向后平行于{从点1(end - 1)到点3(end + 1)的直线}。
  • 点1或点2到相应控制点的距离是曲线所需平滑度变量(0.0-1.0)与平行线长度的比率。(您可以使用基本三角函数,例如cos()和sin()来计算角度。)
  • 对于端点(它们之前/之后没有点),请将start - 1替换为start或将end + 1替换为end

0
我发现通过这里提供的解决方案,实际上并不能解决找到平滑曲线反射点的问题。
我认为这些解决方案可能能解决一些情况,但并不是真正健壮的。我唯一能计算平滑曲线的方法是使用类似下面伪代码的代码。
我花了整整一天来制定这个解决方案,所以我想分享一下。
这适用于相对和绝对平滑曲线,无论之前的曲线是平滑曲线还是非平滑曲线,相对或绝对,都可以适用。
如果有任何不清楚的地方,请随时提问,我会进一步解释:
假设你有一个三次曲线,后面跟着一个平滑三次曲线
Cubic Curve
 - control 1
  - x0
  - y0
 - control 2
  - x1
  - y1
 - destination
  - x2
  - y2
 
 Cubic Curve Smooth
 - control 1?
  - x3?
  - y3?
 - control 2
  - x4
  - y4
 - destination
  - x5
  - y5
 
 Calculating x3 and y3
 cX and cY are current X and current Y (starting point of the smooth curve)
 rX and rY are the reflection according to the previous curve
 
 rX = abs( x2 - x1 ) (absolute values)
 rY = abs( y2 - y1 ) (absolute values)
 
 if cX > x5
   x3 = cX - rX
 else
   x3 = cX + rX
 
 if cY > y5
   y3 = cY - rY
 else
   y3 = cY + rY

Ps:如果在平滑曲线之前没有一个曲线(无论是平滑还是不平滑),那么:
x3 = cX
y3 = cY

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接