已知元素坐标和框选区域(ptl, ptr, pbr, pbl),判断选择框是否触碰到元素。

解:
由元素坐标可得4个顶点(point_tl, point_tr, point_bl, point_br)

  1. 两多边形是否相交 -> 线段相交
    1. 判断元素某边与框选区域某边是否相交(即证: 线与线相交[向量叉乘])如果两个线段相交,则一条线段的两个端点位于另一条线段的两边.
  2. 元素在选择框内
  3. 选择框在元素内 -> 选择框某顶点在元素内
// 两多边形是否碰撞||包含
utils.checkPolygonIsTouch = (polygon1, polygon2) => {
  // 判断线与线是否相交....orz...
  const isThrowItem = () => {
    return utils.checkCross(polygon1[0], polygon1[1], polygon2[0], polygon2[1]) ||
    utils.checkCross(polygon1[0], polygon1[1], polygon2[1], polygon2[2]) ||
    utils.checkCross(polygon1[0], polygon1[1], polygon2[2], polygon2[3]) ||
    utils.checkCross(polygon1[0], polygon1[1], polygon2[3], polygon2[0]) ||

    utils.checkCross(polygon1[1], polygon1[2], polygon2[0], polygon2[1]) ||
    utils.checkCross(polygon1[1], polygon1[2], polygon2[1], polygon2[2]) ||
    utils.checkCross(polygon1[1], polygon1[2], polygon2[2], polygon2[3]) ||
    utils.checkCross(polygon1[1], polygon1[2], polygon2[3], polygon2[0]) ||

    utils.checkCross(polygon1[2], polygon1[3], polygon2[0], polygon2[1]) ||
    utils.checkCross(polygon1[2], polygon1[3], polygon2[1], polygon2[2]) ||
    utils.checkCross(polygon1[2], polygon1[3], polygon2[2], polygon2[3]) ||
    utils.checkCross(polygon1[2], polygon1[3], polygon2[3], polygon2[0]) ||

    utils.checkCross(polygon1[3], polygon1[0], polygon2[0], polygon2[1]) ||
    utils.checkCross(polygon1[3], polygon1[0], polygon2[1], polygon2[2]) ||
    utils.checkCross(polygon1[3], polygon1[0], polygon2[2], polygon2[3]) ||
    utils.checkCross(polygon1[3], polygon1[0], polygon2[3], polygon2[0])
  }

  return isThrowItem() ||
  // 判断是否在多边形内
  utils.checkPIsInPolygon({ polygon: polygon1, point: polygon2[0] }) ||
  utils.checkPIsInPolygon({ polygon: polygon1, point: polygon2[1] }) ||
  utils.checkPIsInPolygon({ polygon: polygon1, point: polygon2[2] }) ||
  utils.checkPIsInPolygon({ polygon: polygon1, point: polygon2[3] }) ||
  // 选择框4顶点 是否在元素内
  utils.checkPIsInPolygon({ polygon: polygon2, point: polygon1[0] }) ||
  utils.checkPIsInPolygon({ polygon: polygon2, point: polygon1[1] }) ||
  utils.checkPIsInPolygon({ polygon: polygon2, point: polygon1[2] }) ||
  utils.checkPIsInPolygon({ polygon: polygon2, point: polygon1[3] })
}

// 判断点是否在多边形内...orz...
utils.checkPIsInPolygon = function ({ point, polygon }) {
  let p3, p4
  const p1 = point
  const p2 = { x: -10000, y: point.y }
  let count = 0
  // 对每条边都和射线作对比
  for (let i = 0; i < polygon.length - 1; i++) {
    p3 = polygon[i]
    p4 = polygon[i + 1]
    if (utils.checkCross(p1, p2, p3, p4) == true) {
      count++
    }
  }
  p3 = polygon[polygon.length - 1]
  p4 = polygon[0]
  if (utils.checkCross(p1, p2, p3, p4) == true) {
    count++
  }
  return count % 2 != 0;
}

// 判断两直线是否相交 判断两条线相交 => 同理判断两点在直线两边 orz...
utils.checkCross = (p1, p2, p3, p4) => {
  // 计算向量叉乘
  const crossMul = (v1, v2) => {
    return v1.x * v2.y - v1.y * v2.x;
  };
  let v1 = { x: p1.x - p3.x, y: p1.y - p3.y };
  let v2 = { x: p2.x - p3.x, y: p2.y - p3.y };
  let v3 = { x: p4.x - p3.x, y: p4.y - p3.y };
  const v = crossMul(v1, v3) * crossMul(v2, v3);
  v1 = { x: p3.x - p1.x, y: p3.y - p1.y };
  v2 = { x: p4.x - p1.x, y: p4.y - p1.y };
  v3 = { x: p2.x - p1.x, y: p2.y - p1.y };

  return !!((v <= 0 && crossMul(v1, v3) * crossMul(v2, v3) <= 0));
}

附: 旋转点计算

/**
   * 计算旋转后的点坐标
   * @param {Object: {x: number, y: number}} point 坐标点
   * @param {Object: {x: number, y: number}} point_origin 旋转中心点
   * @param {Array} matrixArr transform矩阵值
   * @return {x, y} 保留2位小数
   */
utils.GetRotatePoint = ({ point, matrixArr, point_origin }) => {
  const [cosθ, sinθ] = matrixArr;
  const x = (point.x - point_origin.x) * cosθ - (point.y - point_origin.y) * sinθ + point_origin.x;
  const y = (point.x - point_origin.x) * sinθ + (point.y - point_origin.y) * cosθ + point_origin.y;

  return {
    x: Math.round(x * 100) / 100,
    y: Math.round(y * 100) / 100
  }
}