开源!Cesium中实现酷炫三维风场模拟,助力仿真预测!

2,698 阅读7分钟

大家好,我是日拱一卒的攻城师不浪,致力于技术与艺术的融合。这大概是2024年输出的最后一篇文章啦~

前言

本来今年给自己定的目标是100篇,但实际上只完成了51篇

其实我一开始就知道自己大概率写不完100篇,那我为什么还要去设置这个数字呢?只是因为我想逼自己去无限接近这个数字,因为我知道如果我设定的目标是50篇的话,那我大概率也就是二三十篇的量!

100,既不是一个很离谱很难达到的目标,也不是一个上限很低的阈值,我认为刚刚好,今年的输出量我给自己打一个及格

好了,过两天我会写一篇自己的年终总结,也欢迎小伙伴们围观。

最近几天,有很多小伙伴跟我要三维风场的效果,今天它来了!源码地址文末自取。

实现方式

在Cesium中实现风场效果其实有很多种方法,以下是几种常见的实现方式,我们来逐一分析:

1. 基于纹理贴图的动态渲染

原理:

  • 使用预生成的风场矢量数据(如NetCDFGRIB数据格式)。

  • 将风场矢量数据转换为二维纹理贴图,映射到Cesium的地球表面。

  • 使用着色器动态更新纹理贴图,以模拟风场流动。

优点:

  • 实现相对简单,性能较高。
  • 可以通过调节着色器实现丰富的视觉效果,如色彩渐变、透明度变化等。

缺点:

  • 风场的三维效果较弱,主要用于显示地表的风速和风向。
  • 对动态风场的实时计算能力有限,灵活性较低。

2. 基于粒子系统的风场模拟

原理:

  • 使用Cesium的粒子系统功能,将风速和风向数据作为粒子移动的矢量场。

  • 根据风场数据计算粒子的运动路径。

  • 可通过粒子的速度、大小、颜色和寿命来增强视觉效果。

优点:

  • 可以实现三维风场的动态模拟,效果逼真。

  • 灵活性强,适合动态变化的风场场景。

  • 支持高度差异,能表现不同高度的风场特性。

缺点:

  • 计算量大,对性能要求高。

  • 实现复杂度较高,需要深入优化性能。

3. 使用WebGL实现自定义风场渲染

原理:

  • 编写自定义的WebGL着色器,基于风场数据实现线条流动效果(如StreamlinePathline)。

  • 通过纹理坐标和顶点计算实时绘制风场的动态流线。

  • 可以结合Cesium的Primitive API渲染到地球表面或空间中。

优点:

  • 高度定制化,适合复杂场景。

  • 可以实现高效的实时流场渲染,支持复杂的动态效果。

缺点:

  • WebGL编程门槛较高,代码复杂。

  • 需要对风场数据进行预处理和优化。

  • 调试和维护成本较高。

4. 基于第三方库的集成

原理:

  • 数据处理由第三方库完成,Cesium仅负责展示。

优点:

  • 开发效率高,快速实现风场可视化。
  • 效果成熟,第三方库通常已优化性能。

缺点:

  • 可定制性较低,效果受第三方库限制。
  • 与Cesium深度集成可能存在兼容性问题。
  • 某些库的依赖性可能导致项目负担增加。

综合比较

实现方式效果逼真程度性能实现难度定制化使用场景
纹理贴图动态渲染★★★★★★★★★★★地表风场,性能优先
粒子系统模拟★★★★★★★★★★★★★★★三维风场,动态交互
自定义WebGL风场渲染★★★★★★★★★★★★★★★★★★★复杂风场可视化
第三方库集成★★★★★★★★★★★快速开发,效果稳定

选择建议

  • 实时性和精度要求较低:纹理贴图动态渲染。

  • 需要三维动态风场效果:基于粒子系统。

  • 需要高度定制和复杂交互:自定义WebGL风场渲染。

  • 开发周期紧张或效果优先:使用第三方库集成。

我们在做项目的过程中,通常需要根据项目需求选择合适的实现方式,并在性能效果之间权衡利弊才是关键。

三维风场作用以及应用场景

三维风场可视化技术是一种将风速风向数据以直观的图形方式展现的技术,它在气象学环境科学航空航天等领域有着广泛的应用。

通过这种技术,我们可以更直观地理解风的动态变化,预测天气模式,评估环境影响,甚至在航海和航空领域辅助进行动态路径规划

粒子实现风场

今天我们开源的风场效果,主要是基于粒子系统实现,我们来了解下主要细节。

数据获取

数据源:nomads.ncep.noaa.gov/ (记得要grid转json)

借助cesium-wind插件

作者:joe,开源地址:github.com/QJvic/cesiu…

我们主要来看下插件的主要功能函数:

  1. 数据格式化formatData函数负责将GFS(全球预报系统)数据转换为Field对象,这个对象包含了风速的U(东西方向)和V(南北方向)分量。
function formatData(data) {
    var uComp, vComp;
    // ...省略部分代码...
    var vectorField = new Field({
        xmin: header.lo1,
        ymin: header.la1,
        xmax: header.lo2,
        ymax: header.la2,
        deltaX: header.dx,
        deltaY: header.dy,
        cols: header.nx,
        rows: header.ny,
        us: uComp.data,
        vs: vComp.data
    });
    return vectorField;
}
  1. 向量场计算Field类是风场计算的核心,它包含了构建网格、双线性插值、计算风速范围等方法。
var Field = /** @class */ (function () {
    function Field(params) {
        // ...省略部分代码...
        this.grid = this.buildGrid();
        this.range = this.calculateRange();
    }
    // ...省略部分代码...
    Field.prototype.bilinearInterpolateVector = function (x, y, g00, g10, g01, g11) {
        // 双线性插值计算向量
        var rx = 1 - x;
        var ry = 1 - y;
        var a = rx * ry;
        var b = x * ry;
        var c = rx * y;
        var d = x * y;
        var u = g00.u * a + g10.u * b + g01.u * c + g11.u * d;
        var v = g00.v * a + g10.v * b + g01.v * c + g11.v * d;
        return new Vector(u, v);
    };
    // ...省略部分代码...
    return Field;
}());
  1. 粒子动画BaseLayer类负责在画布上绘制粒子动画,模拟风的流动。
var BaseLayer = /** @class */ (function () {
    function BaseLayer(ctx, options, field) {
        // ...省略部分代码...
        this.particles = this.prepareParticlePaths();
        this.generated = true;
    }
    // ...省略部分代码...
    BaseLayer.prototype.drawParticles = function () {
        // 绘制粒子路径
        var particles = this.particles;
        this.fadeIn();
        this.ctx.globalAlpha = this.options.globalAlpha;
        // ...省略部分代码...
        for (var i = 0; i < len; i++) {
            this[this.options.useCoordsDraw ? 'drawCoordsParticle' : 'drawPixelParticle'](particles[i], min, max);
        }
    };
    // ...省略部分代码...
    return BaseLayer;
}());

开发原理

  1. 数据驱动:整个风场可视化过程是基于数据驱动的,首先需要从气象数据源获取风速和风向数据,然后通过formatData函数将数据格式化为Field对象。

  2. 双线性插值:为了在任意位置获得风速和风向,Field类使用双线性插值方法bilinearInterpolateVector来估算非格点位置的风场数据。

  3. 粒子动画模拟BaseLayer类通过模拟粒子在风场中的运动来可视化风的流动,粒子的路径由风速和风向决定,通过不断更新粒子位置来实现动画效果。

  4. 性能优化:考虑到性能问题,BaseLayer类在prerender方法中预先生成粒子路径,避免在每一帧渲染时都进行复杂的计算。

最后

开源地址: 【贾宛龙的开源】:github.com/jiawanlong/…

【不浪的开源】github.com/tingyuxuan2…

不会Cesium的基础,也很难做出更高级的效果,所以可以了解下不浪的教程《Cesium从入门到实战》,将Cesium的知识点进行串联,让不了解Cesium的小伙伴拥有一个完整的学习路线,并最终完成一个智慧城市的完整项目,课程也在不断更新迭代中,想了解+作者:brown_7778(备注来意)。

有需要进可视化&Webgis交流群可以加我:brown_7778(备注来意),另外也可接项目合作。