Skip to content

Commit

Permalink
feat(geo): convert quadkey to/from tile index (#688)
Browse files Browse the repository at this point in the history
* feat(geo): convert quadkey to/from tile index

* perf(geo): use charcode for quadkeys as its faster than strings
  • Loading branch information
blacha authored May 28, 2020
1 parent 3acc6d1 commit adac225
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
17 changes: 17 additions & 0 deletions packages/geo/src/__tests__/quad.key.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,21 @@ o.spec('QuadKey', () => {
o(QuadKey.compareKeys('31', '33')).equals(-1);
o(QuadKey.compareKeys('31', '22')).equals(1);
});

o('toTile', () => {
o(QuadKey.toTile('')).deepEquals({ x: 0, y: 0, z: 0 });
o(QuadKey.toTile('31')).deepEquals({ x: 3, y: 2, z: 2 });
o(QuadKey.toTile('31021')).deepEquals({ x: 25, y: 18, z: 5 });
});

o('fromTile', () => {
o(QuadKey.fromTile({ x: 0, y: 0, z: 0 })).equals('');
o(QuadKey.fromTile({ x: 0, y: 0, z: 32 })).equals('00000000000000000000000000000000');
o(QuadKey.fromTile({ x: 3, y: 2, z: 2 })).equals('31');
o(QuadKey.fromTile({ x: 25, y: 18, z: 5 })).equals('31021');

o(QuadKey.fromTile({ x: 2 ** 24 - 1, y: 0, z: 24 })).equals('111111111111111111111111');
o(QuadKey.fromTile({ x: 0, y: 2 ** 24 - 1, z: 24 })).equals('222222222222222222222222');
o(QuadKey.fromTile({ x: 2 ** 24 - 1, y: 2 ** 24 - 1, z: 24 })).equals('333333333333333333333333');
});
});
45 changes: 45 additions & 0 deletions packages/geo/src/quad.key.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { quadkeyToTile, tileToBBOX } from '@mapbox/tilebelt';
import { Bounds } from './bounds';
import { Tile } from './tile.matrix.set';

const CHAR_0 = '0'.charCodeAt(0);
const CHAR_1 = '1'.charCodeAt(0);
const CHAR_2 = '2'.charCodeAt(0);
const CHAR_3 = '3'.charCodeAt(0);

export const QuadKey = {
Keys: ['0', '1', '2', '3'],
Expand Down Expand Up @@ -56,6 +62,45 @@ export const QuadKey = {
return tileToBBOX(quadkeyToTile(quadKey));
},

/**
* Convert a quadkey to a XYZ Tile location
* @param quadKey quadkey to convert
*/
toTile(quadKey: string): Tile {
let x = 0;
let y = 0;
const z = quadKey.length;

for (let i = z; i > 0; i--) {
const mask = 1 << (i - 1);
const q = quadKey.charCodeAt(z - i);
if (q === CHAR_1) x |= mask;
if (q === CHAR_2) y |= mask;
if (q === CHAR_3) {
x |= mask;
y |= mask;
}
}
return { x, y, z };
},

/**
* Convert a tile location to a quadkey
* @param tile tile to covert
*/
fromTile(tile: Tile): string {
const { x, y, z } = tile;
let quadKey = '';
for (let zI = z; zI > 0; zI--) {
let b = CHAR_0;
const mask = 1 << (zI - 1);
if ((x & mask) !== 0) b++;
if ((y & mask) !== 0) b += 2;
quadKey += String.fromCharCode(b);
}
return quadKey;
},

/**
* Convert a quadKey to its bounding box
* @param quadKey
Expand Down

0 comments on commit adac225

Please sign in to comment.