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

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值