From f31f0991c0d2036e563b886f57de4cf45d3c72cb Mon Sep 17 00:00:00 2001 From: dcb <xgybdcb@163.com> Date: 星期二, 01 七月 2025 14:51:59 +0800 Subject: [PATCH] 实时模拟异步功能实现 --- src/main/java/com/se/nsl/service/ResolveService.java | 210 +++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 157 insertions(+), 53 deletions(-) diff --git a/src/main/java/com/se/nsl/service/ResolveService.java b/src/main/java/com/se/nsl/service/ResolveService.java index e9a9740..01b4c9f 100644 --- a/src/main/java/com/se/nsl/service/ResolveService.java +++ b/src/main/java/com/se/nsl/service/ResolveService.java @@ -4,35 +4,46 @@ import cn.hutool.core.io.FileUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; +import com.fasterxml.jackson.databind.ObjectMapper; import com.se.nsl.config.PropertiesConfig; -import com.se.nsl.domain.dto.Zarr2Tif; +import com.se.nsl.domain.dto.*; import com.se.nsl.domain.po.Rainfall; 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.helper.ComHelper; +import com.se.nsl.helper.GdalHelper; import com.se.nsl.helper.StringHelper; import com.se.nsl.helper.WebHelper; +import com.se.nsl.utils.AreaType; +import com.se.nsl.utils.RainFallUnit; +import com.se.nsl.utils.SimulateType; +import com.se.nsl.utils.TimeFormatUtil; import lombok.SneakyThrows; 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.gdal.ogr.Geometry; import org.gdal.ogr.ogr; +import org.gdal.osr.CoordinateTransformation; +import org.gdal.osr.SpatialReference; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; 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; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; +import java.nio.file.*; import java.sql.Timestamp; import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -53,6 +64,8 @@ @Resource TestService testService; + + private ObjectMapper mapper = new ObjectMapper(); Integer DIGIT = 1000000; @@ -108,11 +121,11 @@ SimuData data = JSONUtil.toBean(simu.getData(), SimuData.class); update(simu, 1, "鍒濆鍖栧弬鏁�"); - initArgs(data); + initArgs(simu, data); createRainfallFile(simu, data); update(simu, 2, "璋冪敤姹傝В鍣�"); - callUwSolver(data); + callUwSolver(simu, data); update(simu, 3, "璋冪敤Zarr杞琓if"); callZarr2tif(data); @@ -121,6 +134,7 @@ createNsl(data); update(simu, 10, "瀹屾垚"); + log.info("妯℃嫙瀹屾垚"); } catch (Exception ex) { log.error(ex.getMessage(), ex); update(simu, 20, ex.getMessage()); @@ -138,18 +152,96 @@ /** * 鍒濆鍖栧弬鏁� */ - public void initArgs(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"); createDir(inPath + File.separator + "velocity"); createDir(config.getOutPath() + File.separator + data.getOutPath()); - // 涓存椂澶嶅埗楂樼▼tif锛屼互鍚庨渶瑕佽嚜琛屽垏鍓� - File uwBat = new File(config.getUwSolverBat()); - String sourceTif = uwBat.getParent() + File.separator + "case1" + File.separator + "LiuLiMiaoZhen_5m_f32.tif"; - String targetTif = inPath + File.separator + config.getDemFile(); - Files.copy(Paths.get(sourceTif), Paths.get(targetTif), StandardCopyOption.REPLACE_EXISTING); + Short areaType = simu.getAreaType(); + AreaType at = AreaType.of(areaType); + String terrainTif = config.getSourceDem(); + String landuseTif = config.getSourceLanduse(); + String stationTif = null; + if (at == AreaType.KEY_DITCH) { + File keyDitchDir = new File(config.getKeyDitch()); + String areaName = simu.getAreaName(); + Optional<File> first = Arrays.stream(keyDitchDir.listFiles()).filter(f -> f.getName().equals(areaName)).findFirst(); + if (first.isPresent()) { + File targetTifDir = first.get(); + File[] files = targetTifDir.listFiles(); + for (File file : files) { + String name = file.getName(); + if (name.toLowerCase().contains("dem")) { + terrainTif = file.getAbsolutePath(); + } + if (name.toLowerCase().contains("landuse")) { + landuseTif = file.getAbsolutePath(); + } + if (name.toLowerCase().contains("station")) { + stationTif = file.getAbsolutePath(); + } + } + } + } + + Geometry geom = Geometry.CreateFromWkt(simu.getGeom()); + if (geom.GetGeometryType() == ogr.wkbMultiPolygon) geom = geom.GetGeometryRef(0); + SpatialReference dstSR = GdalHelper.createSpatialReference(config.getEpsg()); + + CoordinateTransformation ct = CoordinateTransformation.CreateCoordinateTransformation(GdalHelper.SR4326, dstSR); + geom.Transform(ct); + String wkt = geom.ExportToWkt(); + + String terrainFile = inPath + File.separator + config.getTerrainFile(); + + Dataset dsDem = gdal.Open(terrainTif, gdalconstConstants.GA_ReadOnly); + ComHelper.cutAndResample(dsDem, null, terrainFile, null, wkt, null, null); + dsDem.delete(); + + String landuseFile = inPath + File.separator + config.getLanduseFile(); + + Dataset dsLanduse = gdal.Open(landuseTif, gdalconstConstants.GA_ReadOnly); + ComHelper.cutAndResample(dsLanduse, null, landuseFile, null, wkt, null, null); + dsLanduse.delete(); + + if (stationTif != null) { + String stationFile = inPath + File.separator + "Station.tif"; + Dataset dsStation = gdal.Open(stationTif, gdalconstConstants.GA_ReadOnly); + ComHelper.cutAndResample(dsStation, null, stationFile, null, wkt, null, null); + dsStation.delete(); + } + } + + public void updateTif(Simu simu, SimuData data2) { + Dataset ds = gdal.Open(config.getSourceLanduse(), gdalconstConstants.GA_Update); // 浠ヨ鍐欐ā寮忔墦寮�TIFF鏂囦欢 + + Band band = ds.GetRasterBand(1); + if (band.GetRasterDataType() != gdalconstConstants.GDT_Byte) { + System.err.println("閿欒锛氶潪Byte绫诲瀷鏁版嵁"); + ds.delete(); + return; + } + + int width = band.getXSize(); + int height = band.getYSize(); + + // 璇诲彇Byte绫诲瀷鏁版嵁 + byte[] data = new byte[width * height]; + band.ReadRaster(0, 0, width, height, data); + + // 鏇挎崲0鍊间负8锛堟敞鎰廕ava鐨刡yte鏄湁绗﹀彿鐨勶紝闇�澶勭悊0-255鑼冨洿锛� + for (int i = 0; i < data.length; i++) { + if ((data[i] & 0xFF) == 0) { // 鏃犵鍙锋瘮杈� + data[i] = (byte) 8; + } + } + + band.WriteRaster(0, 0, width, height, data); // 鍐欏洖鏁版嵁骞朵繚瀛� + band.SetNoDataValue(8.0); // 璁剧疆鏂癗odata鍊� + band.FlushCache(); // 寮哄埗鍐欏叆鏇存敼 + ds.delete(); } private void createDir(String path) { @@ -177,8 +269,12 @@ 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璁$畻锛屽惁鍒欐寜鐓m/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.getUnit()); + int unit = rfUnit.getC(); int c = rainfalls.size() - 1; for (int i = 0; i < c; i++) { Rainfall r1 = rainfalls.get(i); @@ -188,7 +284,7 @@ } //list.add(prefix + YYYYMDHM.format(rainfalls.get(c).getTime()) + getMinVal(rainfalls.get(c).getIntensity() / unit, DIGIT)); list.add(String.format("%s%s%f", prefix, YYYYMDHM.format(rainfalls.get(c).getTime()), getMinVal(rainfalls.get(c).getIntensity() / unit, DIGIT))); - list.add(0, "1 " + (list.size() - 1)); +// list.add(0, "1 " + (list.size() - 1)); Files.write(Paths.get(rainfallFile), list, StandardCharsets.UTF_8); } @@ -219,25 +315,39 @@ /** * 璋冪敤UWSolver */ - public String callUwSolver(SimuData data) throws Exception { - File uwBat = new File(config.getUwSolverBat()); - + public String callUwSolver(Simu simu, SimuData data) throws Exception { int duration = 3600 * data.getDuration(); // 绉掓暟 if (null != data.getRainfalls() && data.getRainfalls().size() > 1) { - duration = (int) (Math.abs(data.getRainfalls().get(data.getRainfalls().size() - 1).getTime().getTime() - data.getRainfalls().get(0).getTime().getTime()) / 60); + List<Rainfall> rainfalls = data.getRainfalls(); + int size = rainfalls.size(); + Rainfall last = rainfalls.get(size - 1); + Rainfall first = rainfalls.get(0); + Instant end = last.getTime().toInstant(); + Instant start = first.getTime().toInstant(); + long diff = ChronoUnit.SECONDS.between(end, start); + duration = (int) (Math.abs(diff)); } String inPath = config.getInPath() + File.separator + data.getInPath(); - String terrainFile = (inPath + File.separator + config.getDemFile()); + String terrainFile = inPath + File.separator + config.getTerrainFile(); + 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, terrainFile, 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; + Short type = simu.getType(); + SimulateType simulateType = SimulateType.of(type); + String saveMode = simulateType.getSaveMode(); + String startTime = TimeFormatUtil.formatDate(data.getStartTime()); + ConfigVo vo = new ConfigVo(terrainFile, landuseFile, terrainFile, rainfallFile, + saveName, duration, saveFrames, saveMode, startTime); + vo.setEvaporation(config.getEvaporation()); + vo.getResult().setSave_filter(config.getSaveFilter()); String configFile = config.getInPath() + File.separator + data.getInPath() + File.separator + data.getInPath() + ".json"; - ComHelper.writeJson(configFile, JSON.toJSONString(vo)); - +// ComHelper.writeJson(configFile, JSON.toJSONString(vo)); + mapper.writeValue(new File(configFile), vo); String cmd = String.format("%s \"%s\"", config.getUwSolverBat(), configFile); - return callBat2(cmd); } @@ -248,12 +358,11 @@ String inPath = config.getInPath() + File.separator + data.getInPath(); String zarrFile = inPath + File.separator + "result.zarr"; String geotiffDir = inPath + File.separator + "depth"; - String terrainFile = inPath + File.separator + config.getDemFile(); + String terrainFile = inPath + File.separator + config.getTerrainFile(); String jsonPath = inPath + File.separator + "zarr2tif.json"; - - Zarr2Tif zarr2Tif = new Zarr2Tif(zarrFile, geotiffDir, terrainFile, data.getStartTime()); - ComHelper.writeJson(jsonPath, JSON.toJSONString(zarr2Tif)); - + Zarr2Tif zarr2Tif = new Zarr2Tif(zarrFile, geotiffDir, terrainFile, Collections.emptyList()); +// ComHelper.writeJson(jsonPath, JSON.toJSONString(zarr2Tif)); + mapper.writeValue(new File(jsonPath), zarr2Tif); String cmd = String.format("%s \"%s\"", config.getZarr2tifBat(), jsonPath); return callBat2(cmd); @@ -267,12 +376,10 @@ Process process = pb.start(); process.getOutputStream().close(); - //StringBuilder sb = new StringBuilder(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"))) { String line; while ((line = reader.readLine()) != null) { - System.out.println(line); - //sb.append(line); + log.info(line); } } @@ -284,18 +391,6 @@ return null; } } - - /*private String callZarr2tif(SimuData data) throws Exception { - File uwBat = new File(config.getUwSolverBat()); - String zarrFile = uwBat.getParent() + File.separator + "result.zarr"; - String inPath = config.getInPath() + File.separator + data.getInPath(); - String terrainFile = inPath + File.separator + config.getDemFile(); - String waterPath = inPath + File.separator + "depth"; - - String cmd = String.format("%s \"%s\" \"%s\" \"%s\" \"%s\"", config.getZarr2tifBat(), "depth", zarrFile, terrainFile, waterPath); - - return callBat(cmd); - }*/ private String callBat(String cmd) { try { @@ -324,9 +419,6 @@ } private void createNsl(SimuData data) throws Exception { - /*String inPath = config.getInPath() + File.separator + data.getInPath() + File.separator + "depth"; - procTifs(inPath, inPath, data.getStartTime());*/ - testService.test(data); } @@ -354,7 +446,6 @@ public String createRainfallCsv(String csvPath, String mode, double total, double intensity, int hours) { // python 鑴氭湰鍚�.py <鍙傛暟1-csv鏂囦欢鍚�> <鍙傛暟2-闄嶉洦妯″紡:姝f�佸垎甯億骞冲潎鍒嗗竷|娉㈠姩骞冲潎鍒嗗竷|鎸佺画涓婂崌> <鍙傛暟3-闄嶉洦鎬婚噺> <鍙傛暟4-鏈�澶ч洦寮�> <鍙傛暟5-闄嶉洦鏃堕棿(鍒嗛挓)> String cmd = String.format("%s \"%s\" \"%s\" %f %f %d", config.getCreateRainfall(), csvPath, mode, total, intensity, hours * 60); - return callBat(cmd); } @@ -388,11 +479,10 @@ } private List<Double> getValues(String csvPath) throws Exception { - if (!new File(csvPath).exists()) return null; + if (!new File(csvPath).exists()) return Collections.emptyList(); List<String> list = Files.readAllLines(Paths.get(csvPath)); list.remove(0); - //list.remove(list.size() - 1); return list.stream() .map(s -> new BigDecimal(s).setScale(6, RoundingMode.HALF_DOWN).doubleValue()) @@ -423,8 +513,22 @@ cal.add(Calendar.MINUTE, 1); } - list.add(0, "1 " + (list.size() - 1)); +// list.add(0, "1 " + (list.size() - 1)); Files.write(Paths.get(dat), list, StandardCharsets.UTF_8); } + + public List<String> simulationResults(String serviceName) { + String outPath = config.getOutPath(); + File serviceNameDir = new File(outPath, serviceName); + List<String> res = new ArrayList<>(); + File[] files = serviceNameDir.listFiles(); + for (File file : files) { + String name = file.getName(); + if (name.startsWith("layer")) { + res.add(name); + } + } + return res; + } } -- Gitblit v1.9.3