src/main/java/com/se/simu/controller/SimuController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/se/simu/domain/vo/CreateFilesSimuVo.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/se/simu/utils/CsvToSQLiteUtils.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/se/simu/utils/ShpToolUtils.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/main/java/com/se/simu/controller/SimuController.java
@@ -1,5 +1,6 @@ package com.se.simu.controller; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.metadata.IPage; import com.se.simu.config.PropertiesConfig; @@ -12,9 +13,11 @@ import com.se.simu.domain.vo.R; import com.se.simu.domain.vo.SimuVo; import com.se.simu.service.*; import com.se.simu.utils.CsvToSQLiteUtils; import com.se.simu.utils.ShpToolUtils; import io.swagger.annotations.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @@ -207,16 +210,28 @@ String floodFile = vo.getFloodFile(); log.info("范围文件地址:{}", floodFile); try { // 判断地址不为空 if (StringUtils.isEmpty(floodFile)) { return fail("范围文件地址不能为空", false); } else { // 获取文件的后缀名 String fileName = floodFile.substring(floodFile.lastIndexOf(".")); // 判断后缀名是否为.shp if (!fileName.equalsIgnoreCase(".shp")) { return fail("范围文件格式不正确", false); } else { // 1 读取shp文件,获取范围值 JSONObject jsonObject = ShpToolUtils.readShp(floodFile); // 2 获取jsonObject中的范围值 vo.setMinx(jsonObject.getDouble("minX")); vo.setMaxx(jsonObject.getDouble("maxX")); vo.setMiny(jsonObject.getDouble("minY")); vo.setMaxy(jsonObject.getDouble("maxY")); } } // todo: 解析范围文件 根据不同的的格式文件进行不同的解析,获取需要计算的范围值 // 上传格式:.shp/.tiff/.img/.geojson // 重新给vo赋值 // 1 读取shp文件,获取范围值 JSONObject jsonObject = ShpToolUtils.readShp(floodFile); // 2 获取jsonObject中的范围值 vo.setMinx(jsonObject.getDouble("minX")); vo.setMaxx(jsonObject.getDouble("maxX")); vo.setMiny(jsonObject.getDouble("minY")); vo.setMaxy(jsonObject.getDouble("maxY")); } catch (Exception e) { log.error("解析范围文件失败"); if (null == vo.getMinx() || null == vo.getMiny() || null == vo.getMaxx() || null == vo.getMaxy()) { @@ -225,13 +240,40 @@ } String stationFile = vo.getStationFile(); log.info("站点文件shp地址:{}", floodFile); log.info("站点文件shp地址:{}", stationFile); try { // 判断地址不为空 if (StringUtils.isEmpty(stationFile)) { return fail("站点文件shp地址不能为空", false); } // 1 读取shp文件,获取站点坐标值 JSONArray jsonArray = ShpToolUtils.readShpGetLocal(stationFile); System.out.println("jsonArray = " + jsonArray); } catch (Exception e) { log.error("解析站点文件shp失败"); } String stationRainFile = vo.getStationRainFile(); log.info("站点雨量CSV文件地址:{}", floodFile); // TODO: 2024/12/24 根据这些文件的地址,获取文件内容,创建仿真视图 try { // 判断地址不为空 if (StringUtils.isEmpty(stationRainFile)) { return fail("站点雨量CSV文件地址不能为空", false); } // 创建表名 时间戳 String tableName = "station_rain_" + System.currentTimeMillis(); // 1 读取CSV 文件 CsvToSQLiteUtils.readCsvSaveLocal(stationRainFile, tableName); // 获取仿真时间 duration // 获取降雨总量 total } catch (Exception e) { log.error("解析站点雨量CSV文件失败"); } // TODO: 2024/12/24 根据这些文件的地址,获取文件内容,创建仿真视图 try { if (null == vo.getTotal() || vo.getTotal() < 1 || vo.getTotal() > 1000) { return fail("降雨量不能为空,且取值在1~1000之间"); src/main/java/com/se/simu/domain/vo/CreateFilesSimuVo.java
@@ -82,4 +82,7 @@ @ApiModelProperty("站点雨量CSV文件地址") private String stationRainFile; @ApiModelProperty("计算模型类型") private String modelType; } src/main/java/com/se/simu/utils/CsvToSQLiteUtils.java
@@ -10,6 +10,12 @@ import java.nio.file.Paths; import java.sql.*; /** * CSV 到 SQLite 实用程序 * * @author xingjinshuang@smartearth.cn * @date 2024/12/26 */ public class CsvToSQLiteUtils { private static final String DATABASE_URL = "jdbc:sqlite:D:\\0a_project\\simulation\\simuserver\\rainfall.db"; // SQLite数据库路径 @@ -142,4 +148,86 @@ System.err.println("读取CSV或插入数据时出错: " + e.getMessage()); } } /** * 读取 CSV 保存本地 * * @param stationRainFile Station Rain 文件 * @param tableName 表名称 */ public static void readCsvSaveLocal(String stationRainFile, String tableName) { // 1. 创建SQLite数据库连接 try (Connection conn = DriverManager.getConnection("jdbc:sqlite:rainfall.db")) { if (conn != null) { // 2. 创建表(如果不存在) createTableIfNotExists(conn, tableName); // 3. 设置SQLite连接的字符编码为UTF-8 try (Statement stmt = conn.createStatement()) { // 设置SQLite编码为UTF-8 stmt.execute("PRAGMA encoding = 'UTF-8';"); } // 4. 开始事务 conn.setAutoCommit(false); // 5. 读取CSV文件并插入数据 readCsvAndInsertDatas(stationRainFile, conn, tableName); // 6. 提交事务 conn.commit(); System.out.println("数据成功插入到SQLite数据库!"); } } catch (SQLException e) { System.err.println("SQLite连接失败: " + e.getMessage()); } } private static void readCsvAndInsertDatas(String csvFilePath, Connection conn, String tableName) { // 使用 Apache Commons CSV 读取CSV文件 try (Reader reader = new InputStreamReader(Files.newInputStream(Paths.get(csvFilePath)), "GBK")) { Iterable<CSVRecord> records = CSVFormat.DEFAULT .withHeader("雨量站", "降雨量", "经度", "纬度", "datatime") .withSkipHeaderRecord() // 跳过表头 .parse(reader); String insertDataSql = "INSERT INTO " + tableName + " (station_name, rainfall, longitude, latitude, datetime) VALUES (?, ?, ?, ?, ?);"; try (PreparedStatement pstmt = conn.prepareStatement(insertDataSql)) { // 批量大小 int batchSize = 1000; int count = 0; for (CSVRecord record : records) { // 获取每一列的数据 String stationName = record.get("雨量站"); double rainfall = Double.parseDouble(record.get("降雨量")); double longitude = Double.parseDouble(record.get("经度")); double latitude = Double.parseDouble(record.get("纬度")); String datetime = record.get("datatime"); // 设置插入数据的参数 pstmt.setString(1, stationName); pstmt.setDouble(2, rainfall); pstmt.setDouble(3, longitude); pstmt.setDouble(4, latitude); pstmt.setString(5, datetime); // 添加到批处理 pstmt.addBatch(); count++; // 每batchSize条数据执行一次批量插入 if (count % batchSize == 0) { pstmt.executeBatch(); } } // 执行剩余的批量插入 pstmt.executeBatch(); } catch (SQLException e) { System.err.println("批量插入数据时出错: " + e.getMessage()); } } catch (IOException e) { System.err.println("读取CSV或插入数据时出错: " + e.getMessage()); } } } src/main/java/com/se/simu/utils/ShpToolUtils.java
@@ -96,6 +96,72 @@ return json; } /** * 读取 shp get local * * @param strVectorFile str 向量文件 * @return {@link JSONObject} */ public static JSONArray readShpGetLocal(String strVectorFile) { // 注册所有的驱动 ogr.RegisterAll(); // 为了支持中文路径,请添加下面这句代码 gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // 读取数据,这里以ESRI的shp文件为例 String strDriverName = "ESRI Shapefile"; org.gdal.ogr.Driver oDriver = ogr.GetDriverByName(strDriverName); if (oDriver == null) { System.out.println(strDriverName + " 驱动不可用!\n"); return null; } // 打开数据源 DataSource dataSource = oDriver.Open(strVectorFile); if (dataSource == null) { System.out.println("无法打开 Shapefile 文件!"); return null; } Layer layer = dataSource.GetLayer(0); // 获取图层的范围(初步的矩形范围) double[] layerExtent = layer.GetExtent(); System.out.println("初始图层范围:minx:" + layerExtent[0] + ", maxx:" + layerExtent[1] + ", miny:" + layerExtent[2] + ", maxy:" + layerExtent[3]); // 获取图层的空间参考 SpatialReference layerSpatialRef = layer.GetSpatialRef(); // 创建目标空间参考 (EPSG:4326) SpatialReference targetSpatialRef = new SpatialReference(); targetSpatialRef.ImportFromEPSG(4326); // EPSG:4326 是 WGS84 // 创建坐标转换对象 CoordinateTransformation coordTransform = CoordinateTransformation.CreateCoordinateTransformation(layerSpatialRef, targetSpatialRef); // 遍历每个 feature 获取坐标点 for (int i = 0; i < layer.GetFeatureCount(); i++) { Feature feature = layer.GetFeature(i); Geometry geometry = feature.GetGeometryRef(); // 判断几何类型并处理 if (geometry != null) { if (geometry.GetGeometryType() == ogr.wkbPoint) { // 单个点的处理 processPointGeometry(geometry, coordTransform); } else if (geometry.GetGeometryType() == ogr.wkbMultiPoint) { // 多个点的处理 System.out.println("geometry = " + geometry); //processMultiPointGeometry(geometry, coordTransform); } } } // 打印转换后的矩形范围(经纬度) System.out.println("所有点的经纬度矩形范围:minX = " + minX + ", maxX = " + maxX + ", minY = " + minY + ", maxY = " + maxY); return coordinatesArray; } // 处理单个点的几何体 private static void processPointGeometry(Geometry geometry, CoordinateTransformation coordTransform) { double x = geometry.GetX();