cesium中动态渲染热力图

1、引入插件

CesiumHeatmap-master.js

2、封装js

大概的实现步骤:

1)选择中心点:以某个指定点作为热力图的中心。

2)确定半径:定义一个半径来确定热力图的影响范围。

3)计算边界:基于半径计算出该范围的边界区域。

4)生成随机点:在边界区域内生成随机点来表示热力图中的数据分布。

5)绘制热力图:使用这些点的分布情况来以此形成热力图。

//-----------------加载热力图start------------------//
//图片
var image = new Image(); 
//最小值
let valueMin = 0;
//最大值
let valueMax = 200;
var randomRect = []; //存储随机生成的热力图,矩形,延迟方法
var randomid = 0; //id

//点,随机数,生成热力图
function PointRandomHeatMap() {
    // viewer.clock.shouldAnimate = true;
   
    var point = {
        longitude: 108.45,
        latitude: 33.9,
        height: 11.409122369106317
    }
    var primitiveid = "test";
    var radius = 200; //半径  
    var randiusPoint = 200; //点周围范围半径内
    var rvalue = 150; //范围半径
    // 计算边界
    var west = point.longitude - Cesium.Math.toDegrees(rvalue / Cesium.Ellipsoid.WGS84.maximumRadius);
    var south = point.latitude - Cesium.Math.toDegrees(rvalue / Cesium.Ellipsoid.WGS84.maximumRadius);
    var east = point.longitude + Cesium.Math.toDegrees(rvalue / Cesium.Ellipsoid.WGS84.maximumRadius);
    var north = point.latitude + Cesium.Math.toDegrees(rvalue / Cesium.Ellipsoid.WGS84.maximumRadius);

    var bounds = new Cesium.Rectangle(west, south, east, north);

// 输出计算得到的边界

    viewer.camera.setView({
        destination: Cesium.Rectangle.fromDegrees(bounds.west, bounds.south, bounds.east, bounds.north)
    });

    // var data = getDatapoint(point, bounds, randiusPoint, 100); //数据
    // 定义热力图的角度范围
    var northeastDirectionRange = {
    min: Math.PI / 6, // 45度,指向东北方向开始
    max: 3 * Math.PI / 6 // 135度,指向东北方向结束
    };
var data = getDatapoint(point, bounds, randiusPoint, 100,northeastDirectionRange);//数据
    var heatMap;

    var heatPrimitive = viewer.scene.primitives.add(
        new Cesium.GroundPrimitive({
            geometryInstances: new Cesium.GeometryInstance({
                geometry: new Cesium.RectangleGeometry({
                    rectangle: Cesium.Rectangle.fromDegrees(bounds.west, bounds.south, bounds.east, bounds.north),
                    vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
                }),
            }),
            appearance: new Cesium.EllipsoidSurfaceAppearance({
                aboveGround: true,
                material: new Cesium.Material({
                    fabric: {
                        type: "Image",
                        uniforms: {
                            image: image.src,
                        },
                    },
                }),
            }),
        })
    );
    heatPrimitive.id = primitiveid;
    heatPrimitive.show = false;

    SyncCreate(valueMin, valueMax, radius, data, heatPrimitive);

    // viewer.clock.onTick.addEventListener(syncRadius);
    //动态加载渲染
    var synctimer1 = setInterval(function () {
        console.log('4444444动态加载渲染',)
        syncRadius();
    }, 100);

    randomRect.push({
        id: heatPrimitive.id,
        obj: {
            heatmap: heatMap,
            primitive: heatPrimitive,
            synctimer: synctimer1
        }
    });

    function syncRadius(params) {
        //clearInterval(synctimer1);
        radius++;
        if (radius >= 100) {
            radius = 0;
        }
        SyncCreate(valueMin, valueMax, radius, data, heatPrimitive);
        //到达点后清除掉
        if (radius == 80) {
            ClearHeatMapSync('test')
            clearInterval(synctimer1);
            radius = 100.0;
            heatMap.clearLayer();
            viewer.scene.primitives.remove(heatPrimitive);
            viewer.scene.requestRender(); // 请求一个新的渲染帧
            viewer.entities.removeAll()
            CameraFlyTo1(115.628414, 29.668894, 5000000); //改变默认初始地图高度
        }
    }

    //生成
    function SyncCreate(valueMin, valueMax, radius, data, heatPrimitive) {
        viewer.scene.requestRender(); // 请求一个新的渲染帧
        heatMap = CesiumHeatmap.create(
            viewer, // 视图层
            bounds, // 矩形坐标
            { // heatmap相应参数
                backgroundColor: "rgba(0,0,0,0)",
                radius: radius,
                maxOpacity: .5,
                minOpacity: 0,
                blur: .75
            }
        );

        heatMap.setWGS84Data(valueMin, valueMax, data);
        heatMap.show(false);
        CreateImageCanvasSync(heatMap, heatPrimitive);
    }

}

// 计算范围内的随机点,限制在特定方向范围内生成
function getDatapoint(point, bounds, rp, length, directionRange) {
var data = [];
data.push({ x: point.longitude, y: point.latitude, value: valueMax });
 
for (var i = 0; i < length; i++) {
    // 生成随机方位角,限制在给定的方向范围内
    var bearing = Cesium.Math.randomBetween(directionRange.min, directionRange.max);
    
    // 生成随机距离(在半径范围内)
    var distance = Cesium.Math.randomBetween(0, rp);

    // 根据中心点、方位角和距离计算生成点的经纬度坐标
    var randompoint = calculatingTargetPoints(point, bearing, distance);

    var x = randompoint.longitude;
    var y = randompoint.latitude;
    var value = Math.random() * 100;
    data.push({ x: x, y: y, value: value });
}
return data;
}

//热力图数据渲染成图片,贴在地图上
function CreateImageCanvasSync(heatMap, heatPrimitive) {

    //指定格式PNG,更新材质
    image.src = heatMap._heatmap._renderer.canvas.toDataURL("image/jpg");
    heatPrimitive.appearance.material.uniforms.image = image.src;
    heatPrimitive.show = true;

    if (heatMap.getLayer()) {
        heatMap.clearLayer();
    }

}

//清除结果
function ClearHeatMapSync(id) {
    var ob = GetObj(id);
    clearInterval(ob.b.obj.synctimer);
    ob.b.obj.heatmap.clearLayer();
    viewer.scene.primitives.remove(ob.b.obj.primitive);
    randomRect.splice(ob.a, 1);
}

//根据id查找
function GetObj(id) {
    for (var i = 0; i < randomRect.length; i++) {
        if (randomRect[i].id == id) {

            return {
                a: i,
                b: randomRect[i]
            };
        }
    }
}

//----------------------------end热力图end----------------------//

3、调用

在页面引入封装的js,调用下方函数就可以

  PointRandomHeatMap()

4、效果

1)、 热力图设置角度范围

    var DirectionRange = {

    min: Math.PI / 4, // 45度,指向东北方向开始

    max: 3 * Math.PI / 4 // 135度,指向东北方向结束

};

利用数学中的计算方式,算出它的一个弧度

2)热力图圆圈显示

去掉DirectionRange  这个传参;

计算函数里面,代码改成

//计算范围内的随机点
function getDatapoint(point, bounds, rp, length) {
    data = [];
    data.push({
        x: point.longitude,
        y: point.latitude,
        value: valueMax
    });

    for (var i = 0; i < length; i++) {

        // 生成随机方位角(bearing)
        var bearing = Cesium.Math.randomBetween(0, 2 * Math.PI);
        // 生成随机距离(在半径范围内)
        var distance = Cesium.Math.randomBetween(0, rp);
        var randompoint = calculatingTargetPoints(point, bearing, distance);

        var x = randompoint.longitude; //point.longitude + Math.random() * (bounds.west - bounds.east);
        var y = randompoint.latitude; //point.latitude + Math.random() * (bounds.north - bounds.south);
        var value = Math.random() * 100;
        data.push({
            x: x,
            y: y,
            value: value
        });
    }
    return data;
}

是动态效果,截图是静态,可以自己运行试试

5、少个函数,补充

    //计算一个点周围某一方向,某一距离上的点
    function calculatingTargetPoints(pos, direction, radius) {
      // 观察点
      var viewPoint = Cesium.Cartesian3.fromDegrees(pos.longitude, pos.latitude, pos.height);
      // 世界坐标转换为投影坐标
      var webMercatorProjection = new Cesium.WebMercatorProjection(viewer.scene.globe.ellipsoid);
      var viewPointWebMercator = webMercatorProjection.project(Cesium.Cartographic.fromCartesian(viewPoint));
      // 计算目标点
      var toPoint = new Cesium.Cartesian3(viewPointWebMercator.x + radius * Math.cos(direction), viewPointWebMercator.y +
        radius * Math.sin(direction), 0);
      // 投影坐标转世界坐标
      toPoint = webMercatorProjection.unproject(toPoint);
      toPoint = Cesium.Cartographic.toCartesian(toPoint.clone());
      // 世界坐标转地理坐标
      var cartographic = Cesium.Cartographic.fromCartesian(toPoint);

      var point = {
        longitude: Cesium.Math.toDegrees(cartographic.longitude),
        latitude: Cesium.Math.toDegrees(cartographic.latitude),
        height: cartographic.height
      }
      return point;
    }

最后感谢阅读,如有不足指出,请指正,谢谢。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值