Cesium实时数据的雷达包络图渲染

一、效果

二、前言

由算法工程师给出雷达包络数据点,数据由方位角、高度、距离三部分组成的数组。我将这些点连成了线和面,加上了着色器扫描效果,跟之前分享的代码相比都中规中矩,没啥需要特别说明的。

三、核心代码

1.顶点的计算
复制代码
        //数据的俯仰值在递增、等增到一定值比如82之后,偏航值+1,俯仰值又在增,依次类推。数据是从经线的底部到顶部、顺时针转圈给出的。
        for (var pIndex = 0; pIndex < pointSum; pIndex++) {
            //     console.log( pIndex+'  偏航角:' +mergedArray[pIndex].azimuth+'  俯仰角:' +mergedArray[pIndex].elevation+'  距离' +mergedArray[pIndex].distance);
            var heading = Cesium.Math.toRadians(pointArray[pIndex].azimuth);
            var pitch = Cesium.Math.toRadians(pointArray[pIndex].elevation);
            var radius = pointArray[pIndex].distance;


            var x = radius * Math.sin(heading) * Math.cos(pitch);
            var y = radius * Math.cos(heading) * Math.cos(pitch);
            var z = radius * Math.sin(pitch);

            points.push(x);
            points.push(y);
            points.push(z);

        }
2.线段生成
复制代码
   // 创建线框几何体 - 使用LINES图元
        var wireframeIndices = [];
        for (var vvv = 0; vvv < vSteps - 1; vvv++) {
            for (var hhh = 0; hhh < hSteps; hhh++) {
                var index2 = vvv * hSteps + hhh;
                // 垂直线(纬度方向)
                wireframeIndices.push(index2, index2 + hSteps);
                // 水平线(经度方向) - 仅当不是最后一条经线时
                if (hhh < hSteps - 1) {
                    wireframeIndices.push(index2, index2 + 1);
                }
            }
        }

        console.log(wireframeIndices);
//构建几何体对象
        var geometry2 = new Cesium.Geometry({
            attributes: {
                position: new Cesium.GeometryAttribute({
                    componentDatatype: Cesium.ComponentDatatype.DOUBLE,
                    componentsPerAttribute: 3,
                    values: points
                })
            },
            indices: wireframeIndices,
            primitiveType: Cesium.PrimitiveType.LINES,
            boundingSphere: Cesium.BoundingSphere.fromVertices(points)
        });

        //构建对象实例
        var instance = new Cesium.GeometryInstance({
            geometry: geometry2,
            attributes: {
                color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.AQUA.withAlpha(0.5)) //******
            },
            id: 'top',
            modelMatrix: Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(
                Cesium.Cartesian3.fromDegrees(105.59777, 40.03883)), new Cesium.Cartesian3(0.0, 0.0, 10.0), new Cesium.Matrix4()),
        });

        //创建这个外表
        var appearance = new Cesium.PerInstanceColorAppearance({
            flat: true,
            translucent: true,
            vertexShaderSource: vs,
            fragmentShaderSource: fs,
        });
3.动态扫描实现
复制代码
//顶点着色器
        var vs = `attribute vec3 position3DHigh;
               attribute vec3 position3DLow;
               attribute vec4 color;
               attribute float batchId;
               varying vec4 v_color;
               varying vec3 v_position;
               void main()
               {
                    v_position = position3DHigh + position3DLow;
                    v_color = color;

                    //方式1
                    // vec4 p = czm_computePosition();
                    // gl_Position = czm_modelViewProjectionRelativeToEye *p;

                    //方式2
                    gl_Position = czm_modelViewProjection * vec4(v_position,1.0);

                    //方式3
                    //vec4 p = czm_translateRelativeToEye(position3DHigh, position3DLow);
                    //gl_Position = czm_modelViewProjectionRelativeToEye * p;

               }`;

        //片元着色器 - 修正了扫描方向和区域判断
        var fs = `varying vec4 v_color;
               varying vec3 v_position;
               uniform float u_time;
               uniform float u_scanWidth; // 扫描扇区宽度(弧度)

               void main()
               {

                   // 计算当前点在XOY平面上的角度(相对于X轴)
                   float currentAngle = atan(v_position.y, v_position.x);//[-czm_pi,czm_pi]

                   // 计算扫描线的角度(随时间变化,取负号使旋转方向为顺时针)
                   float scanAngle = mod(-u_time, 2.0*czm_pi); // [0,2PI]

                   // 计算当前点相对于扫描线的角度差(带方向)currentAngle - scanAngle在[-3PI,czm_pi]
                   float angleDiff = mod(currentAngle - scanAngle + 3.0*czm_pi, 2.0*czm_pi) - czm_pi;//最终结果在[-czm_pi,czm_pi]

                   // 判断是否在扫描扇区内(只考虑扫描线前方的区域)
                   if(angleDiff > 0.0 && angleDiff < u_scanWidth) {
                       // 计算相对距离(0-1范围),0表示扫描线位置,1表示扫描区域末尾
                       float relativeDistance = angleDiff / u_scanWidth;
                       // 透明度从1.0(扫描线位置)线性过渡到几何体的基础透明度(扫描区域末尾)
                       float alphaFactor = 1.0 - relativeDistance;
                       vec3 scanColor = vec3(1.0, 1.0, 0.0);
                       gl_FragColor = vec4(mix(v_color.rgb, scanColor, alphaFactor), mix(v_color.a, 1.0, alphaFactor));
                   } else {
                       gl_FragColor = v_color;
                   }
               }`;

四、变形效果(只绘制出点)

修改点1:

替换掉顶点和片源着色器为如下:

复制代码
    const vs = `
        attribute vec3 position3DHigh;
        attribute vec3 position3DLow;
        varying vec3 v_position;
        attribute vec4 color;
        varying vec4 v_color;
        attribute float batchId;
        void main() {
            v_position = position3DHigh + position3DLow;
            gl_Position = czm_projection * czm_modelView * vec4(v_position, 1.0);
            gl_PointSize = 5.0;  // 设置点的大小(单位:像素)
            v_color = color;
        }
`;

        const fs = `
        varying vec4 v_color;
        void main() {
            gl_FragColor = v_color;
            // 如果需要圆形点而不是方形点
            vec2 coord = gl_PointCoord - vec2(0.5);
            if (length(coord) > 0.5) {
                discard;
            }
        }
`;

修改点2:

修改绘制方式为点,并去掉索引,其他不变,代码如下:

复制代码
        //构建几何体对象
        var geometry2 = new Cesium.Geometry({
            attributes: {
                position: new Cesium.GeometryAttribute({
                    componentDatatype: Cesium.ComponentDatatype.DOUBLE,
                    componentsPerAttribute: 3,
                    values: points
                })
            },
            // indices: wireframeIndices,
            primitiveType: Cesium.PrimitiveType.POINTS,
            boundingSphere: Cesium.BoundingSphere.fromVertices(points)
        });

绘制方法参见我的这边博文Cesium实现半球扫描效果

原创不易,记得点赞加关注哦,我会持续分享实用的功能(:-

相关推荐
二狗哈2 天前
Cesium快速入门27:GeoJson自定义样式
前端·cesium·着色器
二狗哈3 天前
Cesium快速入门26:加载渲染GeoJson数据
3d·webgl·cesium·地图可视化
GIS遥遥3 天前
本科想找三维GIS的工作,需要学什么?
cesium·gis开发·三维gis·webgis开发
二狗哈4 天前
Cesium快速入门24:Appearance编写着色器修改外观
3d·webgl·cesium·着色器·地图可视化
二狗哈5 天前
Cesium快速入门22:fabric自定义着色器
运维·开发语言·前端·webgl·fabric·cesium·着色器
二狗哈6 天前
Cesium快速入门21:Primitive材质类型与设置
3d·webgl·材质·cesium·地图可视化
二狗哈6 天前
Cesium快速入门18:Entity材质设置
3d·webgl·材质·cesium·地图可视化
二狗哈7 天前
Cesium快速入门19:Entity折线材质
3d·webgl·材质·cesium·地图可视化
二狗哈7 天前
Cesium快速入门17:与entity和primitive交互
开发语言·前端·javascript·3d·webgl·cesium·地图可视化