From 3180087ca6a0cf30f3f75bb8907e03fcaa7e54bf Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Mon, 9 Jan 2023 16:07:46 +0800 Subject: [PATCH] add fast parent tile ID calculation [#31] --- pmtiles/bitmap.go | 10 +++------- pmtiles/tile_id.go | 20 +++++++++++++++++++- pmtiles/tile_id_test.go | 24 ++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/pmtiles/bitmap.go b/pmtiles/bitmap.go index 1d0a839..e88bc85 100644 --- a/pmtiles/bitmap.go +++ b/pmtiles/bitmap.go @@ -59,11 +59,8 @@ func generalizeOr(r *roaring64.Bitmap) { for current_z := int(max_z); current_z > 0; current_z-- { iter := to_iterate.Iterator() for iter.HasNext() { - z, x, y := IdToZxy(iter.Next()) - parent_z := z - 1 - parent_x := x >> 1 - parent_y := y >> 1 - temp.Add(ZxyToId(parent_z, parent_x, parent_y)) + parent_id := ParentId(iter.Next()) + temp.Add(parent_id) } to_iterate = temp r.Or(temp) @@ -89,8 +86,7 @@ func generalizeAnd(r *roaring64.Bitmap) { current := uint64(0) // check me... for iter.HasNext() { id := iter.Next() - z, x, y := IdToZxy(id) - parent_id := ZxyToId(z-1, x>>1, y>>1) + parent_id := ParentId(id) if parent_id == current { filled += 1 if filled == 4 { diff --git a/pmtiles/tile_id.go b/pmtiles/tile_id.go index 741265d..c818ccc 100644 --- a/pmtiles/tile_id.go +++ b/pmtiles/tile_id.go @@ -57,10 +57,10 @@ func ZxyToId(z uint8, x uint32, y uint32) uint64 { } func IdToZxy(i uint64) (uint8, uint32, uint32) { - var num_tiles uint64 var acc uint64 var z uint8 for { + var num_tiles uint64 num_tiles = (1 << z) * (1 << z) if acc+num_tiles > i { return t_on_level(z, i-acc) @@ -69,3 +69,21 @@ func IdToZxy(i uint64) (uint8, uint32, uint32) { z++ } } + +// fast parent ID calculation without converting to ZXY. +func ParentId(i uint64) uint64 { + var acc uint64 + var last_acc uint64 + var z uint8 + for { + var num_tiles uint64 + num_tiles = (1 << z) * (1 << z) + if acc+num_tiles > i { + return last_acc + (i-acc)/4 + } + last_acc = acc + acc += num_tiles + z++ + } + +} diff --git a/pmtiles/tile_id_test.go b/pmtiles/tile_id_test.go index 7b4ea01..41a5c52 100644 --- a/pmtiles/tile_id_test.go +++ b/pmtiles/tile_id_test.go @@ -69,3 +69,27 @@ func TestExtremes(t *testing.T) { assert.Equal(t, dim, y) } } + +func TestParent(t *testing.T) { + assert.Equal(t, ZxyToId(0,0,0), ParentId(ZxyToId(1,0,0))) + + assert.Equal(t, ZxyToId(1,0,0), ParentId(ZxyToId(2,0,0))) + assert.Equal(t, ZxyToId(1,0,0), ParentId(ZxyToId(2,0,1))) + assert.Equal(t, ZxyToId(1,0,0), ParentId(ZxyToId(2,1,0))) + assert.Equal(t, ZxyToId(1,0,0), ParentId(ZxyToId(2,1,1))) + + assert.Equal(t, ZxyToId(1,0,1), ParentId(ZxyToId(2,0,2))) + assert.Equal(t, ZxyToId(1,0,1), ParentId(ZxyToId(2,0,3))) + assert.Equal(t, ZxyToId(1,0,1), ParentId(ZxyToId(2,1,2))) + assert.Equal(t, ZxyToId(1,0,1), ParentId(ZxyToId(2,1,3))) + + assert.Equal(t, ZxyToId(1,1,0), ParentId(ZxyToId(2,2,0))) + assert.Equal(t, ZxyToId(1,1,0), ParentId(ZxyToId(2,2,1))) + assert.Equal(t, ZxyToId(1,1,0), ParentId(ZxyToId(2,3,0))) + assert.Equal(t, ZxyToId(1,1,0), ParentId(ZxyToId(2,3,1))) + + assert.Equal(t, ZxyToId(1,1,1), ParentId(ZxyToId(2,2,2))) + assert.Equal(t, ZxyToId(1,1,1), ParentId(ZxyToId(2,2,3))) + assert.Equal(t, ZxyToId(1,1,1), ParentId(ZxyToId(2,3,2))) + assert.Equal(t, ZxyToId(1,1,1), ParentId(ZxyToId(2,3,3))) +}