在 Javascript 中用多边形剪裁一条线

时间:2021-07-14 16:52:27

标签: javascript geometry data-visualization trigonometry

我评估了各种不同的库,试图找到一种解决方案,让我可以采用任意线并用多边形对其进行裁剪。

我想要做的是取 A 和 B 之间的线并用正方形剪裁它,结果是坐标 C、D。请注意这是一个简单的例子,实际上将使用多面多边形.

enter image description here

评估的库只执行多边形到多边形的布尔运算 https://github.com/alexbol99/flatten-js https://npm.io/package/polygon-clipping https://github.com/velipso/polybooljs

我需要一种可以执行此操作的技术或库。与往常一样,任何帮助将不胜感激!

在实施以下解决方案后,我很快发现了一些难以克服的问题。我的下一步是找到两个交点之间的中点并确定它是否在多边形内。 enter image description here

更新: enter image description here

查找中间点并确定它是否在多边形内部适用于具有开始和结束的线段。但是,拥有多段线并非易事。该算法可以对每个单独的线段进行交叉检测,但成本会很高。

1 个答案:

答案 0 :(得分:0)

假设您将多边形 P 作为线段数组(每段有四个数字,因为有两个端点,每个端点有两个坐标)以及 A 和 B 的坐标。我们想找到线段之间所有交点的坐标AB 和多边形中的线段。

您可以简单地测试多边形的每一段是否与 AB 相交以及在何处与 AB 相交。这将为您提供所有 C, D, ... 点。这是这种算法的一个选项(在 js 中):

function intersection(ax, ay, bx, by, cx, cy, dx, dy) {
  // ax, ay, bx, and by are the coordinates of the endpoints of one line segment
  // cx, cy, dx, and dy are the coordinates of the endpoints of the other line segment
  // returns [x, y], the coordinates of their intersection
  // returns [NaN, NaN] if they do not intersect
  let x, y;
  if (ax === bx) {
    x = ax;
    y = cy + ((dy - cy) / (dx - cx)) * (ax - cx);
  } else if (cx === dx) {
    x = cx;
    y = ay + ((by - ay) / (bx - ax)) * (cx - ax);
  } else {
    x =
      (ay - cy + (cx * (dy - cy)) / (dx - cx) - (ax * (by - ay)) / (bx - ax)) /
      ((dy - cy) / (dx - cx) - (by - ay) / (bx - ax));
    y = ay + ((by - ay) * (x - ax)) / (bx - ax);
  }
  if (
    ((ax <= x && x <= bx) || (bx <= x && x <= ax)) &&
    ((ay <= y && y <= by) || (by <= y && y <= ay)) &&
    ((cx <= x && x <= dx) || (dx <= x && x <= cx)) &&
    ((cy <= y && y <= dy) || (dy <= y && y <= cy))
  ) {
    return [x, y];
  }
  return [0 / 0, 0 / 0];
}

如果循环遍历多边形的边并将每个交点添加到数组中,则该数组中最终会出现 CD。根据您打算如何处理这些要点,您可能需要考虑以下几种情况:

  1. AB 在多边形内。即使 AB 的部分位于多边形内部,这也可能导致您的交点数组为空。
  2. 多边形是凹面的(如 Ripi2 在上面的评论中提到的)。这将使交点数组的长度可能超过两个点,这将使确定线在多边形内部和外部的位置变得更加困难。