先说一下,两个方法均是js实现,均是转载自其他大佬的文章,地址贴在下面
我最近接了个单子,里面有很多大棚,要求鼠标进入大棚范围高亮,我试过网上很多方法。大多不准确,或者说不适合有很多矩形、多边形的这种环境。后来找到了两种方法,可以实现。
放心,能满足我这种有很多矩形、多边形的 ,肯定也能满足你们那些多边形不多的需求
方法一:转载自JS实现判断点是否在多边形范围内 - 馨语随风 - 博客园 (cnblogs.com)
原理:在GIS领域,判断点是否在多边形范围内是一个基础方法,这里主要说下实现原理。原理比较简单,就是有一个GIS理论,一个点向一个方向发送射线,射线与多边形各个边相交的交点如果是奇数说明点在多边形范围内。
说一下我个人使用存在的误差:由于做鼠标的射线会穿过很多多边形,当这个线擦着其他多边形的点经过的时候,会判定相交一个点,这个时候那个多边形也会被点亮,还是有误差的。但如果多边形数量少的话可以使用,没问题
//判断点是否在多边形范围内
function queryPtInPolygon(point, polygon) {
var p1, p2, p3, p4;
p1 = point;
p2 = { x: 1000000000000, y: point.y };
var count = 0;
//对每条边都和射线作对比
for (var i = 0; i < polygon.length - 1; i++) {
p3 = polygon[i];
p4 = polygon[i + 1];
if (checkCross(p1, p2, p3, p4) == true) {
count++;
}
}
p3 = polygon[polygon.length - 1];
p4 = polygon[0];
if (checkCross(p1, p2, p3, p4) == true) {
count++;
}
return (count % 2 == 0) ? false : true;
}
//判断两条线段是否相交
function checkCross(p1, p2, p3, p4) {
var v1 = { x: p1.x - p3.x, y: p1.y - p3.y },
v2 = { x: p2.x - p3.x, y: p2.y - p3.y },
v3 = { x: p4.x - p3.x, y: p4.y - p3.y },
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) ? true : false;
}
//计算向量叉乘
function crossMul(v1, v2) {
return v1.x * v2.y - v1.y * v2.x;
}
使用示例
var point={x:10,y:10};
var polygon=[{x:0,y:0},{x:100,y:0},{x:100,y:100},{x:0,y:100},{x:0,y:0}];
var pts=queryPtInPolygon(points,polygon); //pts即为和多边形交叉的点集合,判断为奇数说明在多边形范围内
方法二:最牛逼的方法 转载自判断点是否在多边形内部 - 知乎 (zhihu.com)
function ContainsPoint(polygon, pointX, pointY) {
let n = polygon.length >> 1;
let ax, lup;
let ay = polygon[2 * n - 3] - pointY;
let bx = polygon[2 * n - 2] - pointX;
let by = polygon[2 * n - 1] - pointY;
if (bx === 0 && by === 0) return false; // point on edge
// let lup = by > ay;
for (let ii = 0; ii < n; ii++) {
ax = bx;
ay = by;
bx = polygon[2 * ii] - pointX;
by = polygon[2 * ii + 1] - pointY;
if (bx === 0 && by === 0) return false; // point on edge
if (ay === by) continue;
lup = by > ay;
}
let depth = 0;
for (let i = 0; i < n; i++) {
ax = bx;
ay = by;
bx = polygon[2 * i] - pointX;
by = polygon[2 * i + 1] - pointY;
if (ay < 0 && by < 0) continue; // both 'up' or both 'down'
if (ay > 0 && by > 0) continue; // both 'up' or both 'down'
if (ax < 0 && bx < 0) continue; // both points on the left
if (ay === by && Math.min(ax, bx) < 0) return true;
if (ay === by) continue;
let lx = ax + ((bx - ax) * -ay) / (by - ay);
if (lx === 0) return false; // point on edge
if (lx > 0) depth++;
if (ay === 0 && lup && by > ay) depth--; // hit vertex, both up
if (ay === 0 && !lup && by < ay) depth--; // hit vertex, both down
lup = by > ay;
}
return (depth & 1) === 1;
}
polygon---组成多边形的点 [x1, y1, x2, y2, x3, y3, ...]