From a2ee6e0dcdcfd9d1b8011a3cecb4e0fc4f6eeea3 Mon Sep 17 00:00:00 2001 From: dcb <xgybdcb@163.com> Date: 星期五, 06 六月 2025 18:10:32 +0800 Subject: [PATCH] 实时模拟功能实现 --- src/main/java/com/se/nsl/service/SimuService.java | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 154 insertions(+), 1 deletions(-) diff --git a/src/main/java/com/se/nsl/service/SimuService.java b/src/main/java/com/se/nsl/service/SimuService.java index c218828..1c314bc 100644 --- a/src/main/java/com/se/nsl/service/SimuService.java +++ b/src/main/java/com/se/nsl/service/SimuService.java @@ -4,24 +4,44 @@ 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; import com.se.nsl.helper.StringHelper; import com.se.nsl.mapper.SimuMapper; +import com.se.nsl.utils.CoordinateTransformer; +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.util.Arrays; -import java.util.Collections; import java.util.List; @Slf4j @Service @SuppressWarnings("ALL") public class SimuService { + public static final String TIF_EXTSION = ".tif"; @Resource SimuMapper simuMapper; + + @Resource + PropertiesConfig config; /** * 鍒嗛〉鏌ヨ鎺ㄦ紨妯℃嫙 @@ -108,4 +128,137 @@ public int updateById(Simu simu) { return simuMapper.updates(Arrays.asList(simu)); } + + 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("杞崲鍓嶇殑鍧愭爣锛歺:%s,y:%s", lon, lat)); +// System.out.println(String.format("杞崲鍚庣殑鍧愭爣锛歺:%s,y:%s", xy[0], xy[1])); + //read from zarr +// return queryByZarr(xy, time, serviceName); + + //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++; +// } + File dem = new File(inPath, serviceName + File.separator + "DEM.tif"); + ColumnRow cr = getColumnRow(dem.getAbsoluteFile(), x, y); + if (cr == null) return null; + + File zarr = new File(inPath, serviceName + File.separator + "result.zarr"); + try { + ZarrGroup group = ZarrGroup.open(zarr.toPath()); + ZarrArray depthArray = group.openArray("depth"); + int[] shape = new int[] {60, 637, 351}; +// int[] offset = new int[]{210, 384}; + float[] depth = (float[]) depthArray.read(shape); + System.out.println("depth:" + depth.length); + } 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; + } + + 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; + } + + private static ColumnRow getColumnRow(File tifFile, double x, double y) { + Dataset dataset = gdal.Open(tifFile.getAbsolutePath(), gdalconstConstants.GA_ReadOnly); + // 鑾峰彇鍦扮悊鍙樻崲鍙傛暟锛�6鍏冪礌鏁扮粍锛� + // [0]: 宸︿笂瑙扻鍧愭爣, [1]: 鍍忓厓瀹藉害, [2]: X鏂瑰悜鏃嬭浆, + // [3]: 宸︿笂瑙扽鍧愭爣, [4]: Y鏂瑰悜鏃嬭浆, [5]: 鍍忓厓楂樺害锛堣礋鍊艰〃绀篩杞村悜涓嬶級 + 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("琛屽垪鍙蜂笉鍦╰if鑼冨洿鍐�"); + 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]; + } + + 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, "yyyyMMddHHmmss"); + } + } -- Gitblit v1.9.3