# 判断点是否在线上
其实判断点是否在线上,跟判断折线方向一样,就是三个点共线,那么他们之间的叉乘就是 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))
阅读量: