dcb
2025-05-27 b25ba75d2e0c60242d0f9195f0820db470485c61
新增根据点位查询水深流速接口
已修改4个文件
191 ■■■■ 文件已修改
pom.xml 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/controller/BaseController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/controller/SimuController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/nsl/service/SimuService.java 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -213,23 +213,18 @@
            <artifactId>commons-fileupload</artifactId>
            <version>1.5</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/dev.zarr/jzarr -->
        <dependency>
            <groupId>dev.zarr</groupId>
            <artifactId>jzarr</artifactId>
            <version>0.4.2</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/libs/jzarr-0.4.2.jar</systemPath>
        </dependency>
        <!-- https://mvnrepository.com/artifact/edu.ucar/cdm-core -->
        <dependency>
        <!--<dependency>
            <groupId>edu.ucar</groupId>
            <artifactId>cdm-core</artifactId>
            <version>5.4.1</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/libs/cdm-core-5.4.1.jar</systemPath>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.blosc/jblosc -->
        <dependency>
            <groupId>org.blosc</groupId>
            <artifactId>jblosc</artifactId>
@@ -242,8 +237,6 @@
            <artifactId>jna</artifactId>
            <version>4.2.2</version>
        </dependency>
        <!-- zarr -->
        <!-- https://mvnrepository.com/artifact/org.janelia.saalfeldlab/n5-zarr -->
        <dependency>
            <groupId>org.janelia.saalfeldlab</groupId>
            <artifactId>n5-zarr</artifactId>
@@ -251,14 +244,13 @@
            <scope>system</scope>
            <systemPath>${project.basedir}/libs/n5-zarr-1.3.5.jar</systemPath>
        </dependency>
        <!-- https://mvnrepository.com/artifact/dev.zarr/jzarr -->
        <dependency>
            <groupId>dev.zarr</groupId>
            <artifactId>jzarr</artifactId>
            <version>0.4.2</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/libs/jzarr-0.4.2.jar</systemPath>
        </dependency>
        </dependency>-->
        <!--gavaghan测距-->
        <dependency>
            <groupId>org.gavaghan</groupId>
@@ -327,8 +319,30 @@
            <scope>test</scope>
        </dependency>
    </dependencies>
    <pluginRepositories>
        <pluginRepository>
            <id>alimaven</id>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
    <repositories>
        <repository>
            <id>alimaven</id>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>osgeo</id>
            <name>OSGeo Release Repository</name>
            <url>https://repo.osgeo.org/repository/release/</url>
src/main/java/com/se/nsl/controller/BaseController.java
@@ -40,4 +40,14 @@
        log.error(ex.getMessage(), ex);
        return new R<T>(HttpStatus.INTERNAL_SERVER_ERROR, data, ex.getMessage());
    }
    public <T> R<T> notFound(String msg) {
        return new R<T>(HttpStatus.NOT_FOUND, null, msg);
    }
    public <T> R<T> clientError(String msg) {
        return new R<T>(HttpStatus.BAD_REQUEST, null, msg);
    }
}
src/main/java/com/se/nsl/controller/SimuController.java
@@ -6,6 +6,7 @@
import com.se.nsl.domain.po.Simu;
import com.se.nsl.domain.po.SimuData;
import com.se.nsl.domain.vo.R;
import com.se.nsl.domain.vo.SimuResult;
import com.se.nsl.domain.vo.SimuVo;
import com.se.nsl.service.ResolveService;
import com.se.nsl.service.SimuService;
@@ -163,20 +164,23 @@
    @ApiOperation(value = "position")
    @GetMapping("/position")
    public R<Object> queryByPosition(double lon, double lat, String time, String serviceName) {
    public R<Object> queryByPosition(double lon, double lat, Long time, String serviceName) {
        if (lon > 180 || lon < -180) {
            return fail("经度范围应该在-180到180");
            return clientError("经度范围应该在-180到180");
        }
        if (lat > 90 || lat < -90) {
            return fail("纬度范围应该在-90到90");
            return clientError("纬度范围应该在-90到90");
        }
        if (time == null || time.trim().isEmpty()) {
            return fail("时间戳不能为空");
        if (time == null) {
            return clientError("时间戳不能为空");
        }
        if (serviceName == null || serviceName.trim().isEmpty()) {
            return fail("服务名不能为空");
            return clientError("服务名不能为空");
        }
        return null;
        SimuResult result = simuService.queryByPosition(lon, lat, time, serviceName);
        if (result == null) {
            return notFound("未查找到相关数据");
        }
        return success(result);
    }
}
src/main/java/com/se/nsl/service/SimuService.java
@@ -4,6 +4,9 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bc.zarr.ZarrArray;
import com.bc.zarr.ZarrGroup;
import com.se.nsl.config.PropertiesConfig;
import com.se.nsl.domain.po.Simu;
import com.se.nsl.domain.vo.SimuResult;
import com.se.nsl.domain.vo.SimuVo;
@@ -11,9 +14,20 @@
import com.se.nsl.mapper.SimuMapper;
import com.se.nsl.utils.CoordinateTransformer;
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.util.Arrays;
import java.util.List;
@@ -21,8 +35,12 @@
@Service
@SuppressWarnings("ALL")
public class SimuService {
    public static final String TIF_EXTSION = ".tif";
    @Resource
    SimuMapper simuMapper;
    @Resource
    PropertiesConfig config;
    /**
     * 分页查询推演模拟
@@ -110,14 +128,115 @@
        return simuMapper.updates(Arrays.asList(simu));
    }
    public SimuResult queryByPosition(double lon, double lat, String time, String serviceName) {
    public SimuResult queryByPosition(double lon, double lat, long time, String serviceName) {
        //transform coordiante from 4326 to 4548
        double[] xy = CoordinateTransformer.transform(4326, 4548, 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 zarr data and compare the data with lon,lat,time
//        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 null;
        //read from tif file
        return queryByTif(xy, time, serviceName);
    }
    private SimuResult queryByZarr(double[] xy, long time, String serviceName) {
        double x = xy[0];
        double y = xy[1];
        String prefix = formatTime(time);
        File inPath = new File(config.getInPath());
        File tifDir = new File(inPath, serviceName + File.separator + "depth");
        int index = 0;
        File[] files = tifDir.listFiles();
        for (File file : files) {
            String name = file.getName();
            if (!name.endsWith(TIF_EXTSION)) continue;
            if (name.equals(prefix + TIF_EXTSION)) {
                break;
            }
            index++;
        }
        //TODO需要计算行列号
        int col = 0;
        int row = 0;
        File zarr = new File(inPath, serviceName + File.separator + "result.zarr");
        try {
            ZarrGroup group = ZarrGroup.open(zarr.toPath());
            ZarrArray depthArray = group.openArray("depth");
            Object object = depthArray.read();
            System.out.println(object);
        } 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;
        File tifFile = new File(inPath, child);
        if (!tifFile.exists()) {
            return null;
        }
        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;
        }
        float depth = readPixelValue(dataset, col, row, 1);
        float velocity = calcVelocity(dataset, col, row);
        SimuResult result = new SimuResult();
        result.setDepth(depth);
        result.setVelocity(velocity);
        return  result;
    }
    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];
    }
    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);
    }
}