利用GeoHash实现逆地理编码(经纬度坐标转换行政区划) |
您所在的位置:网站首页 › 获取经纬度及位置行政地址信息的软件是 › 利用GeoHash实现逆地理编码(经纬度坐标转换行政区划) |
目录
前言理解GeoHashGeoHash精度GeoHash特征GeoHash规律
逆地理编码实现逆地理编码的基本思路1.全国范围内6位精度GeoHash计算2.获取全国范围内区/县/三级市级别行政区划地址围栏点3.计算6位精度GeoHash块与区/县/三级市级别行政区划关联关系4.将GeoHash结果值与行政区划关联关系数据存储5.跟据坐标点的GeoHash值查询行政区划信息
结尾
前言
GeoHash是很多基于LBS(Location Based Services)服务不可绕过的解决方案之一,网上关于GeoHash的介绍和算法很多,资源也算比较丰富。这篇文章主要是介绍如何利用GeoHash或者进行逆地理编码(经纬度坐标转换行政区划)的实现。 以中文地址【江苏省南京市玄武区梅园新村街道总统府】为例,省级【江苏省】,市级【南京市】,区县级【玄武区】,街道乡镇级【梅园新村街道】,详细地址【总统府】。由于没有地图服务没有提供街道乡镇级的行政区划polygon数据(行政区划边界的坐标点集合),所以本文利用geoHash进行的逆地理编码的方式,只能到区县级。第四级和详细地址信息,变更相对会比较频繁,需要人工接入,维护成本比较大。 理解GeoHashGeoHash是按照固定的算法,将经纬度信息转换为Base32码表中的一串字符。具体的算法网上资源较多,不进行详细介绍。逻辑并不是非常复杂,大概逻辑如下: 按照经度范围[-180°,180°],纬度范围[-90°,90°]对目标经纬度进行计算;二分经度和纬度范围区间,分别判断经度和纬度,在右侧集合则为1,在左侧集合则为0;循环进行此计算。将所得经纬度1和0结果,经度在偶数位(从0位计算),纬度在奇数位进行拼接,5位二进制结果为一组,转换为十进制数后,再转换为对应Base32码表中数字,即得到对应GeoHash值。推荐一个github上GeoHash的实现: GeoHash算法实现 GeoHash精度GeoHash使用5位计算结果(左右区间)作为一个精度,例如wtw6kf共有6个Base32编码表的字母或数字,代表这个geoHash值的精度为6。 GeoHash特征 以一个坐标点118.797405,32.044227为例,该坐标点实际上是无数个精度更高(小数点后精确位到6位以后)的坐标点集合;将其放大理解,可以看作为一个二维矩形,此二维矩形的4角的坐标值分别应为: 坐标位置经度纬度西南点118.79740532.044227西北点118.79740532.044227999999…东北点118.797405999999…32.044227999999…东南点118.797405999999…32.044227 通过对坐标点的理解, GeoHash的值可以理解为,是无数个经纬度坐标的集合。通过多个经纬度坐标在不同精度的GeoHash计算后,都可以得到一个相同GeoHash的值的规律;可得知,GeoHash的覆盖面积会比经纬度单点的覆盖面积大,只有当GeoHash计算精度越大时,其覆盖面积越小,越近似于经纬度单点的覆盖面积。同类的思路,在我们高等数学中,使用微分计算不规则曲线图形面积时的方法,最终也是极限接近结果。以坐标点118.797405,32.044227(实际地理位置为:江苏省南京市总统府)的6位精度geoHash值wtsqr3为例,其二维矩形4角的坐标值分别为: 坐标位置经度纬度西南点118.79516601562532.0416259765625西北点118.79516601562532.047119140625东北点118.8061523437532.047119140625东南点118.8061523437532.0416259765625在地图上表现为: 可见该GeoHash块的覆盖面积已经将地理位置江苏省南京市总统府完全覆盖,并且也会覆盖更多其他地区。 GeoHash规律通过GeoHash的运算规则和全球经纬度范围,可以推导出不同精度的GeoHash块父子级规律:即精度为n的GeoHash会有32个精度为n+1的GeoHash块。例如当GeoHash值精度为1,全世界地图都会被32个GeoHash值覆盖。例如精度为1的GeoHash值w,其会覆盖我国大部分国土。 当GeoHash精度为2时,其展示效果如下: 逆地理编码指的是将经纬度坐标转换为具体的标准的行政区划信息,以高德逆地理编码接口为例,坐标点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终端进行实际定位,再转换火星坐标系进行记录)或者乡/镇/街道级别的地址信息,人工维护成本比较大,以笔者不算太长的地图服务接触时间来看,我们国家因城市化速度较快等原因,第四级的行政区划变更速度比较频繁。 实现逆地理编码的基本思路 1.全国范围内6位精度GeoHash计算 如果按照GeoHash的算法,需要使用全国的示例点进行计算得到结果,这个计算量和工作量非常巨大,基本上可以考虑放弃。按照上述的GeoHash规律,我们可以轻易的通过GeoHash奇偶数表获取全国所有的6位精度GeoHash值。首先确定全国2位精度GeoHash块(甚至3位)有多少,此数据可以直接通过画图来获取粗略结果,如下图所示:![]() 6位精度数量:29 * 25 * 25* 25* 25 = 30408704 7位精度数量:29 * 25 * 25* 25* 25 * 25= 973078528 6位精度的Geohash值可以麻烦大部分数据需求,7位精度Geohash值主要市为了解决区/县/三级市行政区划边界点与6位精度GeoHash块重合现象,7位精度的GeoHash值并不需要完全计算。 2.获取全国范围内区/县/三级市级别行政区划地址围栏点 首先感谢高德,行政区划地址围栏坐标点的数据需要从高德开放平台获取(高德开放平台地址围栏点比腾讯地图提供的要精准),申请一个高德的Key,批量拉去数据即可。注意编写脚本时建议写入文本文件或者直接写入数据库,数据量比较大。高德在线测试获取行政区划围栏点 拉取数据时,注意区/县/三级市级别行政区划名称有可能会重复,建议使用adcode字段进行区分。拉取得围栏点在地图中示例(江苏省南京市玄武区)如下,比较可靠:![]() 判断是否包含: 判断是否相交: 为了减少单个散列表中数据量过大问题,可以按照2位精度或者3位精度GeoHash值区分存储,具体策略可以根据具体场景自行调整。 5.跟据坐标点的GeoHash值查询行政区划信息 将目标坐标点进行7位精度GeoHash值计算根据GeoHash值获取对应散列表数据,查询获取结果。 结尾以上查询过程很简单,复杂度O(1)即可拿到对应行政区划数据,不过1-4步骤的数据初始化过程需要人工介入次数较多;在部分边界点处理上,出现7位精度GeoHash仍然是相交而不是包含时,可以选择人工处理或上升到8位精度,按照大部分业务需求不建议上升至9位精度以上计算;如果采用人工处理,可以根据GeoHash覆盖点大小直接确定行政区划归属。 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |