You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
256 lines
4.9 KiB
C++
256 lines
4.9 KiB
C++
#include "StdAfx.h"
|
|
#include "GetElevation.h"
|
|
|
|
// tiff文件读取
|
|
#include "gdal_priv.h"
|
|
#include "cpl_conv.h" //for CPLMalloc()
|
|
|
|
// boost-1.56:准C++标准库
|
|
#include <boost/lexical_cast.hpp>
|
|
#include <boost/format.hpp>
|
|
|
|
#include <vector>
|
|
using namespace std;
|
|
|
|
|
|
// 定义高程图像存储结构体
|
|
#pragma pack(1)
|
|
struct struDemPic
|
|
{
|
|
struDemPic()
|
|
{
|
|
pDEMData = NULL;
|
|
};
|
|
|
|
virtual ~struDemPic()
|
|
{
|
|
if (pDEMData != NULL)
|
|
{
|
|
delete[] pDEMData;
|
|
pDEMData = NULL;
|
|
}
|
|
}
|
|
|
|
signed short int *pDEMData;
|
|
string strDemName;
|
|
double adfGeoTransform[6];
|
|
int iXSize;
|
|
int iYSize;
|
|
};
|
|
#pragma pack()
|
|
|
|
// 定义类型: DEM_PIC_LIST
|
|
typedef vector<struDemPic*> DEM_PIC_LIST;
|
|
|
|
// 全局变量
|
|
DEM_PIC_LIST g_DemPicList;
|
|
|
|
// 基于经纬度 计算tif文件名称
|
|
string GetDemName( const float fLonDeg, const float fLatDeg )
|
|
{
|
|
string sLatLon; // 输出
|
|
|
|
int iLon = (int) fLonDeg;
|
|
int iLat = (int) fLatDeg;
|
|
|
|
//判断经纬度在正常范围之内
|
|
if ((fLonDeg < -180) || (fLonDeg > 180))
|
|
{
|
|
return "";
|
|
}
|
|
|
|
if ((fLatDeg < -90) || (fLatDeg > 90))
|
|
{
|
|
return "";
|
|
}
|
|
|
|
string sLat, sLon;
|
|
|
|
|
|
// 纬度 南北纬 区别对待
|
|
boost::format fmt("S%02d");
|
|
if (fLatDeg <= 0)
|
|
{
|
|
fmt % ((-iLat) + 1);
|
|
sLat = fmt.str();
|
|
}
|
|
else
|
|
{
|
|
fmt = boost::format("N%02d");
|
|
fmt % iLat;
|
|
sLat = fmt.str();
|
|
}
|
|
|
|
// 经度 东西经 区别对待
|
|
if (fLonDeg <= 0)
|
|
{
|
|
fmt = boost::format("W%03d");
|
|
fmt % ((-iLon) + 1);
|
|
sLon = fmt.str();
|
|
}
|
|
else
|
|
{
|
|
fmt = boost::format("E%03d");
|
|
fmt % iLon;
|
|
sLon = fmt.str();
|
|
}
|
|
|
|
sLatLon = "ASTGTM_" + sLat + sLon + "_dem.tif";
|
|
return sLatLon;
|
|
}
|
|
|
|
|
|
// 搜寻文件路径是否已经存在
|
|
int FindDemDataSet( const string strDemName )
|
|
{
|
|
for ( unsigned int i = 0; i < g_DemPicList.size(); i++ )
|
|
{
|
|
if ( g_DemPicList[i]->strDemName == strDemName )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
bool GetDem( float& fElevator, const float fLonDeg, const float fLatDeg, struDemPic* pDemPic )
|
|
{
|
|
// 空值判断
|
|
if (pDemPic == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 分辨率 判断
|
|
if (pDemPic->adfGeoTransform[1] <= 0 || pDemPic->adfGeoTransform[5] >= 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 计算像素坐标
|
|
float px = float(( fLonDeg - pDemPic->adfGeoTransform[0] ) / pDemPic->adfGeoTransform[1]);
|
|
float py = float(( pDemPic->adfGeoTransform[3] - fLatDeg ) / fabs(pDemPic->adfGeoTransform[5]));
|
|
|
|
//防止越界
|
|
if ((px < 0) || (px > pDemPic->iXSize - 1) ||
|
|
(py < 0) || ( py > pDemPic->iYSize - 1))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 规则:双线性内插 计算高程值
|
|
int yt = 0, yb = 0; // y 上下
|
|
int xl = 0, xr = 0; // x 左右
|
|
|
|
yt = int(py);
|
|
yb = yt + 1;
|
|
xl = int(px);
|
|
xr = xl + 1;
|
|
|
|
if ((xl < 0) || (xl > pDemPic->iXSize - 1) ||
|
|
(xr < 0) || (xr > pDemPic->iYSize - 1))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ((yt < 0) || (yt > pDemPic->iXSize - 1) ||
|
|
(yb < 0) || (yb > pDemPic->iYSize - 1))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 相邻四个像素的值
|
|
signed short int DNlt = *(pDemPic->pDEMData + yt * pDemPic->iXSize + xl);
|
|
signed short int DNrt = *(pDemPic->pDEMData + yt * pDemPic->iXSize + xr);
|
|
signed short int DNlb = *(pDemPic->pDEMData + yb * pDemPic->iXSize + xl);
|
|
signed short int DNrb = *(pDemPic->pDEMData + yb * pDemPic->iXSize + xr);
|
|
|
|
// 间距
|
|
float h, v;
|
|
h = py - yt;
|
|
v = px - xl;
|
|
|
|
fElevator = DNlt * (1 - h) * (1 - v) + DNlb * h * (1 - v)+ DNrt * (1 - h) * v + DNrb * h * v;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
// 获取高程
|
|
bool GetDem( float& fElevator, float fLonDeg, float fLatDeg, string sDir)
|
|
{
|
|
// tif文件 名称
|
|
string strName = GetDemName(fLonDeg, fLatDeg);
|
|
if (strName == "")
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// tif文件 路径名称
|
|
string strPathName;
|
|
|
|
if (sDir != "")
|
|
{
|
|
strPathName = sDir + "\\" + strName;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
// 是否能在记录中找到
|
|
int idx = FindDemDataSet(strPathName);
|
|
if (idx >= 0)
|
|
{
|
|
return GetDem(fElevator, fLonDeg, fLatDeg, g_DemPicList[idx]);;
|
|
}
|
|
|
|
//如果在数据集数组中找不到 读取文件并添加到数据集
|
|
// 注册
|
|
GDALAllRegister();
|
|
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
|
|
|
|
GDALDataset* tempdata = NULL;
|
|
tempdata = (GDALDataset*) GDALOpen(strPathName.c_str(), GA_ReadOnly);
|
|
if ( tempdata != NULL )
|
|
{
|
|
GDALDataType dataType = tempdata->GetRasterBand(1)->GetRasterDataType();
|
|
int iXSzie = tempdata->GetRasterBand(1)->GetXSize();
|
|
int iYSzie = tempdata->GetRasterBand(1)->GetYSize();
|
|
struDemPic* temp = new struDemPic;
|
|
temp->iXSize = iXSzie;
|
|
temp->iYSize = iYSzie;
|
|
tempdata->GetGeoTransform(temp->adfGeoTransform);
|
|
temp->pDEMData = new signed short int[iXSzie * iYSzie];
|
|
|
|
memset((void*) temp->pDEMData, 0, iXSzie * iYSzie * sizeof(signed short int));
|
|
tempdata->GetRasterBand(1)->RasterIO( GF_Read, 0, 0, iXSzie, iYSzie, temp->pDEMData, iXSzie, iYSzie, GDT_Int16, 0, 0 );
|
|
GDALClose(tempdata);
|
|
|
|
// 入队 存储
|
|
temp->strDemName = strPathName;
|
|
g_DemPicList.push_back(temp);
|
|
|
|
return GetDem(fElevator, fLonDeg, fLatDeg, g_DemPicList[g_DemPicList.size() - 1]);;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//功能:释放资源
|
|
void ReleaseDemMemory()
|
|
{
|
|
// 高程数集
|
|
for (unsigned int i = 0; i < g_DemPicList.size(); i++ )
|
|
{
|
|
if ( g_DemPicList[i] != NULL )
|
|
{
|
|
delete g_DemPicList[i];
|
|
}
|
|
}
|
|
g_DemPicList.clear();
|
|
}
|
|
|