openlayers 实现风场效果图

要求:在地图中展示风场效果,大致效果如下图

由于不会这方面的原理,只能搬砖,也没啥好说的,下面开始搬砖吧。
开发环境:openlayers5
参考:
https://github.com/Esri/wind-js
https://github.com/blissvisitor/wind-layer
https://github.com/sakitam-fdd/wind-layer
https://blog.csdn.net/u012413551/article/details/94298039
https://www.cnblogs.com/yanjinliang/p/7879312.html
思路:
利用别人封装的适用于openlayers的windy.js开发风场效果,风场数据采用项目中json文件夹下的current-wind.json做数据源
主体代码:

var projection = ol.proj.get('EPSG:4326');
    var projectionExtent = projection.getExtent();
    var size = ol.extent.getWidth(projectionExtent) / 256;
    var resolutions = new Array(19);
    var matrixIds = new Array(19);
    for (var z = 1; z < 19; ++z) {
        resolutions[z] = size / Math.pow(2, z);
        matrixIds[z] = z;
    }
    var map = new ol.Map({
        target: 'map',
        layers: [
            new ol.layer.Tile({
                source: new ol.source.WMTS({
                    name: "天地图影像地图",
                    url: "http://t{0-7}.tianditu.gov.cn/vec_c/wmts?tk=1b94e3699b4d7b567dfb6c82599ef519",
                    layer: "vec",
                    style: "default",
                    matrixSet: "c",
                    format: "tiles",
                    wrapX: true,
                    tileGrid: new ol.tilegrid.WMTS({
                        origin: ol.extent.getTopLeft(projectionExtent),
                        resolutions: resolutions,
                        matrixIds: matrixIds
                    })
                }),
                maxResolution: resolutions[0],
                minResolution: resolutions[18]
            })
        ],
        view: new ol.View({
            projection: 'EPSG:4326',
            center: [113.53450137499999, 34.44104525],
            zoom: 5
        })
    });
function getWindyLayer(){
	$.ajax({
	    url:"json/current-wind.json",
	    type:"get",
	    dataType:"json",
	    success:function(result){
	        if(result.returnCode == "0"){
	            windydata = JSON.parse(result.DS.content);
	            if(!!windyLayer){
	                windyLayer.setData(windydata);
	            }else{
	                windyLayer = new WindLayer(windydata, {
	                    layerName: 'data',
	                    projection: 'EPSG:4326',
	                    ratio: 1,
	                    map: map
	                });
	                windyLayer.appendTo(map);
	            }
	        }else{
	            alert("暂无风场数据!");
	        }
	    }
	})
}
function exitWindyLayer(){
    windyLayer.clearWind();
}
        

效果:
https://kaixin51.github.io/openlayers-windy/

最近有个需求是,通过这个风场的数据,要求点击地图上任意一个点,返回风有关的详情。一脸懵逼中,然后去查了一下数据对应的含义:得到以下信息:
风场数据结构大致为:

[
    {
        header: {
            dx: 1
            dy: 1
            la1: -7.5
            la2: -28.5
            lo1: 143
            lo2: 156
            nx: 14
            ny: 22
            parameterCategory: 2
            parameterNumber: 2
            parameterNumberName: "eastward_wind"
            parameterUnit: "m.s-1"
            refTime: "2017-02-01 23:00:00"
        },
        data:[num1,num2,....]
    },{
        header{
            结构同上
        },
        data:[.....]
    }

]

其中:
dx、dy网格间距,
nx、ny网格数量,总网格数量= nx * ny = data.length;
parameterNumberName:表示风向
parameterUnit:风速单位
lo1:起点经度
la1:起点纬度
lo2:终点经度
la2:终点纬度

data中提供了正东方向和正北方向的风速,于是可以求得对应的风速和风向。


var allgrid = [];
function analysisWindyData(windydata){
	var p = 0;
	var east,north;
	if(windydata[0].header.parameterNumberName == "eastward_wind"){
		east = windydata[0];
		north = windydata[1];
	}else{
		east = windydata[1];
		north = windydata[0];
	}
	for (var j = 0; j < north.header.ny; j++) {
      var row = [];
      for (var i = 0; i < north.header.nx; i++, p++) {
        row[i] = [east.data[p],north.data[p]];
      }
      grid[j] = row;
    }
}

function getWindyDetail(coord){
    var lng = coord[0];
    var lat = coord[1];
    if(lng < 70 || lng > 140 || lat < 0 || lat > 60){
        layer.alert("暂无该区域风向数据!");
        return;
    }
    var xlength = Math.floor((lng-70)/0.5);
    var ylength = Math.floor((60-lat)/0.5);
    var xdata,ydata;
    xdata = allgrid[ylength][xlength][0];
    ydata = allgrid[ylength][xlength][1];
    console.log(xdata);
    console.log(ydata);
    var v = Math.sqrt(Math.pow(xdata,2)+Math.pow(ydata,2));
    var angle = getWindyAngle(xdata,ydata);
    var result = {
        "direction":getWindyDirection(angle),
        "level":getWindyLevel(v),
        "speed":v.toFixed(2)
    };
    return result;
}

function getWindyDirection(angle){
    if((angle >=0 && angle <= 22.5) || (angle <=360 && angle >337.5)){
        return "北风";
    }
    if(angle <=337.5 && angle >292.5){
        return "西北风";
    }
    if(angle <=292.5 && angle > 247.5){
        return "西风";
    }
    if(angle <=247.5 && angle > 202.5){
        return "西南风";
    }
    if(angle <= 202.5 && angle >157.5){
        return "南风";
    }
    if(angle <=157.5 && angle > 112.5){
        return "东南风";
    }
    if(angle <= 112.5 && angle >67.5){
        return "东风";
    }
    if(angle <= 67.5 && angle >22.5){
        return "东北风";
    }
}

function getWindyAngle(u,v) {
    var fx = 0;
    if (u > 0 & v > 0) {
        fx = 270 - Math.atan(v / u) * 180 / Math.PI;
    }
    else if (u < 0 & v > 0) {
        fx = 90 - Math.atan(v / u) * 180 / Math.PI;
    }
    else if (u < 0 & v < 0) {
        fx = 90 - Math.atan(v / u) * 180 / Math.PI;
    }
    else if (u > 0 & v < 0) {
        fx = 270 - Math.atan(v / u) * 180 / Math.PI;
    }
    else if (u == 0 & v > 0) {
        fx = 180;
    }
    else if (u == 0 & v < 0) {
        fx = 0;
    }
    else if (u > 0 & v == 0) {
        fx = 270;
    }
    else if (u < 0 & v == 0) {
        fx = 90;
    }
    else if (u == 0 & v == 0) {
        fx = 999.9;
    }
    return fx;
}

function getWindyLevel(v){
    if(v<0.3){
        return 0;
    }
    if(v>=0.3 && v<1.6){
        return 1;
    }
    if(v>=1.6 && v<3.4){
        return 2;
    }
    if(v>=3.4 && v<5.5){
        return 3;
    }
    if(v>=5.5 && v<8.0){
        return 4;
    }
    if(v>=8.0 && v<10.8){
        return 5;
    }
    if(v>=10.8 && v<13.9){
        return 6;
    }
    if(v>=13.9 && v<17.2){
        return 7;
    }
    if(v>=17.2 && v<20.8){
        return 8;
    }
    if(v>=20.8 && v<24.5){
        return 9;
    }
    if(v>=24.5 && v<28.5){
        return 10;
    }
    if(v>=28.5 && v<32.7){
        return 11;
    }
    if(v>=32.7 && v<37.0){
        return 12;
    }
    if(v>=37.0 && v<41.5){
        return 13;
    }
    if(v>=41.5 && v<46.2){
        return 14;
    }
    if(v>=46.2 && v<51.0){
        return 15;
    }
    if(v>=51.0 && v<56.1){
        return 16;
    }
    if(v>=56.1 && v<61.2){
        return 17;
    }
    if(v>=61.2){
        return 18;
    }

}

你可能感兴趣的