当前位置: 代码迷 >> 综合 >> openlayers 实现风场效果图
  详细解决方案

openlayers 实现风场效果图

热度:71   发布时间:2023-12-03 09:15:48.0

要求:在地图中展示风场效果,大致效果如下图
在这里插入图片描述
由于不会这方面的原理,只能搬砖,也没啥好说的,下面开始搬砖吧。
开发环境: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: 1dy: 1la1: -7.5la2: -28.5lo1: 143lo2: 156nx: 14ny: 22parameterCategory: 2parameterNumber: 2parameterNumberName: "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;}}
  相关解决方案