可以做到:
通过经纬度获取到该经纬度的所在区县的区划代码以及区县名称.
限制:
无法获取详细地址信息.

第一步 获取省市区县乡镇边界数据

前往开源库https://github.com/xiangyuecn/AreaCity-JsSpider-StatsGov 下载
【边界三级】省市区 坐标和边界 数据 ok_geo.csv.7z
解压后得到ok_geo.csv
前往AreaCity Geo格式转换工具官网下载转换工具,
目前链接为:https://pan.baidu.com/s/14LsvF_PuPOEiOXgGAWI20w?pwd=b6ct#list/path=%2F
下载AreaCity-Geo格式转换工具-1.3.230403-已带GDAL组件.7z
解压后打开AreaCity-Geo-Transform.exe
点击左上角选择ok_geo.csv文件 选择上一步得到的ok_geo.csv
点击转为geojson文件,即可在ok_geo文件所在文件夹生成两个GeoJSON-Polygon-ok_geo-xxx.json文件
大小较大文件是我们需要的.
注意:默认导出为高德GCJ-02火星坐标系,如果需要导出其他坐标系,点击高级,在内置脚本处选择转换为xx坐标系,然后点击应用,再次点击转为geojson文件就可以.
如果没有密钥只能转换一个城市下的区划,在城市名前缀处填写要导出的城市名,有密钥把密钥填在密钥处,城市名前缀置空即可,一个临时密钥10元,不贵.

第二步 启动应用测试接口

前往https://github.com/xiangyuecn/AreaCity-Query-Geometry/releases 下载Source code
(zip) 解压后得到AreaCity-Query-Geometry-main,把上方生成的GeoJSON-Polygon-ok_geo-xxx.json文件放入该目录,启动该目录的编译和运行Test.java直接测试.bat.
启动完成后,输入2选择
2. 初始化:调用 Init_StoreInMemory -内存占用和json文件差不多大(性能豪放)
在 在当前目录内发现数据文件,请选择要从哪个文件初始化,请输入文件序号:
选择我们放入的GeoJSON-Polygon-ok_geo-xxx.json文件.等待读取完成.会在目录下生成.json.wkbs的文件
输入6. 查询: QueryPoint 查找坐标点所在省市区乡镇
然后输入经纬度即可测试.

附:.wkbs文件说明
初始化时如果提供了saveWkbsFilePath参数(为.wkbs结构化文件的路径):
如果此文件已存在,将自动从此文件进行初始化,初始化速度会很快(文件只读不写,可以不提供geojson文件);
如果此文件不存在,将从.json或.geojson文件中读取边界图形数据,并生成此文件,速度比较慢(文件读写)。
因此可以先在本地用json文件进行初始化,自动生成一个wkbs文件,然后copy wkbs文件到别的地方使用(比如服务器、只读环境中)。

第三步 依赖添加到项目

将此依赖添加至项目

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.locationtech.jts/jts-core -->
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>1.18.2</version>
</dependency>

并将目录下的AreaCityQuery.java文件copy到项目中.
启动项目后调用Init方法,传入.json.wkbs文件的路径,(直接传json文件的路径可能有bug无法初始化)
然后调用此方法查询区划,具体返回值请看源码注释

1
AreaCityQuery.QueryResult queryResult = AreaCityQuery.QueryPoint(longitude, latitude, null, null);

附:查询一个坐标对应城市的结果判定
比如查询省市区三级,查询结果在res.Result中:
请不要假定查询结果的数量,比如:坐标刚好在边界上可能会查询出多个省市区,结果中将超过3条数据;
请不要假定查询结果顺序,结果中省市区顺序是乱序的,需要判断每条结果是省市区哪一级,通过判断结果中的deep=0省|1市|2区来区分这条结果是哪个级别;
请检查判定查询结果中的数据是否完全符合查询的城市级别:省市区三级结果中必须且仅有3条数据,并且这3条数据省市区三级都有,否则一律可判定为查询无效。

样例代码

项目启动自动Init

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @author rui
*/
@Component
@Slf4j
public class InitApplicationRunner implements ApplicationRunner {
@Value("${areacity-query.init.geoJsonFilePath}")
private String geoJsonFilePath;
/**
* Callback used to run the bean.
*
* @param args incoming application arguments
*/
@Override
public void run(ApplicationArguments args) {
log.info("初始化查询服务开始!从:{}文件开始进行初始化",geoJsonFilePath);
AreaCityQuery.Init_StoreInMemory(geoJsonFilePath,null,true);
AreaCityQuery.QueryInitInfo queryInitInfo = AreaCityQuery.GetInitInfo();
log.info("初始化查询服务信息为:{}",queryInitInfo);
}
}

接口通过经纬度查询所在地区 仅返回一个匹配的区级实体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 通过经纬度查询所在地区(百度坐标系) 仅返回一个匹配的区级实体
*
* @param longitude 经度
* @param latitude 纬度
* @return
*/
@GetMapping("/queryPointV2")
@SneakyThrows
public AreaCityQueryResVO queryPointV2(@RequestParam Double longitude, @RequestParam Double latitude) {
AreaCityQuery.QueryResult queryResult = AreaCityQuery.QueryPoint(longitude, latitude, null, null);
ArrayList<String> result = queryResult.Result;
Map<String, AreaCityQueryResVO> areaCityQueryResVOMap =
result.stream()
.map(e -> JSON.parseObject(e, AreaCityQueryResVO.class))
.collect(Collectors.toMap(AreaCityQueryResVO::getDeep, e -> e));
// 请检查判定查询结果中的数据是否完全符合查询的城市级别:省市区三级结果中必须且仅有3条数据,并且这3条数据省市区三级都有,否则一律可判定为查询无效。
if (result.size() == AreaCityQueryConstant.CORRECTSIZE && areaCityQueryResVOMap.containsKey(AreaCityQueryConstant.DEEP_PROVINCE)
&& areaCityQueryResVOMap.containsKey(AreaCityQueryConstant.DEEP_CITY)
&& areaCityQueryResVOMap.containsKey(AreaCityQueryConstant.DEEP_AREA)) {
return areaCityQueryResVOMap.get(AreaCityQueryConstant.DEEP_AREA);
}else {
log.warn("参数经纬度为:{},{},返回区划异常!", longitude, latitude);
return null;
}
}