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<String> 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<String> 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<String> 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<String> 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<PointDto> 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<PointDto> 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<PointDto> 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<XYDto> xyList = new ArrayList<>();
|
for (int x = startX; x <= endX; x++) {
|
for (int y = startY; y <= endY; y++) {
|
xyList.add(new XYDto(x, y));
|
}
|
}
|
|
List<PointDto> 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;
|
}
|
}
|