【问题标题】:Is there a SVG API allowing to get Bezier and Spline point coordinates once generated?是否有 SVG API 允许在生成后获取 Bezier 和 Spline 点坐标?
【发布时间】:2015-07-03 04:01:48
【问题描述】:

在 JS 中是否有一个 SVG API 允许在生成后获取 Bezier 和 Spline 点坐标?

我想控制一台将遵循曲线路径的生产机器。我需要知道: 1) 沿路径的长度,或沿路径的每个部分的长度。 2)在沿路径的每个指定距离处,知道曲率半径。我可以想象我可以计算曲率半径的一种方法是比较从相邻点到另一个点的tengent(或路径方向)。

但是如果我想能够“读取”路径曲线规范,我真的需要生成自己的 JS 来绘制这些曲线吗?

在最坏的情况下,我需要收集生成的所有像素的坐标。 谢谢

【问题讨论】:

  • path elements 有一个 API,其中包括将 xy 坐标作为长度的函数。您可以使用二进制搜索将其反转为 xy 的函数。您还可以使用路径元素构建路径,并轻松获取每个组件的长度。

标签: svg bezier spline


【解决方案1】:
  1. 总路径长度:SVG APIpath.getTotalLength()
  2. 沿路径的长度:SVG API:path.getPointAtLength(...),您可能希望基于总长度
  3. 一个点的曲率半径:API 中没有烘焙,因此您将不得不通过简单地将一个圆拟合到您的点以及它之前和之后的点来滚动自己。

我们构造三个点:

var p1 = path.getPointAtLength(n - e),
    p2 = path.getPointAtLength(n),
    p3 = path.getPointAtLength(n + e);

e 是一个很小的值。然后,我们知道通过所有三个点的圆在圆上的每个点都具有相同的距离(显然),并且我们还知道如果我们在点之间构造和弦,那么通过这些弦的中心的线(垂直于它们)将在圆的中心相交。

这就是通过任意三个点找到圆的方法:我们需要找到和弦p1--p2p2--p3,找到它们的中点,通过这些中点构造一些垂直于每个弦的线,然后它们的交点就是我们圈子的中心,我们就完成了。我们将知道原点的曲率半径。所以:

// chords p1--p2 and p2--p3
var dx1 = (p2.x - p1.x), dy1 = (p2.y - p1.y),
    dx2 = (p3.x - p2.x), dy2 = (p3.y - p2.y);

// chord midpoints
var mx1 = (p1.x + p2.x)/2, my1 = (p1.y + p2.y)/2,
    mx2 = (p2.x + p3.x)/2, my2 = (p2.y + p3.y)/2;

// chord normals
var nx1 = -dy1, ny1 = dx1
    nx2 = -dy2, ny2 = dx2;

// chord midpoint offsets along the normals
var ox1 = mx1 + dx1p, oy1 = my1 + dy1p,
    ox2 = mx2 + dx2p, oy2 = my2 + dy2p;

然后我们可以使用公共线相交测试找到圆的中点:

// line-line-intersection using a flat 8 coordinate values
function lli8(x1,y1,x2,y2,x3,y3,x4,y4) {
  var nx=(x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4),
      ny=(x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4),
      d=(x1-x2)*(y3-y4)-(y1-y2)*(x3-x4);
  if(d==0) { return false; }
  return { x: nx/d, y: ny/d };
}

我们称之为lli8(mx1, my1, ox1, oy1, mx2, my2, ox2, oy2),因为我们通过这三个点知道圆的中心,所以我们得到了我们最初感兴趣的点的半径。

【讨论】:

    【解决方案2】:

    路径元素有一个可以调用的getPointAtLength() 方法。你沿着曲线传递一个长度,它会返回 x 和 y。

    var path = document.getElementById("test");
    var point = path.getPointAtLength(300);
    alert("x=" + point.x + " y=" + point.y);
    <svg>
      <path id="test" d="M 0,0 C 0,150 300,0 300,150" fill="none" stroke="black"/>
    </svg>

    【讨论】:

      猜你喜欢
      • 2021-01-30
      • 1970-01-01
      • 2014-05-03
      • 2017-10-25
      • 1970-01-01
      • 2018-10-18
      • 2015-02-10
      • 1970-01-01
      • 2021-11-25
      相关资源
      最近更新 更多