java+iClientOpenlayers实现城市内涝积涝模拟内涝模拟演进

程序实现效果图

洪水演进过程

 

一、应用背景 

城市内涝和积涝是一个严重的问题,特别是在气候变化的背景下。为了更好地了解这个问题,模拟城市内涝和积涝是非常重要的。这个过程可以帮助我们预测哪些区域可能会受到影响,以及在发生内涝和积涝时应该如何应对。同时,这个过程也可以帮助我们更好地规划城市建设,以减少内涝和积涝的发生。总的来说,城市内涝和积涝模拟是一个非常有价值的工具,可以帮助我们更好地应对这个问题,使城市更加安全和可持续。

城市内涝和积涝是一个全球性的问题,对城市的可持续发展和居民的生活质量都会产生影响。为了减少这些影响,我们需要采取措施来预测和应对内涝和积涝的发生。城市内涝和积涝模拟可以帮助我们更好地了解这个问题,以便我们在城市规划和应急响应方面做出更加科学和有效的决策。希望未来能够有更多的研究和投入来加强城市内涝和积涝模拟技术,让城市更加安全、可持续和宜居。

此外,还需要加强城市基础设施的建设,例如改善排水系统和城市绿地的规划。同时,也需要进行公众教育,提高居民的环保意识和应对内涝和积涝的能力。只有通过多方面的合作和努力,才能实现城市内涝和积涝的有效管理和缓解。让我们一起为创造更加美好的城市生活而努力。

除了进行城市内涝积涝模拟,我们还需要加强城市基础设施的建设。这包括改善排水系统和城市绿地的规划,以应对极端天气事件。与此同时,公众教育也很重要,我们需要提高居民的环保意识和应对内涝和积涝的能力。只有多方合作和努力,才能实现城市内涝和积涝的有效管理和缓解,让我们共同努力,创造更美好的城市生活。

二、常见城市内涝积涝场景

三、准备网格化的asc地形数据为模型计算提供基础数据(点位百万以上,如果卡顿,可分布式实现负载均衡解决)

四、关键java代码编写

/*
 * Copyright 2021 zdh,
 * [email protected]
 */
package wcontour;

import wcontour.KDTree.Euclidean;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

import static jdk.nashorn.internal.objects.Global.Infinity;

/**
 * Interpolate class - including the functions of interpolation
 *
 * @author zdh
 * @version $Revision: 1.6 $
 */
public class Interpolate {

    // <editor-fold desc="IDW">
    /**
     * Create grid x/y coordinate arrays with x/y delt
     *
     * @param Xlb x of left-bottom
     * @param Ylb y of left-bottom
     * @param Xrt x of right-top
     * @param Yrt y of right-top
     * @param XDelt x delt
     * @param YDelt y delt
     * @return X/Y coordinate arrays
     */
    public static List<double[]> createGridXY_Delt(double Xlb, double Ylb, double Xrt, double Yrt, double XDelt, double YDelt) {
        int i, Xnum, Ynum;
        Xnum = (int) ((Xrt - Xlb) / XDelt + 1);
        Ynum = (int) ((Yrt - Ylb) / YDelt + 1);
        double[] X = new double[Xnum];
        double[] Y = new double[Ynum];
        for (i = 0; i < Xnum; i++) {
            X[i] = Xlb + i * XDelt;
        }
        for (i = 0; i < Ynum; i++) {
            Y[i] = Ylb + i * YDelt;
        }

        List<double[]> values = new ArrayList<>();
        values.add(X);
        values.add(Y);
        return values;
    }

    /**
     * Create grid X/Y coordinate
     *
     * @param Xlb X left bottom 左下 x
     * @param Ylb Y left bottom
     * @param Xrt X right top   右上 x
     * @param Yrt Y right top
     * @param X X coordinate x 坐标
     * @param Y Y coordinate y 坐标
     *
     *  根据x,y 的边界值,在边界值范围内生成一组 x[] 和 一组 y[]
     */
    public static void createGridXY_Num(double Xlb, double Ylb, double Xrt, double Yrt,
            double[] X, double[] Y) {
        System.out.println("Interpolate.createGridXY_Num");
        int i;
        double XDelt, YDelt;
        int Xnum = X.length;
        int Ynum = Y.length;
        XDelt = (Xrt - Xlb) / Xnum;
        YDelt = (Yrt - Ylb) / Ynum;
        for (i = 0; i < Xnum; i++) {
            X[i] = Xlb + i * XDelt;
        }
        for (i = 0; i < Ynum; i++) {
            Y[i] = Ylb + i * YDelt;
        }
    }

    /**
     * 用IDW邻接法插值
     * Interpolation with IDW neighbor method
     *
     * @param SCoords discrete data array
     * @param X grid X array
     * @param Y grid Y array
     * @param NumberOfNearestNeighbors number of nearest neighbors
     * @return grid data
     */
    public static double[][] interpolation_IDW_Neighbor(double[][] SCoords, double[] X, double[] Y,
            int NumberOfNearestNeighbors) {
        int rowNum, colNum, pNum;
        colNum = X.length;
        rowNum = Y.length;
        pNum = SCoords.length;
        double[][] GCoords = new double[rowNum][colNum];
        int i, j, p, l, aP;
        double w, SV, SW, aMin;
        int points;
        points = NumberOfNearestNeighbors;
        Object[][] NW = new Object[2][points];

        //---- Do interpolation
        for (i = 0; i < rowNum; i++) {
            for (j = 0; j < colNum; j++) {
                GCoords[i][j] = -999.0;
                SV = 0;
                SW = 0;
                for (p = 0; p < points; p++) {
                    if (X[j] == SCoords[p][0] && Y[i] == SCoords[p][1]) {
                        GCoords[i][j] = SCoords[p][2];
                        break;
                    } else {
                        w = 1 / (Math.pow(X[j] - SCoords[p][0], 2) + Math.pow(Y[i] - SCoords[p][1], 2));
                        NW[0][p] = w;
                        NW[1][p] = p;
                    }
                }
                if (GCoords[i][j] == -999.0) {
                    for (p = points; p < pNum; p++) {
                        if (Math.pow(X[j] - SCoords[p][0], 2) + Math.pow(Y[i] - SCoords[p][1], 2) == 0) {
                            GCoords[i][j] = SCoords[p][2];
                            break;
                        } else {
                            w = 1 / (Math.pow(X[j] - SCoords[p][0], 2) + Math.pow(Y[i] - SCoords[p][1], 2));
                            aMin = Double.parseDouble(NW[0][0].toString());
                            aP = 0;
                            for (l = 1; l < points; l++) {
                                if (Double.parseDouble(NW[0][l].toString()) < aMin) {
                                    aMin = Double.parseDouble(NW[0][l].toString());
                                    aP = l;
                                }
                            }
                            if (w > aMin) {
                                NW[0][aP] = w;
                                NW[1][aP] = p;
                            }
                        }
                    }
                    if (GCoords[i][j] == -999.0) {
                        for (p = 0; p < points; p++) {
                            SV += Double.parseDouble(NW[0][p].toString()) * SCoords[Integer.parseInt(NW[1][p].toString())][2];
                            SW += Double.parseDouble(NW[0][p].toString());
                        }
                        GCoords[i][j] = SV / SW;
                    }
                }
            }
        }

        //---- Smooth with 5 points
        double s = 0.5;
        for (i = 1; i < rowNum - 1; i++) {
            for (j = 1; j < colNum - 1; j++) {
                GCoords[i][j] = GCoords[i][j] + s / 4 * (GCoords[i + 1][j] + GCoords[i - 1][j]
                        + GCoords[i][j + 1] + GCoords[i][j - 1] - 4 * GCoords[i][j]);
            }
        }

        return GCoords;
    }

    /**
     * 用IDW邻接法插值
     * Interpolation with IDW neighbor method
     *
     * @param SCoords discrete data array
     * @param X grid X array
     * @param Y grid Y array
     * @param NumberOfNearestNeighbors number of nearest neighbors
     * @param unDefData undefine data
     * @return interpolated grid data
     */
    public static double[][] interpolation_IDW_Neighbor(double[][] SCoords, double[] X, double[] Y,
            int NumberOfNearestNeighbors, double unDefData) {
        int rowNum, colNum, pNum;
        colNum = X.length;
        rowNum = Y.length;
        pNum = SCoords.length;
        double[][] GCoords = new double[rowNum][colNum];
        int i, j, p, l, aP;
        double w, SV, SW, aMin;
        int points;
        points = NumberOfNearestNeighbors;
        double[] AllWeights = new double[pNum];
        double[][] NW = new double[2][points];
        int NWIdx;

        //---- Do interpolation with IDW method
        for (i = 0; i < rowNum; i++) {
            for (j = 0; j < colNum; j++) {
                GCoords[i][j] = unDefData;
                SV = 0;
                SW = 0;
                NWIdx = 0;
                for (p = 0; p < pNum; p++) {
                    if (SCoords[p][2] == unDefData) {
                        AllWeights[p] = -1;
                        continue;
                    }
                    if (X[j] == SCoords[p][0] && Y[i] == SCoords[p][1]) {
                        GCoords[i][j] = SCoords[p][2];
                        break;
                    } else {
                        w = 1 / (Math.pow(X[j] - SCoords[p][0], 2) + Math.pow(Y[i] - SCoords[p][1], 2));
                        AllWeights[p] = w;
                        if (NWIdx < points) {
                            NW[0][NWIdx] = w;
                            NW[1][NWIdx] = p;
                        }
                        NWIdx += 1;
                    }
                }

                if (GCoords[i][j] == unDefData) {
                    for (p = 0; p < pNum; p++) {
                        w = AllWeights[p];
                        if (w == -1) {
                            continue;
                        }

                        aMin = NW[0][0];
                        aP = 0;
                        for (l = 1; l < points; l++) {
                            if ((double) NW[0][l] < aMin) {
                                aMin = (double) NW[0][l];
                                aP = l;
                            }
                        }
                        if (w > aMin) {
                            NW[0][aP] = w;
                            NW[1][aP] = p;
                        }
                    }
                    for (p = 0; p < points; p++) {
                        SV += (double) NW[0][p] * SCoords[(int) NW[1][p]][2];
                        SW += (double) NW[0][p];
                    }
                    GCoords[i][j] = SV / SW;
                }
            }
        }

        //---- Smooth with 5 points
        double s = 0.5;
        for (i = 1; i < rowNum - 1; i++) {
            for (j = 1; j < colNum - 1; j++) {
                GCoords[i][j] = GCoords[i][j] + s / 4 * (GCoords[i + 1][j] + GCoords[i - 1][j] + GCoords[i][j + 1]
                        + GCoords[i][j - 1] - 4 * GCoords[i][j]);
            }

        }

        return GCoords;
    }

    /**
     * IDW半径法插值
     *
     * 反距离权重法
     * Interpolation with IDW radius method
     *
     * @param SCoords discrete data array
     * @param X grid X array
     * @param Y grid Y array
     * @param NeededPointNum needed at least point number
     * @param radius search radius
     * @param unDefData undefine data
     * @return interpolated grid data 插值后的网格数据
     */
    public static double[][] interpolation_IDW_Radius(double[][] SCoords, double[] X, double[] Y,
            int NeededPointNum, double radius, double unDefData) {
        System.out.println("Interpolate.interpolation_IDW_Radius");
        int rowNum, colNum, pNum;
        colNum = X.length;
        rowNum = Y.length;
        pNum = SCoords.length;
        double[][] GCoords = new double[rowNum][colNum];
        int i, j, p, vNum;
        double w, SV, SW;
        boolean ifPointGrid;

        //---- Do interpolation
        for (i = 0; i < rowNum; i++) {
            for (j = 0; j < colNum; j++) {
                GCoords[i][j] = unDefData;
                ifPointGrid = false;
                SV = 0;
                SW = 0;
                vNum = 0;
                for (p = 0; p < pNum; p++) {
                    if (SCoords[p][2] == unDefData) {
                        continue;
                    }

                    if (SCoords[p][0] < X[j] - radius || SCoords[p][0] > X[j] + radius || SCoords[p][1] < Y[i] - radius
                            || SCoords[p][1] > Y[i] + radius) {
                        continue;
                    }

                    if (X[j] == SCoords[p][0] && Y[i] == SCoords[p][1]) {
                        GCoords[i][j] = SCoords[p][2];
                        ifPointGrid = true;
                        break;
                    } else if (Math.sqrt(Math.pow(X[j] - SCoords[p][0], 2)
                            + Math.pow(Y[i] - SCoords[p][1], 2)) <= radius) {
                        w = 1 / (Math.pow(X[j] - SCoords[p][0], 2) + Math.pow(Y[i] - SCoords[p][1], 2));
                        SW = SW + w;
                        SV = SV + SCoords[p][2] * w;
                        vNum += 1;
                    }
                }

                if (!ifPointGrid) {
                    if (vNum >= NeededPointNum) {
                        GCoords[i][j] = SV / SW;
                    }
                }
            }
        }

        //---- Smooth with 5 points
        double s = 0.5;
        for (i = 1; i < rowNum - 1; i++) {
            for (j = 1; j < colNum - 2; j++) {
                if (GCoords[i][j] == unDefData || GCoords[i + 1][j] == unDefData || GCoords[i - 1][j]
                        == unDefData || GCoords[i][j + 1] == unDefData || GCoords[i][j - 1] == unDefData) {
                    continue;
                }
                GCoords[i][j] = GCoords[i][j] + s / 4 * (GCoords[i + 1][j] + GCoords[i - 1][j] + GCoords[i][j + 1]
                        + GCoords[i][j - 1] - 4 * GCoords[i][j]);
            }
        }

        return GCoords;
    }

    /**
     * Interpolation with IDW radius method - using KDTree for fast search
     *
     * @param stData discrete data array
     * @param xGrid grid X array
     * @param yGrid grid Y array
     * @param neededPointNum needed at least point number
     * @param radius search radius
     * @param fillValue Fill value
     * @return interpolated grid data
     */
    public static double[][] idw_Radius_kdTree(double[][] stData, double[] xGrid, double[] yGrid,
            int neededPointNum, double radius, double fillValue) {
        Euclidean<double[]> kdtree = new Euclidean<>(2);
        int l = stData.length;

        for (int i = 0; i < l; i++) {
            //Avoid key repeat
            double nodex = stData[i][0] + (Math.random() * 10e-5);
            double nodey = stData[i][1] + (Math.random() * 10e-5);
            kdtree.addPoint(new double[]{nodex, nodey}, new double[]{stData[i][0], stData[i][1], stData[i][2]});
        }

        int w = xGrid.length;
        int h = yGrid.length;

        double[][] grid = new double[h][w];
        for (int i = 0; i < h; i++) {
            double yValue = yGrid[i];
            for (int j = 0; j < w; j++) {
                double xValue = xGrid[j];
                List<double[]> nearPntList = kdtree.ballSearch(new double[]{xValue, yValue}, radius);
                int nearSize = nearPntList.size();
                if (nearSize < neededPointNum) {
                    grid[i][j] = fillValue;
                    continue;
                }

                double z_sum = 0.0;
                double weight_sum = 0.0;
                for (int k = 0; k < nearSize; k++) {
                    double[] xyz = nearPntList.get(k);
                    double distance = Point2D.Double.distance(xValue, yValue, xyz[0], xyz[1]);
                    if (distance <= radius && distance > 0) {
                        weight_sum += radius / distance;
                        z_sum += radius / distance * xyz[2];
                    } else if (Math.abs(distance) < 0.0001) {  //Using point value when the grid is point
                        z_sum = xyz[2];
                        weight_sum = 1.0f;
                        break;
                    }
                }
                if (Math.abs(weight_sum) < 0.0001) {
                    grid[i][j] = fillValue;
                } else {
                    grid[i][j] = z_sum / weight_sum;
                }
            }
        }
        return grid;
    }

    /**
     * Interpolate from grid data
     *
     * @param GridData input grid data
     * @param X input x coordinates
     * @param Y input y coordinates
     * @param unDefData undefine data
     * @param nX output x coordinate
     * @param nY output y coordinate
     * @return output grid data
     */
    public static double[][] interpolation_Grid(double[][] GridData, double[] X, double[] Y, double unDefData,
            double[] nX, double[] nY) {
        int nxNum = X.length * 2 - 1;
        int nyNum = Y.length * 2 - 1;
        nX = new double[nxNum];
        nY = new double[nyNum];
        double[][] nGridData = new double[nyNum][nxNum];
        int i, j;
        double a, b, c, d;
        List<Double> dList;
        for (i = 0; i < nxNum; i++) {
            if (i % 2 == 0) {
                nX[i] = X[i / 2];
            } else {
                nX[i] = (X[(i - 1) / 2] + X[(i - 1) / 2 + 1]) / 2;
            }
        }
        for (i = 0; i < nyNum; i++) {
            if (i % 2 == 0) {
                nY[i] = Y[i / 2];
            } else {
                nY[i] = (Y[(i - 1) / 2] + Y[(i - 1) / 2 + 1]) / 2;
            }
            for (j = 0; j < nxNum; j++) {
                if (i % 2 == 0 && j % 2 == 0) {
                    nGridData[i][j] = GridData[i / 2][j / 2];
                } else if (i % 2 == 0 && j % 2 != 0) {
                    a = GridData[i / 2][(j - 1) / 2];
                    b = GridData[i / 2][(j - 1) / 2 + 1];
                    dList = new ArrayList<>();
                    if (a != unDefData) {
                        dList.add(a);
                    }
                    if (b != unDefData) {
                        dList.add(b);
                    }

                    if (dList.isEmpty()) {
                        nGridData[i][j] = unDefData;
                    } else if (dList.size() == 1) {
                        nGridData[i][j] = dList.get(0);
                    } else {
                        nGridData[i][j] = (a + b) / 2;
                    }
                } else if (i % 2 != 0 && j % 2 == 0) {
                    a = GridData[(i - 1) / 2][j / 2];
                    b = GridData[(i - 1) / 2 + 1][j / 2];
                    dList = new ArrayList<>();
                    if (a != unDefData) {
                        dList.add(a);
                    }
                    if (b != unDefData) {
                        dList.add(b);
                    }

                    if (dList.isEmpty()) {
                        nGridData[i][j] = unDefData;
                    } else if (dList.size() == 1) {
                        nGridData[i][j] = dList.get(0);
                    } else {
                        nGridData[i][j] = (a + b) / 2;
                    }
                } else {
                    a = GridData[(i - 1) / 2][(j - 1) / 2];
                    b = GridData[(i - 1) / 2][(j - 1) / 2 + 1];
                    c = GridData[(i - 1) / 2 + 1][(j - 1) / 2 + 1];
                    d = GridData[(i - 1) / 2 + 1][(j - 1) / 2];
                    dList = new ArrayList<>();
                    if (a != unDefData) {
                        dList.add(a);
                    }
                    if (b != unDefData) {
                        dList.add(b);
                    }
                    if (c != unDefData) {
                        dList.add(c);
                    }
                    if (d != unDefData) {
                        dList.add(d);
                    }

                    if (dList.isEmpty()) {
                        nGridData[i][j] = unDefData;
                    } else if (dList.size() == 1) {
                        nGridData[i][j] = dList.get(0);
                    } else {
                        double aSum = 0;
                        for (double dd : dList) {
                            aSum += dd;
                        }
                        nGridData[i][j] = aSum / dList.size();
                    }
                }
            }
        }

        return nGridData;
    }

    // </editor-fold>
    // <editor-fold desc="Cressman">
    /**
     * Cressman analysis
     *
     * @param stationData station data array - x,y,value
     * @param X x array
     * @param Y y array
     * @param unDefData undefine data
     * @return grid data
     */
    public static double[][] cressman(double[][] stationData, double[] X, double[] Y, double unDefData) {
        List<Double> radList = new ArrayList<>();
        radList.add(10.0);
        radList.add(7.0);
        radList.add(4.0);
        radList.add(2.0);
        radList.add(1.0);

        return cressman(stationData, X, Y, unDefData, radList);
    }

    /**
     * Cressman analysis
     *
     * @param stData station data array - x,y,value
     * @param X x array
     * @param Y y array
     * @param unDefData undefine data
     * @param radList radii list
     * @return result grid data
     */
    public static double[][] cressman(double[][] stData, double[] X, double[] Y, double unDefData, List<Double> radList) {
        int xNum = X.length;
        int yNum = Y.length;
        int pNum = stData.length;
        double[][] gridData = new double[yNum][xNum];
        int irad = radList.size();
        int i, j;

        //Loop through each stn report and convert stn lat/lon to grid coordinates
        double xMin = X[0];
        double xMax = X[X.length - 1];
        double yMin = Y[0];
        double yMax = Y[Y.length - 1];
        double xDelt = X[1] - X[0];
        double yDelt = Y[1] - Y[0];
        double x, y;
        double sum = 0, total = 0;
        int stNum = 0;
        double[][] stationData = new double[pNum][3];
        for (i = 0; i < pNum; i++) {
            x = stData[i][0];
            y = stData[i][1];
            stationData[i][0] = (x - xMin) / xDelt;
            stationData[i][1] = (y - yMin) / yDelt;
            stationData[i][2] = stData[i][2];
            if (stationData[i][2] != unDefData) {
                total += stationData[i][2];
                stNum += 1;
            }
        }
        total = total / stNum;

        //Initial the arrays
        double HITOP = -999900000000000000000.0;
        double HIBOT = 999900000000000000000.0;
        double[][] TOP = new double[yNum][xNum];
        double[][] BOT = new double[yNum][xNum];
        for (i = 0; i < yNum; i++) {
            for (j = 0; j < xNum; j++) {
                TOP[i][j] = HITOP;
                BOT[i][j] = HIBOT;
            }
        }

        //Initial grid values are average of station reports within the first radius
        Double rad;
        if (radList.size() > 0) {
            rad = radList.get(0);
        } else {
            rad = 4.0;
        }
        for (i = 0; i < yNum; i++) {
            y = (double) i;
            yMin = y - rad;
            yMax = y + rad;
            for (j = 0; j < xNum; j++) {
                x = (double) j;
                xMin = x - rad;
                xMax = x + rad;
                stNum = 0;
                sum = 0;
                for (int s = 0; s < pNum; s++) {
                    double val = stationData[s][2];
                    double sx = stationData[s][0];
                    double sy = stationData[s][1];
                    if (sx < 0 || sx >= xNum - 1 || sy < 0 || sy >= yNum - 1) {
                        continue;
                    }

                    if (val == unDefData || sx < xMin || sx > xMax || sy < yMin || sy > yMax) {
                        continue;
                    }

                    double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2));
                    if (dis > rad) {
                        continue;
                    }

                    sum += val;
                    stNum += 1;
                    if (TOP[i][j] < val) {
                        TOP[i][j] = val;
                    }
                    if (BOT[i][j] > val) {
                        BOT[i][j] = val;
                    }
                }
                if (stNum == 0) {
                    gridData[i][j] = unDefData;
                } else {
                    gridData[i][j] = sum / stNum;
                }
            }
        }

        //Perform the objective analysis
        for (int p = 0; p < irad; p++) {
            rad = radList.get(p);
            for (i = 0; i < yNum; i++) {
                y = (double) i;
                yMin = y - rad;
                yMax = y + rad;
                for (j = 0; j < xNum; j++) {
                    if (gridData[i][j] == unDefData) {
                        continue;
                    }

                    x = (double) j;
                    xMin = x - rad;
                    xMax = x + rad;
                    sum = 0;
                    double wSum = 0;
                    for (int s = 0; s < pNum; s++) {
                        double val = stationData[s][2];
                        double sx = stationData[s][0];
                        double sy = stationData[s][1];
                        if (sx < 0 || sx >= xNum - 1 || sy < 0 || sy >= yNum - 1) {
                            continue;
                        }

                        if (val == unDefData || sx < xMin || sx > xMax || sy < yMin || sy > yMax) {
                            continue;
                        }

                        double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2));
                        if (dis > rad) {
                            continue;
                        }

                        int i1 = (int) sy;
                        int j1 = (int) sx;
                        int i2 = i1 + 1;
                        int j2 = j1 + 1;
                        double a = gridData[i1][j1];
                        double b = gridData[i1][j2];
                        double c = gridData[i2][j1];
                        double d = gridData[i2][j2];
                        List<Double> dList = new ArrayList<>();
                        if (a != unDefData) {
                            dList.add(a);
                        }
                        if (b != unDefData) {
                            dList.add(b);
                        }
                        if (c != unDefData) {
                            dList.add(c);
                        }
                        if (d != unDefData) {
                            dList.add(d);
                        }

                        double calVal;
                        if (dList.isEmpty()) {
                            continue;
                        } else if (dList.size() == 1) {
                            calVal = dList.get(0);
                        } else if (dList.size() <= 3) {
                            double aSum = 0;
                            for (double dd : dList) {
                                aSum += dd;
                            }
                            calVal = aSum / dList.size();
                        } else {
                            double x1val = a + (c - a) * (sy - i1);
                            double x2val = b + (d - b) * (sy - i1);
                            calVal = x1val + (x2val - x1val) * (sx - j1);
                        }
                        double eVal = val - calVal;
                        double w = (rad * rad - dis * dis) / (rad * rad + dis * dis);
                        sum += eVal * w;
                        wSum += w;
                    }
                    if (wSum < 0.000001) {
                        gridData[i][j] = unDefData;
                    } else {
                        double aData = gridData[i][j] + sum / wSum;
                        gridData[i][j] = Math.max(BOT[i][j], Math.min(TOP[i][j], aData));
                    }
                }
            }
        }

        //Return
        return gridData;
    }

    /**
     * Cressman analysis - KDTree
     *
     * @param stationData station data array - x,y,value
     * @param X x array
     * @param Y y array
     * @param unDefData undefine data
     * @return grid data
     */
    public static double[][] cressman_kdTree(double[][] stationData, double[] X, double[] Y, double unDefData) {
        List<Double> radList = new ArrayList<>();
        radList.add(10.0);
        radList.add(7.0);
        radList.add(4.0);
        radList.add(2.0);
        radList.add(1.0);

        return cressman_kdTree(stationData, X, Y, unDefData, radList);
    }

    /**
     * Cressman analysis - KDTree
     *
     * @param stData station data array - x,y,value
     * @param X x array
     * @param Y y array
     * @param unDefData undefine data
     * @param radList radii list
     * @return result grid data
     */
    public static double[][] cressman_kdTree(double[][] stData, double[] X, double[] Y, double unDefData, List<Double> radList) {
        int xNum = X.length;
        int yNum = Y.length;
        int pNum = stData.length;

        double[][] gridData = new double[yNum][xNum];
        int irad = radList.size();
        int i, j;

        //Loop through each stn report and convert stn lat/lon to grid coordinates
        double xMin = X[0];
        double xMax = X[X.length - 1];
        double yMin = Y[0];
        double yMax = Y[Y.length - 1];
        double xDelt = X[1] - X[0];
        double yDelt = Y[1] - Y[0];
        double x, y;
        double sum = 0, total = 0;
        int stNum = 0;
        double[][] stationData = new double[pNum][3];
        for (i = 0; i < pNum; i++) {
            x = stData[i][0];
            y = stData[i][1];
            stationData[i][0] = (x - xMin) / xDelt;
            stationData[i][1] = (y - yMin) / yDelt;
            stationData[i][2] = stData[i][2];
            if (stationData[i][2] != unDefData) {
                total += stationData[i][2];
                stNum += 1;
            }
        }
        total = total / stNum;

        Euclidean<double[]> kdTree = new Euclidean<>(2);
        for(i = 0; i < pNum; i++){
           kdTree.addPoint(new double[]{stationData[i][0], stationData[i][1]}, stationData[i]);
        }

        //Initial the arrays
        double HITOP = -999900000000000000000.0;
        double HIBOT = 999900000000000000000.0;
        double[][] TOP = new double[yNum][xNum];
        double[][] BOT = new double[yNum][xNum];
        for (i = 0; i < yNum; i++) {
            for (j = 0; j < xNum; j++) {
                TOP[i][j] = HITOP;
                BOT[i][j] = HIBOT;
            }
        }

        //Initial grid values are average of station reports within the first radius
        double rad;
        if (radList.size() > 0) {
            rad = radList.get(0);
        } else {
            rad = 4;
        }
        for (i = 0; i < yNum; i++) {
            y = (double) i;
            yMin = y - rad;
            yMax = y + rad;
            for (j = 0; j < xNum; j++) {
                x = (double) j;
                xMin = x - rad;
                xMax = x + rad;
                stNum = 0;
                sum = 0;
                ArrayList<double[]> neighbours = kdTree.ballSearch(new double[]{x,y}, rad*rad);
                for (double[] station: neighbours) {
                    double val = station[2];
                    double sx = station[0];
                    double sy = station[1];
                    if (sx < 0 || sx >= xNum - 1 || sy < 0 || sy >= yNum - 1) {
                        continue;
                    }

                    if (val == unDefData || sx < xMin || sx > xMax || sy < yMin || sy > yMax) {
                        continue;
                    }

                    double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2));
                    if (dis > rad) {
                        continue;
                    }

                    sum += val;
                    stNum += 1;
                    if (TOP[i][j] < val) {
                        TOP[i][j] = val;
                    }
                    if (BOT[i][j] > val) {
                        BOT[i][j] = val;
                    }
                }

                if (stNum == 0) {
                    gridData[i][j] = unDefData;
                    //gridData[i, j] = total;
                } else {
                    gridData[i][j] = sum / stNum;
                }
            }
        }

        //Perform the objective analysis
        for (int p = 0; p < irad; p++) {
            rad = radList.get(p);
            for (i = 0; i < yNum; i++) {
                y = (double) i;
                yMin = y - rad;
                yMax = y + rad;
                for (j = 0; j < xNum; j++) {
                    if (gridData[i][j] == unDefData) {
                        continue;
                    }

                    x = (double) j;
                    xMin = x - rad;
                    xMax = x + rad;
                    sum = 0;
                    double wSum = 0;
                    ArrayList<double[]> neighbours = kdTree.ballSearch(new double[]{x,y}, rad*rad);
                    for(double[] station: neighbours){
                       double val = station[2];
                        double sx = station[0];
                        double sy = station[1];
                        if (sx < 0 || sx >= xNum - 1 || sy < 0 || sy >= yNum - 1) {
                            continue;
                        }

                        if (val == unDefData || sx < xMin || sx > xMax || sy < yMin || sy > yMax) {
                            continue;
                        }

                        double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2));
                        if (dis > rad) {
                            continue;
                        }

                        int i1 = (int) sy;
                        int j1 = (int) sx;
                        int i2 = i1 + 1;
                        int j2 = j1 + 1;
                        double a = gridData[i1][j1];
                        double b = gridData[i1][j2];
                        double c = gridData[i2][j1];
                        double d = gridData[i2][j2];
                        List<Double> dList = new ArrayList<>();
                        if (a != unDefData) {
                            dList.add(a);
                        }
                        if (b != unDefData) {
                            dList.add(b);
                        }
                        if (c != unDefData) {
                            dList.add(c);
                        }
                        if (d != unDefData) {
                            dList.add(d);
                        }

                        double calVal;
                        if (dList.isEmpty()) {
                            continue;
                        } else if (dList.size() == 1) {
                            calVal = dList.get(0);
                        } else if (dList.size() <= 3) {
                            double aSum = 0;
                            for (double dd : dList) {
                                aSum += dd;
                            }
                            calVal = aSum / dList.size();
                        } else {
                            double x1val = a + (c - a) * (sy - i1);
                            double x2val = b + (d - b) * (sy - i1);
                            calVal = x1val + (x2val - x1val) * (sx - j1);
                        }
                        double eVal = val - calVal;
                        double w = (rad * rad - dis * dis) / (rad * rad + dis * dis);
                        sum += eVal * w;
                        wSum += w;
                    }

                    if (wSum < 0.000001) {
                        gridData[i][j] = unDefData;
                    } else {
                        double aData = gridData[i][j] + sum / wSum;
                        gridData[i][j] = Math.max(BOT[i][j], Math.min(TOP[i][j], aData));
                    }
                }
            }
        }

        //Return
        return gridData;
    }

    // </editor-fold>
    // <editor-fold desc="Others">
    /**
     * Assign point value to grid value
     *
     * @param SCoords point value array
     * @param X x coordinate
     * @param Y y coordinate
     * @param unDefData undefine value
     * @return grid data
     */
    public static double[][] assignPointToGrid(double[][] SCoords, double[] X, double[] Y,
            double unDefData) {
        int rowNum, colNum, pNum;
        colNum = X.length;
        rowNum = Y.length;
        pNum = SCoords.length;
        double[][] GCoords = new double[rowNum][colNum];
        double dX = X[1] - X[0];
        double dY = Y[1] - Y[0];
        int[][] pNums = new int[rowNum][colNum];

        for (int i = 0; i < rowNum; i++) {
            for (int j = 0; j < colNum; j++) {
                pNums[i][j] = 0;
                GCoords[i][j] = 0.0;
            }
        }

        for (int p = 0; p < pNum; p++) {
            if (doubleEquals(SCoords[p][2], unDefData)) {
                continue;
            }

            double x = SCoords[p][0];
            double y = SCoords[p][1];
            if (x < X[0] || x > X[colNum - 1]) {
                continue;
            }
            if (y < Y[0] || y > Y[rowNum - 1]) {
                continue;
            }

            int j = (int) ((x - X[0]) / dX);
            int i = (int) ((y - Y[0]) / dY);
            pNums[i][j] += 1;
            GCoords[i][j] += SCoords[p][2];
        }

        for (int i = 0; i < rowNum; i++) {
            for (int j = 0; j < colNum; j++) {
                if (pNums[i][j] == 0) {
                    GCoords[i][j] = unDefData;
                } else {
                    GCoords[i][j] = GCoords[i][j] / pNums[i][j];
                }
            }
        }

        return GCoords;
    }

    private static boolean doubleEquals(double a, double b) {
        //if (Math.Abs(a - b) < 0.000001)
        if (Math.abs(a / b - 1) < 0.00000000001) {
            return true;
        } else {
            return false;
        }
    }
    // </editor-fold>
}
//getAscGeoJsonByCIdxSim
//http://localhost:8145/api/getAscGeoJsonByCIdxSim?rowInterval=868&rowIntervalIdxNum=0&crowIntervalIdx=0&rainVal=300&SurfaceInfiltration=0.6&vegetation=0.5
/**
 * 索引从0开始
 * @param rowInterval
 * @param rowIntervalIdxNum
 * @param crowIntervalIdx
 * @return
 */
@GetMapping("/getAscGeoJsonByCIdxSim")
public String getAscGeoJsonByCIdxSim(int rowInterval,int rowIntervalIdxNum,int crowIntervalIdx,double rainVal,double SurfaceInfiltration,double vegetation) {
    String ascGeoJson = ascGeo.getAscGeoJsonByCIdxSim(rowInterval,rowIntervalIdxNum,crowIntervalIdx,rainVal,SurfaceInfiltration,vegetation);
    return ascGeoJson;
}
五、模型调用生成的结果数据为geojson

六、前端配置接入模型生成的成果geojson实现模拟洪水演进关键代码

<template>
  <div class="layerPanel">
    <div v-if="isPanelShow" class="layerPanel-content">
      <el-container>
        <el-header style="height: 30px">城市内涝积涝模拟计算</el-header>
        <el-main>
          <div>
            <div style="margin: 3px">
              <span>降雨量(mm):</span>
              <el-input v-model= 'RainVal' style="width: 90%;" clearable></el-input>
            </div>
            <div style="margin: 3px">
              <span>降雨持续时间(分钟):</span>
              <el-input v-model= 'IntervalTime' style="width: 90%;" clearable></el-input>
            </div>
            <div style="margin: 3px">
              <span>地表下渗系数:</span>
              <el-input v-model= 'SurfaceInfiltration' style="width: 90%;" clearable></el-input>
            </div>
            <div style="margin: 3px">
              <span>植被系数:</span>
              <el-input v-model= 'vegetation' style="width: 90%;" clearable></el-input>
            </div>
            <div style="margin: 3px">
              <span>模拟计算:</span>
              <el-button type="primary" round @click="simulationCalculate">计算</el-button>
              <el-button type="primary" round @click="FloodProgress">洪水演进</el-button>
            </div>
          </div>
        </el-main>
      </el-container>
    </div>
    <div class="layer-collapse" @click="layersPanelCollapse">
      <i class="layerlist"></i>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      layers: 11,
      isPanelShow: false,
      clayersInfo: [],
      opacityValue: 100,
      RainVal: 300,
      IntervalTime: 30,
      SurfaceInfiltration: 0.1,
      vegetation: 0.5,
      count:0
    }
  },
  mounted () {

  },
  methods: {
    layersPanelCollapse () {
      this.isPanelShow = !this.isPanelShow
    },
    simulationCalculate(){
      this.$emit("WaterDiffSimulation", this.RainVal,this.IntervalTime,this.SurfaceInfiltration,this.vegetation)
    },
    FloodProgress () {
      let _this = this;
      if(this.count==10){
        this.count=0
        this.$emit("FloodProgress",9)
        return
      }else {
        setTimeout(function () {
          _this.FloodProgress()
        },1000)
      }
      this.$emit("FloodProgress",this.count)
      this.count+=1
    }
  },
  props: {
    startLonLat: Object
  }
}
</script>

<style lang="less" scoped>
@import "./assets/css/index";
</style>

七、模拟展示效果(可调整降雨量、下渗系数等参数,后续版本升级加入更多参数调校率定,技术合作交流qq:2401315930)

 

 如果对您有所帮助,请打赏点赞支持!

猜你喜欢

转载自blog.csdn.net/weixin_42496466/article/details/130583197
今日推荐