洪涝有源淹没算法及淹没结果分析

洪涝模拟仿真的实现方法主要有两种:一种是基于水动力学的洪水演进模型;另一种是基于DEM的洪水淹没分析。具体分析如下:

我是GIS从业者,从我们的专业角度出发,选择基于DEM的洪水淹没分析来做洪涝的模拟仿真。而基于DEM的洪水淹没分析方法主要分为有源淹没和无源淹没。

本篇博客采用有源淹没算法实现洪涝的模拟,算法为八领域种子扩散算法。采用C#版本GDAL编写了FloodSimulation类,下面给出全部源代码:

  class FloodSimulation
    {
        #region 类成员变量

        //点结构体
        public struct Point
        {
            public int X;          //行号
            public int Y;          //列号
            public int Elevation;  //像素值(高程值)
            public bool IsFlooded; //淹没标记

        };
        private bool[,] IsFlood;                //淹没区域标记二维数组,用于标记淹没栅格
        private List<Point> m_FloodBufferList;  //淹没缓冲区堆栈

        public Dataset m_DEMDataSet;            //DEM数据集
        public Dataset m_FloodSimulatedDataSet; //洪涝淹没范围数据集
        public int m_XSize;                     //数据X方向栅格个数
        public int m_YSize;                     //数据Y方向栅格个数
        public OSGeo.GDAL.Driver driver;        //影像格式驱动
        public int[] m_FloodBuffer;            //填充缓冲区(洪涝淹没范围)
        public int[] m_DEMdataBuffer;          //DEM数据(存储高程值) 

        public double m_AreaFlooded;            //水面面积
        public double m_WaterVolume;            //淹没水体体积
        /* 这里的GeoTransform(影像坐标变换参数)的定义是:通过像素所在的行列值得到其左上角点空间坐标的运算参数
            例如:某图像上(P,L)点左上角的实际空间坐标为:
            Xp = GeoTransform[0] + P * GeoTransform[1] + L * GeoTransform[2];
            Yp = GeoTransform[3] + P * GeoTransform[4] + L * GeoTransform[5];                                                                     */
        public double[] m_adfGeoTransform;   

        #endregion

        //构造函数
        public FloodSimulation()
        {
            m_adfGeoTransform = new double[6];
            m_FloodBufferList = new List<Point>();

        }

        /// <summary>
        /// 加载淹没区DEM,并创建淹没范围影像
        /// </summary>
        /// <param name="m_DEMFilePath">DEM文件路径</param>
        /// <returns></returns>
        public void loadDataSet(string m_DEMFilePath)
        {
            //读取DEM数据
            m_DEMDataSet = Gdal.Open(m_DEMFilePath, Access.GA_ReadOnly);
            m_XSize = m_DEMDataSet.RasterXSize;
            m_YSize = m_DEMDataSet.RasterYSize;

            //获取影像坐标转换参数
            m_DEMDataSet.GetGeoTransform(m_adfGeoTransform);
            //读取DEM数据到内存中
            Band m_DEMBand = m_DEMDataSet.GetRasterBand(1); //获取第一个波段
            m_DEMdataBuffer = new int [m_XSize * m_YSize];
            m_DEMBand.ReadRaster(0, 0, m_XSize, m_YSize, m_DEMdataBuffer, m_XSize, m_YSize, 0, 0);

            //淹没范围填充缓冲区
            m_FloodBuffer = new int[m_XSize * m_YSize];
            IsFlood=new bool[m_XSize,m_YSize];

            //初始化二维淹没区bool数组
            for (int i = 0; i < m_XSize; i++)
            {
                for (int j = 0; j < m_YSize; j++)
                {
                    IsFlood[i, j] = false;
                }
            }

            //创建洪涝淹没范围影像
            string m_FloodImagePath = System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + "\\FloodSimulation\\FloodedRegion.tif";
            if (System.IO.File.Exists(m_FloodImagePath))
            {
                System.IO.File.Delete(m_FloodImagePath);
            }

            //在GDAL中创建影像,先需要明确待创建影像的格式,并获取到该影像格式的驱动
            driver = Gdal.GetDriverByName("GTiff");
            //调用Creat函数创建影像
            // m_FloodSimulatedDataSet = driver.CreateCopy(m_FloodImagePath, m_DEMDataSet, 1, null, null, null);
            m_FloodSimulatedDataSet = driver.Create(m_FloodImagePath, m_XSize, m_YSize, 1, DataType.GDT_Float32, null);
            //设置影像属性
            m_FloodSimulatedDataSet.SetGeoTransform(m_adfGeoTransform); //影像转换参数
            m_FloodSimulatedDataSet.SetProjection(m_DEMDataSet.GetProjectionRef()); //投影
            //m_FloodSimulatedDataSet.WriteRaster(0, 0, m_XSize, m_YSize, m_FloodBuffer, m_XSize, m_YSize, 1, null, 0, 0, 0);

            //输出影像
            m_FloodSimulatedDataSet.GetRasterBand(1).WriteRaster(0, 0, m_XSize, m_YSize, m_FloodBuffer, m_XSize, m_YSize, 0, 0);
            m_FloodSimulatedDataSet.GetRasterBand(1).FlushCache();
            m_FloodSimulatedDataSet.FlushCache();

        }

        /// <summary>
        /// 种子扩散算法淹没分析
        /// </summary>
        /// <param name="m_Lat">种子点纬度</param>
        /// <param name="m_Log">种子点经度</param>
        /// <param name="m_FloodLevel">淹没水位</param>
        public void FloodFill8Direct(double m_Lat,double m_Log,double m_FloodLevel)
        {
            //首先根据种子点经纬度获取其所在行列号
            Point pFloodSourcePoint = new Point();
            int x, y;
            geoToImageSpace(m_adfGeoTransform, m_Log, m_Lat, out x, out y);
            pFloodSourcePoint.X = x;
            pFloodSourcePoint.Y = y;

            //获取种子点高程值
            pFloodSourcePoint.Elevation = GetElevation(pFloodSourcePoint);
            m_FloodBufferList.Add(pFloodSourcePoint);

            //判断堆栈中时候还有未被淹没点,如有继续搜索,没有则淹没分析结束。
            while (m_FloodBufferList.Count!=0)
            {
                Point pFloodSourcePoint_temp = m_FloodBufferList[0];
                int rowX = pFloodSourcePoint_temp.X;
                int colmY = pFloodSourcePoint_temp.Y;

                //标记可淹没,并从淹没堆栈中移出
                IsFlood[rowX, colmY] = true;
                m_FloodBuffer[getIndex(pFloodSourcePoint_temp)] = 1;
                m_FloodBufferList.RemoveAt(0); 

                //向中心栅格单元的8个临近方向搜索连通域
                for (int i = rowX - 1; i < rowX + 2; i++)
                {
                    for (int j = colmY - 1; j < colmY + 2; j++)
                    {
                        //判断是否到达栅格边界
                        if (i<=m_XSize&&j<=m_YSize)
                        {
                            Point temp_point = new Point();
                            temp_point.X = i;
                            temp_point.Y = j;
                            temp_point.Elevation = GetElevation(temp_point);
                            //搜索可以淹没且未被标记的栅格单元
                            if ((temp_point.Elevation<m_FloodLevel||temp_point.Elevation <= pFloodSourcePoint_temp.Elevation) && IsFlood[temp_point.X, temp_point.Y] == false)
                            {
                                //将符合条件的栅格单元加入堆栈,标记为淹没,避免重复运算
                                m_FloodBufferList.Add(temp_point);
                                IsFlood[temp_point.X, temp_point.Y] = true;
                                m_FloodBuffer[getIndex(temp_point)] = 1;
                            }

                        }

                    }
                }
            }
            //统计淹没网格数
            int count = 0;
            for (int i = 0; i < m_XSize; i++)
            {
                for (int j = 0; j < m_YSize; j++)
                {
                    if (IsFlood[i,j]==true)
                    {
                        count++;
                    }
                }
            }

        }

        /// <summary>
        /// 输出洪涝淹没范围图
        /// </summary>
        public void OutPutFloodRegion()
        {
            m_FloodSimulatedDataSet.GetRasterBand(1).WriteRaster(0, 0, m_XSize, m_YSize, m_FloodBuffer, m_XSize, m_YSize, 0, 0);
            // m_FloodSimulatedDataSet.WriteRaster(0, 0, m_XSize, m_YSize, m_FloodBuffer, m_XSize, m_YSize, 1, null, 0, 0, 0);
            m_FloodSimulatedDataSet.GetRasterBand(1).FlushCache();
            m_FloodSimulatedDataSet.FlushCache();
        }

//         public void OutPutFloodedInfo()
//         {
//         }
        /// <summary>
        /// 获取第x行第y列栅格索引
        /// </summary>
        /// <param name="point">栅格点</param>
        /// <returns>该点在DEM内存数组中的索引</returns>
        private int getIndex(Point point)
        {
            return  point.Y* m_XSize + point.X;
        }

        /// <summary>
        /// 获取高程值
        /// </summary>
        /// <param name="m_point">栅格点</param>
        /// <returns>高程值</returns>
        private int GetElevation(Point m_point)
        {
            return m_DEMdataBuffer[getIndex(m_point)];

        }

        /// <summary>
        /// 从像素空间转换到地理空间
        /// </summary>
        /// <param name="adfGeoTransform">影像坐标变换参数</param>
        /// <param name="pixel">像素所在行</param>
        /// <param name="line">像素所在列</param>
        /// <param name="x">X</param>
        /// <param name="y">Y</param>
        public void imageToGeoSpace(double[] m_GeoTransform, int pixel, int line, out double X, out double Y)
        {
            X = m_GeoTransform[0] + pixel * m_GeoTransform[1] + line * m_GeoTransform[2];
            Y = m_GeoTransform[3] + pixel * m_GeoTransform[4] + line * m_GeoTransform[5];
        }

        /// <summary>
        /// 从地理空间转换到像素空间
        /// </summary>
        /// <param name="adfGeoTransform">影像坐标变化参数</param>
        /// <param name="x">X(经度)</param>
        /// <param name="y">Y(纬度)</param>
        /// <param name="pixel">像素所在行</param>
        /// <param name="line">像素所在列</param>
        public void geoToImageSpace(double[] m_GeoTransform, double x, double y, out int pixel, out int line)
        {
            line = (int)((y * m_GeoTransform[1] - x * m_GeoTransform[4] + m_GeoTransform[0] * m_GeoTransform[4] - m_GeoTransform[3] * m_GeoTransform[1]) / (m_GeoTransform[5] * m_GeoTransform[1] - m_GeoTransform[2] * m_GeoTransform[4]));
            pixel = (int)((x - m_GeoTransform[0] - line * m_GeoTransform[2]) / m_GeoTransform[1]);
        }

    }

模拟结果在ArcGlobe中的显示效果图:

欢迎大家留言交流。

时间: 2024-12-22 19:51:32

洪涝有源淹没算法及淹没结果分析的相关文章

细菌觅食优化算法:理论基础,分析,以及应用(未完)

原作者:Swagatam Das,Arijit Biswas,Sambarta Dasgupta,和Ajith Abraham  [摘 要]细菌觅食优化算法(Bacterial foraging optimization algorithm[BFOA])已经被分布式优化和控制的同行们当作一种全局性的优化算法接受.BFOA是由大肠杆菌的群体觅食行为所启发而总结出来 的.BFOA已经吸引了足够多的研究者的注意,由于它出现在解决真实世界中一些应用领域上优化问题的高效性.E.coli 的群体策略的生物基

MATLAB智能算法30个案例分析

<matlab智能算法30个案例分析>采用案例形式,以智能算法为主线,讲解了遗传算法.免疫算法.退火算法.粒子群算法.鱼群算法.蚁群算法和神经网络算法等最常用的智能算法的matlab实现.本书共给出30个案例,每个案例都是一个使用智能算法解决问题的具体实例,所有案例均由理论讲解.案例背景.matlab程序实现和扩展阅读四个部分组成,并配有完整的原创程序,使读者在掌握算法的同时更能快速提高使用算法求解实际问题的能力.本书可作为本科毕业设计.研究生项目设计.博士低年级课题设计参考书籍,同时对广大科

比较排序算法及复杂度分析

比较排序算法分类 比较排序(Comparison Sort)通过对数组中的元素进行比较来实现排序. 比较排序算法(Comparison Sorts) Category Name Best Average Worst Memory Stability  插入排序  (Insertion Sorts) 插入排序 (Insertion Sort) n n2 n2 1 Stable 希尔排序 (Shell Sort) n n log2 n n log2 n 1 Not Stable  交换排序 (Exc

SURF算法与源码分析、下

上一篇文章 SURF算法与源码分析.上 中主要分析的是SURF特征点定位的算法原理与相关OpenCV中的源码分析,这篇文章接着上篇文章对已经定位到的SURF特征点进行特征描述.这一步至关重要,这是SURF特征点匹配的基础.总体来说算法思路和SIFT相似,只是每一步都做了不同程度的近似与简化,提高了效率. 1. SURF特征点方向分配 为了保证特征矢量具有旋转不变性,与SIFT特征一样,需要对每个特征点分配一个主方向.为些,我们需要以特征点为中心,以$6s$($s = 1.2 *L /9$为特征点

从软件project的角度写机器学习3——主要监督学习算法的project性分析

主要机器学习算法的project适用性分析 前段时间AlphaGo跟李世石的大战及相关的深度学习的新闻刷了一遍又一遍的朋友圈.只是这件事情,也仅仅是在机器学习的深度上进一步拓展,而机器学习的广度(也即project化实践)上,仍然没有什么突破性的理论或实践,用的领域继续用,不用的领域依旧不用. project性分析的作用 project上的琐事 机器学习的使命是使计算机强大的运算能力和存储能力转化为推演能力.能转化是一方面.转化的效率则是还有一方面.科研性质的AlphaGo,拥有近乎无限的计算资

加州大学用机器学习北京赛车(PK10)源码出售算法来预测和分析梦境

[导读]梦是神秘的一种主体经验,是哲学.宗教.心理学等最感兴趣的话题北京赛车(PK10)源码出售  QQ2952777280[话仙源码论坛]hxforum.com[木瓜源码论坛]papayabbs.com,也产生了许多有关的科学猜想.但人类从未真正理解梦的内容.机制和作用.我们能不能设计一种机器学习算法来预测和分析我们的梦境呢?答案是肯定的.在AI的帮助下,理解.预测和控制梦境的技术上已经取得了进展. 你有没有做过令人不安的梦,梦见高中时认识的某个人?或者做过以某种特殊的方式预知未来的梦,比如预

实现 | 朴素贝叶斯模型算法研究与实例分析

实现 | 朴素贝叶斯模型算法研究与实例分析(白宁超2018年9月4日09:03:21) 导读:朴素贝叶斯模型是机器学习常用的模型算法之一,其在文本分类方面简单易行,且取得不错的分类效果.所以很受欢迎,对于朴素贝叶斯的学习,本文首先介绍理论知识即朴素贝叶斯相关概念和公式推导,为了加深理解,采用一个维基百科上面性别分类例子进行形式化描述.然后通过编程实现朴素贝叶斯分类算法,并在屏蔽社区言论.垃圾邮件.个人广告中获取区域倾向等几个方面进行应用,包括创建数据集.数据预处理.词集模型和词袋模型.朴素贝叶斯

简单理解算法篇--摊还分析

摊还分析是用来评价程序中的一个操作序列的平均代价,有时可能某个操作的代价特别高,但总体上来看也并非那么糟糕,可以形象的理解为把高代价的操作“分摊”到其他操作上去了,要求的就是均匀分摊后的平均代价. 摊还分析有三种常用的技术:聚合分析,核算法,势能法. 首先看个例子,现在有三种操作,push(s),pop(s),mutlipop(s,k),push(s),统称为栈操作. push(s)每次只能压一个数据,所以规定操作的代价为1,pop(s)每次只能弹一个数据,所以也规定操作的代价为1,而mutli

Weka算法Classifier-meta-AdditiveRegression源码分析

博主最近迷上了打怪物猎人,这片文章拖了很久才开始动笔 一.算法 AdditiveRegression,换个更出名一点的叫法可以称作GBDT(Grandient Boosting Decision Tree)梯度下降分类树,或者GBRT(Grandient Boosting Regression Tree)梯度下降回归树,是一种多分类器组合的算法,更确切的说,是属于Boosting算法. 谈到Boosting算法,就不能不提AdaBoost,参见之前我写的博客,可以看到AdaBoost的核心是级联