程序实现效果图
洪水演进过程
一、应用背景
城市内涝和积涝是一个严重的问题,特别是在气候变化的背景下。为了更好地了解这个问题,模拟城市内涝和积涝是非常重要的。这个过程可以帮助我们预测哪些区域可能会受到影响,以及在发生内涝和积涝时应该如何应对。同时,这个过程也可以帮助我们更好地规划城市建设,以减少内涝和积涝的发生。总的来说,城市内涝和积涝模拟是一个非常有价值的工具,可以帮助我们更好地应对这个问题,使城市更加安全和可持续。
城市内涝和积涝是一个全球性的问题,对城市的可持续发展和居民的生活质量都会产生影响。为了减少这些影响,我们需要采取措施来预测和应对内涝和积涝的发生。城市内涝和积涝模拟可以帮助我们更好地了解这个问题,以便我们在城市规划和应急响应方面做出更加科学和有效的决策。希望未来能够有更多的研究和投入来加强城市内涝和积涝模拟技术,让城市更加安全、可持续和宜居。
此外,还需要加强城市基础设施的建设,例如改善排水系统和城市绿地的规划。同时,也需要进行公众教育,提高居民的环保意识和应对内涝和积涝的能力。只有通过多方面的合作和努力,才能实现城市内涝和积涝的有效管理和缓解。让我们一起为创造更加美好的城市生活而努力。
除了进行城市内涝积涝模拟,我们还需要加强城市基础设施的建设。这包括改善排水系统和城市绿地的规划,以应对极端天气事件。与此同时,公众教育也很重要,我们需要提高居民的环保意识和应对内涝和积涝的能力。只有多方合作和努力,才能实现城市内涝和积涝的有效管理和缓解,让我们共同努力,创造更美好的城市生活。
二、常见城市内涝积涝场景
三、准备网格化的asc地形数据为模型计算提供基础数据(点位百万以上,如果卡顿,可分布式实现负载均衡解决)
四、关键java代码编写
/* * Copyright 2021 zdh, * zdh@gmail.com */ 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)
如果对您有所帮助,请打赏点赞支持!