isard 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -0
- package/README.md +10 -2
- package/dist/basemap.worker.js +2 -2
- package/dist/basemap.worker.js.map +5 -4
- package/dist/decoder.worker.js +3 -3
- package/dist/decoder.worker.js.map +3 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/isard_bg.wasm +0 -0
- package/dist/isard_core_bg.wasm +0 -0
- package/dist/map.d.ts +13 -2
- package/dist/map.js +26 -2
- package/dist/map.js.map +1 -1
- package/dist/pmtiles.d.ts +68 -0
- package/dist/pmtiles.js +297 -0
- package/dist/pmtiles.js.map +1 -0
- package/dist/types.d.ts +25 -1
- package/dist/types.js.map +1 -1
- package/dist/vectortiles.d.ts +30 -1
- package/dist/vectortiles.js +109 -3
- package/dist/vectortiles.js.map +1 -1
- package/dist/wasm/isard.d.ts +12 -3
- package/dist/wasm/isard.js +32 -2
- package/dist/wasm/isard_core.d.ts +12 -3
- package/dist/wasm/isard_core.js +32 -2
- package/package.json +1 -1
package/dist/pmtiles.js
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PMTiles v3 archives: one file of tiles read by HTTP range requests (or from a `Blob`), as Protomaps publishes them.
|
|
3
|
+
* The header and root directory in one request, the leaf directories as needed (kept in a small cache), each tile in
|
|
4
|
+
* its own range; gzip through `DecompressionStream`. The same reader in the page (raster tiles) and in the basemap
|
|
5
|
+
* workers (vector tiles of a style source `pmtiles://…`, as MapLibre's protocol names them).
|
|
6
|
+
*/
|
|
7
|
+
import { Lru } from "./lru.js";
|
|
8
|
+
const HEADER = 127;
|
|
9
|
+
/** The header and the root directory lie within the first 16 KB of the file */
|
|
10
|
+
const FIRST = 16384;
|
|
11
|
+
const TYPES = ['unknown', 'mvt', 'png', 'jpeg', 'webp', 'avif'];
|
|
12
|
+
/** Tiles before level z: (4^z - 1) / 3 */
|
|
13
|
+
const levelStart = (z) => (4 ** z - 1) / 3;
|
|
14
|
+
/** The tile id of z/x/y: the tiles of the lower levels, then the position along the level's Hilbert curve */
|
|
15
|
+
export function zxyToTileId(z, x, y) {
|
|
16
|
+
if (z > 26)
|
|
17
|
+
throw new Error(`isard: PMTiles level ${z} past 26`);
|
|
18
|
+
const n = 2 ** z;
|
|
19
|
+
if (x < 0 || y < 0 || x >= n || y >= n)
|
|
20
|
+
throw new Error(`isard: PMTiles tile ${z}/${x}/${y} out of its level`);
|
|
21
|
+
let [px, py] = [x, y];
|
|
22
|
+
let d = 0;
|
|
23
|
+
for (let s = n / 2; s >= 1; s /= 2) {
|
|
24
|
+
const rx = (px & s) > 0 ? 1 : 0;
|
|
25
|
+
const ry = (py & s) > 0 ? 1 : 0;
|
|
26
|
+
d += s * s * ((3 * rx) ^ ry);
|
|
27
|
+
if (ry === 0) {
|
|
28
|
+
if (rx === 1)
|
|
29
|
+
[px, py] = [s - 1 - px, s - 1 - py];
|
|
30
|
+
[px, py] = [py, px];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return levelStart(z) + d;
|
|
34
|
+
}
|
|
35
|
+
/** The z/x/y of a tile id (the inverse of `zxyToTileId`) */
|
|
36
|
+
export function tileIdToZxy(id) {
|
|
37
|
+
let z = 0;
|
|
38
|
+
while (levelStart(z + 1) <= id)
|
|
39
|
+
z += 1;
|
|
40
|
+
const n = 2 ** z;
|
|
41
|
+
let t = id - levelStart(z);
|
|
42
|
+
let [x, y] = [0, 0];
|
|
43
|
+
for (let s = 1; s < n; s *= 2) {
|
|
44
|
+
// Arithmetic, not bitwise: positions pass 32 bits past level 16
|
|
45
|
+
const rx = Math.floor(t / 2) % 2;
|
|
46
|
+
const ry = (t % 2) ^ rx;
|
|
47
|
+
if (ry === 0) {
|
|
48
|
+
if (rx === 1)
|
|
49
|
+
[x, y] = [s - 1 - x, s - 1 - y];
|
|
50
|
+
[x, y] = [y, x];
|
|
51
|
+
}
|
|
52
|
+
x += s * rx;
|
|
53
|
+
y += s * ry;
|
|
54
|
+
t = Math.floor(t / 4);
|
|
55
|
+
}
|
|
56
|
+
return [z, x, y];
|
|
57
|
+
}
|
|
58
|
+
/** A reader of unsigned varints past 32 bits (tile ids reach 2^52) */
|
|
59
|
+
class Varints {
|
|
60
|
+
bytes;
|
|
61
|
+
pos = 0;
|
|
62
|
+
constructor(bytes) {
|
|
63
|
+
this.bytes = bytes;
|
|
64
|
+
}
|
|
65
|
+
next() {
|
|
66
|
+
let value = 0;
|
|
67
|
+
let scale = 1;
|
|
68
|
+
for (;;) {
|
|
69
|
+
const b = this.bytes[this.pos++];
|
|
70
|
+
if (b === undefined)
|
|
71
|
+
throw new Error('isard: PMTiles directory truncated');
|
|
72
|
+
value += (b & 0x7f) * scale;
|
|
73
|
+
if (b < 0x80)
|
|
74
|
+
return value;
|
|
75
|
+
scale *= 128;
|
|
76
|
+
if (scale > 2 ** 63)
|
|
77
|
+
throw new Error('isard: PMTiles varint too long');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** The entries of a directory (decompressed) */
|
|
82
|
+
export function parseDirectory(bytes) {
|
|
83
|
+
const v = new Varints(bytes);
|
|
84
|
+
const count = v.next();
|
|
85
|
+
if (count > bytes.length)
|
|
86
|
+
throw new Error('isard: PMTiles directory larger than its bytes');
|
|
87
|
+
const entries = [];
|
|
88
|
+
let id = 0;
|
|
89
|
+
for (let i = 0; i < count; i += 1) {
|
|
90
|
+
id += v.next();
|
|
91
|
+
entries.push({ tileId: id, offset: 0, length: 0, runLength: 1 });
|
|
92
|
+
}
|
|
93
|
+
for (const e of entries)
|
|
94
|
+
e.runLength = v.next();
|
|
95
|
+
for (const e of entries)
|
|
96
|
+
e.length = v.next();
|
|
97
|
+
entries.forEach((e, i) => {
|
|
98
|
+
const value = v.next();
|
|
99
|
+
const previous = entries[i - 1];
|
|
100
|
+
// 0 after the first: right after the previous entry's bytes
|
|
101
|
+
e.offset = value === 0 && previous ? previous.offset + previous.length : value - 1;
|
|
102
|
+
});
|
|
103
|
+
return entries;
|
|
104
|
+
}
|
|
105
|
+
/** The entry holding a tile id: its run of tiles, or the leaf directory it falls in; undefined if none */
|
|
106
|
+
export function findEntry(entries, id) {
|
|
107
|
+
let [lo, hi] = [0, entries.length - 1];
|
|
108
|
+
while (lo <= hi) {
|
|
109
|
+
const mid = (lo + hi) >> 1;
|
|
110
|
+
const e = entries[mid];
|
|
111
|
+
if (e.tileId === id)
|
|
112
|
+
return e;
|
|
113
|
+
if (e.tileId < id)
|
|
114
|
+
lo = mid + 1;
|
|
115
|
+
else
|
|
116
|
+
hi = mid - 1;
|
|
117
|
+
}
|
|
118
|
+
const e = entries[hi];
|
|
119
|
+
if (!e)
|
|
120
|
+
return undefined;
|
|
121
|
+
if (e.runLength === 0 || id - e.tileId < e.runLength)
|
|
122
|
+
return e;
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
/** The header of an archive from its first bytes */
|
|
126
|
+
export function parseHeader(bytes) {
|
|
127
|
+
if (bytes.length < HEADER || String.fromCharCode(...bytes.subarray(0, 7)) !== 'PMTiles') {
|
|
128
|
+
throw new Error('isard: not a PMTiles archive');
|
|
129
|
+
}
|
|
130
|
+
if (bytes[7] !== 3)
|
|
131
|
+
throw new Error(`isard: PMTiles version ${bytes[7]} (only 3 is read)`);
|
|
132
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
133
|
+
const u64 = (at) => Number(view.getBigUint64(at, true));
|
|
134
|
+
const deg = (at) => view.getInt32(at, true) / 1e7;
|
|
135
|
+
return {
|
|
136
|
+
rootDirectoryOffset: u64(8),
|
|
137
|
+
rootDirectoryLength: u64(16),
|
|
138
|
+
metadataOffset: u64(24),
|
|
139
|
+
metadataLength: u64(32),
|
|
140
|
+
leafDirectoryOffset: u64(40),
|
|
141
|
+
leafDirectoryLength: u64(48),
|
|
142
|
+
tileDataOffset: u64(56),
|
|
143
|
+
tileDataLength: u64(64),
|
|
144
|
+
internalCompression: view.getUint8(97),
|
|
145
|
+
tileCompression: view.getUint8(98),
|
|
146
|
+
tileType: TYPES[view.getUint8(99)] ?? 'unknown',
|
|
147
|
+
minZoom: view.getUint8(100),
|
|
148
|
+
maxZoom: view.getUint8(101),
|
|
149
|
+
bounds: [deg(102), deg(106), deg(110), deg(114)],
|
|
150
|
+
center: [deg(119), deg(123), view.getUint8(118)],
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/** Bytes as they are stored, decompressed (1: none, 2: gzip; 0, unknown, is read as none) */
|
|
154
|
+
export async function decompress(bytes, compression) {
|
|
155
|
+
if (compression === 0 || compression === 1)
|
|
156
|
+
return bytes;
|
|
157
|
+
if (compression !== 2) {
|
|
158
|
+
throw new Error(`isard: PMTiles compression ${compression === 3 ? 'brotli' : 'zstd'} is not read (gzip only)`);
|
|
159
|
+
}
|
|
160
|
+
const stream = new Blob([bytes]).stream().pipeThrough(new DecompressionStream('gzip'));
|
|
161
|
+
return new Uint8Array(await new Response(stream).arrayBuffer());
|
|
162
|
+
}
|
|
163
|
+
/** Past this, a whole file sent for a range request (a server ignoring ranges) is an error rather than kept */
|
|
164
|
+
const WHOLE_FILE_MAX = 64 * 1024 * 1024;
|
|
165
|
+
/** A PMTiles archive at a URL (range requests) or in a `Blob` (a dropped file) */
|
|
166
|
+
export class PMTiles {
|
|
167
|
+
source;
|
|
168
|
+
head;
|
|
169
|
+
/** The leaf directories read, by offset */
|
|
170
|
+
leaves = new Lru(64);
|
|
171
|
+
/** The whole file, when the server answered a range request with it (small files, `blob:` URLs) */
|
|
172
|
+
whole;
|
|
173
|
+
constructor(source) {
|
|
174
|
+
this.source = source;
|
|
175
|
+
}
|
|
176
|
+
/** `length` bytes from `offset` */
|
|
177
|
+
async range(offset, length, signal) {
|
|
178
|
+
if (typeof this.source !== 'string') {
|
|
179
|
+
return new Uint8Array(await this.source.slice(offset, offset + length).arrayBuffer());
|
|
180
|
+
}
|
|
181
|
+
if (this.whole)
|
|
182
|
+
return (await this.whole).subarray(offset, offset + length);
|
|
183
|
+
const response = await fetch(this.source, {
|
|
184
|
+
headers: { Range: `bytes=${offset}-${offset + Math.max(length, 1) - 1}` },
|
|
185
|
+
...(signal ? { signal } : {}),
|
|
186
|
+
});
|
|
187
|
+
if (!response.ok)
|
|
188
|
+
throw new Error(`${this.source}: HTTP ${response.status}`);
|
|
189
|
+
if (response.status === 206)
|
|
190
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
191
|
+
// The whole file: kept, when small enough, for the next ranges
|
|
192
|
+
const size = Number(response.headers.get('Content-Length'));
|
|
193
|
+
if (size > WHOLE_FILE_MAX) {
|
|
194
|
+
await response.body?.cancel();
|
|
195
|
+
throw new Error(`${this.source}: the server ignores range requests (HTTP 206 expected)`);
|
|
196
|
+
}
|
|
197
|
+
const whole = response.arrayBuffer().then((b) => new Uint8Array(b));
|
|
198
|
+
this.whole = whole;
|
|
199
|
+
whole.catch(() => {
|
|
200
|
+
this.whole = undefined;
|
|
201
|
+
});
|
|
202
|
+
return (await whole).subarray(offset, offset + length);
|
|
203
|
+
}
|
|
204
|
+
load() {
|
|
205
|
+
this.head ??= (async () => {
|
|
206
|
+
const first = await this.range(0, FIRST);
|
|
207
|
+
const header = parseHeader(first);
|
|
208
|
+
const { rootDirectoryOffset: o, rootDirectoryLength: n } = header;
|
|
209
|
+
const raw = o + n <= first.length ? first.subarray(o, o + n) : await this.range(o, n);
|
|
210
|
+
const root = parseDirectory(await decompress(raw, header.internalCompression));
|
|
211
|
+
return { header, root };
|
|
212
|
+
})();
|
|
213
|
+
// A failure is not kept: asked again next time
|
|
214
|
+
this.head.catch(() => {
|
|
215
|
+
this.head = undefined;
|
|
216
|
+
});
|
|
217
|
+
return this.head;
|
|
218
|
+
}
|
|
219
|
+
/** The archive's header */
|
|
220
|
+
async header() {
|
|
221
|
+
return (await this.load()).header;
|
|
222
|
+
}
|
|
223
|
+
/** The archive's JSON metadata (`vector_layers`, `attribution`, `name`…); `{}` if it has none */
|
|
224
|
+
async metadata() {
|
|
225
|
+
const { header } = await this.load();
|
|
226
|
+
if (header.metadataLength === 0)
|
|
227
|
+
return {};
|
|
228
|
+
const raw = await this.range(header.metadataOffset, header.metadataLength);
|
|
229
|
+
const text = new TextDecoder().decode(await decompress(raw, header.internalCompression));
|
|
230
|
+
const value = JSON.parse(text);
|
|
231
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
232
|
+
}
|
|
233
|
+
leaf(header, entry) {
|
|
234
|
+
const offset = header.leafDirectoryOffset + entry.offset;
|
|
235
|
+
let leaf = this.leaves.get(offset);
|
|
236
|
+
if (!leaf) {
|
|
237
|
+
leaf = this.range(offset, entry.length).then(async (raw) => parseDirectory(await decompress(raw, header.internalCompression)));
|
|
238
|
+
leaf.catch(() => this.leaves.delete(offset));
|
|
239
|
+
this.leaves.set(offset, leaf);
|
|
240
|
+
}
|
|
241
|
+
return leaf;
|
|
242
|
+
}
|
|
243
|
+
/** The bytes of tile z/x/y, decompressed (a vector tile ungzipped); undefined where the archive has none */
|
|
244
|
+
async tile(z, x, y, signal) {
|
|
245
|
+
const { header, root } = await this.load();
|
|
246
|
+
if (z < header.minZoom || z > header.maxZoom)
|
|
247
|
+
return undefined;
|
|
248
|
+
const id = zxyToTileId(z, x, y);
|
|
249
|
+
let entries = root;
|
|
250
|
+
// The root, then at most three levels of leaves
|
|
251
|
+
for (let depth = 0; depth < 4; depth += 1) {
|
|
252
|
+
const entry = findEntry(entries, id);
|
|
253
|
+
if (!entry)
|
|
254
|
+
return undefined;
|
|
255
|
+
if (entry.runLength > 0) {
|
|
256
|
+
const raw = await this.range(header.tileDataOffset + entry.offset, entry.length, signal);
|
|
257
|
+
return decompress(raw, header.tileCompression);
|
|
258
|
+
}
|
|
259
|
+
entries = await this.leaf(header, entry);
|
|
260
|
+
}
|
|
261
|
+
throw new Error('isard: PMTiles directories nested too deep');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
/** The archives opened, by URL: one reader (and its directory cache) per archive in a page or worker */
|
|
265
|
+
const archives = new Lru(16);
|
|
266
|
+
/** The reader of an archive URL (without `pmtiles://`), shared */
|
|
267
|
+
export function pmtiles(url) {
|
|
268
|
+
let archive = archives.get(url);
|
|
269
|
+
if (!archive) {
|
|
270
|
+
archive = new PMTiles(url);
|
|
271
|
+
archives.set(url, archive);
|
|
272
|
+
}
|
|
273
|
+
return archive;
|
|
274
|
+
}
|
|
275
|
+
/** The archive URL of a `pmtiles://` URL, absolute (relative to the page), or undefined for another URL */
|
|
276
|
+
export function pmtilesUrl(url, base) {
|
|
277
|
+
if (!url.startsWith('pmtiles://'))
|
|
278
|
+
return undefined;
|
|
279
|
+
const inner = url.slice('pmtiles://'.length);
|
|
280
|
+
const from = base ?? globalThis.location?.href;
|
|
281
|
+
try {
|
|
282
|
+
return from ? new URL(inner, from).href : inner;
|
|
283
|
+
}
|
|
284
|
+
catch {
|
|
285
|
+
return inner;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/** A tile URL `pmtiles://<archive>/{z}/{x}/{y}` (with its numbers in) read from its archive: its bytes, undefined
|
|
289
|
+
* where there is none; undefined too (`false`) for a URL that is not one */
|
|
290
|
+
export function pmtilesTile(url, signal) {
|
|
291
|
+
const match = /^pmtiles:\/\/(.+)\/(\d+)\/(\d+)\/(\d+)$/.exec(url);
|
|
292
|
+
if (!match)
|
|
293
|
+
return false;
|
|
294
|
+
const [, archive = '', z, x, y] = match;
|
|
295
|
+
return pmtiles(archive).tile(Number(z), Number(x), Number(y), signal);
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=pmtiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pmtiles.js","sourceRoot":"","sources":["../src/pmtiles.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PMTiles v3 archives: one file of tiles read by HTTP range requests (or from a `Blob`), as Protomaps publishes them.\n * The header and root directory in one request, the leaf directories as needed (kept in a small cache), each tile in\n * its own range; gzip through `DecompressionStream`. The same reader in the page (raster tiles) and in the basemap\n * workers (vector tiles of a style source `pmtiles://…`, as MapLibre's protocol names them).\n */\nimport { Lru } from './lru.ts';\n\n/** What a PMTiles archive's tiles are */\nexport type PmtilesTileType = 'unknown' | 'mvt' | 'png' | 'jpeg' | 'webp' | 'avif';\n\n/** The header of a PMTiles archive (v3) */\nexport interface PmtilesHeader {\n rootDirectoryOffset: number;\n rootDirectoryLength: number;\n metadataOffset: number;\n metadataLength: number;\n leafDirectoryOffset: number;\n leafDirectoryLength: number;\n tileDataOffset: number;\n tileDataLength: number;\n /** 1 none, 2 gzip, 3 brotli, 4 zstd (only none and gzip are read) */\n internalCompression: number;\n tileCompression: number;\n tileType: PmtilesTileType;\n minZoom: number;\n maxZoom: number;\n /** `[west, south, east, north]`, degrees */\n bounds: [number, number, number, number];\n center: [lon: number, lat: number, zoom: number];\n}\n\n/** An entry of a directory: a run of tiles (`runLength` > 0) or a leaf directory (0) */\nexport interface PmtilesEntry {\n tileId: number;\n offset: number;\n length: number;\n runLength: number;\n}\n\nconst HEADER = 127;\n/** The header and the root directory lie within the first 16 KB of the file */\nconst FIRST = 16384;\nconst TYPES: PmtilesTileType[] = ['unknown', 'mvt', 'png', 'jpeg', 'webp', 'avif'];\n\n/** Tiles before level z: (4^z - 1) / 3 */\nconst levelStart = (z: number) => (4 ** z - 1) / 3;\n\n/** The tile id of z/x/y: the tiles of the lower levels, then the position along the level's Hilbert curve */\nexport function zxyToTileId(z: number, x: number, y: number): number {\n if (z > 26) throw new Error(`isard: PMTiles level ${z} past 26`);\n const n = 2 ** z;\n if (x < 0 || y < 0 || x >= n || y >= n) throw new Error(`isard: PMTiles tile ${z}/${x}/${y} out of its level`);\n let [px, py] = [x, y];\n let d = 0;\n for (let s = n / 2; s >= 1; s /= 2) {\n const rx = (px & s) > 0 ? 1 : 0;\n const ry = (py & s) > 0 ? 1 : 0;\n d += s * s * ((3 * rx) ^ ry);\n if (ry === 0) {\n if (rx === 1) [px, py] = [s - 1 - px, s - 1 - py];\n [px, py] = [py, px];\n }\n }\n return levelStart(z) + d;\n}\n\n/** The z/x/y of a tile id (the inverse of `zxyToTileId`) */\nexport function tileIdToZxy(id: number): [z: number, x: number, y: number] {\n let z = 0;\n while (levelStart(z + 1) <= id) z += 1;\n const n = 2 ** z;\n let t = id - levelStart(z);\n let [x, y] = [0, 0];\n for (let s = 1; s < n; s *= 2) {\n // Arithmetic, not bitwise: positions pass 32 bits past level 16\n const rx = Math.floor(t / 2) % 2;\n const ry = (t % 2) ^ rx;\n if (ry === 0) {\n if (rx === 1) [x, y] = [s - 1 - x, s - 1 - y];\n [x, y] = [y, x];\n }\n x += s * rx;\n y += s * ry;\n t = Math.floor(t / 4);\n }\n return [z, x, y];\n}\n\n/** A reader of unsigned varints past 32 bits (tile ids reach 2^52) */\nclass Varints {\n pos = 0;\n constructor(private readonly bytes: Uint8Array) {}\n next(): number {\n let value = 0;\n let scale = 1;\n for (;;) {\n const b = this.bytes[this.pos++];\n if (b === undefined) throw new Error('isard: PMTiles directory truncated');\n value += (b & 0x7f) * scale;\n if (b < 0x80) return value;\n scale *= 128;\n if (scale > 2 ** 63) throw new Error('isard: PMTiles varint too long');\n }\n }\n}\n\n/** The entries of a directory (decompressed) */\nexport function parseDirectory(bytes: Uint8Array): PmtilesEntry[] {\n const v = new Varints(bytes);\n const count = v.next();\n if (count > bytes.length) throw new Error('isard: PMTiles directory larger than its bytes');\n const entries: PmtilesEntry[] = [];\n let id = 0;\n for (let i = 0; i < count; i += 1) {\n id += v.next();\n entries.push({ tileId: id, offset: 0, length: 0, runLength: 1 });\n }\n for (const e of entries) e.runLength = v.next();\n for (const e of entries) e.length = v.next();\n entries.forEach((e, i) => {\n const value = v.next();\n const previous = entries[i - 1];\n // 0 after the first: right after the previous entry's bytes\n e.offset = value === 0 && previous ? previous.offset + previous.length : value - 1;\n });\n return entries;\n}\n\n/** The entry holding a tile id: its run of tiles, or the leaf directory it falls in; undefined if none */\nexport function findEntry(entries: readonly PmtilesEntry[], id: number): PmtilesEntry | undefined {\n let [lo, hi] = [0, entries.length - 1];\n while (lo <= hi) {\n const mid = (lo + hi) >> 1;\n const e = entries[mid] as PmtilesEntry;\n if (e.tileId === id) return e;\n if (e.tileId < id) lo = mid + 1;\n else hi = mid - 1;\n }\n const e = entries[hi];\n if (!e) return undefined;\n if (e.runLength === 0 || id - e.tileId < e.runLength) return e;\n return undefined;\n}\n\n/** The header of an archive from its first bytes */\nexport function parseHeader(bytes: Uint8Array): PmtilesHeader {\n if (bytes.length < HEADER || String.fromCharCode(...bytes.subarray(0, 7)) !== 'PMTiles') {\n throw new Error('isard: not a PMTiles archive');\n }\n if (bytes[7] !== 3) throw new Error(`isard: PMTiles version ${bytes[7]} (only 3 is read)`);\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n const u64 = (at: number) => Number(view.getBigUint64(at, true));\n const deg = (at: number) => view.getInt32(at, true) / 1e7;\n return {\n rootDirectoryOffset: u64(8),\n rootDirectoryLength: u64(16),\n metadataOffset: u64(24),\n metadataLength: u64(32),\n leafDirectoryOffset: u64(40),\n leafDirectoryLength: u64(48),\n tileDataOffset: u64(56),\n tileDataLength: u64(64),\n internalCompression: view.getUint8(97),\n tileCompression: view.getUint8(98),\n tileType: TYPES[view.getUint8(99)] ?? 'unknown',\n minZoom: view.getUint8(100),\n maxZoom: view.getUint8(101),\n bounds: [deg(102), deg(106), deg(110), deg(114)],\n center: [deg(119), deg(123), view.getUint8(118)],\n };\n}\n\n/** Bytes as they are stored, decompressed (1: none, 2: gzip; 0, unknown, is read as none) */\nexport async function decompress(bytes: Uint8Array, compression: number): Promise<Uint8Array> {\n if (compression === 0 || compression === 1) return bytes;\n if (compression !== 2) {\n throw new Error(`isard: PMTiles compression ${compression === 3 ? 'brotli' : 'zstd'} is not read (gzip only)`);\n }\n const stream = new Blob([bytes as Uint8Array<ArrayBuffer>]).stream().pipeThrough(new DecompressionStream('gzip'));\n return new Uint8Array(await new Response(stream).arrayBuffer());\n}\n\n/** Past this, a whole file sent for a range request (a server ignoring ranges) is an error rather than kept */\nconst WHOLE_FILE_MAX = 64 * 1024 * 1024;\n\n/** A PMTiles archive at a URL (range requests) or in a `Blob` (a dropped file) */\nexport class PMTiles {\n private head: Promise<{ header: PmtilesHeader; root: PmtilesEntry[] }> | undefined;\n /** The leaf directories read, by offset */\n private readonly leaves = new Lru<number, Promise<PmtilesEntry[]>>(64);\n /** The whole file, when the server answered a range request with it (small files, `blob:` URLs) */\n private whole: Promise<Uint8Array> | undefined;\n\n constructor(readonly source: string | Blob) {}\n\n /** `length` bytes from `offset` */\n private async range(offset: number, length: number, signal?: AbortSignal): Promise<Uint8Array> {\n if (typeof this.source !== 'string') {\n return new Uint8Array(await this.source.slice(offset, offset + length).arrayBuffer());\n }\n if (this.whole) return (await this.whole).subarray(offset, offset + length);\n const response = await fetch(this.source, {\n headers: { Range: `bytes=${offset}-${offset + Math.max(length, 1) - 1}` },\n ...(signal ? { signal } : {}),\n });\n if (!response.ok) throw new Error(`${this.source}: HTTP ${response.status}`);\n if (response.status === 206) return new Uint8Array(await response.arrayBuffer());\n // The whole file: kept, when small enough, for the next ranges\n const size = Number(response.headers.get('Content-Length'));\n if (size > WHOLE_FILE_MAX) {\n await response.body?.cancel();\n throw new Error(`${this.source}: the server ignores range requests (HTTP 206 expected)`);\n }\n const whole = response.arrayBuffer().then((b) => new Uint8Array(b));\n this.whole = whole;\n whole.catch(() => {\n this.whole = undefined;\n });\n return (await whole).subarray(offset, offset + length);\n }\n\n private load() {\n this.head ??= (async () => {\n const first = await this.range(0, FIRST);\n const header = parseHeader(first);\n const { rootDirectoryOffset: o, rootDirectoryLength: n } = header;\n const raw = o + n <= first.length ? first.subarray(o, o + n) : await this.range(o, n);\n const root = parseDirectory(await decompress(raw, header.internalCompression));\n return { header, root };\n })();\n // A failure is not kept: asked again next time\n this.head.catch(() => {\n this.head = undefined;\n });\n return this.head;\n }\n\n /** The archive's header */\n async header(): Promise<PmtilesHeader> {\n return (await this.load()).header;\n }\n\n /** The archive's JSON metadata (`vector_layers`, `attribution`, `name`…); `{}` if it has none */\n async metadata(): Promise<Record<string, unknown>> {\n const { header } = await this.load();\n if (header.metadataLength === 0) return {};\n const raw = await this.range(header.metadataOffset, header.metadataLength);\n const text = new TextDecoder().decode(await decompress(raw, header.internalCompression));\n const value: unknown = JSON.parse(text);\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : {};\n }\n\n private leaf(header: PmtilesHeader, entry: PmtilesEntry): Promise<PmtilesEntry[]> {\n const offset = header.leafDirectoryOffset + entry.offset;\n let leaf = this.leaves.get(offset);\n if (!leaf) {\n leaf = this.range(offset, entry.length).then(async (raw) =>\n parseDirectory(await decompress(raw, header.internalCompression)),\n );\n leaf.catch(() => this.leaves.delete(offset));\n this.leaves.set(offset, leaf);\n }\n return leaf;\n }\n\n /** The bytes of tile z/x/y, decompressed (a vector tile ungzipped); undefined where the archive has none */\n async tile(z: number, x: number, y: number, signal?: AbortSignal): Promise<Uint8Array | undefined> {\n const { header, root } = await this.load();\n if (z < header.minZoom || z > header.maxZoom) return undefined;\n const id = zxyToTileId(z, x, y);\n let entries = root;\n // The root, then at most three levels of leaves\n for (let depth = 0; depth < 4; depth += 1) {\n const entry = findEntry(entries, id);\n if (!entry) return undefined;\n if (entry.runLength > 0) {\n const raw = await this.range(header.tileDataOffset + entry.offset, entry.length, signal);\n return decompress(raw, header.tileCompression);\n }\n entries = await this.leaf(header, entry);\n }\n throw new Error('isard: PMTiles directories nested too deep');\n }\n}\n\n/** The archives opened, by URL: one reader (and its directory cache) per archive in a page or worker */\nconst archives = new Lru<string, PMTiles>(16);\n\n/** The reader of an archive URL (without `pmtiles://`), shared */\nexport function pmtiles(url: string): PMTiles {\n let archive = archives.get(url);\n if (!archive) {\n archive = new PMTiles(url);\n archives.set(url, archive);\n }\n return archive;\n}\n\n/** The archive URL of a `pmtiles://` URL, absolute (relative to the page), or undefined for another URL */\nexport function pmtilesUrl(url: string, base?: string): string | undefined {\n if (!url.startsWith('pmtiles://')) return undefined;\n const inner = url.slice('pmtiles://'.length);\n const from = base ?? (globalThis as { location?: { href: string } }).location?.href;\n try {\n return from ? new URL(inner, from).href : inner;\n } catch {\n return inner;\n }\n}\n\n/** A tile URL `pmtiles://<archive>/{z}/{x}/{y}` (with its numbers in) read from its archive: its bytes, undefined\n * where there is none; undefined too (`false`) for a URL that is not one */\nexport function pmtilesTile(url: string, signal?: AbortSignal): Promise<Uint8Array | undefined> | false {\n const match = /^pmtiles:\\/\\/(.+)\\/(\\d+)\\/(\\d+)\\/(\\d+)$/.exec(url);\n if (!match) return false;\n const [, archive = '', z, x, y] = match;\n return pmtiles(archive).tile(Number(z), Number(x), Number(y), signal);\n}\n"]}
|
package/dist/types.d.ts
CHANGED
|
@@ -37,7 +37,8 @@ export type TerrainEncoding = 'float32' | 'terrarium' | 'mapbox';
|
|
|
37
37
|
* fade in; fewer downloads, for slow networks or GPUs.
|
|
38
38
|
*/
|
|
39
39
|
export type LoadingMode = 'immediate' | 'smooth';
|
|
40
|
-
/** 'globe': a sphere at low zoom, blending into Web Mercator between zooms 5 and 7
|
|
40
|
+
/** 'globe': a sphere at low zoom, blending into Web Mercator between zooms 5 and 7, up to three levels later under a
|
|
41
|
+
* tilted camera (it sees much farther than its center: the horizon stays curved) */
|
|
41
42
|
export type Projection = 'globe' | 'mercator';
|
|
42
43
|
/** A body to draw the map on, other than the named ones (`CelestialBody`) */
|
|
43
44
|
export interface BodyOptions {
|
|
@@ -172,6 +173,29 @@ export interface AtmosphereOptions {
|
|
|
172
173
|
/** Share of the distance to the far plane over which the ground fades into the fog, 0-1 (default 0.4) */
|
|
173
174
|
fogGroundBlend?: number;
|
|
174
175
|
}
|
|
176
|
+
/** What can be seen from a point (`GeoMap.setViewshed`) */
|
|
177
|
+
export interface ViewshedOptions {
|
|
178
|
+
/** The observer */
|
|
179
|
+
position: LonLat;
|
|
180
|
+
/** Metres above the ground (default 1.7, eye level) */
|
|
181
|
+
height?: number;
|
|
182
|
+
/** Metres around the observer that are tinted (default 1000) */
|
|
183
|
+
range?: number;
|
|
184
|
+
/** A CSS color for what is seen (default `#2f9e44`) */
|
|
185
|
+
visibleColor?: string;
|
|
186
|
+
/** A CSS color for what is hidden (default `#e03131`) */
|
|
187
|
+
hiddenColor?: string;
|
|
188
|
+
/** 0-1 (default 0.55) */
|
|
189
|
+
opacity?: number;
|
|
190
|
+
/** To look one way only (a camera, a lookout), degrees clockwise from north; all around without it */
|
|
191
|
+
direction?: number;
|
|
192
|
+
/** Degrees above the horizon the cone looks, negative below (default 0) */
|
|
193
|
+
tilt?: number;
|
|
194
|
+
/** Angle of view across, degrees (default 60) */
|
|
195
|
+
fov?: number;
|
|
196
|
+
/** Angle of view up and down, degrees (default 40) */
|
|
197
|
+
verticalFov?: number;
|
|
198
|
+
}
|
|
175
199
|
/** Animation of a camera move */
|
|
176
200
|
export interface AnimationOptions {
|
|
177
201
|
/** Milliseconds */
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["/** Public types of the `isard` package */\nimport type { AttributionOptions } from './controls.ts';\nimport type { DecoderUrls } from './decoders.ts';\nimport type { Feature, Ramp, Size } from './features.ts';\nimport type { TileGrid } from './grid.ts';\nimport type { Layer } from './layers.ts';\nimport type { Camera, Engine } from './wasm/isard.js';\n\nexport type LonLat = [lon: number, lat: number];\nexport type Point = [x: number, y: number];\n\n/**\n * The named basemaps. OpenFreeMap's vector styles, OpenStreetMap data worldwide, their labels above the other layers:\n * `osm-positron` (light grey, quiet: data over it reads first), `osm-liberty` and `osm-bright` (in colour). The\n * Géoplateforme's (IGN, France): rasters (`ign-plan`, `ign-plan-grey`, `ign-ortho`, the aerial photographs) or vector\n * tiles with their labels (`ign-plan-vector`, `ign-plan-grey-vector`, the PLAN.IGN styles).\n */\nexport type BasemapName =\n | 'osm-positron'\n | 'osm-liberty'\n | 'osm-bright'\n | 'ign-plan'\n | 'ign-plan-grey'\n | 'ign-ortho'\n | 'ign-plan-vector'\n | 'ign-plan-grey-vector'\n | 'none';\n\n/**\n * @deprecated The former names of the Géoplateforme basemaps, still accepted (with a warning): the same names with the\n * `ign-` prefix (`'plan-grey'` is `'ign-plan-grey'`)\n */\nexport type LegacyBasemap = 'plan' | 'plan-grey' | 'plan-vector' | 'plan-grey-vector' | 'ortho';\n\n/** A basemap by name (see `BasemapName`; the former names of `LegacyBasemap` are deprecated) */\nexport type Basemap = BasemapName | LegacyBasemap;\n\n/**\n * The Earth's named terrain models. `'terrain-tiles'`: worldwide, the Terrain Tiles of AWS's open data registry\n * (SRTM, EU-DEM, GMTED… merged by Mapzen, 30 m in most places), the sea floor flattened at sea level. `'ign'`: France,\n * the IGN's RGE ALTI from the Géoplateforme (1 to 5 m), raised by the RAF20 geoid to heights above the ellipsoid.\n */\nexport type TerrainModel = 'terrain-tiles' | 'ign';\n\n/** How tiles encode their altitudes: `'float32'`, raw little-endian floats (`image/x-bil;bits=32`, an ArcGIS raw\n * grid); `'terrarium'`, the colors of a PNG, `R × 256 + G + B / 256 - 32768`; `'mapbox'`, those of Terrain-RGB,\n * `(R × 65536 + G × 256 + B) / 10 - 10000` */\nexport type TerrainEncoding = 'float32' | 'terrarium' | 'mapbox';\n\n/**\n * How tiles load and show. 'immediate' (default): everything visible loads, tiles show as soon as they arrive.\n * 'smooth': during flights the levels flown through are skipped, off-center tiles wait while the camera moves, tiles\n * fade in; fewer downloads, for slow networks or GPUs.\n */\nexport type LoadingMode = 'immediate' | 'smooth';\n\n/** 'globe': a sphere at low zoom, blending into Web Mercator between zooms 5 and 7 */\nexport type Projection = 'globe' | 'mercator';\n\n/** A body to draw the map on, other than the named ones (`CelestialBody`) */\nexport interface BodyOptions {\n /** Equatorial radius, metres */\n radius: number;\n /** Flattening of its ellipsoid, 0 for a sphere (default 0) */\n flattening?: number;\n /** An atmosphere: its halo around the globe, true for the Earth's light blue, or a CSS color (its alpha the\n * halo's strength) (default false) */\n atmosphere?: boolean | string;\n /** Color of the globe where no tile covers it (past the Web Mercator latitudes, 85°), a CSS color (default\n * `#808080`) */\n color?: string;\n /** Lowest and highest altitudes of its ground, metres around the ellipsoid: what its relief may raise into view\n * (default ±1 % of the radius) */\n relief?: [lowest: number, highest: number];\n}\n\n/**\n * The body the map is drawn on: 'earth' (WGS 84, the default), 'moon' (a sphere of 1 737 400 m, no atmosphere),\n * 'mars' (a sphere of 3 396 190 m, its equatorial radius, a thin dusty halo; planetocentric latitudes) or another\n * one. Zoom levels keep their meaning on screen (the Web Mercator tile pyramid), their metres follow the body:\n * altitudes, relief, buildings, 3D Tiles. Off the Earth, the map has none of the Earth's defaults: no basemap, no\n * credits, and space for its background; the Moon and Mars have NASA's relief for `terrain: true`.\n */\nexport type CelestialBody = 'earth' | 'moon' | 'mars' | BodyOptions;\n\nexport interface GeoMapOptions extends Partial<Camera> {\n /** The body the map is drawn on (default 'earth'); set at creation */\n body?: CelestialBody;\n /** Default 'globe' */\n projection?: Projection;\n /** Default 'immediate' */\n loading?: LoadingMode;\n /** The basemap (default 'osm-positron'; 'none' off the Earth) */\n basemap?: Basemap;\n /** Opacity of the IGN hillshade over the basemap (France, Géoplateforme), 0 for none (default 0) */\n hillshade?: number;\n /** Color behind the map (sky of tilted flat views), a CSS color (default `#f2f2f0`; black off the Earth) */\n background?: string;\n /** Space behind the globe: stars and atmosphere halo, fading out as the globe turns flat (default true) */\n sky?: boolean;\n /** Relief under the basemap: true for the body's terrain model (on the Earth the worldwide Terrain Tiles; NASA's on\n * the Moon and Mars: LOLA, MOLA), one of the Earth's models by name (`'ign'`: France, RGE ALTI), or its options\n * (default false; on another body, its `url` is required). Network layers are draped on it */\n terrain?: boolean | TerrainModel | TerrainOptions;\n minZoom?: number;\n maxZoom?: number;\n /** Highest pitch, degrees, up to 85 (default 70) */\n maxPitch?: number;\n /** Sky over the plane, seen when the camera is tilted towards the horizon, and the fog the ground fades into\n * (MapLibre's `setSky`); default none: the background color */\n atmosphere?: AtmosphereOptions;\n /** Mouse, touch and keyboard controls (default true) */\n interactive?: boolean;\n /** Keyboard controls once the map has the focus (it is reached with Tab): arrows pan, Shift + arrows rotate and\n * tilt, + and - zoom (Shift: two levels), 0 faces north and levels the view (default true; none when not\n * `interactive`) */\n keyboard?: boolean;\n /** Accessible name of the map, read by screen readers (default 'Map') */\n ariaLabel?: string;\n /** Where to load the engine with 3D Tiles from (`isard_bg.wasm`), when a bundler does not resolve the default URL.\n * Given without `coreWasmUrl`, maps load this engine from the start */\n wasmUrl?: string | URL;\n /** Where to load the engine without 3D Tiles from (`isard_core_bg.wasm`, a third smaller), when a bundler does not\n * resolve the default URL. Maps load it first, and the engine with 3D Tiles (`wasmUrl`) for their first 3D Tiles\n * layer only */\n coreWasmUrl?: string | URL;\n /** Where the decoding workers load the point cloud module from (`isard_points_bg.wasm`, the LAZ decoder of COPC),\n * when a bundler does not resolve the default URL. Loaded with the first point cloud only */\n pointsWasmUrl?: string | URL;\n /** Load the engine with 3D Tiles from the start (default false: it is loaded when the first 3D Tiles layer or glTF\n * model is added, the map then moving its camera and layers onto it, a stall of about a frame or two). For a map that shows 3D Tiles\n * at once: one engine downloaded instead of two. `'preload'`: the map starts on the engine without 3D Tiles and\n * downloads and compiles the other once idle, without running it: its first 3D Tiles layer does not wait for the\n * download (for a map that will show 3D Tiles later, on demand) */\n tiles3d?: boolean | 'preload';\n /** Where to load the vector basemap worker from, when a bundler does not resolve the default URL */\n basemapWorkerUrl?: string | URL;\n /** Texture size of the vector basemap's tiles, pixels (default 512: lines and edges sharp at every zoom on a screen\n * of pixel ratio 1). 256: a quarter of the drawing in the workers, of the uploads and of the GPU memory, for lines\n * and edges a little softer between two zoom levels (the tiles are shown 181 to 362 CSS pixels wide) */\n basemapTileSize?: number;\n /** Glyphs of the symbol layers: a URL with `{fontstack}` and `{range}` (MapLibre's glyph format; default\n * OpenFreeMap's fonts, Noto Sans). A vector basemap's labels take the glyphs of its style */\n glyphs?: string;\n /** Workers decoding 3D Tiles off the main thread: a count, or false to decode on the main thread (default: cores - 1,\n * 1 to 4). False (or 0) also decodes the PNG relief and reprojects the equirectangular rasters on the main thread,\n * else done by the vector basemap's workers */\n workers?: number | false;\n /** Where to load the decoding worker from, when a bundler does not resolve the default URL */\n workerUrl?: string | URL;\n /** Folders of the Draco and Basis Universal decoders, loaded by the workers on first use (default: the official\n * builds on gstatic.com and jsDelivr; self-host them for offline or locked-down networks). They run through\n * `new Function`: a Content Security Policy needs `'unsafe-eval'` (see `DecoderUrls`) */\n decoders?: Partial<DecoderUrls>;\n /** Credits at the bottom right: false for none, or its options (default true: the credits of the basemap,\n * hillshade and relief in use, compact on maps narrower than 640 px) */\n attributionControl?: boolean | AttributionOptions;\n}\n\nexport interface TerrainOptions {\n /** One of the Earth's named models (default `'terrain-tiles'` on the Earth); unused with a `url` */\n model?: TerrainModel;\n /** Altitudes of 256 × 256 tiles in `encoding`: a WMS GetMap URL with {bbox} (EPSG:3857 on the Earth, the body's\n * Mercator metres elsewhere: the sphere of its radius), a tile URL with {z}, {x} and {y}, or an ArcGIS image service\n * (a URL ending in `/ImageServer`), asked for raw altitudes in the body's Mercator (default: the `model`'s; on the\n * Moon and Mars, NASA's Trek LOLA and MOLA models) */\n url?: string;\n /** How the tiles of `url` encode their altitudes (default `'float32'`); `'terrarium'` and `'mapbox'` take a URL with\n * {z}, {x} and {y} */\n encoding?: TerrainEncoding;\n /** Vertical exaggeration, 1 for the true relief (default 1) */\n exaggeration?: number;\n /** Finest level of the relief, up to 15 (default 15; 14 for the Terrain Tiles, 8 for the Moon's and Mars's models). It\n * starts at level 6 on the Earth, coarser on bodies of a larger relief for their size (3 on the Moon and Mars) */\n maxZoom?: number;\n /** Altitudes over mainland France raised by the height of the RAF20 geoid (the French one, 0 away from France), to\n * heights above the ellipsoid (those of 3D Tiles); false keeps the altitudes as served (NGF-IGN69 for the IGN's)\n * (default true for the `'ign'` model, false otherwise) */\n geoid?: boolean;\n}\n\n/** Sky, horizon and fog over the plane, with the names and meanings of MapLibre's `setSky` */\nexport interface AtmosphereOptions {\n /** A CSS color (default `#9cc7ec`) */\n skyColor?: string;\n /** (default `#e8f1f8`) */\n horizonColor?: string;\n /** (default `#f2f5f8`) */\n fogColor?: string;\n /** Blend from the horizon to the sky color, share of the field of view above the horizon, 0-1 (default 0.6) */\n skyHorizonBlend?: number;\n /** Blend from the horizon to the fog color below the horizon, 0-1 (default 0.7) */\n horizonFogBlend?: number;\n /** Share of the distance to the far plane over which the ground fades into the fog, 0-1 (default 0.4) */\n fogGroundBlend?: number;\n}\n\n/** Animation of a camera move */\nexport interface AnimationOptions {\n /** Milliseconds */\n duration?: number;\n /** Progress over time, both 0 to 1 */\n easing?: (t: number) => number;\n}\n\nexport interface FlyToOptions extends AnimationOptions {\n /** How far the flight zooms out on its way, as MapLibre's `curve` (default 1.42) */\n curve?: number;\n /** Average speed in screens per second when `duration` is not given (default 1.2) */\n speed?: number;\n}\n\n/**\n * Tile grid of a raster's URL. 'mercator': Web Mercator (XYZ, WMTS PM), the engine's own. 'equirectangular':\n * longitudes and latitudes (Plate Carrée, EPSG:4326-like), two 256 px tiles side by side at level 0, rows from the\n * north (NASA's Trek WMTS, WorldCRS84Quad). A `TileGrid`: the tile matrices of a WMTS in any CRS (Lambert-93…), or a\n * WMS asked for each tile's box in its CRS. The last two are reprojected into Web Mercator tiles by the map's workers\n * (in the page with `workers: false`).\n */\nexport type RasterGrid = 'mercator' | 'equirectangular' | TileGrid;\n\n/** What `RasterLayer.setStyle` changes */\nexport interface RasterStyle {\n opacity: number;\n /** 0 = greyscale, 1 = original colors */\n saturation: number;\n}\n\nexport interface RasterOptions {\n /** Tile URL with {z}, {x} and {y} (256 px tiles); unused with a `loader` */\n url: string;\n /** Tile grid of `url` (default 'mercator'); with 'equirectangular', `minZoom` and `maxZoom` are levels of that\n * grid; with a `TileGrid`, they are map zooms, by default those its matrices span */\n grid?: RasterGrid;\n minZoom?: number;\n maxZoom?: number;\n opacity?: number;\n /** 0 = greyscale, 1 = original colors */\n saturation?: number;\n /** Side of the tiles' textures, pixels (default 256): more for sharper tiles drawn by a `loader` */\n size?: number;\n /** Draws each tile instead of fetching `url`: an image of `size` × `size`, null for nothing there; a rejection is\n * retried like a network error */\n loader?: (z: number, x: number, y: number, signal: AbortSignal) => Promise<ImageBitmap | null>;\n /** Credits of the tiles, HTML: shown by the attribution control while the layer is on the map */\n attribution?: string;\n}\n\nexport interface NetworkStyle {\n /** Line width, CSS pixels, or zoom stops `[[zoom, width], …]` (default 2) */\n width: Size;\n /** Values above are drawn as unreached (default 1800) */\n max: number;\n /** Darker line every `contour` value units, 0 for none (default 0) */\n contour: number;\n opacity: number;\n /** Width of the halo drawn under the lines, CSS pixels or zoom stops, 0 for none (default 0): wide and faint, the\n * reached streets add up into a heat map that fills the blocks */\n halo: Size;\n /** Opacity of the halo at the middle of a line, fading quadratically to its sides (default 0.11) */\n haloOpacity: number;\n /** Colors from 0 to `max`: `[[fraction of max, color], …]` (default green to red) */\n ramp: Ramp | undefined;\n /** Color of the parts beyond `max` or unreached (default `rgba(140, 140, 140, 0.25)`) */\n unreachedColor: string;\n /** Share of `max` over which the colors fade out before it, 0 to 1 (default 0) */\n fade: number;\n}\n\nexport interface NetworkOptions extends Partial<NetworkStyle> {\n /** Node coordinates in degrees: lon0, lat0, lon1, lat1… */\n nodes: Float64Array;\n /** Edges as node index pairs: a0, b0, a1, b1… */\n edges: Uint32Array;\n /** Line of each edge, from A to B: the points of edge e are `points[start[e] .. start[e + 1]]` (lon, lat pairs,\n * counted in points); with fewer than two points an edge is straight. Default: all straight. */\n lines?: { start: Uint32Array; points: Float64Array };\n /** Per edge, the cost of travelling it from A to B then from B to A, in value units (Infinity: closed that way;\n * closed both ways: not drawn). A point along an edge then takes the quickest way there, min(value(A) + cost from\n * A, value(B) + cost from B), as a travel time does. Without costs, values are interpolated along the edges. */\n costs?: Float32Array;\n /** Width factor of each edge (default 1): rail lines wider than streets */\n edgeWidths?: Float32Array;\n}\n\nexport interface Tiles3dStyle {\n /** Screen-space error (CSS pixels) above which a tile is refined: 16 by default, lower is finer and heavier */\n maxScreenSpaceError: number;\n opacity: number;\n /** Size of the points of point cloud tiles (`.pnts`, glTF points), CSS pixels: 2 by default */\n pointSize?: number;\n}\n\nexport interface Tiles3dOptions extends Partial<Tiles3dStyle> {\n /** URL of a `tileset.json` (3D Tiles 1.0 b3dm and pnts, 1.1 glb meshes and points, external tilesets) */\n url: string;\n}\n\nexport interface MapPointerEvent {\n point: Point;\n /** Undefined above the horizon */\n lonLat: LonLat | undefined;\n}\n\n/** What 'hoverfeature' found under the pointer */\nexport interface MapHoverFeatureEvent extends MapPointerEvent {\n /** The feature under the pointer (see `GeoMap.pickFeature`), undefined if none */\n hit: FeatureHit | undefined;\n}\n\n/** A picked feature: its layer handle, its index there and, for line, circle and fill layers, the feature itself */\nexport interface FeatureHit {\n layer: Layer;\n index: number;\n feature: Feature | undefined;\n}\n\nexport interface MapEvents {\n /** The camera started moving (a gesture, an animation or `setCamera`) */\n movestart: Camera;\n /** The camera moved */\n move: Camera;\n /** The camera stopped: no gesture held, no animation running */\n moveend: Camera;\n /** The map changed size (CSS pixels) */\n resize: { width: number; height: number };\n /** The pointer moved over the map (at most once per frame, not while dragging) */\n hover: MapPointerEvent;\n /** What is under the pointer, picked without stalling the GPU: a frame or two after 'hover', only while listened to\n * (radius and layers in `GeoMap.hoverPicking`) */\n hoverfeature: MapHoverFeatureEvent;\n /** Click without drag */\n click: MapPointerEvent;\n /** A frame was drawn; duration of the engine call in milliseconds */\n render: { ms: number };\n /** Everything in view is loaded and drawn, nothing moves: the end of a load, once after each change (as MapLibre's\n * `idle`). Tiles requested by the first frame count, so it never fires before they arrive. */\n idle: Record<string, never>;\n /** The pointer left the canvas (a mouse going out of the map, or onto a control or marker) */\n leave: Record<string, never>;\n}\n\n/** What a layer handle needs from its map */\nexport interface LayerHost {\n readonly engine: Engine;\n requestRender(): void;\n /** Forgets a removed layer */\n detach(layer: object): void;\n /** Moves a layer under `before`, or on top */\n moveLayer(layer: object, before: object | undefined): void;\n /** A layer created again in the engine (new id): put at the place of its old id, which is removed */\n replaceLayer(layer: object, old: number): void;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["/** Public types of the `isard` package */\nimport type { AttributionOptions } from './controls.ts';\nimport type { DecoderUrls } from './decoders.ts';\nimport type { Feature, Ramp, Size } from './features.ts';\nimport type { TileGrid } from './grid.ts';\nimport type { Layer } from './layers.ts';\nimport type { Camera, Engine } from './wasm/isard.js';\n\nexport type LonLat = [lon: number, lat: number];\nexport type Point = [x: number, y: number];\n\n/**\n * The named basemaps. OpenFreeMap's vector styles, OpenStreetMap data worldwide, their labels above the other layers:\n * `osm-positron` (light grey, quiet: data over it reads first), `osm-liberty` and `osm-bright` (in colour). The\n * Géoplateforme's (IGN, France): rasters (`ign-plan`, `ign-plan-grey`, `ign-ortho`, the aerial photographs) or vector\n * tiles with their labels (`ign-plan-vector`, `ign-plan-grey-vector`, the PLAN.IGN styles).\n */\nexport type BasemapName =\n | 'osm-positron'\n | 'osm-liberty'\n | 'osm-bright'\n | 'ign-plan'\n | 'ign-plan-grey'\n | 'ign-ortho'\n | 'ign-plan-vector'\n | 'ign-plan-grey-vector'\n | 'none';\n\n/**\n * @deprecated The former names of the Géoplateforme basemaps, still accepted (with a warning): the same names with the\n * `ign-` prefix (`'plan-grey'` is `'ign-plan-grey'`)\n */\nexport type LegacyBasemap = 'plan' | 'plan-grey' | 'plan-vector' | 'plan-grey-vector' | 'ortho';\n\n/** A basemap by name (see `BasemapName`; the former names of `LegacyBasemap` are deprecated) */\nexport type Basemap = BasemapName | LegacyBasemap;\n\n/**\n * The Earth's named terrain models. `'terrain-tiles'`: worldwide, the Terrain Tiles of AWS's open data registry\n * (SRTM, EU-DEM, GMTED… merged by Mapzen, 30 m in most places), the sea floor flattened at sea level. `'ign'`: France,\n * the IGN's RGE ALTI from the Géoplateforme (1 to 5 m), raised by the RAF20 geoid to heights above the ellipsoid.\n */\nexport type TerrainModel = 'terrain-tiles' | 'ign';\n\n/** How tiles encode their altitudes: `'float32'`, raw little-endian floats (`image/x-bil;bits=32`, an ArcGIS raw\n * grid); `'terrarium'`, the colors of a PNG, `R × 256 + G + B / 256 - 32768`; `'mapbox'`, those of Terrain-RGB,\n * `(R × 65536 + G × 256 + B) / 10 - 10000` */\nexport type TerrainEncoding = 'float32' | 'terrarium' | 'mapbox';\n\n/**\n * How tiles load and show. 'immediate' (default): everything visible loads, tiles show as soon as they arrive.\n * 'smooth': during flights the levels flown through are skipped, off-center tiles wait while the camera moves, tiles\n * fade in; fewer downloads, for slow networks or GPUs.\n */\nexport type LoadingMode = 'immediate' | 'smooth';\n\n/** 'globe': a sphere at low zoom, blending into Web Mercator between zooms 5 and 7, up to three levels later under a\n * tilted camera (it sees much farther than its center: the horizon stays curved) */\nexport type Projection = 'globe' | 'mercator';\n\n/** A body to draw the map on, other than the named ones (`CelestialBody`) */\nexport interface BodyOptions {\n /** Equatorial radius, metres */\n radius: number;\n /** Flattening of its ellipsoid, 0 for a sphere (default 0) */\n flattening?: number;\n /** An atmosphere: its halo around the globe, true for the Earth's light blue, or a CSS color (its alpha the\n * halo's strength) (default false) */\n atmosphere?: boolean | string;\n /** Color of the globe where no tile covers it (past the Web Mercator latitudes, 85°), a CSS color (default\n * `#808080`) */\n color?: string;\n /** Lowest and highest altitudes of its ground, metres around the ellipsoid: what its relief may raise into view\n * (default ±1 % of the radius) */\n relief?: [lowest: number, highest: number];\n}\n\n/**\n * The body the map is drawn on: 'earth' (WGS 84, the default), 'moon' (a sphere of 1 737 400 m, no atmosphere),\n * 'mars' (a sphere of 3 396 190 m, its equatorial radius, a thin dusty halo; planetocentric latitudes) or another\n * one. Zoom levels keep their meaning on screen (the Web Mercator tile pyramid), their metres follow the body:\n * altitudes, relief, buildings, 3D Tiles. Off the Earth, the map has none of the Earth's defaults: no basemap, no\n * credits, and space for its background; the Moon and Mars have NASA's relief for `terrain: true`.\n */\nexport type CelestialBody = 'earth' | 'moon' | 'mars' | BodyOptions;\n\nexport interface GeoMapOptions extends Partial<Camera> {\n /** The body the map is drawn on (default 'earth'); set at creation */\n body?: CelestialBody;\n /** Default 'globe' */\n projection?: Projection;\n /** Default 'immediate' */\n loading?: LoadingMode;\n /** The basemap (default 'osm-positron'; 'none' off the Earth) */\n basemap?: Basemap;\n /** Opacity of the IGN hillshade over the basemap (France, Géoplateforme), 0 for none (default 0) */\n hillshade?: number;\n /** Color behind the map (sky of tilted flat views), a CSS color (default `#f2f2f0`; black off the Earth) */\n background?: string;\n /** Space behind the globe: stars and atmosphere halo, fading out as the globe turns flat (default true) */\n sky?: boolean;\n /** Relief under the basemap: true for the body's terrain model (on the Earth the worldwide Terrain Tiles; NASA's on\n * the Moon and Mars: LOLA, MOLA), one of the Earth's models by name (`'ign'`: France, RGE ALTI), or its options\n * (default false; on another body, its `url` is required). Network layers are draped on it */\n terrain?: boolean | TerrainModel | TerrainOptions;\n minZoom?: number;\n maxZoom?: number;\n /** Highest pitch, degrees, up to 85 (default 70) */\n maxPitch?: number;\n /** Sky over the plane, seen when the camera is tilted towards the horizon, and the fog the ground fades into\n * (MapLibre's `setSky`); default none: the background color */\n atmosphere?: AtmosphereOptions;\n /** Mouse, touch and keyboard controls (default true) */\n interactive?: boolean;\n /** Keyboard controls once the map has the focus (it is reached with Tab): arrows pan, Shift + arrows rotate and\n * tilt, + and - zoom (Shift: two levels), 0 faces north and levels the view (default true; none when not\n * `interactive`) */\n keyboard?: boolean;\n /** Accessible name of the map, read by screen readers (default 'Map') */\n ariaLabel?: string;\n /** Where to load the engine with 3D Tiles from (`isard_bg.wasm`), when a bundler does not resolve the default URL.\n * Given without `coreWasmUrl`, maps load this engine from the start */\n wasmUrl?: string | URL;\n /** Where to load the engine without 3D Tiles from (`isard_core_bg.wasm`, a third smaller), when a bundler does not\n * resolve the default URL. Maps load it first, and the engine with 3D Tiles (`wasmUrl`) for their first 3D Tiles\n * layer only */\n coreWasmUrl?: string | URL;\n /** Where the decoding workers load the point cloud module from (`isard_points_bg.wasm`, the LAZ decoder of COPC),\n * when a bundler does not resolve the default URL. Loaded with the first point cloud only */\n pointsWasmUrl?: string | URL;\n /** Load the engine with 3D Tiles from the start (default false: it is loaded when the first 3D Tiles layer or glTF\n * model is added, the map then moving its camera and layers onto it, a stall of about a frame or two). For a map that shows 3D Tiles\n * at once: one engine downloaded instead of two. `'preload'`: the map starts on the engine without 3D Tiles and\n * downloads and compiles the other once idle, without running it: its first 3D Tiles layer does not wait for the\n * download (for a map that will show 3D Tiles later, on demand) */\n tiles3d?: boolean | 'preload';\n /** Where to load the vector basemap worker from, when a bundler does not resolve the default URL */\n basemapWorkerUrl?: string | URL;\n /** Texture size of the vector basemap's tiles, pixels (default 512: lines and edges sharp at every zoom on a screen\n * of pixel ratio 1). 256: a quarter of the drawing in the workers, of the uploads and of the GPU memory, for lines\n * and edges a little softer between two zoom levels (the tiles are shown 181 to 362 CSS pixels wide) */\n basemapTileSize?: number;\n /** Glyphs of the symbol layers: a URL with `{fontstack}` and `{range}` (MapLibre's glyph format; default\n * OpenFreeMap's fonts, Noto Sans). A vector basemap's labels take the glyphs of its style */\n glyphs?: string;\n /** Workers decoding 3D Tiles off the main thread: a count, or false to decode on the main thread (default: cores - 1,\n * 1 to 4). False (or 0) also decodes the PNG relief and reprojects the equirectangular rasters on the main thread,\n * else done by the vector basemap's workers */\n workers?: number | false;\n /** Where to load the decoding worker from, when a bundler does not resolve the default URL */\n workerUrl?: string | URL;\n /** Folders of the Draco and Basis Universal decoders, loaded by the workers on first use (default: the official\n * builds on gstatic.com and jsDelivr; self-host them for offline or locked-down networks). They run through\n * `new Function`: a Content Security Policy needs `'unsafe-eval'` (see `DecoderUrls`) */\n decoders?: Partial<DecoderUrls>;\n /** Credits at the bottom right: false for none, or its options (default true: the credits of the basemap,\n * hillshade and relief in use, compact on maps narrower than 640 px) */\n attributionControl?: boolean | AttributionOptions;\n}\n\nexport interface TerrainOptions {\n /** One of the Earth's named models (default `'terrain-tiles'` on the Earth); unused with a `url` */\n model?: TerrainModel;\n /** Altitudes of 256 × 256 tiles in `encoding`: a WMS GetMap URL with {bbox} (EPSG:3857 on the Earth, the body's\n * Mercator metres elsewhere: the sphere of its radius), a tile URL with {z}, {x} and {y}, or an ArcGIS image service\n * (a URL ending in `/ImageServer`), asked for raw altitudes in the body's Mercator (default: the `model`'s; on the\n * Moon and Mars, NASA's Trek LOLA and MOLA models) */\n url?: string;\n /** How the tiles of `url` encode their altitudes (default `'float32'`); `'terrarium'` and `'mapbox'` take a URL with\n * {z}, {x} and {y} */\n encoding?: TerrainEncoding;\n /** Vertical exaggeration, 1 for the true relief (default 1) */\n exaggeration?: number;\n /** Finest level of the relief, up to 15 (default 15; 14 for the Terrain Tiles, 8 for the Moon's and Mars's models). It\n * starts at level 6 on the Earth, coarser on bodies of a larger relief for their size (3 on the Moon and Mars) */\n maxZoom?: number;\n /** Altitudes over mainland France raised by the height of the RAF20 geoid (the French one, 0 away from France), to\n * heights above the ellipsoid (those of 3D Tiles); false keeps the altitudes as served (NGF-IGN69 for the IGN's)\n * (default true for the `'ign'` model, false otherwise) */\n geoid?: boolean;\n}\n\n/** Sky, horizon and fog over the plane, with the names and meanings of MapLibre's `setSky` */\nexport interface AtmosphereOptions {\n /** A CSS color (default `#9cc7ec`) */\n skyColor?: string;\n /** (default `#e8f1f8`) */\n horizonColor?: string;\n /** (default `#f2f5f8`) */\n fogColor?: string;\n /** Blend from the horizon to the sky color, share of the field of view above the horizon, 0-1 (default 0.6) */\n skyHorizonBlend?: number;\n /** Blend from the horizon to the fog color below the horizon, 0-1 (default 0.7) */\n horizonFogBlend?: number;\n /** Share of the distance to the far plane over which the ground fades into the fog, 0-1 (default 0.4) */\n fogGroundBlend?: number;\n}\n\n/** What can be seen from a point (`GeoMap.setViewshed`) */\nexport interface ViewshedOptions {\n /** The observer */\n position: LonLat;\n /** Metres above the ground (default 1.7, eye level) */\n height?: number;\n /** Metres around the observer that are tinted (default 1000) */\n range?: number;\n /** A CSS color for what is seen (default `#2f9e44`) */\n visibleColor?: string;\n /** A CSS color for what is hidden (default `#e03131`) */\n hiddenColor?: string;\n /** 0-1 (default 0.55) */\n opacity?: number;\n /** To look one way only (a camera, a lookout), degrees clockwise from north; all around without it */\n direction?: number;\n /** Degrees above the horizon the cone looks, negative below (default 0) */\n tilt?: number;\n /** Angle of view across, degrees (default 60) */\n fov?: number;\n /** Angle of view up and down, degrees (default 40) */\n verticalFov?: number;\n}\n\n/** Animation of a camera move */\nexport interface AnimationOptions {\n /** Milliseconds */\n duration?: number;\n /** Progress over time, both 0 to 1 */\n easing?: (t: number) => number;\n}\n\nexport interface FlyToOptions extends AnimationOptions {\n /** How far the flight zooms out on its way, as MapLibre's `curve` (default 1.42) */\n curve?: number;\n /** Average speed in screens per second when `duration` is not given (default 1.2) */\n speed?: number;\n}\n\n/**\n * Tile grid of a raster's URL. 'mercator': Web Mercator (XYZ, WMTS PM), the engine's own. 'equirectangular':\n * longitudes and latitudes (Plate Carrée, EPSG:4326-like), two 256 px tiles side by side at level 0, rows from the\n * north (NASA's Trek WMTS, WorldCRS84Quad). A `TileGrid`: the tile matrices of a WMTS in any CRS (Lambert-93…), or a\n * WMS asked for each tile's box in its CRS. The last two are reprojected into Web Mercator tiles by the map's workers\n * (in the page with `workers: false`).\n */\nexport type RasterGrid = 'mercator' | 'equirectangular' | TileGrid;\n\n/** What `RasterLayer.setStyle` changes */\nexport interface RasterStyle {\n opacity: number;\n /** 0 = greyscale, 1 = original colors */\n saturation: number;\n}\n\nexport interface RasterOptions {\n /** Tile URL with {z}, {x} and {y} (256 px tiles); unused with a `loader` */\n url: string;\n /** Tile grid of `url` (default 'mercator'); with 'equirectangular', `minZoom` and `maxZoom` are levels of that\n * grid; with a `TileGrid`, they are map zooms, by default those its matrices span */\n grid?: RasterGrid;\n minZoom?: number;\n maxZoom?: number;\n opacity?: number;\n /** 0 = greyscale, 1 = original colors */\n saturation?: number;\n /** Side of the tiles' textures, pixels (default 256): more for sharper tiles drawn by a `loader` */\n size?: number;\n /** Draws each tile instead of fetching `url`: an image of `size` × `size`, null for nothing there; a rejection is\n * retried like a network error */\n loader?: (z: number, x: number, y: number, signal: AbortSignal) => Promise<ImageBitmap | null>;\n /** Credits of the tiles, HTML: shown by the attribution control while the layer is on the map */\n attribution?: string;\n}\n\nexport interface NetworkStyle {\n /** Line width, CSS pixels, or zoom stops `[[zoom, width], …]` (default 2) */\n width: Size;\n /** Values above are drawn as unreached (default 1800) */\n max: number;\n /** Darker line every `contour` value units, 0 for none (default 0) */\n contour: number;\n opacity: number;\n /** Width of the halo drawn under the lines, CSS pixels or zoom stops, 0 for none (default 0): wide and faint, the\n * reached streets add up into a heat map that fills the blocks */\n halo: Size;\n /** Opacity of the halo at the middle of a line, fading quadratically to its sides (default 0.11) */\n haloOpacity: number;\n /** Colors from 0 to `max`: `[[fraction of max, color], …]` (default green to red) */\n ramp: Ramp | undefined;\n /** Color of the parts beyond `max` or unreached (default `rgba(140, 140, 140, 0.25)`) */\n unreachedColor: string;\n /** Share of `max` over which the colors fade out before it, 0 to 1 (default 0) */\n fade: number;\n}\n\nexport interface NetworkOptions extends Partial<NetworkStyle> {\n /** Node coordinates in degrees: lon0, lat0, lon1, lat1… */\n nodes: Float64Array;\n /** Edges as node index pairs: a0, b0, a1, b1… */\n edges: Uint32Array;\n /** Line of each edge, from A to B: the points of edge e are `points[start[e] .. start[e + 1]]` (lon, lat pairs,\n * counted in points); with fewer than two points an edge is straight. Default: all straight. */\n lines?: { start: Uint32Array; points: Float64Array };\n /** Per edge, the cost of travelling it from A to B then from B to A, in value units (Infinity: closed that way;\n * closed both ways: not drawn). A point along an edge then takes the quickest way there, min(value(A) + cost from\n * A, value(B) + cost from B), as a travel time does. Without costs, values are interpolated along the edges. */\n costs?: Float32Array;\n /** Width factor of each edge (default 1): rail lines wider than streets */\n edgeWidths?: Float32Array;\n}\n\nexport interface Tiles3dStyle {\n /** Screen-space error (CSS pixels) above which a tile is refined: 16 by default, lower is finer and heavier */\n maxScreenSpaceError: number;\n opacity: number;\n /** Size of the points of point cloud tiles (`.pnts`, glTF points), CSS pixels: 2 by default */\n pointSize?: number;\n}\n\nexport interface Tiles3dOptions extends Partial<Tiles3dStyle> {\n /** URL of a `tileset.json` (3D Tiles 1.0 b3dm and pnts, 1.1 glb meshes and points, external tilesets) */\n url: string;\n}\n\nexport interface MapPointerEvent {\n point: Point;\n /** Undefined above the horizon */\n lonLat: LonLat | undefined;\n}\n\n/** What 'hoverfeature' found under the pointer */\nexport interface MapHoverFeatureEvent extends MapPointerEvent {\n /** The feature under the pointer (see `GeoMap.pickFeature`), undefined if none */\n hit: FeatureHit | undefined;\n}\n\n/** A picked feature: its layer handle, its index there and, for line, circle and fill layers, the feature itself */\nexport interface FeatureHit {\n layer: Layer;\n index: number;\n feature: Feature | undefined;\n}\n\nexport interface MapEvents {\n /** The camera started moving (a gesture, an animation or `setCamera`) */\n movestart: Camera;\n /** The camera moved */\n move: Camera;\n /** The camera stopped: no gesture held, no animation running */\n moveend: Camera;\n /** The map changed size (CSS pixels) */\n resize: { width: number; height: number };\n /** The pointer moved over the map (at most once per frame, not while dragging) */\n hover: MapPointerEvent;\n /** What is under the pointer, picked without stalling the GPU: a frame or two after 'hover', only while listened to\n * (radius and layers in `GeoMap.hoverPicking`) */\n hoverfeature: MapHoverFeatureEvent;\n /** Click without drag */\n click: MapPointerEvent;\n /** A frame was drawn; duration of the engine call in milliseconds */\n render: { ms: number };\n /** Everything in view is loaded and drawn, nothing moves: the end of a load, once after each change (as MapLibre's\n * `idle`). Tiles requested by the first frame count, so it never fires before they arrive. */\n idle: Record<string, never>;\n /** The pointer left the canvas (a mouse going out of the map, or onto a control or marker) */\n leave: Record<string, never>;\n}\n\n/** What a layer handle needs from its map */\nexport interface LayerHost {\n readonly engine: Engine;\n requestRender(): void;\n /** Forgets a removed layer */\n detach(layer: object): void;\n /** Moves a layer under `before`, or on top */\n moveLayer(layer: object, before: object | undefined): void;\n /** A layer created again in the engine (new id): put at the place of its old id, which is removed */\n replaceLayer(layer: object, old: number): void;\n}\n"]}
|
package/dist/vectortiles.d.ts
CHANGED
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import type { Priority } from './basemap.worker.ts';
|
|
12
12
|
import type { Feature, Size } from './features.ts';
|
|
13
|
-
import type { RasterLayer } from './layers.ts';
|
|
13
|
+
import type { Layer, RasterLayer } from './layers.ts';
|
|
14
14
|
import type { GeoMap } from './map.ts';
|
|
15
15
|
import type { SymbolLayer } from './symbols.ts';
|
|
16
|
+
import type { RasterOptions } from './types.ts';
|
|
16
17
|
import { type Json, type LabelCandidate, type RasterSource, type Style, type StyleLayer } from './vectorstyle.ts';
|
|
17
18
|
import type { Camera } from './wasm/isard.js';
|
|
18
19
|
/** OpenFreeMap's styles: OpenStreetMap data in the OpenMapTiles schema, worldwide, free and without a key */
|
|
@@ -133,4 +134,32 @@ export declare class VectorTiles {
|
|
|
133
134
|
/** Stops its workers' work and removes its raster and label layers from the map (those still there) */
|
|
134
135
|
destroy(): void;
|
|
135
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* A plain style for vector tiles known only by their layers' names (a PMTiles archive's `vector_layers`, an MBTiles'
|
|
139
|
+
* metadata): each layer's polygons filled, its lines and outlines stroked and its points as circles, a color per
|
|
140
|
+
* layer, the `name` of points as labels. `source` is the style's vector source (`url`: TileJSON or `pmtiles://…`, or
|
|
141
|
+
* `tiles`)
|
|
142
|
+
*/
|
|
143
|
+
export declare function basicStyle(source: {
|
|
144
|
+
url?: string;
|
|
145
|
+
tiles?: string[];
|
|
146
|
+
minzoom?: number;
|
|
147
|
+
maxzoom?: number;
|
|
148
|
+
}, layers: readonly string[]): Style;
|
|
149
|
+
/** Options of `GeoMap.addPmtiles` */
|
|
150
|
+
export interface PmtilesOptions {
|
|
151
|
+
/** What the archive holds (default from its header: raster images or vector tiles) */
|
|
152
|
+
kind?: 'raster' | 'vector';
|
|
153
|
+
/** A MapLibre style for vector tiles (its vector source `pmtiles://…`); default `basicStyle` of the archive's layers */
|
|
154
|
+
style?: Style;
|
|
155
|
+
opacity?: number;
|
|
156
|
+
/** Texture size of raster tiles (default 256; 512 for the sharper tiles of a 512 px archive) */
|
|
157
|
+
size?: number;
|
|
158
|
+
/** Credits, HTML (default the archive's `attribution` metadata, as text) */
|
|
159
|
+
attribution?: string;
|
|
160
|
+
before?: Layer;
|
|
161
|
+
}
|
|
162
|
+
/** A raster loader reading the tiles of a `pmtiles://` archive URL (images of any size, drawn at `size`); undefined
|
|
163
|
+
* for another URL */
|
|
164
|
+
export declare function pmtilesRasterLoader(url: string, size: number): RasterOptions['loader'];
|
|
136
165
|
export {};
|