You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Konva中检测线多边形完全位于另一线多边形内的实现方法

Konva线多边形包含关系判断实现方案

多边形包含判断本质是几何计算问题,和React Konva框架本身没有强绑定,核心逻辑是拿到两个多边形的绝对坐标顶点后,用标准几何规则校验即可,具体实现步骤如下:

1. 预处理:获取多边形绝对坐标顶点

如果多边形做过平移、旋转、缩放等变换,原始存储的顶点坐标会和画布实际渲染位置不一致,需要先转换为全局坐标系下的绝对坐标:

// 入参为Konva.Polygon实例
const getAbsolutePoints = (polygonNode) => {
  const rawPoints = polygonNode.points();
  const transform = polygonNode.getAbsoluteTransform();
  const points = [];
  for (let i = 0; i < rawPoints.length; i += 2) {
    const absolutePoint = transform.point({
      x: rawPoints[i],
      y: rawPoints[i + 1]
    });
    points.push([absolutePoint.x, absolutePoint.y]);
  }
  return points;
}

2. 核心几何算法实现

判断多边形A完全处于多边形B内部,需要同时满足两个条件:

  • 多边形A的所有顶点都在多边形B内部
  • 多边形A的所有边和多边形B的所有边没有交点

点是否在多边形内(射线法)

const isPointInPolygon = (point, polygonPoints) => {
  const [px, py] = point;
  let inside = false;
  const len = polygonPoints.length;
  for (let i = 0, j = len - 1; i < len; j = i++) {
    const [xi, yi] = polygonPoints[i];
    const [xj, yj] = polygonPoints[j];
    const intersect = ((yi > py) !== (yj > py))
      && (px < (xj - xi) * (py - yi) / (yj - yi) + xi);
    if (intersect) inside = !inside;
  }
  return inside;
}

两条线段是否相交

const isSegmentsIntersect = (seg1, seg2) => {
  const [[x1, y1], [x2, y2]] = seg1;
  const [[x3, y3], [x4, y4]] = seg2;
  // 叉积计算判断朝向
  const ccw = (a, b, c) => (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
  return ccw([x1, y1], [x3, y3], [x4, y4]) * ccw([x2, y2], [x3, y3], [x4, y4]) < 0
    && ccw([x1, y1], [x2, y2], [x3, y3]) * ccw([x1, y1], [x2, y2], [x4, y4]) < 0;
}

3. 组合逻辑完成判断

const isPolygonFullyInside = (innerPolygon, outerPolygon) => {
  // 先做包围盒快速过滤,减少不必要的计算
  const innerRect = innerPolygon.getClientRect();
  const outerRect = outerPolygon.getClientRect();
  if (
    innerRect.x < outerRect.x ||
    innerRect.y < outerRect.y ||
    innerRect.x + innerRect.width > outerRect.x + outerRect.width ||
    innerRect.y + innerRect.height > outerRect.y + outerRect.height
  ) {
    return false;
  }

  const innerPoints = getAbsolutePoints(innerPolygon);
  const outerPoints = getAbsolutePoints(outerPolygon);

  // 校验所有内多边形顶点都在外多边形内部
  const allPointsInside = innerPoints.every(p => isPointInPolygon(p, outerPoints));
  if (!allPointsInside) return false;

  // 提取多边形边
  const getEdges = (points) => {
    return points.map((p, i) => [p, points[(i + 1) % points.length]]);
  }
  const innerEdges = getEdges(innerPoints);
  const outerEdges = getEdges(outerPoints);

  // 校验无交叉边
  for (const innerEdge of innerEdges) {
    for (const outerEdge of outerEdges) {
      if (isSegmentsIntersect(innerEdge, outerEdge)) return false;
    }
  }

  return true;
}

该方案不需要引入任何额外第三方库,性能足以应对前端常规场景下的多边形判断需求。

内容的提问来源于stack exchange,提问作者user1791139

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 12:12:01