基于DEM的降雨淹没算法

数字高程模型(Digital Elevation Model),简称DEM,是通过有限的地形高程数据实现对地面地形的数字化模拟(即地形表面形态的数字化表达),它是用一组有序数值阵列形式表示地面高程的一种实体地面模型,是 数字地形模型(Digital Terrain Model,简称DTM)的一个分支,其它各种地形特征值均可由此派生。
一般认为,DTM是描述包括高程在内的各种地貌因子,如坡度、坡向、坡度变化率等因子在内的线性和非线性组合的空间分布,其中DEM是零阶单纯的单项数字地貌模型,其他如坡度、坡向及坡度变化率等地貌特性可在DEM的基础上派生。

        因为最近接了一个计算降雨时洼地汇水情况的任务,便苦逼的写下了这个算法。因为对GIS相关知识以前并没有过了解,因此算法可能存在诸多疏漏或错误欢迎评论指正。本算法只是一个理想化模型的demo,不包括地表渗水,蒸发等因素。此外,算法中使用的DEM并不是C#中标准的ArcGis相关类,而是自己写的伪代码(偷点懒,先把算法赶出来再说- -)。

       本算法从区域的最低点开始,不断向四周递归的淹没临近栅格。使用List来保存最低点数据(从最低到第二低到第三低....),将本次淹没点周围的栅格加入List,直到已淹没的n个栅格能够容纳该区域内的降水总体积而不溢出。

基于DEM的降雨淹没算法_第1张图片


然后上代码了,转用的话麻烦注明一下出处:

using System;
using System.Collections.Generic;

/** 
* @author mengwei
* @E-mail:[email protected]
* @version 创建时间:2018/7/3
* 本程序为基于DEM(并不是标准的DEM,DEM部分算是伪代码)的降雨淹没算法,模拟一个小区域内降雨淹没的范围
* 本算法仅作为一个简单的理想化demo,还应考虑渗水量(根据地表类型)等因素
* 如有错误或意见欢迎讨论
*/

namespace WaterSpread
{
    class WaterSpread
    {
        public class Point:IComparable
        {
            public int X;  //横坐标
            public int Y;  //纵坐标
            public int h;  //高程值
            public Point(int X,int Y,int h)
            {
                this.X = X;
                this.Y = Y;
                this.h = h;
            }

            int IComparable.CompareTo(Point other)
            {
                Point otherPoint = (Point)other;
                return (this.h < otherPoint.h ? -1 : (this.h == otherPoint.h ? 0 : 1));
            }
        }

        private int length;  //栅格总长度

        private int width;  //栅格总宽度

        private bool[,] isFlooded;  //栅格是否被淹没

        private bool[,] borderPoints;  //用于标识水位边界点

        private Point[,] DEM; //dem数据

        private int waterFall;  //降水量

        private int s;  //一个栅格的面积

        private List depthList = new List();  //一个按高程从小到大排列的List

        //构造函数
        public WaterSpread(Point[,] dem,int fall,int _s)
        {
            s = _s;
            waterFall = fall;
            DEM = dem;
            length = dem.GetLength(0);
            width = dem.GetLength(1);
            isFlooded = new bool[length, width];
            borderPoints = new bool[length, width];
        }


        /// 
        /// 种子扩散算法淹没分析
        /// 起始点为洼地最低点
        /// 
        /// 淹没起始点横坐标
        /// 淹没起始点纵坐标
        public void waterSpreading(int posX,int posY)
        {
            //若该点未被淹没
            if (!isFlooded[posX, posY])
            {
                isFlooded[posX, posY] = true;
                //寻找该点周围未被淹没的栅格加入队列
                int lowest = int.MaxValue;
                //取临近的八个栅格,从未淹没的栅格中寻找最低点
                for(int i = posX - 1; i < posX + 2; i++)
                {
                    for(int j = posY - 1; j < posY + 2; j++)
                    {
                        if(i >= 0 && i < length && j >= 0 && j < width)
                        if (!isFlooded[i, j] && !(i == posX && j ==posY))
                        {
                                depthList.Add(DEM[i, j]);
                                depthList.Sort();  //对List进行重排序
                        }
                    }
                }
                //若水位线高于临近最低点
                if (depthList[0] != null)
                    lowest = depthList[0].h;
                if(lowest < waterDepth())
                {
                    Point curr = depthList[0];
                    depthList.Remove(curr);
                    //递归继续向List的第一个Point淹没
                    waterSpreading(curr.X,curr.Y);
                }
            }
        }

        /// 
        /// 计算当前淹没区域的水位距地平面的距离
        /// 
        public int waterDepth()
        {
            int n = 0;  //淹没栅格总数
            int h = 0;
            int totalDepth = 0;  //各个已淹没栅格淹没深度之和
            for(int i = 0; i < length; i++)
                for(int j=0;j
namespace WaterSpread
{
    class test
    {
        //测试用例
        static void Main(string[] args)
        {
            WaterSpread.Point[,] testDEM = new WaterSpread.Point[1, 3];
            testDEM[0, 0] = new WaterSpread.Point(0, 0, -5);
            testDEM[0, 1] = new WaterSpread.Point(0, 1, -7);
            testDEM[0, 2] = new WaterSpread.Point(0, 2, -6);
            WaterSpread ws = new WaterSpread(testDEM,1,1);
            ws.waterSpreading(0, 1);
            ws.showFlooded();
        }
    }
}


你可能感兴趣的:(基于DEM的降雨淹没算法)