| | |
| | | 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.*; |
| | | 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.domain.vo.RealTimeInput; |
| | | import com.se.nsl.domain.vo.ResultVo; |
| | | 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.LocalDateTime; |
| | | import java.time.temporal.ChronoUnit; |
| | | import java.util.*; |
| | | import java.util.concurrent.ExecutorService; |
| | | import java.util.concurrent.Executors; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Slf4j |
| | | @Service |
| | |
| | | @Resource |
| | | TestService testService; |
| | | |
| | | private ObjectMapper mapper = new ObjectMapper(); |
| | | |
| | | Integer DIGIT = 1000000; |
| | | |
| | | SimpleDateFormat YYYYMDHM = new SimpleDateFormat("yyyy M d H m "); |
| | | |
| | | List<String> MODES = new ArrayList<>(Arrays.asList("正态分布", "平均分布", "波动平均分布", "持续上升")); |
| | | |
| | | public int start(Simu simu) { |
| | | Date now = new Date(); |
| | |
| | | SimuData data = JSON.parseObject(simu.getData(), SimuData.class); |
| | | data.setInPath(date); |
| | | data.setOutPath(date); |
| | | data.setEpsg(4548); |
| | | data.setEnvelope(envelope); |
| | | data.setEpsg(config.getEpsg()); |
| | | |
| | | simu.setData(JSON.toJSONString(data)); |
| | | simu.setServiceName(date); |
| | |
| | | SimuData data = JSONUtil.toBean(simu.getData(), SimuData.class); |
| | | |
| | | update(simu, 1, "初始化参数"); |
| | | initArgs(data); |
| | | createRainfallFile(data); |
| | | initArgs(simu, data); |
| | | createRainfallFile(simu, data); |
| | | |
| | | /*update(simu, 2, "调用求解器"); |
| | | callUwSolver(data); |
| | | update(simu, 2, "调用求解器"); |
| | | callUwSolver(simu, data); |
| | | |
| | | update(simu, 3, "调用Zarr转Tif"); |
| | | callZarr2tif(data); |
| | | |
| | | update(simu, 4, "解析数据"); |
| | | createNsl(data);*/ |
| | | createNsl(data); |
| | | |
| | | update(simu, 10, "完成"); |
| | | log.info("模拟完成"); |
| | | } catch (Exception ex) { |
| | | log.error(ex.getMessage(), ex); |
| | | update(simu, 20, ex.getMessage()); |
| | |
| | | /** |
| | | * 初始化参数 |
| | | */ |
| | | private void initArgs(SimuData data) throws IOException { |
| | | public void initArgs(Simu simu, SimuData data) throws IOException { |
| | | 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 + "data" + File.separator + "Hillzone.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.Resample(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.Resample(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.Resample(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(注意Java的byte是有符号的,需处理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); // 设置新Nodata值 |
| | | band.FlushCache(); // 强制写入更改 |
| | | ds.delete(); |
| | | } |
| | | |
| | | private void createDir(String path) { |
| | |
| | | f.mkdirs(); |
| | | } |
| | | |
| | | private void createRainfallFile(SimuData data) throws Exception { |
| | | public void createRainfallFile(Simu simu, SimuData data) throws Exception { |
| | | List<Rainfall> rainfalls = data.getRainfalls(); |
| | | if (null == rainfalls || rainfalls.size() < 2) return; // CollUtil.isEmpty |
| | | if (null == rainfalls || rainfalls.size() < 2) createRainfall(simu); |
| | | |
| | | String dat = config.getInPath() + File.separator + "Rainfalls" + File.separator + simu.getId() + ".dat"; |
| | | String rainfallFile = config.getInPath() + File.separator + data.getInPath() + File.separator + "rainfall.dat"; |
| | | if (new File(dat).exists()) { |
| | | Files.copy(Paths.get(dat), Paths.get(rainfallFile), StandardCopyOption.REPLACE_EXISTING); |
| | | return; |
| | | } |
| | | |
| | | List<String> list = new ArrayList<>(); |
| | | list.add(config.getRainfallTitle()); |
| | |
| | | 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.getUnit()); |
| | | int unit = rfUnit.getC(); |
| | | int c = rainfalls.size() - 1; |
| | | for (int i = 0; i < c; i++) { |
| | | Rainfall r1 = rainfalls.get(i); |
| | |
| | | |
| | | list.addAll(calcRainfall(r1, r2, prefix, unit)); |
| | | } |
| | | list.add(prefix + YYYYMDHM.format(rainfalls.get(c).getTime()) + ComHelper.getMinVal(rainfalls.get(c).getIntensity() / unit, DIGIT)); |
| | | //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)); |
| | | |
| | | String rainfallFile = config.getInPath() + File.separator + data.getInPath() + File.separator + "rainfall.dat"; |
| | | Files.write(Paths.get(rainfallFile), list, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | public static double getMinVal(double val, double radix) { |
| | | return ((long) Math.floor(val * radix)) / radix; |
| | | } |
| | | |
| | | // beijing 116.0 40.0 2025 1 1 0 13 1.666666 |
| | | private List<String> calcRainfall(Rainfall r1, Rainfall r2, String prefix, int unit) { |
| | | long mins = Math.abs(r2.getTime().getTime() - r1.getTime().getTime()) / (1000 * 60); // 计算分钟数 |
| | | double diff = ComHelper.getMinVal((r1.getIntensity() - r2.getIntensity()) / mins / unit, DIGIT); |
| | | double diff = (r2.getIntensity() - r1.getIntensity()) / mins / unit; //ComHelper.getMinVal((r1.getIntensity() - r2.getIntensity()) / mins / unit, DIGIT); |
| | | |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.setTime(r1.getTime()); |
| | | |
| | | List<String> list = new ArrayList<>(); |
| | | double intensity = ComHelper.getMinVal(r1.getIntensity() / unit, DIGIT); |
| | | for (int i = 0; i < mins; i++) { |
| | | list.add(prefix + YYYYMDHM.format(cal.getTime()) + r1.getIntensity() + diff * i); |
| | | //list.add(prefix + YYYYMDHM.format(cal.getTime()) + getMinVal((intensity + diff * i), DIGIT)); |
| | | list.add(String.format("%s%s%f", prefix, YYYYMDHM.format(cal.getTime()), getMinVal((intensity + diff * i), DIGIT))); |
| | | cal.add(Calendar.MINUTE, 1); |
| | | } |
| | | |
| | |
| | | /** |
| | | * 调用UWSolver |
| | | */ |
| | | private String callUwSolver(SimuData data) throws Exception { |
| | | public String callUwSolver(Simu simu, SimuData data) throws Exception { |
| | | File uwBat = new File(config.getUwSolverBat()); |
| | | |
| | | 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 rainfallFile = config.getInPath() + File.separator + data.getInPath() + File.separator + "rainfall.dat"; |
| | | ConfigVo vo = new ConfigVo(duration, config.getSaveFrames(), rainfallFile); |
| | | |
| | | String inPath = config.getInPath() + File.separator + data.getInPath(); |
| | | 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, 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); |
| | | String configFile = config.getInPath() + File.separator + data.getInPath() + File.separator + data.getInPath() + ".json"; |
| | | ComHelper.writeJson(configFile, JSON.toJSONString(vo)); |
| | | |
| | | String cmd = String.format("%s %s", config.getUwSolverBat(), configFile); |
| | | |
| | | return callBat(cmd); |
| | | // ComHelper.writeJson(configFile, JSON.toJSONString(vo)); |
| | | mapper.writeValue(new File(configFile), vo); |
| | | String cmd = String.format("%s \"%s\"", config.getUwSolverBat(), configFile); |
| | | return callBat2(cmd); |
| | | } |
| | | |
| | | /** |
| | | * 调用zarr2tif |
| | | */ |
| | | private String callZarr2tif(SimuData data) throws Exception { |
| | | File uwBat = new File(config.getUwSolverBat()); |
| | | String zarrFile = uwBat.getParent() + File.separator + "result.zarr"; |
| | | public String callZarr2tif(SimuData data) throws Exception { |
| | | String inPath = config.getInPath() + File.separator + data.getInPath(); |
| | | String terrainFile = inPath + File.separator + config.getDemFile(); |
| | | String waterPath = inPath + File.separator + "depth"; |
| | | String zarrFile = inPath + File.separator + "result.zarr"; |
| | | String geotiffDir = inPath + File.separator + "depth"; |
| | | String terrainFile = inPath + File.separator + config.getTerrainFile(); |
| | | String jsonPath = inPath + File.separator + "zarr2tif.json"; |
| | | 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); |
| | | |
| | | String cmd = String.format("%s \"%s\" \"%s\" \"%s\" \"%s\"", config.getZarr2tifBat(), "depth", zarrFile, terrainFile, waterPath); |
| | | return callBat2(cmd); |
| | | } |
| | | |
| | | return callBat(cmd); |
| | | private String callBat2(String cmd) { |
| | | try { |
| | | ProcessBuilder pb = new ProcessBuilder("cmd", "/c", cmd); |
| | | pb.redirectErrorStream(true); // 合并错误流到标准输出 |
| | | |
| | | Process process = pb.start(); |
| | | process.getOutputStream().close(); |
| | | |
| | | try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"))) { |
| | | String line; |
| | | while ((line = reader.readLine()) != null) { |
| | | log.info(line); |
| | | } |
| | | } |
| | | |
| | | int exitCode = process.waitFor(); |
| | | |
| | | return "ok"; // sb.toString(); |
| | | } catch (Exception ex) { |
| | | log.error(ex.getMessage(), ex); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private String callBat(String cmd) { |
| | |
| | | } |
| | | |
| | | 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); |
| | | } |
| | | |
| | |
| | | file.delete(); |
| | | } |
| | | } |
| | | |
| | | public String createRainfallCsv(String csvPath, String mode, double total, double intensity, int hours) { |
| | | // python 脚本名.py <参数1-csv文件名> <参数2-降雨模式:正态分布|平均分布|波动平均分布|持续上升> <参数3-降雨总量> <参数4-最大雨强> <参数5-降雨时间(分钟)> |
| | | String cmd = String.format("%s \"%s\" \"%s\" %f %f %d", config.getCreateRainfall(), csvPath, mode, total, intensity, hours * 60); |
| | | return callBat(cmd); |
| | | } |
| | | |
| | | public void createRainfall(Simu simu) throws Exception { |
| | | SimuData data = JSON.parseObject(simu.getData(), SimuData.class); |
| | | if (null == data.getMode() || MODES.contains(data.getMode())) data.setMode(MODES.get(0)); |
| | | if (StringUtils.isEmpty(data.getIntensityUnit())) data.setIntensityUnit("mm/h"); |
| | | |
| | | Geometry geom = Geometry.CreateFromWkt(simu.getGeom()); |
| | | if (geom.GetGeometryType() == ogr.wkbMultiPolygon) geom = geom.GetGeometryRef(0); |
| | | double[] envelope = new double[4]; |
| | | geom.GetEnvelope(envelope); |
| | | data.setEnvelope(envelope); |
| | | data.setEpsg(config.getEpsg()); |
| | | |
| | | String basePath = config.getInPath() + File.separator + "Rainfalls"; |
| | | if (!new File(basePath).exists()) new File(basePath).mkdirs(); |
| | | if (null == simu.getCreateTime()) simu.setCreateTime(new Timestamp(new Date().getTime())); |
| | | |
| | | String csvPath = basePath + File.separator + simu.getId() + ".csv"; |
| | | int unit = StringUtils.isEmpty(data.getIntensityUnit()) || "mm/h".equals(data.getIntensityUnit()) ? 60 : 5; |
| | | createRainfallCsv(csvPath, data.getMode(), data.getTotal(), data.getIntensity() / unit, data.getDuration()); |
| | | |
| | | List<Double> list = getValues(csvPath); |
| | | if (!CollUtil.isEmpty(list)) { |
| | | data.setRainfalls(new ArrayList<>()); |
| | | setRainfalls(simu, data, list); |
| | | } |
| | | |
| | | simu.setData(JSON.toJSONString(data)); |
| | | } |
| | | |
| | | private List<Double> getValues(String csvPath) throws Exception { |
| | | if (!new File(csvPath).exists()) return null; |
| | | |
| | | 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()) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | private void setRainfalls(Simu simu, SimuData data, List<Double> vals) throws Exception { |
| | | String basePath = config.getInPath() + File.separator + "Rainfalls"; |
| | | String dat = basePath + File.separator + simu.getId() + ".dat"; |
| | | |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.setTime(data.getStartTime()); |
| | | |
| | | List<String> list = new ArrayList<>(); |
| | | list.add(config.getRainfallTitle()); |
| | | |
| | | 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 + " "; |
| | | |
| | | Double total = 0.0; |
| | | for (int i = 0, c = vals.size(); i < c; i++) { |
| | | total += vals.get(i); |
| | | if (i % 15 == 0) { |
| | | data.getRainfalls().add(new Rainfall(cal.getTime(), vals.get(i), total)); |
| | | } |
| | | list.add(String.format("%s%s%f", prefix, YYYYMDHM.format(cal.getTime()), vals.get(i))); |
| | | |
| | | cal.add(Calendar.MINUTE, 1); |
| | | } |
| | | // list.add(0, "1 " + (list.size() - 1)); |
| | | |
| | | Files.write(Paths.get(dat), list, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | //实时模拟 |
| | | public String realTimeSimulate(RealTimeInput input) throws IOException { |
| | | long currentTime = System.currentTimeMillis(); |
| | | //根据服务找到指定的文件夹 |
| | | String serviceName = input.getServiceName(); |
| | | File serviceNameDir = new File(config.getInPath(), serviceName); |
| | | //生成一个新的雨量文件,需要原先雨量文件的一些信息,所以需要先读取旧的 |
| | | String[] values = readTheOldFirstLineRainfallValue(serviceNameDir); |
| | | File newDatFile = generateNewRainfallFile(input, values, serviceNameDir, currentTime); |
| | | |
| | | //生成一个新的生成zarr的配置文件 |
| | | File newConfigFile = generateNewZarrConfigFile(serviceNameDir, serviceName, currentTime, newDatFile); |
| | | //执行求解器运算 |
| | | String cmd = String.format("%s \"%s\"", config.getUwSolverBat(), newConfigFile); |
| | | callBat2(cmd); |
| | | |
| | | //生成一个新的zarr转tif的json文件 |
| | | File newZarr2TifJson = generateNewZarr2TifJson(serviceNameDir, currentTime); |
| | | //执行zarr转tif |
| | | String zarr2TifCmd = String.format("%s \"%s\"", config.getZarr2tifBat(), newZarr2TifJson); |
| | | callBat2(zarr2TifCmd); |
| | | //返回新的layer.json名称 |
| | | return generateLayerJsonAndPng(serviceName, serviceNameDir, currentTime); |
| | | |
| | | } |
| | | |
| | | private String generateLayerJsonAndPng(String serviceName, File serviceNameDir, long currentTime) throws IOException { |
| | | ResultDto resultDto = new ResultDto(); |
| | | resultDto.setServiceName(serviceName); |
| | | File temp = Paths.get(config.getOutPath(), serviceName, "temp").toFile(); |
| | | if (!temp.exists()) temp.mkdir(); |
| | | resultDto.setTemp(temp.getAbsolutePath()); |
| | | resultDto.setOutPath(Paths.get(config.getOutPath(), serviceName).toString()); |
| | | File dem = new File(serviceNameDir, "DEM.tif"); |
| | | resultDto.setTerrainFile(dem.getAbsolutePath()); |
| | | File newDepthDir = new File(serviceNameDir + File.separator + "depth_" + currentTime); |
| | | File[] files = newDepthDir.listFiles(); |
| | | resultDto.setWaterPath(newDepthDir.getAbsolutePath()); |
| | | LayerDto layerDto = new LayerDto(config.getVer(), 4548, config.getSizes()); |
| | | String newLayerJsonName = "layer_" + currentTime + ".json"; |
| | | layerDto.setName(newLayerJsonName); |
| | | testService.processRealTime(resultDto, layerDto); |
| | | return newLayerJsonName; |
| | | } |
| | | |
| | | private File generateNewZarr2TifJson(File serviceNameDir, long currentTime) throws IOException { |
| | | File srcZarr2TifJson = new File(serviceNameDir, "zarr2tif.json"); |
| | | Zarr2Tif zarr2Tif = mapper.readValue(srcZarr2TifJson, Zarr2Tif.class); |
| | | //修改zarr2tif对象中的字段 |
| | | // String stamp = TimeFormatUtil.formatTime(currentTime, "yyyy-MM-dd HH:mm:ss"); |
| | | // zarr2Tif.setStart_timestamp(stamp); |
| | | // String newZarrPath = serviceNameDir + File.separator + "result_" + currentTime + ".zarr"; |
| | | String newZarrPath = serviceNameDir + File.separator + "result.zarr"; |
| | | zarr2Tif.setZarr_file(newZarrPath); |
| | | zarr2Tif.setGeotiff_dir(serviceNameDir + File.separator + "depth_" + currentTime); |
| | | File newZarr2TifJson = new File(serviceNameDir, "zarr2tif_" + currentTime + ".json"); |
| | | mapper.writeValue(newZarr2TifJson, zarr2Tif); |
| | | return newZarr2TifJson; |
| | | } |
| | | |
| | | private File generateNewZarrConfigFile(File serviceNameDir, String serviceName, long currentTime, File newDatFile) throws IOException { |
| | | File configFile = new File(serviceNameDir, serviceName + ".json"); |
| | | ConfigVo configVo = mapper.readValue(configFile, ConfigVo.class); |
| | | int simulateTime = 300; //模拟时间,默认为5min,即300s |
| | | int intervalTime = 60; //每帧的间隔时间,默认为60s,60s生成一帧 |
| | | configVo.getRaingage().set(0, newDatFile.getAbsolutePath()); //raingage file |
| | | ResultVo result = configVo.getResult(); |
| | | Integer oldDuration = configVo.getDuration(); |
| | | // result.setSave_start(oldDuration); //起始时间要在上次时间的基础上开始 |
| | | configVo.setDuration(oldDuration + simulateTime); //固定为5min |
| | | result.setSave_interval(intervalTime); |
| | | result.setSave_frames(result.getSave_frames() + (simulateTime / intervalTime)); //保留5帧,在原来的基础上增加5帧 |
| | | // String newZarrPath = serviceNameDir + File.separator + "result_" + currentTime + ".zarr"; |
| | | String newZarrPath = serviceNameDir + File.separator + "result.zarr"; |
| | | result.setSave_name(newZarrPath); |
| | | File newConfigFile = new File(serviceNameDir, currentTime + ".json"); |
| | | mapper.writeValue(newConfigFile, configVo); |
| | | return newConfigFile; |
| | | } |
| | | |
| | | private File generateNewRainfallFile(RealTimeInput input, String[] values, File serviceNameDir, long currentTime) throws IOException { |
| | | String station = values[0]; |
| | | double lon = Double.parseDouble(values[1]); |
| | | double lat = Double.parseDouble(values[2]); |
| | | String title = config.getRainfallTitle(); |
| | | List<String> newLines = new ArrayList<>(); |
| | | newLines.add(title); |
| | | List<RealTimeInput.RealTimeData> data = input.getData(); |
| | | for (RealTimeInput.RealTimeData rd : data) { |
| | | LocalDateTime dateTime = rd.getDateTime(); |
| | | int year = dateTime.getYear(); |
| | | int month = dateTime.getMonthValue(); |
| | | int day = dateTime.getDayOfMonth(); |
| | | int hour = dateTime.getHour(); |
| | | int minute = dateTime.getMinute(); |
| | | double intensity = rd.getIntensity(); //保留指定位数小数 |
| | | String l = String.format("%s %s %s %s %s %s %s %s %s", |
| | | station, lon, lat, year, month, day, hour, minute, String.format("%.6f", intensity)); |
| | | newLines.add(l); |
| | | } |
| | | File newDatFile = new File(serviceNameDir, "rainfall_" + currentTime + ".dat"); |
| | | if (!newDatFile.exists()) newDatFile.createNewFile(); |
| | | Files.write(newDatFile.toPath(), newLines, StandardOpenOption.TRUNCATE_EXISTING); |
| | | return newDatFile; |
| | | } |
| | | |
| | | private static String[] readTheOldFirstLineRainfallValue(File serviceNameDir) throws IOException { |
| | | File srcRailfallFile = new File(serviceNameDir, "rainfall.dat"); |
| | | List<String> lines = Files.readAllLines(srcRailfallFile.toPath()); |
| | | String secondLine = lines.get(1); |
| | | return secondLine.split(" "); |
| | | } |
| | | } |