1:起因
对于一些因为安全等级而不连通外网的服务器,客户提出了根据本地.geoJson文件获取区域地理信息,根据用户提供的经纬度x,y坐标,找到这个点所在的区域
2:思路
根据.geoJson文件中连续的点连线,画框构建多边形,再判断这个点再哪个多边形内
3:.geoJson文件简单了解
以下是chatgpt3.5给出的解释:
注意:根据我的理解,此处gpt还漏掉了一种类型MultiPolygon,MultiPolygon表示的是多个多边形,而Polygon表示的是单个多边形:
4:下载测试.geoJson文件
先准备一下测试数据:
免费下载实时更新的geoJson数据、行政区划边界数据、区划边界坐标集合__HashTang (hxkj.vip)https://geojson.hxkj.vip/打开上述连接,选择广东省,下载文件,我这里下载的文件名为440000.geoJson,路径直接放在D盘
5:向Chatgpt提需求
方便复制,不截图了,以下是我的提问:
1:解析.geoJson文件
我:从.geoJson文件中提取Polygon和MultiPolygon类型的coordinates经纬度数据,使用这些数据构建Coordinate多边形对象,存在一个map中,其中map的key为,geoJson文件中properties下的code,value为Coordinate对象
2:构建多边形并查找
再写一个函数,传入x,y经纬度坐标构建一个点,可以从上面构建的map中找到其中这个点所在的多边形
6:代码(正片开始)
gpt直接生成的代码还是有点问题的,具体的调教过程可以看最后的聊天记录连接,这里直接附上我修改后可以直接运行的代码:
先引入依赖
org.geotools gt-main 25.0 org.geotools gt-shapefile 25.0 org.locationtech.jts jts-core 1.16.1
下载这几个依赖需要添加他们家的仓库
osgeo OSGeo Release Repository https://repo.osgeo.org/repository/release/ false true
package com.gdunicom.cloud.system.geo;import com.fasterxml.jackson.databind.JsonNode;import com.fasterxml.jackson.databind.ObjectMapper;import org.locationtech.jts.algorithm.PointLocator;import org.locationtech.jts.geom.*;import java.io.File;import java.io.IOException;import java.util.*;public class GeoJSONParser { // 创建Map用于存储Coordinate多边形对象 static Map polygonsMap = new HashMap<>(); public static void main(String[] args) { // 创建ObjectMapper对象 ObjectMapper objectMapper = new ObjectMapper(); try { // 读取.geojson文件并解析为JsonNode对象 File file = new File("D:\\440000.geoJson"); JsonNode rootNode = objectMapper.readTree(file); // 获取FeatureCollection下的features数组 JsonNode featuresNode = rootNode.get("features"); // 遍历features数组 for (JsonNode featureNode : featuresNode) { // 获取geometry字段 JsonNode geometryNode = featureNode.get("geometry"); // 获取类型字段 String type = geometryNode.get("type").asText(); // 获取坐标字段 JsonNode coordinatesNode = geometryNode.get("coordinates"); // 获取properties字段 JsonNode propertiesNode = featureNode.get("properties"); // 获取code字段 String code = propertiesNode.get("adcode").asText(); // 根据类型进行相应处理 if (type.equals("Polygon")) { // 处理Polygon类型 Coordinate[] coordinates = parseCoordinates(coordinatesNode); polygonsMap.put(code, coordinates); } else if (type.equals("MultiPolygon")) { // 处理MultiPolygon类型 for (JsonNode polygonNode : coordinatesNode) { Coordinate[] coordinates = parseCoordinates(polygonNode); polygonsMap.put(code, coordinates); } } }// // 输出结果// for (Map.Entry entry : polygonsMap.entrySet()) {// String code = entry.getKey();// Coordinate[] coordinates = entry.getValue();// System.out.println("Code: " + code);// for (Coordinate coordinate : coordinates) {// System.out.println("Coordinate: " + coordinate.getX() + ", " + coordinate.getY());// }// System.out.println();// } System.out.println("size:"+polygonsMap.size()); //我的位置,我在广州 double longitude = 113.374172; // 经度 double latitude = 23.064884; // 纬度 String containingPolygon = findContainingPolygon(longitude, latitude); System.out.println("Containing Polygon: " + containingPolygon); } catch (IOException e) { e.printStackTrace(); } } public static Coordinate[] parseCoordinates(JsonNode coordinatesNode) { if (!coordinatesNode.isArray()) { return null; // 非法的 JSON 数组 } List coordinateList = new ArrayList<>(); Iterator iterator = coordinatesNode.elements(); while (iterator.hasNext()) { JsonNode coordinateNode = iterator.next(); if (coordinateNode.isArray() && coordinateNode.size() == 2) { double x = coordinateNode.get(0).asDouble(); double y = coordinateNode.get(1).asDouble(); Coordinate coordinate = new Coordinate(x, y); coordinateList.add(coordinate); }else if(coordinateNode.isArray() && coordinateNode.size() > 2){ Iterator elements = coordinateNode.elements(); while (elements.hasNext()) { JsonNode next = elements.next(); if (next.isArray() && next.size() == 2) { double x = next.get(0).asDouble(); double y = next.get(1).asDouble(); Coordinate coordinate = new Coordinate(x, y); coordinateList.add(coordinate); } } } else { return null; // 非法的坐标格式 } } return coordinateList.toArray(new Coordinate[0]); } public static String findContainingPolygon(double longitude, double latitude) { // 创建GeometryFactory GeometryFactory geometryFactory = new GeometryFactory(); // 创建点坐标 Coordinate pointCoordinate = new Coordinate(longitude, latitude); // 遍历多边形Map,查找包含点的多边形 for (Map.Entry entry : polygonsMap.entrySet()) { String code = entry.getKey(); Coordinate[] coordinates = entry.getValue(); // 创建MultiPolygon对象 MultiPolygon multiPolygon = geometryFactory.createMultiPolygon(new Polygon[] { geometryFactory.createPolygon(coordinates) }); // 使用PointLocator检查点是否在多边形内 PointLocator pointLocator = new PointLocator(); int location = pointLocator.locate(pointCoordinate, multiPolygon); if (location != Location.EXTERIOR) { return code; } } return null; // 未找到包含点的多边形 }}
6:验证
我当前在广州,看看我的坐标 23.064884,113.374172
运行结果:
size为这个这个map的大小,刚好对应广东省21个市,返回值为区域代码440100,查找一下源文件中的信息,就是广州市,完结撒花
7:聊天记录
最后附上交流记录(需要魔法):
https://chat.openai.com/share/e57817bf-ae6b-45e9-8074-25b7cd52b2d4
来源地址:https://blog.csdn.net/weixin_44123956/article/details/131302964