Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,32 @@ export function cellToParent(quadbin: Quadbin): Quadbin {
return parent;
}

/**
* Returns the children of a cell, in row-major order starting from NW and ending at SE.
*/
export function cellToChildren(quadbin: Quadbin, resolution: bigint): Quadbin[] {
if (resolution < 0 || resolution > 26 || resolution < getResolution(quadbin)) {
throw new Error('Invalid resolution');
}

const zoomLevelMask = ~(0x1fn << 52n);
const blockRange = 1n << ((resolution - ((quadbin >> 52n) & 0x1fn)) << 1n);
const sqrtBlockRange = 1n << (resolution - ((quadbin >> 52n) & 0x1fn));
const blockShift = 52n - (resolution << 1n);

const childBase =
((quadbin & zoomLevelMask) | (resolution << 52n)) & ~((blockRange - 1n) << blockShift);

const children: Quadbin[] = [];
for (let blockRow = 0n; blockRow < sqrtBlockRange; blockRow++) {
for (let blockColumn = 0n; blockColumn < sqrtBlockRange; blockColumn++) {
children.push(childBase | ((blockRow * sqrtBlockRange + blockColumn) << blockShift));
}
}

return children;
}

export function geometryToCells(geometry, resolution: bigint): Quadbin[] {
const zoom = Number(resolution);
return tiles(geometry, {
Expand Down
29 changes: 27 additions & 2 deletions test/index.spec.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import test from 'tape';
import {
cellToBoundary,
tileToCell,
cellToChildren,
cellToTile,
cellToParent,
geometryToCells,
getResolution,
cellToBoundary
hexToBigInt
} from 'quadbin';

import {tileToQuadkey} from './quadkey-utils.js';
Expand All @@ -31,7 +33,7 @@ test('Quadbin conversion', async t => {
t.end();
});

test('Quadbin getParent', async t => {
test('Quadbin cellToParent', async t => {
let tile = {x: 134, y: 1238, z: 10};
const quadkey = tileToQuadkey(tile);

Expand All @@ -49,6 +51,29 @@ test('Quadbin getParent', async t => {
t.end();
});

test('Quadbin cellToChildren', async t => {
const parentTile = { z: 8, x: 59, y: 97 };
const parent = tileToCell(parentTile);

t.deepEquals(cellToChildren(parent, 8n), [parent], 'children at resolution + 0');

// Order is row major, starting from NW and ending at SE.
t.deepEquals(
cellToChildren(parent, 9n).map(cellToTile),
[
{ z: 9, x: 118, y: 194 }, // nw
{ z: 9, x: 119, y: 194 }, // ne
{ z: 9, x: 118, y: 195 }, // sw
{ z: 9, x: 119, y: 195 } // se
],
'children at resolution + 1'
);

t.deepEquals(cellToChildren(parent, 10n).length, 16, 'children at resolution + 2');

t.end();
});

// Zoom:26 test not agreeing with Python
import PointGeometry from './data/PointGeometry.json' with {type: 'json'};
import MultiPointGeometry from './data/MultiPointGeometry.json' with {type: 'json'};
Expand Down