- 度娘了一圈,只发现了一个python代码有用。其他要么太复杂,要么都是调GD地图util啊,BD地图util啊,或者Java util的封装好的方法,但人家又不开源啊!我把这段python翻译成了js代码,简单测试发现OK。这代码看起来也太简单了,简单到我都不相信,,,but, it works!!!
设:需要判断的目标点为P
参数
aLat: P的纬度
aLon: P的经度
pointList: 单个多边形区域顶点数组。如果有多个独立区域,则分别调用本方法,只要有一次为ture即表示在区域内。
getLatLngFunc: 见调用示例
调用示例:
- 假设原始数据如 pointList = [{lng: 113.111111, lat, 23.111111},...],则可省略getLatLngFunc
utilofMap.IsPtInPoly(23.xx, 113.xx, pointList)
- 假设原始数据如 pointList = [[113.111111, 23.111111],...],则应传入的getLatLngFunc为
utilofMap.IsPtInPoly(23.xx, 113.xx, pointList, (orgin) => {return {lat: orgin[1], lng: orgin[0]}})
- 假设原始数据如 pointList = [{longitude: 113.111111, latitude, 23.111111},...],则应传入的getLatLngFunc为
utilofMap.IsPtInPoly(23.xx, 113.xx, pointList, (orgin) => {return {lat: orgin.latitude, lng: orgin.longitude}})
utilofMap.js文件:
function IsPtInPoly(aLat, aLon, pointList, getLatLngFunc = (obj) => {return obj}) {
/*
:param aLon: double 经度
:param aLat: double 纬度
:param pointList: list [{latitude: 22.22, longitude: 113.113}...] 多边形点的顺序需根据顺时针或逆时针,不能乱
*/
var iSum = 0
var iCount = pointList.length
if(iCount < 3) {
return false
}
// 待判断的点(x, y) 为已知值
var y = aLat
var x = aLon
for(var i = 0; i < iCount; i++) {
var y1 = getLatLngFunc(pointList[i]).lat
var x1 = getLatLngFunc(pointList[i]).lng
if(i == iCount - 1) {
var y2 = getLatLngFunc(pointList[0]).lat
var x2 = getLatLngFunc(pointList[0]).lng
} else {
var y2 = getLatLngFunc(pointList[i + 1]).lat
var x2 = getLatLngFunc(pointList[i + 1]).lng
}
// 当前边的 2 个端点分别为 已知值(x1, y1), (x2, y2)
if (((y >= y1) && (y < y2)) || ((y >= y2) && (y < y1))) {
// y 界于 y1 和 y2 之间
// 假设过待判断点(x, y)的水平直线和当前边的交点为(x_intersect, y_intersect),有y_intersect = y
// 则有(2个相似三角形,公用顶角,宽/宽 = 高/高):|x1 - x2| / |x1 - x_intersect| = |y1 - y2| / |y1 - y|
if (Math.abs(y1 - y2) > 0) {
var x_intersect = x1 - ((x1 - x2) * (y1 - y)) / (y1 - y2);
if(x_intersect < x) {
iSum += 1
}
}
}
}
if(iSum % 2 != 0) {
return true
}else {
return false
}
}
module.exports = {
IsPtInPoly: IsPtInPoly,
};