气象数据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 @ResponseBody
    Map 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 @ResponseBody
    JSONArray 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 @ResponseBody
    String 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 @ResponseBody
    String 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 @ResponseBody
    String 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 @ResponseBody
    String 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 @ResponseBody
    String 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 @ResponseBody
    String 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,//点击+-按钮的放缩刻度尺度,默认值1
        zoomSnap: 0.5,//地图能放缩的zoom的最小刻度尺度,默认值1
        fullscreenControl: 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博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用VScode打开keil下的文件中文编码乱码的问题,以及利用VScode转换字符编码的方法

目录 问题描述 解决方法 利用VScode转换字符编码的方法 问题描述 keil中默认的编码是ANIS如下图所示。 而VScode中默认的编码为UTF-8 &#xff0c;打开后如下。 解决方法 建议另存后&#xff0c;再打开目标文件&#xff0c;防止误操作&#xff01; 在VScode的最下方可以找…

海豚调度调优 | 正在运行的工作流(DAG)如何重新拉起失败的任务(Task)

&#x1f4a1; 本系列文章是DolphinScheduler由浅入深的教程&#xff0c;涵盖搭建、二开迭代、核心原理解读、运维和管理等一系列内容。适用于想对 DolphinScheduler了解或想要加深理解的读者。 *祝开卷有益。 * 本系列教程基于 DolphinScheduler 2.0.5 做的优化。&#xff…

javaSE字符串学习笔记

API和API帮助文档 API API(Application Programming Interface)&#xff1a;应用程序编程接口简单理解&#xff1a;API酒啊别人已经写好的东西&#xff0c;我们不需要自己编写&#xff0c;直接使用即可。 API这个术语在编程圈中非常常见.我第一次接触API这个词语是在大一下。老…

SQLCMD完全指南:掌控 SQL Server

SQL Server 拥有被广泛认可的一流管理工具——SQL Server Management Studio&#xff08;简称 SSMS&#xff09;。它提供了丰富的功能&#xff0c;极大地简化了开发人员和数据库管理员&#xff08;DBA&#xff09;的工作。 目录 SQLCMD 入门使用 SQLCMD 连接 SQL ServerSQLCMD …

进程、线程的区别

进程、线程的关系 开工厂生产手机&#xff0c;制作一条生产线&#xff0c;这个生产线上有很多的器件以及材料。一条生产线就是一个进程。 只有生产线是不够的&#xff0c;使用找五个工人来进行生产&#xff0c;这个工人能够利用这些材料最终一步步的将手机做出来&#xff0c;这…

Python xlrd库:读excel表格

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

【Apache Doris】周FAQ集锦:第 7 期

【Apache Doris】周FAQ集锦&#xff1a;第 7 期 SQL问题数据操作问题运维常见问题其它问题关于社区 欢迎查阅本周的 Apache Doris 社区 FAQ 栏目&#xff01; 在这个栏目中&#xff0c;每周将筛选社区反馈的热门问题和话题&#xff0c;重点回答并进行深入探讨。旨在为广大用户和…

【机器学习 复习】第7章 集成学习(小重点,混之前章节出题但小题)

一、概念 1.集成学习&#xff0c;顾名思义&#xff0c;不是一个玩意&#xff0c;而是一堆玩意混合到一块。 &#xff08;1&#xff09;基本思想是先 生成一定数量基学习器&#xff0c;再采用集成策略 将这堆基学习器的预测结果组合起来&#xff0c;从而形成最终结论。 &#x…

MicroBlaze IP核中Local Memory Bus (LMB)接口描述

LMB&#xff08;Local Memory Bus&#xff09;是一种同步总线&#xff0c;主要用于访问FPGA上的块RAM&#xff08;Block RAM&#xff0c;BRAM&#xff09;。LMB使用最少的控制信号和一个简单的协议&#xff0c;以保证块RAM能在一个时钟周期内被存取。所有的LMB信号都是高电平有…

计算机网络5:运输层

概述 进程间基于网络的通信 计算机网络中实际进行通信的真正实体&#xff0c;是位于通信两端主机中的进程。 如何为运行在不同主机上的应用进程提供直接的逻辑通信服务&#xff0c;就是运输层的主要任务。运输层协议又称为端到端协议。 运输层向应用层实体屏蔽了下面网络核心…

k8s资源的基本操作

文章目录 一、Namespace1、概述2、预定义的k8s命名空间2.1、default2.2、kube-public2.3、kube-system2.4、kube-node-lease 3、命名空间基本操作3.1、查看3.1.1、查看所有的命名空间3.1.2、查看指定的命名空间3.1.3、指定输出格式3.1.4、查看ns详情 3.2、创建3.2.1、命令行创建…

VMware vSphere Bitfusion 4.5.4 - 面向 AI 和 ML 应用提供弹性基础架构

VMware vSphere Bitfusion 4.5.4 - 面向 AI 和 ML 应用提供弹性基础架构 请访问原文链接&#xff1a;VMware vSphere Bitfusion 4.5.4 - 面向 AI 和 ML 应用提供弹性基础架构&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org VM…

Android图片圆角转换 RoundedImageView开源项目 小记(1)

android:background“#7f000000” android:paddingLeft“8dp” android:paddingRight“8dp” android:textAppearance“?android:attr/textAppearanceMediumInverse” /> <TextView android:id“id/textView1” android:layout_width“wrap_content” android:la…

十一、数据结构(图的最短路)

文章目录 基础部分最短路径问题用 D F S DFS DFS搜索所有的路径用 B F S BFS BFS求最短路径 最短路算法 F l o y d Floyd Floydcode(Floyd的实现): S P F A SPFA SPFAcode(基于邻接表的 S P F A ) SPFA) SPFA) D i j k s t r a Dijkstra Dijkstracode&#xff08;dijkstra的实现…

Excel导出实例

在上一节的基础上&#xff0c;本文演示下如何导出excel数据。 Excel导出操作演示 继承ocean-easyexcel SDK <dependency><groupId>com.angel.ocean</groupId><artifactId>ocean-easyexcel</artifactId><version>1.0.0</version> …

2024头歌数据库期末综合(部分题)

目录 第1关&#xff1a;数据表结构修改1 任务描述 学习补充 答案 第2关&#xff1a;数据记录删除 任务描述 学习补充 答案 第3关&#xff1a;数据表结构修改2 任务描述 学习补充 答案 第5关&#xff1a;数据查询一 任务描述 学习补充 答案 本篇博客声明&…

【ARMv8/ARMv9 硬件加速系列 4 -- 加解密 Cryptographic Extension 介绍】

文章目录 ARMv8.0 Cryptographic ExtensionFEAT_AESFEAT_PMULLFEAT_SHA1FEAT_SHA256ARMv8.2 扩展FEAT_SHA512FEAT_SHA3FEAT_SM3FEAT_SM4ARMv8.0 Cryptographic Extension ARMv8.0引入了加密扩展(Cryptographic Extension),旨在加速加密和解密操作。这一扩展通过新增专用指令…

【Linux】 yum学习

yum介绍 在Linux系统中&#xff0c;yum&#xff08;Yellowdog Updater, Modified&#xff09;是一个用于管理软件包的命令行工具&#xff0c;特别适用于基于RPM&#xff08;Red Hat Package Manager&#xff09;的系统&#xff0c;如CentOS、Fedora和Red Hat Enterprise Linux…

一、docker简介及卸载、安装

目录 一、Docker 简介 二、dockers三要素 1、Docker镜像&#xff08;image&#xff09; 2、Docker仓库 3、Docker容器 三、docker架构图 四. Docker 运行的基本流程 五、docker 卸载 1、停止docker服务 2、查看yum安装的docker文件包 3、查看docker相关的rpm源文件 …

力扣随机一题 模拟+字符串

博客主页&#xff1a;誓则盟约系列专栏&#xff1a;IT竞赛 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 1910.删除一个字符串中所有出现的给定子字符串【中等】 题目&#xff1a; …