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实现半球扫描效果

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

相关推荐
gis_rc3 天前
python下shp转3dtiles
python·3d·cesium·3dtiles·数字孪生模型
grasperp4 天前
3DTiles数据切片工具,支持LAS、OBJ、FBX 3DTiles怎么切片?3DTiles切片
cesium·3dtiles·三维gis·3dtiles切片·数据切片
duansamve6 天前
Cesium中实现在地图上移动/旋转点、线、面
cesium
冥界摄政王7 天前
CesiumJS学习第四章 替换指定3D建筑模型
3d·vue·html·webgl·js·cesium
冥界摄政王9 天前
Cesium学习第二章 camera 相机
node.js·html·vue3·js·cesium
冥界摄政王10 天前
Cesium学习第一章 安装下载 基于vue3引入Cesium项目开发
vue·vue3·html5·webgl·cesium
你们瞎搞12 天前
Cesium加载20GB航测影像.tif
前端·cesium·gdal·地图切片
闲云一鹤13 天前
Cesium 使用 Turf 实现坐标点移动(偏移)
前端·gis·cesium
二狗哈13 天前
Cesium快速入门34:3dTile高级样式设置
前端·javascript·算法·3d·webgl·cesium·地图可视化
二狗哈14 天前
Cesium快速入门33:tile3d设置样式
3d·状态模式·webgl·cesium·地图可视化