package com.se.simu.helper; import com.se.simu.domain.LayerVo; import lombok.extern.slf4j.Slf4j; import org.gdal.gdal.Band; import org.gdal.gdal.Dataset; import org.gdal.gdal.gdal; import org.gdal.gdalconst.gdalconst; import org.gdal.ogr.Geometry; import org.gdal.ogr.ogr; import org.gdal.osr.SpatialReference; import java.io.File; /** * GDAL帮助类 * * @author WWW * @date 2024-07-16 */ @Slf4j @SuppressWarnings("ALL") public class GdalHelper { public final static int I4326 = 4326; public final static int I4490 = 4490; public static SpatialReference SR4326; public static SpatialReference SR4490; public final static String CGCS2000 = "CGCS2000"; /** * 初始化 */ public static void init(String gdalPath) { // 支持中文路径 gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // 属性表支持中文:CP936 gdal.SetConfigOption("SHAPE_ENCODING", ""); gdal.SetConfigOption("PGEO_DRIVER_TEMPLATE", "DRIVER=Microsoft Access Driver (*.mdb, *.accdb);DBQ=%s"); gdal.SetConfigOption("MDB_DRIVER_TEMPLATE", "DRIVER=Microsoft Access Driver (*.mdb, *.accdb);DBQ=%s"); // 配置环境变量 if (!StringHelper.isEmpty(gdalPath)) { gdal.SetConfigOption("GDAL_DATA", gdalPath + "/gdal-data"); gdal.SetConfigOption("PROJ_LIB", gdalPath + "/proj7/share"); //System.setProperty("PROJ_LIB", gdalPath + "/proj7/share") gdal.SetConfigOption("GDAL_DRIVER_PATH", gdalPath + "/gdalplugins"); String path = System.getenv("PATH"); if (!path.contains(gdalPath)) { System.setProperty("PATH", path + ";" + gdalPath); } } // 注册所有的驱动 gdal.AllRegister(); ogr.RegisterAll(); initSr(); } /** * 初始化坐标系 */ public static void initSr() { try { SR4326 = new SpatialReference(); SR4326.ImportFromEPSG(I4326); SR4490 = new SpatialReference(); SR4490.ImportFromEPSG(I4490); } catch (Exception ex) { log.error(ex.getMessage(), ex); } } /** * 读取DEM边界 */ public static LayerVo readDemExtent(String file) { LayerVo layer = new LayerVo(); Dataset ds = null; try { File f = new File(file); if (!f.exists() || f.isDirectory()) { return null; } ds = gdal.Open(file, gdalconst.GA_ReadOnly); if (null == ds) { return null; } Band band = ds.GetRasterBand(1); double[] mm = new double[2]; band.ComputeRasterMinMax(mm); Geometry minPoint = getMinPoint(ds); Geometry maxPoint = getMaxPoint(ds); layer.setExtension(new LayerVo.Extension(minPoint.GetX(), minPoint.GetY(), maxPoint.GetX(), maxPoint.GetY(), mm[0], mm[1])); layer.setTerrain(new LayerVo.Terrain(band.getXSize(), band.getYSize())); layer.setWater(new LayerVo.Water(band.getXSize(), band.getYSize(), null)); } catch (Exception ex) { log.error(ex.getMessage(), ex); } finally { if (null != ds) { ds.delete(); } } return layer; } /** * 获取Dataset的最小点 */ private static Geometry getMinPoint(Dataset ds) { double[] transform = new double[6]; ds.GetGeoTransform(transform); double xMin = transform[0]; double yMin = transform[3] - ds.getRasterYSize() * transform[1]; Geometry point = new Geometry(ogr.wkbPoint); point.AddPoint(xMin, yMin, 0); return transform(ds, point); } /** * 获取Dataset的最大点 */ private static Geometry getMaxPoint(Dataset ds) { /* * transform[0] 左上角x坐标 * transform[1] 东西方向分辨率 * transform[2] 旋转角度, 0表示图像 "北方朝上" * * transform[3] 左上角y坐标 * transform[4] 旋转角度, 0表示图像 "北方朝上" * transform[5] 南北方向分辨率 */ double[] transform = new double[6]; ds.GetGeoTransform(transform); double xMax = transform[0] + (ds.getRasterXSize() * transform[1]); double yMax = transform[3]; Geometry point = new Geometry(ogr.wkbPoint); point.AddPoint(xMax, yMax, 0); return transform(ds, point); } /** * 坐标转换 */ private static Geometry transform(Dataset ds, Geometry point) { point.AssignSpatialReference(ds.GetSpatialRef()); if (ds.GetSpatialRef().IsGeographic() > 0) { return point; } String srsName = ds.GetSpatialRef().GetName(); if (srsName.contains(CGCS2000)) { point.TransformTo(SR4490); } else { point.TransformTo(SR4326); } point.SwapXY(); return point; } /** * 创建金字塔 */ public static void createPyramid(String file) { Dataset ds = null; try { File f = new File(file); if (!f.exists() || f.isDirectory()) { return; } ds = gdal.Open(file, gdalconst.GA_ReadOnly); if (null == ds) { return; } // 创建金字塔 Band band = ds.GetRasterBand(1); if (0 == band.GetOverviewCount()) { ds.BuildOverviews("nearest", new int[]{2, 4, 6, 8, 16}, null); } } catch (Exception ex) { log.error(ex.getMessage(), ex); } finally { if (null != ds) { ds.delete(); } } } }