package com.yj.earth.common.util; import org.gdal.gdal.gdal; import org.gdal.ogr.*; import org.gdal.osr.CoordinateTransformation; import org.gdal.osr.SpatialReference; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.gdal.ogr.ogrConstants.*; public class GdalJsonConverter { static { // 动态获取项目根目录下的lib文件夹路径 String projectRoot = System.getProperty("user.dir"); // 拼接lib目录路径(项目根目录/lib) String projLibPath = projectRoot + File.separator + "lib"; // 设置PROJ库路径(指向包含proj.db的lib目录) gdal.SetConfigOption("PROJ_LIB", projLibPath); gdal.AllRegister(); } /** * 将地理数据文件转换为指定结构的JSON */ public static String convertToJson(String filePath) { return convertToJson(filePath, ""); } /** * 将地理数据文件转换为指定结构的JSON */ private static String convertToJson(String filePath, String targetCrs) { try { // 打开数据源 DataSource dataSource = ogr.Open(filePath, 0); if (dataSource == null) { throw new RuntimeException("无法打开文件: " + filePath); } JSONObject result = new JSONObject(); JSONArray listArray = new JSONArray(); // 获取所有图层 int layerCount = dataSource.GetLayerCount(); for (int i = 0; i < layerCount; i++) { Layer layer = dataSource.GetLayer(i); String layerName = layer.GetName(); JSONObject featureCollection = createFeatureCollection(layer, layerName, targetCrs); if (featureCollection != null) { listArray.put(featureCollection); } } result.put("list", listArray); dataSource.delete(); return result.toString(2); } catch (Exception e) { throw new RuntimeException("转换失败: " + e.getMessage(), e); } } /** * 创建 FeatureCollection 对象 */ private static JSONObject createFeatureCollection(Layer layer, String layerName, String targetCrs) throws JSONException { JSONObject featureCollection = new JSONObject(); featureCollection.put("type", "FeatureCollection"); featureCollection.put("name", layerName); // 获取源坐标系 String crsSrc = getLayerCrs(layer); featureCollection.put("crs_src", crsSrc != null ? crsSrc : ""); // 设置目标坐标系 featureCollection.put("crs_dst", targetCrs != null ? targetCrs : ""); JSONArray featuresArray = new JSONArray(); Feature feature; // 重置图层读取位置 layer.ResetReading(); // 获取图层定义、用于字段信息 FeatureDefn layerDefn = layer.GetLayerDefn(); // 如果需要坐标转换、创建坐标转换对象 SpatialReference sourceSrs = layer.GetSpatialRef(); SpatialReference targetSrs = null; CoordinateTransformation coordTrans = null; if (targetCrs != null && !targetCrs.isEmpty() && sourceSrs != null) { try { targetSrs = new SpatialReference(); if (targetCrs.startsWith("EPSG:")) { int epsgCode = Integer.parseInt(targetCrs.substring(5)); targetSrs.ImportFromEPSG(epsgCode); } else { targetSrs.ImportFromProj4(targetCrs); } coordTrans = new CoordinateTransformation(sourceSrs, targetSrs); } catch (Exception e) { System.err.println("坐标转换初始化失败: " + e.getMessage()); } } while ((feature = layer.GetNextFeature()) != null) { JSONObject featureObj = createFeature(feature, layerDefn, coordTrans, targetSrs != null); if (featureObj != null) { featuresArray.put(featureObj); } feature.delete(); } // 清理资源 if (coordTrans != null) { coordTrans.delete(); } if (targetSrs != null) { targetSrs.delete(); } featureCollection.put("features", featuresArray); return featureCollection; } /** * 获取图层的坐标系信息 */ private static String getLayerCrs(Layer layer) { try { SpatialReference srs = layer.GetSpatialRef(); if (srs != null) { // 优先尝试获取PROJ4字符串 String proj4 = srs.ExportToProj4(); if (proj4 != null && !proj4.trim().isEmpty()) { return proj4.trim(); } // 如果PROJ4为空、尝试获取WKT String wkt = srs.ExportToWkt(); if (wkt != null && !wkt.trim().isEmpty()) { return wkt.trim(); } // 最后尝试获取EPSG代码 String authorityCode = srs.GetAuthorityCode(null); String authorityName = srs.GetAuthorityName(null); if (authorityName != null && authorityCode != null) { return authorityName + ":" + authorityCode; } } } catch (Exception e) { System.err.println("获取坐标系信息失败: " + e.getMessage()); } return null; } /** * 创建单个Feature对象 */ private static JSONObject createFeature(Feature feature, FeatureDefn layerDefn, CoordinateTransformation coordTrans, boolean transformCoords) throws JSONException { JSONObject featureObj = new JSONObject(); featureObj.put("type", "Feature"); // 处理属性字段 JSONObject properties = new JSONObject(); int fieldCount = layerDefn.GetFieldCount(); for (int i = 0; i < fieldCount; i++) { FieldDefn fieldDefn = layerDefn.GetFieldDefn(i); String fieldName = fieldDefn.GetName(); Object fieldValue = getFieldValue(feature, fieldDefn, i); if (fieldValue != null) { properties.put(fieldName, fieldValue); } } featureObj.put("properties", properties); // 处理几何图形 Geometry geometry = feature.GetGeometryRef(); if (geometry != null && !geometry.IsEmpty()) { Geometry geomToUse = geometry; // 如果需要坐标转换 if (transformCoords && coordTrans != null) { try { Geometry transformedGeom = geometry.Clone(); transformedGeom.Transform(coordTrans); geomToUse = transformedGeom; } catch (Exception e) { System.err.println("坐标转换失败: " + e.getMessage()); // 如果转换失败、使用原始几何 geomToUse = geometry; } } JSONObject geometryObj = convertGeometryToJson(geomToUse); featureObj.put("geometry", geometryObj); // 清理临时几何对象 if (geomToUse != geometry) { geomToUse.delete(); } } else { // 如果没有几何信息、创建空的MultiPolygon featureObj.put("geometry", createEmptyMultiPolygon()); } return featureObj; } /** * 获取字段值 */ private static Object getFieldValue(Feature feature, FieldDefn fieldDefn, int fieldIndex) { int fieldType = fieldDefn.GetFieldType(); if (feature.IsFieldSet(fieldIndex)) { switch (fieldType) { case ogr.OFTInteger: return feature.GetFieldAsInteger(fieldIndex); case ogr.OFTInteger64: return feature.GetFieldAsInteger64(fieldIndex); case ogr.OFTReal: return feature.GetFieldAsDouble(fieldIndex); case ogr.OFTString: return feature.GetFieldAsString(fieldIndex); case ogr.OFTDate: case ogr.OFTTime: case ogr.OFTDateTime: return feature.GetFieldAsString(fieldIndex); default: return feature.GetFieldAsString(fieldIndex); } } return null; } /** * 将几何图形转换为JSON */ private static JSONObject convertGeometryToJson(Geometry geometry) throws JSONException { JSONObject geometryObj = new JSONObject(); String geometryType = geometry.GetGeometryName(); // 根据几何类型处理 switch (geometry.GetGeometryType()) { case wkbPoint: case wkbPoint25D: geometryObj.put("type", "Point"); geometryObj.put("coordinates", getPointCoordinates(geometry)); break; case wkbLineString: case wkbLineString25D: geometryObj.put("type", "LineString"); geometryObj.put("coordinates", getLineStringCoordinates(geometry)); break; case wkbPolygon: case wkbPolygon25D: geometryObj.put("type", "Polygon"); geometryObj.put("coordinates", getPolygonCoordinates(geometry)); break; case wkbMultiPoint: case wkbMultiPoint25D: geometryObj.put("type", "MultiPoint"); geometryObj.put("coordinates", getMultiPointCoordinates(geometry)); break; case wkbMultiLineString: case wkbMultiLineString25D: geometryObj.put("type", "MultiLineString"); geometryObj.put("coordinates", getMultiLineStringCoordinates(geometry)); break; case wkbMultiPolygon: case wkbMultiPolygon25D: geometryObj.put("type", "MultiPolygon"); geometryObj.put("coordinates", getMultiPolygonCoordinates(geometry)); break; case wkbGeometryCollection: case wkbGeometryCollection25D: geometryObj.put("type", "GeometryCollection"); geometryObj.put("geometries", getGeometryCollection(geometry)); break; default: // 默认使用WKT格式 geometryObj.put("type", geometryType); geometryObj.put("wkt", geometry.ExportToWkt()); break; } return geometryObj; } /** * 获取点坐标 */ private static JSONArray getPointCoordinates(Geometry geometry) throws JSONException { JSONArray coords = new JSONArray(); coords.put(geometry.GetX()); coords.put(geometry.GetY()); if (geometry.GetGeometryType() == wkbPoint25D) { coords.put(geometry.GetZ()); } return coords; } /** * 获取线坐标 */ private static JSONArray getLineStringCoordinates(Geometry geometry) throws JSONException { JSONArray coords = new JSONArray(); int pointCount = geometry.GetPointCount(); for (int i = 0; i < pointCount; i++) { JSONArray point = new JSONArray(); point.put(geometry.GetX(i)); point.put(geometry.GetY(i)); if (geometry.GetGeometryType() == wkbLineString25D) { point.put(geometry.GetZ(i)); } coords.put(point); } return coords; } /** * 获取多边形坐标 */ private static JSONArray getPolygonCoordinates(Geometry geometry) throws JSONException { JSONArray rings = new JSONArray(); // 外环 Geometry exteriorRing = geometry.GetGeometryRef(0); rings.put(getLineStringCoordinates(exteriorRing)); // 内环(如果有) int ringCount = geometry.GetGeometryCount(); for (int i = 1; i < ringCount; i++) { Geometry interiorRing = geometry.GetGeometryRef(i); rings.put(getLineStringCoordinates(interiorRing)); } return rings; } /** * 获取多点坐标 */ private static JSONArray getMultiPointCoordinates(Geometry geometry) throws JSONException { JSONArray points = new JSONArray(); int geometryCount = geometry.GetGeometryCount(); for (int i = 0; i < geometryCount; i++) { Geometry point = geometry.GetGeometryRef(i); points.put(getPointCoordinates(point)); } return points; } /** * 获取多线坐标 */ private static JSONArray getMultiLineStringCoordinates(Geometry geometry) throws JSONException { JSONArray lines = new JSONArray(); int geometryCount = geometry.GetGeometryCount(); for (int i = 0; i < geometryCount; i++) { Geometry line = geometry.GetGeometryRef(i); lines.put(getLineStringCoordinates(line)); } return lines; } /** * 获取多多边形坐标 */ private static JSONArray getMultiPolygonCoordinates(Geometry geometry) throws JSONException { JSONArray polygons = new JSONArray(); int geometryCount = geometry.GetGeometryCount(); for (int i = 0; i < geometryCount; i++) { Geometry polygon = geometry.GetGeometryRef(i); polygons.put(getPolygonCoordinates(polygon)); } return polygons; } /** * 获取几何集合 */ private static JSONArray getGeometryCollection(Geometry geometry) throws JSONException { JSONArray geometries = new JSONArray(); int geometryCount = geometry.GetGeometryCount(); for (int i = 0; i < geometryCount; i++) { Geometry geom = geometry.GetGeometryRef(i); geometries.put(convertGeometryToJson(geom)); } return geometries; } /** * 创建空的 MultiPolygon 几何 */ private static JSONObject createEmptyMultiPolygon() throws JSONException { JSONObject geometry = new JSONObject(); geometry.put("type", "MultiPolygon"); geometry.put("coordinates", new JSONArray()); return geometry; } /** * 获取文件信息(辅助方法) */ public static Map getFileInfo(String filePath) { Map info = new HashMap<>(); try { DataSource dataSource = ogr.Open(filePath, 0); if (dataSource != null) { info.put("driver", dataSource.GetDriver().GetName()); info.put("layerCount", dataSource.GetLayerCount()); List> layers = new ArrayList<>(); for (int i = 0; i < dataSource.GetLayerCount(); i++) { Layer layer = dataSource.GetLayer(i); Map layerInfo = new HashMap<>(); layerInfo.put("name", layer.GetName()); layerInfo.put("featureCount", layer.GetFeatureCount()); layerInfo.put("geometryType", ogr.GeometryTypeToName(layer.GetGeomType())); // 添加坐标系信息 String crs = getLayerCrs(layer); layerInfo.put("crs", crs != null ? crs : "未知"); layers.add(layerInfo); } info.put("layers", layers); dataSource.delete(); } } catch (Exception e) { info.put("error", e.getMessage()); } return info; } }