| | |
| | | import cn.hutool.json.JSONUtil; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.se.nsl.config.PropertiesConfig; |
| | | import com.se.nsl.domain.dto.Zarr2Tif; |
| | | 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 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.StandardCopyOption; |
| | | 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; |
| | |
| | | SimuData data = JSONUtil.toBean(simu.getData(), SimuData.class); |
| | | |
| | | update(simu, 1, "初始化参数"); |
| | | initArgs(data); |
| | | initArgs(simu, data); |
| | | createRainfallFile(simu, data); |
| | | |
| | | update(simu, 2, "调用求解器"); |
| | |
| | | /** |
| | | * 初始化参数 |
| | | */ |
| | | 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); |
| | | 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(config.getSourceDem(), 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(config.getSourceLanduse(), gdalconstConstants.GA_ReadOnly); |
| | | ComHelper.Resample(dsLanduse, null, landuseFile, null, wkt, null, null); |
| | | dsLanduse.delete(); |
| | | } |
| | | |
| | | public void updateTif(Simu simu, SimuData data2) throws IOException { |
| | | 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(Simu simu, SimuData data) throws Exception { |
| | | public void createRainfallFile(Simu simu, SimuData data) throws Exception { |
| | | List<Rainfall> rainfalls = data.getRainfalls(); |
| | | if (null == rainfalls || rainfalls.size() < 2) createRainfall(simu); |
| | | |
| | |
| | | } |
| | | //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)); |
| | | |
| | | Files.write(Paths.get(rainfallFile), list, StandardCharsets.UTF_8); |
| | | } |
| | |
| | | /** |
| | | * 调用UWSolver |
| | | */ |
| | | private String callUwSolver(SimuData data) throws Exception { |
| | | public String callUwSolver(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 inPath = config.getInPath() + File.separator + data.getInPath(); |
| | | String terrainFile = (inPath + File.separator + config.getDemFile()).replace("\\", "/"); |
| | | String rainfallFile = (inPath + File.separator + "rainfall.dat").replace("\\", "/"); |
| | | ConfigVo vo = new ConfigVo(duration, config.getSaveFrames(), terrainFile, terrainFile, terrainFile, rainfallFile); |
| | | 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()); |
| | | |
| | | 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); |
| | | String cmd = String.format("%s \"%s\"", config.getUwSolverBat(), configFile); |
| | | |
| | | return callBat(cmd); |
| | | return callBat2(cmd); |
| | | } |
| | | |
| | | /** |
| | | * 调用zarr2tif |
| | | */ |
| | | private String callZarr2tif(SimuData data) throws Exception { |
| | | String zarr2tifBat = config.getZarr2tifBat(); |
| | | File dir = new File(zarr2tifBat).getParentFile(); |
| | | String configJson = new File(dir, "config.json").getAbsolutePath(); |
| | | public String callZarr2tif(SimuData data) throws Exception { |
| | | 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.getTerrainFile(); |
| | | String jsonPath = inPath + File.separator + "zarr2tif.json"; |
| | | |
| | | String cmd = String.format("%s \"%s\"", zarr2tifBat, configJson); |
| | | String res = callBat(cmd); |
| | | Zarr2Tif zarr2Tif = new Zarr2Tif(zarrFile, geotiffDir, terrainFile, data.getStartTime()); |
| | | ComHelper.writeJson(jsonPath, JSON.toJSONString(zarr2Tif)); |
| | | |
| | | File resultTifDir = new File(dir, "result_tif"); |
| | | File targetDir = new File(config.getInPath(), data.getInPath() + File.separator + "depth"); |
| | | System.out.println("targetDir:" + targetDir); |
| | | File[] files = resultTifDir.listFiles(); |
| | | for (File file : files) { |
| | | File target = new File(targetDir, file.getName()); |
| | | Files.copy(file.toPath(), target.toPath()); |
| | | String cmd = String.format("%s \"%s\"", config.getZarr2tifBat(), jsonPath); |
| | | |
| | | return callBat2(cmd); |
| | | } |
| | | |
| | | private String callBat2(String cmd) { |
| | | try { |
| | | ProcessBuilder pb = new ProcessBuilder("cmd", "/c", cmd); |
| | | pb.redirectErrorStream(true); // 合并错误流到标准输出 |
| | | |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | int exitCode = process.waitFor(); |
| | | |
| | | return "ok"; // sb.toString(); |
| | | } catch (Exception ex) { |
| | | log.error(ex.getMessage(), ex); |
| | | return null; |
| | | } |
| | | |
| | | return res; |
| | | } |
| | | |
| | | /*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 terrainFile = inPath + File.separator + config.getTerrainFile(); |
| | | String waterPath = inPath + File.separator + "depth"; |
| | | |
| | | String cmd = String.format("%s \"%s\" \"%s\" \"%s\" \"%s\"", config.getZarr2tifBat(), "depth", zarrFile, terrainFile, waterPath); |
| | |
| | | } |
| | | |
| | | private void createNsl(SimuData data) throws Exception { |
| | | String inPath = config.getInPath() + File.separator + data.getInPath() + File.separator + "depth"; |
| | | procTifs(inPath, inPath, data.getStartTime()); |
| | | /*String inPath = config.getInPath() + File.separator + data.getInPath() + File.separator + "depth"; |
| | | procTifs(inPath, inPath, data.getStartTime());*/ |
| | | |
| | | testService.test(data); |
| | | } |
| | |
| | | |
| | | cal.add(Calendar.MINUTE, 1); |
| | | } |
| | | list.add(0, "1 " + (list.size() - 1)); |
| | | |
| | | Files.write(Paths.get(dat), list, StandardCharsets.UTF_8); |
| | | } |