基于 Highcharts 的官方教程 我们可以很轻松的通过经纬度定位点,也很轻松的用眼睛看出其所在区域,但是如何用代码实现这个看的过程呢?
简单分析一下这个问题,由于 Highmaps 的底图和定位点完全是两个独立的数据列,他们两者的关系不大,地图底图是由多个点组成的不规则点,所以这个问题可以抽象成 “判断一个坐标点是否在不规则多边形内部”,算法是 PNPoly
结合 Highmaps,该算法的实现是:
/**
- PNPoly 算法查找坐标点是否在不规则多边形(Highmaps 底图区域)中
- @param [x, y] point 坐标点
- @param Highcharts.Point area Highmaps 底图数据点对象
- @return boolean point is in area
*/
function pointInArea(point, area) {
var x = point[0],
y = point[1],
xAxis = map.xAxis[0],
yAxis = map.yAxis[0];
// 如果点不在不规则多边形所在矩形内,则直接返回 false
if (x < area._minX || x > area._maxX || y > area._maxY || y < area._minY) {
return false;
}
var paths = area.path, // paths 为 svg 命令数组,形如 ['L', 1212, 11212, 1212, 2323, 'M'...]
i = 0,
currentPoint = null, // 当前点
lastPoint = null, // 前一个点
firstPoint = null, // 第一个点
even = false, // 是否是偶数
result = false, // 结果
length = paths.length;
for (; i < length; i++) {
// 只有是数值的时候才是点的坐标值
if (Highcharts.isNumber(paths[i])) {
if (even) { // 偶数时才构成一个 x,y 点
currentPoint = [paths[i - 1], paths[i]];
even = !even;
} else {
even = !even;
continue;
}
if (lastPoint) {
// 根据 PNPoly 算法来计算点是否在区域内
// 参考链接:
// * http://www.cnblogs.com/armyfai/p/3529243.html
// * http://riyueshi.github.io/2015/10/07/is_point_in_polygon/
if (
(lastPoint[1] > y) !== (currentPoint[1] > y) &&
(x < (currentPoint[0] - lastPoint[0]) * (y - lastPoint[1]) / (currentPoint[1] - lastPoint[1]) + currentPoint[0])
) {
result = !result;
}
} else {
// 保存第一个点
firstPoint = currentPoint;
}
lastPoint = currentPoint;
}
}
// 补充计算最后一个点和第一个点
if (
(lastPoint[1] > y) !== (firstPoint[1] > y) &&
(x < (firstPoint[0] - lastPoint[0]) * (y - lastPoint[1]) / (firstPoint[1] - lastPoint[1]) + firstPoint[0])
) {
result = !result;
}
return result
}
具体的代码见 例子,例子截图