From c160cca53132de98497127505a8b3c7eac8365a4 Mon Sep 17 00:00:00 2001 From: shiyi Date: Wed, 12 Jun 2024 18:22:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E8=88=AA=E7=BA=BF=E4=B8=8A?= =?UTF-8?q?=E7=9A=84=E9=A2=84=E6=8A=A5=E6=95=B0=E6=8D=AE=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=86=E4=BB=A3=E7=A0=81=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E5=A4=8D=E7=94=A8=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/UpperWeatherController.java | 5 +- .../web/pojo/response/TimeSeriesDataset.java | 1 + .../web/service/GfsDataServiceImpl.java | 150 ++++++++++++------ 3 files changed, 106 insertions(+), 50 deletions(-) diff --git a/weather-service/src/main/java/com/htfp/weather/web/controller/UpperWeatherController.java b/weather-service/src/main/java/com/htfp/weather/web/controller/UpperWeatherController.java index 98731ac..31654a8 100644 --- a/weather-service/src/main/java/com/htfp/weather/web/controller/UpperWeatherController.java +++ b/weather-service/src/main/java/com/htfp/weather/web/controller/UpperWeatherController.java @@ -106,7 +106,8 @@ public class UpperWeatherController { } } int level = multiPointsRequest.getLevel().intValue(); - // List nowWeatherByMultiPoint = gfsDataService.getNowWeatherByMultiPoint(latitudeList, longitudeList, level); - return Result.success(); + List nowWeatherByMultiPoint = gfsDataService.getForecastSeriesByMultiPoint(latitudeList, longitudeList, level); + return Result.success(nowWeatherByMultiPoint); } + } diff --git a/weather-service/src/main/java/com/htfp/weather/web/pojo/response/TimeSeriesDataset.java b/weather-service/src/main/java/com/htfp/weather/web/pojo/response/TimeSeriesDataset.java index f018919..c2211a8 100644 --- a/weather-service/src/main/java/com/htfp/weather/web/pojo/response/TimeSeriesDataset.java +++ b/weather-service/src/main/java/com/htfp/weather/web/pojo/response/TimeSeriesDataset.java @@ -25,6 +25,7 @@ public class TimeSeriesDataset { float[] cloud; float[] precip; + public TimeSeriesDataset() {} public TimeSeriesDataset(int size) { time = new ArrayList<>(size); temp = new float[size]; diff --git a/weather-service/src/main/java/com/htfp/weather/web/service/GfsDataServiceImpl.java b/weather-service/src/main/java/com/htfp/weather/web/service/GfsDataServiceImpl.java index 20e80f6..109cf49 100644 --- a/weather-service/src/main/java/com/htfp/weather/web/service/GfsDataServiceImpl.java +++ b/weather-service/src/main/java/com/htfp/weather/web/service/GfsDataServiceImpl.java @@ -81,7 +81,7 @@ public class GfsDataServiceImpl implements IDataService { String gridDataSetId = lastGridDataSetMeta.getGridDataSetId(); int[] pressureLevels = tableConfig.getPressureList(); Array array = gfsDataFetcher.getProfile(gridDataSetId, targetVariable, iTime, iLat, iLon); - float[] values = (float[]) array.getStorage(); + float[] values = (float[]) array.copyTo1DJavaArray(); return new ProfileResponse(pressureLevels, values); } catch (Exception e) { throw new RuntimeException(e); @@ -117,11 +117,11 @@ public class GfsDataServiceImpl implements IDataService { String gridDataSetId = lastGridDataSetMeta.getGridDataSetId(); GridDataSet gridDataSet = gfsDataFetcher.getSeries(gridDataSetId, variableNames, iTimes, iLev, iLat, iLon); - if (level == SURFACE_LEVEL) { - return buildTimeSeriesDatasetSurface(timeList, gridDataSet); - } else { - return buildTimeSeriesDatasetPressure(timeList, gridDataSet); - } + final GfsLevelsEnum levelFlag = GfsLevelsEnum.getByCode(level); + TimeSeriesDataset timeSeriesDataset = buildTimeSeriesDatasetInTargetPoint(timeList, gridDataSet, 0, 0, 0, levelFlag); + timeSeriesDataset.setLatitude(latitude); + timeSeriesDataset.setLongitude(longitude); + return timeSeriesDataset; } catch (Exception e) { throw new RuntimeException(e); @@ -152,9 +152,9 @@ public class GfsDataServiceImpl implements IDataService { try { String gridDataSetId = lastGridDataSetMeta.getGridDataSetId(); GridDataSet gridDataSet = gfsDataFetcher.getSinglePoint(gridDataSetId, variableNames, iTime, iLev, iLat, iLon); - // 每个变量都是0维数组 - final GfsLevelsEnum levelFlag = GfsLevelsEnum.getByCode(level); + final GfsLevelsEnum levelFlag = GfsLevelsEnum.getByCode(level); + // 每个变量都是0维数组 NowWeatherStatus nowWeatherStatus = buildNowWeatherInTargetPoint(gridDataSet, 0, 0, 0, levelFlag); nowWeatherStatus.setLatitude(latitude); nowWeatherStatus.setLongitude(longitude); @@ -198,7 +198,7 @@ public class GfsDataServiceImpl implements IDataService { String gridDataSetId = lastGridDataSetMeta.getGridDataSetId(); int[] origin = new int[]{iTime, iLev, 0, 0}; - int[] shape = new int[]{1, 1, tableConfig.getLatSize(), tableConfig.getLatSize()}; + int[] shape = new int[]{1, 1, tableConfig.getLatSize(), tableConfig.getLonSize()}; GridDataSet gridDataSet = gfsDataFetcher.queryByTableStore(gridDataSetId, variableNames, origin, shape); @@ -221,6 +221,57 @@ public class GfsDataServiceImpl implements IDataService { } } + /** + * 获得指定点序列上的未来24小时气象预报 + * @param latitude + * @param longitude + * @param level + * @return + */ + public List getForecastSeriesByMultiPoint(List latitude, List longitude, int level) { + GridDataSetMeta lastGridDataSetMeta = null; + try { + lastGridDataSetMeta = queryMeta.getLastGridDataSetMeta(); + } catch (Exception e) { + throw new AppException(ErrorCode.DATA_SET_EMPTY, ": " + e.getMessage()); + } + if (latitude.size() != longitude.size()) { + throw new AppException(ErrorCode.INDEX_SIZE_ERROR, ": 经纬度数组大小不一致"); + } + int pointSize = latitude.size(); + List variableNames = getVariableNamesInDatabase(level); + Map params = getFutureTimeIndexList(lastGridDataSetMeta); + List iTimeList = params.get("iTimeList"); + List timeList = params.get("timeList"); + int[] iTimes = iTimeList.stream().mapToInt(Integer::valueOf).toArray(); + List latIndex = latitude.stream().map(this::getLatitudeIndex).collect(Collectors.toList()); + List lonIndex = longitude.stream().map(this::getLongitudeIndex).collect(Collectors.toList()); + int iLev = getLevelIndex(level); + try { + String gridDataSetId = lastGridDataSetMeta.getGridDataSetId(); + + int[] origin = new int[]{iTimes[0], iLev, 0, 0}; + // TODO 2024/6/12: 全域查询量太大,可以考虑只在航线所在区域查询,提升查询效率 + int[] shape = new int[]{iTimes.length, 1, tableConfig.getLatSize(), tableConfig.getLonSize()}; + GridDataSet gridDataSet = gfsDataFetcher.queryByTableStore(gridDataSetId, variableNames, + origin, shape); + + List timeSeriesDatasetList = new ArrayList<>(); + + for (int i = 0; i < pointSize; i++) { + // NOTE 2024/6/11: build中传入的索引和数据库的查询索引意义不同 + final GfsLevelsEnum levelFlag = GfsLevelsEnum.getByCode(level); + TimeSeriesDataset timeSeriesDataset = buildTimeSeriesDatasetInTargetPoint(timeList, gridDataSet, 0, latIndex.get(i), lonIndex.get(i), levelFlag); + timeSeriesDataset.setLatitude(latitude.get(i)); + timeSeriesDataset.setLongitude(longitude.get(i)); + timeSeriesDatasetList.add(timeSeriesDataset); + } + return timeSeriesDatasetList; + + } catch (Exception e) { + throw new RuntimeException(e); + } + } private int[] getMarginIndexByMultiPoint(List latitude, List longitude, List level) { int minLat = Integer.MIN_VALUE; @@ -322,55 +373,58 @@ public class GfsDataServiceImpl implements IDataService { return planeResponse; } - private TimeSeriesDataset buildTimeSeriesDatasetPressure(List timeList, GridDataSet gridDataSet) { - TimeSeriesDataset timeSeriesDataset = new TimeSeriesDataset(timeList.size()); - timeSeriesDataset.setTime(timeList); - Grid4D grid4D; - grid4D = gridDataSet.getVariable(GfsVariableIsobaricEnum.getGfsVariableName(GfsVariableIsobaricEnum.TEMP)); - if (grid4D != null) { - timeSeriesDataset.setTemp((float[]) grid4D.toArray().getStorage()); - } - grid4D = gridDataSet.getVariable(GfsVariableIsobaricEnum.getGfsVariableName(GfsVariableIsobaricEnum.WIND_SPEED)); - if (grid4D != null) { - timeSeriesDataset.setWindSpeed((float[]) grid4D.toArray().getStorage()); - } - grid4D = gridDataSet.getVariable(GfsVariableIsobaricEnum.getGfsVariableName(GfsVariableIsobaricEnum.WIND360)); - if (grid4D != null) { - timeSeriesDataset.setWind360((float[]) grid4D.toArray().getStorage()); - } - grid4D = gridDataSet.getVariable(GfsVariableIsobaricEnum.getGfsVariableName(GfsVariableIsobaricEnum.CLOUD)); - if (grid4D != null) { - timeSeriesDataset.setCloud((float[]) grid4D.toArray().getStorage()); - } - return timeSeriesDataset; - } - private TimeSeriesDataset buildTimeSeriesDatasetSurface(List timeList, GridDataSet gridDataSet) { - TimeSeriesDataset timeSeriesDataset = new TimeSeriesDataset(timeList.size()); - timeSeriesDataset.setTime(timeList); - Grid4D grid4D; - grid4D = gridDataSet.getVariable(GfsVariableHeightEnum.getGfsVariableName(GfsVariableHeightEnum.TEMP)); - if (grid4D != null) { - timeSeriesDataset.setTemp((float[]) grid4D.toArray().getStorage()); - } - grid4D = gridDataSet.getVariable(GfsVariableHeightEnum.getGfsVariableName(GfsVariableHeightEnum.WIND_SPEED)); - if (grid4D != null) { - timeSeriesDataset.setWindSpeed((float[]) grid4D.toArray().getStorage()); - } - grid4D = gridDataSet.getVariable(GfsVariableHeightEnum.getGfsVariableName(GfsVariableHeightEnum.WIND360)); - if (grid4D != null) { - timeSeriesDataset.setWind360((float[]) grid4D.toArray().getStorage()); + /** + * 构建指定位置的预报数据 + * @param timeList-时间列表 + * @param gridDataSet + * @param iLevInGrid-目标点在返回的网格中的高度索引 + * @param iLatInGrid-目标点在返回的网格中的高度索引 + * @param iLonInGrid-目标点在返回的网格中的高度索引 + * @param levelFlag-高度层次标记,地面或高空 + * @return + */ + private TimeSeriesDataset buildTimeSeriesDatasetInTargetPoint(List timeList, GridDataSet gridDataSet, int iLevInGrid, int iLatInGrid, int iLonInGrid, GfsLevelsEnum levelFlag) { + TimeSeriesDataset result = new TimeSeriesDataset(); + result.setTime(timeList); + int tsize = timeList.size(); + // 利用反射构建数据集 + Class aClass = result.getClass(); + for (Map.Entry entry : gridDataSet.getVariables().entrySet()) { + String variableNameInFile = entry.getKey(); + String variableNameInApi; + if (GfsLevelsEnum.SURFACE.equals(levelFlag)) { + variableNameInApi = GfsVariableHeightEnum.getVariableNameInApi(variableNameInFile); + } else { + variableNameInApi = GfsVariableIsobaricEnum.getVariableNameInApi(variableNameInFile); + } + if (variableNameInApi == null) { + throw new AppException(ErrorCode.NO_SUCH_VARIABLE); + } + + try { + Grid4D grid4D = entry.getValue(); + String setMethodName = "set" + variableNameInApi.substring(0, 1).toUpperCase() + variableNameInApi.substring(1); + Method method = aClass.getDeclaredMethod(setMethodName, aClass.getDeclaredField(variableNameInApi).getType()); + float[] storage = (float[]) grid4D.toArray().section(new int[]{0, iLevInGrid, iLatInGrid, iLonInGrid}, new int[]{tsize, 1, 1, 1}).copyTo1DJavaArray(); + method.invoke(result, storage); + } catch (ReflectiveOperationException e) { + throw new AppException(ErrorCode.NO_SUCH_VARIABLE, e); + } catch (Exception e) { + e.printStackTrace(); + throw new AppException(ErrorCode.RESPONSE_DATA_BUILD_ERROR, e); + } } - return timeSeriesDataset; + return result; } - /** * 构建指定位置的当前天气 * @param gridDataSet * @param iLevInGrid-目标点在返回的网格中的高度索引 * @param iLatInGrid-目标点在返回的网格中的高度索引 * @param iLonInGrid-目标点在返回的网格中的高度索引 + * @param levelFlag-高度层次标记,地面或高空 * @return */ private NowWeatherStatus buildNowWeatherInTargetPoint(GridDataSet gridDataSet, int iLevInGrid, int iLatInGrid, int iLonInGrid, GfsLevelsEnum levelFlag) {