使用GeoTools解析shp檔案內容

香酥豆腐皮發表於2024-09-09

前言

記錄一下工作中使用GeoTools解析shp過程。

預設上傳shp檔案為zip格式檔案,shp壓縮包內容如下圖

image

程式碼流程

1.解壓zip檔案

// 解壓縮zip包
File shpFile = ShpParseUtil.unShapeZip(file.getInputStream(), tempDir);

2.解析shp檔案內容

parseShapeFile(shpFile);
public static void parseShapeFile(File file) throws Exception {
        Map<String, Object> map = new HashMap<>(1);
        map.put("url", file.toURI().toURL());
        DataStore dataStore = DataStoreFinder.getDataStore(map);
        //字元轉碼,防止中文亂碼
        ShapefileDataStore shpStore = (ShapefileDataStore) dataStore;
//        shpStore.setCharset(StandardCharsets.UTF_8);
        shpStore.setCharset(Charset.forName("GBK"));

        SimpleFeatureSource source = shpStore.getFeatureSource();
        SimpleFeatureType schema = source.getSchema();
        Query query = new Query(schema.getTypeName());
        FeatureCollection<SimpleFeatureType, SimpleFeature> collection = source.getFeatures(query);
        //獲取shp檔案內容
        try (FeatureIterator<SimpleFeature> features = collection.features()) {
            while (features.hasNext()) {
                SimpleFeature feature = features.next();
                String name = feature.getName().toString();
                System.out.println("名稱:" + name);

                //獲取座標系
                CoordinateReferenceSystem coordinateReferenceSystem = feature.getFeatureType().getCoordinateReferenceSystem();
                if (coordinateReferenceSystem != null) {
                    ReferenceIdentifier referenceIdentifier = coordinateReferenceSystem.getCoordinateSystem().getName();
                    String code = referenceIdentifier.getCode();
                    System.out.println("座標系:" + code);
                }
                //獲取shp檔案的屬性資訊
//                List<Object> attributes = feature.getAttributes();
                String geomType = feature.getFeatureType().getDescriptor("the_geom").getType().getName().toString();
                System.out.println("屬性值數量:" + feature.getValue().size());
                Map<String, Object> propertoryMap = feature.getValue().stream()
                        .filter(property -> !"the_geom".equals(property.getName().toString()))
                        .collect(Collectors.toMap(property -> property.getName().toString(), Property::getValue));
                for (Property property : feature.getValue()) {
                    String propertyName = property.getName().toString();
                    String typeName = property.getType().getName().toString();
                    System.out.println("屬性名:" + propertyName + "型別:" + typeName + " 屬性值:" + property.getValue());
                }
                Geometry geom = (Geometry) feature.getAttribute("the_geom");
                String geometryType = geom.getGeometryType();
				// 封裝為geojson格式
                String geoJson = convertToJson(geom,propertoryMap);
            }
        }
    }

工具類

public class ShpParseUtil {


    /**
     * 解壓shapefile壓縮包
     */
    public static File unShapeZip(InputStream inputStream,File tempDir){
        // 解壓shp檔案
        File unzipFiles = ZipUtil.unzip(inputStream, tempDir, null);
        Optional<File> optional = ListUtil.toList(unzipFiles.listFiles())
                .stream()
                .filter(file1 -> file1.getName().endsWith(".shp"))
                .findAny();
        if (!optional.isPresent()) {
            throw new JeecgBootException("不存在解壓後shp檔案");
        }
        return optional.get();
    }

    /**
     * 格式化向量資料為json格式
     * @param the_geom
     * @return
     */
    public static String convertToJson(Geometry the_geom, Map<String, Object> propertoryMap){
        String geomType = the_geom.getGeometryType();
        // 解析組裝座標Json陣列
        JSONArray geoJsonArray = getCoordinates(the_geom);

        // 構建 GeoJSON 物件
        JSONObject geoJsonFeature = new JSONObject();
        geoJsonFeature.put("type", "Feature");
        JSONObject geometry = new JSONObject();
        geometry.put("type", geomType);
        geometry.put("coordinates", geoJsonArray);
        geoJsonFeature.put("geometry", geometry);

        // 新增屬性
        geoJsonFeature.put("properties", propertoryMap);

        // 返回 GeoJSON 結果
        JSONObject geoJson = new JSONObject();
        geoJson.put("type", "FeatureCollection");
        geoJson.put("features", new JSONArray().fluentAdd(geoJsonFeature));
        return geoJson.toString();
    }

    /**
     *  解析不同型別座標返回JSON陣列
     */
    private static JSONArray getCoordinates(Geometry geometry) {
        if (geometry instanceof Point) {
            Point point = (Point) geometry;
            JSONArray geoJsonPoints = new JSONArray();
            geoJsonPoints.add(point.getX());
            geoJsonPoints.add(point.getY());
            return geoJsonPoints;
        } else if (geometry instanceof LineString) {
            LineString lineString = (LineString) geometry;
            org.locationtech.jts.geom.Coordinate[] coordinates = lineString.getCoordinates();
            JSONArray geoJsonLineString = new JSONArray();
            for (Coordinate coordinate : coordinates) {
                geoJsonLineString.add(coordinate.getX());
                geoJsonLineString.add(coordinate.getY());
            }
            return geoJsonLineString;
        } else if (geometry instanceof Polygon) {
            Polygon polygon = (Polygon) geometry;
            return getPolygonCoordinates(polygon);
        } else if (geometry instanceof MultiPoint) {
            MultiPoint multiPoint = (MultiPoint) geometry;
            JSONArray coords = new JSONArray();
            for (int i = 0; i < multiPoint.getNumGeometries(); i++) {
                Point point = (Point) multiPoint.getGeometryN(i);
                coords.add(new JSONArray().fluentAdd(point.getX()).fluentAdd(point.getY()));
            }
            return coords;
        } else if (geometry instanceof MultiLineString) {
            MultiLineString multiLineString = (MultiLineString) geometry;
            JSONArray coords = new JSONArray();
            for (int i = 0; i < multiLineString.getNumGeometries(); i++) {
                coords.add(getCoordinates(multiLineString.getGeometryN(i)));
            }
            return coords;
        } else if (geometry instanceof MultiPolygon) {
            MultiPolygon multiPolygon = (MultiPolygon) geometry;
            JSONArray coords = new JSONArray();
            for (int i = 0; i < multiPolygon.getNumGeometries(); i++) {
                coords.add(getPolygonCoordinates((Polygon) multiPolygon.getGeometryN(i)));
            }
            return coords;
        } else {
            return null;
        }
    }

    // 解析獲取多邊形的座標陣列
    private static JSONArray getPolygonCoordinates(Polygon polygon) {
        JSONArray coords = new JSONArray();
        // 多邊形外環
        JSONArray exteriorRing = new JSONArray();
        for (int i = 0; i < polygon.getExteriorRing().getNumPoints(); i++) {
            exteriorRing.fluentAdd(new JSONArray().fluentAdd(polygon.getExteriorRing().getCoordinateN(i).x)
                    .fluentAdd(polygon.getExteriorRing().getCoordinateN(i).y));
        }
        coords.add(exteriorRing);
        // 多邊形內環
        for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
            JSONArray interiorRing = new JSONArray();
            for (int j = 0; j < polygon.getInteriorRingN(i).getNumPoints(); j++) {
                interiorRing.fluentAdd(new JSONArray().fluentAdd(polygon.getInteriorRingN(i).getCoordinateN(j).x)
                        .fluentAdd(polygon.getInteriorRingN(i).getCoordinateN(j).y));
            }
            coords.add(interiorRing);
        }
        return coords;
    }
}

相關文章