坐标边界查询工具:AreaCity-Query-Geometry
本工具核心功能:使用jts库
从省市区县乡镇边界数据
(AreaCity-JsSpider-StatsGov开源库)或geojson边界数据
文件中查找出和任意点、线、面有相交的矢量边界,内存占用低,性能优良。
GitHub地址:https://github.com/xiangyuecn/AreaCity-Query-Geometry
Gitee镜像库:https://gitee.com/xiangyuecn/AreaCity-Query-Geometry
主要特性:
- 查询一个坐标点对应的城市信息;
- 查询一条路径经过的所有城市;
- 查询一个矢量范围覆盖的所有城市;
- 查询一个城市或下一级所有边界数据(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图形界面:
控制台运行:
性能测试数据
测试数据源:AreaCity-JsSpider-StatsGov开源库2021.220321.220428版本下载的ok_geo.csv文件按省市区导出成不同的geojson文件。
测试采用开启多线程进行随机坐标点的查询(Test.java控制台5号菜单),测试机器配置:8核 2.20GHz CPU,SSD 硬盘。
测试一:Init_StoreInWkbsFile 内存占用很低(性能受IO限制)
数据源 | 文件大小 | 数据量 | 内存占用 | 7核QPS | 单核QPS | 单次查询耗时 |
---|---|---|---|---|---|---|
省市区三级 | 176MB | 3632条 | 41MB | 6212 | 887 | 1.13ms |
仅区级 | 107MB | 3208条 | 24MB | 13818 | 1974 | 0.51ms |
仅省级 | 20MB | 34条 | 4MB | 19832 | 2833 | 0.35ms |
Init_StoreInWkbsFile
:用加载数据到结构化数据文件的模式进行初始化,推荐使用本方法初始化,边界图形数据存入结构化数据文件中,内存占用很低,查询时会反复读取文件对应内容,查询性能消耗主要在IO上,IO性能极高问题不大。
测试二:Init_StoreInMemory 内存占用和json文件差不多大(性能豪放)
数据源 | 文件大小 | 数据量 | 内存占用 | 7核QPS | 单核QPS | 单次查询耗时 |
---|---|---|---|---|---|---|
省市区三级 | 176MB | 3632条 | 161MB | 77242 | 11034 | 0.091ms |
仅区级 | 107MB | 3208条 | 96MB | 121228 | 17318 | 0.058ms |
仅省级 | 20MB | 34条 | 18MB | 465940 | 66562 | 0.015ms |
Init_StoreInMemory
:用加载数据到内存的模式进行初始化,边界图形数据存入内存中,内存占用和json数据文件大小差不多大,查询性能极高;另外可通过设置AreaCityQuery.SetInitStoreInMemoryUseObject=true
来进一步提升性能,但内存占用会增大一倍多,省市区三级单核可达到 15000 QPS。
参考:数据库查询测试对比
数据源 | 数据量 | 查询坐标 | MySQL单次查询耗时 | SQL Server单次查询耗时 |
---|---|---|---|---|
省市区三级 | 3632条 | 深圳-龙华区 | 163ms | 25ms |
省市区三级 | 3632条 | 北京-房山区 | 173ms | 47ms |
数据库查询坐标点:
POINT(114.044346 22.691963)
深圳市 龙华区;POINT(116.055588 39.709385)
北京市 房山区(查询受内蒙envelope干扰影响性能)
查询坐标对应的省市区县乡镇名称
使用此工具进行坐标省市区县乡镇查询,先要准备一个省市区县乡镇的边界geojson数据文件。
数据中有哪一级的边界就能查询出哪一级的名称;比如你只有区级的数据,那么给一个坐标就能查询出此坐标所在的区县名称(需另外查找出上级的省市名称);如果有省市区三级的边界,那一次性就能查询出省市区三级的名称,如果有乡镇的边界,就能查询出乡镇这级的名称。
步骤一:准备好省市区县乡镇边界的geojson文件
如果你没有边界json文件,可以按以下步骤获得最新的全国省市区县乡镇边界数据json文件:
- 到开源库下载省市区边界数据
ok_geo.csv
文件: https://github.com/xiangyuecn/AreaCity-JsSpider-StatsGov (github可换成gitee); - 下载开源库里面的
AreaCity-Geo格式转换工具软件
; - 打开转换工具软件,选择
ok_geo.csv
,然后导出成geojson文件即可(默认会导出全国的省级数据,通过填写不同城市名前缀可以导出不同城市)。
如果你有多个geojson文件,需要合并成一个才行,可以通过上面下载的
AreaCity-Geo格式转换工具软件
中的高级功能
-GeoJSON多个文件合并成一个文件
来合并。
步骤二:运行测试程序进行初始化
双击 编译和运行Test.java直接测试.bat
运行测试控制台程序;根据控制台菜单命令进行初始化,有两种初始化方式,随便哪种都行:
Init_StoreInWkbsFile
:内存占用很低,但查询速度相对StoreInMemory慢很多,但也很快的,推荐用此方法初始化;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】