Files
yjearth/src/main/java/com/yj/earth/common/util/GdalJsonConverter.java
2025-10-30 15:30:14 +08:00

454 lines
16 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<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;
}
}