dcb
2025-06-30 59b432c883011119649c283cc9d4c1d357599802
对于没有不能获取到数据的雨量计,使用其他雨量计数据填充
已添加1个文件
已修改4个文件
600 ■■■■■ 文件已修改
src/main/java/com/se/nsl/service/RealTimeSimulationService.java 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/service/ResolveService.java 216 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/service/SimuService.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/utils/SolverTifUtil.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dev.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/service/RealTimeSimulationService.java
@@ -237,11 +237,16 @@
        List<String> newLines = new ArrayList<>();
        newLines.add(title);
        Map<String, Integer> deviceInfoMap = deviceInfos.stream().collect(Collectors.toMap(DeviceInfo::getId, DeviceInfo::getMappingId));
        List<RainRecord> rainRecords = new ArrayList<>();
        for (RainGauge gauge : gauges) {
            String id = gauge.getId();
            Integer mappingId = deviceInfoMap.getOrDefault(id, 0);
            String l = getRainGaugeResult(gauge, mappingId, currentTime);
            newLines.add(l);
            RainRecord rr = getRainGaugeResult(gauge, mappingId, currentTime);
            rainRecords.add(rr);
        }
        fillEmptyValue(rainRecords); //填充没有值的雨量计
        for (RainRecord rr : rainRecords) {
            newLines.add(rr.toString());
        }
        File newDatFile = new File(serviceNameDir, "rainfall_" + currentTime + ".dat");
        if (!newDatFile.exists()) newDatFile.createNewFile();
@@ -249,7 +254,52 @@
        return newDatFile;
    }
    private String getRainGaugeResult(RainGauge gauge,int stationId, long currentTime) throws JsonProcessingException {
    //将雨量计中空值(intensity为-1)的部分填充值
    private void fillEmptyValue(List<RainRecord> rainRecords) {
        double[] rainValues = rainRecords.stream().mapToDouble(r -> r.getIntensity()).toArray();
        double[] forwardValues = forwardFill(rainValues);
        double[] backwordValues = backwordFill(rainValues);
        for (int i = 0; i < rainRecords.size(); i++) {
            RainRecord rr = rainRecords.get(i);
            double filledValue = forwardValues[i] != -1 ? forwardValues[i] : backwordValues[i];
            rr.setIntensity(filledValue);
        }
        //如果都是-1,则设置为0
        for (RainRecord rr : rainRecords) {
            double intensity = rr.getIntensity();
            if (intensity == -1) {
                rr.setIntensity(0);
            }
        }
    }
    private double[] forwardFill(double[] rainValues) {
        double[] result = Arrays.copyOf(rainValues, rainValues.length);
        double lastValid = -1D;
        for (int i = 0; i < result.length; i++) {
            if (result[i] != -1) {
                lastValid = result[i];
            } else if (lastValid != -1) {
                result[i] = lastValid;
            }
        }
        return result;
    }
    private double[] backwordFill(double[] rainValues) {
        double[] result = Arrays.copyOf(rainValues, rainValues.length);
        double lastValid = -1D;
        for (int i = result.length - 1; i >= 0; i--) {
            if (result[i] != -1) {
                lastValid = result[i];
            } else if (lastValid != -1) {
                result[i] = lastValid;
            }
        }
        return result;
    }
    private RainRecord getRainGaugeResult(RainGauge gauge,int stationId, long currentTime) throws JsonProcessingException {
        double lon = gauge.getX();
        double lat = gauge.getY();
        LocalDateTime dateTime = TimeFormatUtil.toDate(currentTime);
@@ -263,8 +313,9 @@
        String startTime = TimeFormatUtil.formatTime(someMinutesAgo, YYYY_MM_DD_HH_MM_SS);
        String endTime = TimeFormatUtil.formatTime(currentTime, YYYY_MM_DD_HH_MM_SS);
        double intensity = getIntensityByDeviceId(id, startTime, endTime); //保留指定位数小数
        return String.format("%s %s %s %s %s %s %s %s %s",
                stationId, lon, lat, year, month, day, hour, minute, String.format("%.6f", intensity));
//        return String.format("%s %s %s %s %s %s %s %s %s",
//                stationId, lon, lat, year, month, day, hour, minute, String.format("%.6f", intensity));
        return new RainRecord(stationId, lon, lat, year, month, day, hour, minute, intensity);
    }
    //根据雨量计标识查询雨量数据
@@ -285,9 +336,8 @@
        if (!pageData.isEmpty()) {
            return pageData.get(0).get("value").asDouble();
        }
        return 0;
        return -1D;
    }
    private String callBat(String cmd) {
        try {
@@ -309,4 +359,116 @@
        }
    }
    static class RainRecord {
        private int stationId;
        private double lon;
        private double lat;
        private  int year;
        private int month;
        private int day;
        private int hour;
        private int minute;
        private double intensity; //-1代表没有数值
        public RainRecord() {}
        public RainRecord(int stationId, double lon, double lat, int year, int month,
                          int day, int hour, int minute, double intensity) {
            this.stationId = stationId;
            this.lon = lon;
            this.lat = lat;
            this.year = year;
            this.month = month;
            this.day = day;
            this.hour = hour;
            this.minute = minute;
            this.intensity = intensity;
        }
        public int getStationId() {
            return stationId;
        }
        public void setStationId(int stationId) {
            this.stationId = stationId;
        }
        public double getLon() {
            return lon;
        }
        public void setLon(double lon) {
            this.lon = lon;
        }
        public double getLat() {
            return lat;
        }
        public void setLat(double lat) {
            this.lat = lat;
        }
        public int getYear() {
            return year;
        }
        public void setYear(int year) {
            this.year = year;
        }
        public int getMonth() {
            return month;
        }
        public void setMonth(int month) {
            this.month = month;
        }
        public int getDay() {
            return day;
        }
        public void setDay(int day) {
            this.day = day;
        }
        public int getHour() {
            return hour;
        }
        public void setHour(int hour) {
            this.hour = hour;
        }
        public int getMinute() {
            return minute;
        }
        public void setMinute(int minute) {
            this.minute = minute;
        }
        public double getIntensity() {
            return intensity;
        }
        public void setIntensity(double intensity) {
            this.intensity = intensity;
        }
        @Override
        public String toString() {
            return "" + stationId +
                    " " + lon +
                    " " + lat +
                    " " + year +
                    " " + month +
                    " " + day +
                    " " + hour +
                    " " + minute +
                    " " + String.format("%.6f", intensity);
        }
    }
}
src/main/java/com/se/nsl/service/ResolveService.java
@@ -11,8 +11,6 @@
import com.se.nsl.domain.po.Simu;
import com.se.nsl.domain.po.SimuData;
import com.se.nsl.domain.vo.ConfigVo;
import com.se.nsl.domain.vo.RealTimeInput;
import com.se.nsl.domain.vo.ResultVo;
import com.se.nsl.helper.ComHelper;
import com.se.nsl.helper.GdalHelper;
import com.se.nsl.helper.StringHelper;
@@ -37,7 +35,6 @@
import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
@@ -46,7 +43,6 @@
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.ExecutorService;
@@ -156,7 +152,7 @@
    /**
     * åˆå§‹åŒ–参数
     */
    public void initArgs(Simu simu, SimuData data) throws IOException {
    public void initArgs(Simu simu, SimuData data) {
        String inPath = config.getInPath() + File.separator + data.getInPath();
        createDir(inPath);
        createDir(inPath + File.separator + "depth");
@@ -522,114 +518,114 @@
    }
    //实时模拟
    public String realTimeSimulate(RealTimeInput input) throws IOException {
        long currentTime = System.currentTimeMillis();
        //根据服务找到指定的文件夹
        String serviceName = input.getServiceName();
        File serviceNameDir = new File(config.getInPath(), serviceName);
        //生成一个新的雨量文件,需要原先雨量文件的一些信息,所以需要先读取旧的
        String[] values = readTheOldFirstLineRainfallValue(serviceNameDir);
        File newDatFile = generateNewRainfallFile(input, values, serviceNameDir, currentTime);
//    public String realTimeSimulate(RealTimeInput input) throws IOException {
//        long currentTime = System.currentTimeMillis();
//        //根据服务找到指定的文件夹
//        String serviceName = input.getServiceName();
//        File serviceNameDir = new File(config.getInPath(), serviceName);
//        //生成一个新的雨量文件,需要原先雨量文件的一些信息,所以需要先读取旧的
//        String[] values = readTheOldFirstLineRainfallValue(serviceNameDir);
//        File newDatFile = generateNewRainfallFile(input, values, serviceNameDir, currentTime);
//
//        //生成一个新的生成zarr的配置文件
//        File newConfigFile = generateNewZarrConfigFile(serviceNameDir, serviceName, currentTime, newDatFile);
//        //执行求解器运算
//        String cmd = String.format("%s \"%s\"", config.getUwSolverBat(), newConfigFile);
//        callBat2(cmd);
//
//        //生成一个新的zarr转tif的json文件
//        File newZarr2TifJson = generateNewZarr2TifJson(serviceNameDir, currentTime);
//        //执行zarr转tif
//        String zarr2TifCmd = String.format("%s \"%s\"", config.getZarr2tifBat(), newZarr2TifJson);
//        callBat2(zarr2TifCmd);
//        //返回新的layer.json名称
//        return generateLayerJsonAndPng(serviceName, serviceNameDir, currentTime);
//
//    }
        //生成一个新的生成zarr的配置文件
        File newConfigFile = generateNewZarrConfigFile(serviceNameDir, serviceName, currentTime, newDatFile);
        //执行求解器运算
        String cmd = String.format("%s \"%s\"", config.getUwSolverBat(), newConfigFile);
        callBat2(cmd);
//    private String generateLayerJsonAndPng(String serviceName, File serviceNameDir, long currentTime) throws IOException {
//        ResultDto resultDto = new ResultDto();
//        resultDto.setServiceName(serviceName);
//        File temp = Paths.get(config.getOutPath(), serviceName, "temp").toFile();
//        if (!temp.exists()) temp.mkdir();
//        resultDto.setTemp(temp.getAbsolutePath());
//        resultDto.setOutPath(Paths.get(config.getOutPath(), serviceName).toString());
//        File dem = new File(serviceNameDir, "DEM.tif");
//        resultDto.setTerrainFile(dem.getAbsolutePath());
//        File newDepthDir = new File(serviceNameDir + File.separator + "depth_" + currentTime);
//        resultDto.setWaterPath(newDepthDir.getAbsolutePath());
//        LayerDto layerDto = new LayerDto(config.getVer(), 4548, config.getSizes());
//        String newLayerJsonName = "layer_" + currentTime + ".json";
//        layerDto.setName(newLayerJsonName);
//        testService.processRealTime(resultDto, layerDto);
//        return newLayerJsonName;
//    }
        //生成一个新的zarr转tif的json文件
        File newZarr2TifJson = generateNewZarr2TifJson(serviceNameDir, currentTime);
        //执行zarr转tif
        String zarr2TifCmd = String.format("%s \"%s\"", config.getZarr2tifBat(), newZarr2TifJson);
        callBat2(zarr2TifCmd);
        //返回新的layer.json名称
        return generateLayerJsonAndPng(serviceName, serviceNameDir, currentTime);
//    private File generateNewZarr2TifJson(File serviceNameDir, long currentTime) throws IOException {
//        File srcZarr2TifJson = new File(serviceNameDir, "zarr2tif.json");
//        Zarr2Tif zarr2Tif = mapper.readValue(srcZarr2TifJson, Zarr2Tif.class);
//        //修改zarr2tif对象中的字段
////        String stamp = TimeFormatUtil.formatTime(currentTime, "yyyy-MM-dd HH:mm:ss");
////        zarr2Tif.setStart_timestamp(stamp);
////        String newZarrPath = serviceNameDir + File.separator + "result_" + currentTime + ".zarr";
//        String newZarrPath = serviceNameDir + File.separator + "result.zarr";
//        zarr2Tif.setZarr_file(newZarrPath);
//        zarr2Tif.setGeotiff_dir(serviceNameDir + File.separator + "depth_" + currentTime);
//        File newZarr2TifJson = new File(serviceNameDir, "zarr2tif_" + currentTime + ".json");
//        mapper.writeValue(newZarr2TifJson, zarr2Tif);
//        return newZarr2TifJson;
//    }
    }
//    private File generateNewZarrConfigFile(File serviceNameDir, String serviceName, long currentTime, File newDatFile) throws IOException {
//        File configFile = new File(serviceNameDir, serviceName + ".json");
//        ConfigVo configVo = mapper.readValue(configFile, ConfigVo.class);
//        int simulateTime = 300; //模拟时间,默认为5min,即300s
//        int intervalTime = 60; //每帧的间隔时间,默认为60s,60s生成一帧
//        configVo.getRaingage().set(0, newDatFile.getAbsolutePath()); //raingage file
//        ResultVo result = configVo.getResult();
//        Integer oldDuration = configVo.getDuration();
////        result.setSave_start(oldDuration); //起始时间要在上次时间的基础上开始
//        configVo.setDuration(oldDuration + simulateTime); //固定为5min
//        result.setSave_interval(intervalTime);
//        result.setSave_frames(result.getSave_frames() + (simulateTime / intervalTime)); //保留5帧,在原来的基础上增加5帧
////        String newZarrPath = serviceNameDir + File.separator + "result_" + currentTime + ".zarr";
//        String newZarrPath = serviceNameDir + File.separator + "result.zarr";
//        result.setSave_name(newZarrPath);
//        File newConfigFile = new File(serviceNameDir, currentTime + ".json");
//        mapper.writeValue(newConfigFile, configVo);
//        return newConfigFile;
//    }
    private String generateLayerJsonAndPng(String serviceName, File serviceNameDir, long currentTime) throws IOException {
        ResultDto resultDto = new ResultDto();
        resultDto.setServiceName(serviceName);
        File temp = Paths.get(config.getOutPath(), serviceName, "temp").toFile();
        if (!temp.exists()) temp.mkdir();
        resultDto.setTemp(temp.getAbsolutePath());
        resultDto.setOutPath(Paths.get(config.getOutPath(), serviceName).toString());
        File dem = new File(serviceNameDir, "DEM.tif");
        resultDto.setTerrainFile(dem.getAbsolutePath());
        File newDepthDir = new File(serviceNameDir + File.separator + "depth_" + currentTime);
        resultDto.setWaterPath(newDepthDir.getAbsolutePath());
        LayerDto layerDto = new LayerDto(config.getVer(), 4548, config.getSizes());
        String newLayerJsonName = "layer_" + currentTime + ".json";
        layerDto.setName(newLayerJsonName);
        testService.processRealTime(resultDto, layerDto);
        return newLayerJsonName;
    }
//    private File generateNewRainfallFile(RealTimeInput input, String[] values, File serviceNameDir, long currentTime) throws IOException {
//        String station = values[0];
//        double lon = Double.parseDouble(values[1]);
//        double lat = Double.parseDouble(values[2]);
//        String title = config.getRainfallTitle();
//        List<String> newLines = new ArrayList<>();
//        newLines.add(title);
//        List<RealTimeInput.RealTimeData> data = input.getData();
//        for (RealTimeInput.RealTimeData rd : data) {
//            LocalDateTime dateTime = rd.getDateTime();
//            int year = dateTime.getYear();
//            int month = dateTime.getMonthValue();
//            int day = dateTime.getDayOfMonth();
//            int hour = dateTime.getHour();
//            int minute = dateTime.getMinute();
//            double intensity = rd.getIntensity(); //保留指定位数小数
//            String l = String.format("%s %s %s %s %s %s %s %s %s",
//                    station, lon, lat, year, month, day, hour, minute, String.format("%.6f", intensity));
//            newLines.add(l);
//        }
//        File newDatFile = new File(serviceNameDir, "rainfall_" + currentTime + ".dat");
//        if (!newDatFile.exists()) newDatFile.createNewFile();
//        Files.write(newDatFile.toPath(), newLines, StandardOpenOption.TRUNCATE_EXISTING);
//        return newDatFile;
//    }
    private File generateNewZarr2TifJson(File serviceNameDir, long currentTime) throws IOException {
        File srcZarr2TifJson = new File(serviceNameDir, "zarr2tif.json");
        Zarr2Tif zarr2Tif = mapper.readValue(srcZarr2TifJson, Zarr2Tif.class);
        //修改zarr2tif对象中的字段
//        String stamp = TimeFormatUtil.formatTime(currentTime, "yyyy-MM-dd HH:mm:ss");
//        zarr2Tif.setStart_timestamp(stamp);
//        String newZarrPath = serviceNameDir + File.separator + "result_" + currentTime + ".zarr";
        String newZarrPath = serviceNameDir + File.separator + "result.zarr";
        zarr2Tif.setZarr_file(newZarrPath);
        zarr2Tif.setGeotiff_dir(serviceNameDir + File.separator + "depth_" + currentTime);
        File newZarr2TifJson = new File(serviceNameDir, "zarr2tif_" + currentTime + ".json");
        mapper.writeValue(newZarr2TifJson, zarr2Tif);
        return newZarr2TifJson;
    }
    private File generateNewZarrConfigFile(File serviceNameDir, String serviceName, long currentTime, File newDatFile) throws IOException {
        File configFile = new File(serviceNameDir, serviceName + ".json");
        ConfigVo configVo = mapper.readValue(configFile, ConfigVo.class);
        int simulateTime = 300; //模拟时间,默认为5min,即300s
        int intervalTime = 60; //每帧的间隔时间,默认为60s,60s生成一帧
        configVo.getRaingage().set(0, newDatFile.getAbsolutePath()); //raingage file
        ResultVo result = configVo.getResult();
        Integer oldDuration = configVo.getDuration();
//        result.setSave_start(oldDuration); //起始时间要在上次时间的基础上开始
        configVo.setDuration(oldDuration + simulateTime); //固定为5min
        result.setSave_interval(intervalTime);
        result.setSave_frames(result.getSave_frames() + (simulateTime / intervalTime)); //保留5帧,在原来的基础上增加5帧
//        String newZarrPath = serviceNameDir + File.separator + "result_" + currentTime + ".zarr";
        String newZarrPath = serviceNameDir + File.separator + "result.zarr";
        result.setSave_name(newZarrPath);
        File newConfigFile = new File(serviceNameDir, currentTime + ".json");
        mapper.writeValue(newConfigFile, configVo);
        return newConfigFile;
    }
    private File generateNewRainfallFile(RealTimeInput input, String[] values, File serviceNameDir, long currentTime) throws IOException {
        String station = values[0];
        double lon = Double.parseDouble(values[1]);
        double lat = Double.parseDouble(values[2]);
        String title = config.getRainfallTitle();
        List<String> newLines = new ArrayList<>();
        newLines.add(title);
        List<RealTimeInput.RealTimeData> data = input.getData();
        for (RealTimeInput.RealTimeData rd : data) {
            LocalDateTime dateTime = rd.getDateTime();
            int year = dateTime.getYear();
            int month = dateTime.getMonthValue();
            int day = dateTime.getDayOfMonth();
            int hour = dateTime.getHour();
            int minute = dateTime.getMinute();
            double intensity = rd.getIntensity(); //保留指定位数小数
            String l = String.format("%s %s %s %s %s %s %s %s %s",
                    station, lon, lat, year, month, day, hour, minute, String.format("%.6f", intensity));
            newLines.add(l);
        }
        File newDatFile = new File(serviceNameDir, "rainfall_" + currentTime + ".dat");
        if (!newDatFile.exists()) newDatFile.createNewFile();
        Files.write(newDatFile.toPath(), newLines, StandardOpenOption.TRUNCATE_EXISTING);
        return newDatFile;
    }
    private static String[] readTheOldFirstLineRainfallValue(File serviceNameDir) throws IOException {
        File srcRailfallFile = new File(serviceNameDir, "rainfall.dat");
        List<String> lines = Files.readAllLines(srcRailfallFile.toPath());
        String secondLine = lines.get(1);
        return secondLine.split(" ");
    }
//    private static String[] readTheOldFirstLineRainfallValue(File serviceNameDir) throws IOException {
//        File srcRailfallFile = new File(serviceNameDir, "rainfall.dat");
//        List<String> lines = Files.readAllLines(srcRailfallFile.toPath());
//        String secondLine = lines.get(1);
//        return secondLine.split(" ");
//    }
}
src/main/java/com/se/nsl/service/SimuService.java
@@ -13,12 +13,9 @@
import com.se.nsl.helper.StringHelper;
import com.se.nsl.mapper.SimuMapper;
import com.se.nsl.utils.CoordinateTransformer;
import com.se.nsl.utils.SolverTifUtil;
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 ucar.ma2.InvalidRangeException;
@@ -36,7 +33,7 @@
@SuppressWarnings("ALL")
public class SimuService {
    public static final String TIF_EXTSION = ".tif";
    public static final String YYYY_MM_DD_HHMMSS = "yyyyMMddHHmmss";
    public static final String YYYY_MM_DD_HH_MM_SS = "yyyyMMddHHmmss";
    @Resource
    SimuMapper simuMapper;
@@ -56,9 +53,7 @@
        Page<Simu> page = new Page<>(pageNum, pageSize);
        page.addOrder(OrderItem.desc("id"));
        IPage<Simu> paged = simuMapper.selectPage(page, wrapper);
        return paged;
        return simuMapper.selectPage(page, wrapper);
    }
    private QueryWrapper<Simu> getPageWrapper(SimuVo vo, int pageNum, int pageSize) {
@@ -144,7 +139,7 @@
    public List<SimuResult> queryByPosition(double lon, double lat, String serviceName) {
        //transform coordiante from 4326 to 4548
        double[] xy = CoordinateTransformer.transform(4326, 4548, lon, lat);
        double[] xy = CoordinateTransformer.transform(4326, config.getEpsg(), lon, lat);
//        System.out.println(String.format("转换前的坐标:x:%s,y:%s", lon, lat));
//        System.out.println(String.format("转换后的坐标:x:%s,y:%s", xy[0], xy[1]));
        //read from zarr
@@ -172,8 +167,7 @@
//            index++;
//        }
        File dem = new File(inPath, serviceName + File.separator + "DEM.tif");
        ColumnRow cr = getColumnRow(dem.getAbsoluteFile(), x, y);
        if (cr == null) return null;
        //TODO
        File zarr = new File(inPath, serviceName + File.separator + "result.zarr");
        try {
@@ -186,14 +180,10 @@
        } catch (IOException | InvalidRangeException e) {
            throw new RuntimeException(e);
        }
        return null;
    }
    private SimuResult queryByTif(double[] xy, long time, String serviceName) {
        double x = xy[0];
        double y = xy[1];
        File inPath = new File(config.getInPath());
        String prefix = formatTime(time);
        String child = serviceName + File.separator + "depth" + File.separator + prefix + TIF_EXTSION;
@@ -201,22 +191,10 @@
        if (!tifFile.exists()) {
            return null;
        }
        ColumnRow cr = getColumnRow(tifFile, x, y);
        if (cr == null) return null;
//        System.out.println("col:" + cr.col + " ,row:" + cr.row);
        float depth = readPixelValue(cr.dataset, cr.col, cr.row, 1);
        float velocity = calcVelocity(cr.dataset, cr.col, cr.row);
        SimuResult result = new SimuResult();
        result.setDepth(depth);
        result.setVelocity(velocity);
        result.setTime(time);
        return  result;
        return  SolverTifUtil.getSimuResult(tifFile, xy);
    }
    private List<SimuResult> queryByTif(double[] xy, String serviceName) {
        double x = xy[0];
        double y = xy[1];
        List<SimuResult> res = new ArrayList<>();
        File inPath = new File(config.getInPath());
        Path depthPath = Paths.get(inPath.getAbsolutePath(), serviceName, "depth");
@@ -225,75 +203,15 @@
        for (File tifFile : files) {
            String name = tifFile.getName();
            if (!name.endsWith(TIF_EXTSION)) continue;
            ColumnRow cr = getColumnRow(tifFile, x, y);
            if (cr == null) continue;
            float depth = readPixelValue(cr.dataset, cr.col, cr.row, 1);
            float velocity = calcVelocity(cr.dataset, cr.col, cr.row);
            SimuResult result = new SimuResult();
            result.setDepth(depth);
            result.setVelocity(velocity);
            String time = tifFile.getName().replace(".tif", "");
            result.setTime(TimeFormatUtil.toMillis(time, YYYY_MM_DD_HHMMSS));
            SimuResult result = SolverTifUtil.getSimuResult(tifFile, xy);
            if (result == null) continue;
            res.add(result);
        }
        return  res;
    }
    private static ColumnRow getColumnRow(File tifFile, double x, double y) {
        Dataset dataset = gdal.Open(tifFile.getAbsolutePath(), gdalconstConstants.GA_ReadOnly);
        // èŽ·å–åœ°ç†å˜æ¢å‚æ•°ï¼ˆ6元素数组)
        // [0]: å·¦ä¸Šè§’X坐标, [1]: åƒå…ƒå®½åº¦, [2]: X方向旋转,
        // [3]: å·¦ä¸Šè§’Y坐标, [4]: Y方向旋转, [5]: åƒå…ƒé«˜åº¦ï¼ˆè´Ÿå€¼è¡¨ç¤ºY轴向下)
        double[] geoTransform = dataset.GetGeoTransform();
        //计算栅格行列号
        int col = (int) ((x - geoTransform[0]) / geoTransform[1]);
        int row = (int) ((geoTransform[3] - y) / Math.abs(geoTransform[5]));
        int width = dataset.getRasterXSize();
        int height = dataset.getRasterYSize();
        if (col < 0 || col > width || row < 0 || row > height) {
            log.warn("行列号不在tif范围内");
            return null;
        }
        return new ColumnRow(dataset, col, row);
    }
    private static class ColumnRow {
        public final Dataset dataset;
        public final int col;
        public final int row;
        public ColumnRow(Dataset dataset, int col, int row) {
            this.dataset = dataset;
            this.col = col;
            this.row = row;
        }
    }
    private float calcVelocity(Dataset dataset, int col, int row) {
        float x = readPixelValue(dataset, col, row, 2);
        float y = readPixelValue(dataset, col, row, 3);
        float velocity = 0f;
        if (Float.isNaN(x) && Float.isNaN(y)) {
            velocity = 0f;
        } else if (Float.isNaN(x)) {
            velocity = y;
        } else if (Float.isNaN(y)) {
            velocity = x;
        } else {
            velocity = (float) Math.sqrt(x * x + y * y);
        }
        return velocity;
    }
    private float readPixelValue(Dataset dataset, int col, int row, int bandNum) {
        Band band = dataset.GetRasterBand(bandNum);
        float[] values = new float[1];
        band.ReadRaster(col, row, 1, 1, values);
        return values[0];
        return res;
    }
    private String formatTime(long time) {
        return TimeFormatUtil.formatTime(time, YYYY_MM_DD_HHMMSS);
        return TimeFormatUtil.formatTime(time, YYYY_MM_DD_HH_MM_SS);
    }
}
src/main/java/com/se/nsl/utils/SolverTifUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,104 @@
package com.se.nsl.utils;
import com.se.nsl.domain.vo.SimuResult;
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 java.io.File;
//求解器产生的tif文件处理工具
@Slf4j
public class SolverTifUtil {
    private SolverTifUtil() {}
    private static final String YYYY_MM_DD_HH_MM_SS = "yyyyMMddHHmmss";
    private static class ColumnRow {
        public final Dataset dataset;
        public final int col;
        public final int row;
        public ColumnRow(Dataset dataset, int col, int row) {
            this.dataset = dataset;
            this.col = col;
            this.row = row;
        }
    }
    public static SimuResult getSimuResult(File tifFile, double[] position) {
        double x = position[0];
        double y = position[1];
        ColumnRow cr = getColumnRow(tifFile, x, y);
        if (cr == null) return null;
        float depth = readPixelValue(cr.dataset, cr.col, cr.row, 1);
        float velocity = calcVelocity(cr.dataset, cr.col, cr.row);
        SimuResult result = new SimuResult();
        result.setDepth(depth);
        result.setVelocity(velocity);
        String time = tifFile.getName().replace(".tif", "");
        result.setTime(TimeFormatUtil.toMillis(time, YYYY_MM_DD_HH_MM_SS));
        return result;
    }
    public static float getDepth(File tifFile, double[] position) {
        double x = position[0];
        double y = position[1];
        ColumnRow cr = getColumnRow(tifFile, x, y);
        if (cr == null) return 0;
        return readPixelValue(cr.dataset, cr.col, cr.row, 1);
    }
    public static float getValue(File tifFile, double[] position, int band) {
        double x = position[0];
        double y = position[1];
        ColumnRow cr = getColumnRow(tifFile, x, y);
        if (cr == null) return 0;
        return readPixelValue(cr.dataset, cr.col, cr.row, band);
    }
    private static ColumnRow getColumnRow(File tifFile, double x, double y) {
        Dataset dataset = gdal.Open(tifFile.getAbsolutePath(), gdalconstConstants.GA_ReadOnly);
        // èŽ·å–åœ°ç†å˜æ¢å‚æ•°ï¼ˆ6元素数组)
        // [0]: å·¦ä¸Šè§’X坐标, [1]: åƒå…ƒå®½åº¦, [2]: X方向旋转,
        // [3]: å·¦ä¸Šè§’Y坐标, [4]: Y方向旋转, [5]: åƒå…ƒé«˜åº¦ï¼ˆè´Ÿå€¼è¡¨ç¤ºY轴向下)
        double[] geoTransform = dataset.GetGeoTransform();
        //计算栅格行列号
        int col = (int) ((x - geoTransform[0]) / geoTransform[1]);
        int row = (int) ((geoTransform[3] - y) / Math.abs(geoTransform[5]));
        int width = dataset.getRasterXSize();
        int height = dataset.getRasterYSize();
        if (col < 0 || col > width || row < 0 || row > height) {
            log.warn("行列号不在tif范围内");
            return null;
        }
        return new ColumnRow(dataset, col, row);
    }
    private static float calcVelocity(Dataset dataset, int col, int row) {
        float x = readPixelValue(dataset, col, row, 2);
        float y = readPixelValue(dataset, col, row, 3);
        float velocity;
        if (Float.isNaN(x) && Float.isNaN(y)) {
            velocity = 0f;
        } else if (Float.isNaN(x)) {
            velocity = y;
        } else if (Float.isNaN(y)) {
            velocity = x;
        } else {
            velocity = (float) Math.sqrt(x * x + y * y);
        }
        return velocity;
    }
    private static float readPixelValue(Dataset dataset, int col, int row, int bandNum) {
        Band band = dataset.GetRasterBand(bandNum);
        float[] values = new float[1];
        band.ReadRaster(col, row, 1, 1, values);
        return values[0];
    }
}
src/main/resources/application-dev.yml
@@ -175,7 +175,7 @@
  token: YjhhYjAwOWFhMjk1MTM1ZDA0NGU3ZWZlMDQzMzUzZDE1MGJmY2Q4ZWEyYjliNjQzZjcwMjhlNDY0ZjAxNWZjOTZmNzMwYmNmZDA2YmVmNTIzNjU0ZDgzODRjYTUxYTM1
  realTimeInterval: 5
  #请求雨量计数据时,时间范围相差多少分钟
  requestOffsetMinutes: 10
  requestOffsetMinutes: 15
  #往前偏移多少天,为了方便实时模拟以前的降雨情况,设置为0表示,从当前时间开始计算
  offsetDays: 0