# 判断点是否在线上

其实判断点是否在线上,跟判断折线方向一样,就是三个点共线,那么他们之间的叉乘就是 0 。设点为 Q,线段为 P1P2 判断点 Q 在该线段上的依据是:

  • (Q-P1) x (P2-P1) = 0
  • Q 在以 P1、P2为 对角顶点的矩形内

前者保证 Q 点在直线 P1P2 上,后者是保证 Q 点不在线段 P1P2 的延长线或反向延长线上,对于这一步骤的判断可以用以下过程实现:

/**
 * 判断 checkPoint 是否在 startPoint 与 endPoint 组成的线段上
 * @param {*} startPoint 点1
 * @param {*} endPoint 点2
 * @param {*} checkPoint 点3
 * <returns>true:在线上;false:不在线上</returns>
 */
function isOnSegment(startPoint, endPoint, checkPoint) {
  const L2 = (((endPoint.x - startPoint.x) * (endPoint.x - startPoint.x)) + ((endPoint.y - startPoint.y) * (endPoint.y - startPoint.y)) )
  if(L2 === 0) return false
  const r = ( ((checkPoint.x - startPoint.x) * (endPoint.x - startPoint.x)) + ((checkPoint.y - startPoint.y) * (endPoint.y - startPoint.y)) ) / L2
  return (0 <= r) && (r <= 1)
}

const startPoint = {x: 30, y: 30}
const checkPoint = {x: 40, y: 40}
const endPoint = {x: 50, y: 50}

console.log(isOnSegment(startPoint, endPoint, endPoint))

或者

/**
 * 判断 checkPoint 是否在 startPoint 与 endPoint 组成的线段上
 * @param {*} startPoint 点1
 * @param {*} endPoint 点2
 * @param {*} checkPoint 点3
 * <returns>true:在线上;false:不在线上</returns>
 */
function isOnSegment(startPoint, endPoint, checkPoint) {
  // 判断是否共线
  const L2 = (((endPoint.x - startPoint.x) * (endPoint.x - startPoint.x)) + ((endPoint.y - startPoint.y) * (endPoint.y - startPoint.y)) )
  if(L2 === 0) return false
  // 判断是否在矩形内
  const minx = Math.min.call(Math, startPoint.x, endPoint.x)
  const miny = Math.min.call(Math, startPoint.y, endPoint.y)
  const maxx = Math.max.call(Math, startPoint.x, endPoint.x)
  const maxy = Math.max.call(Math, startPoint.y, endPoint.y)
  console.log(minx, miny, maxx, maxy)
  if (checkPoint.x >= minx && checkPoint.x <= maxx && checkPoint.y >= miny&& checkPoint.y <= maxy ) {
    return true
  }
  return false
}

const startPoint = {x: 30, y: 30}
const checkPoint = {x: 40, y: 40}
const endPoint = {x: 50, y: 50}

console.log(isOnSegment(startPoint, endPoint, endPoint))

上面代码只是判断点是否在直线上,下面代码可以判断点是否在折线上(也就是循环遍历线数组执行上面的操作):

function booleanPointOnLine(ptCoords, lineCoords) {

  for (let i = 0; i < lineCoords.length - 1; i++) {
    if (isPointOnLineSegment(lineCoords[i], lineCoords[i + 1], ptCoords)) { return true }
  }
  return false
}
function isPointOnLineSegment(lineSegmentStart, lineSegmentEnd, pt) {
  const x = pt[0]
  const y = pt[1]
  const x1 = lineSegmentStart[0]
  const y1 = lineSegmentStart[1]
  const x2 = lineSegmentEnd[0]
  const y2 = lineSegmentEnd[1]
  const dxc = pt[0] - x1
  const dyc = pt[1] - y1
  const dxl = x2 - x1
  const dyl = y2 - y1
  const cross = dxc * dyl - dyc * dxl
  if (cross !== 0) {
    return false
  }
  if (Math.abs(dxl) >= Math.abs(dyl)) {
    return dxl > 0 ? x1 <= x && x <= x2 : x2 <= x && x <= x1
  }
  return dyl > 0 ? y1 <= y && y <= y2 : y2 <= y && y <= y1
}


const ptCoords = [0, 0]
const lineCoords = [[-1, -1],[1, 1],[1.5, 2.2]]
console.log(booleanPointOnLine(ptCoords, lineCoords))

评 论:

更新: 11/21/2020, 7:00:56 PM