Files
yjearth/src/main/java/com/yj/earth/common/util/GdalJsonConverter.java

454 lines
16 KiB
Java
Raw Normal View History

2025-10-09 11:03:15 +08:00
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;
2025-10-22 11:44:18 +08:00
import java.io.File;
2025-10-09 11:03:15 +08:00
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 {
2025-10-22 11:44:18 +08:00
// 动态获取项目根目录下的lib文件夹路径
String projectRoot = System.getProperty("user.dir");
// 拼接lib目录路径项目根目录/lib
String projLibPath = projectRoot + File.separator + "lib";
// 设置PROJ库路径指向包含proj.db的lib目录
gdal.SetConfigOption("PROJ_LIB", projLibPath);
2025-10-09 11:03:15 +08:00
gdal.AllRegister();
}
/**
* 将地理数据文件转换为指定结构的JSON
*/
public static String convertToJson(String filePath) {
return convertToJson(filePath, "");
}
/**
* 将地理数据文件转换为指定结构的JSON
*/
2025-10-22 11:44:18 +08:00
private static String convertToJson(String filePath, String targetCrs) {
2025-10-09 11:03:15 +08:00
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();
2025-10-22 11:44:18 +08:00
return result.toString(2);
2025-10-09 11:03:15 +08:00
} catch (Exception e) {
throw new RuntimeException("转换失败: " + e.getMessage(), e);
}
}
/**
2025-10-22 11:44:18 +08:00
* 创建 FeatureCollection 对象
2025-10-09 11:03:15 +08:00
*/
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();
2025-10-22 11:44:18 +08:00
// 获取图层定义、用于字段信息
2025-10-09 11:03:15 +08:00
FeatureDefn layerDefn = layer.GetLayerDefn();
2025-10-22 11:44:18 +08:00
// 如果需要坐标转换、创建坐标转换对象
2025-10-09 11:03:15 +08:00
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();
}
2025-10-22 11:44:18 +08:00
// 如果PROJ4为空、尝试获取WKT
2025-10-09 11:03:15 +08:00
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对象
*/
2025-10-22 11:44:18 +08:00
private static JSONObject createFeature(Feature feature, FeatureDefn layerDefn, CoordinateTransformation coordTrans, boolean transformCoords) throws JSONException {
2025-10-09 11:03:15 +08:00
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());
2025-10-22 11:44:18 +08:00
// 如果转换失败、使用原始几何
2025-10-09 11:03:15 +08:00
geomToUse = geometry;
}
}
JSONObject geometryObj = convertGeometryToJson(geomToUse);
featureObj.put("geometry", geometryObj);
// 清理临时几何对象
if (geomToUse != geometry) {
geomToUse.delete();
}
} else {
2025-10-22 11:44:18 +08:00
// 如果没有几何信息、创建空的MultiPolygon
2025-10-09 11:03:15 +08:00
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;
}
/**
2025-10-30 15:30:14 +08:00
* 创建空的 MultiPolygon 几何
2025-10-09 11:03:15 +08:00
*/
private static JSONObject createEmptyMultiPolygon() throws JSONException {
JSONObject geometry = new JSONObject();
geometry.put("type", "MultiPolygon");
geometry.put("coordinates", new JSONArray());
return geometry;
}
/**
* 获取文件信息辅助方法
*/
public static Map<String, Object> getFileInfo(String filePath) {
Map<String, Object> 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<Map<String, Object>> layers = new ArrayList<>();
for (int i = 0; i < dataSource.GetLayerCount(); i++) {
Layer layer = dataSource.GetLayer(i);
Map<String, Object> 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;
}
}