geolibre-wasm 0.6.0 → 0.7.1
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/geolibre-cli.wasm +0 -0
- package/geolibre_wasm.d.ts +62 -0
- package/geolibre_wasm.js +222 -0
- package/geolibre_wasm_bg.wasm +0 -0
- package/geolibre_wasm_bg.wasm.d.ts +10 -0
- package/package.json +1 -1
- package/tools.d.ts +11 -1
- package/tools.mjs +136 -1
package/geolibre-cli.wasm
CHANGED
|
Binary file
|
package/geolibre_wasm.d.ts
CHANGED
|
@@ -262,6 +262,58 @@ export class GeoTiffReader {
|
|
|
262
262
|
readonly width: number;
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
+
export class PmtilesExtractor {
|
|
266
|
+
free(): void;
|
|
267
|
+
[Symbol.dispose](): void;
|
|
268
|
+
/**
|
|
269
|
+
* Hand back the bytes of one `wanted_json()` range, identified by its
|
|
270
|
+
* offset. Ranges may be fed in any order.
|
|
271
|
+
*/
|
|
272
|
+
feed(offset: number, bytes: Uint8Array): void;
|
|
273
|
+
/**
|
|
274
|
+
* Assemble the extracted archive. Consumes the extractor's buffers; the
|
|
275
|
+
* returned `Uint8Array` is a complete `.pmtiles` file.
|
|
276
|
+
*/
|
|
277
|
+
finish(): Uint8Array;
|
|
278
|
+
/**
|
|
279
|
+
* Source archive header as JSON (`{}` until the first feed): zooms,
|
|
280
|
+
* bounds, tile type/compression, tile counts. Lets a UI validate the
|
|
281
|
+
* request and describe the source before committing to the download.
|
|
282
|
+
*/
|
|
283
|
+
header_json(): string;
|
|
284
|
+
/**
|
|
285
|
+
* Plan an extraction of `min_zoom..=max_zoom` tiles intersecting the
|
|
286
|
+
* WGS84 bbox. Zooms are clamped to what the source archive contains once
|
|
287
|
+
* its header arrives; `min_zoom` 0 keeps the basemap usable zoomed out.
|
|
288
|
+
*/
|
|
289
|
+
constructor(min_lon: number, min_lat: number, max_lon: number, max_lat: number, min_zoom: number, max_zoom: number);
|
|
290
|
+
/**
|
|
291
|
+
* Progress as JSON: `{"phase":"header|directories|data|done",
|
|
292
|
+
* "tiles_selected":n,"blobs_total":n,"data_bytes_total":n,
|
|
293
|
+
* "data_bytes_received":n,"estimated_output_bytes":n}`.
|
|
294
|
+
*/
|
|
295
|
+
progress_json(): string;
|
|
296
|
+
/**
|
|
297
|
+
* Coalesce tile-data requests whose byte gap is at most this (default
|
|
298
|
+
* 65,536). Larger values trade overfetch for fewer HTTP round-trips.
|
|
299
|
+
*/
|
|
300
|
+
set_max_range_gap(max_gap: number): void;
|
|
301
|
+
/**
|
|
302
|
+
* Cap on addressed tiles (default 2,000,000). Raise for huge desktop
|
|
303
|
+
* extracts; lower to fail fast in memory-constrained embeds.
|
|
304
|
+
*/
|
|
305
|
+
set_max_tiles(max_tiles: number): void;
|
|
306
|
+
/**
|
|
307
|
+
* Outstanding byte ranges the host should fetch, as a JSON array of
|
|
308
|
+
* `{"offset":n,"length":n}`. Empty array when nothing is outstanding.
|
|
309
|
+
*/
|
|
310
|
+
wanted_json(): string;
|
|
311
|
+
/**
|
|
312
|
+
* True once every needed range has been fed; `finish()` is then valid.
|
|
313
|
+
*/
|
|
314
|
+
readonly done: boolean;
|
|
315
|
+
}
|
|
316
|
+
|
|
265
317
|
/**
|
|
266
318
|
* Install a panic hook so Rust panics surface as readable `console.error`
|
|
267
319
|
* messages instead of an opaque `RuntimeError: unreachable`.
|
|
@@ -392,6 +444,7 @@ export interface InitOutput {
|
|
|
392
444
|
readonly __wbg_cogbuilder_free: (a: number, b: number) => void;
|
|
393
445
|
readonly __wbg_cogstream_free: (a: number, b: number) => void;
|
|
394
446
|
readonly __wbg_geotiffreader_free: (a: number, b: number) => void;
|
|
447
|
+
readonly __wbg_pmtilesextractor_free: (a: number, b: number) => void;
|
|
395
448
|
readonly cogbuilder_new: (a: number, b: number, c: number) => number;
|
|
396
449
|
readonly cogbuilder_set_bigtiff: (a: number, b: number) => void;
|
|
397
450
|
readonly cogbuilder_set_compression: (a: number, b: number, c: number, d: number) => void;
|
|
@@ -459,6 +512,15 @@ export interface InitOutput {
|
|
|
459
512
|
readonly lidar_read_intensity: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
460
513
|
readonly lidar_read_xyz: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
461
514
|
readonly morans_i: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
515
|
+
readonly pmtilesextractor_done: (a: number) => number;
|
|
516
|
+
readonly pmtilesextractor_feed: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
517
|
+
readonly pmtilesextractor_finish: (a: number, b: number) => void;
|
|
518
|
+
readonly pmtilesextractor_header_json: (a: number, b: number) => void;
|
|
519
|
+
readonly pmtilesextractor_new: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
520
|
+
readonly pmtilesextractor_progress_json: (a: number, b: number) => void;
|
|
521
|
+
readonly pmtilesextractor_set_max_range_gap: (a: number, b: number, c: number) => void;
|
|
522
|
+
readonly pmtilesextractor_set_max_tiles: (a: number, b: number, c: number) => void;
|
|
523
|
+
readonly pmtilesextractor_wanted_json: (a: number, b: number) => void;
|
|
462
524
|
readonly transform_bbox_epsg: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
463
525
|
readonly transform_points_epsg: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
464
526
|
readonly vector_formats: (a: number) => void;
|
package/geolibre_wasm.js
CHANGED
|
@@ -1071,6 +1071,225 @@ export class GeoTiffReader {
|
|
|
1071
1071
|
}
|
|
1072
1072
|
if (Symbol.dispose) GeoTiffReader.prototype[Symbol.dispose] = GeoTiffReader.prototype.free;
|
|
1073
1073
|
|
|
1074
|
+
export class PmtilesExtractor {
|
|
1075
|
+
__destroy_into_raw() {
|
|
1076
|
+
const ptr = this.__wbg_ptr;
|
|
1077
|
+
this.__wbg_ptr = 0;
|
|
1078
|
+
PmtilesExtractorFinalization.unregister(this);
|
|
1079
|
+
return ptr;
|
|
1080
|
+
}
|
|
1081
|
+
free() {
|
|
1082
|
+
const ptr = this.__destroy_into_raw();
|
|
1083
|
+
wasm.__wbg_pmtilesextractor_free(ptr, 0);
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* True once every needed range has been fed; `finish()` is then valid.
|
|
1087
|
+
* @returns {boolean}
|
|
1088
|
+
*/
|
|
1089
|
+
get done() {
|
|
1090
|
+
const ret = wasm.pmtilesextractor_done(this.__wbg_ptr);
|
|
1091
|
+
return ret !== 0;
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Hand back the bytes of one `wanted_json()` range, identified by its
|
|
1095
|
+
* offset. Ranges may be fed in any order.
|
|
1096
|
+
* @param {number} offset
|
|
1097
|
+
* @param {Uint8Array} bytes
|
|
1098
|
+
*/
|
|
1099
|
+
feed(offset, bytes) {
|
|
1100
|
+
try {
|
|
1101
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
1102
|
+
const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_export2);
|
|
1103
|
+
const len0 = WASM_VECTOR_LEN;
|
|
1104
|
+
wasm.pmtilesextractor_feed(retptr, this.__wbg_ptr, offset, ptr0, len0);
|
|
1105
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
1106
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
1107
|
+
if (r1) {
|
|
1108
|
+
throw takeObject(r0);
|
|
1109
|
+
}
|
|
1110
|
+
} finally {
|
|
1111
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Assemble the extracted archive. Consumes the extractor's buffers; the
|
|
1116
|
+
* returned `Uint8Array` is a complete `.pmtiles` file.
|
|
1117
|
+
* @returns {Uint8Array}
|
|
1118
|
+
*/
|
|
1119
|
+
finish() {
|
|
1120
|
+
try {
|
|
1121
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
1122
|
+
wasm.pmtilesextractor_finish(retptr, this.__wbg_ptr);
|
|
1123
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
1124
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
1125
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
1126
|
+
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
1127
|
+
if (r3) {
|
|
1128
|
+
throw takeObject(r2);
|
|
1129
|
+
}
|
|
1130
|
+
var v1 = getArrayU8FromWasm0(r0, r1).slice();
|
|
1131
|
+
wasm.__wbindgen_export(r0, r1 * 1, 1);
|
|
1132
|
+
return v1;
|
|
1133
|
+
} finally {
|
|
1134
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Source archive header as JSON (`{}` until the first feed): zooms,
|
|
1139
|
+
* bounds, tile type/compression, tile counts. Lets a UI validate the
|
|
1140
|
+
* request and describe the source before committing to the download.
|
|
1141
|
+
* @returns {string}
|
|
1142
|
+
*/
|
|
1143
|
+
header_json() {
|
|
1144
|
+
let deferred2_0;
|
|
1145
|
+
let deferred2_1;
|
|
1146
|
+
try {
|
|
1147
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
1148
|
+
wasm.pmtilesextractor_header_json(retptr, this.__wbg_ptr);
|
|
1149
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
1150
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
1151
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
1152
|
+
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
1153
|
+
var ptr1 = r0;
|
|
1154
|
+
var len1 = r1;
|
|
1155
|
+
if (r3) {
|
|
1156
|
+
ptr1 = 0; len1 = 0;
|
|
1157
|
+
throw takeObject(r2);
|
|
1158
|
+
}
|
|
1159
|
+
deferred2_0 = ptr1;
|
|
1160
|
+
deferred2_1 = len1;
|
|
1161
|
+
return getStringFromWasm0(ptr1, len1);
|
|
1162
|
+
} finally {
|
|
1163
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
1164
|
+
wasm.__wbindgen_export(deferred2_0, deferred2_1, 1);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Plan an extraction of `min_zoom..=max_zoom` tiles intersecting the
|
|
1169
|
+
* WGS84 bbox. Zooms are clamped to what the source archive contains once
|
|
1170
|
+
* its header arrives; `min_zoom` 0 keeps the basemap usable zoomed out.
|
|
1171
|
+
* @param {number} min_lon
|
|
1172
|
+
* @param {number} min_lat
|
|
1173
|
+
* @param {number} max_lon
|
|
1174
|
+
* @param {number} max_lat
|
|
1175
|
+
* @param {number} min_zoom
|
|
1176
|
+
* @param {number} max_zoom
|
|
1177
|
+
*/
|
|
1178
|
+
constructor(min_lon, min_lat, max_lon, max_lat, min_zoom, max_zoom) {
|
|
1179
|
+
try {
|
|
1180
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
1181
|
+
wasm.pmtilesextractor_new(retptr, min_lon, min_lat, max_lon, max_lat, min_zoom, max_zoom);
|
|
1182
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
1183
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
1184
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
1185
|
+
if (r2) {
|
|
1186
|
+
throw takeObject(r1);
|
|
1187
|
+
}
|
|
1188
|
+
this.__wbg_ptr = r0;
|
|
1189
|
+
PmtilesExtractorFinalization.register(this, this.__wbg_ptr, this);
|
|
1190
|
+
return this;
|
|
1191
|
+
} finally {
|
|
1192
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
/**
|
|
1196
|
+
* Progress as JSON: `{"phase":"header|directories|data|done",
|
|
1197
|
+
* "tiles_selected":n,"blobs_total":n,"data_bytes_total":n,
|
|
1198
|
+
* "data_bytes_received":n,"estimated_output_bytes":n}`.
|
|
1199
|
+
* @returns {string}
|
|
1200
|
+
*/
|
|
1201
|
+
progress_json() {
|
|
1202
|
+
let deferred2_0;
|
|
1203
|
+
let deferred2_1;
|
|
1204
|
+
try {
|
|
1205
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
1206
|
+
wasm.pmtilesextractor_progress_json(retptr, this.__wbg_ptr);
|
|
1207
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
1208
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
1209
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
1210
|
+
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
1211
|
+
var ptr1 = r0;
|
|
1212
|
+
var len1 = r1;
|
|
1213
|
+
if (r3) {
|
|
1214
|
+
ptr1 = 0; len1 = 0;
|
|
1215
|
+
throw takeObject(r2);
|
|
1216
|
+
}
|
|
1217
|
+
deferred2_0 = ptr1;
|
|
1218
|
+
deferred2_1 = len1;
|
|
1219
|
+
return getStringFromWasm0(ptr1, len1);
|
|
1220
|
+
} finally {
|
|
1221
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
1222
|
+
wasm.__wbindgen_export(deferred2_0, deferred2_1, 1);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
/**
|
|
1226
|
+
* Coalesce tile-data requests whose byte gap is at most this (default
|
|
1227
|
+
* 65,536). Larger values trade overfetch for fewer HTTP round-trips.
|
|
1228
|
+
* @param {number} max_gap
|
|
1229
|
+
*/
|
|
1230
|
+
set_max_range_gap(max_gap) {
|
|
1231
|
+
try {
|
|
1232
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
1233
|
+
wasm.pmtilesextractor_set_max_range_gap(retptr, this.__wbg_ptr, max_gap);
|
|
1234
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
1235
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
1236
|
+
if (r1) {
|
|
1237
|
+
throw takeObject(r0);
|
|
1238
|
+
}
|
|
1239
|
+
} finally {
|
|
1240
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
/**
|
|
1244
|
+
* Cap on addressed tiles (default 2,000,000). Raise for huge desktop
|
|
1245
|
+
* extracts; lower to fail fast in memory-constrained embeds.
|
|
1246
|
+
* @param {number} max_tiles
|
|
1247
|
+
*/
|
|
1248
|
+
set_max_tiles(max_tiles) {
|
|
1249
|
+
try {
|
|
1250
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
1251
|
+
wasm.pmtilesextractor_set_max_tiles(retptr, this.__wbg_ptr, max_tiles);
|
|
1252
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
1253
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
1254
|
+
if (r1) {
|
|
1255
|
+
throw takeObject(r0);
|
|
1256
|
+
}
|
|
1257
|
+
} finally {
|
|
1258
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
/**
|
|
1262
|
+
* Outstanding byte ranges the host should fetch, as a JSON array of
|
|
1263
|
+
* `{"offset":n,"length":n}`. Empty array when nothing is outstanding.
|
|
1264
|
+
* @returns {string}
|
|
1265
|
+
*/
|
|
1266
|
+
wanted_json() {
|
|
1267
|
+
let deferred2_0;
|
|
1268
|
+
let deferred2_1;
|
|
1269
|
+
try {
|
|
1270
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
1271
|
+
wasm.pmtilesextractor_wanted_json(retptr, this.__wbg_ptr);
|
|
1272
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
1273
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
1274
|
+
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
|
1275
|
+
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
|
1276
|
+
var ptr1 = r0;
|
|
1277
|
+
var len1 = r1;
|
|
1278
|
+
if (r3) {
|
|
1279
|
+
ptr1 = 0; len1 = 0;
|
|
1280
|
+
throw takeObject(r2);
|
|
1281
|
+
}
|
|
1282
|
+
deferred2_0 = ptr1;
|
|
1283
|
+
deferred2_1 = len1;
|
|
1284
|
+
return getStringFromWasm0(ptr1, len1);
|
|
1285
|
+
} finally {
|
|
1286
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
1287
|
+
wasm.__wbindgen_export(deferred2_0, deferred2_1, 1);
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
if (Symbol.dispose) PmtilesExtractor.prototype[Symbol.dispose] = PmtilesExtractor.prototype.free;
|
|
1292
|
+
|
|
1074
1293
|
/**
|
|
1075
1294
|
* Install a panic hook so Rust panics surface as readable `console.error`
|
|
1076
1295
|
* messages instead of an opaque `RuntimeError: unreachable`.
|
|
@@ -1646,6 +1865,9 @@ const CogStreamFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
|
1646
1865
|
const GeoTiffReaderFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
1647
1866
|
? { register: () => {}, unregister: () => {} }
|
|
1648
1867
|
: new FinalizationRegistry(ptr => wasm.__wbg_geotiffreader_free(ptr, 1));
|
|
1868
|
+
const PmtilesExtractorFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
1869
|
+
? { register: () => {}, unregister: () => {} }
|
|
1870
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_pmtilesextractor_free(ptr, 1));
|
|
1649
1871
|
|
|
1650
1872
|
function addHeapObject(obj) {
|
|
1651
1873
|
if (heap_next === heap.length) heap.push(heap.length + 1);
|
package/geolibre_wasm_bg.wasm
CHANGED
|
Binary file
|
|
@@ -5,6 +5,7 @@ export const __start: () => void;
|
|
|
5
5
|
export const __wbg_cogbuilder_free: (a: number, b: number) => void;
|
|
6
6
|
export const __wbg_cogstream_free: (a: number, b: number) => void;
|
|
7
7
|
export const __wbg_geotiffreader_free: (a: number, b: number) => void;
|
|
8
|
+
export const __wbg_pmtilesextractor_free: (a: number, b: number) => void;
|
|
8
9
|
export const cogbuilder_new: (a: number, b: number, c: number) => number;
|
|
9
10
|
export const cogbuilder_set_bigtiff: (a: number, b: number) => void;
|
|
10
11
|
export const cogbuilder_set_compression: (a: number, b: number, c: number, d: number) => void;
|
|
@@ -72,6 +73,15 @@ export const lidar_read_classification: (a: number, b: number, c: number, d: num
|
|
|
72
73
|
export const lidar_read_intensity: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
73
74
|
export const lidar_read_xyz: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
74
75
|
export const morans_i: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
|
76
|
+
export const pmtilesextractor_done: (a: number) => number;
|
|
77
|
+
export const pmtilesextractor_feed: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
78
|
+
export const pmtilesextractor_finish: (a: number, b: number) => void;
|
|
79
|
+
export const pmtilesextractor_header_json: (a: number, b: number) => void;
|
|
80
|
+
export const pmtilesextractor_new: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
81
|
+
export const pmtilesextractor_progress_json: (a: number, b: number) => void;
|
|
82
|
+
export const pmtilesextractor_set_max_range_gap: (a: number, b: number, c: number) => void;
|
|
83
|
+
export const pmtilesextractor_set_max_tiles: (a: number, b: number, c: number) => void;
|
|
84
|
+
export const pmtilesextractor_wanted_json: (a: number, b: number) => void;
|
|
75
85
|
export const transform_bbox_epsg: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
76
86
|
export const transform_points_epsg: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
77
87
|
export const vector_formats: (a: number) => void;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "geolibre-wasm",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.7.1",
|
|
5
5
|
"description": "Pure-Rust geospatial toolkit (whitebox_next_gen) compiled to WebAssembly (WASI) for GeoLibre's in-browser tool execution",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
package/tools.d.ts
CHANGED
|
@@ -117,7 +117,17 @@ export function listTools(): Promise<string[]>;
|
|
|
117
117
|
/** Fetch every tool manifest (parameter schemas), for building UIs offline. */
|
|
118
118
|
export function listManifests(): Promise<ToolManifest[]>;
|
|
119
119
|
|
|
120
|
-
/**
|
|
120
|
+
/**
|
|
121
|
+
* Run one tool over an in-memory filesystem.
|
|
122
|
+
*
|
|
123
|
+
* `extract_cog_subset`, `extract_wms_subset`, `extract_xyz_tile_subset`, and
|
|
124
|
+
* `pmtiles_extract` are intercepted and run as JS-orchestrated byte-range
|
|
125
|
+
* extractions instead of whole-file WASI reads: pass `--url=<http source>` to
|
|
126
|
+
* subset a remote archive without downloading it whole (the host must allow
|
|
127
|
+
* cross-origin Range reads). `pmtiles_extract` also accepts `--bbox_crs` (the
|
|
128
|
+
* bbox is reprojected to WGS84, which PMTiles address) and still supports a
|
|
129
|
+
* local `--input=/work/local.pmtiles`.
|
|
130
|
+
*/
|
|
121
131
|
export function runTool(tool: string, opts?: RunToolOptions): Promise<ToolResult>;
|
|
122
132
|
|
|
123
133
|
/** Extract a bbox subset from a local COG or HTTP COG. HTTP sources use byte-range requests. */
|
package/tools.mjs
CHANGED
|
@@ -11,13 +11,23 @@
|
|
|
11
11
|
// });
|
|
12
12
|
// const slopeCog = files["slope.tif"]; // Uint8Array
|
|
13
13
|
import { WASI, File, OpenFile, ConsoleStdout, PreopenDirectory } from "@bjorn3/browser_wasi_shim";
|
|
14
|
-
import initGeoLibre, { CogBuilder, CogStream, GeoTiffReader, transform_bbox_epsg, transform_points_epsg } from "./geolibre_wasm.js";
|
|
14
|
+
import initGeoLibre, { CogBuilder, CogStream, GeoTiffReader, PmtilesExtractor, transform_bbox_epsg, transform_points_epsg } from "./geolibre_wasm.js";
|
|
15
15
|
|
|
16
16
|
let _module = null;
|
|
17
17
|
let _libraryReady = null;
|
|
18
18
|
const COG_SUBSET_TOOL_ID = "extract_cog_subset";
|
|
19
19
|
const WMS_SUBSET_TOOL_ID = "extract_wms_subset";
|
|
20
20
|
const XYZ_SUBSET_TOOL_ID = "extract_xyz_tile_subset";
|
|
21
|
+
const PMTILES_EXTRACT_TOOL_ID = "pmtiles_extract";
|
|
22
|
+
// The `url` + `bbox_crs` params the JS interception adds to the WASI
|
|
23
|
+
// `pmtiles_extract` tool's own manifest, so a host can extract from a remote
|
|
24
|
+
// archive by byte-range (no whole-file download) and offer the same
|
|
25
|
+
// "Use map extent" / "Draw on map" bbox affordance the COG/WMS/XYZ extractors
|
|
26
|
+
// get. The native `geolibre` CLI keeps its local file→file behaviour.
|
|
27
|
+
const PMTILES_EXTRACT_EXTRA_PARAMS = [
|
|
28
|
+
{ name: "url", description: "HTTP(S) PMTiles URL. Provide either url or input; HTTP sources use byte-range requests (the host must allow cross-origin Range reads).", required: false, schema: { type: "string" } },
|
|
29
|
+
{ name: "bbox_crs", description: "EPSG code of the bbox coordinates. Defaults to 4326 (WGS84 lon/lat); other CRSs are reprojected to 4326.", required: false, schema: { kind: "scalar", scalar: "integer" } },
|
|
30
|
+
];
|
|
21
31
|
const COG_SUBSET_MANIFEST = {
|
|
22
32
|
id: COG_SUBSET_TOOL_ID,
|
|
23
33
|
display_name: "Extract COG Subset",
|
|
@@ -189,6 +199,19 @@ export async function listManifests() {
|
|
|
189
199
|
if (!manifests.some((m) => m.id === XYZ_SUBSET_TOOL_ID)) {
|
|
190
200
|
manifests.push(XYZ_SUBSET_MANIFEST);
|
|
191
201
|
}
|
|
202
|
+
// pmtiles_extract is a real WASI tool, so its manifest already lists
|
|
203
|
+
// input/output/bbox/min_zoom/max_zoom/max_tiles. Augment it with the `url`
|
|
204
|
+
// and `bbox_crs` params the JS interception handles, so hosts can extract
|
|
205
|
+
// from a remote archive and reproject the bbox.
|
|
206
|
+
const pmtiles = manifests.find((m) => m.id === PMTILES_EXTRACT_TOOL_ID);
|
|
207
|
+
if (pmtiles && Array.isArray(pmtiles.params)) {
|
|
208
|
+
pmtiles.source = "geolibre";
|
|
209
|
+
for (const extra of PMTILES_EXTRACT_EXTRA_PARAMS) {
|
|
210
|
+
if (!pmtiles.params.some((p) => p.name === extra.name)) {
|
|
211
|
+
pmtiles.params.push({ ...extra });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
192
215
|
return manifests;
|
|
193
216
|
}
|
|
194
217
|
|
|
@@ -206,6 +229,7 @@ export async function runTool(tool, opts = {}) {
|
|
|
206
229
|
if (tool === COG_SUBSET_TOOL_ID) return runCogSubsetTool(args, input);
|
|
207
230
|
if (tool === WMS_SUBSET_TOOL_ID) return runWmsSubsetTool(args);
|
|
208
231
|
if (tool === XYZ_SUBSET_TOOL_ID) return runXyzTileSubsetTool(args);
|
|
232
|
+
if (tool === PMTILES_EXTRACT_TOOL_ID) return runPmtilesExtractTool(args, input);
|
|
209
233
|
return exec([tool, ...args], input);
|
|
210
234
|
}
|
|
211
235
|
|
|
@@ -343,6 +367,117 @@ async function runXyzTileSubsetTool(args) {
|
|
|
343
367
|
}
|
|
344
368
|
}
|
|
345
369
|
|
|
370
|
+
/**
|
|
371
|
+
* Extract a bbox/zoom subset of a PMTiles archive (local or remote) into a new
|
|
372
|
+
* self-contained archive, driving the wasm `PmtilesExtractor` with byte-range
|
|
373
|
+
* reads. Mirrors the COG/WMS/XYZ interception so a remote planet build is
|
|
374
|
+
* subset by range instead of downloaded whole. The bbox is reprojected from
|
|
375
|
+
* `bbox_crs` to WGS84 (what PMTiles address); `bbox_crs` defaults to 4326.
|
|
376
|
+
*/
|
|
377
|
+
async function runPmtilesExtractTool(args, inputFiles) {
|
|
378
|
+
const flags = parseFlagArgs(args);
|
|
379
|
+
const url = flags.url;
|
|
380
|
+
const inputPath = flags.input;
|
|
381
|
+
const rawBbox = parseBbox(flags.bbox);
|
|
382
|
+
const bboxCrs = parseOptionalEpsg(flags.bbox_crs ?? flags.bboxCrs ?? flags.crs, "bbox_crs");
|
|
383
|
+
const minZoom = clampZoom(flags.min_zoom ?? flags.minZoom, 0);
|
|
384
|
+
const maxZoom = clampZoom(flags.max_zoom ?? flags.maxZoom, 30);
|
|
385
|
+
const maxTiles = parseOptionalInteger(flags.max_tiles ?? flags.maxTiles, "max_tiles");
|
|
386
|
+
const key = pmtilesOutputKey(flags.output);
|
|
387
|
+
const stdout = [];
|
|
388
|
+
|
|
389
|
+
try {
|
|
390
|
+
await initLibrary();
|
|
391
|
+
// PMTiles are addressed in WGS84 lon/lat; reproject if the caller gave a
|
|
392
|
+
// bbox in another CRS (the map extent affordance always sends 4326).
|
|
393
|
+
const bbox =
|
|
394
|
+
bboxCrs && bboxCrs !== 4326
|
|
395
|
+
? Array.from(transform_bbox_epsg(bboxCrs, 4326, Float64Array.from(rawBbox)))
|
|
396
|
+
: rawBbox;
|
|
397
|
+
|
|
398
|
+
const reader = makeSourceReader(
|
|
399
|
+
await resolvePmtilesSource({ url, inputPath, inputFiles }),
|
|
400
|
+
);
|
|
401
|
+
const archive = await drivePmtilesExtractor(reader, {
|
|
402
|
+
bbox,
|
|
403
|
+
minZoom,
|
|
404
|
+
maxZoom,
|
|
405
|
+
maxTiles,
|
|
406
|
+
});
|
|
407
|
+
stdout.push(
|
|
408
|
+
JSON.stringify({ output: `/work/${key}`, bytes: archive.byteLength }),
|
|
409
|
+
);
|
|
410
|
+
return { exitCode: 0, stdout, files: { [key]: archive } };
|
|
411
|
+
} catch (error) {
|
|
412
|
+
stdout.push(String(error?.message || error));
|
|
413
|
+
return { exitCode: 1, stdout, files: {} };
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Drive a `PmtilesExtractor` to completion over a range reader, fetching each
|
|
419
|
+
* round of wanted ranges concurrently.
|
|
420
|
+
* @param {{range: (offset:number, length:number) => Promise<Uint8Array>}} reader
|
|
421
|
+
* @param {{bbox:number[], minZoom:number, maxZoom:number, maxTiles?:number}} opts
|
|
422
|
+
* @returns {Promise<Uint8Array>}
|
|
423
|
+
*/
|
|
424
|
+
async function drivePmtilesExtractor(reader, { bbox, minZoom, maxZoom, maxTiles }) {
|
|
425
|
+
const extractor = new PmtilesExtractor(
|
|
426
|
+
bbox[0], bbox[1], bbox[2], bbox[3], minZoom, maxZoom,
|
|
427
|
+
);
|
|
428
|
+
try {
|
|
429
|
+
if (maxTiles != null) extractor.set_max_tiles(maxTiles);
|
|
430
|
+
while (!extractor.done) {
|
|
431
|
+
const wanted = JSON.parse(extractor.wanted_json());
|
|
432
|
+
if (wanted.length === 0) {
|
|
433
|
+
throw new Error("PMTiles extractor stalled: not done but nothing wanted");
|
|
434
|
+
}
|
|
435
|
+
const chunks = await Promise.all(
|
|
436
|
+
wanted.map(({ offset, length }) => reader.range(offset, length)),
|
|
437
|
+
);
|
|
438
|
+
wanted.forEach(({ offset }, i) => extractor.feed(offset, chunks[i]));
|
|
439
|
+
}
|
|
440
|
+
return extractor.finish();
|
|
441
|
+
} finally {
|
|
442
|
+
extractor.free();
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/** Resolve a PMTiles source to a URL string or local bytes for makeSourceReader. */
|
|
447
|
+
async function resolvePmtilesSource({ url, inputPath, inputFiles }) {
|
|
448
|
+
const hasUrl = url && url !== true && String(url).trim() !== "";
|
|
449
|
+
if (!hasUrl && !inputPath) {
|
|
450
|
+
throw new Error("provide either --url=<http pmtiles> or --input=/work/local.pmtiles");
|
|
451
|
+
}
|
|
452
|
+
if (hasUrl && inputPath) {
|
|
453
|
+
throw new Error("provide only one source: --url or --input");
|
|
454
|
+
}
|
|
455
|
+
if (hasUrl) return String(url).trim();
|
|
456
|
+
|
|
457
|
+
const key = String(inputPath).replace(/^\/work\/?/, "");
|
|
458
|
+
if (!inputFiles || !(key in inputFiles)) {
|
|
459
|
+
throw new Error(`input file not found in /work: ${inputPath}`);
|
|
460
|
+
}
|
|
461
|
+
return materializeInput(inputFiles[key]);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/** Clamp/parse a zoom flag to an integer in [0, 30], falling back to a default. */
|
|
465
|
+
function clampZoom(raw, fallback) {
|
|
466
|
+
if (raw == null || raw === true || String(raw).trim() === "") return fallback;
|
|
467
|
+
const value = Number(raw);
|
|
468
|
+
if (!Number.isInteger(value) || value < 0 || value > 30) {
|
|
469
|
+
throw new Error("zoom levels must be whole numbers in 0..=30");
|
|
470
|
+
}
|
|
471
|
+
return value;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/** Default a PMTiles output path to extract.pmtiles, stripping the /work prefix. */
|
|
475
|
+
function pmtilesOutputKey(path) {
|
|
476
|
+
if (!path || path === true) return "extract.pmtiles";
|
|
477
|
+
const normalized = String(path).replace(/^\/work\/?/, "");
|
|
478
|
+
return normalized || "extract.pmtiles";
|
|
479
|
+
}
|
|
480
|
+
|
|
346
481
|
async function resolveCogSubsetSource({ url, inputPath, inputFiles }) {
|
|
347
482
|
if ((url == null || url === true || String(url).trim() === "") && !inputPath) {
|
|
348
483
|
throw new Error("provide either --url=<http COG> or --input=/work/local.tif");
|