webGis 气象格点数据解析与渲染

1.格点数据说明

1.1 数据来源

格点数据的原始数据一般是netcdf数据或grib2数据,然后解析后的数据。

1.2 数据传输

需要将格点气象数据实现前端的展示,数据传输的方式有三种:

  1. json
  2. 二进制 (前端转json)
  3. 灰度图  (暂时不讲,不知道具体如何实现)

1.3 数据解析

{
    "header": {
        "la1": 54,
        "lo1": 73,
        "la2": 18,
        "lo2": 136,
        "nx": 630,
        "ny": 360
    },
    "data": [
        ......
    ]
}
  • 说明:
  1. header为头文件,用以说明数据的信息,其中:la1为左上,lo1为左下,la2为右下,lo2为右上,nx为行数,ny为列数。
  2. data为数据,数据是从左上开始逐行将格点的气象数据转换为一个一维数组

2 色斑图渲染

2.1原理

  • 根据网格点的值进行颜色插值。
  • idw插值(反距离权重)

2.2 实现

2.2.1二维实现

准备   如要生成全球 bound应为-90 --90  -180--180,分辨率稍微大点。

      let tileLayer = DRAWIMGfun(data, {
        color: rgba, //阈值,必传参数
        tile_size: 1290, //设置渲染分辨率,越大越清晰
        gradient: 0.25, //设置渐变度,越小渐变越小,最大0.5,0.25是完全渐变
        opacity: 0.6,
        pane: "radar",
        noWrap: false,
        viewer: viewer,
        opacityThreshold: null,
        boundData: bound,//必传
      });

首先生成网格

    this.setGrid = function(data) {
        //因为地理位置的原因,lat坐标要反转
        //		this.grid_data = data.data.reverse();


        data.data = data.data.reverse();



        this.grid = {
            latmin: data.latmin,
            latmax: data.latmax,
            lonmin: data.lonmin,
            lonmax: data.lonmax,
            nlat: data.nlat,
            nlon: data.nlon,
            ele: data.ele,
            interval_lat: data.interval_lat,
            interval_lng: data.interval_lng,
        }


        this.grid_data = []
        var p = 0;
        var isContinuous = Math.floor(data.nlon * data.interval_lng) >= 360;
        //x方向的跨度乘以x方向的数量是否大于360
        for (var j = 0; j < data.nlat; j++) {
            var row = [];
            for (var i = 0; i < data.nlon; i++) {

                row[i] = data.data[(j * data.nlon) + i];


            }
            if (isContinuous) {
                // For wrapped grids, duplicate first column as last column to simplify interpolation logic
                row.push(row[0]);
            }


            this.grid_data[j] = row;
        }

        // console.log(data.data, this.grid_data);
        //grid是一个二维数组
        //第一纬表示行数
        //第二纬表示列数
        //值为uv

        // [
        //     [
        //         'uv'
        //     ]
        // ]
    }

然后绘制

原理是根据经纬度边界与canvas总像素网格数据对应,得到像素与经纬度对应的值,根据值对应色带设置像素的rgba.

    this.draw = function(ctx, tile_latlng, tile) {
        var color = this.color;
        var grid = this.grid;
        var grid_Data = this.grid_data;

        var vs = [];

        setTimeout(function() {
            var rgba = ctx.createImageData(this.tile_size, this.tile_size);
            for (var i = 0; i < this.tile_size; i++) {
                vs.push([])
                for (var j = 0; j < this.tile_size; j++) {
                    // 只需要得到经纬度的边界值(tile_latlng)就可插值 
                    // j, i为像素值 --> 得到权重值插值 --> 得到颜色值
                    var latlng = imgfun.get_px_latlng(tile_latlng, j, i, this.tile_size);
                    // var latlng = this.pixelPointToLayerPoint(tile_latlng.p, j, i, tile_latlng.z, this.tile_size);
                    var v = imgfun.insertData(latlng.lat, latlng.lng, grid, grid_Data);
                    var thisrgb = imgfun.getrgba(v, color, this.gradient);


                    rgba.data[(i * this.tile_size + j) * 4 + 0] = thisrgb[0];
                    rgba.data[(i * this.tile_size + j) * 4 + 1] = thisrgb[1];
                    rgba.data[(i * this.tile_size + j) * 4 + 2] = thisrgb[2];
                    rgba.data[(i * this.tile_size + j) * 4 + 3] = thisrgb[3] *
                        this.opacity;


                    vs[i].push(v);
                }
            }
            // console.log(vs);

            ctx.putImageData(rgba, 0, 0);
            // ctx.globalAlpha = this.opacity;
            tile.style.pointerEvents = 'initial';
        }.bind(this), 50)



    }
    get_px_latlng: function(t, x, y, tile_size) {
        //参数:瓦片的最大最小经纬度,瓦片画布像素,需要计算的点的x,y坐标
        var lng = t.lonmin + (t.lonmax - t.lonmin) * x / tile_size;
        var lat = t.latmax - (t.latmax - t.latmin) * y / tile_size;
        return { lat, lng };
    },
2.2.2三维实现

原理与二维一样,将生成的canvas图片以贴图形式展示即可。

           // 不宜使用entitiy类因为entitiy类更倾向具体实体,不易用作全局场景,可能会有材质问题(展示不全,切换视角消失图块等)。
            // this.boundData.lonmax = this.boundData.lonmax - 180;
            // this.boundData.lonmin = Number(this.boundData.lonmin) - 180;
            // this.viewer.entities.add({
            //     rectangle: {
            //         coordinates: Cesium.Rectangle.fromDegrees(this.boundData.lonmin, this.boundData.latmin, this.boundData.lonmax, this.boundData.latmax),
            //         material: new Cesium.ImageMaterialProperty({
            //             image: tile.toDataURL("image/png"), //使用贴图的方式将结果贴到面上
            //             // transparent: true
            //         }),
            //     },
            // });


            //全局底图倾向Scene类表示全局,不易使用entitiy类因为entitiy类更倾向具体实体,不宜用作全局场景,可能会有材质问题(展示不全,切换视角消失图块等)。
            //使用SingleTileImageryProvider 是 Cesium 中的一个类,用于表示单个图块的影像数据源。无材质bug
            this.meteLayer = this.viewer.imageryLayers.addImageryProvider(new Cesium.SingleTileImageryProvider({
                url: tile.toDataURL("image/png"),
                tileWidth: 256, // 图块宽度
                tileHeight: 256, // 图块高度
                ellipsoid: Cesium.Ellipsoid.WGS84
            }));
            this.meteLayer._id = "meteLayerProvider";

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值