3DGIS

研究OpenGL,GPU和GIS

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  40 随笔 :: 1 文章 :: 63 评论 :: 8 Trackbacks
 

三维场景下坡度、坡向图生成

在得到区域较大比例尺DEM数据后,通过各格网单元的领域高程差等运算,可生成此区域的三维场景下的坡度与坡向图。其用途较广,如坡度图一般用于退耕还林、土地适宜性评价等方面,坡向图为辐照度等进一步的计算提供基础。另外,坡度、坡向图也应用于自然条件下的水流分布、滑坡等地质灾害监测等方面。以下给出基本公式与程序代码参考。

        
     此图引自:Tarboton, D.G. (1997): A new method for the determination of flow directions and upslope areas in grid digital elevation models, Water Resources Research, Vol.33, No.2, p.309-319

参考上图,将这个简单的三角形看成一坡度,则将坡度用矢量(S1,S2)的形式表示,有

        S1 = (e0– e1)/d1

        S2 = (e1 – e2)/d2

        其中,e0e1e2代表格网单元上的高程数值,d1d2代表单元之间的距离(有时就是1),

        则此坡度的方向r与大小(模)s是:

        r = tan-1(S2 / S1)

        s = sqrt(S1*S1+ S2*S2)

        参考代码如下:

作为第一步的入口函数:

bool SlopeCreate::SlopeStart(void)                                                    //以DEM为基本数据计算地形坡度、坡向

{  

    long gridNum = m_iRows*m_iColumns;

    double* pSurfaceSlope = new double[gridNum];

    long lIndex = 0;

    double dSlopeMin = 3.14;                                                         //90角度等于.5707963弧度45角度等于.78弧度

    double dSlopeMax = -3.14;

    intx, y;

    for(y=0; y<m_iRows; y++)          //两重循环,取DEM上的每个元素                  {

         for(x=0; x<m_iColumns; x++)                                

         {

             double slope = ComputeSlope(x, y);         //对格网上每个元素进行计算

             lIndex = y*m_iColumns+x;

             pSurfaceSlope[lIndex] = slope;

             if(dSlopeMin>slope) dSlopeMin = slope;//得到较小的坡度数值, 记录下来

             if(dSlopeMax<slope) dSlopeMax = slope;//得到较大的坡度数值,记录下来

         }

    }

    //设置颜色表

    m_byRsAnalysis = new BYTE[m_iRows * m_iColumns];                             //

    m_byGsAnalysis = new BYTE[m_iRows * m_iColumns];

    m_byBsAnalysis = new BYTE[m_iRows * m_iColumns];

    for(lIndex=0;lIndex<gridNum;lIndex++)

    {

         OutputSlopeColor(lIndex,pSurfaceSlope[lIndex]); //对格网上的每个单元格赋颜色

    }

   

    return true;

}

计算坡度、坡向的核心函数:

double SlopeCreate::ComputeSlope(int x, int y)         

{

    int      i, ix, iy, j;

    double   z, zm[8], iSlope, iAspect, Slope, Aspect, G, H;

    if( m_p3dDEMGrid->IsNodata(x,y))

    {

         long tIndex = y * m_iColumns + x;

         m_byRsAnalysis[tIndex] = 200;                  //没有数值的地方填充灰白
         m_byGsAnalysis[tIndex] = 200; 
        
m_byBsAnalysis[tIndex] = 200;

         return 0;

    }

    //-----------------------------------------------------

    z = m_p3dDEMPoints[y*m_iColumns+x][2];                                           //得到本位置处的高程数值

   

    for(i=0; i<8; i++)                             //对本位置的相邻个元素进行循环

    {

         ix       = m_p3dDEMGrid->GetxTo(i, x);     //通过方向判断得到邻近XY数值

         iy       = m_p3dDEMGrid->GetyTo(i, y);

         if( m_p3dDEMGrid->IsInGrid(int(ix),int(iy)))   //判断是否落在格网范围内

         {

             zm[i]    = m_p3dDEMPoints[iy*m_iColumns+ix][2];       //记录下这个邻域单元的高程数值

         }

         else                          //如果没有落在格网范围之内

         {

                 ix       = m_p3dDEMGrid->GetxTo(i + 4, x);//得到邻近单元的索引

                 iy       = m_p3dDEMGrid->GetyTo(i + 4, y);//得到邻近单元的索引

                 if( m_p3dDEMGrid->IsInGrid(int(ix),int(iy)) )

                 {

                     zm[i]    = z - (m_p3dDEMPoints[iy*m_iColumns+ix][2] - z);

                 }

                 else

                 {

                     zm[i]    = z;

                 }

         }

    }

    //---------------------------------------------

    Slope    = 0.0;                                        //初始数值

    Aspect   = -1.0;

    for(i=0, j=1; i<8; i++, j=(j+1)%8)                 //相邻元素的循环

    {

         if( i % 2 )                                                                      {

             G        = (z     - zm[j]) / m_iXCellSize;

             H        = (zm[j]- zm[i]) / m_iXCellSize;

         }

         else                                                                             {

             G        = (z     - zm[i]) / m_iXCellSize;

             H        = (zm[i]- zm[j]) / m_iXCellSize;

         }

                                  //参考上面的公式分析

         if( H < 0.0 )

         {

             iAspect = 0.0;

             iSlope   = G;

         }

         else if( H > G )

         {

             iAspect = M_PI_045;

             iSlope   = (z - zm[i % 2 ? i : j]) / (sqrt(2.0) * m_iXCellSize);

         }

         else

         {

             iAspect = atan(H / G);                    //求反函数

             iSlope   = sqrt(G*G + H*H);

         }

         if( iSlope > Slope )

         {

             Aspect   = i * M_PI_045 + (i % 2 ? M_PI_045 - iAspect : iAspect);

             Slope    = iSlope;

         }

    }

    //---------------------------------------------

    if( Aspect < 0.0 )

    {

         return 0;

        

    }

    else

    {

         return atan(Slope);                            //返回坡度数值

    }

}

 寻找邻近单元函数

int CGV3dDEMGrid::GetxTo(int Direction, int x)

{

    static int   ix[8]    = { 0, 1, 1, 1, 0,-1,-1,-1 };

    return( x + ix[Direction % 8] );           //得到邻近单元的索引

}

intCGV3dDEMGrid::GetyTo(int Direction, int y)

{

    static int   iy[8]    = { 1, 1, 0,-1,-1,-1, 0, 1 };

    return( y + iy[Direction % 8] );           //得到邻近单元的索引

}


                                 原始图象(配图例)


                              三维场景下坡度图(大)


                       三维场景下坡向图(大)

posted on 2008-04-12 12:23 武汉侯涛 阅读(498) 评论(0)  编辑 收藏

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
 
另存  打印