| | |
| | | |
| | | private Integer saveFrames; |
| | | |
| | | private Integer saveFrameInterval; |
| | | |
| | | private List<Integer> sizes; |
| | | |
| | | private String terrainFile; |
| | |
| | | this.saveFrames = saveFrames; |
| | | } |
| | | |
| | | public Integer getSaveFrameInterval() { |
| | | return saveFrameInterval; |
| | | } |
| | | |
| | | public void setSaveFrameInterval(Integer saveFrameInterval) { |
| | | this.saveFrameInterval = saveFrameInterval; |
| | | } |
| | | |
| | | public boolean isCopyTif() { |
| | | return copyTif; |
| | | } |
| | |
| | | package com.se.nsl.controller; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.se.nsl.domain.po.Simu; |
| | | import com.se.nsl.domain.po.SimuData; |
| | |
| | | return fail("geomå¯¹è±¡ä¸æ¯å¤è¾¹å½¢"); |
| | | |
| | | int rows = simuService.insert(simu); |
| | | System.out.println(String.format("id:%s", simu.getId())); |
| | | |
| | | if (rows > 0 && (null == data.getRainfalls() || data.getRainfalls().size() < 2)) { |
| | | resolveService.createRainfall(simu); |
| | | simuService.updateById(simu); |
| | | } |
| | | |
| | | return success(rows); |
| | | JSONObject json = new JSONObject(); |
| | | json.put("id", simu.getId()); |
| | | return success(json); |
| | | } catch (Exception ex) { |
| | | return fail(ex, null); |
| | | } |
| | |
| | | return fail(ex, null); |
| | | } |
| | | } |
| | | |
| | | @ApiOperation(value = "position") |
| | | @GetMapping("/position") |
| | | public R<Object> queryByPosition(double lon, double lat, String time, String serviceName) { |
| | | if (lon > 180 || lon < -180) { |
| | | return fail("ç»åº¦èå´åºè¯¥å¨-180å°180"); |
| | | } |
| | | if (lat > 90 || lat < -90) { |
| | | return fail("纬度èå´åºè¯¥å¨-90å°90"); |
| | | } |
| | | if (time == null || time.trim().isEmpty()) { |
| | | return fail("æ¶é´æ³ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (serviceName == null || serviceName.trim().isEmpty()) { |
| | | return fail("æå¡åä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | return null; |
| | | } |
| | | } |
| | |
| | | @ApiModelProperty("éé¨å表") |
| | | private List<Rainfall> rainfalls; |
| | | |
| | | @ApiModelProperty("é¨å¼ºåä½ï¼mm/hãmm/5min") |
| | | @ApiModelProperty("é¨å¼ºåä½ï¼mm/hãmm/5minãmm/min") |
| | | private String intensityUnit; |
| | | |
| | | public SimuData() { |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.se.nsl.domain.vo; |
| | | |
| | | public class SimuResult { |
| | | |
| | | private double depth; |
| | | private double velocity; |
| | | |
| | | public double getDepth() { |
| | | return depth; |
| | | } |
| | | |
| | | public void setDepth(double depth) { |
| | | this.depth = depth; |
| | | } |
| | | |
| | | public double getVelocity() { |
| | | return velocity; |
| | | } |
| | | |
| | | public void setVelocity(double velocity) { |
| | | this.velocity = velocity; |
| | | } |
| | | } |
| | |
| | | } |
| | | f.mkdirs(); |
| | | } |
| | | |
| | | enum RainFallUnit { |
| | | MM_H("mm/h", 60), |
| | | MM_15MIN("mm/15min", 15), |
| | | MM_5MIN("mm/5min", 5), |
| | | MM_MIN("mm/min", 1); |
| | | private String unit; |
| | | private int c; //ç³»æ° |
| | | RainFallUnit(String unit, int c) { |
| | | this.unit = unit; |
| | | this.c = c; |
| | | } |
| | | |
| | | public static RainFallUnit of(String unit) { |
| | | RainFallUnit[] values = values(); |
| | | for (RainFallUnit v : values) { |
| | | if (v.unit.equals(unit)) { |
| | | return v; |
| | | } |
| | | } |
| | | return MM_H; //é»è®¤æç
§mm/hè®¡ç® |
| | | } |
| | | |
| | | } |
| | | |
| | | public void createRainfallFile(Simu simu, SimuData data) throws Exception { |
| | | List<Rainfall> rainfalls = data.getRainfalls(); |
| | |
| | | double centerX = ComHelper.getMinVal((data.getMinx() + data.getMaxx()) / 2, DIGIT); |
| | | double centerY = ComHelper.getMinVal((data.getMiny() + data.getMaxy()) / 2, DIGIT); |
| | | String prefix = config.getRainfallSite() + " " + centerX + " " + centerY + " "; |
| | | int unit = StringUtils.isEmpty(data.getIntensityUnit()) || "mm/h".equals(data.getIntensityUnit()) ? 60 : 5; |
| | | |
| | | //å¦ææ²¡æå使è
åä½ä¸ºmm/håæç
§ mm/h计ç®ï¼å¦åæç
§mm/5minè®¡ç® |
| | | // int unit = StringUtils.isEmpty(data.getIntensityUnit()) || "mm/h".equals(data.getIntensityUnit()) ? 60 : 5; |
| | | String iu = data.getIntensityUnit(); |
| | | RainFallUnit rfUnit = RainFallUnit.of(iu); |
| | | data.setIntensityUnit(rfUnit.unit); |
| | | int unit = rfUnit.c; |
| | | int c = rainfalls.size() - 1; |
| | | for (int i = 0; i < c; i++) { |
| | | Rainfall r1 = rainfalls.get(i); |
| | |
| | | String landuseFile = inPath + File.separator + config.getLanduseFile(); |
| | | String rainfallFile = (inPath + File.separator + "rainfall.dat"); |
| | | String saveName = inPath + File.separator + "result.zarr"; |
| | | ConfigVo vo = new ConfigVo(terrainFile, landuseFile, terrainFile, rainfallFile, saveName, duration, config.getSaveFrames()); |
| | | // ConfigVo vo = new ConfigVo(terrainFile, landuseFile, terrainFile, rainfallFile, saveName, duration, config.getSaveFrames()); |
| | | Integer saveFrameInterval = config.getSaveFrameInterval(); |
| | | int saveFrames = duration / 60 / saveFrameInterval; |
| | | ConfigVo vo = new ConfigVo(terrainFile, landuseFile, terrainFile, rainfallFile, saveName, duration, saveFrames); |
| | | |
| | | String configFile = config.getInPath() + File.separator + data.getInPath() + File.separator + data.getInPath() + ".json"; |
| | | ComHelper.writeJson(configFile, JSON.toJSONString(vo)); |
| | |
| | | import com.baomidou.mybatisplus.core.metadata.OrderItem; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | 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 lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.Arrays; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | |
| | | @Slf4j |
| | |
| | | public int updateById(Simu simu) { |
| | | return simuMapper.updates(Arrays.asList(simu)); |
| | | } |
| | | |
| | | public SimuResult queryByPosition(double lon, double lat, String 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 |
| | | |
| | | return null; |
| | | } |
| | | |
| | | } |
| | |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); |
| | | for (String file : files) { |
| | | String fileName = ComHelper.getNameWithExt(file); |
| | | // è§£æä¸º LocalDateTimeï¼é»è®¤åºäºç³»ç»æ¶åºï¼å¯è½éæå®æ¶åºï¼ |
| | | LocalDateTime dateTime = LocalDateTime.parse(fileName, formatter); |
| | | // 转æ¢ä¸º UTC æ¶é´æ³ï¼æ¨èï¼é¿å
æ¶åºæ§ä¹ï¼ |
| | | Instant utcInstant = dateTime.atZone(ZoneId.of("UTC")).toInstant(); |
| | | long timestamp = utcInstant.toEpochMilli(); |
| | | Instant instant = dateTime.atZone(ZoneId.systemDefault()).toInstant(); |
| | | long timestamp = instant.toEpochMilli(); |
| | | layer.getWaters().getData().add(timestamp); |
| | | } |
| | | layer.getDuration().setStart(layer.getWaters().getData().get(0)); |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.se.nsl.utils; |
| | | |
| | | import org.gdal.gdal.gdal; |
| | | import org.gdal.osr.CoordinateTransformation; |
| | | import org.gdal.osr.SpatialReference; |
| | | import org.gdal.osr.osr; |
| | | |
| | | public class CoordinateTransformer { |
| | | |
| | | // static { |
| | | // try { |
| | | // gdal.AllRegister(); |
| | | // } catch (Exception e) { |
| | | // System.err.println("GDAL驱卿³¨å失败: " + e.getMessage()); |
| | | // } |
| | | // } |
| | | |
| | | public static double[] transform(int sourceEPSG, int targetEPSG, |
| | | double x, double y, double z) { |
| | | SpatialReference sourceSRS = null; |
| | | SpatialReference targetSRS = null; |
| | | CoordinateTransformation ct = null; |
| | | |
| | | try { |
| | | // å建æºåæ ç³» |
| | | sourceSRS = new SpatialReference(); |
| | | int sourceResult = sourceSRS.ImportFromEPSG(sourceEPSG); |
| | | if (sourceResult != 0) { |
| | | throw new IllegalArgumentException("æ æçæºEPSG代ç : " + sourceEPSG); |
| | | } |
| | | |
| | | // åå»ºç®æ åæ ç³» |
| | | targetSRS = new SpatialReference(); |
| | | int targetResult = targetSRS.ImportFromEPSG(targetEPSG); |
| | | if (targetResult != 0) { |
| | | throw new IllegalArgumentException("æ æçç®æ EPSG代ç : " + targetEPSG); |
| | | } |
| | | |
| | | sourceSRS.SetAxisMappingStrategy(osr.OAMS_TRADITIONAL_GIS_ORDER); |
| | | targetSRS.SetAxisMappingStrategy(osr.OAMS_TRADITIONAL_GIS_ORDER); |
| | | |
| | | // åå»ºåæ è½¬æ¢å¯¹è±¡ |
| | | ct = new CoordinateTransformation(sourceSRS, targetSRS); |
| | | double[] result = ct.TransformPoint(x, y, z); |
| | | |
| | | if (result == null || Double.isNaN(result[0]) || Double.isNaN(result[1])) { |
| | | throw new IllegalArgumentException("åæ è½¬æ¢å¤±è´¥ï¼å¯è½æ¯åæ ç³»ä¸å
¼å®¹"); |
| | | } |
| | | |
| | | return result; |
| | | } finally { |
| | | // ç¡®ä¿èµæºè¢«éæ¾ |
| | | if (ct != null) ct.delete(); |
| | | if (targetSRS != null) targetSRS.delete(); |
| | | if (sourceSRS != null) sourceSRS.delete(); |
| | | } |
| | | } |
| | | |
| | | public static double[] transform(int sourceEPSG, int targetEPSG, double x, double y) { |
| | | return transform(sourceEPSG, targetEPSG, x, y, 0.0); |
| | | } |
| | | |
| | | public static double[] transform(String sourceWKT, String targetWKT, |
| | | double x, double y, double z) { |
| | | SpatialReference sourceSRS = null; |
| | | SpatialReference targetSRS = null; |
| | | CoordinateTransformation ct = null; |
| | | |
| | | try { |
| | | // å建æºåæ ç³» |
| | | sourceSRS = new SpatialReference(); |
| | | int sourceResult = sourceSRS.ImportFromWkt(sourceWKT); |
| | | if (sourceResult != 0) { |
| | | throw new IllegalArgumentException("æ æçæºWKTå®ä¹"); |
| | | } |
| | | |
| | | // åå»ºç®æ åæ ç³» |
| | | targetSRS = new SpatialReference(); |
| | | int targetResult = targetSRS.ImportFromWkt(targetWKT); |
| | | if (targetResult != 0) { |
| | | throw new IllegalArgumentException("æ æçç®æ WKTå®ä¹"); |
| | | } |
| | | |
| | | // åå»ºåæ è½¬æ¢å¯¹è±¡ |
| | | ct = new CoordinateTransformation(sourceSRS, targetSRS); |
| | | double[] result = ct.TransformPoint(x, y, z); |
| | | |
| | | if (result == null || Double.isNaN(result[0]) || Double.isNaN(result[1])) { |
| | | throw new IllegalArgumentException("åæ è½¬æ¢å¤±è´¥ï¼å¯è½æ¯åæ ç³»ä¸å
¼å®¹"); |
| | | } |
| | | |
| | | return result; |
| | | } finally { |
| | | // ç¡®ä¿èµæºè¢«éæ¾ |
| | | if (ct != null) ct.delete(); |
| | | if (targetSRS != null) targetSRS.delete(); |
| | | if (sourceSRS != null) sourceSRS.delete(); |
| | | } |
| | | } |
| | | |
| | | public static void main(String[] args) { |
| | | try { |
| | | double[] result1 = transform(4326, 32650, 116.4074, 39.9042); // å京 |
| | | System.out.printf("WGS84 -> UTM 50N: (%.6f, %.6f, %.2f)%n", |
| | | result1[0], result1[1], result1[2]); |
| | | |
| | | double[] result2 = transform(4326, 3857, 116.4074, 39.9042); // å京 |
| | | System.out.printf("WGS84 -> Web Mercator: (%.6f, %.6f, %.2f)%n", |
| | | result2[0], result2[1], result2[2]); |
| | | |
| | | // 使ç¨éåNAD83 California zone 5çåæ |
| | | double[] result3 = transform(4326, 26945, -122.4194, 37.7749); // æ§éå±± |
| | | System.out.printf("WGS84 -> NAD83 California zone 5: (%.6f, %.6f, %.2f)%n", |
| | | result3[0], result3[1], result3[2]); |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.se.nsl.utils; |
| | | |
| | | import org.gdal.gdal.Dataset; |
| | | import org.gdal.gdal.Driver; |
| | | import org.gdal.gdal.gdal; |
| | | import org.gdal.gdalconst.gdalconstConstants; |
| | | |
| | | public class ZarrReader { |
| | | |
| | | static { |
| | | // 注åGDALé©±å¨ |
| | | try { |
| | | gdal.AllRegister(); |
| | | } catch (Exception e) { |
| | | System.err.println("GDAL驱卿³¨å失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 读åZarræ°æ®éå¹¶æå°åºæ¬ä¿¡æ¯ |
| | | * @param zarrPath Zarræ°æ®éè·¯å¾ï¼æ¬å°è·¯å¾æURLï¼ |
| | | */ |
| | | public static void readZarr(String zarrPath) { |
| | | // æå¼Zarræ°æ®é |
| | | Driver driver = gdal.GetDriverByName("Zarr"); |
| | | if (driver == null) { |
| | | System.out.println("zarr驱å¨ä¸å¯ç¨"); |
| | | } |
| | | Dataset dataset = gdal.Open(zarrPath, gdalconstConstants.GA_ReadOnly); |
| | | |
| | | |
| | | if (dataset == null) { |
| | | System.err.println("æ æ³æå¼Zarræ°æ®é: " + zarrPath); |
| | | System.err.println(gdal.GetLastErrorMsg()); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | // æå°æ°æ®éåºæ¬ä¿¡æ¯ |
| | | System.out.println("æ°æ®éä¿¡æ¯:"); |
| | | System.out.println(" 驱å¨: " + dataset.GetDriver().getShortName()); |
| | | System.out.println(" 宽度: " + dataset.GetRasterXSize() + " åç´ "); |
| | | System.out.println(" é«åº¦: " + dataset.GetRasterYSize() + " åç´ "); |
| | | System.out.println(" 波段æ°: " + dataset.GetRasterCount()); |
| | | |
| | | // è·åå°ç忢忰 |
| | | double[] geoTransform = dataset.GetGeoTransform(); |
| | | if (geoTransform != null && geoTransform.length >= 6) { |
| | | System.out.println(" å°ç忢忰:"); |
| | | System.out.printf(" å·¦ä¸è§X: %.6f%n", geoTransform[0]); |
| | | System.out.printf(" å·¦ä¸è§Y: %.6f%n", geoTransform[3]); |
| | | System.out.printf(" Xæ¹åå辨ç: %.6f%n", geoTransform[1]); |
| | | System.out.printf(" Yæ¹åå辨ç: %.6f%n", geoTransform[5]); |
| | | } |
| | | |
| | | // è·åæå½±ä¿¡æ¯ |
| | | String projection = dataset.GetProjection(); |
| | | if (projection != null && !projection.isEmpty()) { |
| | | System.out.println(" æå½±ä¿¡æ¯: " + projection.substring(0, Math.min(100, projection.length())) + "..."); |
| | | } |
| | | |
| | | // 读å第ä¸ä¸ªæ³¢æ®µçæ°æ® |
| | | if (dataset.GetRasterCount() > 0) { |
| | | int width = dataset.GetRasterXSize(); |
| | | int height = dataset.GetRasterYSize(); |
| | | float[] buffer = new float[width * height]; |
| | | |
| | | // è¯»åæ³¢æ®µæ°æ® |
| | | dataset.GetRasterBand(1).ReadRaster(0, 0, width, height, buffer); |
| | | |
| | | // ç»è®¡åºæ¬ä¿¡æ¯ |
| | | float min = Float.MAX_VALUE; |
| | | float max = Float.MIN_VALUE; |
| | | float sum = 0; |
| | | int validCount = 0; |
| | | |
| | | for (float value : buffer) { |
| | | if (!Float.isNaN(value) && !Float.isInfinite(value)) { |
| | | min = Math.min(min, value); |
| | | max = Math.max(max, value); |
| | | sum += value; |
| | | validCount++; |
| | | } |
| | | } |
| | | |
| | | if (validCount > 0) { |
| | | float mean = sum / validCount; |
| | | System.out.printf(" 第ä¸ä¸ªæ³¢æ®µç»è®¡ä¿¡æ¯: æå°å¼=%.2f, æå¤§å¼=%.2f, å¹³åå¼=%.2f%n", min, max, mean); |
| | | } |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | System.err.println("读åZarræ°æ®æ¶åçé误: " + e.getMessage()); |
| | | e.printStackTrace(); |
| | | } finally { |
| | | // éæ¾èµæº |
| | | if (dataset != null) { |
| | | dataset.delete(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | public static void main(String[] args) { |
| | | // 示ä¾Zarræ°æ®éè·¯å¾ - è¯·æ¿æ¢ä¸ºå®é
è·¯å¾ |
| | | // String zarrPath = "C:\\Users\\Deng\\Desktop\\just_test\\result.zarr"; |
| | | String zarrPath = "D:\\other\\simu\\uwsolver\\20250516174452\\result.zarr"; |
| | | |
| | | // 读åå¹¶æå°Zarrä¿¡æ¯ |
| | | readZarr(zarrPath); |
| | | |
| | | } |
| | | } |
| | |
| | | flowUnits: CMS |
| | | solverBat: D:\other\simu\uwsolver\run_solver.bat |
| | | sww2tifBat: D:\other\simu\uwsolver\sww2tif.bat |
| | | uwSolverBat: D:\other\simu\CudaUWSolver.Demo.NoVis.20250430\start.bat |
| | | uwSolverBat: D:\other\simu\CudaUWSolver-2.0\start.bat |
| | | # uwSolverBat: D:\other\simu\CudaUWSolver.Demo.NoVis.20250430\start.bat |
| | | zarr2tifBat: D:\other\simu\zarr2tif-2.1\start.bat |
| | | # zarr2tifBat: D:\other\simu\zarr2tif1.0\start.bat |
| | | zarr2tifBat: D:\other\simu\zarr2tif-2.0-mkl\start.bat |
| | | # zarr2tifBat: D:\other\simu\zarr2tif-2.0-mkl\start.bat |
| | | createRainfall: '"C:\Program Files\Python310\python.exe" D:\terrait\NslServer\data\CreatRainfall.py' |
| | | rainfallTitle: Station Longitude Latitude Year Month Day Hour Minute Intensity |
| | | rainfallSite: beijing |
| | | epsg: 4548 |
| | | saveFrames: 10 |
| | | saveFrames: 3 |
| | | #çæå¸§æ°çé´éæ¶é´ï¼å使¯åéï¼è®¾ç½®ä¸º5表示æ¯é5åéçæä¸å¸§ |
| | | saveFrameInterval: 5 |
| | | # åå°å©ç¨ï¼1-Cropland,2-Forest,3-Shrub,4-Grassland,5-Water,6-Snow/Ice,7-Barren,8-Impervious,9-Wetland |
| | | landuse: 2 |
| | | #sizes: 64,128,256,512,1024,2048,4096 |
| | |
| | | buildingKey: KJSFBM |
| | | waterPath: depth |
| | | flowPath: velocity |
| | | landuseFile: Landuse.tif |
| | | sourceDem: D:\other\simu\CudaUWSolver-2.0\Beijing-Data-10m\Beijing-4548-ASTERDEMV3-10m.tif |
| | | sourceLanduse: D:\other\simu\CudaUWSolver-2.0\Beijing-Data-10m\Beijing-4548-Landuse-10m-Nonodata.tif |
| | | copyTif: false |
| | | tifPath: D:\other\simu\uwsolver\5ca43c87cd8e48c5a9c5399a5da46dbc\tongzhou_raster_4548_1m_clip_river_fill.tif |