从区划边界geojson中查询经纬度坐标对应的省市区县乡镇名称,开源Java工具,内存占用低、高性能

382 阅读6分钟

坐标边界查询工具:AreaCity-Query-Geometry

本工具核心功能:使用jts库省市区县乡镇边界数据AreaCity-JsSpider-StatsGov开源库)或geojson边界数据文件中查找出和任意点、线、面有相交的矢量边界,内存占用低,性能优良。

GitHub地址:github.com/xiangyuecn/…

Gitee镜像库:gitee.com/xiangyuecn/…

主要特性:

  • 查询一个坐标点对应的城市信息;
  • 查询一条路径经过的所有城市;
  • 查询一个矢量范围覆盖的所有城市;
  • 查询一个城市或下一级所有边界数据(WKT格式);
  • 支持通过HTTP API服务进行查询调用;
  • 支持通过Java代码进行查询调用;
  • 源码简单,包括测试bat脚本共5个文件,无需IDE即可修改和运行,copy即用。

可以只copy AreaCityQuery.java 文件到项目中使用,项目中引入jts库,就能使用 AreaCityQuery 中的所有查找功能了。也可以clone整个项目代码双击 编译和运行Test.java直接测试.bat 即可直接运行测试。

API和图形界面:此工具自带了一个HTTP API服务,运行测试然后通过菜单启动此服务,然后就可以直接在浏览器上访问这些接口;此API接口可以直接在 ECharts Map四级下钻在线测试和预览 页面的自定义数据源中进行调用测试,页面会立即绘制查询出来的边界图形。

效果图:

HTTP API图形界面: HTTP API图形界面

控制台运行: 控制台运行

性能测试数据

测试数据源:AreaCity-JsSpider-StatsGov开源库2021.220321.220428版本下载的ok_geo.csv文件按省市区导出成不同的geojson文件。

测试采用开启多线程进行随机坐标点的查询(Test.java控制台5号菜单),测试机器配置:8核 2.20GHz CPU,SSD 硬盘。

测试一:Init_StoreInWkbsFile 内存占用很低(性能受IO限制)

数据源文件大小数据量内存占用7核QPS单核QPS单次查询耗时
省市区三级176MB3632条41MB62128871.13ms
仅区级107MB3208条24MB1381819740.51ms
仅省级20MB34条4MB1983228330.35ms

Init_StoreInWkbsFile:用加载数据到结构化数据文件的模式进行初始化,推荐使用本方法初始化,边界图形数据存入结构化数据文件中,内存占用很低,查询时会反复读取文件对应内容,查询性能消耗主要在IO上,IO性能极高问题不大。

测试二:Init_StoreInMemory 内存占用和json文件差不多大(性能豪放)

数据源文件大小数据量内存占用7核QPS单核QPS单次查询耗时
省市区三级176MB3632条161MB77242110340.091ms
仅区级107MB3208条96MB121228173180.058ms
仅省级20MB34条18MB465940665620.015ms

Init_StoreInMemory:用加载数据到内存的模式进行初始化,边界图形数据存入内存中,内存占用和json数据文件大小差不多大,查询性能极高;另外可通过设置 AreaCityQuery.SetInitStoreInMemoryUseObject=true 来进一步提升性能,但内存占用会增大一倍多,省市区三级单核可达到 15000 QPS。

参考:数据库查询测试对比

数据源数据量查询坐标MySQL单次查询耗时SQL Server单次查询耗时
省市区三级3632条深圳-龙华区163ms25ms
省市区三级3632条北京-房山区173ms47ms

数据库查询坐标点:POINT(114.044346 22.691963) 深圳市 龙华区;POINT(116.055588 39.709385) 北京市 房山区(查询受内蒙envelope干扰影响性能)

查询坐标对应的省市区县乡镇名称

使用此工具进行坐标省市区县乡镇查询,先要准备一个省市区县乡镇的边界geojson数据文件。

数据中有哪一级的边界就能查询出哪一级的名称;比如你只有区级的数据,那么给一个坐标就能查询出此坐标所在的区县名称(需另外查找出上级的省市名称);如果有省市区三级的边界,那一次性就能查询出省市区三级的名称,如果有乡镇的边界,就能查询出乡镇这级的名称。

步骤一:准备好省市区县乡镇边界的geojson文件

如果你没有边界json文件,可以按以下步骤获得最新的全国省市区县乡镇边界数据json文件:

  1. 到开源库下载省市区边界数据ok_geo.csv文件: github.com/xiangyuecn/… (github可换成gitee);
  2. 下载开源库里面的AreaCity-Geo格式转换工具软件
  3. 打开转换工具软件,选择ok_geo.csv,然后导出成geojson文件即可(默认会导出全国的省级数据,通过填写不同城市名前缀可以导出不同城市)。

如果你有多个geojson文件,需要合并成一个才行,可以通过上面下载的 AreaCity-Geo格式转换工具软件 中的 高级功能-GeoJSON多个文件合并成一个文件 来合并。

步骤二:运行测试程序进行初始化

双击 编译和运行Test.java直接测试.bat 运行测试控制台程序;根据控制台菜单命令进行初始化,有两种初始化方式,随便哪种都行:

  1. Init_StoreInWkbsFile:内存占用很低,但查询速度相对StoreInMemory慢很多,但也很快的,推荐用此方法初始化;
  2. Init_StoreInMemory:内存占用大一点,但查询速度非常快。

选择了初始方式后会要求填写geojson文件路径,填写上一步准备好的json文件完整路径即可;或者直接将json文件放到程序根目录,会自动初始化。

步骤三:查询坐标获得省市区名称

初始化完成后,所有的菜单都可以使用了,可以直接在控制台中使用对应的菜单进入菜单查询功能,然后输入坐标查询即可。

建议使用HTTP API来进行查询,在菜单中启动好HTTP服务后,就能通过网址访问查询接口,或者直接使用在线的可视化界面进行查询操作:

坐标查询可视化效果

附:通过Java代码进行查询

//先初始化,全局只会初始化一次,每次查询前都调用即可(查询会在初始化完成后进行),两种初始化方式根据自己业务情况二选一
//首次初始化会从.json或.geojson文件中读取边界图形数据,速度比较慢,会自动生成.wkbs结尾的结构化文件,下次初始化就很快了
AreaCityQuery.Init_StoreInWkbsFile("geojson文件路径", "geojson文件路径.wkbs", true);
//AreaCityQuery.Init_StoreInMemory("geojson文件路径", "geojson文件路径.wkbs", true);

//AreaCityQuery.OnInitProgress=(initInfo)->{ ... } //初始化过程中的回调,可以绑定一个函数,接收初始化进度信息

//查询包含一个坐标点的所有边界图形的属性数据,可通过res参数让查询额外返回wkt格式边界数据
QueryResult res1=AreaCityQuery.QueryPoint(114.044346, 22.691963, null, null);

//查询和一个图形(点、线、面)有交点的所有边界图形的属性数据,可通过res参数让查询额外返回wkt格式边界数据
Geometry geom=new WKTReader(AreaCityQuery.Factory).read("LINESTRING(114.233963 30.546038, 114.468109 30.544264)");
QueryResult res2=AreaCityQuery.QueryGeometry(geom, null, null);

//读取省市区的边界数据wkt格式,这个例子会筛选出武汉市所有区县
QueryResult res3=AreaCityQuery.ReadWKT_FromWkbsFile("wkt_polygon", null, (prop)->{return prop.contains("武汉市 ");}, null);


System.out.println(res1+"\n"+res2+"\n"+res3);

【END】