dcb
2025-06-30 59b432c883011119649c283cc9d4c1d357599802
src/main/java/com/se/nsl/service/SimuService.java
@@ -13,21 +13,18 @@
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;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -36,6 +33,7 @@
@SuppressWarnings("ALL")
public class SimuService {
    public static final String TIF_EXTSION = ".tif";
    public static final String YYYY_MM_DD_HH_MM_SS = "yyyyMMddHHmmss";
    @Resource
    SimuMapper simuMapper;
@@ -55,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) {
@@ -141,6 +137,19 @@
    }
    public List<SimuResult> queryByPosition(double lon, double lat, String serviceName) {
        //transform coordiante from 4326 to 4548
        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
//        return queryByZarr(xy, time, serviceName);
        //read from tif file
        return queryByTif(xy, serviceName);
    }
    private SimuResult queryByZarr(double[] xy, long time, String serviceName) {
        double x = xy[0];
        double y = xy[1];
@@ -158,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 {
@@ -172,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;
@@ -187,76 +191,27 @@
        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);
        return  result;
        return  SolverTifUtil.getSimuResult(tifFile, xy);
    }
    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;
    private List<SimuResult> queryByTif(double[] xy, String serviceName) {
        List<SimuResult> res = new ArrayList<>();
        File inPath = new File(config.getInPath());
        Path depthPath = Paths.get(inPath.getAbsolutePath(), serviceName, "depth");
        File depthDir = depthPath.toFile();
        File[] files = depthDir.listFiles();
        for (File tifFile : files) {
            String name = tifFile.getName();
            if (!name.endsWith(TIF_EXTSION)) continue;
            SimuResult result = SolverTifUtil.getSimuResult(tifFile, xy);
            if (result == null) continue;
            res.add(result);
        }
        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) {
        Instant instant = Instant.ofEpochMilli(time);
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        return localDateTime.format(formatter);
        return TimeFormatUtil.formatTime(time, YYYY_MM_DD_HH_MM_SS);
    }
}