handle leaf levels other than 7

This commit is contained in:
Brandon Liu
2022-02-17 17:16:44 +08:00
parent 837ba393a3
commit 3a9679b952
2 changed files with 92 additions and 50 deletions

View File

@@ -4,6 +4,7 @@ import {
getUint24, getUint24,
getUint48, getUint48,
queryLeafdir, queryLeafdir,
queryLeafLevel,
queryTile, queryTile,
parseEntry, parseEntry,
Entry, Entry,
@@ -79,6 +80,35 @@ test("get leafdir", (assertion) => {
assertion.ok(queryTile(view, 14, 16383, 16383) === null); assertion.ok(queryTile(view, 14, 16383, 16383) === null);
}); });
test("derive the leaf level", (assertion) => {
let data = createDirectory([
{
z: 6,
x: 3,
y: 3,
offset: 0,
length: 0,
is_dir: true,
},
]);
let view = new DataView(data);
let level = queryLeafLevel(view);
assertion.ok(level === 6);
data = createDirectory([
{
z: 6,
x: 3,
y: 3,
offset: 0,
length: 0,
is_dir: false,
},
]);
view = new DataView(data);
level = queryLeafLevel(view);
assertion.ok(level === null);
});
test("convert spec v1 directory to spec v2 directory", (assertion) => { test("convert spec v1 directory to spec v2 directory", (assertion) => {
let data = createDirectory([ let data = createDirectory([
{ {

View File

@@ -16,6 +16,39 @@ export const getUint48 = (view: DataView, pos: number) => {
return shift(view.getUint32(pos + 2, true), 16) + view.getUint16(pos, true); return shift(view.getUint32(pos + 2, true), 16) + view.getUint16(pos, true);
}; };
interface Zxy {
z: number;
x: number;
y: number;
}
interface Header {
version: number;
json_size: number;
root_entries: number;
}
interface Root {
header: Header;
buffer: ArrayBuffer;
dir: DataView;
// etag: string | null;
}
export interface Entry {
z: number;
x: number;
y: number;
offset: number;
length: number;
is_dir: boolean;
}
interface CachedLeaf {
lastUsed: number;
buffer: Promise<ArrayBuffer>;
}
const compare = ( const compare = (
tz: number, tz: number,
tx: number, tx: number,
@@ -88,6 +121,14 @@ const queryView = (
return null; return null;
}; };
export const queryLeafLevel = (view: DataView): number | null => {
if (view.byteLength < 17) return null;
let numEntries = view.byteLength / 17;
let entry = parseEntry(view, numEntries - 1);
if (entry.is_dir) return entry.z;
return null;
};
const entrySort = (a: Entry, b: Entry): number => { const entrySort = (a: Entry, b: Entry): number => {
if (a.is_dir && !b.is_dir) { if (a.is_dir && !b.is_dir) {
return 1; return 1;
@@ -159,47 +200,17 @@ export const createDirectory = (entries: Entry[]): ArrayBuffer => {
return buffer; return buffer;
}; };
interface Zxy { export const deriveLeaf = (root: Root, tile: Zxy): Zxy | null => {
z: number; const leaf_level = queryLeafLevel(root.dir);
x: number; if (leaf_level) {
y: number; let level_diff = tile.z - leaf_level;
} let leaf_x = Math.trunc(tile.x / (1 << level_diff));
let leaf_y = Math.trunc(tile.y / (1 << level_diff));
// TODO: handle different leaf levels return { z: leaf_level, x: leaf_x, y: leaf_y };
export const deriveLeaf = (tile: Zxy): Zxy => { }
let z7_tile_diff = tile.z - 7; return null;
let z7_x = Math.trunc(tile.x / (1 << z7_tile_diff));
let z7_y = Math.trunc(tile.y / (1 << z7_tile_diff));
return { z: 7, x: z7_x, y: z7_y };
}; };
interface Header {
version: number;
json_size: number;
root_entries: number;
}
interface Root {
header: Header;
buffer: ArrayBuffer;
dir: DataView;
// etag: string | null;
}
export interface Entry {
z: number;
x: number;
y: number;
offset: number;
length: number;
is_dir: boolean;
}
interface CachedLeaf {
lastUsed: number;
buffer: Promise<ArrayBuffer>;
}
export const parseHeader = (dataview: DataView): Header => { export const parseHeader = (dataview: DataView): Header => {
var magic = dataview.getUint16(0, true); var magic = dataview.getUint16(0, true);
if (magic !== 19792) { if (magic !== 19792) {
@@ -329,17 +340,18 @@ export class PMTiles {
let entry = queryTile(root.dir, z, x, y); let entry = queryTile(root.dir, z, x, y);
if (entry) return entry; if (entry) return entry;
let leafcoords = deriveLeaf({ z: z, x: x, y: y }); let leafcoords = deriveLeaf(root, { z: z, x: x, y: y });
let leafdir_entry = queryLeafdir( if (leafcoords) {
root.dir, let leafdir_entry = queryLeafdir(
leafcoords.z, root.dir,
leafcoords.x, leafcoords.z,
leafcoords.y leafcoords.x,
); leafcoords.y
);
if (leafdir_entry) { if (leafdir_entry) {
let leafdir = await this.getLeafdir(root.header.version, leafdir_entry); let leafdir = await this.getLeafdir(root.header.version, leafdir_entry);
return queryTile(new DataView(leafdir), z, x, y); return queryTile(new DataView(leafdir), z, x, y);
}
} }
return null; return null;
} }