JS 点到线段的距离

826 阅读1分钟

先求点到线段的距离

/**
 * 点到线段的距离
 * @param {Array} point1 [x1, y1] 直线上点1
 * @param {Array} point2 [x2, y2] 直线上点2
 * @param {Array} point [xx, yy]
 * @returns {Number}
 */
distanceOfPoint2LineSegment([x1, y1], [x2, y2], [xx, yy]) {
  /** 求垂线交点
   * 直线方程  (y - y1) / (y2 - y1) = (x - x1) / (x2 - x1)  =>  y = (x - x1) / (x2 - x1) * (y2 - y1) + y1
   * 斜率      k1 = (y2 - y1) / (x2 - x1)
   * 垂线斜率  k2 = -1 / k1
   * 垂线平移  b = yy - k2 * xx
   * 垂线方程  y = k2 * x + b
   * 求两直线交点 (x - x1) / (x2 - x1) * (y2 - y1) + y1 = k2 * x + b
   * => ((y2 - y1) / (x2 - x1) - k2) * x = b - y1 + ((y2 - y1) / (x2 - x1)) * x1
   * => (k1 - k2) * x = b - y1 + k1 * x1
   */
  const k1 = (y2 - y1) / (x2 - x1)
  const k2 = -1 / k1
  const b = yy - k2 * xx
  // 两直线交点
  const x = (b - y1 + k1 * x1) / (k1 - k2)
  const y = k2 * x + b
  const [[minX, minY], [maxX, maxY]] = x1 < x2 ? [[x1, y1], [x2, y2]] : [[x2, y2], [x1, y1]]
  // 如果中垂线的交点在线段外,那么距离就是点到直线端点的距离
  if (x > maxX) {
    return Math.sqrt((xx - maxX) ** 2 + (yy - maxY) ** 2)
  }
  if (x < minX) {
    return Math.sqrt((xx - minX) ** 2 + (yy - minY) ** 2)
  }
  return Math.sqrt((xx - x) ** 2 + (yy - y) ** 2)
},