首页
 

通知公告

java解析本地.geoJson地理信息,根据经纬度找到所在区域(全程Chatgpt3.5交互写代码,附gpt交流记录)

来源:欧亿体育点击:时间:2024-01-18 11:03

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