@xingjs@20241226@添加查询管线工具类,修改解决查询站点接口token存在无法获取的情况,解决后可正常获取token,并查询出需要的站点;解析shp文件获取站点范围;新增把降水CSV文件内容解析保存到数据库中
已修改4个文件
211 ■■■■■ 文件已修改
src/main/java/com/se/simu/controller/SimuController.java 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/simu/domain/vo/CreateFilesSimuVo.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/simu/utils/CsvToSQLiteUtils.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/se/simu/utils/ShpToolUtils.java 66 ●●●●● 补丁 | 查看 | 原始文档 | 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,9 +210,16 @@
        String floodFile = vo.getFloodFile();
        log.info("范围文件地址:{}", floodFile);
        try {
            // todo: 解析范围文件 根据不同的的格式文件进行不同的解析,获取需要计算的范围值
            //  上传格式:.shp/.tiff/.img/.geojson
            //  重新给vo赋值
            // 判断地址不为空
            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中的范围值
@@ -217,6 +227,11 @@
            vo.setMaxx(jsonObject.getDouble("maxX"));
            vo.setMiny(jsonObject.getDouble("minY"));
            vo.setMaxy(jsonObject.getDouble("maxY"));
                }
            }
            // todo: 解析范围文件 根据不同的的格式文件进行不同的解析,获取需要计算的范围值
            //  上传格式:.shp/.tiff/.img/.geojson
            //  重新给vo赋值
        } 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();