isard 1.3.0 → 1.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/CHANGELOG.md +36 -0
- package/README.md +2 -0
- package/dist/basemap/basemaps.js +1 -0
- package/dist/basemap/basemaps.js.map +1 -1
- package/dist/basemap/vectortiles.d.ts +26 -0
- package/dist/basemap/vectortiles.js +125 -1
- package/dist/basemap/vectortiles.js.map +1 -1
- package/dist/basemap/workerpool.js +9 -0
- package/dist/basemap/workerpool.js.map +1 -1
- package/dist/basemap.worker.js +2 -2
- package/dist/basemap.worker.js.map +7 -4
- package/dist/bind/layers.js +10 -0
- package/dist/bind/layers.js.map +1 -1
- package/dist/decoder.worker.js +3 -3
- package/dist/decoder.worker.js.map +3 -3
- package/dist/engine-loader.d.ts +4 -1
- package/dist/engine-loader.js +9 -0
- package/dist/engine-loader.js.map +1 -1
- package/dist/grid-module.d.ts +44 -0
- package/dist/grid-module.js +63 -0
- package/dist/grid-module.js.map +1 -0
- package/dist/grids.d.ts +51 -0
- package/dist/grids.js +88 -0
- package/dist/grids.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/isard_bg.wasm +0 -0
- package/dist/isard_core_bg.wasm +0 -0
- package/dist/isard_grid_bg.wasm +0 -0
- package/dist/layers/flow.d.ts +111 -0
- package/dist/layers/flow.js +222 -0
- package/dist/layers/flow.js.map +1 -0
- package/dist/layers/symbols.d.ts +2 -0
- package/dist/layers/symbols.js +2 -1
- package/dist/layers/symbols.js.map +1 -1
- package/dist/map/layer-spec.d.ts +4 -1
- package/dist/map/layer-spec.js +2 -0
- package/dist/map/layer-spec.js.map +1 -1
- package/dist/map/workers.d.ts +4 -0
- package/dist/map/workers.js +35 -0
- package/dist/map/workers.js.map +1 -1
- package/dist/map.d.ts +14 -0
- package/dist/map.js +19 -1
- package/dist/map.js.map +1 -1
- package/dist/react/Layer.d.ts +2 -0
- package/dist/react/Layer.js.map +1 -1
- package/dist/types.d.ts +7 -3
- package/dist/types.js.map +1 -1
- package/dist/wasm/isard.d.ts +42 -0
- package/dist/wasm/isard.js +91 -1
- package/dist/wasm/isard_core.d.ts +42 -0
- package/dist/wasm/isard_core.js +91 -1
- package/dist/wasm/isard_grid.d.ts +101 -0
- package/dist/wasm/isard_grid.js +375 -0
- package/dist/workers/basemap/street.d.ts +19 -0
- package/dist/workers/basemap.worker.d.ts +21 -0
- package/dist/workers/basemap.worker.js +23 -4
- package/dist/workers/basemap.worker.js.map +1 -1
- package/package.json +2 -1
- package/vite.js +3 -2
package/dist/engine-loader.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export interface Bindings {
|
|
|
15
15
|
/** `core`: the engine without 3D Tiles; `full`: with them */
|
|
16
16
|
export type EngineKind = 'core' | 'full';
|
|
17
17
|
/** The files a map loads at run time, next to the module unless given elsewhere */
|
|
18
|
-
export type AssetFile = 'isard_bg.wasm' | 'isard_core_bg.wasm' | 'isard_points_bg.wasm' | 'isard_tess_bg.wasm' | 'decoder.worker.js' | 'basemap.worker.js';
|
|
18
|
+
export type AssetFile = 'isard_bg.wasm' | 'isard_core_bg.wasm' | 'isard_points_bg.wasm' | 'isard_tess_bg.wasm' | 'isard_grid_bg.wasm' | 'decoder.worker.js' | 'basemap.worker.js';
|
|
19
19
|
/**
|
|
20
20
|
* Where a file of isard is loaded from: its own option, else in the folder `assetsUrl` (the option, or the page's
|
|
21
21
|
* as `isard/vite` sets it), else next to the module (`import.meta.url`)
|
|
@@ -38,6 +38,9 @@ export declare const pointsUrl: (options: Pick<GeoMapOptions, "pointsWasmUrl" |
|
|
|
38
38
|
* made ready for the GPU off the main thread): the option, or next to the module; absolute, the workers being
|
|
39
39
|
* elsewhere */
|
|
40
40
|
export declare const tessUrl: (options: Pick<GeoMapOptions, "tessWasmUrl" | "assetsUrl">) => string;
|
|
41
|
+
/** Where the workers load the grid module from (`isard_grid_bg.wasm`: GRIB2 and NetCDF files read into grids): the
|
|
42
|
+
* option, or next to the module (absolute: the workers resolve it against their own URL otherwise) */
|
|
43
|
+
export declare const gridUrl: (options: Pick<GeoMapOptions, "gridWasmUrl" | "assetsUrl">) => string;
|
|
41
44
|
/** The decoding workers of 3D Tiles and point clouds, running the full engine's module, unless turned off (`workers:
|
|
42
45
|
* false` or 0, or no workers in this environment) */
|
|
43
46
|
export declare const startTileLoader: (module: WebAssembly.Module, options: Pick<GeoMapOptions, "workers" | "workerUrl" | "decoders" | "pointsWasmUrl" | "assetsUrl">, engine: Engine) => TileLoader | undefined;
|
package/dist/engine-loader.js
CHANGED
|
@@ -46,6 +46,8 @@ export const assetUrl = (file, explicit, assetsUrl) => {
|
|
|
46
46
|
return new URL('./isard_points_bg.wasm', import.meta.url);
|
|
47
47
|
case 'isard_tess_bg.wasm':
|
|
48
48
|
return new URL('./isard_tess_bg.wasm', import.meta.url);
|
|
49
|
+
case 'isard_grid_bg.wasm':
|
|
50
|
+
return new URL('./isard_grid_bg.wasm', import.meta.url);
|
|
49
51
|
case 'decoder.worker.js':
|
|
50
52
|
return new URL('./decoder.worker.js', import.meta.url);
|
|
51
53
|
default:
|
|
@@ -135,6 +137,13 @@ export const tessUrl = (options) => {
|
|
|
135
137
|
const base = typeof document === 'undefined' ? undefined : document.baseURI;
|
|
136
138
|
return base ? new URL(url, base).href : String(url);
|
|
137
139
|
};
|
|
140
|
+
/** Where the workers load the grid module from (`isard_grid_bg.wasm`: GRIB2 and NetCDF files read into grids): the
|
|
141
|
+
* option, or next to the module (absolute: the workers resolve it against their own URL otherwise) */
|
|
142
|
+
export const gridUrl = (options) => {
|
|
143
|
+
const url = assetUrl('isard_grid_bg.wasm', options.gridWasmUrl, options.assetsUrl);
|
|
144
|
+
const base = typeof document === 'undefined' ? undefined : document.baseURI;
|
|
145
|
+
return base ? new URL(url, base).href : String(url);
|
|
146
|
+
};
|
|
138
147
|
/** The decoding workers of 3D Tiles and point clouds, running the full engine's module, unless turned off (`workers:
|
|
139
148
|
* false` or 0, or no workers in this environment) */
|
|
140
149
|
export const startTileLoader = (module, options, engine) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine-loader.js","sourceRoot":"","sources":["../src/engine-loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The two builds of the engine, downloaded, compiled and instantiated once per page; the decoding workers of 3D Tiles\n * that run the full one; the engine of a destroyed map.\n */\n\nimport { defaultWorkerCount } from './basemap/workerpool.ts';\nimport { DEFAULT_DECODERS } from './engine/decoders.ts';\nimport { TileLoader } from './engine/loader.ts';\nimport type { GeoMapOptions } from './types.ts';\nimport type { Camera, Engine } from './wasm/isard.js';\n\n/** The class of an engine build: its constructor and its static `customMatrix` (custom layers) */\nexport type EngineClass = (new (\n canvas: HTMLCanvasElement,\n redraw: () => void,\n) => Engine) &\n Pick<typeof Engine, 'customMatrix' | 'geoidHeight'>;\n\n/** An engine loaded: its compiled module and its class */\nexport interface Bindings {\n module: WebAssembly.Module;\n Engine: EngineClass;\n}\n\n/** `core`: the engine without 3D Tiles; `full`: with them */\nexport type EngineKind = 'core' | 'full';\n\n/** The two builds of the engine, each compiled once per page: `core` without 3D Tiles (a third smaller), loaded by\n * every map; `full` with them, loaded for the first 3D Tiles layer, its module shared with the decoding workers. The\n * core engine has the same API but the 3D Tiles methods: its class is typed as the full one. */\nconst engines: { core?: Promise<Bindings>; full?: Promise<Bindings> } = {};\n/** The modules compiled (downloaded and compiled off the main thread, not instantiated): `tiles3d: 'preload'`\n * compiles the full engine ahead, its first 3D Tiles layer then only instantiates it */\nconst modules: { core?: Promise<WebAssembly.Module>; full?: Promise<WebAssembly.Module> } = {};\n\n/** @internal Forgets the engines loaded (tests) */\nexport const forgetEngines = (): void => {\n (['core', 'full'] as const).forEach((kind) => {\n delete engines[kind];\n delete modules[kind];\n });\n};\n\n/** The files a map loads at run time, next to the module unless given elsewhere */\nexport type AssetFile =\n | 'isard_bg.wasm'\n | 'isard_core_bg.wasm'\n | 'isard_points_bg.wasm'\n | 'isard_tess_bg.wasm'\n | 'decoder.worker.js'\n | 'basemap.worker.js';\n\n/** The folder the assets are served from for the whole page, as `isard/vite` sets it; undefined: next to the module */\nconst pageAssets = (): string | undefined => {\n const url: unknown = Reflect.get(globalThis, 'isardAssetsUrl');\n\n return typeof url === 'string' ? url : undefined;\n};\n\n/**\n * Where a file of isard is loaded from: its own option, else in the folder `assetsUrl` (the option, or the page's\n * as `isard/vite` sets it), else next to the module (`import.meta.url`)\n */\nexport const assetUrl = (\n file: AssetFile,\n explicit: string | URL | undefined,\n assetsUrl?: string | URL,\n): string | URL => {\n if (explicit) return explicit;\n\n const folder = assetsUrl ?? pageAssets();\n\n if (folder) {\n const base = typeof document === 'undefined' ? undefined : document.baseURI;\n const dir = String(folder).endsWith('/') ? String(folder) : `${String(folder)}/`;\n\n return new URL(file, base ? new URL(dir, base) : dir);\n }\n switch (file) {\n case 'isard_bg.wasm':\n return new URL('./isard_bg.wasm', import.meta.url);\n case 'isard_core_bg.wasm':\n return new URL('./isard_core_bg.wasm', import.meta.url);\n case 'isard_points_bg.wasm':\n return new URL('./isard_points_bg.wasm', import.meta.url);\n case 'isard_tess_bg.wasm':\n return new URL('./isard_tess_bg.wasm', import.meta.url);\n case 'decoder.worker.js':\n return new URL('./decoder.worker.js', import.meta.url);\n default:\n return new URL('./basemap.worker.js', import.meta.url);\n }\n};\n\n/** Where a build of the engine is loaded from: the option, the assets' folder, or next to the module */\nexport const engineUrl = (\n kind: EngineKind,\n options: Pick<GeoMapOptions, 'wasmUrl' | 'coreWasmUrl' | 'assetsUrl'>,\n): string | URL => {\n return kind === 'full'\n ? assetUrl('isard_bg.wasm', options.wasmUrl, options.assetsUrl)\n : assetUrl('isard_core_bg.wasm', options.coreWasmUrl, options.assetsUrl);\n};\n\n/** Downloads and compiles a build (once per page, unless it failed: a later call tries again) */\nconst compileEngine = (kind: EngineKind, url: string | URL): Promise<WebAssembly.Module> => {\n const compiled = modules[kind];\n\n if (compiled) return compiled;\n\n const compiling = compile(url).catch((error: unknown) => {\n // A later call tries again (a network error, a wrong URL fixed)\n delete modules[kind];\n throw error;\n });\n\n modules[kind] = compiling;\n\n return compiling;\n};\n\n/** A build compiled and instantiated with its bindings (once per page, unless it failed) */\nexport const loadEngine = (kind: EngineKind, url: string | URL): Promise<Bindings> => {\n const loaded = engines[kind];\n\n if (loaded) return loaded;\n\n const loading = (async () => {\n // The bindings by dynamic import: an application bundles the ones it loads only\n const [module, bindings] = await Promise.all([\n compileEngine(kind, url),\n kind === 'core' ? import('./wasm/isard_core.js') : import('./wasm/isard.js'),\n ]);\n\n await bindings.default({ module_or_path: module });\n\n return { module, Engine: bindings.Engine as unknown as EngineClass };\n })().catch((error: unknown) => {\n delete engines[kind];\n throw error;\n });\n\n engines[kind] = loading;\n\n return loading;\n};\n\n/** The full engine for a map on the core one, resolved in a task of its own, not in the one that instantiated it:\n * the map rebuilt on it there, two shorter tasks */\nexport const loadFullEngineLater = (url: string | URL): Promise<Bindings> => {\n return loadEngine('full', url).then(\n (bindings) => new Promise<Bindings>((resolve) => setTimeout(() => resolve(bindings), 0)),\n );\n};\n\n/** Downloads and compiles the full engine when the page is idle, without running it; a failure is left to the first\n * 3D Tiles layer, which tries again */\nexport const preloadFullEngine = (url: string | URL, wanted: () => boolean): void => {\n const start = () => {\n if (wanted()) compileEngine('full', url).catch(() => undefined);\n };\n\n if (typeof requestIdleCallback === 'function') requestIdleCallback(start, { timeout: 2000 });\n else setTimeout(start, 0);\n};\n\nconst compile = async (url: string | URL): Promise<WebAssembly.Module> => {\n const response = await fetch(url);\n\n if (!response.ok) throw new Error(`isard: failed to load the engine from ${url}: ${response.status}`);\n try {\n return await WebAssembly.compileStreaming(response.clone());\n } catch {\n // Servers that do not send application/wasm\n return WebAssembly.compile(await response.arrayBuffer());\n }\n};\n\n/** Where the workers load the point cloud module from (`isard_points_bg.wasm`, the LAZ decoder): the option, or next\n * to the module; absolute, the workers being elsewhere */\nexport const pointsUrl = (options: Pick<GeoMapOptions, 'pointsWasmUrl' | 'assetsUrl'>): string => {\n const url = assetUrl('isard_points_bg.wasm', options.pointsWasmUrl, options.assetsUrl);\n const base = typeof document === 'undefined' ? undefined : document.baseURI;\n\n return base ? new URL(url, base).href : String(url);\n};\n\n/** Where the basemap workers load the tessellation module from (`isard_tess_bg.wasm`: the vector tiles of `vectors()`\n * made ready for the GPU off the main thread): the option, or next to the module; absolute, the workers being\n * elsewhere */\nexport const tessUrl = (options: Pick<GeoMapOptions, 'tessWasmUrl' | 'assetsUrl'>): string => {\n const url = assetUrl('isard_tess_bg.wasm', options.tessWasmUrl, options.assetsUrl);\n const base = typeof document === 'undefined' ? undefined : document.baseURI;\n\n return base ? new URL(url, base).href : String(url);\n};\n\n/** The decoding workers of 3D Tiles and point clouds, running the full engine's module, unless turned off (`workers:\n * false` or 0, or no workers in this environment) */\nexport const startTileLoader = (\n module: WebAssembly.Module,\n options: Pick<GeoMapOptions, 'workers' | 'workerUrl' | 'decoders' | 'pointsWasmUrl' | 'assetsUrl'>,\n engine: Engine,\n): TileLoader | undefined => {\n const { workers: count, workerUrl, decoders } = options;\n const workers = count ?? defaultWorkerCount();\n\n if (workers === false || workers <= 0 || typeof Worker === 'undefined') return undefined;\n\n return new TileLoader(\n module,\n assetUrl('decoder.worker.js', workerUrl, options.assetsUrl),\n workers,\n { ...DEFAULT_DECODERS, ...decoders },\n engine.textureFormats(),\n pointsUrl(options),\n );\n};\n\n/** The engine of a destroyed map: every method a no-op returning undefined, but the camera (the last one) and the\n * bounds, which late callers read */\nexport const destroyedEngine = (camera: Camera): Engine => {\n return new Proxy(\n {},\n {\n get: (_, name) => {\n if (name === 'camera') return () => camera;\n if (name === 'bounds') return () => Float64Array.of(-180, -85, 180, 85);\n\n return () => undefined;\n },\n },\n ) as Engine;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"engine-loader.js","sourceRoot":"","sources":["../src/engine-loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The two builds of the engine, downloaded, compiled and instantiated once per page; the decoding workers of 3D Tiles\n * that run the full one; the engine of a destroyed map.\n */\n\nimport { defaultWorkerCount } from './basemap/workerpool.ts';\nimport { DEFAULT_DECODERS } from './engine/decoders.ts';\nimport { TileLoader } from './engine/loader.ts';\nimport type { GeoMapOptions } from './types.ts';\nimport type { Camera, Engine } from './wasm/isard.js';\n\n/** The class of an engine build: its constructor and its static `customMatrix` (custom layers) */\nexport type EngineClass = (new (\n canvas: HTMLCanvasElement,\n redraw: () => void,\n) => Engine) &\n Pick<typeof Engine, 'customMatrix' | 'geoidHeight'>;\n\n/** An engine loaded: its compiled module and its class */\nexport interface Bindings {\n module: WebAssembly.Module;\n Engine: EngineClass;\n}\n\n/** `core`: the engine without 3D Tiles; `full`: with them */\nexport type EngineKind = 'core' | 'full';\n\n/** The two builds of the engine, each compiled once per page: `core` without 3D Tiles (a third smaller), loaded by\n * every map; `full` with them, loaded for the first 3D Tiles layer, its module shared with the decoding workers. The\n * core engine has the same API but the 3D Tiles methods: its class is typed as the full one. */\nconst engines: { core?: Promise<Bindings>; full?: Promise<Bindings> } = {};\n/** The modules compiled (downloaded and compiled off the main thread, not instantiated): `tiles3d: 'preload'`\n * compiles the full engine ahead, its first 3D Tiles layer then only instantiates it */\nconst modules: { core?: Promise<WebAssembly.Module>; full?: Promise<WebAssembly.Module> } = {};\n\n/** @internal Forgets the engines loaded (tests) */\nexport const forgetEngines = (): void => {\n (['core', 'full'] as const).forEach((kind) => {\n delete engines[kind];\n delete modules[kind];\n });\n};\n\n/** The files a map loads at run time, next to the module unless given elsewhere */\nexport type AssetFile =\n | 'isard_bg.wasm'\n | 'isard_core_bg.wasm'\n | 'isard_points_bg.wasm'\n | 'isard_tess_bg.wasm'\n | 'isard_grid_bg.wasm'\n | 'decoder.worker.js'\n | 'basemap.worker.js';\n\n/** The folder the assets are served from for the whole page, as `isard/vite` sets it; undefined: next to the module */\nconst pageAssets = (): string | undefined => {\n const url: unknown = Reflect.get(globalThis, 'isardAssetsUrl');\n\n return typeof url === 'string' ? url : undefined;\n};\n\n/**\n * Where a file of isard is loaded from: its own option, else in the folder `assetsUrl` (the option, or the page's\n * as `isard/vite` sets it), else next to the module (`import.meta.url`)\n */\nexport const assetUrl = (\n file: AssetFile,\n explicit: string | URL | undefined,\n assetsUrl?: string | URL,\n): string | URL => {\n if (explicit) return explicit;\n\n const folder = assetsUrl ?? pageAssets();\n\n if (folder) {\n const base = typeof document === 'undefined' ? undefined : document.baseURI;\n const dir = String(folder).endsWith('/') ? String(folder) : `${String(folder)}/`;\n\n return new URL(file, base ? new URL(dir, base) : dir);\n }\n switch (file) {\n case 'isard_bg.wasm':\n return new URL('./isard_bg.wasm', import.meta.url);\n case 'isard_core_bg.wasm':\n return new URL('./isard_core_bg.wasm', import.meta.url);\n case 'isard_points_bg.wasm':\n return new URL('./isard_points_bg.wasm', import.meta.url);\n case 'isard_tess_bg.wasm':\n return new URL('./isard_tess_bg.wasm', import.meta.url);\n case 'isard_grid_bg.wasm':\n return new URL('./isard_grid_bg.wasm', import.meta.url);\n case 'decoder.worker.js':\n return new URL('./decoder.worker.js', import.meta.url);\n default:\n return new URL('./basemap.worker.js', import.meta.url);\n }\n};\n\n/** Where a build of the engine is loaded from: the option, the assets' folder, or next to the module */\nexport const engineUrl = (\n kind: EngineKind,\n options: Pick<GeoMapOptions, 'wasmUrl' | 'coreWasmUrl' | 'assetsUrl'>,\n): string | URL => {\n return kind === 'full'\n ? assetUrl('isard_bg.wasm', options.wasmUrl, options.assetsUrl)\n : assetUrl('isard_core_bg.wasm', options.coreWasmUrl, options.assetsUrl);\n};\n\n/** Downloads and compiles a build (once per page, unless it failed: a later call tries again) */\nconst compileEngine = (kind: EngineKind, url: string | URL): Promise<WebAssembly.Module> => {\n const compiled = modules[kind];\n\n if (compiled) return compiled;\n\n const compiling = compile(url).catch((error: unknown) => {\n // A later call tries again (a network error, a wrong URL fixed)\n delete modules[kind];\n throw error;\n });\n\n modules[kind] = compiling;\n\n return compiling;\n};\n\n/** A build compiled and instantiated with its bindings (once per page, unless it failed) */\nexport const loadEngine = (kind: EngineKind, url: string | URL): Promise<Bindings> => {\n const loaded = engines[kind];\n\n if (loaded) return loaded;\n\n const loading = (async () => {\n // The bindings by dynamic import: an application bundles the ones it loads only\n const [module, bindings] = await Promise.all([\n compileEngine(kind, url),\n kind === 'core' ? import('./wasm/isard_core.js') : import('./wasm/isard.js'),\n ]);\n\n await bindings.default({ module_or_path: module });\n\n return { module, Engine: bindings.Engine as unknown as EngineClass };\n })().catch((error: unknown) => {\n delete engines[kind];\n throw error;\n });\n\n engines[kind] = loading;\n\n return loading;\n};\n\n/** The full engine for a map on the core one, resolved in a task of its own, not in the one that instantiated it:\n * the map rebuilt on it there, two shorter tasks */\nexport const loadFullEngineLater = (url: string | URL): Promise<Bindings> => {\n return loadEngine('full', url).then(\n (bindings) => new Promise<Bindings>((resolve) => setTimeout(() => resolve(bindings), 0)),\n );\n};\n\n/** Downloads and compiles the full engine when the page is idle, without running it; a failure is left to the first\n * 3D Tiles layer, which tries again */\nexport const preloadFullEngine = (url: string | URL, wanted: () => boolean): void => {\n const start = () => {\n if (wanted()) compileEngine('full', url).catch(() => undefined);\n };\n\n if (typeof requestIdleCallback === 'function') requestIdleCallback(start, { timeout: 2000 });\n else setTimeout(start, 0);\n};\n\nconst compile = async (url: string | URL): Promise<WebAssembly.Module> => {\n const response = await fetch(url);\n\n if (!response.ok) throw new Error(`isard: failed to load the engine from ${url}: ${response.status}`);\n try {\n return await WebAssembly.compileStreaming(response.clone());\n } catch {\n // Servers that do not send application/wasm\n return WebAssembly.compile(await response.arrayBuffer());\n }\n};\n\n/** Where the workers load the point cloud module from (`isard_points_bg.wasm`, the LAZ decoder): the option, or next\n * to the module; absolute, the workers being elsewhere */\nexport const pointsUrl = (options: Pick<GeoMapOptions, 'pointsWasmUrl' | 'assetsUrl'>): string => {\n const url = assetUrl('isard_points_bg.wasm', options.pointsWasmUrl, options.assetsUrl);\n const base = typeof document === 'undefined' ? undefined : document.baseURI;\n\n return base ? new URL(url, base).href : String(url);\n};\n\n/** Where the basemap workers load the tessellation module from (`isard_tess_bg.wasm`: the vector tiles of `vectors()`\n * made ready for the GPU off the main thread): the option, or next to the module; absolute, the workers being\n * elsewhere */\nexport const tessUrl = (options: Pick<GeoMapOptions, 'tessWasmUrl' | 'assetsUrl'>): string => {\n const url = assetUrl('isard_tess_bg.wasm', options.tessWasmUrl, options.assetsUrl);\n const base = typeof document === 'undefined' ? undefined : document.baseURI;\n\n return base ? new URL(url, base).href : String(url);\n};\n\n/** Where the workers load the grid module from (`isard_grid_bg.wasm`: GRIB2 and NetCDF files read into grids): the\n * option, or next to the module (absolute: the workers resolve it against their own URL otherwise) */\nexport const gridUrl = (options: Pick<GeoMapOptions, 'gridWasmUrl' | 'assetsUrl'>): string => {\n const url = assetUrl('isard_grid_bg.wasm', options.gridWasmUrl, options.assetsUrl);\n const base = typeof document === 'undefined' ? undefined : document.baseURI;\n\n return base ? new URL(url, base).href : String(url);\n};\n\n/** The decoding workers of 3D Tiles and point clouds, running the full engine's module, unless turned off (`workers:\n * false` or 0, or no workers in this environment) */\nexport const startTileLoader = (\n module: WebAssembly.Module,\n options: Pick<GeoMapOptions, 'workers' | 'workerUrl' | 'decoders' | 'pointsWasmUrl' | 'assetsUrl'>,\n engine: Engine,\n): TileLoader | undefined => {\n const { workers: count, workerUrl, decoders } = options;\n const workers = count ?? defaultWorkerCount();\n\n if (workers === false || workers <= 0 || typeof Worker === 'undefined') return undefined;\n\n return new TileLoader(\n module,\n assetUrl('decoder.worker.js', workerUrl, options.assetsUrl),\n workers,\n { ...DEFAULT_DECODERS, ...decoders },\n engine.textureFormats(),\n pointsUrl(options),\n );\n};\n\n/** The engine of a destroyed map: every method a no-op returning undefined, but the camera (the last one) and the\n * bounds, which late callers read */\nexport const destroyedEngine = (camera: Camera): Engine => {\n return new Proxy(\n {},\n {\n get: (_, name) => {\n if (name === 'camera') return () => camera;\n if (name === 'bounds') return () => Float64Array.of(-180, -85, 180, 85);\n\n return () => undefined;\n },\n },\n ) as Engine;\n};\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The grid module (`isard_grid_bg.wasm`) as the workers (and the page without them) run it: a GRIB2 or NetCDF file's
|
|
3
|
+
* bytes to its grids' descriptions and values. Nothing of the page: the basemap workers import it.
|
|
4
|
+
*/
|
|
5
|
+
/** A grid's description as the grid module gives it (JSON): a grid without its values */
|
|
6
|
+
export interface GridDescription {
|
|
7
|
+
name: string;
|
|
8
|
+
standardName: string | null;
|
|
9
|
+
units: string | null;
|
|
10
|
+
level: {
|
|
11
|
+
kind: string;
|
|
12
|
+
value: number | null;
|
|
13
|
+
} | null;
|
|
14
|
+
time: number | null;
|
|
15
|
+
width: number;
|
|
16
|
+
height: number;
|
|
17
|
+
bounds: (number | null)[];
|
|
18
|
+
}
|
|
19
|
+
/** The flows of a city's streets for a wind of 1 m/s towards the east and one towards the north, their east and north
|
|
20
|
+
* velocities in each of `width` × `height` cells */
|
|
21
|
+
export interface StreetFlows {
|
|
22
|
+
eastU: Float32Array;
|
|
23
|
+
eastV: Float32Array;
|
|
24
|
+
northU: Float32Array;
|
|
25
|
+
northV: Float32Array;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The streets' flows round buildings (their rings in cells from the north-west corner: `points` interleaved, the
|
|
29
|
+
* first point of each ring, the first ring of each polygon, each with its end), by the grid module (`module`), after
|
|
30
|
+
* `iterations` sweeps
|
|
31
|
+
*/
|
|
32
|
+
export declare const streetFlows: (buildings: {
|
|
33
|
+
points: Float64Array;
|
|
34
|
+
ringStart: Uint32Array;
|
|
35
|
+
polygonStart: Uint32Array;
|
|
36
|
+
}, width: number, height: number, iterations: number, module: string | URL) => Promise<StreetFlows>;
|
|
37
|
+
/**
|
|
38
|
+
* The grids of a GRIB2 or classic NetCDF file's bytes, read by the grid module (`module`: its URL, loaded on first
|
|
39
|
+
* use): their descriptions and values, apart (the values to transfer from a worker)
|
|
40
|
+
*/
|
|
41
|
+
export declare const decodeGrids: (bytes: Uint8Array, module: string | URL) => Promise<{
|
|
42
|
+
grids: GridDescription[];
|
|
43
|
+
values: Float32Array[];
|
|
44
|
+
}>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The grid module (`isard_grid_bg.wasm`) as the workers (and the page without them) run it: a GRIB2 or NetCDF file's
|
|
3
|
+
* bytes to its grids' descriptions and values. Nothing of the page: the basemap workers import it.
|
|
4
|
+
*/
|
|
5
|
+
import initGrid, { readGrids, streetFlow } from './wasm/isard_grid.js';
|
|
6
|
+
/** The grid module, loaded once (from `module`), again after a failure */
|
|
7
|
+
const grid = {};
|
|
8
|
+
/** The grid module loaded from `module`, once (again after a failure) */
|
|
9
|
+
const gridModule = async (module) => {
|
|
10
|
+
const ready = grid.ready ?? initGrid({ module_or_path: module });
|
|
11
|
+
grid.ready = ready;
|
|
12
|
+
await ready.catch((error) => {
|
|
13
|
+
grid.ready = undefined;
|
|
14
|
+
throw error;
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* The streets' flows round buildings (their rings in cells from the north-west corner: `points` interleaved, the
|
|
19
|
+
* first point of each ring, the first ring of each polygon, each with its end), by the grid module (`module`), after
|
|
20
|
+
* `iterations` sweeps
|
|
21
|
+
*/
|
|
22
|
+
export const streetFlows = async (buildings, width, height, iterations, module) => {
|
|
23
|
+
await gridModule(module);
|
|
24
|
+
const flow = streetFlow(buildings.points, buildings.ringStart, buildings.polygonStart, width, height, iterations);
|
|
25
|
+
try {
|
|
26
|
+
return { eastU: flow.eastU(), eastV: flow.eastV(), northU: flow.northU(), northV: flow.northV() };
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
flow.free();
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
/** Whether a value is a grid's description as the grid module writes it */
|
|
33
|
+
const isDescription = (value) => typeof value === 'object' &&
|
|
34
|
+
value !== null &&
|
|
35
|
+
'name' in value &&
|
|
36
|
+
'width' in value &&
|
|
37
|
+
'height' in value &&
|
|
38
|
+
'bounds' in value &&
|
|
39
|
+
Array.isArray(value.bounds);
|
|
40
|
+
/**
|
|
41
|
+
* The grids of a GRIB2 or classic NetCDF file's bytes, read by the grid module (`module`: its URL, loaded on first
|
|
42
|
+
* use): their descriptions and values, apart (the values to transfer from a worker)
|
|
43
|
+
*/
|
|
44
|
+
export const decodeGrids = async (bytes, module) => {
|
|
45
|
+
await gridModule(module);
|
|
46
|
+
const set = readGrids(bytes);
|
|
47
|
+
try {
|
|
48
|
+
const grids = [];
|
|
49
|
+
const values = [];
|
|
50
|
+
for (let i = 0; i < set.count(); i++) {
|
|
51
|
+
const description = JSON.parse(set.meta(i));
|
|
52
|
+
if (!isDescription(description))
|
|
53
|
+
throw new Error('isard: a grid without its description');
|
|
54
|
+
grids.push(description);
|
|
55
|
+
values.push(set.values(i));
|
|
56
|
+
}
|
|
57
|
+
return { grids, values };
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
set.free();
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=grid-module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid-module.js","sourceRoot":"","sources":["../src/grid-module.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,QAAQ,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAcvE,0EAA0E;AAC1E,MAAM,IAAI,GAA6C,EAAE,CAAC;AAE1D,yEAAyE;AACzE,MAAM,UAAU,GAAG,KAAK,EAAE,MAAoB,EAAiB,EAAE;IAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;IAEjE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACnB,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QACnC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACvB,MAAM,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAWF;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC9B,SAAsF,EACtF,KAAa,EACb,MAAc,EACd,UAAkB,EAClB,MAAoB,EACE,EAAE;IACxB,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;IAEzB,MAAM,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAElH,IAAI,CAAC;QACH,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;IACpG,CAAC;YAAS,CAAC;QACT,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,2EAA2E;AAC3E,MAAM,aAAa,GAAG,CAAC,KAAc,EAA4B,EAAE,CACjE,OAAO,KAAK,KAAK,QAAQ;IACzB,KAAK,KAAK,IAAI;IACd,MAAM,IAAI,KAAK;IACf,OAAO,IAAI,KAAK;IAChB,QAAQ,IAAI,KAAK;IACjB,QAAQ,IAAI,KAAK;IACjB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAE9B;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAC9B,KAAiB,EACjB,MAAoB,EAC2C,EAAE;IACjE,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;IAEzB,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,KAAK,GAAsB,EAAE,CAAC;QACpC,MAAM,MAAM,GAAmB,EAAE,CAAC;QAElC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,WAAW,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAErD,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;YAC1F,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAC3B,CAAC;YAAS,CAAC;QACT,GAAG,CAAC,IAAI,EAAE,CAAC;IACb,CAAC;AACH,CAAC,CAAC","sourcesContent":["/**\n * The grid module (`isard_grid_bg.wasm`) as the workers (and the page without them) run it: a GRIB2 or NetCDF file's\n * bytes to its grids' descriptions and values. Nothing of the page: the basemap workers import it.\n */\n\nimport initGrid, { readGrids, streetFlow } from './wasm/isard_grid.js';\n\n/** A grid's description as the grid module gives it (JSON): a grid without its values */\nexport interface GridDescription {\n name: string;\n standardName: string | null;\n units: string | null;\n level: { kind: string; value: number | null } | null;\n time: number | null;\n width: number;\n height: number;\n bounds: (number | null)[];\n}\n\n/** The grid module, loaded once (from `module`), again after a failure */\nconst grid: { ready?: Promise<unknown> | undefined } = {};\n\n/** The grid module loaded from `module`, once (again after a failure) */\nconst gridModule = async (module: string | URL): Promise<void> => {\n const ready = grid.ready ?? initGrid({ module_or_path: module });\n\n grid.ready = ready;\n await ready.catch((error: unknown) => {\n grid.ready = undefined;\n throw error;\n });\n};\n\n/** The flows of a city's streets for a wind of 1 m/s towards the east and one towards the north, their east and north\n * velocities in each of `width` × `height` cells */\nexport interface StreetFlows {\n eastU: Float32Array;\n eastV: Float32Array;\n northU: Float32Array;\n northV: Float32Array;\n}\n\n/**\n * The streets' flows round buildings (their rings in cells from the north-west corner: `points` interleaved, the\n * first point of each ring, the first ring of each polygon, each with its end), by the grid module (`module`), after\n * `iterations` sweeps\n */\nexport const streetFlows = async (\n buildings: { points: Float64Array; ringStart: Uint32Array; polygonStart: Uint32Array },\n width: number,\n height: number,\n iterations: number,\n module: string | URL,\n): Promise<StreetFlows> => {\n await gridModule(module);\n\n const flow = streetFlow(buildings.points, buildings.ringStart, buildings.polygonStart, width, height, iterations);\n\n try {\n return { eastU: flow.eastU(), eastV: flow.eastV(), northU: flow.northU(), northV: flow.northV() };\n } finally {\n flow.free();\n }\n};\n\n/** Whether a value is a grid's description as the grid module writes it */\nconst isDescription = (value: unknown): value is GridDescription =>\n typeof value === 'object' &&\n value !== null &&\n 'name' in value &&\n 'width' in value &&\n 'height' in value &&\n 'bounds' in value &&\n Array.isArray(value.bounds);\n\n/**\n * The grids of a GRIB2 or classic NetCDF file's bytes, read by the grid module (`module`: its URL, loaded on first\n * use): their descriptions and values, apart (the values to transfer from a worker)\n */\nexport const decodeGrids = async (\n bytes: Uint8Array,\n module: string | URL,\n): Promise<{ grids: GridDescription[]; values: Float32Array[] }> => {\n await gridModule(module);\n\n const set = readGrids(bytes);\n\n try {\n const grids: GridDescription[] = [];\n const values: Float32Array[] = [];\n\n for (let i = 0; i < set.count(); i++) {\n const description: unknown = JSON.parse(set.meta(i));\n\n if (!isDescription(description)) throw new Error('isard: a grid without its description');\n grids.push(description);\n values.push(set.values(i));\n }\n\n return { grids, values };\n } finally {\n set.free();\n }\n};\n"]}
|
package/dist/grids.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gridded data: the fields of a weather or ocean model read from their files (GRIB2, classic NetCDF) into grids of
|
|
3
|
+
* longitudes and latitudes, by the grid module (`isard_grid_bg.wasm`) in a worker; the wind's components paired into
|
|
4
|
+
* the fields of a flow layer.
|
|
5
|
+
*/
|
|
6
|
+
import type { GridDescription } from './grid-module.ts';
|
|
7
|
+
import type { TimedField } from './layers/flow.ts';
|
|
8
|
+
/**
|
|
9
|
+
* A field on a grid of longitudes and latitudes: `width` × `height` values, row after row from north to south, each
|
|
10
|
+
* from west to east (not a number where there is none), whatever the order of the file
|
|
11
|
+
*/
|
|
12
|
+
export interface Grid {
|
|
13
|
+
/** A GRIB2 parameter's short name (`UGRD`, `VGRD`, `TMP`…), a NetCDF variable's name */
|
|
14
|
+
name: string;
|
|
15
|
+
/** Its CF standard name (`eastward_wind`…), when the file gives one or the parameter is known */
|
|
16
|
+
standardName?: string;
|
|
17
|
+
units?: string;
|
|
18
|
+
/** Its level: kind (`height above ground`, `isobaric`, a NetCDF dimension's name…) and value (metres, pascals…) */
|
|
19
|
+
level?: {
|
|
20
|
+
kind: string;
|
|
21
|
+
value: number;
|
|
22
|
+
};
|
|
23
|
+
/** When it is valid (milliseconds since 1970, UTC) */
|
|
24
|
+
time?: number;
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
/** The longitudes and latitudes of the corner points: west, south, east, north (degrees) */
|
|
28
|
+
bounds: [west: number, south: number, east: number, north: number];
|
|
29
|
+
values: Float32Array;
|
|
30
|
+
}
|
|
31
|
+
/** A grid from its description and values */
|
|
32
|
+
export declare const gridOf: (d: GridDescription, values: Float32Array) => Grid;
|
|
33
|
+
/**
|
|
34
|
+
* The fields of a flow layer from grids: their east and north components (a wind's, a current's: by their standard
|
|
35
|
+
* names `eastward_wind`… or names `UGRD`, `u10`…; `u` and `v` to name them) paired by time and level, at `level` (by
|
|
36
|
+
* default the first one found: a model's 10 m wind), sorted by time
|
|
37
|
+
*/
|
|
38
|
+
export declare const windFields: (grids: readonly Grid[], options?: {
|
|
39
|
+
u?: string;
|
|
40
|
+
v?: string;
|
|
41
|
+
level?: {
|
|
42
|
+
kind: string;
|
|
43
|
+
value: number;
|
|
44
|
+
};
|
|
45
|
+
}) => TimedField[];
|
|
46
|
+
/**
|
|
47
|
+
* A wind at a place and a time (east and north, m/s) from a model's fields (`windFields`): between two of its hours, the
|
|
48
|
+
* mix of the two; undefined outside the fields or where they have none. The wind far away of a city's streets
|
|
49
|
+
* (`vectorTiles().streetWind`), as a clock runs
|
|
50
|
+
*/
|
|
51
|
+
export declare const windAt: (fields: readonly TimedField[], time: Date | number, [lon, lat]: [lon: number, lat: number]) => [u: number, v: number] | undefined;
|
package/dist/grids.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gridded data: the fields of a weather or ocean model read from their files (GRIB2, classic NetCDF) into grids of
|
|
3
|
+
* longitudes and latitudes, by the grid module (`isard_grid_bg.wasm`) in a worker; the wind's components paired into
|
|
4
|
+
* the fields of a flow layer.
|
|
5
|
+
*/
|
|
6
|
+
/** A grid from its description and values */
|
|
7
|
+
export const gridOf = (d, values) => {
|
|
8
|
+
const [west = 0, south = 0, east = 0, north = 0] = d.bounds.map((b) => b ?? 0);
|
|
9
|
+
return {
|
|
10
|
+
name: d.name,
|
|
11
|
+
...(d.standardName ? { standardName: d.standardName } : {}),
|
|
12
|
+
...(d.units ? { units: d.units } : {}),
|
|
13
|
+
...(d.level && d.level.value !== null ? { level: { kind: d.level.kind, value: d.level.value } } : {}),
|
|
14
|
+
...(d.time !== null ? { time: d.time } : {}),
|
|
15
|
+
width: d.width,
|
|
16
|
+
height: d.height,
|
|
17
|
+
bounds: [west, south, east, north],
|
|
18
|
+
values,
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
const EAST = new Set(['eastward_wind', 'eastward_sea_water_velocity', 'UGRD', 'UOGRD', 'u10', 'u', 'uo', 'ugrd']);
|
|
22
|
+
const NORTH = new Set(['northward_wind', 'northward_sea_water_velocity', 'VGRD', 'VOGRD', 'v10', 'v', 'vo', 'vgrd']);
|
|
23
|
+
/** Whether a grid is a velocity's east (or north) component: by its standard name, else its name */
|
|
24
|
+
const isComponent = (g, names, name) => name ? g.name === name : names.has(g.standardName ?? '') || names.has(g.name);
|
|
25
|
+
/** A grid's level as a key */
|
|
26
|
+
const levelKey = (g) => (g.level ? `${g.level.kind} ${g.level.value}` : '');
|
|
27
|
+
/**
|
|
28
|
+
* The fields of a flow layer from grids: their east and north components (a wind's, a current's: by their standard
|
|
29
|
+
* names `eastward_wind`… or names `UGRD`, `u10`…; `u` and `v` to name them) paired by time and level, at `level` (by
|
|
30
|
+
* default the first one found: a model's 10 m wind), sorted by time
|
|
31
|
+
*/
|
|
32
|
+
export const windFields = (grids, options = {}) => {
|
|
33
|
+
const easts = grids.filter((g) => isComponent(g, EAST, options.u));
|
|
34
|
+
const first = easts[0];
|
|
35
|
+
const chosen = options.level && `${options.level.kind} ${options.level.value}`;
|
|
36
|
+
const level = chosen ?? (first ? levelKey(first) : '');
|
|
37
|
+
return easts
|
|
38
|
+
.filter((u) => levelKey(u) === level)
|
|
39
|
+
.flatMap((u) => {
|
|
40
|
+
const v = grids.find((g) => isComponent(g, NORTH, options.v) &&
|
|
41
|
+
g.time === u.time &&
|
|
42
|
+
levelKey(g) === level &&
|
|
43
|
+
g.width === u.width &&
|
|
44
|
+
g.height === u.height);
|
|
45
|
+
if (!v)
|
|
46
|
+
return [];
|
|
47
|
+
const field = { width: u.width, height: u.height, u: u.values, v: v.values, bounds: u.bounds };
|
|
48
|
+
return [{ time: u.time ?? 0, field }];
|
|
49
|
+
})
|
|
50
|
+
.sort((a, b) => Number(a.time) - Number(b.time));
|
|
51
|
+
};
|
|
52
|
+
/** A field's value at a place (bilinear; round the world for a global grid), undefined outside it or where it has none */
|
|
53
|
+
const sample = (field, lon, lat) => {
|
|
54
|
+
const { width, height, u, v, bounds } = field;
|
|
55
|
+
const [west, south, east, north] = bounds;
|
|
56
|
+
const step = (east - west) / Math.max(1, width - 1);
|
|
57
|
+
const wraps = Math.abs(east - west + step - 360) < step / 2;
|
|
58
|
+
const fx = wraps ? ((((lon - west) % 360) + 360) % 360) / step : (lon - west) / step;
|
|
59
|
+
const fy = ((north - lat) / (north - south)) * (height - 1);
|
|
60
|
+
if (fy < 0 || fy > height - 1 || fx < 0 || fx > (wraps ? width : width - 1))
|
|
61
|
+
return undefined;
|
|
62
|
+
const [x0, y0] = [Math.floor(fx), Math.floor(fy)];
|
|
63
|
+
const [tx, ty] = [fx - x0, fy - y0];
|
|
64
|
+
const column = (c) => (wraps ? c % width : Math.min(c, width - 1));
|
|
65
|
+
const at = (grid, r, c) => grid[Math.min(r, height - 1) * width + column(c)] ?? NaN;
|
|
66
|
+
const mix = (grid) => (at(grid, y0, x0) * (1 - tx) + at(grid, y0, x0 + 1) * tx) * (1 - ty) +
|
|
67
|
+
(at(grid, y0 + 1, x0) * (1 - tx) + at(grid, y0 + 1, x0 + 1) * tx) * ty;
|
|
68
|
+
const [a, b] = [mix(u), mix(v)];
|
|
69
|
+
return Number.isFinite(a) && Number.isFinite(b) ? [a, b] : undefined;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* A wind at a place and a time (east and north, m/s) from a model's fields (`windFields`): between two of its hours, the
|
|
73
|
+
* mix of the two; undefined outside the fields or where they have none. The wind far away of a city's streets
|
|
74
|
+
* (`vectorTiles().streetWind`), as a clock runs
|
|
75
|
+
*/
|
|
76
|
+
export const windAt = (fields, time, [lon, lat]) => {
|
|
77
|
+
const t = Number(time);
|
|
78
|
+
const sorted = [...fields].sort((a, b) => Number(a.time) - Number(b.time));
|
|
79
|
+
const after = sorted.findIndex((f) => Number(f.time) > t);
|
|
80
|
+
const [a, b] = after <= 0 ? [sorted[after < 0 ? sorted.length - 1 : 0], undefined] : [sorted[after - 1], sorted[after]];
|
|
81
|
+
const at = a && sample(a.field, lon, lat);
|
|
82
|
+
if (!at || !b)
|
|
83
|
+
return at;
|
|
84
|
+
const next = sample(b.field, lon, lat);
|
|
85
|
+
const k = (t - Number(a.time)) / (Number(b.time) - Number(a.time));
|
|
86
|
+
return next ? [at[0] + (next[0] - at[0]) * k, at[1] + (next[1] - at[1]) * k] : at;
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=grids.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grids.js","sourceRoot":"","sources":["../src/grids.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Gridded data: the fields of a weather or ocean model read from their files (GRIB2, classic NetCDF) into grids of\n * longitudes and latitudes, by the grid module (`isard_grid_bg.wasm`) in a worker; the wind's components paired into\n * the fields of a flow layer.\n */\n\nimport type { GridDescription } from './grid-module.ts';\nimport type { FlowField, TimedField } from './layers/flow.ts';\n\n/**\n * A field on a grid of longitudes and latitudes: `width` × `height` values, row after row from north to south, each\n * from west to east (not a number where there is none), whatever the order of the file\n */\nexport interface Grid {\n /** A GRIB2 parameter's short name (`UGRD`, `VGRD`, `TMP`…), a NetCDF variable's name */\n name: string;\n /** Its CF standard name (`eastward_wind`…), when the file gives one or the parameter is known */\n standardName?: string;\n units?: string;\n /** Its level: kind (`height above ground`, `isobaric`, a NetCDF dimension's name…) and value (metres, pascals…) */\n level?: { kind: string; value: number };\n /** When it is valid (milliseconds since 1970, UTC) */\n time?: number;\n width: number;\n height: number;\n /** The longitudes and latitudes of the corner points: west, south, east, north (degrees) */\n bounds: [west: number, south: number, east: number, north: number];\n values: Float32Array;\n}\n\n/** A grid from its description and values */\nexport const gridOf = (d: GridDescription, values: Float32Array): Grid => {\n const [west = 0, south = 0, east = 0, north = 0] = d.bounds.map((b) => b ?? 0);\n\n return {\n name: d.name,\n ...(d.standardName ? { standardName: d.standardName } : {}),\n ...(d.units ? { units: d.units } : {}),\n ...(d.level && d.level.value !== null ? { level: { kind: d.level.kind, value: d.level.value } } : {}),\n ...(d.time !== null ? { time: d.time } : {}),\n width: d.width,\n height: d.height,\n bounds: [west, south, east, north],\n values,\n };\n};\n\nconst EAST = new Set(['eastward_wind', 'eastward_sea_water_velocity', 'UGRD', 'UOGRD', 'u10', 'u', 'uo', 'ugrd']);\nconst NORTH = new Set(['northward_wind', 'northward_sea_water_velocity', 'VGRD', 'VOGRD', 'v10', 'v', 'vo', 'vgrd']);\n\n/** Whether a grid is a velocity's east (or north) component: by its standard name, else its name */\nconst isComponent = (g: Grid, names: ReadonlySet<string>, name: string | undefined) =>\n name ? g.name === name : names.has(g.standardName ?? '') || names.has(g.name);\n\n/** A grid's level as a key */\nconst levelKey = (g: Grid) => (g.level ? `${g.level.kind} ${g.level.value}` : '');\n\n/**\n * The fields of a flow layer from grids: their east and north components (a wind's, a current's: by their standard\n * names `eastward_wind`… or names `UGRD`, `u10`…; `u` and `v` to name them) paired by time and level, at `level` (by\n * default the first one found: a model's 10 m wind), sorted by time\n */\nexport const windFields = (\n grids: readonly Grid[],\n options: { u?: string; v?: string; level?: { kind: string; value: number } } = {},\n): TimedField[] => {\n const easts = grids.filter((g) => isComponent(g, EAST, options.u));\n const first = easts[0];\n const chosen = options.level && `${options.level.kind} ${options.level.value}`;\n const level = chosen ?? (first ? levelKey(first) : '');\n\n return easts\n .filter((u) => levelKey(u) === level)\n .flatMap((u): TimedField[] => {\n const v = grids.find(\n (g) =>\n isComponent(g, NORTH, options.v) &&\n g.time === u.time &&\n levelKey(g) === level &&\n g.width === u.width &&\n g.height === u.height,\n );\n\n if (!v) return [];\n\n const field: FlowField = { width: u.width, height: u.height, u: u.values, v: v.values, bounds: u.bounds };\n\n return [{ time: u.time ?? 0, field }];\n })\n .sort((a, b) => Number(a.time) - Number(b.time));\n};\n\n/** A field's value at a place (bilinear; round the world for a global grid), undefined outside it or where it has none */\nconst sample = (field: FlowField, lon: number, lat: number): [number, number] | undefined => {\n const { width, height, u, v, bounds } = field;\n const [west, south, east, north] = bounds;\n const step = (east - west) / Math.max(1, width - 1);\n const wraps = Math.abs(east - west + step - 360) < step / 2;\n const fx = wraps ? ((((lon - west) % 360) + 360) % 360) / step : (lon - west) / step;\n const fy = ((north - lat) / (north - south)) * (height - 1);\n\n if (fy < 0 || fy > height - 1 || fx < 0 || fx > (wraps ? width : width - 1)) return undefined;\n\n const [x0, y0] = [Math.floor(fx), Math.floor(fy)];\n const [tx, ty] = [fx - x0, fy - y0];\n const column = (c: number) => (wraps ? c % width : Math.min(c, width - 1));\n const at = (grid: FlowField['u'], r: number, c: number) => grid[Math.min(r, height - 1) * width + column(c)] ?? NaN;\n const mix = (grid: FlowField['u']) =>\n (at(grid, y0, x0) * (1 - tx) + at(grid, y0, x0 + 1) * tx) * (1 - ty) +\n (at(grid, y0 + 1, x0) * (1 - tx) + at(grid, y0 + 1, x0 + 1) * tx) * ty;\n const [a, b] = [mix(u), mix(v)];\n\n return Number.isFinite(a) && Number.isFinite(b) ? [a, b] : undefined;\n};\n\n/**\n * A wind at a place and a time (east and north, m/s) from a model's fields (`windFields`): between two of its hours, the\n * mix of the two; undefined outside the fields or where they have none. The wind far away of a city's streets\n * (`vectorTiles().streetWind`), as a clock runs\n */\nexport const windAt = (\n fields: readonly TimedField[],\n time: Date | number,\n [lon, lat]: [lon: number, lat: number],\n): [u: number, v: number] | undefined => {\n const t = Number(time);\n const sorted = [...fields].sort((a, b) => Number(a.time) - Number(b.time));\n const after = sorted.findIndex((f) => Number(f.time) > t);\n const [a, b] =\n after <= 0 ? [sorted[after < 0 ? sorted.length - 1 : 0], undefined] : [sorted[after - 1], sorted[after]];\n const at = a && sample(a.field, lon, lat);\n\n if (!at || !b) return at;\n\n const next = sample(b.field, lon, lat);\n const k = (t - Number(a.time)) / (Number(b.time) - Number(a.time));\n\n return next ? [at[0] + (next[0] - at[0]) * k, at[1] + (next[1] - at[1]) * k] : at;\n};\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -27,10 +27,13 @@ export { parseTopoJson, type TopoGeometry, type Topology } from './data/topojson
|
|
|
27
27
|
export type { DecoderUrls } from './engine/decoders.ts';
|
|
28
28
|
export { setRequestHeaders } from './engine/requests.ts';
|
|
29
29
|
export { BATIMENTS_3D_URL, type BdTopoBuilding, batiments3d, bdtopoBuildings, type GeocodedPlace, geoplateformeGeocode, geoplateformeWfs, geoplateformeWms, geoplateformeWmts, IGN_ATTRIBUTION, IGN_PRESETS, type IgnPreset, } from './geoplateforme.ts';
|
|
30
|
+
export { type Grid, windAt, windFields } from './grids.ts';
|
|
30
31
|
export type { ExtrusionOptions, ExtrusionStyle, PolygonArrays, TileKey } from './layers/extrusions.ts';
|
|
31
32
|
export { ExtrusionLayer } from './layers/extrusions.ts';
|
|
32
33
|
export type { CircleOptions, CircleStyle, Feature, FeatureCollection, FeatureData, FeatureLayerStyle, FillOptions, FillStyle, Geometry, LineOptions, LineStyle, Placement, Position, Properties, Ramp, Size, Stops, Styled, } from './layers/features.ts';
|
|
33
34
|
export { CircleLayer, FeatureLayer, FillLayer, interpolate, LineLayer, parseColor } from './layers/features.ts';
|
|
35
|
+
export type { FlowField, FlowOptions, FlowStyle, TimedField } from './layers/flow.ts';
|
|
36
|
+
export { FlowLayer, flowFieldFromImage, flowFieldsFromImage } from './layers/flow.ts';
|
|
34
37
|
export type { TextPart } from './layers/glyphs.ts';
|
|
35
38
|
export { DEFAULT_FONT, GLYPHS_URL } from './layers/glyphs.ts';
|
|
36
39
|
export type { ImageOptions, Pixels, SpriteIcon } from './layers/icons.ts';
|
package/dist/index.js
CHANGED
|
@@ -23,8 +23,10 @@ export { parseKml } from "./data/kml.js";
|
|
|
23
23
|
export { parseTopoJson } from "./data/topojson.js";
|
|
24
24
|
export { setRequestHeaders } from "./engine/requests.js";
|
|
25
25
|
export { BATIMENTS_3D_URL, batiments3d, bdtopoBuildings, geoplateformeGeocode, geoplateformeWfs, geoplateformeWms, geoplateformeWmts, IGN_ATTRIBUTION, IGN_PRESETS, } from "./geoplateforme.js";
|
|
26
|
+
export { windAt, windFields } from "./grids.js";
|
|
26
27
|
export { ExtrusionLayer } from "./layers/extrusions.js";
|
|
27
28
|
export { CircleLayer, FeatureLayer, FillLayer, interpolate, LineLayer, parseColor } from "./layers/features.js";
|
|
29
|
+
export { FlowLayer, flowFieldFromImage, flowFieldsFromImage } from "./layers/flow.js";
|
|
28
30
|
export { DEFAULT_FONT, GLYPHS_URL } from "./layers/glyphs.js";
|
|
29
31
|
export { CustomLayer, GroundLayer, Layer, ModelLayer, NetworkLayer, RasterLayer, Tiles3dLayer, } from "./layers/layers.js";
|
|
30
32
|
export { Panoramas } from "./layers/panoramas.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAE3F,OAAO,EACL,OAAO,EAIP,WAAW,EACX,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAuB,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EAAmB,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAWhE,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAGL,MAAM,EACN,qBAAqB,EACrB,WAAW,EACX,SAAS,EACT,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAoC,MAAM,oBAAoB,CAAC;AAErF,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EACL,gBAAgB,EAEhB,WAAW,EACX,eAAe,EAEf,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,WAAW,GAEZ,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAE3F,OAAO,EACL,OAAO,EAIP,WAAW,EACX,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAuB,MAAM,2BAA2B,CAAC;AAC5E,OAAO,EAAmB,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAWhE,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAGL,MAAM,EACN,qBAAqB,EACrB,WAAW,EACX,SAAS,EACT,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAoC,MAAM,oBAAoB,CAAC;AAErF,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EACL,gBAAgB,EAEhB,WAAW,EACX,eAAe,EAEf,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,WAAW,GAEZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAa,MAAM,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAqBxD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEhH,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEtF,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAU9D,OAAO,EACL,WAAW,EACX,WAAW,EACX,KAAK,EACL,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAuC,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvF,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE3F,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAsB,WAAW,EAAuB,MAAM,qBAAqB,CAAC;AAE3F,OAAO,EAAE,MAAM,EAAkB,MAAM,UAAU,CAAC;AAiClD,OAAO,EACL,kBAAkB,EAIlB,iBAAiB,GAElB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAuB,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAEL,MAAM,EAIN,KAAK,EAEL,KAAK,GAGN,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAqB,MAAM,eAAe,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAsB,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC","sourcesContent":["/**\n * isard: a WebGL2 map engine for large, interactive data layers, labels and 3D Tiles.\n *\n * ```ts\n * import { GeoMap } from 'isard';\n * const map = await GeoMap.create(container, { center: [2.4246, 48.8457], zoom: 13 });\n * const network = map.addNetwork({ nodes, edges, max: 1800, contour: 300 });\n * map.on('hover', ({ lonLat }) => lonLat && network.setValues(travelTimes(lonLat)));\n * map.addTiles3d({ url: 'https://…/tileset.json' });\n * map.addControl(new NavigationControl());\n * new Marker().setLonLat([2.4246, 48.8457]).setPopup(new Popup({ offset: [0, -34] }).setText('Here')).addTo(map);\n * ```\n */\nexport { OPENFREEMAP_ATTRIBUTION, TERRAIN_TILES_ATTRIBUTION } from './basemap/basemaps.ts';\nexport type { TileGrid, TileMatrix } from './basemap/grid.ts';\nexport {\n PMTiles,\n type PmtilesEntry,\n type PmtilesHeader,\n type PmtilesTileType,\n tileIdToZxy,\n zxyToTileId,\n} from './basemap/pmtiles.ts';\nexport { basicStyle, type PmtilesOptions } from './basemap/pmtileslayer.ts';\nexport { type TreeColors, treeModel } from './basemap/trees.ts';\nexport type {\n CandidateIcon,\n CandidateOverlap,\n Json,\n LabelCandidate,\n RasterSource,\n Style,\n StyleLayer,\n} from './basemap/vectorstyle.ts';\nexport type { VectorTilesOptions } from './basemap/vectortiles.ts';\nexport { OPENFREEMAP_STYLES, PLAN_STYLES, VectorTiles } from './basemap/vectortiles.ts';\nexport { parseWmtsGrid, wmtsGrid } from './basemap/wmts.ts';\nexport {\n type Crs,\n type CrsLike,\n getCrs,\n lambertConformalConic,\n registerCrs,\n reproject,\n transverseMercator,\n} from './data/crs.ts';\nexport { parseGpx } from './data/gpx.ts';\nexport { parseKml } from './data/kml.ts';\nexport { parseTopoJson, type TopoGeometry, type Topology } from './data/topojson.ts';\nexport type { DecoderUrls } from './engine/decoders.ts';\nexport { setRequestHeaders } from './engine/requests.ts';\nexport {\n BATIMENTS_3D_URL,\n type BdTopoBuilding,\n batiments3d,\n bdtopoBuildings,\n type GeocodedPlace,\n geoplateformeGeocode,\n geoplateformeWfs,\n geoplateformeWms,\n geoplateformeWmts,\n IGN_ATTRIBUTION,\n IGN_PRESETS,\n type IgnPreset,\n} from './geoplateforme.ts';\nexport { type Grid, windAt, windFields } from './grids.ts';\nexport type { ExtrusionOptions, ExtrusionStyle, PolygonArrays, TileKey } from './layers/extrusions.ts';\nexport { ExtrusionLayer } from './layers/extrusions.ts';\nexport type {\n CircleOptions,\n CircleStyle,\n Feature,\n FeatureCollection,\n FeatureData,\n FeatureLayerStyle,\n FillOptions,\n FillStyle,\n Geometry,\n LineOptions,\n LineStyle,\n Placement,\n Position,\n Properties,\n Ramp,\n Size,\n Stops,\n Styled,\n} from './layers/features.ts';\nexport { CircleLayer, FeatureLayer, FillLayer, interpolate, LineLayer, parseColor } from './layers/features.ts';\nexport type { FlowField, FlowOptions, FlowStyle, TimedField } from './layers/flow.ts';\nexport { FlowLayer, flowFieldFromImage, flowFieldsFromImage } from './layers/flow.ts';\nexport type { TextPart } from './layers/glyphs.ts';\nexport { DEFAULT_FONT, GLYPHS_URL } from './layers/glyphs.ts';\nexport type { ImageOptions, Pixels, SpriteIcon } from './layers/icons.ts';\nexport type {\n CustomFrame,\n CustomLayerInterface,\n GroundOptions,\n GroundTexture,\n ModelInstance,\n ModelOptions,\n} from './layers/layers.ts';\nexport {\n CustomLayer,\n GroundLayer,\n Layer,\n ModelLayer,\n NetworkLayer,\n RasterLayer,\n Tiles3dLayer,\n} from './layers/layers.ts';\nexport { type Panorama, type PanoramaOptions, Panoramas } from './layers/panoramas.ts';\nexport type { ClassStyle, PointCloudOptions, PointCloudStyle, PointColor } from './layers/pointclouds.ts';\nexport { CLASSIFICATIONS, ELEVATION_RAMP, PointCloudLayer } from './layers/pointclouds.ts';\nexport type { Overlap, SymbolOptions, SymbolStyle } from './layers/symbols.ts';\nexport { SymbolLayer } from './layers/symbols.ts';\nexport { type VectorFeature, VectorLayer, type VectorSublayer } from './layers/vectors.ts';\nexport type { HoverPicking } from './map/hover-pick.ts';\nexport { GeoMap, type LayerSpec } from './map.ts';\nexport type {\n AnimationOptions,\n AtmosphereOptions,\n Basemap,\n BasemapName,\n BodyOptions,\n CelestialBody,\n FeatureHit,\n FirstPersonView,\n FlyToOptions,\n GeoMapOptions,\n LoadingMode,\n LonLat,\n MapEvents,\n MapHoverFeatureEvent,\n MapPointerEvent,\n NetworkOptions,\n NetworkStyle,\n Point,\n Projection,\n RasterGrid,\n RasterOptions,\n RasterStyle,\n SunOptions,\n SwipeOptions,\n TerrainEncoding,\n TerrainModel,\n TerrainOptions,\n Tiles3dOptions,\n Tiles3dStyle,\n ViewshedOptions,\n} from './types.ts';\nexport {\n AttributionControl,\n type AttributionOptions,\n type Control,\n type ControlPosition,\n NavigationControl,\n type NavigationOptions,\n} from './ui/controls.ts';\nexport { MinimapControl, type MinimapOptions } from './ui/minimap.ts';\nexport {\n type Anchor,\n Marker,\n type MarkerEvent,\n type MarkerEvents,\n type MarkerOptions,\n Panel,\n type PanelOptions,\n Popup,\n type PopupEvents,\n type PopupOptions,\n} from './ui/overlay.ts';\nexport { lengthLabel, roundLength, ScaleControl, type ScaleOptions } from './ui/scale.ts';\nexport { SearchControl, type SearchOptions } from './ui/search.ts';\nexport { sunPosition } from './util/sun.ts';\nexport type {\n Camera,\n NetworkStats,\n PickHit,\n PickResult,\n PointCloudInfo,\n PointCloudPoint,\n PointCloudStats,\n RasterLayerStats,\n Tiles3dStats,\n} from './wasm/isard.js';\n"]}
|
package/dist/isard_bg.wasm
CHANGED
|
Binary file
|
package/dist/isard_core_bg.wasm
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flow layers: particles carried by a field of velocities (a wind's east and north components on a grid of longitudes
|
|
3
|
+
* and latitudes, m/s), their trails drawn on the globe and the relief and animated, colored by speed: wind maps,
|
|
4
|
+
* currents. The engine moves them (`stepFlow`), one step per animation frame while the layer plays.
|
|
5
|
+
*/
|
|
6
|
+
import { type Ramp } from './features.ts';
|
|
7
|
+
import { Layer } from './layers.ts';
|
|
8
|
+
/**
|
|
9
|
+
* A field of velocities: `width` × `height` points, from west to east and from north to south (row after row), the
|
|
10
|
+
* east (`u`) and north (`v`) components at each (m/s; not a number: none there), the corner points at `bounds` (west,
|
|
11
|
+
* south, east, north, degrees). A last column one step short of 360° goes round the world (a global model's grid)
|
|
12
|
+
*/
|
|
13
|
+
export interface FlowField {
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
u: Float32Array | readonly number[];
|
|
17
|
+
v: Float32Array | readonly number[];
|
|
18
|
+
bounds: [west: number, south: number, east: number, north: number];
|
|
19
|
+
}
|
|
20
|
+
export interface FlowStyle {
|
|
21
|
+
/** The colors of the speeds (m/s), linear between them, up to 8 (default from calm blue to storm red) */
|
|
22
|
+
colors: Ramp;
|
|
23
|
+
/** Width of a trail, CSS pixels (default 1.5) */
|
|
24
|
+
width: number;
|
|
25
|
+
/** 0 to 1 (default 0.9) */
|
|
26
|
+
opacity: number;
|
|
27
|
+
/** Metres over the ground (default 0) */
|
|
28
|
+
height: number;
|
|
29
|
+
/** Speed on screen: pixels a second for 10 m/s, whatever the zoom (default 60) */
|
|
30
|
+
speed: number;
|
|
31
|
+
/** Particles moving for each 100 × 100 CSS pixels of the view, the screen as dense at any zoom (default 60; at most
|
|
32
|
+
* `particles`) */
|
|
33
|
+
density: number;
|
|
34
|
+
}
|
|
35
|
+
/** A field at a time: one of a model's hours */
|
|
36
|
+
export interface TimedField {
|
|
37
|
+
time: Date | number;
|
|
38
|
+
field: FlowField;
|
|
39
|
+
}
|
|
40
|
+
export interface FlowOptions extends Partial<FlowStyle> {
|
|
41
|
+
/** The field; or `fields`, at their times, mixed at `time` */
|
|
42
|
+
field?: FlowField;
|
|
43
|
+
/** Fields at their times, on one grid (a model's hours): the layer's field at `time` the mix of the two around it */
|
|
44
|
+
fields?: readonly TimedField[];
|
|
45
|
+
/** The time the fields are mixed at (default the first one's) */
|
|
46
|
+
time?: Date | number;
|
|
47
|
+
/** Particles moving, rounded up to a multiple of 4096 (default 16384) */
|
|
48
|
+
particles?: number;
|
|
49
|
+
/** Positions of a trail, one each 60th of a second (default 24): longer trails, more to draw */
|
|
50
|
+
trail?: number;
|
|
51
|
+
/** Moving from the start (default true); `play`, `pause` and `step` after */
|
|
52
|
+
playing?: boolean;
|
|
53
|
+
before?: Layer;
|
|
54
|
+
}
|
|
55
|
+
export declare class FlowLayer extends Layer {
|
|
56
|
+
#private;
|
|
57
|
+
/** The fields by time (one at time 0 for a single field), the time shown, the two sent to the engine */
|
|
58
|
+
private fields;
|
|
59
|
+
private time;
|
|
60
|
+
private sent;
|
|
61
|
+
private style;
|
|
62
|
+
private readonly particles;
|
|
63
|
+
private readonly trail;
|
|
64
|
+
/** The animation frame asked for, and the time of the last step (ms) */
|
|
65
|
+
private frame;
|
|
66
|
+
private last;
|
|
67
|
+
/** Whether the particles move */
|
|
68
|
+
get playing(): boolean;
|
|
69
|
+
/** The particles move, a step each animation frame */
|
|
70
|
+
play(): void;
|
|
71
|
+
/** The particles stop where they are (the map no longer drawn for them) */
|
|
72
|
+
pause(): void;
|
|
73
|
+
/** Moving or not (`play`, `pause`) */
|
|
74
|
+
setPlaying(playing: boolean): void;
|
|
75
|
+
/** Moves the particles by `seconds` of the page's time, at once (a still image after so many steps; paused) */
|
|
76
|
+
step(seconds?: number): void;
|
|
77
|
+
/** A new field (on another grid, the trails start again) */
|
|
78
|
+
setField(field: FlowField): void;
|
|
79
|
+
/** New fields at their times (a model's hours), mixed at `time` (default the one shown) */
|
|
80
|
+
setFields(fields: readonly TimedField[], time?: Date | number): void;
|
|
81
|
+
/** The time the fields are mixed at: between two of the model's hours, the field goes linearly from one to the
|
|
82
|
+
* other (before the first and after the last, theirs); the particles go on */
|
|
83
|
+
setTime(time: Date | number): void;
|
|
84
|
+
setStyle(style: Partial<FlowStyle>): void;
|
|
85
|
+
/** One step an animation frame while it plays, by the time since the last */
|
|
86
|
+
private loop;
|
|
87
|
+
/** The two fields around the time and how far between them, the fields sent only when they change */
|
|
88
|
+
private sendField;
|
|
89
|
+
private sendStyle;
|
|
90
|
+
remove(): void;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* A field from an image (PNG, as wind maps ship them): the east component in red, the north in green, each scaled
|
|
94
|
+
* from 0-255 to its range (`u`, `v`, m/s), none where the image is transparent; its pixels the grid's points over
|
|
95
|
+
* `bounds`
|
|
96
|
+
*/
|
|
97
|
+
export declare const flowFieldFromImage: (url: string | URL, options: {
|
|
98
|
+
bounds: FlowField["bounds"];
|
|
99
|
+
u: [min: number, max: number];
|
|
100
|
+
v: [min: number, max: number];
|
|
101
|
+
}, init?: RequestInit) => Promise<FlowField>;
|
|
102
|
+
/**
|
|
103
|
+
* The fields of an image holding `count` of them one under the other (a model's hours, the first at the top), each
|
|
104
|
+
* read as `flowFieldFromImage` reads one
|
|
105
|
+
*/
|
|
106
|
+
export declare const flowFieldsFromImage: (url: string | URL, options: {
|
|
107
|
+
bounds: FlowField["bounds"];
|
|
108
|
+
u: [min: number, max: number];
|
|
109
|
+
v: [min: number, max: number];
|
|
110
|
+
count: number;
|
|
111
|
+
}, init?: RequestInit) => Promise<FlowField[]>;
|