vs2013+NetCDF三维数据的读取方法
一、环境
环境:win7+vs2013+NetCDF4.4.2
二、测试数据样例
测试的是读取三维经度是的数据,该数据个数总共有120241480个,我这里的120指的是时间索引数,241和480指经纬度。
图1如下:
说明:
1、时间、经度、纬度个数。
2、scale_factor:缩放因子。
3、add_offset:截距值。
4、_FillValue:填充值。
5、missing_value:无效值。
6、units:温度单位。
数据表:
三、测试效果
四、核心代码
1、主要函数接口
/// 根据varname获得其对应的3维以上维数组数据:例如温度点。目前仅测试3维数据的读取没有问题,一维二维的读取使用该接口有问题,还需要完善
/// 参数说明:
/// varname:变量名字;scaleFactor:缩放因子;addOffset:截距值;missingValue:无效值;timeName:时间变量名称;levelName:层次变量名称;dataVector:读取的数据
/// timeName:一般三维数据时使用
/// levelName:一般是四维数据时使用,如果不是四维的话直接填充空值即可
用到的成员变量:
int m_ncid;
函数接口:
int ReadNCFile::getVarDataArrayManyD(const char *varName, const char *scaleFactor, const char *addOffset, const char *missingValue, const char *timeName, const char *levelName, vector<float> &dataVector)
{
int ret = 0;
int varid = 0;
if (ret = nc_inq_varid(m_ncid, varName, &varid))
ERR(ret);
//获取对应变量的维度
int dimsCount = 0;
if (ret = nc_inq_varndims(m_ncid, varid, &dimsCount))
ERR(ret);
//获取每一维的长度
int *dimidsp = new int[dimsCount];
nc_inq_vardimid(m_ncid, varid, dimidsp);
size_t* dimLenp = new size_t[dimsCount];
for (int i = 0; i < dimsCount; ++i)
{
nc_inq_dimlen(m_ncid, dimidsp[i], &dimLenp[i]);
}
size_t* startp = new size_t[dimsCount];
size_t* countp = new size_t[dimsCount];
int nSizeX = 0;
int nSizeY = 0;
//至少是一维数据
nSizeX = dimLenp[dimsCount - 1];
startp[dimsCount - 1] = 0;
countp[dimsCount - 1] = nSizeX;
//如果大于一维
if (dimsCount > 1)
{
nSizeY = dimLenp[dimsCount - 2];
startp[dimsCount - 2] = 0;
countp[dimsCount - 2] = nSizeY;
}
//如果大于二维
if (dimsCount == 3)
{
int dimLevelid = 0;
size_t dimLevel = 0;
int levelFlag = nc_inq_dimid(m_ncid, timeName, &dimLevelid);
nc_inq_dimlen(m_ncid, dimLevelid, &dimLevel);
int dimTimeid = 0;
size_t dimTime = 0;
int timeFlag = nc_inq_dimid(m_ncid, levelName, &dimTimeid);
nc_inq_dimlen(m_ncid, dimTimeid, &dimTime);
if (dimLevel > 0 && levelFlag == 0)
{
startp[0] = m_nLevel;
}
else if (dimTime > 0 && timeFlag == 0)
{
startp[0] = m_nTime;
}
else
{
startp[0] = 0;
}
countp[0] = 1;//指定取几个时次或层次的数据
}
else if (dimsCount == 4)
{
startp[0] = 0;//指定从第几个时次取数据
startp[1] = 1;//指定从第几个层次取数据
countp[0] = 1;//指定取几个时次的数据
countp[1] = 1;//指定取几个层次的数据
}
//Read the data.
dataVector.resize(nSizeX * nSizeY);
if (ret = nc_get_vara_float(m_ncid, varid, &startp[0], &countp[0], &dataVector[0]))
ERR(ret);
if (scaleFactor != "" || addOffset != "" || missingValue != "")
{
float addOffsetNum;// 截距值
float scaleFactorNum;//缩放因子
float missingValueNum;//无效值
//获取变量的一些属性信息
if ((ret = nc_get_att_float(m_ncid, varid, scaleFactor, &scaleFactorNum)))
ERR(ret);
if ((ret = nc_get_att_float(m_ncid, varid, addOffset, &addOffsetNum)))
ERR(ret);
if ((ret = nc_get_att_float(m_ncid, varid, missingValue, &missingValueNum)))
ERR(ret);
for (int i = 0; i < dataVector.size(); ++i)
{
if (dataVector[i] != missingValueNum)
{
dataVector[i] = dataVector[i] * scaleFactorNum + addOffsetNum;
}
}
}
}
2、测试核心代码
vector<float> dataArray;
pTempFile->getVarDataArrayManyD("sst", "scale_factor", "add_offset", "missing_value","", "time", dataArray);
vector<float>::iterator iterData;
for (iterData = dataArray.begin(); iterData != dataArray.end();)
{
static int flag = 0;
flag++;
float tempdata = *iterData;
cout << "tempdata=" << tempdata << endl;
if (flag == 30)
break;
}
说明:根据自己的实际情况请参考使用,更多问题请参考博客中的其他文章。
本文为博主原创文章,未经博主允许请勿转载!作者:ISmileLi