基于DEM模拟淹没区域随时间推演的实现研究

最近被逼着实现模拟闸口泄洪以后对下游淹没范围的影响程序,要求体现随着时间的推移,淹没区域发生变化的效果。于是自己琢磨了这个算法,因为不是水利水文相关专业出身,所以此处没有考虑到水汽蒸发、土壤、植被、岩石等要素,从地形一个因素上进行考虑,引入数字高程模型作为计算依据,该算法还存在很多疏漏之处,欢迎评论指正。

基本思路是将大坝地址作为初始点,不断向周围8领域扩散,搜索能够被淹没的像素点,标记被淹没。重复以上过程,直到整个dem区域计算完毕。
这里写图片描述
其中P(i,j)作为原始扩散点,搜索其周围八个像素,满足条件C则标记为淹没点,其中条件C定义如下:
1.其高程小于特定淹没高度
2.其高程小于P(i,j)的高程
以上两个条件满足其一即可。

被标记为淹没点的像素记录下来,作为下一轮的原始点继续进行八领域扩散计算。

为了体现时间推演的效果,该算法中添加了FloodLevel变量用于记录每个淹没点的淹没层级,比如起始点大坝地址的FloodLevel为1,其周围淹没点的FloodLevel为2,再次扩散的淹没点FloodLevel为3,依此类推,最后生成一张FloodLevel栅格图,其值大于0的则认为被淹没区域,而FloodLevel值不同代表不同时间点新增的淹没区:
这里写图片描述
从图中可以看出,该方法在平原地区扩散呈现方形边界,这并不符合实际水流的扩散方式,实际水流入平原应该呈现一种类似圆形的扩散图形。
这里写图片描述
这是比较理想的状态,即不考虑平原地区每个像素点之间高程的微小差别。

呈现方形扩散,而不是圆形扩散的原因是八领域扩散方法每次计算FloodLevel时都是在原始点的基础上加1,而没有考虑到每个点离中心点的距离不一样,而且每次计算时,中心点的位置发生了改变,而类似水波纹的同心圆状扩散的中心点位置是一样的。
这里写图片描述
算法改进的基本思路是每次计算FloodLevel时,不再是在上一个点的FloodLevel基础上加1,而是顺藤摸瓜找到最原始的点,然后计算距原始点的距离S,实际的FloodLevel为原始点的FloodLevel+S。

原始点的寻找

如下图所示,下游的所有点都应该把图中红色点位置作为原始点:
这里写图片描述
如下图所示,P1点的原始点应该是P2,而不是P3,原因是P1和P3之间隔着未被淹没的地区(黑色代表未被淹没区),水不可能越过未被淹没的点直线到达新的点,画面彩色部分的左上角为大坝位置(图中黄色直线标注)。
这里写图片描述
所以寻找原始点的方法为,搜索其父节点的原始点(父节点为扩充该像素的中心点),判断该像素和这个原始点中间是否隔着未被淹没的像素,如果没有则继续搜素这个原始点的原始点,如果有则把父节点作为原始点停止搜素,依此类推,直到找到大坝地址或者找到最终原始点。

判断地图上任意两个像素中间是否隔着未被淹没的像素

需要找到这两个像素点中间相隔的像素点,然后依此判定这些像素点是否被淹没,有一个未被淹没则返回false,退出循环。
此处认为八领域内所有像素都是和中心点相邻的,所以像如下图中红色的两个点认为相邻。
这里写图片描述
如下图所示,图中两个红色方格的中间相隔像素为黄色的方格:
这里写图片描述
其计算的方法为:
1.判断两个像素分别在x、y轴方向上相差的距离(即像素个数)
2.选择上一步中相差距离最大的那个方向作为基准方向
3.在基准方向上由起始点一个像素一个像素的移动,计算出对应的另一个方向的像素位置,两个方向的像素位置合起来定义了一个点的位置
4.重复步骤3得出所有中间点

代码请见:
https://blog.csdn.net/wqy248/article/details/87856722

计算结果体现了良好的效果:
这里写图片描述
上图中大坝起始点的第一处水流向拐弯处可以看出较上次计算有了明显的改观,水的前沿部分形状开始随着水流方向的改变而改变:
这里写图片描述

这里写图片描述

这里写图片描述

  • 0
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
基于DEM模拟淹没区域随时推演需要使用到一些地形数据处理和可视化库,比如GDAL和Matplotlib等。以下是一个Python示例代码,可以帮助您实现基于DEM模拟淹没区域随时推演: ```python import gdal import numpy as np import matplotlib.pyplot as plt # 加载DEM数据 dem_path = 'dem.tif' dem_ds = gdal.Open(dem_path) dem_band = dem_ds.GetRasterBand(1) dem_data = dem_band.ReadAsArray().astype(np.float32) nodata = dem_band.GetNoDataValue() # 设置水位高度和时步长 water_level = 10.0 time_step = 1.0 # 根据DEM数据和水位高度,计算淹没区域 flood_data = np.where(dem_data > water_level, dem_data - water_level, 0.0) # 进行时推演 for i in range(10): # 根据时步长和当前淹没区域,计算下一时刻的淹没区域 flood_data = np.where(dem_data > water_level, flood_data + time_step, flood_data) # 可视化当前时刻的淹没区域 plt.imshow(flood_data, cmap='Blues') plt.colorbar() plt.title('Flooded Area at Time Step ' + str(i)) plt.show() ``` 以上代码示例中,首先通过GDAL库加载了DEM数据,并根据设定的水位高度计算了初始的淹没区域。然后使用一个循环,每次根据时步长和当前淹没区域,计算下一时刻的淹没区域。最后,使用Matplotlib库可视化了每个时刻的淹没区域。 需要注意的是,以上示例代码仅仅是一个简单的演示,实际情况中需要考虑更多的因素,比如水流、地形变化等。同时,也需要根据具体的DEM数据格式和分辨率做出相应的调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值