气象降采样
This commit is contained in:
parent
b54df8b5f8
commit
20625bdcad
|
|
@ -0,0 +1,7 @@
|
||||||
|
package org.jeecg.common.constant;
|
||||||
|
|
||||||
|
public class WeatherStepConstants {
|
||||||
|
|
||||||
|
|
||||||
|
public static final double DEFAULT_STEP = 0.5;
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.jeecg.common.constant.WeatherPrefixConstants;
|
import org.jeecg.common.constant.WeatherPrefixConstants;
|
||||||
|
import org.jeecg.common.constant.WeatherStepConstants;
|
||||||
import org.jeecg.common.constant.WeatherSuffixConstants;
|
import org.jeecg.common.constant.WeatherSuffixConstants;
|
||||||
import org.jeecg.common.constant.enums.*;
|
import org.jeecg.common.constant.enums.*;
|
||||||
import org.jeecg.common.exception.JeecgBootException;
|
import org.jeecg.common.exception.JeecgBootException;
|
||||||
|
|
@ -94,7 +95,7 @@ public class WeatherDataServiceImpl extends ServiceImpl<WeatherDataMapper, Weath
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据类型和小时数获取天气数据
|
* 气象预览
|
||||||
* @param weatherId 气象数据id
|
* @param weatherId 气象数据id
|
||||||
* @param weatherType 天气类型
|
* @param weatherType 天气类型
|
||||||
* @return 天气数据列表
|
* @return 天气数据列表
|
||||||
|
|
@ -669,11 +670,6 @@ public class WeatherDataServiceImpl extends ServiceImpl<WeatherDataMapper, Weath
|
||||||
*/
|
*/
|
||||||
private WeatherResultVO processWeatherData(Integer weatherType, LocalDateTime targetTime, WeatherDataSourceEnum dataTypeEnum) {
|
private WeatherResultVO processWeatherData(Integer weatherType, LocalDateTime targetTime, WeatherDataSourceEnum dataTypeEnum) {
|
||||||
WeatherResultVO weatherResultVO = new WeatherResultVO();
|
WeatherResultVO weatherResultVO = new WeatherResultVO();
|
||||||
|
|
||||||
if (WeatherTypeEnum.WIND.getKey().equals(weatherType)) {
|
|
||||||
return processWindData(weatherType, targetTime, dataTypeEnum, weatherResultVO);
|
|
||||||
}
|
|
||||||
|
|
||||||
String filePath = buildFilePath(targetTime, weatherType, dataTypeEnum);
|
String filePath = buildFilePath(targetTime, weatherType, dataTypeEnum);
|
||||||
validateFile(filePath);
|
validateFile(filePath);
|
||||||
|
|
||||||
|
|
@ -682,9 +678,27 @@ public class WeatherDataServiceImpl extends ServiceImpl<WeatherDataMapper, Weath
|
||||||
List<Double> latData = NcUtil.getNCList(ncFile, "lat");
|
List<Double> latData = NcUtil.getNCList(ncFile, "lat");
|
||||||
validateLonLatData(lonData, latData, filePath);
|
validateLonLatData(lonData, latData, filePath);
|
||||||
|
|
||||||
List<List<Double>> dataList = processWeatherTypeData(ncFile, lonData, latData, weatherType, dataTypeEnum.getKey());
|
ValueConverter converter = null;
|
||||||
|
if (WeatherTypeEnum.WIND.getKey().equals(weatherType)) {
|
||||||
processResultData(weatherResultVO, dataList, lonData, latData);
|
converter = value -> value;
|
||||||
|
List<List<List<Double>>> windDataList = processWindData(weatherType, targetTime, dataTypeEnum, weatherResultVO);
|
||||||
|
processResultDataInternal(weatherResultVO, null, windDataList.get(0), windDataList.get(1), lonData, latData, converter);
|
||||||
|
}else{
|
||||||
|
List<List<Double>> dataList;
|
||||||
|
if (WeatherTypeEnum.TEMPERATURE.getKey().equals(weatherType)) {
|
||||||
|
converter = value -> value - 273.15;
|
||||||
|
dataList = processVariableData(ncFile, dataTypeEnum.getKey(), WeatherTypeEnum.TEMPERATURE);
|
||||||
|
} else if (WeatherTypeEnum.PRESSURE.getKey().equals(weatherType)) {
|
||||||
|
converter = value -> value / 1000;
|
||||||
|
dataList = processVariableData(ncFile, dataTypeEnum.getKey(), WeatherTypeEnum.PRESSURE);
|
||||||
|
} else if (WeatherTypeEnum.HUMIDITY.getKey().equals(weatherType)) {
|
||||||
|
converter = value -> value;
|
||||||
|
dataList = processVariableData(ncFile, dataTypeEnum.getKey(), WeatherTypeEnum.HUMIDITY);
|
||||||
|
} else {
|
||||||
|
throw new JeecgBootException("未知天气类型!");
|
||||||
|
}
|
||||||
|
processResultDataInternal(weatherResultVO, dataList, null, null, lonData, latData, converter);
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("NetCDF文件处理失败: {}", filePath, e);
|
log.error("NetCDF文件处理失败: {}", filePath, e);
|
||||||
throw new JeecgBootException("文件读取失败", e);
|
throw new JeecgBootException("文件读取失败", e);
|
||||||
|
|
@ -696,8 +710,9 @@ public class WeatherDataServiceImpl extends ServiceImpl<WeatherDataMapper, Weath
|
||||||
/**
|
/**
|
||||||
* 处理风场数据
|
* 处理风场数据
|
||||||
*/
|
*/
|
||||||
private WeatherResultVO processWindData(Integer weatherType, LocalDateTime targetTime,
|
private List<List<List<Double>>> processWindData(Integer weatherType, LocalDateTime targetTime,
|
||||||
WeatherDataSourceEnum dataTypeEnum, WeatherResultVO weatherResultVO) {
|
WeatherDataSourceEnum dataTypeEnum, WeatherResultVO weatherResultVO) {
|
||||||
|
List<List<List<Double>>> windDataList = new ArrayList<>();
|
||||||
if (!WeatherDataSourceEnum.CRA40.equals(dataTypeEnum)) {
|
if (!WeatherDataSourceEnum.CRA40.equals(dataTypeEnum)) {
|
||||||
String filePath = buildFilePath(targetTime, weatherType, dataTypeEnum);
|
String filePath = buildFilePath(targetTime, weatherType, dataTypeEnum);
|
||||||
validateFile(filePath);
|
validateFile(filePath);
|
||||||
|
|
@ -707,8 +722,8 @@ public class WeatherDataServiceImpl extends ServiceImpl<WeatherDataMapper, Weath
|
||||||
WeatherVariableNameEnum.getValueByTypeAndKey(dataTypeEnum.getKey(), WeatherTypeEnum.WIND.getKey()), 0, 0);
|
WeatherVariableNameEnum.getValueByTypeAndKey(dataTypeEnum.getKey(), WeatherTypeEnum.WIND.getKey()), 0, 0);
|
||||||
List<List<Double>> v = NcUtil.get2DNCByName(ncFile,
|
List<List<Double>> v = NcUtil.get2DNCByName(ncFile,
|
||||||
WeatherVariableNameEnum.getValueByTypeAndKey(dataTypeEnum.getKey(), WeatherTypeEnum.WIND.getKey() + 1), 0, 0);
|
WeatherVariableNameEnum.getValueByTypeAndKey(dataTypeEnum.getKey(), WeatherTypeEnum.WIND.getKey() + 1), 0, 0);
|
||||||
|
windDataList.add(u);
|
||||||
setWindResult(weatherResultVO, u, v);
|
windDataList.add(v);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("NetCDF文件处理失败", e);
|
log.error("NetCDF文件处理失败", e);
|
||||||
throw new JeecgBootException("文件读取失败", e);
|
throw new JeecgBootException("文件读取失败", e);
|
||||||
|
|
@ -727,13 +742,14 @@ public class WeatherDataServiceImpl extends ServiceImpl<WeatherDataMapper, Weath
|
||||||
List<List<Double>> v = NcUtil.get2DNCByName(vNcFile,
|
List<List<Double>> v = NcUtil.get2DNCByName(vNcFile,
|
||||||
WeatherVariableNameEnum.getValueByTypeAndKey(dataTypeEnum.getKey(), WeatherTypeEnum.WIND.getKey() + 1), 0, 0);
|
WeatherVariableNameEnum.getValueByTypeAndKey(dataTypeEnum.getKey(), WeatherTypeEnum.WIND.getKey() + 1), 0, 0);
|
||||||
|
|
||||||
setWindResult(weatherResultVO, u, v);
|
windDataList.add(u);
|
||||||
|
windDataList.add(v);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("NetCDF文件处理失败", e);
|
log.error("NetCDF文件处理失败", e);
|
||||||
throw new JeecgBootException("文件读取失败", e);
|
throw new JeecgBootException("文件读取失败", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return weatherResultVO;
|
return windDataList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -751,31 +767,13 @@ public class WeatherDataServiceImpl extends ServiceImpl<WeatherDataMapper, Weath
|
||||||
weatherResultVO.setDataList(results);
|
weatherResultVO.setDataList(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理天气类型数据
|
|
||||||
*/
|
|
||||||
private List<List<Double>> processWeatherTypeData(NetcdfFile ncFile, List<Double> lonData, List<Double> latData,
|
|
||||||
Integer weatherType, int dataType) {
|
|
||||||
if (WeatherTypeEnum.TEMPERATURE.getKey().equals(weatherType)) {
|
|
||||||
return processVariableData(ncFile, lonData, latData, dataType, WeatherTypeEnum.TEMPERATURE, value -> value - 273.15);
|
|
||||||
} else if (WeatherTypeEnum.PRESSURE.getKey().equals(weatherType)) {
|
|
||||||
return processVariableData(ncFile, lonData, latData, dataType, WeatherTypeEnum.PRESSURE, value -> value / 1000);
|
|
||||||
} else if (WeatherTypeEnum.HUMIDITY.getKey().equals(weatherType)) {
|
|
||||||
return processVariableData(ncFile, lonData, latData, dataType, WeatherTypeEnum.HUMIDITY, value -> value);
|
|
||||||
} else {
|
|
||||||
throw new JeecgBootException("未知天气类型!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理变量数据
|
* 处理变量数据
|
||||||
*/
|
*/
|
||||||
private List<List<Double>> processVariableData(NetcdfFile ncFile, List<Double> lonData, List<Double> latData,
|
private List<List<Double>> processVariableData(NetcdfFile ncFile, int dataType, WeatherTypeEnum weatherType) {
|
||||||
int dataType, WeatherTypeEnum weatherType, ValueConverter converter) {
|
|
||||||
try {
|
try {
|
||||||
String variableName = WeatherVariableNameEnum.getValueByTypeAndKey(dataType, weatherType.getKey());
|
String variableName = WeatherVariableNameEnum.getValueByTypeAndKey(dataType, weatherType.getKey());
|
||||||
List<List<Double>> dataList = NcUtil.get2DNCByName(ncFile, variableName, 0, 0);
|
return NcUtil.get2DNCByName(ncFile, variableName, 0, 0);
|
||||||
return processWeatherData(dataList, lonData, latData, converter);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("处理{}数据失败", weatherType.name(), e);
|
log.error("处理{}数据失败", weatherType.name(), e);
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
|
@ -850,17 +848,230 @@ public class WeatherDataServiceImpl extends ServiceImpl<WeatherDataMapper, Weath
|
||||||
/**
|
/**
|
||||||
* 处理结果数据
|
* 处理结果数据
|
||||||
*/
|
*/
|
||||||
private void processResultData(WeatherResultVO weatherResultVO, List<List<Double>> dataList,
|
/**
|
||||||
List<Double> lonData, List<Double> latData) {
|
* 内部处理方法
|
||||||
List<Double> flattenedList = new ArrayList<>();
|
*/
|
||||||
flattenList(dataList, flattenedList);
|
private void processResultDataInternal(WeatherResultVO weatherResultVO, List<List<Double>> dataList,
|
||||||
List<Double> maxMin = getMaxMin(flattenedList);
|
List<List<Double>> uDataList, List<List<Double>> vDataList,
|
||||||
|
List<Double> lonData, List<Double> latData, ValueConverter converter) {
|
||||||
|
// 统一将采样率降为0.5
|
||||||
|
double originalStep = getOriginalStep(lonData, latData);
|
||||||
|
double targetStep = WeatherStepConstants.DEFAULT_STEP;
|
||||||
|
|
||||||
weatherResultVO.setMax(maxMin.get(0));
|
if (originalStep < targetStep - 0.001) { // 添加容差避免浮点数比较问题
|
||||||
weatherResultVO.setMin(maxMin.get(1));
|
// 需要降采样
|
||||||
|
int ratio = calculateSafeRatio(originalStep, targetStep);
|
||||||
|
|
||||||
|
// 根据数据类型进行降采样
|
||||||
|
if (dataList != null) {
|
||||||
|
dataList = downsampleData(dataList, ratio);
|
||||||
|
} else if (uDataList != null && vDataList != null) {
|
||||||
|
uDataList = downsampleData(uDataList, ratio);
|
||||||
|
vDataList = downsampleData(vDataList, ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
lonData = downsampleLonLat(lonData, ratio);
|
||||||
|
latData = downsampleLonLat(latData, ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Double> maxMinLon = getMaxMin(lonData);
|
||||||
|
List<Double> maxMinLat = getMaxMin(latData);
|
||||||
|
|
||||||
|
weatherResultVO.setMaxLong(maxMinLon.get(0));
|
||||||
|
weatherResultVO.setMinLong(maxMinLon.get(1));
|
||||||
|
weatherResultVO.setMaxLat(maxMinLat.get(0));
|
||||||
|
weatherResultVO.setMinLat(maxMinLat.get(1));
|
||||||
weatherResultVO.setSn(latData.size());
|
weatherResultVO.setSn(latData.size());
|
||||||
weatherResultVO.setWe(lonData.size());
|
weatherResultVO.setWe(lonData.size());
|
||||||
weatherResultVO.setDataList(dataList);
|
weatherResultVO.setXSpeed(targetStep);
|
||||||
|
weatherResultVO.setYSpeed(targetStep);
|
||||||
|
|
||||||
|
// 根据数据类型选择不同的处理方法
|
||||||
|
if (dataList != null) {
|
||||||
|
// 处理普通气象数据
|
||||||
|
List<Double> flattenedList = new ArrayList<>();
|
||||||
|
flattenList(dataList, flattenedList);
|
||||||
|
List<Double> maxMinValue = getMaxMin(flattenedList);
|
||||||
|
weatherResultVO.setMax(maxMinValue.get(0));
|
||||||
|
weatherResultVO.setMin(maxMinValue.get(1));
|
||||||
|
weatherResultVO.setDataList(resultWeatherData(dataList, lonData, latData, converter));
|
||||||
|
} else if (uDataList != null && vDataList != null) {
|
||||||
|
// 处理风场数据
|
||||||
|
List<Double> flattenedUList = new ArrayList<>();
|
||||||
|
List<Double> flattenedVList = new ArrayList<>();
|
||||||
|
flattenList(uDataList, flattenedUList);
|
||||||
|
flattenList(vDataList, flattenedVList);
|
||||||
|
|
||||||
|
// 风场的最大值最小值可以基于风速大小计算,或者分别处理U、V分量
|
||||||
|
List<Double> maxMinU = getMaxMin(flattenedUList);
|
||||||
|
List<Double> maxMinV = getMaxMin(flattenedVList);
|
||||||
|
weatherResultVO.setMaxU(maxMinU.get(0));
|
||||||
|
weatherResultVO.setMinU(maxMinU.get(1));
|
||||||
|
weatherResultVO.setMaxV(maxMinV.get(0));
|
||||||
|
weatherResultVO.setMinV(maxMinV.get(1));
|
||||||
|
weatherResultVO.setDataList(resultWindData(uDataList, vDataList, lonData, latData, converter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理风场数据(只有U、V分量)
|
||||||
|
*/
|
||||||
|
private List<List<Double>> resultWindData(List<List<Double>> uDataList, List<List<Double>> vDataList,
|
||||||
|
List<Double> lonData, List<Double> latData, ValueConverter converter) {
|
||||||
|
List<List<Double>> results = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < latData.size(); i++) {
|
||||||
|
for (int j = 0; j < lonData.size(); j++) {
|
||||||
|
// 获取风场U、V分量
|
||||||
|
double uValue = j < uDataList.get(i).size() ? uDataList.get(i).get(j) : uDataList.get(i).get(0);
|
||||||
|
double vValue = j < vDataList.get(i).size() ? vDataList.get(i).get(j) : vDataList.get(i).get(0);
|
||||||
|
|
||||||
|
double roundedU = Math.round(converter.convert(uValue) * 1000.0) / 1000.0;
|
||||||
|
double roundedV = Math.round(converter.convert(vValue) * 1000.0) / 1000.0;
|
||||||
|
|
||||||
|
// 风场数据格式:[经度, 纬度, U分量, V分量]
|
||||||
|
results.add(List.of(lonData.get(j), latData.get(i), roundedU, roundedV));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理普通气象数据(保持原有逻辑)
|
||||||
|
*/
|
||||||
|
private List<List<Double>> resultWeatherData(List<List<Double>> dataList, List<Double> lonData,
|
||||||
|
List<Double> latData, ValueConverter converter) {
|
||||||
|
List<List<Double>> results = new ArrayList<>();
|
||||||
|
for (int i = 0; i < latData.size(); i++) {
|
||||||
|
for (int j = 0; j < lonData.size(); j++) {
|
||||||
|
double value = j < dataList.get(i).size() ? dataList.get(i).get(j) : dataList.get(i).get(0);
|
||||||
|
double roundedValue = Math.round(converter.convert(value) * 1000.0) / 1000.0;
|
||||||
|
results.add(List.of(lonData.get(j), latData.get(i), roundedValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 改进的步长计算方法,考虑经纬度点数
|
||||||
|
*/
|
||||||
|
private double getOriginalStep(List<Double> lonData, List<Double> latData) {
|
||||||
|
if (lonData.size() < 2 || latData.size() < 2) {
|
||||||
|
return WeatherStepConstants.DEFAULT_STEP;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方法1:直接计算相邻点的差值
|
||||||
|
double directLonStep = Math.abs(lonData.get(1) - lonData.get(0));
|
||||||
|
double directLatStep = Math.abs(latData.get(1) - latData.get(0));
|
||||||
|
|
||||||
|
// 方法2:根据点数估算步长(用于验证)
|
||||||
|
double estimatedLonStep = 360.0 / (lonData.size() - 1);
|
||||||
|
double estimatedLatStep = 180.0 / (latData.size() - 1);
|
||||||
|
|
||||||
|
// 优先使用直接计算的结果,如果异常则使用估算值
|
||||||
|
double lonStep = isValidStep(directLonStep) ? directLonStep : estimatedLonStep;
|
||||||
|
double latStep = isValidStep(directLatStep) ? directLatStep : estimatedLatStep;
|
||||||
|
|
||||||
|
System.out.println("直接计算步长 - 经度: " + directLonStep + ", 纬度: " + directLatStep);
|
||||||
|
System.out.println("估算步长 - 经度: " + estimatedLonStep + ", 纬度: " + estimatedLatStep);
|
||||||
|
|
||||||
|
return Math.min(lonStep, latStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证步长是否合理
|
||||||
|
*/
|
||||||
|
private boolean isValidStep(double step) {
|
||||||
|
return step > 0.01 && step < 10.0; // 合理的步长范围
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安全计算降采样比例,避免浮点数精度问题
|
||||||
|
*/
|
||||||
|
private int calculateSafeRatio(double originalStep, double targetStep) {
|
||||||
|
// 常见分辨率的精确匹配
|
||||||
|
if (Math.abs(originalStep - 0.1) < 0.001) {
|
||||||
|
return 5; // 0.1° -> 0.5°,比例5:1
|
||||||
|
} else if (Math.abs(originalStep - 0.25) < 0.001) {
|
||||||
|
return 2; // 0.25° -> 0.5°,比例2:1
|
||||||
|
} else if (Math.abs(originalStep - 0.5) < 0.001) {
|
||||||
|
return 1; // 0.5°,不降采样
|
||||||
|
} else {
|
||||||
|
// 通用计算,四舍五入
|
||||||
|
double ratio = targetStep / originalStep;
|
||||||
|
return (int) Math.round(ratio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 改进的二维数据降采样,处理边界情况
|
||||||
|
*/
|
||||||
|
private List<List<Double>> downsampleData(List<List<Double>> originalData, int ratio) {
|
||||||
|
if (originalData == null || originalData.isEmpty() || ratio <= 1) {
|
||||||
|
return originalData;
|
||||||
|
}
|
||||||
|
|
||||||
|
int originalRows = originalData.size();
|
||||||
|
int originalCols = originalData.isEmpty() ? 0 : originalData.get(0).size();
|
||||||
|
|
||||||
|
List<List<Double>> downsampled = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < originalRows; i += ratio) {
|
||||||
|
if (i >= originalData.size()) break;
|
||||||
|
|
||||||
|
List<Double> originalRow = originalData.get(i);
|
||||||
|
List<Double> newRow = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int j = 0; j < originalCols; j += ratio) {
|
||||||
|
if (j < originalRow.size()) {
|
||||||
|
newRow.add(originalRow.get(j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newRow.isEmpty()) {
|
||||||
|
downsampled.add(newRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("数据降采样: " + originalRows + "x" + originalCols + " -> " +
|
||||||
|
downsampled.size() + "x" + (downsampled.isEmpty() ? 0 : downsampled.get(0).size()));
|
||||||
|
|
||||||
|
return downsampled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 改进的经纬度降采样
|
||||||
|
*/
|
||||||
|
private List<Double> downsampleLonLat(List<Double> originalList, int ratio) {
|
||||||
|
if (originalList == null || originalList.isEmpty() || ratio <= 1) {
|
||||||
|
return originalList;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Double> downsampled = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < originalList.size(); i += ratio) {
|
||||||
|
downsampled.add(originalList.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("经纬度降采样: " + originalList.size() + " -> " + downsampled.size());
|
||||||
|
|
||||||
|
return downsampled;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 原有的辅助方法保持不变
|
||||||
|
private void flattenList(List<List<Double>> dataList, List<Double> flattenedList) {
|
||||||
|
for (List<Double> row : dataList) {
|
||||||
|
flattenedList.addAll(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Double> getMaxMin(List<Double> list) {
|
||||||
|
if (list == null || list.isEmpty()) {
|
||||||
|
return Arrays.asList(0.0, 0.0);
|
||||||
|
}
|
||||||
|
double max = Collections.max(list);
|
||||||
|
double min = Collections.min(list);
|
||||||
|
return Arrays.asList(max, min);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -900,34 +1111,6 @@ public class WeatherDataServiceImpl extends ServiceImpl<WeatherDataMapper, Weath
|
||||||
return Files.exists(path) && !Files.isDirectory(path);
|
return Files.exists(path) && !Files.isDirectory(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<List<Double>> processWeatherData(List<List<Double>> dataList, List<Double> lonData,
|
|
||||||
List<Double> latData, ValueConverter converter) {
|
|
||||||
List<List<Double>> results = new ArrayList<>();
|
|
||||||
for (int i = 0; i < latData.size(); i++) {
|
|
||||||
for (int j = 0; j < lonData.size(); j++) {
|
|
||||||
double value = j < dataList.get(i).size() ? dataList.get(i).get(j) : dataList.get(i).get(0);
|
|
||||||
double roundedValue = Math.round(converter.convert(value) * 1000.0) / 1000.0;
|
|
||||||
results.add(List.of(lonData.get(j), latData.get(i), roundedValue));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void flattenList(List<List<Double>> nestedList, List<Double> flattenedList) {
|
|
||||||
for (List<Double> subList : nestedList) {
|
|
||||||
if (subList.size() >= 3) {
|
|
||||||
flattenedList.add(subList.get(2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Double> getMaxMin(List<Double> flattenedList) {
|
|
||||||
if (flattenedList == null || flattenedList.isEmpty()) {
|
|
||||||
return List.of(0.0, 0.0);
|
|
||||||
}
|
|
||||||
return List.of(Collections.max(flattenedList), Collections.min(flattenedList));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据经纬度获取网格下标
|
* 根据经纬度获取网格下标
|
||||||
* @param latitude 纬度(-90到90)
|
* @param latitude 纬度(-90到90)
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,19 @@ import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class WeatherResultVO {
|
public class WeatherResultVO {
|
||||||
private List<List<Double>> dataList;
|
|
||||||
private double max;
|
private double max;
|
||||||
private double min;
|
private double min;
|
||||||
|
private double maxU;
|
||||||
|
private double minU;
|
||||||
|
private double maxV;
|
||||||
|
private double minV;
|
||||||
|
private double maxLat;
|
||||||
|
private double minLat;
|
||||||
|
private double maxLong;
|
||||||
|
private double minLong;
|
||||||
private int sn;
|
private int sn;
|
||||||
private int we;
|
private int we;
|
||||||
|
private double xSpeed ;
|
||||||
|
private double ySpeed;
|
||||||
|
private List<List<Double>> dataList;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user