气象数据NC、grb2解析成矢量json、CMIS、MICPS及图片应用到webgis

一、基础概念

气象数据通常以多种格式存储和交换,以适应不同的应用需求和处理工具。以下是一些常见的气象数据格式及其转换方法的概述:

常见气象数据格式

1. NetCDF(Network Common Data Form):一种自描述、自包含的数据格式,广泛用于存储气象和气候模型输出、观测数据等。NetCDF支持多维度数组、属性和变量,便于跨平台共享。

2. GRIB(GRIdded Binary):主要用于气象预报产品,包括GRIB1和GRIB2两种版本。它以高效的方式存储大量的气象格点数据,如温度、风速等,是气象预报中心之间交换数据的标准格式。

3. HDF(Hierarchical Data Format):类似于NetCDF,支持复杂的数据结构,适用于大规模科学数据集的存储和分发。HDF4和HDF5是两个主要版本。

4. CSV(Comma-Separated Values):简单的文本格式,易于阅读和处理,常用于数据交换,但缺乏自描述性,不包含元数据。

5. GeoTIFF:一种地理空间图像格式,用于存储栅格数据,如卫星图像或气象地图,包含地理坐标信息。

6. BUFR(Binary Universal Form for the Representation of Meteorological Data):国际气象组织推荐的一种二进制编码格式,特别适用于气象观测数据的交换。

数据格式转换方法

1. 使用专业软件:

•Panoply:NASA开发的免费软件,可以打开、查看和转换NetCDF、HDF、GRIB等格式数据。•NCAR Command Language (NCL):提供丰富的脚本语言功能,用于处理NetCDF、GRIB等气象数据。

•GDAL/OGR:开源地理空间库,提供了广泛的格式转换能力,支持NetCDF、HDF、GeoTIFF等格式的转换。

2. 编程语言库:

•Python: 利用netCDF4, pygrib, h5py等库进行数据读写和格式转换。xarray库提供了更高级的数据结构,方便处理NetCDF和GRIB数据。

•MATLAB:内置了对NetCDF、HDF的读写支持,也可通过第三方工具箱处理其他格式。

•R语言:使用ncdf4、raster、rgdal等包处理NetCDF、GRIB、GeoTIFF等格式。

3. 在线转换工具:

虽然不如上述方法灵活,但存在一些在线工具,允许用户上传文件并转换为不同格式,不过这类工具在处理大型气象数据集时可能受限。进行数据格式转换时,需注意保留数据的完整性和准确性,特别是元数据信息,以确保转换后的数据在后续分析中仍然有效。

二、实践应用

关键代码实现

package com.netcdf.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.*;import static com.netcdf.util.NcUtil.*;@Controller
@RequestMapping(value = "/ReadGridNc")public class ReadGridNcData {//http://localhost:8087/NetcdfServer/ReadGridNc/getNcData?FilePath=20210708_2021070804.nc&FilterBound=&valField=UGRD_10maboveground/**** @param FilePath* @param FilterBound* @param valField* @return*/@RequestMapping(value = "/getNcData", method = RequestMethod.GET)public @ResponseBodyMap GetNcData(String FilePath,String FilterBound,String valField) {Map map = AnalysisNC(FilePath, FilterBound,valField,1);return map;}//http://localhost:8087/NetcdfServer/ReadGridNc/GetNcWindData?FilePath=2023042323.grb2/**** @param FilePath* @return*/@RequestMapping(value = "/GetNcWindData", method = RequestMethod.GET)public @ResponseBodyJSONArray GetNcWindData(String FilePath) {String map = AnalysisNcWind(FilePath);return JSON.parseArray(map);}//http://localhost:8088/NetcdfServer/ReadGridNc/getNcDataSurface?FilePath=2022090212.nc&FilterBound=&valField=PRES_surface&intvRanges=0,100000,10005,100010,100015&boundPath=1&isIDW=true&isClip=false/**** @param FilePath* @param FilterBound* @param valField* @return*/@RequestMapping(value = "/getNcDataSurface", method = RequestMethod.GET)public @ResponseBodyString GetNcDataSurface(String FilePath,String FilterBound,String valField,String intvRanges,String boundPath,boolean isIDW,boolean isClip) {String[] Ranges=intvRanges.substring(0,intvRanges.length()).split(",");double[] dataInterval = new double[Ranges.length];for(int i=0;i<Ranges.length;i++){dataInterval[i]=Double.valueOf(Ranges[i]);if( i == 1 && dataInterval[i] == 0.0){dataInterval[i] = 0.0001;}}Map map = AnalysisNC(FilePath, FilterBound,valField,1);if(map!=null) {String strGeojson = nc2EquiSurface(map, dataInterval,isClip,boundPath,isIDW);return strGeojson;}return "";}//http://localhost:8088/NetcdfServer/ReadGridNc/getNcDataSurface1?FilePath=wrf_ll.nc&FilterBound=&valField=RH2M&intvRanges=0,100000,10005,100010,100015&boundPath=1&isIDW=true&isClip=false//http://localhost:8088/NetcdfServer/ReadGridNc/getNcDataSurface1?FilePath=wrf_ll.nc&FilterBound=&valField=RH2M&intvRanges=0,70,75,80,85,90,95&boundPath=1&isIDW=false&isClip=false/**** @param FilePath* @param FilterBound* @param valField* @return*/@RequestMapping(value = "/getNcDataSurface1", method = RequestMethod.GET)public @ResponseBodyString GetNcDataSurface1(String FilePath,String FilterBound,String valField,String intvRanges,String boundPath,boolean isIDW,boolean isClip) {String[] Ranges=intvRanges.substring(0,intvRanges.length()).split(",");double[] dataInterval = new double[Ranges.length];for(int i=0;i<Ranges.length;i++){dataInterval[i]=Double.valueOf(Ranges[i]);if( i == 1 && dataInterval[i] == 0.0){dataInterval[i] = 0.0001;}}Map map = AnalysisNC1(FilePath, FilterBound,valField,3);
//        Map map = AnalysisNC1(FilePath, FilterBound,valField);if(map!=null) {String strGeojson = nc2EquiSurface1(map, dataInterval,isClip,boundPath,isIDW);return strGeojson;}return "";}//http://localhost:8088/NetcdfServer/ReadGridNc/getNcDataMICPS?FilePath=wrf_ll.nc&FilterBound=&valField=RH2M&intvRanges=0,70,75,80,85,90,95&boundPath=1&isIDW=false&isClip=false/**** @param FilePath* @param FilterBound* @param valField* @return*/@RequestMapping(value = "/getNcDataMICPS", method = RequestMethod.GET)public @ResponseBodyString GetNcDataMICPS(String FilePath,String FilterBound,String valField,String intvRanges,String boundPath,boolean isIDW,boolean isClip) {String[] Ranges=intvRanges.substring(0,intvRanges.length()).split(",");double[] dataInterval = new double[Ranges.length];for(int i=0;i<Ranges.length;i++){dataInterval[i]=Double.valueOf(Ranges[i]);if( i == 1 && dataInterval[i] == 0.0){dataInterval[i] = 0.0001;}}Map map = AnalysisNC1(FilePath, FilterBound,valField,1);
//        Map map = AnalysisNC1(FilePath, FilterBound,valField);if(map!=null) {StringBuilder strGeojson = new StringBuilder();strGeojson.append("diamond 4 2022年4月1日GFS地面相对湿度3小时预报\n" +"    2022    4    1    0   3   2   0.5  -0.5 \n" +"    96.5 106.5 29.5 20.5 \n" +"    1001 901 5 -50 50 1 0\n");strGeojson.append(map.get("val").toString().replace("[","").replace("]","").replaceAll(","," "));return strGeojson.toString();}return "";}//http://localhost:8088/NetcdfServer/ReadGridNc/getNcDataCMISS?FilePath=wrf_ll.nc&FilterBound=&valField=RH2M&intvRanges=0,70,75,80,85,90,95&boundPath=1&isIDW=false&isClip=false/**** @param FilePath* @param FilterBound* @param valField* @return*/@RequestMapping(value = "/getNcDataCMISS", method = RequestMethod.GET)public @ResponseBodyString GetNcDataCMISS(String FilePath,String FilterBound,String valField,String intvRanges,String boundPath,boolean isIDW,boolean isClip) {String[] Ranges=intvRanges.substring(0,intvRanges.length()).split(",");double[] dataInterval = new double[Ranges.length];for(int i=0;i<Ranges.length;i++){dataInterval[i]=Double.valueOf(Ranges[i]);if( i == 1 && dataInterval[i] == 0.0){dataInterval[i] = 0.0001;}}Map map = AnalysisNC1(FilePath, FilterBound,valField,1);
//        Map map = AnalysisNC1(FilePath, FilterBound,valField);if(map!=null) {StringBuilder strGeojson = new StringBuilder();strGeojson.append("{\"returnCode\":\"0\",\"returnMessage\":\"Query Succeed\",\"startLat\":29.5,\"startLon\":96.5,\"endLat\":20.5,\"endLon\":106.5,\"latCount\":901,\"lonCount\":1001,\"latStep\":-0.01,\"lonStep\":0.01,\"requestParams\":\"minlat=20.5&time=20190810000000&fcstele=VVP&datacode=NAFP_FOR_FTM_HIGH_JAP_NEHE&maxlat=29.5&fcstlevel=850&maxlon=106.5&validtime=0&minlon=96.5\",\"requestTime\":\"2019-08-20 08:02:24\",\"responseTime\":\"2019-08-20 08:02:24\",\"takeTime\":\"0.022\",\"fieldNames\":\"湿度\",\"fieldUnits\":\"Pa*s^-1\",\"DS\":[");strGeojson.append(map.get("val").toString());strGeojson.append("]}");return strGeojson.toString();}return "";}//http://localhost:8088/NetcdfServer/ReadGridNc/getNcDataSurfaceWind?FilePath=2024050914.nc&FilterBound=&intvRanges=0,2,4,6,8,10&boundPath=1&isIDW=true&isClip=false/**** @param FilePath* @param FilterBound* @param valField* @return*/@RequestMapping(value = "/getNcDataSurfaceWind", method = RequestMethod.GET)public @ResponseBodyString GetNcDataSurfaceWind(String FilePath,String FilterBound,String valField,String intvRanges,String boundPath,boolean isIDW,boolean isClip) {String[] Ranges=intvRanges.substring(0,intvRanges.length()).split(",");double[] dataInterval = new double[Ranges.length];for(int i=0;i<Ranges.length;i++){dataInterval[i]=Double.valueOf(Ranges[i]);if( i == 1 && dataInterval[i] == 0.0){dataInterval[i] = 0.0001;}}//导出图片AnalysisNCWindyToPng(FilePath, FilterBound,"UGRD_10maboveground","VGRD_10maboveground");
//        Map map = AnalysisNCWindy(FilePath, FilterBound,"UGRD_10maboveground","VGRD_10maboveground");//        if(map!=null) {
//            String strGeojson = nc2EquiSurface(map, dataInterval,isClip,boundPath,isIDW);
//            return strGeojson;
//        }return "nc";}//http://localhost:8088/NetcdfServer/ReadGridNc/getGribDataSurfaceWind?FilePath=2024050914.grb2&FilterBound=&intvRanges=0,1,2,3,4,5,6,7,8,9,10,11,12&boundPath=1&isIDW=true&isClip=false/**** @param FilePath* @param FilterBound* @param valField* @return*/@RequestMapping(value = "/getGribDataSurfaceWind", method = RequestMethod.GET)public @ResponseBodyString GetGribDataSurfaceWind(String FilePath,String FilterBound,String valField,String intvRanges,String boundPath,boolean isIDW,boolean isClip) {String[] Ranges=intvRanges.substring(0,intvRanges.length()).split(",");double[] dataInterval = new double[Ranges.length];for(int i=0;i<Ranges.length;i++){dataInterval[i]=Double.valueOf(Ranges[i]);if( i == 1 && dataInterval[i] == 0.0){dataInterval[i] = 0.0001;}}//导出图片
//        AnalysisNCWindyToPng(FilePath, FilterBound,"UGRD_10maboveground","VGRD_10maboveground");AnalysisGribWindyToPng(FilePath, FilterBound,"u-component_of_wind_height_above_ground","v-component_of_wind_height_above_ground");return "grib";}}
<!DOCTYPE html>
<html>
<head><title>Layers Control Tutorial - Leaflet</title><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" /><link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/><script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""></script><style>html, body {height: 100%;margin: 0;}#map {width: 1000px;height: 700px;}</style></head>
<body><div id='map'></div><script>var grayscaleLayer= L.tileLayer('http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineCommunity/MapServer/tile/{z}/{y}/{x}', {id: 'map11',maxZoom: 16,minZoom: 4});var map = L.map('map', {minZoom: 5,maxZoom: 12,center: [21, 100],zoom: 10,zoomDelta: 0.5,//点击+-按钮的放缩刻度尺度,默认值1zoomSnap: 0.5,//地图能放缩的zoom的最小刻度尺度,默认值1fullscreenControl: false,//全屏控件,不显示zoomControl: false,//放大缩小控件,不显示attributionControl: false//右下角属性控件,不显示});map.addLayer(grayscaleLayer);var imageBounds = [[20.5, 96.5], [29.41, 106.5]];//图片的经纬度范围,西南角点,东北角点(纬度、经度)var imageUrl='pixel_art.png';//图片的地址var imageLayer =L.imageOverlay(imageUrl, imageBounds,{opacity:0.8});//opacity是透明度map.addLayer(imageLayer);//如果imageLayer已经创建,后续只需要切换url即可if(imageLayer!=null){imageLayer.setUrl(imageUrl);}
</script></body>
</html>

转换成图片成果

示例调用实现

转换成矢量json成果

转换成MICPS成果

转换成CMIS成果

 前端可视效果

成果应用展示

参照windy配置可视化实现

 如果对您有所帮助,请点赞打赏支持!

技术合作交流qq:2401315930

最后分享一下地图下载器设计及下载地址:

链接:https://pan.baidu.com/s/1RZX7JpTpxES-G7GiaVUxOw 
提取码:61cn

地图下载器代码结构设计及功能实现_地图下载管理器解析-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/356053.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

js如何使得四舍五入的百分比之和为100%

在JavaScript中&#xff0c;如果你想要确保一组四舍五入后的百分比之和严格等于100%&#xff0c;那么你不能直接对每个百分比进行四舍五入&#xff0c;因为四舍五入会引入误差。但是&#xff0c;你可以采用一种策略&#xff0c;即先对所有的百分比进行常规的四舍五入&#xff0…

数据结构6---树

一、定义 树(Tree)是n(n>0)个结点的有限集。当n0时成为空树,在任意一棵非空树中: 1、有且仅有一个特定的称为根(Root)的结点; 2、当n>1时,其余结点可分为m(m>日)个互不相交的有限集T1、T2、...、 Tm&#xff0c;其中每一个集合本身又是一棵树&#xff0c;并且称为根的…

“打造智能售货机系统,基于ruoyi微服务版本生成基础代码“

目录 # 开篇 1. 菜单 2. 字典配置 3. 表配置 3.1 导入表 3.2 区域管理 3.3 合作商管理 3.4 点位管理 4. 代码导入 4.1 后端代码生成 4.2 前端代码生成 5. 数据库代码执行 6. 点位管理菜单顺序修改 7. 页面展示 8. 附加设备表 8.1 新增设备管理菜单 8.2 创建字…

Python武器库开发-武器库篇之SMB服务暴力破解(五十五)

Python武器库开发-武器库篇之SMB服务暴力破解(五十五) SMB服务&#xff08;Server Message Block&#xff09;是一种用于文件共享、打印机共享和其他资源共享的网络协议。它最初由IBM开发&#xff0c;后来被微软广泛采用。 SMB服务允许多台计算机在网络上共享文件和资源&…

中石化加油卡有什么用?

对于有车一族来说&#xff0c;有一张加油卡真的可以省下不少钱 但是像我们这种没车的人&#xff0c;即使得到加油卡也毫无用武之地 久而久之&#xff0c;难免会造成卡过期的情况出现 还好&#xff0c;前两天把我手上堆积了好久的加油卡在收卡云上卖出去了&#xff0c;99折真…

QT

#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) ,Gcancle(new QPushButton("取消",this)) ,EmmEdit(new QLineEdit(this)) { ui->setupUi(this);…

怎么看电脑实时充电功率

因为我想测试不同的充电器给电脑充电的速度&#xff0c;所以就想找一款软件可以看电脑当前充电功率的软件&#xff0c;我给一个图 直接搜索就可以下载了&#xff0c;charge rate就是功率&#xff0c;这里是毫瓦&#xff0c;换算单位是 1000mw1w 所以我这里充电功率是65w&…

福建聚鼎:装饰画现在做起来难吗

在当代社会&#xff0c;艺术创作已经成为很多人表达自我、追求美学生活的方式之一。装饰画作为家居装饰的重要元素&#xff0c;也受到了越来越多人的喜爱。但做一个优质的装饰画真的容易吗? 从技术层面讲&#xff0c;随着科技的发展&#xff0c;制作装饰画的手段和材料都比以往…

HTML和CSS基础(一)

前言 HTML&#xff08;HyperText Markup Language&#xff09;是一种用于创建网页的标准标记语言。它由各种标签组成&#xff0c;这些标签定义了网页的结构和内容。HTML的早期形式诞生于1989年&#xff0c;由CERN的物理学家Tim Berners-Lee发明&#xff0c;最初用于在科学家之…

IPTCP知识

1. IP&#xff1a; IP地址是一个32位的二进制数&#xff0c;通常被分割为4个“8位二进制数”IP地址分类&#xff1a;A类地址、B类地址、C类地址、D类地址、E类地址 A类地址分配给规模特别大的网络使用&#xff0c;B类地址分配给一般的中型网络&#xff0c;C类地址分配给小型网…

Day 29:1600. 王位继承顺序

Leetcode1600. 王位继承顺序 一个王国里住着国王、他的孩子们、他的孙子们等等。每一个时间点&#xff0c;这个家庭里有人出生也有人死亡。 这个王国有一个明确规定的王位继承顺序&#xff0c;第一继承人总是国王自己。我们定义递归函数 Successor(x, curOrder) &#xff0c;给…

DN-DETR

可以看到&#xff0c;与 DAB-DETR 相比&#xff0c;最大的差别仍然在 decoder 处&#xff0c;主要是 query 的输入。DN-DETR 认为可以把对 offsets 的学习&#xff0c;看作一种对噪声学习的过程&#xff0c;因此&#xff0c;可以直接在 GT 周围生成一些 noised boxes&#xff0…

ASP.NET Core 6.0 使用 Log4Net 和 Nlog日志中间件

前言 两年前,浅浅的学过 .NET 6,为啥要记录下来,大概是为了以后搭架子留下引线,还有抛砖引玉。 1. 环境准备 下载 建议使用 Visual Studio 2022 开发版 官网的下载地址:Visual Studio 2022 IDE - 适用于软件开发人员的编程工具借助 Visual Studio 设计,具有自动完成…

【MySQL】 -- 事务

如果对表中的数据进行CRUD操作时&#xff0c;不加控制&#xff0c;会带来一些问题。 比如下面这种场景&#xff1a; 有一个tickets表&#xff0c;这个数据库被两个客户端机器A和B用时连接对此表进行操作。客户端A检查tickets表中还有一张票的时候&#xff0c;将票出售了&#x…

面试官:JavaScript执行机制中的闭包?

前言 JavaScript 中的闭包指的是一个函数以及其捆绑的周边环境状态的引用的组合。闭包可以让开发者从内部函数访问外部函数的作用域&#xff0c;即使外部函数已经执行完毕 今天我们通过JavaScript执行机制来聊聊闭包 正文 首先来分析这段代码的执行机制&#xff0c;这段代码…

太牛了!AI换脸数字人,限制解除,免费用!

哈喽&#xff0c;各位小伙伴们好&#xff0c;我是给大家带来各类黑科技与前沿资讯的小武。 今天给大家安利一款美图公司出品的神器&#xff0c;功能限制完全解除&#xff0c;可以免费使用AI换脸数字人、AI提词器、AI脚本、AI抠图、AI清除、AI封面等超多超实用功能&#xff0c;…

Freertos-----任务之间的消息传递(使用消息队列信号量方法)

这次来分享任务之间的数据传递的方法&#xff0c;方法有很多种&#xff0c;我展示2种&#xff0c;让大家对freertos有更深刻的印象 目录 消息队列 信号量 消息队列 首先直接打开普中的例程&#xff0c;然后在里面加上ADC的驱动代码&#xff0c;先初始化外设先&#xff0c;我…

【ARMv8/ARMv9 硬件加速系列 1 -- SVE | NEON | SIMD | VFP | MVE | MPE 基础介绍】

文章目录 ARM 扩展功能介绍VFP (Vector Floating Point)SIMD (Single Instruction, Multiple Data)NEONSVE (Scalable Vector Extension)SME (Scalable Matrix Extension)CME (Compute Matrix Engine)MVE (M-profile Vector Extension)MPE (Media Processing Engine)总结 ARM 扩…

【刷力扣】23. 合并 K 个升序链表(dummy节点技巧 + 分治思维 + 优先队列)

目录 一、合并升序链表问题二、题目&#xff1a;[21. 合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/description/)1、掌握dummy节点的技巧 三、题目&#xff1a;[23. 合并 K 个升序链表](https://leetcode.cn/problems/merge-k-sorted-lists/descri…

ASP.NET Core 6.0 启动方式

启动方式 Visualstudio 2022启动 IIS Express IIS Express 是一个专为开发人员优化的轻型独立版本的 IIS。 借助 IIS Express,可以轻松地使用最新版本的 IIS 开发和测试网站。 控制台版面 直接在浏览器输入监听的地址,监听的是 http://localhost:5137 脚本启动 dotnet run…