Nec_Eu
新冠肺炎,是人类迈入21世纪二十年代后遭遇的首个全球重大突发事件。掐指算来,从1月疫情爆发开始到现在,时间已经过去了3个月。然而,凶猛的病毒并没有因此逐渐消逝,反而在全球各个角落愈演愈烈。所幸,最先爆发疫情的中国,在我党的正确领导下,本土病例不仅得到了大幅控制,与此同时展开的疫情防控工作也收效显著。为了进一步的精准防控、减少人流聚集,将热力图与三维结合,进行人流可视化监视是有效手段之一。
本篇博客,将基于Supermap iClient3D for WebGL平台,从数据获取到数据展示,提供三维人流热力图的具体参考方案。
最终效果如图(本示例仅为场景模拟,不与实际相符):
1、获取并解析人流大数据
详细的人流大数据请从相关的专业大数据采集平台获取,这里不再赘述;本博客仅以免费公开的腾讯位置大数据(https://heat.qq.com)作为参考,实现人流大数据的获取。
腾讯位置大数据服务,发送get请求即可获取到相应数据。不过需要注意的是,直接发送请求会出现跨域问题。所以需要先部署nginx反向代理。
部署好nginx后,发送的get请求就可以返回有效的json值了。相关代码如下:
$.getJSON('https://heat.qq.com/api/getHeatDataByDate.php?region_id=1287&date=2020-03-26&sub_domain=?,function(jsondata)'){
//获取json的key值和value值并设置为全局变量。
//其中,每一个key值代表时间
//而每一个value值则包含了当前时间下的人流坐标以及密度信息
keys = Object.keys(jsonData);
values = Object.values(jsonData);
$("#timeline").empty();
//获取时间戳名称,将名称加入下拉选择框
for(var i = 0; i < keys.length; i++){
$("#timeline").append("<option value=" + i +">" + keys[i] + "</option>");
}
};
2、初始化热力图
热力图的生成,我们可以借助一个功能强大的热力图开源js库,即heatmap.js(https://www.patrick-wied.at/static/heatmapjs/)。通过这个js库我们可以简单快速的生成新的热力图。相关js文件可以在Supermap iClient3D for WebGL产品包里获取。
在引用了该js库后,我们首先要创建一个热力图画布。
<div class="heatmap" style="overflow: hidden; width: 100px;height: 100px;">
<div class="heatmap-canvas" width="50%" height="25%" >
</div>
</div>
然后,我们创建好一个热力图实体,即可完成热力图的初始化了。
heatmapInstance = h337.create({
container : document.querySelector('.heatmap')
});
3、动态生成热力图
在第一部分里,我们获取到了各个时间节点以及该时间节点下的人流位置信息;然后在第二部分里,我们初始化了一个热力图画布。现在,根据位置信息我们就可以在画布上动态生成热力图了。
heatmap.js动态生成热力图需要两个参数。一个是热力值的总阈值,每个热力值与总阈值的比例决定了显示时不同的颜色;另外一个是形式为{x, y, value}的热力点的集合,其中x, y分别代表画布的像素位置点,而value代表了该点的热力值。
function createHeatMap(timeid) {
var id = parseInt(timeid);
var points = [];
var max = 0;
var value = values[id];
var pointsValue = value.split("|");
for(var j=0; j<pointsValue.length; j++){
var pointValue = pointsValue[j];
if(pointValue !=""){
var pointDetail = pointValue.split(",");
var val;
if(pointDetail.length == 2){
val = 1;
}else{
val = parseInt(pointDetail[2]);
}
var point = {
x : parseInt(pointDetail[0])+50,
y : parseInt(pointDetail[1])+50,
value : val
};
max = Math.max(max, val);
points.push(point);
}
}
var data = {
max : max,
data : points
}
heatmapInstance.setData(data);
addHeatMapToScene();
}
4、三维与热力图结合
生成好了热力图,我们就可以把它加到场景里用于展示与监控了。Supermap iClient3D for WebGL产品支持将图像直接投放到三维模型上,可调用该接口用于热力图与三维场景的结合。
function addHeatMapToScene() {
var mycanvas = $(".heatmap-canvas");
var imgData= mycanvas[1].toDataURL("image/png");
var img = new Image();
img.src = imgData;
img.onload = function() {
var layers = viewer.scene.layers.layerQueue;
for(var layer of layers) {
layer.addOverlayImage({
bounds: new Cesium.Rectangle(116.44595678194692/180*Math.PI, 39.9029928162429/180*Math.PI, 116.4713854187713/180*Math.PI, 39.92118449094035/180*Math.PI),
name: 'heat-map' + Date.now(),
image: img
});
}
}
}
Bonus.历史热力图动态浏览
除了浏览特定时刻的热力图,我们也可以使用定时器实现热力图的历史动画浏览。
$("#start").click(function(){
i=0;
var interval = setInterval(function(){
if(i<keys.length){
$("#timeline").val(i);
createHeatMap(i);
i++;
}else{
clearInterval(interval);
}
},100);
});
动画效果如下: