package com.se.nsl.helper; import com.se.nsl.domain.dto.*; import lombok.extern.slf4j.Slf4j; import org.gdal.gdal.*; import org.gdal.gdalconst.gdalconst; import org.gdal.ogr.Geometry; import org.gdal.ogr.ogr; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Vector; import java.util.concurrent.CopyOnWriteArrayList; @Slf4j @SuppressWarnings("ALL") public class ComHelper { public static BufferedImage createImage(int width, int height) { BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D graphic = image.createGraphics(); Color transparent = new Color(0, 0, 0, 0); graphic.setColor(transparent); graphic.clearRect(0, 0, width, height); graphic.dispose(); return image; } public static void savePng(BufferedImage image, String png) { try { ImageIO.write(image, "png", new File(png)); } catch (Exception ex) { log.error(ex.getMessage(), ex); } } public static void cutAndResample(Dataset ds, String dest, int width, int height, LayerDto layer, boolean resample) { Vector vector = new Vector<>(); //vector.add("-s_srs"); //vector.add("EPSG:" + 4548); //vector.add("-t_srs"); //vector.add("EPSG:" + 4326); vector.add("-ts"); vector.add("" + width); vector.add("" + height); //vector.add("-te"); //vector.add("" + layer.getExtension().getMinx()); //vector.add("" + layer.getExtension().getMiny()); //vector.add("" + layer.getExtension().getMaxx()); //vector.add("" + layer.getExtension().getMaxy()); //vector.add("-te_srs"); //vector.add("EPSG:" + 4326); if (resample) { vector.add("-r"); vector.add("bilinear"); // 双线性插值 vector.add("-of"); vector.add("GTiff"); } WarpOptions warpOptions = new WarpOptions(vector); Dataset destDs = gdal.Warp(dest, new Dataset[]{ds}, warpOptions); destDs.delete(); } public static void cutAndResample(Dataset ds, Integer targetEpsg, String dest, Double destNoData, String wkt, Integer width, Integer height) { Vector vector = new Vector<>(); if (targetEpsg != null) { //vector.add("-s_srs"); //vector.add("EPSG:" + 4548); vector.add("-t_srs"); vector.add("EPSG:" + targetEpsg); } //if (destNoData != null) { // vector.add("-dstnodata"); // vector.add("" + destNoData); //} if (wkt != null) { vector.add("-cutline"); vector.add(wkt); vector.add("-crop_to_cutline"); } if (width != null && height != null) { vector.add("-ts"); vector.add("" + width); vector.add("" + height); } vector.add("-r"); vector.add("bilinear"); // 双线性插值 vector.add("-of"); vector.add("GTiff"); Dataset destDs = gdal.Warp(dest, new Dataset[]{ds}, new WarpOptions(vector)); if (null != destDs) destDs.delete(); } public static void coordinateTransformAndResample(Dataset ds, String dest, int width, int height, LayerDto layer, boolean resample) { Vector vector = new Vector<>(); vector.add("-s_srs"); vector.add("EPSG:" + 4548); vector.add("-t_srs"); vector.add("EPSG:" + 4326); vector.add("-ts"); vector.add("" + width); vector.add("" + height); //vector.add("-te"); //vector.add("" + layer.getExtension().getMinx()); //vector.add("" + layer.getExtension().getMiny()); //vector.add("" + layer.getExtension().getMaxx()); //vector.add("" + layer.getExtension().getMaxy()); //vector.add("-te_srs"); //vector.add("EPSG:" + 4326); if (resample) { vector.add("-r"); // vector.add("average"); vector.add("cubic"); vector.add("-of"); vector.add("GTiff"); } WarpOptions warpOptions = new WarpOptions(vector); Dataset destDs = gdal.Warp(dest, new Dataset[]{ds}, warpOptions); updateLayerExtension(destDs, layer); destDs.delete(); } private static void updateLayerExtension(Dataset ds, LayerDto layer) { double[] bbox = readTifBbox(ds); double minLon = bbox[0]; double maxLon = bbox[1]; double minLat = bbox[2]; double maxLat = bbox[3]; ExtensionDto extension = layer.getExtension(); double minx = extension.getMinx(); double miny = extension.getMiny(); double maxx = extension.getMaxx(); double maxy = extension.getMaxy(); if (minx > minLon) extension.setMinx(minLon); if (miny > minLat) extension.setMiny(minLat); if (maxx < maxLon) extension.setMaxx(maxLon); if (maxy < maxLat) extension.setMaxy(maxLat); } private static double[] readTifBbox(Dataset ds) { // 1. 获取图像尺寸 int width = ds.getRasterXSize(); int height = ds.getRasterYSize(); // 2. 获取GeoTransform参数 double[] geoTransform = new double[6]; ds.GetGeoTransform(geoTransform); // 3. 解析GeoTransform参数(经纬度坐标) double originLon = geoTransform[0]; // 左上角经度 double originLat = geoTransform[3]; // 左上角纬度 double pixelWidth = geoTransform[1]; // 经度方向分辨率(度/像素) double pixelHeight = geoTransform[5]; // 纬度方向分辨率(度/像素,通常为负) // 4. 计算四至范围(经纬度) double minLon = Math.min(originLon, originLon + width * pixelWidth); double maxLon = Math.max(originLon, originLon + width * pixelWidth); double minLat = Math.min(originLat, originLat + height * pixelHeight); double maxLat = Math.max(originLat, originLat + height * pixelHeight); return new double[] {minLon, maxLon, minLat, maxLat}; } public static BuildingDto intersects(ResultDto dto, double x, double y) { Geometry p = new Geometry(ogr.wkbPoint); p.AddPoint_2D(x, y); p.AssignSpatialReference(dto.getBuildingList().get(0).getGeom().GetSpatialReference()); return dto.getBuildingList().parallelStream().filter(b -> b.getGeom().Intersects(p)).findFirst().orElse(null); } public static boolean isContains(Geometry g, double x, double y) { Geometry p = new Geometry(ogr.wkbPoint); p.AddPoint_2D(x, y); p.AssignSpatialReference(g.GetSpatialReference()); return g.Contains(p); } public static double getMinVal(double val, double radix) { return ((long) Math.floor(val * radix)) / radix; } public static double getMaxVal(double val, double radix) { return ((long) Math.ceil(val * radix)) / radix; } public static float getFloatValue(float val) { return (Float.isNaN(val) || val < -999) ? Float.NaN : val; } public static int getSafeValue(int val) { if (val < 0) return 0; if (val > 255) return 255; return val; } public static boolean isValid(Double val) { return !Double.isNaN(val) && val > Integer.MIN_VALUE; } public static void getFiles(List files, File file, String suffix) { if (!file.exists()) return; if (file.isDirectory()) { File[] fileList = file.listFiles(); for (File f : fileList) { if (f.isDirectory()) { getFiles(files, f, suffix); } else { if (f.getName().toLowerCase().endsWith(suffix)) { files.add(f.getPath()); } } } } else { if (file.getName().toLowerCase().endsWith(suffix)) { files.add(file.getPath()); } } } public static String getNameWithExt(String file) { return file.substring(file.lastIndexOf(File.separator) + 1, file.lastIndexOf(".")); } public static void writeJson(String filePath, String json) throws IOException { FileWriter fw = new FileWriter(filePath); BufferedWriter bw = new BufferedWriter(fw); bw.write(json); bw.close(); fw.close(); } private List getValues(Dataset ds, Geometry g, double[] transform, int xSize, int ySize) { double[] env = new double[4]; g.GetEnvelope(env); int startX = (int) Math.floor((env[0] - transform[0]) / transform[1]); int endX = (int) Math.floor((env[1] - transform[0]) / transform[1]); int startY = (int) Math.floor((transform[3] - env[3]) / Math.abs(transform[5])); int endY = (int) Math.floor((transform[3] - env[2]) / Math.abs(transform[5])); if (startX < 0) startX = 0; if (startY < 0) startY = 0; if (endX > ds.getRasterXSize()) endX = ds.getRasterXSize(); if (endY > ds.getRasterYSize()) endY = ds.getRasterYSize(); if (endX - startX < 1 || endY - startY < 1) return null; float[] values = new float[1]; List points = new ArrayList<>(); for (int x = startX; x <= endX; x++) { for (int y = startY; y <= endY; y++) { double X = transform[0] + x * transform[1] + y * transform[2]; double Y = transform[3] + x * transform[4] + y * transform[5]; ds.GetRasterBand(1).ReadRaster(x, y, 1, 1, values); if (Float.isNaN(values[0]) || values[0] < -999 || !isContains(g, X, Y)) continue; points.add(new PointDto(X, Y, values[0])); } } return null; } private void water2Png2(ResultDto dto, LayerDto layer, String tif, String png, int width, int height) { Dataset ds = null; try { ds = gdal.Open(tif, gdalconst.GA_ReadOnly); if (null == ds || 0 == ds.getRasterCount()) return; Band band = ds.GetRasterBand(1); float[] buffer = new float[width * height]; band.ReadRaster(0, 0, width, height, buffer); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); double differ = layer.getExtension().getDiffer(), maxHeight = layer.getExtension().getMaxHeight(), minHeight = layer.getExtension().getMinHeight(); float[] ts = layer.getTerrain().getVals().get(width + "_" + height); /*layer.getTerrain().getXyo().get(width + "_" + height).stream().forEach(xyo -> { });*/ for (XYO xyo : layer.getTerrain().getXyo().get(width + "_" + height)) { float depth = buffer[xyo.getOffset()] + ts[xyo.getOffset()]; if (Float.isNaN(depth) || depth < minHeight) continue; int r = 0, g, b; if (depth > maxHeight) { g = b = 255; } else { int val = (int) ((depth - minHeight) / differ * 65535); g = val / 256; b = val % 256; } Color color = new Color(r, g, b, 127); image.setRGB(xyo.getX(), xyo.getY(), color.getRGB()); } //savePng(image, png); } finally { if (null != ds) ds.delete(); } } private List getValues2(Dataset ds, Geometry g, double[] transform, int xSize, int ySize) { double[] env = new double[4]; g.GetEnvelope(env); int startX = (int) Math.floor((env[0] - transform[0]) / transform[1]); int endX = (int) Math.floor((env[1] - transform[0]) / transform[1]); int startY = (int) Math.floor((transform[3] - env[3]) / Math.abs(transform[5])); int endY = (int) Math.floor((transform[3] - env[2]) / Math.abs(transform[5])); if (startX < 0) startX = 0; if (startY < 0) startY = 0; if (endX > ds.getRasterXSize()) endX = ds.getRasterXSize(); if (endY > ds.getRasterYSize()) endY = ds.getRasterYSize(); if (endX - startX < 1 || endY - startY < 1) return null; List xyList = new ArrayList<>(); for (int x = startX; x <= endX; x++) { for (int y = startY; y <= endY; y++) { xyList.add(new XYDto(x, y)); } } List points = new CopyOnWriteArrayList<>(); xyList.stream().forEach(xy -> { double X = transform[0] + xy.getX() * transform[1] + xy.getY() * transform[2]; double Y = transform[3] + xy.getX() * transform[4] + xy.getY() * transform[5]; float[] values = new float[1]; ds.GetRasterBand(1).ReadRaster(xy.getX(), xy.getY(), 1, 1, values); if (Float.isNaN(values[0]) || values[0] < -999 || !ComHelper.isContains(g, X, Y)) return; points.add(new PointDto(X, Y, values[0])); }); return points; } }