Vue
/**
* 判断点是否多边形内
* @param {Point} point 点对象
* @param {Polyline} polygon 多边形对象
* @returns {Boolean} 点在多边形内返回true,否则返回false
*/
export function isPointInPolygon(point, polygon) {
// 检查类型
// eslint-disable-next-line no-undef
if (!(point instanceof BMap.Point) ||
// eslint-disable-next-line no-undef
!(polygon instanceof BMap.Polygon)) {
return false
}
// 首先判断点是否在多边形的外包矩形内,如果在,则进一步判断,否则返回false
const polygonBounds = polygon.getBounds()
if (!isPointInRect(point, polygonBounds)) {
return false
}
const pts = polygon.getPath()// 获取多边形点
// 下述代码来源:http:// paulbourke.net/geometry/insidepoly/,进行了部分修改
// 基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则
// 在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。
const N = pts.length
const boundOrVertex = true // 如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
let intersectCount = 0// cross points count of x
const precision = 2e-10 // 浮点类型计算时候与0比较时候的容差
let p1, p2// neighbour bound vertices
const p = point // 测试点
p1 = pts[0]// left vertex
for (let i = 1; i <= N; ++i) {
// check all rays
if (p.equals(p1)) {
return boundOrVertex// p is an vertex
}
p2 = pts[i % N]
// right vertex
if (p.lat < Math.min(p1.lat, p2.lat) || p.lat > Math.max(p1.lat, p2.lat)) {
// ray is outside of our interests
p1 = p2
continue
// next ray left point
}
if (p.lat > Math.min(p1.lat, p2.lat) && p.lat < Math.max(p1.lat, p2.lat)) {
// ray is crossing over by the algorithm (common part of)
if (p.lng <= Math.max(p1.lng, p2.lng)) {
// x is before of ray
if (p1.lat === p2.lat && p.lng >= Math.min(p1.lng, p2.lng)) {
// overlies on a horizontal ray
return boundOrVertex
}
if (p1.lng === p2.lng) {
// ray is vertical
if (p1.lng === p.lng) {
// overlies on a vertical ray
return boundOrVertex
} else {
// before ray
++intersectCount
}
} else {
// cross point on the left side
const xinters = (p.lat - p1.lat) * (p2.lng - p1.lng) / (p2.lat - p1.lat) + p1.lng
// cross point of lng
if (Math.abs(p.lng - xinters) < precision) {
// overlies on a ray
return boundOrVertex
}
if (p.lng < xinters) {
// before ray
++intersectCount
}
}
}
} else {
// special case when ray is crossing through the vertex
if (p.lat === p2.lat && p.lng <= p2.lng) {
// p crossing over p2
const p3 = pts[(i + 1) % N]
// next vertex
if (p.lat >= Math.min(p1.lat, p3.lat) && p.lat <= Math.max(p1.lat, p3.lat)) {
// p.lat lies between p1.lat & p3.lat
++intersectCount
} else {
intersectCount += 2
}
}
}
p1 = p2
// next ray left point
}
if (intersectCount % 2 === 0) {
// 偶数在多边形外
return false
} else {
// 奇数在多边形内
return true
}
}
/**
* 判断点是否在矩形内
* @param {Point} point 点对象
* @param {Bounds} bounds 矩形边界对象
* @returns {Boolean} 点在矩形内返回true,否则返回false
*/
export function isPointInRect(point, bounds) {
// 检查类型是否正确
// eslint-disable-next-line no-undef
if (!(point instanceof BMap.Point) ||
// eslint-disable-next-line no-undef
!(bounds instanceof BMap.Bounds)) {
return false
}
const sw = bounds.getSouthWest()
// 西南脚点
const ne = bounds.getNorthEast()
// 东北脚点
return (point.lng >= sw.lng && point.lng <= ne.lng && point.lat >= sw.lat && point.lat <= ne.lat)
}
测试
// 判断经纬度在那个网格内
gridRange() {
noPageGridList().then(res => {
res.data.data.forEach(result => {
const pointArray = []
JSON.parse(result.path).forEach(everyPoint => {
// eslint-disable-next-line no-undef
pointArray.push(new BMap.Point(everyPoint.lng, everyPoint.lat))
})
// eslint-disable-next-line no-undef
const judgePolygon = new BMap.Polygon(pointArray)
const jsonPoint = JSON.parse(this.temp.coordinates)
// eslint-disable-next-line no-undef
const site = new BMap.Point(jsonPoint.lng, jsonPoint.lat)
const judgement = isPointInPolygon(site, judgePolygon)
if (judgement) {
this.organizationId = result.organizationId
return
}
})
})
}
Java
待完成
声明
代码资源来源于百度地图官方