在LBS利用中,依据坐标来解析取得对应是哪个城市是一个很常见的性能,比方App外面通过手机定位主动抉择城市;本文介绍的是通过本人建的数据库,利用SQL空间查问来进行坐标解析失去对应的省市区,绝大部分反对空间数据类型(Spatial)的数据库均反对,包含但不限于:MySQLSQL ServerOraclePostgreSQL等;开发语言不限,只有能进行数据库查问就都反对,用JavaPythonPHPC#均能很简略的实现。

省市区边界数据在线预览、下载:https://xiangyuecn.gitee.io/areacity-jsspider-statsgov/
GitHub地址:https://github.com/xiangyuecn/AreaCity-JsSpider-StatsGov

通过坐标来获取地址:百度地图提供的接口叫 “地址逆解析”,高德地图提供的接口叫 “天文逆编码”,它们开放平台均提供了前后端接口,发个http申请就能够拿到数据,相干的接口调用请自行浏览平台开发文档,应用起来很不便。

当然这篇文章不会去介绍怎么搞街道门牌号这些残缺地址,也不讲怎么样调用人家的接口,只介绍坐标对应的省市区名称的获取,自建数据库写SQL进行空间查问,齐全本人实现,比调开放平台接口绝对会简单些。

因为全国区县每年都会有比拟多的变更,所以省市区边界数据须要常常去同步保护,好在这下面这个开源库有在继续的长期保护,新数据公布后更新绝对容易很多。因为开源库更新保护数据比拟及时,所以只有开源库没有被敞开,本文介绍的提取办法就始终实用; 比那些上传到下载平台就万年不更新的数据优良很多。

查问成果展现:

从这里轻易拿的一个坐标:

直观的成果如上图,在百度地图外面轻易点选一下(或App定位取得的坐标)失去一个坐标,而后到数据库外面利用空间查问SQL就能查问到坐标所在的城市。

步骤一、下载省市区边界数据

到开源库外面下载最新的 ok_geo.csv.7z 文件(13M大小,解压130M+),点此下载。下载好后解压失去 ok_geo.csv,此文件内蕴含了最新全国所有的省市区县坐标边界矢量数据。

注:这个文件只蕴含三级(省市区)数据不含第四级(乡镇街道),如需乡镇坐标边界数据,能够请点此下载 ok_geo4_*.csv 文件(90MB+压缩包 导出后300M+)。

步骤二、解析CSV文件导入数据库

下载好的文件 ok_geo.csv 是纯文本文件,能够自行编写脚本进行解析,而后导进数据库中,自行解析解决比较复杂,请参考开源库内文档;开源库内提供了一个格局转换工具,此工具反对将CSV数据导入数据库,因而咱们间接在下载数据时顺带把工具下载好,点此下载。

此转换工具除了反对将 ok_geo.csv 导入数据库外,还反对导出:sqlshpgeojson,和坐标系转换;还可执行自定义 JavaScript 脚本,扩大出丰盛性能;软件是Windows版,如果须要在MacOs中用,能够用虚拟机。

转换工具执行导入数据库操作:

  1. 点击 抉择ok_geo.csv文件 按钮,抉择解压进去的CSV文件;
  2. 数据库设置中抉择要导入的数据库类型,这里选的是MySQL,再填写数据库连贯,包含:端口、数据库名称、账号密码;
  3. 点击导入数据库按钮,期待一会,大概3分钟左右,所有数据就都导入到了数据库按明天日期新建的表外面。

注:csv文件内的边界数据默认是高德地图GCJ-02火星坐标系,如果须要其余坐标系,比方百度的BD-09或GPS的WGS-84,能够通过高级脚本中的坐标系转换插件进行转换,抉择好对应的插件后,点击利用就能够了,在导入数据库时会主动进行坐标系转换。

注:这个工具限度每次操作只可导出一个城市和它的下一级数据,导出大量数据还是很轻松的,所以咱们能够多操作几次,将须要的城市数据全副导入数据库;比方要深圳的所有区县数据:第一遍导入全国所有的省,第二遍在城市名前缀中填写广东省 (结尾带一个空格)导入广东所有的市,第三遍在城市名前缀中填写广东省 深圳市 (结尾带一个空格)导入深圳所有的区。如果在密钥输入框中填写了密钥,此工具就没有这些限度了,开源库外面会不定期发放密钥搞福利,点击一次操作即可导出全国所有的省市区三级数据。

表构造和空间字段(MySQL版,其余数据库相似):

CREATE TABLE Areacity_Geo_20220216 (  id int NOT NULL, --城市id  pid int NOT NULL, --下级城市id  deep int NOT NULL, --层级:0省、1市、2区  name varchar(250) NOT NULL, --城市名称:`深圳市`  ext_path varchar(255) NOT NULL, --省市区三级残缺名称:广东省 深圳市 罗湖区  geo geometry NOT NULL, --城市核心坐标,空间数据格式                --,ST_AsText转成WKT文本后:`POINT EMPTY`、`POINT (123.456 34.567)`  polygon geometry NOT NULL --城市边界范畴图形,空间数据格式                --,ST_AsText转成WKT文本后:`POLYGON EMPTY`、`POLYGON ((123.456 34.567,...))`、`MULTIPOLYGON (((123.456 34.567,...)),...)`)对空间字段的查问,须要用`ST_AsText()`办法能力查问出字符串文本(WKT: Well Known Text),否则查问进去的是二进制数据-- MySQL版:SELECT id, name, ST_AsText(geo) AS geo, ST_AsText(polygon) AS polygon FROM 表名-- SQL Server版:SELECT id, name, geo.STAsText() AS geo, polygon.STAsText() AS polygon FROM 表名

步骤三、在程序中依据坐标解析取得城市

省市区边界导入到了数据库后,咱们就能够在在 JavaPythonPHPC# 等程序中对数据库进行查问,通过SQL的空间计算函数ST_Intersects来查问一个坐标在哪些边界范畴内,就能失去对应的省市区信息了。

空间查问SQL语句

比方要查问坐标`lng:113.929976 lat:22.529497`是在哪个城市-- MySQL版:SELECT id,deep,name FROM 表名 WHERE ST_Intersects(polygon, ST_GeomFromText('POINT(113.929976 22.529497)',0))=1-- SQL Server版:SELECT id,deep,name FROM 表名 WHERE polygon.STIntersects(geometry::STGeomFromText('POINT(113.929976 22.529497)',0))=1

查问后果例子(MySQL版,其余数据库相似)

程序代码连贯上数据库,通过以上SQL查问到数据库数据后,就取得了省市区信息,能够通过deep字段来辨别哪条数据是省(deep=0)、市(deep=1)、区县(deep=2)

通过以上三步,咱们就齐全是本人实现了依据经纬度坐标来解析取得对应是哪个城市这一性能。

【END】