JAVA:通过netcdf.dll操作nc、grib2文件

1、操作nc文件

//12ceng
public static void readERA5NcDuoCeng(String inputFile,int ceng) {
	
	String outputFile="E://Pic/chenxia/不同高度风数据/output/";
	
	int point=2;
	double lonSize=0.125;
	double latSize=-0.125;
	
	NetcdfFile openNC = null;
	try {
		openNC = NetcdfFile.open(inputFile);
		Variable dataU = openNC.findVariable("u");
		Variable dataV = openNC.findVariable("v");
		Variable Lat=openNC.findVariable("latitude");
		Variable Lon=openNC.findVariable("longitude");
		Variable Level=openNC.findVariable("level");
		Variable time=openNC.findVariable("time");
		float[] arrLat=(float[]) Lat.read().copyTo1DJavaArray();
		float[] arrLon=(float[]) Lon.read().copyTo1DJavaArray();
		int[] arrLevel=(int[]) Level.read().copyTo1DJavaArray();
		int latCount=arrLat.length;
		int lonCount=arrLon.length;
		int levelCount=arrLevel.length;
		
		BigDecimal b=new BigDecimal(arrLon[0]);
		double dBeginLon=b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
		b=new BigDecimal(arrLat[0]);
		double dBeginLat=b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
		b=new BigDecimal(arrLat[latCount-1]);
		double dEndLat=b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
		b=new BigDecimal(arrLon[lonCount-1]);
		double dEndLon=b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
		
		double u_scale_factor=0,u_add_offset=0;
		List<Attribute> uAttr = dataU.getAttributes();
		for (Attribute attribute : uAttr) {
			if(attribute.getShortName().equals("scale_factor")) {
				Array aString = attribute.getValues();
				u_scale_factor=aString.getDouble(0);
			}
			else if(attribute.getShortName().equals("add_offset")) {
				Array aString = attribute.getValues();
				u_add_offset=aString.getDouble(0);
			}
		}
		
		double v_scale_factor=0,v_add_offset=0;
		List<Attribute> vAttr = dataV.getAttributes();
		for (Attribute attribute : vAttr) {
			if(attribute.getShortName().equals("scale_factor")) {
				Array aString = attribute.getValues();
				v_scale_factor=aString.getDouble(0);
			}
			else if(attribute.getShortName().equals("add_offset")) {
				Array aString = attribute.getValues();
				v_add_offset=aString.getDouble(0);
			}
		}
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:00:00");	
		Calendar calendar=Calendar.getInstance();
		int[] arrTime=(int[]) time.read().copyTo1DJavaArray();
		for(int m=0;m<levelCount;m++) {
			if(arrLevel[m]!=ceng) {
				continue;
			}
			for (int j = 0; j < arrTime.length; j++) {
				int t = arrTime[j];	
				calendar.setTime(sdf.parse("1900-01-01 00:00:00"));
				calendar.add(Calendar.HOUR, t);
				String forecastDate=new SimpleDateFormat("yyyyMMdd000000").format(calendar.getTime());
				
				short[][] arrU= (short[][])dataU.read(new int [] {j,m,0,0},new int [] {1,1,latCount,lonCount}).reduce().copyToNDJavaArray();
				short[][] arrV= (short[][])dataV.read(new int [] {j,m,0,0},new int [] {1,1,latCount,lonCount}).reduce().copyToNDJavaArray();
				
				
				double[][] arrDoubleU=new double[latCount][lonCount];
				for(int x=0;x<latCount;x++) {
					for(int y=0;y<lonCount;y++) {
						if(arrU[x][y]==-32767) {
							arrDoubleU[x][y]=-32767;
						}else {
							arrDoubleU[x][y]=arrU[x][y]*u_scale_factor+u_add_offset;
						}
					}
				}
				
				double[][] arrDoubleV=new double[latCount][lonCount];
				for(int x=0;x<latCount;x++) {
					for(int y=0;y<lonCount;y++) {
						if(arrV[x][y]==-32767) {
							arrDoubleV[x][y]=-32767;
						}else {
							arrDoubleV[x][y]=arrV[x][y]*v_scale_factor+v_add_offset;							
						}
					}
				}					
			}
		}
	}catch (Exception e) {
		e.printStackTrace();
	}finally {
		try {
			openNC.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

2、操作grib2文件

public SmartGridForecastModel readData(String filePath, double beginLon, double beginLat, double endLon, double endLat, int[] arrForecastTime) throws Exception {
		NetcdfFile netcdfFile = null;
		try {
			// 打开文件
			netcdfFile = NetcdfFile.open(filePath,null);

			// 获取变量
			Variable varLon = netcdfFile.findVariable(lonFieldText);
			Variable varLat = netcdfFile.findVariable(latFieldText);
			Variable varTime = netcdfFile.findVariable(timeFieldText);
			Variable varData = netcdfFile.findVariable(dataFieldText);
			if (varLon == null || varLat == null || varTime == null || varData == null) {
				return null;
			}

			// 定义文件头和数据体
			SmartGridForecastHeader header = new SmartGridForecastHeader();
			List<SmartGridForecastData> listData = new ArrayList<SmartGridForecastData>();
			
			float[] arrLon = (float[]) varLon.read().copyTo1DJavaArray();
			float[] arrLat = (float[]) varLat.read().copyTo1DJavaArray();
			int[] arrTime =	(int[]) varTime.read().copyTo1DJavaArray();
			
			int beginY= Arrays.binarySearch(arrLat, (float)beginLat);
			int beginX= Arrays.binarySearch(arrLon, (float)beginLon);
			
			int endY= Arrays.binarySearch(arrLat, (float)endLat);
			int endX= Arrays.binarySearch(arrLon, (float)endLon);
												
			// 获取符合经纬度范围、时次条件的数据
			if (arrForecastTime == null) {
				arrForecastTime = arrTime;
			}
			int[] size = new int[] { 1, endX-beginX, endY-beginY };
			for (int forecastTime : arrForecastTime) {
				// 寻找时次
				int timeStart = -1;
				for (int i = 0; i < arrTime.length; i++) {
					if (arrTime[i] == forecastTime) {
						timeStart = i;
						break;
					}
				}
				if (timeStart == -1) {
					continue;
				}

				int[] origin = new int[] { timeStart, beginX, beginY }; // 第一维的timeStart开始,第二维从0开始,第三维从0开始
				float[] arrData = (float[]) varData.read(origin, size).copyTo1DJavaArray();

				int rowIndex = 0;
				int dataIndex = 0;

				for (int latIndex = beginY; latIndex < endY; latIndex++) {
					double lat = DataConvert.toDouble(arrLat[latIndex], 2);
					
					boolean hasRow = false;
					int colIndex = 0;

					for (int lonIndex = beginX; lonIndex < endX; lonIndex++) {
						double lon = DataConvert.toDouble(arrLon[lonIndex], 2);
						
						// 找到的点数据
						SmartGridForecastData data = new SmartGridForecastData();
						data.setForecastTime(forecastTime);
						data.setLon(Float.parseFloat(String.valueOf(lon)));
						data.setLat(Float.parseFloat(String.valueOf(lat)));
						data.setRowIndex(rowIndex);
						data.setColIndex(colIndex);
						data.setValue(arrData[dataIndex]);
						listData.add(data);
						hasRow = true;
						colIndex++;
						dataIndex++;
					}

					if (hasRow) {
						header.setColCount(colIndex);
						rowIndex++;
					}
				}
				header.setRowCount(rowIndex);
			}
			if (listData.size() > 0) {
				header.setBeginLon(Double.parseDouble(String.valueOf(listData.get(0).getLon())));
				header.setBeginLat(Double.parseDouble(String.valueOf(listData.get(0).getLat())));
			}
			header.setGridSize(DataConvert.toDouble(arrLon[1] - arrLon[0], 2));
			header.setArrForecastTime(arrForecastTime);
	
			// 结果集
			SmartGridForecastModel sgfm = new SmartGridForecastModel();
			sgfm.setHeader(header);
			sgfm.setData(listData);
			return sgfm;
		} catch (Exception e) {
			throw e;
		} finally {
			netcdfFile.close();
		}
	}

3、实现双线性插值方法

/** 
	 将格点数据转换为站点数据,取值为双线性插值。
	 	注意:传入的开始经纬、纬度,须匹配二维数组的实际情况,过大或过小都导致转换偏差。
	 @param arrValue 格点行、列数组。
	 @param listStation 站点集合,需包含站号、经度、纬度。
	 @param beginLon 格点集合的起始经度。
	 @param beginLat 格点集合的起始纬度。
	 @param lonSize 经度格点集合的分辨率,1公里则设置0.01。
	 @param latSize 纬度格点集合的分辨率,1公里则设置0.01。
	 @return 新的站点集合。
	 */
public List<StationPoint> convertGridPointToStationPointByBilinear(double[][] arrValue, List<StationPoint> listStation, double beginLon, double beginLat, double lonSize, double latSize){
	//复制一份 listStation
	List<StationPoint> list = new ArrayList<StationPoint>(listStation.size());
	for (int i = 0; i < listStation.size(); i++) {
		StationPoint sp = (StationPoint) listStation.get(i).clone();
		list.add(sp);
	}
	
	int maxRowIndex = arrValue.length - 1;
	int maxColIndex = arrValue[0].length - 1;
	for (StationPoint station : list){
		double rowIndexDouble = (station.getLat() - beginLat) / latSize;
		double colIndexDouble = (station.getLon() - beginLon) / lonSize;

		int rowIndexInt = (int)Math.floor(rowIndexDouble);
		int colIndexInt = (int)Math.floor(colIndexDouble);

		if (rowIndexInt >= maxRowIndex){
			rowIndexInt = maxRowIndex-1;
		}

		if (colIndexInt >= maxColIndex){
			colIndexInt = maxColIndex-1;
		}

		double valueLeftUp = (rowIndexDouble - rowIndexInt) * (colIndexDouble - colIndexInt);
		double valueRightUp = (rowIndexInt + 1 - rowIndexDouble) * (colIndexDouble - colIndexInt);
		double valueRightDown = (rowIndexInt + 1 - rowIndexDouble) * (colIndexInt + 1 - colIndexDouble);
		double valueLeftDown = (rowIndexDouble - rowIndexInt) * (colIndexInt + 1 - colIndexDouble);
		try {
			
			station.setValue(arrValue[rowIndexInt][colIndexInt] * valueRightDown + arrValue[rowIndexInt + 1][colIndexInt] * valueLeftDown + arrValue[rowIndexInt + 1][colIndexInt + 1] * valueLeftUp + arrValue[rowIndexInt][colIndexInt + 1] * valueRightUp);
		} catch (Exception e) {
			System.out.println(station.getLat()+","+station.getLon());
			e.printStackTrace();
		}
	}
	return list;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肆意飞扬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值