wuhanht
路人甲
路人甲
  • 注册日期2007-05-24
  • 发帖数12
  • QQ
  • 铜币175枚
  • 威望0点
  • 贡献值0点
  • 银元0个
阅读:1634回复:0

[原创]常见DEM格式分析与三维分层设色显示

楼主#
更多 发布于:2007-11-12 11:51
在城市地质调查项目中需要读取<FONT face="Courier New">CNSDTF</FONT> DEM数据,这种格式与美国USGS DEM数据格式相比较,有些简单,不包含椭球体,投影方式等元数据,实际上就是投影后的平面格网数据,所以读取入系统不困难.以后将介绍ERDAS IMG格式的读取,这个就显得有些复杂了.<BR>     std::locale::global(std::locale(""));
<P>   ifstream _demfile;           //DEM文件流<BR>   _demfile.open(lpszPathName);        //读取文件<BR>  <BR>   string sDataName,sCNDataName;<BR>   string sVersion;float iVersion;<BR>   string sAlpha;float fAlpha;<BR>   string sUnit; string sUnitName;<BR>   string sCompress; float dCompress;<BR>   string sX0; double dX0;<BR>   string sY0; double dY0;<BR>   string sDX; double dDX;<BR>   string sDY; double dDY;<BR>   string sRow; int iRows;<BR>   string sColumn; int iColumns;<BR>   string sValueTypeName; string sValueType;<BR>   string sHzoom; int iHzoom;<BR>   string sMinV;<BR>   string sMaxV;</P>
<P>   if(_demfile)<BR>   {<BR>    _demfile>>sDataName>>sCNDataName;<BR>    _demfile>>sVersion>>iVersion;<BR>    _demfile>>sAlpha>>fAlpha;<BR>    _demfile>>sUnit>>sUnitName;<BR>    _demfile>>sCompress>>dCompress;<BR>    _demfile>>sX0>>dX0;<BR>    _demfile>>sY0>>dY0;<BR>    _demfile>>sDX>>dDX;<BR>    _demfile>>sDY>>dDY;<BR>    _demfile>>sRow>>iRows;<BR>    _demfile>>sColumn>>iColumns;<BR>    _demfile>>sValueTypeName>>sValueType;<BR>    _demfile>>sHzoom>>iHzoom;<BR>    _demfile>>sMinV;<BR>    _demfile>>sMaxV;</P>
<P>   }<BR>   else <BR>   {<BR>    AfxMessageBox("无法读取文件数据头!");<BR>    return false;<BR>   }<BR>     dY0 = dY0 - dDY*iRows;              //从文件中读取的dYO记录的是最大数值<BR>   long index = 0,PointsTotalNumber = 0;<BR>   int i,j;<BR>   double tmpHeight = 0;<BR>  <BR>   POINT3d* p3dDEMGridPoint = new POINT3d[iRows*iColumns];       //准备读文件中数据<BR>  <BR>   double dNodata =   -99999;<BR>   double dZMin = 9999,dZMax = -9999;<BR>   for(j=iRows-1;j>=0;j--)               //由于此文件记录Y数值的方法与其他不同,需要翻转数据<BR>   {<BR>    for(i=0;i<iColumns;i++)<BR>    {<BR>     index =   j*iColumns+i;<BR>     _demfile>>tmpHeight;<BR>     if(iHzoom != 0) tmpHeight = tmpHeight/iHzoom;      //原始的缩放因子<BR>     p3dDEMGridPoint[index][2] = tmpHeight;<BR>    <BR>     if( tmpHeight > -9999)            //也就是不等于 dNodata<BR>     {<BR>      if(dZMin > tmpHeight) dZMin = tmpHeight;       //记录高程上的最小数值<BR>      if(dZMax < tmpHeight) dZMax = tmpHeight;       //记录高程上的最大数值<BR>     }<BR>    <BR>    }<BR>}</P>


<P><BR> </P>
<P><IMG src="http://www.cnblogs.com/images/cnblogs_com/wuhanhoutao/111912/r_layercoloring1.jpg" border=0></P>
<P>美国USGS的DEM数据读取的程序代码已经提供,关键是对文件头的处理要注意每个字段的含义,到数据部分需要注意XY轴的最大和最小数值,Z轴的最大最小数值提取的时候,要防止NodataValue数据的干扰,因为部分数据是NodataValue,会非常小或大。<BR>     </P>
<P>读取美国USGS的DEM数据程序</P>
<P>string quadName,processInfo;<BR>    double seGeoCornerX,seGeoCornerY;<BR>    long processCode;<BR>    string sectionIndicator, mapCenterCode;<BR>       long levelCode,elevPattern,groundRefSysCode,groundRefSysZone,groundRefSysUnits;<BR>       long elevUnits, numPolySides;<BR>       DEMPointVector demCorners;<BR>    double counterclockAngle;<BR>    long elevAccuracyCode;<BR>      <BR>       double spatialResX,spatialResY,spatialResZ;<BR>       long profileRows,profileColumns;<BR>    long largeContInt,maxSourceUnits,smallContInt,minSourceUnits;<BR>    long sourceDate, inspRevDate;<BR>    string inspFlag;<BR>    long valFlag;<BR>    long suspectVoidFlg;<BR>    long vertDatum,horizDatum;<BR>    long dataEdition;<BR>    long perctVoid;<BR>    long westEdgeFlag,northEdgeFlag,eastEdgeFlag,southEdgeFlag;<BR>    double vertDatumShift;               //通过文件流得到DEM文件头信息<BR>   <BR>   <BR>    char bufstr[1024];<BR>    char temp[1024];<BR>    long i;</P>
<P>     DEMUtil::getRecord(dem,bufstr);             //从文件流中获得信息</P>
<P>     strncpy(temp, bufstr, 40);              //从获得信息中拷贝到临时变量<BR>     temp[40] = '\0';<BR>     quadName = temp;</P>
<P>     strncpy(temp,bufstr+40,40);              //从获得信息中拷贝到临时变量<BR>     temp[40] = '\0';<BR>     processInfo = temp;<BR>    <BR>     DEMUtil::getDouble(bufstr, 109, 13, seGeoCornerX);<BR>     DEMUtil::getDouble(bufstr, 122, 13, seGeoCornerY);<BR>     processCode = DEMUtil::getLong(bufstr, 135, 1);         //135 = 122 + 13</P>
<P>     strncpy(temp,bufstr+137,3);<BR>     temp[3] = '\0';<BR>     sectionIndicator = temp;</P>
<P>     strncpy(temp,bufstr+140,4);<BR>     temp[4] = '\0';<BR>     mapCenterCode = temp;<BR>     <BR>     levelCode = DEMUtil::getLong(bufstr, 144, 6);         //level编码<BR>     elevPattern = DEMUtil::getLong(bufstr, 150, 6);<BR>     groundRefSysCode = DEMUtil::getLong(bufstr, 156, 6);<BR>     groundRefSysZone = DEMUtil::getLong(bufstr, 162, 6);<BR>     groundRefSysUnits = DEMUtil::getLong(bufstr, 528, 6);       //得到平面上使用的度量单位<BR>     elevUnits = DEMUtil::getLong(bufstr, 534, 6);         //得到Z轴上的度量单位<BR>     numPolySides = DEMUtil::getLong(bufstr, 540, 6);</P>
<P>     for (i = 0; i < 4; i++)<BR>     {<BR>     double x,y;<BR>     long pos = 546 + (i * 48);<BR>     DEMUtil::getDouble(bufstr, pos, 24, x);<BR>     DEMUtil::getDouble(bufstr, pos + 24, 24, y);<BR>     demCorners.push_back(DEMPoint(x,y));          //各角部顶点数据<BR>     }</P>
<P>     DEMUtil::getDouble(bufstr, 738, 24, m_dminElevation);       //得到最小高程数值<BR>     DEMUtil::getDouble(bufstr, 762, 24, m_dmaxElevation);       //得到最大高程数值 <BR>     DEMUtil::getDouble(bufstr, 786, 24, counterclockAngle );<BR>     elevAccuracyCode = DEMUtil::getLong(bufstr, 810, 6);<BR>     DEMUtil::getDouble(bufstr, 816, 12, spatialResX);        //X轴分辨率<BR>     DEMUtil::getDouble(bufstr, 828, 12, spatialResY);        //Y轴分辨率<BR>     DEMUtil::getDouble(bufstr, 840, 12, spatialResZ);        //Z轴分辨率<BR>     profileRows = DEMUtil::getLong(bufstr, 852, 6);         //得到行数<BR>     profileColumns = DEMUtil::getLong(bufstr, 858, 6);        //得到列数<BR>     largeContInt = DEMUtil::getLong(bufstr, 864, 5);<BR>     maxSourceUnits = DEMUtil::getLong(bufstr, 869, 1);<BR>     smallContInt = DEMUtil::getLong(bufstr, 870, 5);<BR>     minSourceUnits = DEMUtil::getLong(bufstr, 875, 1);<BR>     sourceDate = DEMUtil::getLong(bufstr, 876, 4);<BR>     inspRevDate = DEMUtil::getLong(bufstr, 880, 4);<BR>    <BR>     strncpy(temp, bufstr+884,1);<BR>     temp[1]='\0';<BR>     inspFlag = temp;</P>
<P>     valFlag = DEMUtil::getLong(bufstr, 885, 1);<BR>     suspectVoidFlg = DEMUtil::getLong(bufstr, 886, 2);<BR>     vertDatum = DEMUtil::getLong(bufstr, 888, 2);   //垂直<BR>     horizDatum = DEMUtil::getLong(bufstr, 890, 2);      //水平<BR>     dataEdition = DEMUtil::getLong(bufstr, 892, 4);<BR>     perctVoid = DEMUtil::getLong(bufstr, 896, 4);<BR>     westEdgeFlag = DEMUtil::getLong(bufstr, 900, 2);   //西部<BR>     northEdgeFlag = DEMUtil::getLong(bufstr, 902, 2); //北部<BR>     eastEdgeFlag = DEMUtil::getLong(bufstr, 904, 2);   //东部<BR>     southEdgeFlag = DEMUtil::getLong(bufstr, 906, 2); //南部<BR>     DEMUtil::getDouble(bufstr, 908, 7, vertDatumShift);</P>
<P>     m_p3dDEMGrid->SetXMin( demCorners[0].getX() );<BR>     m_p3dDEMGrid->SetYMin( demCorners[0].getY() );<BR>     m_p3dDEMGrid->SetXCellSize( spatialResX );<BR>     m_p3dDEMGrid->SetYCellSize( spatialResY );<BR>     m_p3dDEMGrid->SetColumns( profileColumns );<BR>   <BR>     long retval;</P>
<P>    retval = FillGeographic(dem,incrementalRead);</P>
<P>long ImportDEMDataUSGS::FillGeographic(istream; dem,bool incrementalRead)<BR>{<BR>if (m_bReadingFileHeadOnlyOnce) <BR>{<BR>   m_lCurProfile = 0;<BR>}</P>
<P>    while (m_lCurProfile < m_p3dDEMGrid->GetColumns())          //断面数据还没有读完<BR>    {<BR>          m_vecProfiles.push_back(DEMProfile());<BR>          dem >> m_vecProfiles.back();              //存储断面数据<BR>          m_lCurProfile++;<BR>          if (incrementalRead)                //倘若采用增量读法,则马上返回<BR>             return m_p3dDEMGrid->GetColumns() - m_lCurProfile + 1;<BR>    }<BR>   <BR>    int width = m_p3dDEMGrid->GetColumns();<BR>    int height = m_vecProfiles[0].getNumberOfElevations();         //假设所有的断面和第一个断面有一样的一连串高程数值<BR>    m_p3dDEMGrid->SetRows( height );</P>
<P>    m_ppt3dPoint = new POINT3d[width * height];            //added</P>
<P>    double dXMin = m_p3dDEMGrid->GetXMin();<BR>    double dYMin = m_p3dDEMGrid->GetYMin();<BR>    double dXCellSize = m_p3dDEMGrid->GetXCellSize();<BR>    double dYCellSize = m_p3dDEMGrid->GetYCellSize();<BR>    int i,j;<BR>    long Index;<BR>    for (i = 1; i < width; i++)<BR>    {<BR>         DEMElevationVector const; elev = m_vecProfiles.getElevations();     //得到这个断面的一连串高程数值<BR>   for (j = 0; j < height; j++)<BR>   {<BR>             Index = width * j + i;<BR>    m_ppt3dPoint[Index][0]=dXMin + i*dXCellSize;            <BR>    m_ppt3dPoint[Index][1]=dYMin + j*dYCellSize;     <BR>    m_ppt3dPoint[Index][2]=elev[j]/m_dPlaneHeightRadio;       //保证三轴单位统一<BR>   }<BR>    }</P>
<P>i=0;                     //为了填充数组第一列<BR>DEMElevationVector const; elev_1 = m_vecProfiles[1].getElevations();<BR>for(j = 0; j < elev_1.size();j++)<BR>{<BR>    Index = width * j + i;<BR>    m_ppt3dPoint[Index][0]=dXMin + i*dXCellSize;        <BR>    m_ppt3dPoint[Index][1]=dYMin + j*dYCellSize;<BR>    m_ppt3dPoint[Index][2]=elev_1[j]/m_dPlaneHeightRadio;    <BR>  <BR>}<BR>m_vecProfiles.erase(m_vecProfiles.begin(), m_vecProfiles.end());<BR>return 0;<BR>}<BR></P>
<P><IMG src="http://hiphotos.baidu.com/wuhanhoutao/pic/item/22cdc0ee53e9c0222cf534f8.jpg" border=0></P>
<P><FONT face="Courier New">   SDTS(Spatial Data Transfer Standard ) DEM 读取也是颇费力的一件事情,首先这个体系并不是一个单一的数据文件,而是由一系列的相同后缀(.ddf)构成文件的组合.其中,*CATD.DDF是首要文件,相当于一个索引,告知其他文件的功能.剩下的文件中,*LDEF.DDF可以获得格网的长宽数值。*IREF.DDF文件可以得到XY轴的分辨率。*CELL.DDF是真正带有数据的文件。可以提取高程数值。另外还涉及到读取8211文件的问题,所以说,是件比较费力的事情.<BR>    在<a href="http://wuhanhoutao.cnblogs.com/" target="_blank" >http://wuhanhoutao.cnblogs.com/</A>提供程序框架和结果图供大家参考。愿与大家多多交流.<BR></FONT></P>
喜欢0 评分0
游客

返回顶部