js m 数值缩写k_使用 k-d tree 实现点聚合图

d19edb8b73f83c9c85ad37f868535598.png

在上一篇文章中,我们介绍了 Mapbox 对于海量数据展示的最佳实践,即数据瓦片方案,以及其中涉及的对于 LineString 和 Polygon 要素的简化算法。

潘与其:使用数据瓦片展示海量数据​zhuanlan.zhihu.com
68077b7c9b2522dc56c67088d425b5c9.png

最后我们遗留了两个问题:

  1. 对于 Point 要素,我们需要不同于 LineString 和 Polygon 要素的简化算法
  2. 将要素简化、裁剪瓦片放入 WebWorker 中进行。保证主线程中用户流畅的地图交互

在本文中我们将解决第一个问题,按以下顺序介绍:

  1. 基于 k-d tree 的空间索引和查询操作
  2. 结合数据瓦片方案,应用 k-d tree
  3. 实现点聚合图,包括在 WebGL 中绘制圆形的方法

点聚合场景

对于展现 Point 要素的点分布图来说,在低缩放等级下同样不需要渲染全量数据,我们可以采用聚合的方式展示点集合的概览。例如下图(不是给安居客打广告哈),随着缩放等级的提升,将出现更多更小的集合,直至最终每个点的分布被展现出来:

bdcce0c1546161b14136f8ea9fc13b04.png
点聚合图

在以上点聚合的场景中,我们有两个问题需要解决:

  1. 如何聚合?即给定一个点,以此为圆心,如何找到一定半径范围内所有点?
  2. 聚合完毕后,给定一个包围盒(例如当前视口),如何找到其中包含的聚合后的要素?

对于这两个问题(radius & range query),在海量点数据下,如果使用暴力遍历每个点的方法必然是低效的。为了高效搜索,我们需要使用空间索引。

空间索引

强烈推荐阅读 Mapbox 工程师的这篇文章:「A dive into spatial search algorithms」,本文后续引用的 k-d tree 的 JS 实现 kdbush 正是出自他手,此外他还写了 r-tree 的 JS 实现 rbush 以及 rbush-knn。

https://blog.mapbox.com/a-dive-into-spatial-search-algorithms-ebd0c5e39d2a​blog.mapbox.com

知乎上也有一篇介绍 spatial index 空间索引的文章,介绍了 r-tree、k-d tree、八叉树等实现:

李喆:空间索引Spatial Indexing​zhuanlan.zhihu.com
e05cf1aa76851cbfccf2849ab5e92e95.png

在空间数据库中肯定少不了索引,例如 PostGIS 中的索引就是基于 R-tree 实现的:

不睡觉的怪叔叔:PostGIS教程一:PostGIS介绍​zhuanlan.zhihu.com
0a8056e48d4b3ecf5fa6cb4361dd8ddb.png

除了地理场景,在 光线追踪 场景中,k-d tree 也可用于 Ray 与包围盒的求交,参考玉米关于 PBRT 相关章节的笔记:

玉米:PBRT-E4.4-KD树(KD-Tree)​zhuanlan.zhihu.com

限于篇幅本文只介绍 k-d tree 的构建以及查询算法。如果只关心如何在点聚合场景中应用,可以直接跳到最后 DEMO 实现部分。

创建 k-d tree

K-d(k-dimensional)tree 是一棵二叉树,每个叶节点都是一个 k 维的点。而每个非叶节点表示分割平面,分割方向在 X 和 Y 轴间交替。下面我们通过 Wiki 中的例子简单感受 k-d tree 的构建过程。

https://en.wikipedia.org/wiki/K-d_tree​en.wikipedia.org

假设我们在空间中有一组点:(2,3), (5,4), (9,6), (4,7), (8,1), (7,2)。通过某种选择算法(下一节会详细介绍),我们首先选定 (7,2),以 X=7(红色) 为分割线将点集分成左右两部分,接着分别在左右两部分中选定 (5,4) 和 (9,6),切换方向以 Y=4 和 Y=6(蓝色)继续分割成上下两部分。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值