From 68372fd1905515c5c8dbb9e3b158241994439e06 Mon Sep 17 00:00:00 2001
From: dcb <xgybdcb@163.com>
Date: 星期四, 19 六月 2025 14:18:53 +0800
Subject: [PATCH] 增加生成结果的水深过滤参数

---
 src/main/java/com/se/nsl/service/TestService.java |  514 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 500 insertions(+), 14 deletions(-)

diff --git a/src/main/java/com/se/nsl/service/TestService.java b/src/main/java/com/se/nsl/service/TestService.java
index ab5a11b..bb90b25 100644
--- a/src/main/java/com/se/nsl/service/TestService.java
+++ b/src/main/java/com/se/nsl/service/TestService.java
@@ -1,16 +1,27 @@
 package com.se.nsl.service;
 
 import cn.hutool.core.io.FileUtil;
+import com.alibaba.fastjson.JSON;
 import com.se.nsl.config.PropertiesConfig;
-import com.se.nsl.domain.dto.LayerDto;
-import com.se.nsl.domain.dto.ResultDto;
-import com.se.nsl.domain.po.DataPo;
+import com.se.nsl.domain.dto.*;
+import com.se.nsl.domain.po.SimuData;
 import com.se.nsl.domain.vo.BuildingDepthVo;
+import com.se.nsl.helper.ComHelper;
+import com.se.nsl.utils.TimeFormatUtil;
 import lombok.extern.slf4j.Slf4j;
+import org.gdal.gdal.Band;
+import org.gdal.gdal.Dataset;
+import org.gdal.gdal.gdal;
+import org.gdal.gdalconst.gdalconstConstants;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import java.awt.*;
+import java.awt.image.BufferedImage;
 import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.*;
 import java.util.List;
 
 @Slf4j
@@ -20,10 +31,13 @@
     @Resource
     PropertiesConfig config;
 
-    @Resource
-    ResultService resultService;
+    public static final double MIN_VAL = 0.00001;
 
-    public void test(DataPo data) {
+    public static final double MAX_X_OFFSET = 0;
+
+    public static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+
+    public void test(SimuData data) throws IOException {
         String basePath = config.getInPath() + File.separator + data.getInPath() + File.separator;
         ResultDto dto = new ResultDto(
                 data.getInPath(),
@@ -38,15 +52,12 @@
         process(dto, layer);
     }
 
-    private void process(ResultDto dto, LayerDto layer) {
+    private void process(ResultDto dto, LayerDto layer) throws IOException {
         try {
-//            copeTerrain(dto, layer);
-//            copeBuilding(dto, layer);
-//            List<BuildingDepthVo> buildings = copeWater(dto, layer);
-//            copeFlow(dto, layer);
-//            copeLayerJson(dto, layer);
-//            copeRainFallJson(dto, layer);
-//            copeBuildingDepthJson(dto, buildings);
+            copeTerrain(dto, layer);
+            copeWater(dto, layer);
+            copeFlow(dto, layer);
+            copeLayerJson(dto, layer);
         } finally {
             File dir = new File(dto.getTemp());
             if (dir.exists()) {
@@ -54,4 +65,479 @@
             }
         }
     }
+
+    public void processRealTime(ResultDto dto, LayerDto layer) throws IOException {
+        try {
+            copeTerrainRealTime(dto, layer);
+            copeWater(dto, layer);
+            copeFlow(dto, layer);
+            copeLayerJson(dto, layer);
+        } finally {
+            File dir = new File(dto.getTemp());
+            if (dir.exists()) {
+                FileUtil.del(dir);
+            }
+        }
+    }
+
+    public void copeTerrain(ResultDto dto, LayerDto layer) {
+        Dataset ds = null;
+        try {
+            ds = gdal.Open(dto.getTerrainFile(), gdalconstConstants.GA_ReadOnly); // gdalconst
+            if (null == ds || 0 == ds.getRasterCount()) return;
+
+            setSizes(ds, layer);
+            setTerrainInfo(ds, layer);
+            setWaterInfo(dto, layer);
+            createTerrainPng(dto, ds, layer);
+        } finally {
+            if (null != ds) ds.delete();
+        }
+    }
+
+    private void copeTerrainRealTime(ResultDto dto, LayerDto layer) {
+        Dataset ds = null;
+        try {
+            ds = gdal.Open(dto.getTerrainFile(), gdalconstConstants.GA_ReadOnly); // gdalconst
+            if (null == ds || 0 == ds.getRasterCount()) return;
+
+            setSizes(ds, layer);
+            setTerrainInfo(ds, layer);
+            setWaterInfo(dto, layer);
+            createTerrainPng(dto, ds, layer);
+        } finally {
+            if (null != ds) ds.delete();
+        }
+    }
+
+    private void setSizes(Dataset ds, LayerDto layer) {
+        int xSize = ds.getRasterXSize();
+        int ySize = ds.getRasterYSize();
+        double rate = xSize < ySize ? xSize * 1.0 / ySize : ySize * 1.0 / xSize;
+
+        List<int[]> list = layer.getTerrain().getSize();
+        for (int i = 0, c = list.size(); i < c; i++) {
+            if (xSize < ySize) {
+                list.get(i)[0] = (int) Math.floor(list.get(i)[0] * rate);
+            } else {
+                list.get(i)[1] = (int) Math.floor(list.get(i)[1] * rate);
+            }
+        }
+    }
+
+    public void setTerrainInfo(Dataset ds, LayerDto layer) {
+        double minx = Double.MAX_VALUE;
+        double miny = Double.MAX_VALUE;
+        double maxx = Double.MIN_VALUE;
+        double maxy = Double.MIN_VALUE;
+
+        Band band = ds.GetRasterBand(1);
+        double[] mm = new double[2];
+        band.ComputeRasterMinMax(mm, 0);
+        layer.setExtension(new ExtensionDto(minx, miny, maxx, maxy, mm[0], mm[1]));
+    }
+
+    public void createTerrainPng(ResultDto dto, Dataset ds, LayerDto layer) {
+        String terrainPath = dto.getOutPath() + File.separator + "terrain";
+        File f = new File(terrainPath);
+        if (!f.exists() || !f.isDirectory()) f.mkdirs();
+
+        for (int[] sizes : layer.getTerrain().getSize()) {
+            String tif = dto.getTemp() + File.separator + "terrain_" + sizes[0] + "_" + sizes[1] + ".tif";
+            ComHelper.cutAndResample(ds, tif, sizes[0], sizes[1], layer, true);
+            if (!new File(tif).exists()) continue;
+
+            String png = terrainPath + File.separator + sizes[0] + "_" + sizes[1] + ".png";
+            terrain2Png(layer, tif, png, sizes[0], sizes[1]);
+        }
+    }
+
+    public void terrain2Png(LayerDto layer, String tif, String png, int width, int height) {
+        Dataset ds = null;
+        try {
+            ds = gdal.Open(tif, gdalconstConstants.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, width, height, 0, 0);
+            band.ReadRaster(0, 0, width, height, buffer);
+            layer.getTerrain().getVals().put(width + "_" + height, buffer);
+
+            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+            double differ = layer.getExtension().getMaxHeight() - layer.getExtension().getMinHeight();
+            double minHeight = layer.getExtension().getMinHeight();
+            for (int x = 0; x < width; x++) {
+                for (int y = 0; y < height; y++) {
+                    int offset = x + y * width;
+                    if (Float.isNaN(buffer[offset]) || buffer[offset] < -999 || buffer[offset] < minHeight) continue;
+
+                    int r = 0;
+                    int g;
+                    int b;
+                    if (buffer[offset] - layer.getExtension().getMaxHeight() > 0) {
+                        g = b = 255;
+                    } else {
+                        int val = (int) ((buffer[offset] - minHeight) / differ * 65535);
+                        g = val / 256;
+                        b = val % 256;
+                    }
+
+                    Color color = new Color(r, g, b, 127);
+                    //graphic.drawImage(image, x, y, 1, 1, color, null);
+                    image.setRGB(x, y, color.getRGB());
+                }
+            }
+            ComHelper.savePng(image, png);
+        } finally {
+            if (null != ds) ds.delete();
+        }
+    }
+
+    public void setWaterInfo(ResultDto dto, LayerDto layer) {
+        List<String> files = getFiles(dto.getWaterPath(), ".tif");
+        layer.getWaters().setFiles(files);
+        if (null == files || files.isEmpty()) return;
+
+        setWaterData(layer, files);
+        setWaterHeight(layer, files);
+    }
+
+    public List<BuildingDepthVo> copeWater(ResultDto dto, LayerDto layer) {
+        List<String> files = layer.getWaters().getFiles();
+        if (files.isEmpty() || files.size() != layer.getWaters().getData().size()) return Collections.emptyList();
+
+        processWaters(dto, files, layer);
+
+        return Collections.emptyList();
+    }
+
+    public List<String> getFiles(String path, String suffix) {
+        List<String> files = new ArrayList<>();
+        ComHelper.getFiles(files, new File(path), suffix);
+        files.sort((a, b) -> a.compareToIgnoreCase(b));
+
+        return files;
+    }
+
+    public void setWaterData(LayerDto layer, List<String> files) {
+        for (String file : files) {
+            String fileName = ComHelper.getNameWithExt(file);
+            long timestamp = TimeFormatUtil.toMillis(fileName, "yyyyMMddHHmmss");
+            layer.getWaters().getData().add(timestamp);
+        }
+        layer.getDuration().setStart(layer.getWaters().getData().get(0));
+        layer.getDuration().setEnd(layer.getWaters().getData().get(layer.getWaters().getData().size() - 1));
+    }
+
+    public void setWaterHeight(LayerDto layer, List<String> files) {
+        int c = files.size();
+        int step = files.size() / 10;
+        if (step < 1) step = 1;
+        for (int i = 0; i < c; i += step) {
+            Dataset ds = null;
+            try {
+                ds = gdal.Open(files.get(i), gdalconstConstants.GA_ReadOnly);
+                if (null == ds || 0 == ds.getRasterCount()) return;
+
+                double[] mm = new double[2];
+                ds.GetRasterBand(1).ComputeRasterMinMax(mm, 0);
+                layer.getWaters().setHeight(mm[0], mm[1]);
+            } finally {
+                if (null != ds) ds.delete();
+            }
+        }
+
+        layer.getExtension().setMaxHeight(layer.getExtension().getMaxHeight() + layer.getWaters().getMaxHeight() + 1);
+        layer.getExtension().setMaxHeight(ComHelper.getMaxVal(layer.getExtension().getMaxHeight(), 1000000));
+        layer.getExtension().setMinHeight(ComHelper.getMaxVal(layer.getExtension().getMinHeight(), 1000000));
+        layer.getExtension().setDiffer();
+    }
+
+    public void processWaters(ResultDto dto, List<String> files, LayerDto layer) {
+        List<Double> waterDepths = new ArrayList<>();
+        for (int i = 0, c = files.size(); i < c; i++) {
+            Dataset ds = null;
+            try {
+                ds = gdal.Open(files.get(i), gdalconstConstants.GA_ReadOnly);
+                if (null == ds || 0 == ds.getRasterCount()) return;
+                if (null == ds.GetSpatialRef()) ds.SetSpatialRef(dto.getSpatialReference());
+                waterDepths.add(layer.getWaters().getMinHeight());
+                waterDepths.add(layer.getWaters().getMaxHeight());
+                createWaterPng(dto, ds, layer, layer.getWaters().getData().get(i));
+                //if (config.getCopyTif()) copyWaterTif(dto, ds, layer.getWaters().getData().get(i));
+                ///createVectors(dto, ds, layer, layer.getWaters().getData().get(i));
+            } finally {
+                if (null != ds) ds.delete();
+            }
+        }
+        waterDepths.sort(null);
+        layer.getWaters().setMinHeight(waterDepths.get(0));
+        layer.getWaters().setMaxHeight(waterDepths.get(waterDepths.size() - 1));
+    }
+
+    public void createWaterPng(ResultDto dto, Dataset ds, LayerDto layer, long ticks) {
+        String waterPath = dto.getOutPath() + File.separator + "waters" + File.separator + ticks;
+        File dir = new File(waterPath);
+        if (!dir.exists() || !dir.isDirectory()) dir.mkdirs();
+
+        for (int[] sizes : layer.getTerrain().getSize()) {
+            String fileName = ComHelper.getNameWithExt(ds.GetDescription()) + "_" + sizes[0] + "_" + sizes[1];
+            String tif = dto.getTemp() + File.separator + fileName + ".tif";
+            ComHelper.coordinateTransformAndResample(ds, tif, sizes[0], sizes[1], layer, true);
+            if (!new File(tif).exists()) continue;
+
+            String png = waterPath + File.separator + sizes[0] + "_" + sizes[1] + ".png";
+            water2Png(dto, layer, tif, png, sizes[0], sizes[1]);
+        }
+    }
+
+    public void water2Png(ResultDto dto, LayerDto layer, String tif, String png, int width, int height) {
+        Dataset ds = null;
+        try {
+            ds = gdal.Open(tif, gdalconstConstants.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);
+            double[] transform = ds.GetGeoTransform();
+            buffer = interpolateGrid(buffer, width, height);
+
+            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+            //double differ = layer.getWaters().getMaxHeight() - layer.getWaters().getMinHeight(), minHeight = layer.getWaters().getMinHeight();
+            double differ = layer.getExtension().getDiffer();
+            double maxHeight = layer.getExtension().getMaxHeight();
+            double minHeight = layer.getExtension().getMinHeight();
+            float[] ts = layer.getTerrain().getVals().get(width + "_" + height);
+//            double minDepth = Double.MAX_VALUE;
+//            double maxDepth = Double.MIN_VALUE;
+            for (int x = 0; x < width; x++) {
+                for (int y = 0; y < height; y++) {
+                    int offset = x + y * width;
+                    float depth = buffer[offset];
+                    if (Float.isNaN(depth) || depth < MIN_VAL || Float.isNaN(ts[offset])) continue;
+
+                    int r = 0;
+                    int g;
+                    int b;
+                    if (depth + ts[offset] > maxHeight) {
+                        g = b = 255;
+                    } else {
+                        int val = (int) ((depth + ts[offset] - minHeight) / differ * 65535);
+                        //int val = (int) (buffer[offset] / differ * 65535);
+                        g = val / 256;
+                        b = val % 256;
+                    }
+                    g = ComHelper.getSafeValue(g);
+                    b = ComHelper.getSafeValue(b);
+                    Color color = new Color(r, g, b, 127);
+                    image.setRGB(x, y, color.getRGB());
+
+//                    maxDepth = Math.max(maxDepth, depth);
+//                    minDepth = Math.min(minDepth, depth);
+                }
+            }
+//            Double srcMinHeight = layer.getWaters().getMinHeight();
+//            Double srcMaxHeight = layer.getWaters().getMaxHeight();
+//            if (srcMinHeight == null) {
+//                srcMinHeight = minDepth;
+//                layer.getWaters().setMinHeight(minDepth);
+//            }
+//            if (srcMaxHeight == null) {
+//                srcMaxHeight = maxDepth;
+//                layer.getWaters().setMaxHeight(maxDepth);
+//            }
+//            if (minDepth < srcMinHeight) {
+//                layer.getWaters().setMinHeight(minDepth);
+//            }
+//            if (maxDepth < srcMaxHeight) {
+//                layer.getWaters().setMaxHeight(maxDepth);
+//            }
+            ComHelper.savePng(image, png);
+        } finally {
+            if (null != ds) ds.delete();
+        }
+    }
+
+    /**
+     * 鎻掑�煎鐞�-鍥涢偦鍩�
+     */
+    public float[] interpolateGrid(float[] buffer,  int width, int height) {
+        float[] tempBuffer = new float[width * height];
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                int index = x + y * width;
+                float current = buffer[index];
+                if (current <= MIN_VAL) {
+                    float sum = 0;
+                    int count = 0;
+                    // 妫�鏌ヤ笂閭�
+                    if (y > 0) {
+                        float neighbor = buffer[x + (y - 1) * width];
+                        if (neighbor > MIN_VAL) {
+                            sum += neighbor;
+                            count++;
+                        }
+                    }
+                    // 妫�鏌ヤ笅閭�
+                    if (y < height - 1) {
+                        float neighbor = buffer[x + (y + 1) * width];
+                        if (neighbor > MIN_VAL) {
+                            sum += neighbor;
+                            count++;
+                        }
+                    }
+                    // 妫�鏌ュ乏閭�
+                    if (x > 0) {
+                        float neighbor = buffer[x - 1 + y * width];
+                        if (neighbor > MIN_VAL) {
+                            sum += neighbor;
+                            count++;
+                        }
+                    }
+                    // 妫�鏌ュ彸閭�
+                    if (x < width - 1) {
+                        float neighbor = buffer[x + 1 + y * width];
+                        if (neighbor > MIN_VAL) {
+                            sum += neighbor;
+                            count++;
+                        }
+                    }
+                    // 璁$畻鏂板��
+                    if (count > 0) {
+                        tempBuffer[index] = (sum / count) * 0.5f;
+                    } else {
+                        tempBuffer[index] = 0;
+                    }
+                } else {
+                    tempBuffer[index] = current;
+                }
+            }
+        }
+        //System.arraycopy(tempBuffer, 0, buffer, 0, tempBuffer.length); // 澶嶅埗鍥炲師鏁扮粍
+        return tempBuffer;
+    }
+
+    public void copeFlow(ResultDto dto, LayerDto layer) {
+        List<String> files = layer.getWaters().getFiles();
+        if (null == files || files.isEmpty()) return;
+        for (int i = 0, c = files.size(); i < c; i++) {
+            Dataset ds = null;
+            try {
+                ds = gdal.Open(files.get(i), gdalconstConstants.GA_ReadOnly);
+                if (null == ds || 0 == ds.getRasterCount()) return;
+                if (null == ds.GetSpatialRef()) ds.SetSpatialRef(dto.getSpatialReference());
+
+                createFlowPng(dto, ds, layer, layer.getWaters().getData().get(i));
+            } finally {
+                if (null != ds) ds.delete();
+            }
+        }
+    }
+
+    public void createFlowPng(ResultDto dto, Dataset ds, LayerDto layer, long ticks) {
+        String flowPath = dto.getOutPath() + File.separator + "flows" + File.separator + ticks;
+        File dir = new File(flowPath);
+        if (!dir.exists() || !dir.isDirectory()) dir.mkdirs();
+
+        for (int[] sizes : layer.getTerrain().getSize()) {
+            String name = ComHelper.getNameWithExt(ds.GetDescription()) + "_" + sizes[0] + "_" + sizes[1];
+            String tif = dto.getTemp() + File.separator + name + ".tif";
+            if (!new File(tif).exists()) continue;
+
+            String png = flowPath + File.separator + sizes[0] + "_" + sizes[1] + ".png";
+            vxyTif2Png(tif, png, sizes[0], sizes[1]);
+        }
+    }
+
+    public void vxyTif2Png(String tif, String png, int width, int height) {
+        Dataset ds = null;
+        try {
+            ds = gdal.Open(tif, gdalconstConstants.GA_ReadOnly);
+            if (null == ds || 0 == ds.getRasterCount()) return;
+
+            float[] depthBuffer = new float[width * height];
+            float[] vxBuffer = new float[width * height];
+            float[] vyBuffer = new float[width * height];
+
+            ds.GetRasterBand(1).ReadRaster(0, 0, width, height, depthBuffer);
+            ds.GetRasterBand(2).ReadRaster(0, 0, width, height, vxBuffer);
+            ds.GetRasterBand(3).ReadRaster(0, 0, width, height, vyBuffer);
+
+            createFlowPng(depthBuffer, vxBuffer, vyBuffer, png, width, height);
+        } finally {
+            if (null != ds) ds.delete();
+        }
+    }
+
+    public void createFlowPng(float[] depthBuffer, float[] vxBuffer, float[] vyBuffer, String png, int width, int height) {
+        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                int offset = x + y * width;
+                float depth = ComHelper.getFloatValue(depthBuffer[offset]);
+                float fx = ComHelper.getFloatValue(vxBuffer[offset]);
+                float fy = ComHelper.getFloatValue(vyBuffer[offset]);
+                if (Float.isNaN(fx) && Float.isNaN(fy) || (fx < MIN_VAL && fy < MIN_VAL)) continue;
+
+                if (depth == 0) {
+                    fx = 0f;
+                    fy = 0f;
+                } else {
+                    fx = Float.isNaN(fx) ? 0 : fx / depth;
+                    fy = Float.isNaN(fy) ? 0 : fy / depth;
+                }
+                double dr = Math.sqrt(Math.pow(fx, 2) + Math.pow(fy, 2));
+
+                int r = (int) (dr / 4 * 255);
+                int g = (int) ((fx / dr * 0.5 + 0.5) * 255);
+                int b = (int) ((fy / dr * 0.5 + 0.5) * 255);
+
+                Color color = new Color(ComHelper.getSafeValue(r), ComHelper.getSafeValue(g), ComHelper.getSafeValue(b), 127);
+                image.setRGB(x, y, color.getRGB());
+            }
+        }
+        ComHelper.savePng(image, png);
+    }
+
+    /*public void createFlowPng(float[] vxBuffer, float[] vyBuffer, String png, int width, int height) {
+        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                int offset = x + y * width;
+                float fx = ComHelper.getFloatValue(vxBuffer[offset]);
+                float fy = ComHelper.getFloatValue(vyBuffer[offset]);
+                if (Float.isNaN(fx) && Float.isNaN(fy) || (fx < MIN_VAL && fy < MIN_VAL)) continue;
+
+                fx = Float.isNaN(fx) ? 0 : fx;
+                fy = Float.isNaN(fy) ? 0 : fy;
+                double dr = Math.sqrt(Math.pow(fx, 2) + Math.pow(fy, 2));
+
+                int r = (int) (dr / 4 * 255);
+                int g = (int) ((fx / dr * 0.5 + 0.5) * 255);
+                int b = (int) ((fy / dr * 0.5 + 0.5) * 255);
+
+                Color color = new Color(ComHelper.getSafeValue(r), ComHelper.getSafeValue(g), ComHelper.getSafeValue(b), 127);
+                image.setRGB(x, y, color.getRGB());
+            }
+        }
+        ComHelper.savePng(image, png);
+    }*/
+
+    public void copeLayerJson(ResultDto dto, LayerDto layer) throws IOException {
+        layer.getWaters().setFiles(null);
+        layer.getTerrain().setEpsg(null);
+        layer.getExtension().setDiffer(null);
+
+        String path = dto.getOutPath().replace(config.getOutPath() + File.separator, "");
+        layer.setWaterUrl("/hls/w" + path + ".m3u8");
+        layer.setFlowUrl("/hls/f" + path + ".m3u8");
+
+        String json = JSON.toJSONString(layer);
+//        String filePath = dto.getOutPath() + File.separator + "layer.json";
+        String filePath = dto.getOutPath() + File.separator + layer.getName();
+
+        ComHelper.writeJson(filePath, json);
+    }
 }

--
Gitblit v1.9.3