whitebox-wasm 0.3.0 → 0.4.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/README.md +35 -0
- package/package.json +19 -3
- package/tools.d.ts +26 -0
- package/tools.mjs +83 -0
- package/whitebox-cli.wasm +0 -0
- package/whitebox_wasm.d.ts +3 -3
- package/whitebox_wasm.js +3 -3
- package/whitebox_wasm_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ in the browser, Node, Deno, or any Wasm host:
|
|
|
9
9
|
- **Vector** - read GeoJSON, TopoJSON, GML, GPX, KML, FlatGeobuf, GeoPackage, KMZ -> GeoJSON, with reprojection
|
|
10
10
|
- **LiDAR** - read LAS / LAZ / PLY point clouds (xyz, classification, intensity)
|
|
11
11
|
- **Analysis** - convex hull, Moran's I spatial autocorrelation
|
|
12
|
+
- **Tools** - the full WhiteboxTools suite (733 tools) via `whitebox-wasm/tools`
|
|
12
13
|
|
|
13
14
|
This wraps `wbgeotiff`, the shared GeoTIFF engine from the original
|
|
14
15
|
[**whitebox_next_gen**](https://github.com/jblindsay/whitebox_next_gen) project
|
|
@@ -172,6 +173,40 @@ const xyz = lidar_read_xyz(las, "laz"); // Float64Array [x0,y0,z0, x1,y
|
|
|
172
173
|
- `convex_hull(points_xy)` -> hull ring `Float64Array` (input `[x0,y0,x1,y1,...]`)
|
|
173
174
|
- `morans_i(points_xy, values, distance_threshold)` -> JSON global spatial autocorrelation `{morans_i, expected, variance, z_score, p_value, n}`
|
|
174
175
|
|
|
176
|
+
## Tools (the full WhiteboxTools suite)
|
|
177
|
+
|
|
178
|
+
The `whitebox-wasm/tools` subpath runs the complete **WhiteboxTools** algorithm
|
|
179
|
+
suite (**733 tools** - slope, filters, hydrology, geomorphometry, vector ops,
|
|
180
|
+
...). The tools are path-based, so they run through an in-memory WASI filesystem
|
|
181
|
+
(bundled `whitebox-cli.wasm`); raster outputs are Cloud Optimized GeoTIFFs.
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
import { runTool, listTools } from "whitebox-wasm/tools";
|
|
185
|
+
|
|
186
|
+
console.log((await listTools()).length); // 733
|
|
187
|
+
|
|
188
|
+
// raster: slope -> a COG
|
|
189
|
+
const { files } = await runTool("slope", {
|
|
190
|
+
args: ["--input=/work/dem.tif", "--output=/work/slope.tif", "--units=degrees"],
|
|
191
|
+
input: { "dem.tif": demBytes }, // Uint8Array, placed under /work
|
|
192
|
+
});
|
|
193
|
+
const slopeCog = files["slope.tif"]; // Uint8Array (tiled, Deflate, overviews)
|
|
194
|
+
|
|
195
|
+
// vector: convex hull -> GeoJSON
|
|
196
|
+
const hull = await runTool("minimum_convex_hull", {
|
|
197
|
+
args: ["--input=/work/in.geojson", "--output=/work/hull.geojson"],
|
|
198
|
+
input: { "in.geojson": geojsonBytes },
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
- `listTools()` -> `string[]` of tool ids
|
|
203
|
+
- `runTool(id, { args, input })` -> `{ exitCode, stdout, files }` (`files` = outputs the tool wrote)
|
|
204
|
+
- `initTools(source?)` -> compile the runner; in Node pass the wasm bytes (browsers/bundlers omit it)
|
|
205
|
+
|
|
206
|
+
Needs the `@bjorn3/browser_wasi_shim` peer (declared as a dependency). The
|
|
207
|
+
`whitebox-cli.wasm` (~5 MB gzipped) is only fetched the first time you call a
|
|
208
|
+
tool, so the rest of the library stays lightweight.
|
|
209
|
+
|
|
175
210
|
## Limits
|
|
176
211
|
|
|
177
212
|
WebAssembly is 32-bit, so linear memory is capped at ~4 GiB. `geotiff_info` is
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "whitebox-wasm",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"description": "Pure-Rust geospatial toolkit (raster, vector, LiDAR, projections) compiled to WebAssembly",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.4.0",
|
|
6
6
|
"license": "MIT OR Apache-2.0",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -11,7 +11,10 @@
|
|
|
11
11
|
"files": [
|
|
12
12
|
"whitebox_wasm_bg.wasm",
|
|
13
13
|
"whitebox_wasm.js",
|
|
14
|
-
"whitebox_wasm.d.ts"
|
|
14
|
+
"whitebox_wasm.d.ts",
|
|
15
|
+
"whitebox-cli.wasm",
|
|
16
|
+
"tools.mjs",
|
|
17
|
+
"tools.d.ts"
|
|
15
18
|
],
|
|
16
19
|
"main": "whitebox_wasm.js",
|
|
17
20
|
"homepage": "https://github.com/opengeos/whitebox-wasm",
|
|
@@ -25,5 +28,18 @@
|
|
|
25
28
|
"gis",
|
|
26
29
|
"geotiff",
|
|
27
30
|
"lidar"
|
|
28
|
-
]
|
|
31
|
+
],
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@bjorn3/browser_wasi_shim": "^0.4.2"
|
|
34
|
+
},
|
|
35
|
+
"exports": {
|
|
36
|
+
".": {
|
|
37
|
+
"types": "./whitebox_wasm.d.ts",
|
|
38
|
+
"default": "./whitebox_wasm.js"
|
|
39
|
+
},
|
|
40
|
+
"./tools": {
|
|
41
|
+
"types": "./tools.d.ts",
|
|
42
|
+
"default": "./tools.mjs"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
29
45
|
}
|
package/tools.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Result of running a tool. */
|
|
2
|
+
export interface ToolResult {
|
|
3
|
+
/** Process exit code (0 = success). */
|
|
4
|
+
exitCode: number;
|
|
5
|
+
/** Captured stdout/stderr lines. */
|
|
6
|
+
stdout: string[];
|
|
7
|
+
/** New files the tool wrote, keyed by filename (e.g. the --output path's basename). */
|
|
8
|
+
files: Record<string, Uint8Array>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface RunToolOptions {
|
|
12
|
+
/** CLI args, e.g. ["--input=/work/dem.tif", "--output=/work/out.tif", "--units=degrees"]. */
|
|
13
|
+
args?: string[];
|
|
14
|
+
/** Input files placed under /work, keyed by filename. */
|
|
15
|
+
input?: Record<string, Uint8Array>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Compile the WASI tool runner once. Omit `source` in browsers/bundlers; pass
|
|
19
|
+
* the wasm bytes or a URL/Response in Node. */
|
|
20
|
+
export function initTools(source?: URL | Response | BufferSource | string): Promise<WebAssembly.Module>;
|
|
21
|
+
|
|
22
|
+
/** List every available tool id. */
|
|
23
|
+
export function listTools(): Promise<string[]>;
|
|
24
|
+
|
|
25
|
+
/** Run one tool over an in-memory filesystem. */
|
|
26
|
+
export function runTool(tool: string, opts?: RunToolOptions): Promise<ToolResult>;
|
package/tools.mjs
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// whitebox-wasm/tools - run the WhiteboxTools (wbtools_oss) algorithm suite from
|
|
2
|
+
// JavaScript. The tools are the WASI binary `whitebox-cli.wasm` (733 path-based
|
|
3
|
+
// tools); this module executes them through a WASI shim with an in-memory
|
|
4
|
+
// filesystem, so they run in browsers, Node, Deno, and bundlers without a real
|
|
5
|
+
// disk. Raster outputs are Cloud Optimized GeoTIFFs.
|
|
6
|
+
//
|
|
7
|
+
// import { runTool, listTools } from "whitebox-wasm/tools";
|
|
8
|
+
// const { files } = await runTool("slope", {
|
|
9
|
+
// args: ["--input=/work/dem.tif", "--output=/work/slope.tif", "--units=degrees"],
|
|
10
|
+
// input: { "dem.tif": demBytes }, // Uint8Array, placed under /work
|
|
11
|
+
// });
|
|
12
|
+
// const slopeCog = files["slope.tif"]; // Uint8Array
|
|
13
|
+
import { WASI, File, OpenFile, ConsoleStdout, PreopenDirectory } from "@bjorn3/browser_wasi_shim";
|
|
14
|
+
|
|
15
|
+
let _module = null;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Compile the WASI tool runner once. In browsers/bundlers it loads the bundled
|
|
19
|
+
* `whitebox-cli.wasm` relative to this module. In Node (no fetch of file URLs),
|
|
20
|
+
* pass the wasm bytes or a URL/Response explicitly.
|
|
21
|
+
* @param {URL|Response|BufferSource|string} [source]
|
|
22
|
+
* @returns {Promise<WebAssembly.Module>}
|
|
23
|
+
*/
|
|
24
|
+
export async function initTools(source) {
|
|
25
|
+
if (_module) return _module;
|
|
26
|
+
if (!source) source = new URL("./whitebox-cli.wasm", import.meta.url);
|
|
27
|
+
if (source instanceof Uint8Array || source instanceof ArrayBuffer) {
|
|
28
|
+
_module = await WebAssembly.compile(source);
|
|
29
|
+
} else if (source instanceof Response) {
|
|
30
|
+
_module = await WebAssembly.compileStreaming(source);
|
|
31
|
+
} else {
|
|
32
|
+
_module = await WebAssembly.compileStreaming(fetch(source));
|
|
33
|
+
}
|
|
34
|
+
return _module;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function exec(argv, inputFiles) {
|
|
38
|
+
const mod = await initTools();
|
|
39
|
+
const inNames = new Set(Object.keys(inputFiles));
|
|
40
|
+
const contents = new Map(
|
|
41
|
+
Object.entries(inputFiles).map(([k, v]) => [k, new File(new Uint8Array(v))]));
|
|
42
|
+
const work = new PreopenDirectory("/work", contents);
|
|
43
|
+
const stdout = [];
|
|
44
|
+
const fds = [
|
|
45
|
+
new OpenFile(new File(new Uint8Array())),
|
|
46
|
+
ConsoleStdout.lineBuffered((s) => stdout.push(s)),
|
|
47
|
+
ConsoleStdout.lineBuffered((s) => stdout.push(s)),
|
|
48
|
+
work,
|
|
49
|
+
];
|
|
50
|
+
const wasi = new WASI(["whitebox", ...argv], [], fds, { debug: false });
|
|
51
|
+
const inst = await WebAssembly.instantiate(mod, { wasi_snapshot_preview1: wasi.wasiImport });
|
|
52
|
+
let exitCode = 0;
|
|
53
|
+
try { exitCode = wasi.start(inst); }
|
|
54
|
+
catch (e) { if (e && e.constructor && e.constructor.name === "WASIProcExit") exitCode = e.code; else throw e; }
|
|
55
|
+
const files = {};
|
|
56
|
+
for (const [name, entry] of work.dir.contents) {
|
|
57
|
+
if (entry.data && !inNames.has(name)) files[name] = entry.data;
|
|
58
|
+
}
|
|
59
|
+
return { exitCode, stdout, files };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* List every available tool id (733 of them).
|
|
64
|
+
* @returns {Promise<string[]>}
|
|
65
|
+
*/
|
|
66
|
+
export async function listTools() {
|
|
67
|
+
const { stdout } = await exec(["list"], {});
|
|
68
|
+
return stdout.map((s) => s.trim()).filter((s) => s && !/tools:$/.test(s));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Run one tool over an in-memory filesystem.
|
|
73
|
+
* @param {string} tool tool id, e.g. "slope" (see {@link listTools})
|
|
74
|
+
* @param {object} [opts]
|
|
75
|
+
* @param {string[]} [opts.args] CLI args, e.g. ["--input=/work/dem.tif","--output=/work/out.tif","--units=degrees"]
|
|
76
|
+
* @param {Object<string, Uint8Array>} [opts.input] files placed under /work (key = filename)
|
|
77
|
+
* @returns {Promise<{exitCode:number, stdout:string[], files:Object<string,Uint8Array>}>}
|
|
78
|
+
* `files` contains any new files the tool wrote (e.g. the --output path).
|
|
79
|
+
*/
|
|
80
|
+
export async function runTool(tool, opts = {}) {
|
|
81
|
+
const { args = [], input = {} } = opts;
|
|
82
|
+
return exec([tool, ...args], input);
|
|
83
|
+
}
|
|
Binary file
|
package/whitebox_wasm.d.ts
CHANGED
|
@@ -282,10 +282,10 @@ export function geotiff_stats(data: Uint8Array): string;
|
|
|
282
282
|
export function lidar_formats(): string;
|
|
283
283
|
|
|
284
284
|
/**
|
|
285
|
-
* Read a LiDAR file's metadata as JSON
|
|
286
|
-
*
|
|
285
|
+
* Read a LiDAR file's metadata as JSON. For LAS/LAZ this is header-only (count,
|
|
286
|
+
* bounds, CRS, point format, COPC flag) and never decodes points:
|
|
287
287
|
* `{"ok":true,"format","points","epsg"|null,"point_format"|null,
|
|
288
|
-
* "bounds":[min_x,min_y,min_z,max_x,max_y,max_z]|null}`.
|
|
288
|
+
* "bounds":[min_x,min_y,min_z,max_x,max_y,max_z]|null,"copc":bool}`.
|
|
289
289
|
*/
|
|
290
290
|
export function lidar_info(data: Uint8Array, format: string): string;
|
|
291
291
|
|
package/whitebox_wasm.js
CHANGED
|
@@ -1120,10 +1120,10 @@ export function lidar_formats() {
|
|
|
1120
1120
|
}
|
|
1121
1121
|
|
|
1122
1122
|
/**
|
|
1123
|
-
* Read a LiDAR file's metadata as JSON
|
|
1124
|
-
*
|
|
1123
|
+
* Read a LiDAR file's metadata as JSON. For LAS/LAZ this is header-only (count,
|
|
1124
|
+
* bounds, CRS, point format, COPC flag) and never decodes points:
|
|
1125
1125
|
* `{"ok":true,"format","points","epsg"|null,"point_format"|null,
|
|
1126
|
-
* "bounds":[min_x,min_y,min_z,max_x,max_y,max_z]|null}`.
|
|
1126
|
+
* "bounds":[min_x,min_y,min_z,max_x,max_y,max_z]|null,"copc":bool}`.
|
|
1127
1127
|
* @param {Uint8Array} data
|
|
1128
1128
|
* @param {string} format
|
|
1129
1129
|
* @returns {string}
|
package/whitebox_wasm_bg.wasm
CHANGED
|
Binary file
|