Hilbert Curve 算法

最近看google的s2库, 里面用到了Hilbert Curve的算法,  算法早就忘了, 就记得那个图是以前家里厨房垫脚用的脚垫上面的图案, 当时还说了句, “看来这个设计师还是个数学家”.

先来个图:

是不是很像个迷宫. 这个图乍一看是有逻辑的, 但是很难立刻说出来, 因为上面的图没有划分boarder. 其实左上的图是order/level = 1的Hilbert Curve. 然后是2 3 4 5 6, 我怎么知道的?  先看看介绍:

在那遥远的年代, 18xx年吧..那时候有帮人,在研究: 如何将一个一维空间上的线映射到一个二维空间上, 致使线穿过二维空间上的每个点, 然后不交叉. 这个问题看起来很simple, 但是有好多条件哇, 首先是这个space是continue的, 就是说无限大, 然后线穿过的点要无限的小和无限的多, 也就是说, 你不能数出来这些点有多少, 但是你需要证明你这一条线是肯定穿的过去的.举几个反例:

Screen Shot 2016-05-04 at 11.48.14 AM <–这图来自于https://www.youtube.com/watch?v=DuiryHHTrjU 这个视频很好哇

上面的图就不行, 为啥呢?  因为上面的space是由边际的,所以你才知道啥时候拐弯不是么?

Hilbert Curve的构建:

  1. 先画上面的图1
  2. 做4个图1的copy, 然后翻转上面2个.
  3. 交叉连接两个脚
  4. 继续做2~3步…

Hilbert Curve 有很多很好的性质 (那个视频介绍了很多):

  1. 连续性:  作为一个continually mapping, Hilbert Curve能准确的:1) 将一个数字比如(0.24) 映射到二维空间上的一点, 并且维度增加时,比如level: 2->4, 点不移动, 2) 因为数字是连续的, 比如0.24,0.25….., Hilbert Curve能做到数字映射后的curve中的点也是连续的. 这个是其中一个精髓.
  2. 可扩展性: 比如上面的snake curve当空间扩展的时候, 图像上的点要flip到其他位置, 这意味着每个点的位置当空间扩展时都要update, 这个update是指数时间的(空间扩展是指数的), 而上面红色Hilbert Curve可以保证只需要重新连接固定的几个点, 就实现了无限扩展的空间.
  3. 稳定性: 和可扩展性类似, 随着level的增加, 每个点在图上的移动距离会越来越小, 而因为level增加, 图形越来越大, 使得点的移动变得不再重要.所以可以看做不移动.
  4. 相关性: 连续的数字对应的点也是相近的, 但是相近的点不一定对应相近的数字

Google的s2库资料很少, 但是Hilbert Curve的算法却很经典, 不过我仔细看了一下, 发现在做点的查询的时候,Google进行了很多优化..具体为什么, 我还需要时间看下..不过构建Hilbert Curve的方式一样. Google用的是level30的Hilbert Curve, 约等于2^30, 真是很大的图,哈哈哈.

这里有个demo, 不是我写的哈:

http://bit-player.org/extras/hilbert/hilbert-mapping.html