开源Gis专辑

借助Postgresql生成热力图

2019-02-18  本文已影响6人  上岸躲雨

背景

热力图,在空间数据可视化场景中是一个非常常见的需求。首先看下一个完整的热力图效果。

image.png

前端实现热力图的原理可以看该博文。本文不是探究热力图前端实现原理的,是来探讨由于热力图一次性加载的点过多,产生卡顿的问题。

最后,为大家提供一个热力图的性能优化方法,由于热力图一次性加载的点过多,所以容易出现卡顿问题,而前端在渲染热力图时,可以进行热力图的点聚合优化。关于点聚合优化的实施方法:将视窗划分成为网格进行操作,由此判断热力图数据点在网格中所处的位置,如果同时几个点处于一个网格,则合并这几个点,以此降低渲染成本。

前面的博文也提出了自己的解决办法。但是若数据居多(10w+),光数据传输就头疼。现有的热力图的前端组件有很多,可以用openlayer、高德地图js、百度地图js、mapbox等。但是大多数的数据结构的都是下面这种形式。

image.png

所以需要在后台将下面策略实现,给前台页面传输合适的数据就行。

最后,为大家提供一个热力图的性能优化方法,由于热力图一次性加载的点过多,所以容易出现卡顿问题,而前端在渲染热力图时,可以进行热力图的点聚合优化。关于点聚合优化的实施方法:将视窗划分成为网格进行操作,由此判断热力图数据点在网格中所处的位置,如果同时几个点处于一个网格,则合并这几个点,以此降低渲染成本。

计算热力图中bucket的方法

width_bucket(operand dp, b1 dp, b2 dp, count int)     
int   
return the bucket number to which operand would be assigned in a histogram having count equal-width buckets spanning the range b1 to b2;   
returns 0 or count+1 for an input outside the range   
width_bucket(5.35, 0.024, 10.06, 5)   
3  
  
width_bucket(operand numeric, b1 numeric, b2 numeric, count int)      
int   
return the bucket number to which operand would be assigned in a histogram having count equal-width buckets spanning the range b1 to b2;   
returns 0 or count+1 for an input outside the range   
width_bucket(5.35, 0.024, 10.06, 5)   
3  

生成数据

SELECT ST_SetSRID(ST_MakeBox2D(ST_Point(119.7342, 29.9602),ST_Point(120.6181 ,30.5581)),4326) geom;
image
--生成热力图点
CREATE TABLE heatmap_points AS  SELECT
    (
        ST_Dump (
            ST_GeneratePoints (kl.geom, 200000)
        )).geom AS geom,md5((random()*random())::text) as id,random()*1000 as val
        FROM
            (
                SELECT
                    ST_SetSRID (
                        ST_MakeBox2D (
                            ST_Point (119.7342, 29.9602),
                            ST_Point (120.6181, 30.5581)
                        ),
                        4326
                    ) geom
            ) kl;

20W的点

点位聚合

with tt as (select   
  width_bucket(st_x(geom), 119.7342, 120.6181, 50) grid_x, 
  width_bucket(st_y(geom), 29.9602, 30.5581, 50) grid_y,  
    geom,
    val
from heatmap_points)  
SELECT avg(val),min(val), max(val), stddev(val),st_centroid(st_collect(geom)) geom from tt GROUP BY tt.grid_x,grid_y
image
image

小结

借助postgresql的width_bucket和postgis,仅用0.4s将20W的数据压缩到2500,这就大大降低了数据传输和渲染的压力。同时也不需要对已有的GIS前端热力图组件进行修改。

参考

德哥的文章

数据可视化:浅谈热力图如何在前端实现

上一篇 下一篇

猜你喜欢

热点阅读