赞
踩
GeoHash是很多基于LBS(Location Based Services)服务不可绕过的解决方案之一,网上关于GeoHash的介绍和算法很多,资源也算比较丰富。这篇文章主要是介绍如何利用GeoHash或者进行逆地理编码(经纬度坐标转换行政区划)的实现。
GeoHash是按照固定的算法,将经纬度信息转换为Base32码表中的一串字符。具体的算法网上资源较多,不进行详细介绍。逻辑并不是非常复杂,大概逻辑如下:
推荐一个github上GeoHash的实现:
GeoHash算法实现
GeoHash使用5位计算结果(左右区间)作为一个精度,例如wtw6kf
共有6个Base32编码表的字母或数字,代表这个geoHash值的精度为6。
118.797405,32.044227
为例,该坐标点实际上是无数个精度更高(小数点后精确位到6位以后)的坐标点集合;将其放大理解,可以看作为一个二维矩形,此二维矩形的4角的坐标值分别应为:坐标位置 | 经度 | 纬度 |
---|---|---|
西南点 | 118.797405 | 32.044227 |
西北点 | 118.797405 | 32.044227999999… |
东北点 | 118.797405999999… | 32.044227999999… |
东南点 | 118.797405999999… | 32.044227 |
118.797405,32.044227
(实际地理位置为:江苏省南京市总统府)的6位精度geoHash值wtsqr3
为例,其二维矩形4角的坐标值分别为:坐标位置 | 经度 | 纬度 |
---|---|---|
西南点 | 118.795166015625 | 32.0416259765625 |
西北点 | 118.795166015625 | 32.047119140625 |
东北点 | 118.80615234375 | 32.047119140625 |
东南点 | 118.80615234375 | 32.0416259765625 |
在地图上表现为:
在线绘制地址围栏
可见该GeoHash块的覆盖面积已经将地理位置江苏省南京市总统府完全覆盖,并且也会覆盖更多其他地区。
通过GeoHash的运算规则和全球经纬度范围,可以推导出不同精度的GeoHash块父子级规律:即精度为n的GeoHash会有32个精度为n+1的GeoHash块。例如当GeoHash值精度为1,全世界地图都会被32个GeoHash值覆盖。例如精度为1的GeoHash值w
,其会覆盖我国大部分国土。
在线标选GeoHash块
当GeoHash精度为2时,其展示效果如下:
当GeoHash精度为3时,其展示效果如下:
所以如果要遍历GeoHash时,不需要进行经纬度的再次运算,可以根据GeoHash奇偶数的规律,进行GeoHash值的生成。其中奇数位的规律如下表所示:
偶数位的规律如下表所示:
逆地理编码指的是将经纬度坐标转换为具体的标准的行政区划信息,以高德逆地理编码接口为例,坐标点118.797405,32.044227
响应的结果如下:
{ "status": "1", "regeocode": { "addressComponent": { "city": "南京市", "province": "江苏省", "adcode": "320102", "district": "玄武区", "towncode": "320102002000", "streetNumber": { "number": "292号", "location": "118.797317,32.044008", "direction": "南", "distance": "25.7166", "street": "长江路" }, "country": "中国", "township": "梅园新村街道", "citycode": "025" }, "formatted_address": "江苏省南京市玄武区梅园新村街道总统府" }, "info": "OK", "infocode": "10000" }
此篇博文只介绍可以模拟到行政区划的省/直辖市、二级市、区/县/三级市的方式。如果想要详细地址(这个需要GPS终端进行实际定位,再转换火星坐标系进行记录)或者乡/镇/街道级别的地址信息,人工维护成本比较大,以笔者不算太长的地图服务接触时间来看,我们国家因城市化速度较快等原因,第四级的行政区划变更速度比较频繁。
6位精度数量:29 * 25 * 25* 25* 25 = 30408704
7位精度数量:29 * 25 * 25* 25* 25 * 25= 973078528
import java.awt.Polygon;
import java.awt.geom.Area;
判断是否包含:
判断是否相交:
tz
仅在新疆范围内,遍历tz开头的6位精度GeoHash值时,可以仅将新疆地区行政区划参与计算。建议脚本中计算完毕部分数据就写入本地或者数据库,脚本写的粗糙的话,跑计算时很有可能会OOM。118.797405,32.044227
各精度GeoHash值:精度 | GeoHash值 |
---|---|
1 | w |
2 | wt |
3 | wts |
4 | wtsq |
5 | wtsqr |
6 | wtsqr3 |
7 | wtsqr33 |
8 | wtsqr33x |
为了减少单个散列表中数据量过大问题,可以按照2位精度或者3位精度GeoHash值区分存储,具体策略可以根据具体场景自行调整。
以上查询过程很简单,复杂度O(1)即可拿到对应行政区划数据,不过1-4步骤的数据初始化过程需要人工介入次数较多;在部分边界点处理上,出现7位精度GeoHash仍然是相交而不是包含时,可以选择人工处理或上升到8位精度,按照大部分业务需求不建议上升至9位精度以上计算;如果采用人工处理,可以根据GeoHash覆盖点大小直接确定行政区划归属。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。