zoukankan      html  css  js  c++  java
  • 洪涝有源淹没算法及淹没结果分析【转】

    http://blog.csdn.net/giser_whu/article/details/41288761

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

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

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

    [csharp] view plain copy
    1.   class FloodSimulation  
    2.     {  
    3.         #region 类成员变量  
    4.   
    5.         //点结构体  
    6.         public struct Point  
    7.         {  
    8.             public int X;          //行号  
    9.             public int Y;          //列号  
    10.             public int Elevation;  //像素值(高程值)  
    11.             public bool IsFlooded; //淹没标记  
    12.   
    13.         };  
    14.         private bool[,] IsFlood;                //淹没区域标记二维数组,用于标记淹没栅格  
    15.         private List<Point> m_FloodBufferList;  //淹没缓冲区堆栈  
    16.         
    17.         public Dataset m_DEMDataSet;            //DEM数据集  
    18.         public Dataset m_FloodSimulatedDataSet; //洪涝淹没范围数据集  
    19.         public int m_XSize;                     //数据X方向栅格个数  
    20.         public int m_YSize;                     //数据Y方向栅格个数  
    21.         public OSGeo.GDAL.Driver driver;        //影像格式驱动  
    22.         public int[] m_FloodBuffer;            //填充缓冲区(洪涝淹没范围)  
    23.         public int[] m_DEMdataBuffer;          //DEM数据(存储高程值)   
    24.   
    25.         public double m_AreaFlooded;            //水面面积  
    26.         public double m_WaterVolume;            //淹没水体体积  
    27.         /* 这里的GeoTransform(影像坐标变换参数)的定义是:通过像素所在的行列值得到其左上角点空间坐标的运算参数 
    28.             例如:某图像上(P,L)点左上角的实际空间坐标为: 
    29.             Xp = GeoTransform[0] + P * GeoTransform[1] + L * GeoTransform[2]; 
    30.             Yp = GeoTransform[3] + P * GeoTransform[4] + L * GeoTransform[5];                                                                     */  
    31.         public double[] m_adfGeoTransform;     
    32.  
    33.         #endregion  
    34.           
    35.         //构造函数  
    36.         public FloodSimulation()  
    37.         {  
    38.             m_adfGeoTransform = new double[6];  
    39.             m_FloodBufferList = new List<Point>();  
    40.               
    41.         }  
    42.   
    43.         /// <summary>  
    44.         /// 加载淹没区DEM,并创建淹没范围影像  
    45.         /// </summary>  
    46.         /// <param name="m_DEMFilePath">DEM文件路径</param>  
    47.         /// <returns></returns>  
    48.         public void loadDataSet(string m_DEMFilePath)  
    49.         {  
    50.             //读取DEM数据  
    51.             m_DEMDataSet = Gdal.Open(m_DEMFilePath, Access.GA_ReadOnly);  
    52.             m_XSize = m_DEMDataSet.RasterXSize;  
    53.             m_YSize = m_DEMDataSet.RasterYSize;  
    54.               
    55.             //获取影像坐标转换参数  
    56.             m_DEMDataSet.GetGeoTransform(m_adfGeoTransform);   
    57.             //读取DEM数据到内存中  
    58.             Band m_DEMBand = m_DEMDataSet.GetRasterBand(1); //获取第一个波段  
    59.             m_DEMdataBuffer = new int [m_XSize * m_YSize];  
    60.             m_DEMBand.ReadRaster(0, 0, m_XSize, m_YSize, m_DEMdataBuffer, m_XSize, m_YSize, 0, 0);  
    61.   
    62.             //淹没范围填充缓冲区  
    63.             m_FloodBuffer = new int[m_XSize * m_YSize];  
    64.             IsFlood=new bool[m_XSize,m_YSize];  
    65.   
    66.             //初始化二维淹没区bool数组  
    67.             for (int i = 0; i < m_XSize; i++)  
    68.             {  
    69.                 for (int j = 0; j < m_YSize; j++)  
    70.                 {  
    71.                     IsFlood[i, j] = false;  
    72.                 }  
    73.             }  
    74.   
    75.             //创建洪涝淹没范围影像  
    76.             string m_FloodImagePath = System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + "\FloodSimulation\FloodedRegion.tif";  
    77.             if (System.IO.File.Exists(m_FloodImagePath))  
    78.             {  
    79.                 System.IO.File.Delete(m_FloodImagePath);  
    80.             }  
    81.   
    82.             //在GDAL中创建影像,先需要明确待创建影像的格式,并获取到该影像格式的驱动  
    83.             driver = Gdal.GetDriverByName("GTiff");  
    84.             //调用Creat函数创建影像  
    85.             // m_FloodSimulatedDataSet = driver.CreateCopy(m_FloodImagePath, m_DEMDataSet, 1, null, null, null);  
    86.             m_FloodSimulatedDataSet = driver.Create(m_FloodImagePath, m_XSize, m_YSize, 1, DataType.GDT_Float32, null);  
    87.             //设置影像属性  
    88.             m_FloodSimulatedDataSet.SetGeoTransform(m_adfGeoTransform); //影像转换参数  
    89.             m_FloodSimulatedDataSet.SetProjection(m_DEMDataSet.GetProjectionRef()); //投影  
    90.             //m_FloodSimulatedDataSet.WriteRaster(0, 0, m_XSize, m_YSize, m_FloodBuffer, m_XSize, m_YSize, 1, null, 0, 0, 0);  
    91.               
    92.             //输出影像  
    93.             m_FloodSimulatedDataSet.GetRasterBand(1).WriteRaster(0, 0, m_XSize, m_YSize, m_FloodBuffer, m_XSize, m_YSize, 0, 0);  
    94.             m_FloodSimulatedDataSet.GetRasterBand(1).FlushCache();  
    95.             m_FloodSimulatedDataSet.FlushCache();  
    96.   
    97.         }  
    98.   
    99.         /// <summary>  
    100.         /// 种子扩散算法淹没分析  
    101.         /// </summary>  
    102.         /// <param name="m_Lat">种子点纬度</param>  
    103.         /// <param name="m_Log">种子点经度</param>  
    104.         /// <param name="m_FloodLevel">淹没水位</param>  
    105.         public void FloodFill8Direct(double m_Lat,double m_Log,double m_FloodLevel)  
    106.         {  
    107.             //首先根据种子点经纬度获取其所在行列号  
    108.             Point pFloodSourcePoint = new Point();  
    109.             int x, y;  
    110.             geoToImageSpace(m_adfGeoTransform, m_Log, m_Lat, out x, out y);  
    111.             pFloodSourcePoint.X = x;  
    112.             pFloodSourcePoint.Y = y;  
    113.               
    114.             //获取种子点高程值  
    115.             pFloodSourcePoint.Elevation = GetElevation(pFloodSourcePoint);  
    116.             m_FloodBufferList.Add(pFloodSourcePoint);  
    117.   
    118.             //判断堆栈中时候还有未被淹没点,如有继续搜索,没有则淹没分析结束。  
    119.             while (m_FloodBufferList.Count!=0)  
    120.             {  
    121.                 Point pFloodSourcePoint_temp = m_FloodBufferList[0];  
    122.                 int rowX = pFloodSourcePoint_temp.X;  
    123.                 int colmY = pFloodSourcePoint_temp.Y;  
    124.                  
    125.                 //标记可淹没,并从淹没堆栈中移出  
    126.                 IsFlood[rowX, colmY] = true;  
    127.                 m_FloodBuffer[getIndex(pFloodSourcePoint_temp)] = 1;  
    128.                 m_FloodBufferList.RemoveAt(0);   
    129.                   
    130.                 //向中心栅格单元的8个临近方向搜索连通域  
    131.                 for (int i = rowX - 1; i < rowX + 2; i++)  
    132.                 {  
    133.                     for (int j = colmY - 1; j < colmY + 2; j++)  
    134.                     {  
    135.                         //判断是否到达栅格边界  
    136.                         if (i<=m_XSize&&j<=m_YSize)  
    137.                         {  
    138.                             Point temp_point = new Point();  
    139.                             temp_point.X = i;  
    140.                             temp_point.Y = j;  
    141.                             temp_point.Elevation = GetElevation(temp_point);  
    142.                             //搜索可以淹没且未被标记的栅格单元  
    143.                             if ((temp_point.Elevation<m_FloodLevel||temp_point.Elevation <= pFloodSourcePoint_temp.Elevation) && IsFlood[temp_point.X, temp_point.Y] == false)  
    144.                             {  
    145.                                 //将符合条件的栅格单元加入堆栈,标记为淹没,避免重复运算  
    146.                                 m_FloodBufferList.Add(temp_point);  
    147.                                 IsFlood[temp_point.X, temp_point.Y] = true;  
    148.                                 m_FloodBuffer[getIndex(temp_point)] = 1;  
    149.                             }  
    150.                               
    151.                         }  
    152.                          
    153.                     }  
    154.                 }  
    155.             }  
    156.             //统计淹没网格数  
    157.             int count = 0;  
    158.             for (int i = 0; i < m_XSize; i++)  
    159.             {  
    160.                 for (int j = 0; j < m_YSize; j++)  
    161.                 {  
    162.                     if (IsFlood[i,j]==true)  
    163.                     {  
    164.                         count++;  
    165.                     }  
    166.                 }  
    167.             }  
    168.         
    169.         }  
    170.           
    171.         /// <summary>  
    172.         /// 输出洪涝淹没范围图  
    173.         /// </summary>  
    174.         public void OutPutFloodRegion()  
    175.         {  
    176.             m_FloodSimulatedDataSet.GetRasterBand(1).WriteRaster(0, 0, m_XSize, m_YSize, m_FloodBuffer, m_XSize, m_YSize, 0, 0);  
    177.             // m_FloodSimulatedDataSet.WriteRaster(0, 0, m_XSize, m_YSize, m_FloodBuffer, m_XSize, m_YSize, 1, null, 0, 0, 0);  
    178.             m_FloodSimulatedDataSet.GetRasterBand(1).FlushCache();  
    179.             m_FloodSimulatedDataSet.FlushCache();  
    180.         }  
    181.   
    182. //         public void OutPutFloodedInfo()  
    183. //         {  
    184. //         }  
    185.         /// <summary>  
    186.         /// 获取第x行第y列栅格索引  
    187.         /// </summary>  
    188.         /// <param name="point">栅格点</param>  
    189.         /// <returns>该点在DEM内存数组中的索引</returns>  
    190.         private int getIndex(Point point)  
    191.         {  
    192.             return  point.Y* m_XSize + point.X;  
    193.         }  
    194.   
    195.         /// <summary>  
    196.         /// 获取高程值  
    197.         /// </summary>  
    198.         /// <param name="m_point">栅格点</param>  
    199.         /// <returns>高程值</returns>  
    200.         private int GetElevation(Point m_point)  
    201.         {  
    202.             return m_DEMdataBuffer[getIndex(m_point)];  
    203.   
    204.         }  
    205.   
    206.         /// <summary>  
    207.         /// 从像素空间转换到地理空间  
    208.         /// </summary>  
    209.         /// <param name="adfGeoTransform">影像坐标变换参数</param>  
    210.         /// <param name="pixel">像素所在行</param>  
    211.         /// <param name="line">像素所在列</param>  
    212.         /// <param name="x">X</param>  
    213.         /// <param name="y">Y</param>  
    214.         public void imageToGeoSpace(double[] m_GeoTransform, int pixel, int line, out double X, out double Y)  
    215.         {  
    216.             X = m_GeoTransform[0] + pixel * m_GeoTransform[1] + line * m_GeoTransform[2];  
    217.             Y = m_GeoTransform[3] + pixel * m_GeoTransform[4] + line * m_GeoTransform[5];  
    218.         }  
    219.   
    220.         /// <summary>  
    221.         /// 从地理空间转换到像素空间  
    222.         /// </summary>  
    223.         /// <param name="adfGeoTransform">影像坐标变化参数</param>  
    224.         /// <param name="x">X(经度)</param>  
    225.         /// <param name="y">Y(纬度)</param>  
    226.         /// <param name="pixel">像素所在行</param>  
    227.         /// <param name="line">像素所在列</param>  
    228.         public void geoToImageSpace(double[] m_GeoTransform, double x, double y, out int pixel, out int line)  
    229.         {  
    230.             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]));  
    231.             pixel = (int)((x - m_GeoTransform[0] - line * m_GeoTransform[2]) / m_GeoTransform[1]);  
    232.         }  
    233.   
    234.   
    235.     }  

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

    欢迎大家留言交流。

  • 相关阅读:
    mybatis的mapper特殊字符转移以及动态SQL条件查询
    MySQL查询结果集字符串操作之多行合并与单行分割
    MySQL查询之内连接,外连接查询场景的区别与不同
    SpringBoot异步使用@Async原理及线程池配置
    SpringBoot 属性配置文件数据注入配置和yml与properties区别
    MySQL实战45讲第33讲
    Beta冲刺第1次
    Beta冲刺第5次
    Beta冲刺第4次
    Beta冲刺第3次
  • 原文地址:https://www.cnblogs.com/mazhenyu/p/8119019.html
Copyright © 2011-2022 走看看